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ê mvpossui 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) foocom o nome bare remover a fooentrada. Como agora, ao remover foo, existe uma segunda entrada do sistema de arquivos apontando para fooo inode, remover a entrada antiga foona 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 mvisso 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 demvfato 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.