[Mono-dev] Mono.Unix - UnixDirectoryInfo.IsSymbolyicLink question

Jonathan Pryor jonpryor at vt.edu
Mon Oct 3 07:56:10 EDT 2005

On Mon, 2005-10-03 at 20:50 +1000, Paddy Joy wrote:
> I have a directory /home/paddy/test which contains one sub-directory and 
> one symbolic link:
> [root at localhost test]# ls -lh
> total 12K
> drwxr-xr-x  2 root root 4.0K Oct  3 20:38 directory
> lrwxrwxrwx  1 root root    4 Oct  3 20:39 SYMLINK -> /tmp
> -rw-r--r--  1 root root  535 Oct  3 20:41 test.cs
> -rwxr-xr-x  1 root root 3.5K Oct  3 20:41 test.exe
> [root at localhost test]#
> When I run the following code:
> I get the output:
> /home/paddy/test/directory
> False
> /home/paddy/test/SYMLINK
> False
> Should I get True for the symbolic link /home/paddy/test/SYMLINK? Am I 
> misunderstanding the meaning of the property IsSymbolicLink or is it 
> just my dodgy code?

It's either your misunderstanding or my dodgy code. :-)

Background: there are three system calls to get status information:
stat(2), fstat(2), and lstat(2).  fstat(2) works on file descriptors, so
who cares (see UnixStream)?   stat(2) and lstat(2) both accept file
names, the difference being their behavior when given symbolic links:
stat(2) will implicitly "dereference" the symbolic link(s), giving you
status information for the *target* file; lstat(2) will give you
information about the symbolic link *itself*.

Why's this matter?  Because UnixFileInfo and UnixDirectoryInfo call
stat(2), and thus will always "dereference" any symbolic links given to
them.  UnixSymbolicLinkInfo, on the other hand, uses lstat(2), and thus
will return IsSymbolicLink=True for:

	Console.WriteLine("IsSymbolicLink=" + 
		new UnixSymbolicLinkInfo("/home/paddy/test/SYMLINK")

One potential point of confusion is that, while UnixFileInfo and
UnixDirectoryInfo always refer to the symlink target, they don't update
the FullName (and related) properties to also refer to the symlink
target.  I thought this was a good idea at the time, since getting the
Parent directory would return the "logical" parent instead of the
target's parent, but perhaps that isn't a good idea.  Or perhaps
everything else should return the results of stat(2), but IsSymbolicLink
should return the results of lstat(2)...

Regardless, unless the current design changes (I'm open to suggestions),
if you care about symbolic links you should use UnixSymbolicLinkInfo,
and you can use UnixSymbolicLinkInfo.Contents to get a
UnixFileSystemInfo instance for the symlink target.  Note that this is
only one "indirection" -- if the target is itself a symlink (pointing to
another symlink, pointing to another symlink...),
UnixSymbolicLinkInfo.Contents will return another UnixSymbolicLinkInfo
instance, and you can manually walk the symlink "chain".

Alternatively, if you don't care about the chain after the first
indirection, create a UnixFileInfo/UnixDirectoryInfo instance over
UnixSymbolicLinkInfo.ContentsPath.  (How you figure out if it's a file
or a directory without walking the entire chain is up to you, or I add
another property to UnixSymbolicLinkInfo.
IsTargetFile/IsTargetDirectory, anyone?)

 - Jon

More information about the Mono-devel-list mailing list