Existem dois subdiretórios com a mesma raiz garantidos no mesmo sistema de arquivos montado?

5

Um arquivo cpp no qual estou trabalhando cria um diretório, por exemplo, mkdir( path, ... ) , onde o caminho vem de uma variável de ambiente (por exemplo, getenv( "FOO" ); ).

Por exemplo, digamos $FOO é /foo e path , criado acima, é '/ foo / newPath /'.

Para meu cenário de pergunta, é possível que /foo/oldPath/ exista e tenha conteúdo (não assuma mais subdiretórios), nesse caso eu quero mover arquivos de /foo/oldPath/ para /foo/newPath .

Minha pergunta é: porque /foo/newPath/ é criado como um subdiretório de $FOO , ou seja, /foo/newPath/ e /foo/oldPath/ tem o mesmo diretório pai, é garantido que ambos os diretórios estejam no mesmo "sistema de arquivos montado "? Meu entendimento de pontos de montagem e sistemas de arquivos no Linux é tênue, na melhor das hipóteses.

O contexto por trás dessa pergunta é: se /foo/newPath/ e /foo/oldPath/ tiver a garantia de estar no mesmo sistema de arquivos montado, posso usar rename() para executar mais facilmente a movimentação de arquivos do que outras alternativas. A página man da função diz que ela falhará se oldPath e newPath não estiverem no mesmo "sistema de arquivos montado".

    
por StoneThrow 03.05.2018 / 22:13

3 respostas

13

Eles não têm garantia disso. É possível que /foo/oldPath seja um ponto de montagem.

Isso pode, no entanto, ser facilmente verificado executando mount | grep 'on /foo/oldPath' Nenhuma saída deve indicar que o diretório oldPath não é um ponto de montagem.

Você precisará ser mais cuidadoso se estiver usando diretórios aninhados, já que você pode ter um ponto de montagem em qualquer lugar.

Não sei se isso é automatizado, mas é importante notar que o terceiro campo da montagem (separado por espaço) é o ponto de montagem de cada linha, portanto, utilizar cut -d ' ' -f 3 pode ser usado para extrair o caminho ( Se você precisar verificar se não é apenas uma subseqüência de outro ponto de montagem, como /foo/oldPath/nested/mountPoint )

Se você gostaria de traduzir isso em código C / C ++, você pode usar system("mount | grep 'on /foo/oldPath'") , mas não vou jurar por isso. Você pode ter mais sorte no StackOverflow para mais detalhes de implementação, se precisar.

    
por 03.05.2018 / 22:17
5

Você não deve tentar isso, por vários motivos (detalhados nas outras respostas): /foo/oldPath pode ser um ponto de montagem ou um sistema de arquivos de sobreposição pode estar presente e impedir a movimentação de arquivos. Você pode até encontrar montagens de bind, em arquivos únicos, o que também causará problemas ao renomear arquivos.

Em vez de tentar determinar antecipadamente se os arquivos podem ser renomeados, tente renomeá-los e lidar com os erros. rename retornará -1 se ocorrer um erro e errno será definido como EXDEV se a renomeação não for possível devido a problemas de montagem cruzada. Você pode então prosseguir de outra maneira (copiar e excluir).

Em geral, para determinar se dois objetos do sistema de arquivos estão no mesmo sistema de arquivos, você deve executar stat sobre eles e veja o identificador do dispositivo (o campo st_dev em struct stat ). Dois objetos do sistema de arquivos no mesmo sistema de arquivos terão o mesmo identificador de dispositivo.

    
por 04.05.2018 / 10:33
4

Observe que, quando você executa em overlayfs, não pode confiar em rename() de diretórios pré-existentes.

Eu acho que você poderia geralmente ignorar essa possibilidade, se você não está escrevendo uma ferramenta de gerenciamento de arquivos de propósito geral ... Por exemplo, um gerenciador de pacotes ... e nesse caso você aparentemente não pode consertá-lo (por razões de atomicidade) e quer confiar no novo formato redirect_dir do overlayfs.

Portanto, esta é uma nota mais pedante para você saber que isso é Linux, nós não estamos em conformidade com POSIX se não queremos, e "garantida" é uma palavra muito strong:).

link

Unless "redirect_dir" feature is enabled, rename(2) on a lower or merged directory will fail with EXDEV.

O Overlayfs já não corresponde às expectativas usuais de um sistema de arquivos unix em outros detalhes:

Objects that are not directories (files, symlinks, device-special files etc.) are presented either from the upper or lower filesystem as appropriate. When a file in the lower filesystem is accessed in a way the requires write-access, such as opening for write access, changing some metadata etc., the file is first copied from the lower filesystem to the upper filesystem (copy_up)...

The copy_up operation essentially creates a new, identical file and moves it over to the old name. Any open files referring to this inode will access the old data.

    
por 03.05.2018 / 23:07