Windows: hardlink support is broken on shared drives

Adrian Buehlmann adrian at cadifra.com
Mon Aug 23 17:44:38 CDT 2010


On 24.08.2010 00:17, Adrian Buehlmann wrote:
> (adding Patrick to cc)
> 
> On 23.08.2010 22:22, Gavin Erry wrote:
>> All
>>
>>  
>>
>> I’ve been reading this thread with interest since I posted the problem
>> on the discussion list.  Thanks for the fix – I will test it in the next
>> build of Hg.  It seemed strange that GetFileInformationByHandle doesn’t
>> work too well so I had a look (in C++ though)
>>
>>  
>>
>> It seems that you can get different results depending on how the handle
>> was created with the CreateFile function.
>>
>> If I use GENERIC_READ or FILE_GENERIC_READ for the desired access in
>> CreateFile then I get an incorrect hardlink count.
>>
>> Using FILE_READ_ATTRIBUTES | SYNCHRONIZE (which is a subset of
>> FILE_GENERIC_READ) then I get the correct hardlink count over the network.
>>
>>  
>>
>> This is all with Windows XP, and MS C++ (I don’t do Python).
>>
>>  
>>
>> This is really a FYI - I have a bit of C++ code if anyone is interested,
>> but am not sure of the posting policy.
>>
>>  
>>
>> Gavin
> 
> Very interesting! Thanks.
> 
> I've modified Patrick's testlink.py accordingly (attached). Specifically
> I changed _getfileinfo to (the symbolic constants for FILE_READ_ATTRIBUTES 
> 0x0080 and SYNCHRONIZE 0x00100000L were missing in win32file):
> 
>     def _getfileinfo(pathname):
>         """Return number of hardlinks for the given file."""
>         try:
>             fh = win32file.CreateFile(pathname,
>                                       0x0080 | 0x00100000L,
>                                       win32file.FILE_SHARE_READ,
>                                       None, win32file.OPEN_EXISTING, 0, None)
>             try:
>                 return win32file.GetFileInformationByHandle(fh)
>             finally:
>                 fh.Close()
>         except pywintypes.error, e:
>             print e
>             return None

Even simpler. Just specifying 0 for dwDesiredAccess works as well:

    def _getfileinfo(pathname):
        """Return number of hardlinks for the given file."""
        try:
            fh = win32file.CreateFile(pathname,
                                      0, # device query access
                                      win32file.FILE_SHARE_READ,
                                      None, win32file.OPEN_EXISTING, 0, None)
            try:
                return win32file.GetFileInformationByHandle(fh)
            finally:
                fh.Close()
        except pywintypes.error, e:
            print e
            return None


[1] has '0' for desiredAccess as (quote):

  "Specifies device query access to the object. An application can query device
   attributes without accessing the device."

[1] http://docs.activestate.com/activepython/2.5/pywin32/win32file__CreateFile_meth.html


More information about the Mercurial-devel mailing list