rename(2) using NTFS transactions on Vista/2008

Eric Blake ebb9@byu.net
Tue May 20 02:04:00 GMT 2008


According to Corinna Vinschen on 5/19/2008 1:21 PM:
>> cygwin-1.7.0-9 had problems with rename("file","link") returning a spurious 
>> ENOENT.  But I haven't been able to test 1.7.0-10 yet, to see if it has 
>> been fixed.
> 
> Probably not.  How to reproduce?

// Demonstrate rename(2) bug.
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

int main()
{
   int result = 0;
   int fd = creat ("f", 0666);
   if (fd < 0 || close (fd) || symlink ("nowhere", "l"))
     {
       puts ("framework failure");
       result = 1;
       goto cleanup;
     }

   if (rename ("f", "l"))
     {
       printf ("rename failed with errno %d, %s\n", errno,
               strerror (errno));
       result = 2;
     }

  cleanup:
   remove ("f");
   remove ("l");
   return result;
}

Should succeed silently (and did in 1.5.x). I haven't tested whether your 
latest patch fixes it; I also noticed that while it failed for 
cygwin-1.7.0-9, it appeared to work for a self-built cygwin1.dll (but I'm 
not sure if that's the extra debugging or other changes I've put into my 
self-built version).  I'll double check again tomorrow, if you don't beat 
me to it.

I also noticed today a behavior where 'cp -p old new' was setting the 
system bit on the new file, as if by 'attrib +S new', but haven't had time 
to look into it further.

> 
>> Meanwhile, while looking at the code, is it really a good idea to have 3 
>> stack-allocated path_conv variables, each 32k in size?  That sounds like a 
> 
> They are not necessarily 32K but you're right, they could be in the
> worst case.

I saw what you fixed with alloca usage, and it is an improvement.  But I 
was talking about path_conv, which is still broken.  sizeof(path_conv) > 
32k at the moment, because of path_conv.path[], even when the two file 
names are 1 byte each.  It looks like it could still be useful to keep the 
path[] member to reduce pressure on cmalloc in the common case, but with a 
much smaller size than NT_MAX_PATH (maybe 1k bytes, so that a method like 
rename(2) can still have three instances of a stack-allocated path_conv 
without overflowing a 4k guard) where both the original name and the 
normalized_path can fit into that area, while leaving larger paths (both 
original and normalized, rather than the current approach of just 
normalized) under cmalloc management.

-- 
Don't work too hard, make some time for fun as well!

Eric Blake             ebb9@byu.net



More information about the Cygwin-developers mailing list