Thus spake Matthew Dillon <[EMAIL PROTECTED]>: > :However, when you are saving a new version of an important file, > :you need to be careful that the new version (and its directory > :entry) hits the disk before the old one goes away. I know that vi > :saves files in a safe way, whereas ee and emacs do not. (Emacs > :introduces only a small race, though.) Also, mv will DTRT only if > :the source and destination files live on the same filesystem. > : > > I think you have that reversed. vi just overwrites the destination > file (O_CREAT|O_TRUNC, try ktrace'ing a vi session and you will see). > I believe emacs defaults to a mode where it creates a new file and > renames it over the original. > > This means that there is a period of time where a crash may result in > the loss of the file if the vi session cannot be recovered (with vi -r) > after the fact.
vi writes and fsyncs a recovery file when it opens a file for editing, and it fsyncs the real file before removing the recovery file. (I don't know how reliable vi's recovery mechanism is because I don't use vi, but at least it's ensuring that the recovery file is written to disk when it should be.) In Emacs, if 'make-backup-files' is non-nil (the default), the original file ${FILE} is renamed to ${FILE}~. Then it writes out and fsyncs a new file, which is perfectly safe. If 'make-backup-files' is nil, emacs simply omits the renaming part, unsafely overwriting the original file. The behavior in the latter case appears to be a bug, or at least an undocumented feature. Emacs even causes data loss in this case when the disk fills up! It needs to either do an fsync/rename or write and fsync a backup file for the duration of the save. Lastly, with ee, there's no backup file and no fsync. Some ktrace snippets are below. 3662 vi CALL open(0x808e260,0x2,0x180) 3662 vi NAMI "/var/tmp/vi.recover/vi.HjDlgO" 3662 vi RET open 4 ... 3662 vi CALL write(0x4,0x809a01c,0x400) 3662 vi GIO fd 4 wrote 1024 bytes "[...]old contents[...]" ... 3662 vi CALL fsync(0x4) 3662 vi RET fsync 0 ... [I edit the file from "old contents" to "new contents"] ... 3662 vi CALL open(0x8095140,0x601,0x1b6) 3662 vi NAMI "foo" 3662 vi RET open 7 ... 3662 vi CALL write(0x7,0x80bb000,0xd) 3662 vi GIO fd 7 wrote 13 bytes "new contents " 3662 vi RET write 13/0xd ... 3662 vi CALL fsync(0x7) 3662 vi RET fsync 0 3662 vi CALL close(0x7) 3662 vi RET close 0 ... 3662 vi CALL lseek(0x4,0,0x400,0,0) 3662 vi RET lseek 1024/0x400 3662 vi CALL write(0x4,0x809a01c,0x400) 3662 vi GIO fd 4 wrote 1024 bytes "[...]new contents[...]" ... 3662 vi CALL fsync(0x4) 3662 vi RET fsync 0 [The following bit only happens if make-backup-files is non-nil] 3799 emacs CALL rename(0x848c328,0x848fba8) 3799 emacs NAMI "/home/test/foo" 3799 emacs NAMI "/home/test/foo~" 3799 emacs RET rename 0 ... [This part happens unconditionally] 3799 emacs CALL open(0x848c328,0x601,0x1b6) 3799 emacs NAMI "/home/test/foo" 3799 emacs RET open 3 3799 emacs CALL write(0x3,0xbfbfae24,0x3) 3799 emacs GIO fd 3 wrote 3 bytes "new" 3799 emacs RET write 3 3799 emacs CALL write(0x3,0xbfbfae24,0x9) 3799 emacs GIO fd 3 wrote 9 bytes " contents" 3799 emacs RET write 9 3799 emacs CALL fsync(0x3) 3799 emacs RET fsync 0 3799 emacs CALL close(0x3) 3799 emacs RET close 0 To Unsubscribe: send mail to [EMAIL PROTECTED] with "unsubscribe freebsd-current" in the body of the message