Visible symlinks under Windows

Corinna Vinschen corinna at
Thu Feb 21 10:37:07 GMT 2008

Any comment?  I'd really have some feedback before I implement something
totally broken.


On Feb 14 11:45, Corinna Vinschen wrote:
> To follow up on this...  [Beware!  It's somewhat long...]
> On Feb  7 12:04, Corinna Vinschen wrote:
> > On Feb  6 13:41, James Peach wrote:
> > > With your EA proposal, I think the server would have to restrict symlinks 
> > > to be relative to the SMB share and to point to a file within the share. 
> > > You'd need this because some clients will follow the symlink on the server, 
> > > and some will resolve the target on the client side and you want both 
> > > methods to end up at the same place.
> > 
> > I guess you're right.  Otherwise the non-EA file information returned
> > by calls to ZwQueryInformationFile would point to another file than
> > the symlink path in the EA, and an application trying to access a file
> > gotten by a call to readlink would fail.  That sounds rather... medium
> > well.
> > 
> > > So, yeh I'm convinced that EA symlinks are worthwhile ...
> ...on second thought it turns out that the EAs alone are not very
> helpful as far as the Cygwin side is concerned.
> The problem is that the information if EAs are available is only
> accessible when opening the file.  This would be a big performance
> problem.  Right now, Cygwin only requests file information which is
> available without having to open a file.  Only if that information hints
> to a file being a symlink, *then* Cygwin opens the file and retrieves
> the information from the file.
> For instance, the old-style faked symlinks on Cygwin have the SYSTEM
> attribute bit set, the new-style symlinks are actually Windows shortcuts
> with the R/O attribute bit set.  So the code which tries to figure out
> if a file is a symlink works basically like this:
>   NtQueryAttributesFile ();
>   if (attributes & FILE_ATTRIBUTE_SYSTEM)
>     maybe_symlink = true;
>   else if ((filename ends in ".lnk") && attributes & FILE_ATTRIBUTE_READONLY)
>     maybe_symlink = true;
>   if (maybe_symlink)
>     {
>       NtOpenFile();
>       get_symlink_info();
>       NtClose();
>     }
> Assuming we get only the EAs from Samba, we would have to open *every*
> single file on Samba to retrieve EAs:
>   else if (is_samba ())
>     {
>       NtOpenFile ();
>       NtQueryEaFile ();
>       if (has_symlink_ea)
>         get_symlink_info();
>       NtClose();
>     }
> I guess the performance hit would be a real show stopper.  What we need
> is some way to retrieve file information without having to open the file
> and to get a hint that this file might be a symlink.
> Mulling about this problem, I stumbled over the NtQueryFullAttributesFile
> function, which is the NT function retrieving the NT equivalent of the
> SMB_FILE_NETWORK_OPEN_INFORMATION block.  It's the maximum amount of 
> information available to a Windows client without opening a file.  The
> structure consists of
>   birthtime
>   atime
>   mtime
>   ctime
>   allocation_size
>   file_size
>   dos_attributes
> Is it possible to sneak in the information that the file or dir is
> actually a symlink into the above structure?
> Two members of this structure are not used by Win32 clients, ctime and
> allocation_size, because the Win32 equivalent of the
> NtQueryFullAttributesFile function, GetFileAttributesEx, does not expose
> them.  But ctime is retrieved by Cygwin as... ctime.
> So, I had the following idea:  Since the allocation_size isn't used
> anyway, what if it simply gets set to st_size?
> This would be different from the allocation_size for directories (0)
> as well as different from the allocation_size of files (st_size rounded
> up to some blocksize value) most of the time.  That would allow Cygwin
> to retrieve EAs only when it's really a symlink, in 99.9% of the cases.
> Does that makes sense?
> Thanks,
> Corinna

More information about the samba-technical mailing list