Um cpp
arquivo com o qual estou trabalhando cria um diretório, ou seja mkdir( path, ... )
, onde path vem de uma variável de ambiente (por exemplo, getenv( "FOO" );
).
Por exemplo, digamos que $FOO
seja /foo
, e path
, criado acima, seja `/foo/newPath/'.
Para o meu cenário de pergunta, é possível que /foo/oldPath/
exista e tenha conteúdo (suponha que não haja mais subdiretórios), caso em que desejo 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 é, na melhor das hipóteses, tênue.
O contexto por trás dessa pergunta é: se /foo/newPath/
e tiver /foo/oldPath/
a garantia de estar no mesmo sistema de arquivos montado, posso usar rename()
para executar a movimentação de arquivos com mais facilidade do que outras alternativas. A página de manual da função diz que ela falhará se oldPath
e newPath
não estiver no mesmo "sistema de arquivos montado".
Eles não têm garantia disso. É possível que
/foo/oldPath
seja um ponto de montagem.No entanto, isso pode ser facilmente verificado executando
mount | grep 'on /foo/oldPath'
Nenhuma saída deve indicar que ooldPath
diretório não é um ponto de montagem.Você precisará ter mais cuidado se estiver usando diretórios aninhados, pois pode haver um ponto de montagem em qualquer lugar.
Não tenho certeza se isso é automatizado, mas vale a pena notar que o terceiro campo de montagem (separado por espaço) é o ponto de montagem para cada linha, portanto, a utilização de um
cut -d ' ' -f 3
pode ser usada para extrair o caminho (se você precisar verificar se é não apenas uma substring 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 obter mais detalhes de implementação, se necessário.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 ligação, em arquivos únicos, o que também causará problemas ao renomear arquivos.Em vez de tentar determinar com antecedência se os arquivos podem ser renomeados, você deve tentar renomeá-los e lidar com os erros.
rename
retornará -1 se ocorrer um erro eerrno
será definido comoEXDEV
se a renomeação não for possível devido a problemas de montagem cruzada. Você pode então proceder de outra forma (copiar e deletar).Em geral, para determinar se dois objetos do sistema de arquivos estão no mesmo sistema de arquivos, você deve executá
stat
-los e verificar o identificador do dispositivo (ost_dev
campo emstruct stat
). Dois objetos do sistema de arquivos no mesmo sistema de arquivos terão o mesmo identificador de dispositivo.Observe que, ao executar overlayfs, você não pode confiar em
rename()
diretórios pré-existentes.Eu acho que você normalmente poderia ignorar essa possibilidade, se você não estiver escrevendo uma ferramenta de gerenciamento de arquivos de uso geral ... para contar com o novo
redirect_dir
formato de overlayfs.Portanto, esta é mais uma nota pedante para informar que este é o Linux, não cumprimos o POSIX se não quisermos e "garantido" é uma palavra muito forte :).
https://www.kernel.org/doc/Documentation/filesystems/overlayfs.txt
Overlayfs já não corresponde às expectativas usuais de um sistema de arquivos unix em outros detalhes: