difficult problem with symbolic link handling

Christopher Faylor cgf@redhat.com
Sat Apr 28 10:07:00 GMT 2001


[long explanation follows]
Someone recently pointed out a problem with "1.3.1 symbolic link handling".
In reality, AFAICT, this is a long-standing problem with cygwin's symbolic
problem.  It's at least a year old and probably older.

The pathological case was the /usr/lib/terminfo link.  /usr/lib/terminfo
is a link to ../share/terminfo.

The problem with that is that /usr/lib is a link to /lib.  So Cygwin's
current symbolic link handling does this:

1) Convert /usr/lib/terminfo to (for example) f:\cygwin\lib\terminfo.

2) Read f:\cygwin\link\terminfo and retrieve the value ../share/terminfo.

3) Bite off the trailing path component and change this to:
   f:\cygwin\lib\..\share\terminfo.

4) "Canonicalize" this path to f:\cygwin\share\terminfo.

5) Does this file exist?  No.  Return an error.

As you can see this is an "error" in cygwin's file handling.

I've "fixed" this problem by doing the following:

1) Canonicalize /usr/lib/terminfo -> /usr/lib/terminfo

2) Pass /usr/lib/terminfo to symlink lookup which converts this
   to the MS-DOS equivalent f:\cygwin\lib\terminfo.

3) Return "../share/terminfo"

4) Bite off trailing path component and change this to:
   "/usr/lib/../share/terminfo"

5) Goto 1, which converts this to "/usr/share/terminfo", eventually
   exiting the loop with "success" when the file is found.

On the face of it, this seems to be the right thing to do, but there are
some problems.  One problem is that step 2 is called repeatedly in this
new scenario.  This is a fairly expensive scan of cygwin's mount table
(which involves a gratuitous canonicalize that was already done in step
1).  Another more serious problem is that there is ambiguity in the
parsing.

What if /usr/lib/terminfo had a mount table entry of:

f:\foo\bar\blaz\terminfo

and blaz was a symlink?  That would not be handled in my "improved"
filename scanning above because f:\foo\bar\blaz\terminfo wouldn't
actually exist.  That doesn't bother the current process but the
"improved" process would notice that it didn't exist and start trying to
find a prefix to /usr/lib/terminfo that did exist.

So, it would do a:

/usr/lib/terminfo
    doesn't exist, try:
	/usr/lib
	    exists, is is a symbolic link?
		No, /usr/lib/terminfo doesn't exist


So, basically, what this means is that symlinks won't work in the mount
table, where they did before.

Does anyone have any problems with this new behavior?  IMO, this new
way is more correct but I have a nagging feeling that I may be missing
something.

cgf



More information about the Cygwin-developers mailing list