Why doesn't std.file.exists follow symbolic links?
Jack Applegame
japplegame at gmail.com
Fri Jul 2 14:11:22 UTC 2021
On Friday, 2 July 2021 at 12:32:21 UTC, jfondren wrote:
> On Friday, 2 July 2021 at 12:09:20 UTC, Jack Applegame wrote:
>> ```d
>> import std.stdio : writeln;
>> import std.file : exists, write, symlink, remove;
>>
>> void main() {
>> write("file.txt", "hello");
>> symlink("file.txt", "link.txt");
>> writeln(exists("link.txt")); // true
>> remove("file.txt");
>> writeln(exists("link.txt")); // true, why?
>> }
>> ```
>>
>> In other languages (including C++) similar functions follow
>> symbolic links.
>
> Some thoughts:
>
> 1. This is a dubious test anyway as the status of the file can
> change
> immediately after the test. If at all possible the better way
> to deal
> with a file system is to "ask for forgiveness" (gracefully
> react to
> errors) rather than "ask for permission" (use tests like this
> and then
> be surprised by an error that can still happen).
>
This is a completely different topic. The above code is just a
demonstration that `std.file.exists` does not follow symbolic
links, and not the real code.
> 2. Saying that a symlink "doesn't exist" when it clearly does
> exist
> could also be confusing.
I do not think so. The symbolic link should be transparent by
default.
> 3. System software that's trying to make secure use of the
> filesystem
> should really be using the openat() and other *at syscalls with
> dir fds. The kernel APIs have developed a lot in the past few
> decades
> and one reason I prefer D over traditional 'scripting
> languages' is
> that those languages have all refused to track these
> developments, so
> e.g. D but not Perl can swap two files atomically (with
> renameat2),
> without worrying about race conditions where a process might
> notice
> that one of the files doesn't exist.
>
This is also a completely different topic.
> 4. Actually for the reasons above, if std.file.exists were
> freshly
> made I think it would also be completely fine to change it if
> indeed
> stat() is the more popular underlying call...
>
> 5. ... but it's been like this since 2015. So people who wanted
> to know what the function actually did have already peeked into
> the library, saw it was lstat() on POSIX, and are now relying
> on that.
>
> I would resolving this in the direction of clearly documenting
> the interaction with symlinks.
Maybe you're right. I don't know how to fix this correctly.
More information about the Digitalmars-d
mailing list