rename(2) using NTFS transactions on Vista/2008

Eric Blake
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;

   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   

More information about the Cygwin-developers mailing list