Поки ви не переміщуєте файл через межі файлової системи, робота повинна бути безпечною. Це пов'язано з механізмом того, як насправді робиться «переміщення».
Якщо ви mv
знаходитесь в одній файловій системі, файл насправді не торкається, а змінюється лише запис файлової системи.
$ mv foo bar
насправді робить щось подібне
$ ln foo bar
$ rm foo
Це створило б жорстке посилання (другий запис у каталозі) для файлу (власне, вкладеного пункту, вказаного файловою системою), foo
названого bar
та видалення foo
запису. Оскільки тепер при видаленні foo
існує друга запис файлової системи, що вказує на foo
inode 's, видалення старого запису foo
фактично не видаляє блоки, що належать до inode.
Ваша програма з радістю додасть файл у будь-який момент, оскільки його відкрита ручка файлу вказує на вкладення файлу, а не на запис файлової системи.
Примітка: Якщо ваша програма закриє і знову відкриє файл між записами, у вас з'явиться новий файл, створений зі старою записом файлової системи!
Перехресна файлова система рухається:
Якщо ви переміщуєте файл через межі файлової системи, все стає некрасивим. У цьому випадку ви не могли гарантувати постійне зберігання файлів, оскільки це mv
було б насправді
- створити новий файл у цільовій файловій системі
- скопіюйте вміст старого файлу в новий файл
- видаліть старий файл
або
$ cp /path/to/foo /path/to/bar
$ rm /path/to/foo
респ.
$ touch /path/to/bar
$ cat < /path/to/foo > /path/to/bar
$ rm /path/to/foo
Залежно від того, чи дійне копіювання до кінця файлу під час запису вашої заявки, може статися, що у вас в новій файлі є лише половина рядка.
Крім того, якщо ваша програма не закриє і не відкриє старий файл, він продовжує записувати до старого файлу, навіть якщо він видається видаленим: ядро знає, які файли відкриті, і хоча воно видалило б запис файлової системи, воно не видалить inode старого файлу та пов’язані з ним блоки, поки ваша програма не закриє свою відкриту ручку файлу.
rename()
системного виклику. Таким чином, оригінальна версіяmv
фактично закликалаlink()
створити жорстке посилання з подальшимunlink()
видаленням оригінальної назви.rename()
додано у FreeBSD, щоб реалізувати це атомно в ядрі.