Bram Moolenaar wrote:
> > rename() would behave identically and moreover would be atomic.
> 
> It appears you don't have 'backupcopy' set, as was recommended in the
> thread you quote.

I thought about rename temporary file to target one and backupcopy doesn't
change it. Below, strace of command with backupcopy set:

17518 execve("/usr/bin/vim", ["vim", "+set backupcopy=yes", "testfile"], [/* 49 
vars */]) = 0
[...]
17518 open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0600) = 3
17518 write(3, "test test test something else\n"..., 30) = 30
17518 fsync(3)                          = 0
17518 close(3)                          = 0
17518 chmod("testfile", 0100600)        = 0

As you can see, vim opens edited file with O_TRUNC, so it is truncated
for non-zero time. No matter what I set, backupcopy=yes or backupcopy=no,
above mentioned fragment is exactly the same. backupcopy has influence
only on creating another inode or writing to the same one:

> > So, I have a little request to developers. Please, read it again and try
> > to understand me. Atomic rename() is better solution. It's not so stupid
> > as it may appear at first look and shouldn't break to much. :-)
> 
> I'm afraid that it will break much.  Especially when not on a Unix
> system.

I thought only about unix. I don't know how vim behave on other systems,
but on unix it could behave better. I don't want you to change it on all
systems (because I am aware that something may be broken because of that),
but only on unix (in principle on POSIX).

> The problem is that using rename() is not atomic, because we need two
> of them.

One rename() is always atomic and changing from temporary file to target
file should be atomic, what I expect vim to do:

    rename("test.tmp", "test");

Of course, ale the process of saving file (preparing temporary files,
making backup file, cleaning up, etc.) can't be atomic, but exchanging
target (edited) file could be atomic by means of rename().

> And the procedure to write a new file and then rename
> again has the problem that the inode changes, which is bad for hard
> links and complex ACL.

I wrote about hard links, and I agree that rename() may break it.
Files with number of hard links greater then one should be treated
individually.

As to ACLs, if vim can change standard unix mode, owner and group (e.g.
with backupcopy=no), why it couldn't change POSIX extended attributes,
ACLs, etc.?

> The only solution is overwriting the file.  Currently it's first made
> empty.  It would be possible to first write the new contents and then
> truncate to remove any remaining old text.  But that's worse: halfway
> writing you have an inconsistent file, at some place it switches from
> the new text to the old text.  I rather have a truncated file, that's
> less problematic.
> 
> In case we rename the file to make a backup, it would be possible to
> first write the new file and then use two rename calls to swap the old
> and new files.  Again, if another process is using the file, it will
> suddenly see different text.  And on Unix, if the file was opened by
> another process, it will keep on using the old version.  This only
> solves a few very specific situations.

I don't expect vim to rename edited file to backup file. Rather, it should
be copied. All the operations would be done on temporary file and during
saving, temporary file should be filled with new content, set with right
permissions, ACLs, owner, group, etc. and finally, should be atomically
renamed to target file. From another process point of view (which only
read this file), its contents changes atomically and there is no time
when file was broken, truncated or half written. In meta-code it could
look like this:

    fd = open("file");
    read(fd, buffer, size);
    close(fd);
    copy("file", "file~");
    [...here user edits file...]
    fd = open("file.tmp", O_WRONLY|O_CREAT|O_TRUNC);
    write(fd, "new content of file");
    close(fd);
    chmod("file.swp", mode);
    chown("file.swp", owner, group);
    [...if need be, setting other parameters like ACLs...]
    rename("file.swp", "file");

Of course, file content and inode attributes could be changed between
reading it's content and final rename(), but this situation is not resolvable
on standard POSIX file system semantic. However, this behaviour secures
other processes, which only read (not write), against incorrect content.

Regards.

-- 
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php

Raspunde prin e-mail lui