The Samba-Bugzilla – Bug 4557
smbc_stat or smbc_getxattr can't handle Vista symlinks.
Last modified: 2007-12-20 04:16:30 UTC
We are not able to tell if a file is a symlink or junction when run against a Vista client.
This causes quite a bit of problem as smbc_open/smbc_read will throw a lot of errors going through a directory structure on a Vista client with a lot of symlinks/junctions.
Below are our tests and findings.
C:\Users\Administrator\Documents>mklink /j myjunction mydir
Junction created for myjunction <<===>> mydir
C:\Users\Administrator\Documents>mklink /d mysymlink mydir
symbolic link created for mysymlink <<===>> mydir
Volume in drive C has no label.
Volume Serial Number is 0256-B10C
Directory of C:\Users\Administrator\Documents
2007-04-26 09:44 <DIR> .
2007-04-26 09:44 <DIR> ..
2007-04-26 09:41 <DIR> mydir
2007-04-26 09:40 <JUNCTION> myjunction [C:\Users\Administrator\Documents\mydir]
2007-04-26 09:40 <SYMLINKD> mysymlink [mydir]
0 File(s) 0 bytes
5 Dir(s) 139 957 547 008 bytes free
stat: mode 0x41ed
getxattr: mode 0x10
stat: mode 0x41ed
getxattr: mode (9) EBADF
stat: mode 0x41ed
getxattr: mode 0x410
Created attachment 3027 [details]
Vista-Vista dir command showing junction
I did a connect from a vista machine to another vista machine and executed a dir command on the remote share.
Created attachment 3028 [details]
Followed a junction in Explorer when mounting a Vista share from Vista
Created attachment 3029 [details]
Listing folder through explorer on a vista machine when connected to another vista machine
Can you repeat the same traces with Vista against W2k3, XP or some Windows version that is *not* Vista? What you sent is smb2 traffic which Samba does not yet support.
Created attachment 3035 [details]
WIn XP to Vista dir command showing a junction.
XP machine mounted a Vista share and did a dir /a. I can see that it identifies the junction as a Reparse Point but with the difference that there is no information to where the junctions points. Maybe we need SMB2 for that?
I've been researching this topic. Reparse points predate Vista, so SMB2 should not be required. However, to read a reparse point (which it seems is a junction), the required library function is DeviceIoControl() using FSCTL_GET_REPARSE_POINT. The documentation subtree worth reviewing appears to be:
I'm not sure that DeviceIoControl can be used over the network, although I'd be a bit surprised if it could not be. If you can provide me with a packet trace that shows returning what the reparse point points to (using XP or W2K, not Vista), I may be able to add that functionality. You may be able to obtain that using Windows commands or by writing an application which uses DeviceIoControl().
I've been trying to get a pre-vista machine to issue a FCTL_GET_REPARSE_POINT call but I can't I suppose its not due to the limitation of the SMB protocol but rather there is no utility out there that uses FCTL_GET_REPARSE_POINT. Maybe you can use the information on the technet article you showed me together with the trace from Vista-Vista where the FCTL_GET_REPARSE_POINT is used?
I'll keep trying!
The previous traces were all SMB2 traffic. I don't think we're quite ready to add SMB2 to Samba3. (Samba4 supports it in some fashion, although to what extent I'm not sure.)
> I'll keep trying!
There's got to be some application that uses it, but if not, if you can figure out the semantics of the ioctl or library call, you should be able to write a small app that issues the request and receives the response... Yes?
Created attachment 3054 [details]
Dump of traffic showing use of FCTL_GET_REPARSE_POINT over SMB v1
Today is you lucky day! ( and mine =) )
I succeeded to issue a FCTL_GET_REPARSE_POINT over the SMB protocol! :)
Now work your magic! :D
Ok, after spending the morning doing more researching... Here are a couple of pretty good developer-oriented background articles:
It seems possible to add handling of reparse points in the internal Samba library. It's less obvious how to map it to the POSIX-like interface of libsmbclient. In particular, how would one distinguish between a Junction (which can only be on a directory) and a Symbolic Link if the latter is on a directory?
If I were to just return the Junction or SymLink data on a newly-created smbc_lstat() call (ignoring the previous issue), I'd also want to create an smbc_symlink() to create them...
I could possibly use the /??/ "unparse" header to distinguish between a Junction and a SymLink by always returning that from smbc_lstat()... and then similarly create a Juncion if the provided path begins with /??/ and a SymLink otherwise.
And furthermore, if smbc_lstat() returns what a reparse point points to, then what must smbc_stat() now do? Follow the reparse point? (I'm getting a headache.) I don't think I can follow it without breaking backward compatibility unless I add an option specifying which procedure to use...
(What about a MountPoint reparse point? I suppose that would be done with a smbc_mount() function which I don't plan to implement now.)
Still thinking, and open to suggestions.
Good links! I found some other nice links regarding reparse points on codeproject also.
To distinguish between junction and symlink I suppose the header is the only way but I haven't looked that thoroughly on the SMB traffic regarding that yet.
I believe all these issues need to be looked at different angles to really get a complete view on how to handle it but the most important features to start with is.
a) Return a SMBC_LINK type OR a new type (SMBC_REPARSE_POINT?) when we come upon a reparse point.
b) Implement a smbc_lstat function that can retrieve the target of the reparse point and also type of reparse point (symlink/junction) if we don't do it directly.
If we just know these things the programmer can determine what he/she wants to do with it. I don't think we need to worry about following these reparse points for starters. If a programmer wants to issue a smbc_stat on the target then he should call a smbc_lstat first to determine the target.
Of course it would be great if we could handle them the same way we handle the POSIX links but I guess we need more research to determine that. As always windows has done a poor job implementing links functionality in their filesystem.
Creating junctions/symlinks would be a really nice features also. I really don't have any creative input on how yet but I think it would be quite straight forward.
Thats my input for now. I'll keep thinking about it and give you any input I come up with. You can message me directly on my e-mail if you want some more feedback outside the bugreport.