Windows: hardlink support is broken on shared drives

Adrian Buehlmann adrian at cadifra.com
Mon Aug 23 18:09:45 CDT 2010


On 24.08.2010 00:44, Adrian Buehlmann wrote:
> 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

I found 0 for desiredAccess in MSDN documented as [2]:

"If this parameter is zero, the application can query certain metadata
such as file, directory, or device attributes without accessing that
file or device, even if GENERIC_READ access would have been denied. "

[2] http://msdn.microsoft.com/en-us/library/aa363858%28VS.85%29.aspx


More information about the Mercurial-devel mailing list