OCaml Forge

Detail: [#712] stat and non-existing symlink

Bugs: Browse | Download .csv | Monitor

[#712] stat and non-existing symlink

2010-08-04 14:29
Submitted by:
Sylvain Le Gall (gildor-admin)
Assigned to:
Sylvain Le Gall (gildor-admin)
Operating System:
stat and non-existing symlink

Detailed description
stat fails when called on a symlink which target is missing.


Date: 2014-05-10 16:46
Sender: Adrien Nader

Just a note to say I haven't forgotten about this issue. My current patch works for me but as time went by I've noticed more and more that it has shortcomings which make it definitely not mergeable. Unfortunately I haven't yet had time to spend on it.
Date: 2013-10-05 14:06
Sender: Adrien Nader

I'm a bit stuck on one detail.

Basically, FileUtil.stat should be changed to behave either as stat() or lstat().

I first added a ?(follow = Follow) argument but as far as I can tell, it would behave differently compared to other places with my current implementation.

Basically, I wrote:
if should_follow ~follow fln then
Unix.LargeFile.stat fln
Unix.LargeFile.lstat fln

This is simple but if there are several levels of symlinks, the AskFollow/SkipInform functions will only be called once for the first filename.

It is not difficult to do the recursive symlink resolving ourselves. The real question is which behaviour is wanted: call AskFollow/SkipInform once or for each intermediate symlink.
Date: 2013-10-05 11:23
Sender: Adrien Nader

I've done the change for find and updated the test suite (along with some additional tests). By the way, the code turned out to be simpler that way.
There is an additional behaviour change: no exception is raised if one of the symlink loops. Instead the entry is simply discarded. I believe it is more correct that way. However it could be nice to have a corresponding callback instead of silently ignoring.

I also have to update cp but I haven't done it yet. It's also a bit annoying that if a -> b -> c -> d and d is a regular file, d needs to be copied to a, b and c.
I've also just noticed that cp took a ?dereference argument but did nothing with it so I'm going to make a patch that removes the argument for now.
Date: 2013-10-04 08:23
Sender: Sylvain Le Gall

Full ACK. I need to do a new version of ocaml-fileutils, too many bugs sitting in the bug tracker and not enough version released.
Date: 2013-10-04 06:41
Sender: Adrien Nader


This issue is bitting me because it makes find() miss symlinks to non-existent targets.

The current implementation tries to dereference the symlink, look at the type and store it as the type of the file. Obviously, that's completely impossible if the target doesn't exist. I believe the approach cannot work and instead, the link must not be dereferenced.

The only possible solution that I can imagine involves:
- adding "Link" to the FileUtil.kind variant
- removing the "is_link" record member in FileUtil.stat

Back to the FileUtil.find function, from my find(1) manpage, I get:
l symbolic link; this is never true if the -L option or the
-follow option is in effect, unless the symbolic link is
broken. If you want to search for symbolic links when -L
is in effect, use -xtype.

FileUtil.find already has a ?follow parameter so we can get the right behaviour with the same function prototype.

FileUtil.cp also relies on the kind field (the one that needs to also include "Link") and has a ?follow parameter too. I've only looked at it quickly after a poor night of sleep but I think that its current behaviour is incorrect when handling symlinks.

Changing FileUtil.stat is definitely an API-break and a behaviour change and I'm not sure how this would be best handled. Unfortunately I see no other solution.

I'll make a patch this week-end if I can do it confidently.

Attached Files:


No Changes Have Been Made to This Item