8

I've narrowed down a bug in a program I'm working on to (surprisingly) some vim behavior!

The program contains a file watcher. When I write a file with vim -u NONE and all the default settings, the behavior is as expected: some swap files are created and deleted, and the main file is saved.

But when I add :set nocompatible, I get the following additional inotify events:

wd=149, mask=IN_CREATE (0x100), cookie=0, length=16, name='4913'
wd=149, mask=IN_ATTRIB (0x4), cookie=0, length=16, name='4913'
wd=149, mask=IN_DELETE (0x200), cookie=0, length=16, name='4913'
<normal events appear after>

This indicates that vim is creating, modifying, and then deleting a file called 4913 in the directory of the file I'm editing.

If I create such a file myself (and chmod 000 it), vim will use 5036 instead. This leads me to believe that vim is looking for some arbitrary temporary file.

The number is always 4913 (across files, across reboots).

This is quite alarming. I obviously want to use nocompatible, but this is a prohibitive bug. What can I do?

3
  • 2
    Why is this a bug? Rethink your file watcher to allow other programs to do their job as they can. Vim isn't doing something forbidden.
    – VanLaser
    Commented Jul 27, 2015 at 9:48
  • 1
    @VanLaser: Yep, I've since added exceptions for 4913 and friends. The bug is that the file is called 4913 instead of .vim_permissions_test. I'm certain that I'm not the first person confused by such a filename. Just because it's not forbidden doesn't mean it's not unwise.
    – wchargin
    Commented Jul 27, 2015 at 17:32
  • Yes, I just wanted to say that it's not clear what your program / file watcher is doing, and why the fact that another program (i.e. vim) creates some temporary files would be "alarming" and "a prohibitive bug". Is your program actually a vim plugin? (this isn't something important, just unclear)
    – VanLaser
    Commented Jul 27, 2015 at 21:48

1 Answer 1

6

When writing a buffer Vim will create a temporary file which it will fchown() to verify it has permission to create files in this directory; simplified version from buf_write() in src/fileio.c:

/*
 * Check if we can create a file and set the owner/group to
 * the ones from the original file.
 * First find a file name that doesn't exist yet (use some
 * arbitrary numbers).
 */
STRCPY(IObuff, fname);
for (i = 4913; ; i += 123)
{
    sprintf((char *)gettail(IObuff), "%d", i);
    if (mch_lstat((char *)IObuff, &st) < 0)
        break;
}
fd = mch_open((char *)IObuff,
                    O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm);
if (fd < 0)     /* can't write in directory */
    backup_copy = TRUE;
else
{

    ignored = fchown(fd, st_old.st_uid, st_old.st_gid);
    if (mch_stat((char *)IObuff, &st) < 0
            || st.st_uid != st_old.st_uid
            || st.st_gid != st_old.st_gid
            || (long)st.st_mode != perm)
        backup_copy = TRUE;
    /* Close the file before removing it, on MS-Windows we
     * can't delete an open file. */
    close(fd);
    mch_remove(IObuff);

So it will first try 4913, and it will keep increment it with 123 until we find a filename that doesn't exist yet. Why 4913 and not 4912 or 4914? I have no idea. It could be that the number is truly arbitrary.

This code is only run if the 'backupcopy' setting is set to auto; from the help page:

The main values are:
"yes"   make a copy of the file and overwrite the original one
"no"    rename the file and write a new one
"auto"  one of the previous, what works best

It's used to help determine which value to use (hence the setting of backup_copy = TRUE in the above code).

The "compatible" vi default for backupcopy is yes, while the "non-compatible" Vim default is auto; when setting compatible Vim will reset various settings back to the Vi or Vim defaults:

:set compatible
:set backupcopy?
  backupcopy=yes

:set nocompatible
:set backupcopy?
  backupcopy=auto

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.