Desde que você não mova o arquivo pelas bordas do sistema de arquivos, a operação deve ser segura. Isto é devido ao mecanismo, como "mover" realmente é feito.
Se você mv
possui um arquivo no mesmo sistema de arquivos, o arquivo não é realmente tocado, mas apenas a entrada do sistema de arquivos é alterada.
$ mv foo bar
realmente faz algo como
$ ln foo bar
$ rm foo
Isso criaria um duro link (uma segunda entrada de diretório) para o arquivo (na verdade, o inode apontado por entrada do sistema de arquivos) foo
com o nome bar
e remover a foo
entrada. Como agora, ao remover foo
, existe uma segunda entrada do sistema de arquivos apontando para foo
o inode, remover a entrada antiga foo
na verdade não remove nenhum bloco pertencente ao inode.
Seu programa seria felizmente acrescentado ao arquivo de qualquer maneira, uma vez que seu identificador de arquivo aberto aponta para o inode do arquivo, não para a entrada do sistema de arquivos.
Nota: Se o seu programa fechar e reabrir o arquivo entre gravações, você poderá criar um novo arquivo com a entrada antiga do sistema de arquivos!
Movimentos cruzados do sistema de arquivos:
Se você mover o arquivo pelas bordas do sistema de arquivos, as coisas ficarão feias. Nesse caso, você não pode garantir que seu arquivo seja consistente, pois mv
isso realmente
- crie um novo arquivo no sistema de arquivos de destino
- copie o conteúdo do arquivo antigo para o novo arquivo
- remova o arquivo antigo
or
$ cp /path/to/foo /path/to/bar
$ rm /path/to/foo
resp.
$ touch /path/to/bar
$ cat < /path/to/foo > /path/to/bar
$ rm /path/to/foo
Dependendo se a cópia atinge o final do arquivo durante a gravação do seu aplicativo, pode acontecer que você tenha apenas metade de uma linha no novo arquivo.
Além disso, se seu aplicativo não fechar e reabrir o arquivo antigo, ele continuará gravando no arquivo antigo, mesmo que pareça ser excluído: o kernel sabe quais arquivos estão abertos e, embora exclua a entrada do sistema de arquivos, não excluirá o inode do arquivo antigo e os blocos associados até que seu aplicativo feche seu identificador de arquivo aberto.
rename()
chamada de sistema. Portanto, a versão original demv
fato chamoulink()
para criar o link físico, seguido porunlink()
para remover o nome original.rename()
foi adicionado no FreeBSD, para implementar isso atomicamente no kernel.