On Thu, 04 Nov 2010 23:37:28 +0100 Colomban Wendling lists.ban@herbesfolles.org wrote:
Le 04/11/2010 21:42, Dimitar Zhekov a ecrit :
For more than 20 years now, the only safe save is to write the data into a temporary file in the same directory, and then rename it over the target file. Even if the rename fails, you still have the temporary file. That changes the onwership and permissions, which is exactly the behaviour of the safe g_file_set_contents().
Well... stop me if I'm saying bullshit but what about:
No, you are not; I should have been more specific. It's the only way which requires 2x disk space (that is unavoidable) but not 2x I/O. For Geany the latter doesn't matter so much, but glib is a general purpose library, and that's why it includes a safe method that modifies the metadata and links, and an unsafe method (documented as "the safest way possible", no less!), which preserves them.
Our choices are:
1. The unsafe old or GIO method. Already supported. 2. The safe glib method which modifies the metadata/links. Supported for GIO = false, easy to include for GIO = true. 3. Our own method, which is safe, but generates 2x the I/O (minimum). 4. Our own method, based on the safe glib method, which preserves at least the ownership and permissions (but even that fails sometimes).
backup = path + '~' # or whatever if copy (path, backup_path): # COPY file to the backup if not write (path, data): # write in original file move (backup_path, path) # if write failed, restore backup elif not make_backup: unlink (backup_path) # if no backup is to be done, delete backup
That'll be fine if backups are on, but as Lex pointed out, does too much I/O if they are off. So for backups = false we can:
a. Create filename-foo, write data to it, abort and unlink on failure. b. Write data to filename. On failure, rename filename-foo to filename, and notify the user that the metadata and links are lost. c. If even the rename fails, which is highly unlikely for files in the same directory, inform the user that the original file is _probably_ lost, and if so, filename-foo contains the data, but lacks the metadata and links.
(probably, because remote filesystems may do the rename but fail to report it; that's specially mentioned for NFS in rename(2):BUGS)
(filename-foo and not filename~, because we don't our insurance file containing the _new_ data to be replaced by some accidential backup, be it Geany's (if the user subsequently turned backups on) or cp's, mv's etc.)
The problems I see are:
- needs at least 2 times the size of the file in the target directory (but it's the same anytime we bake backups)
Unavoidable.
- backup file may have altered permissions/attrs
...links, ACL-s etc. Unavoidable.
- ...so if write fails, we have changed the permissions/attrs on the original file
Unavoidable.
In the worst case, the original file has another name and lost its permissions/attrs.
Unavoidable. Alas, no miracles for us.
Being a bit lazy, I'd prefer to include the safe glib method in the GIO code path (with the use_safe_file_saving option, as before) and be done with it. So for limited disk space and/or unstable connections, just turn the option on, we even have a GUI for that now. It's a compromise, but what isn't?..