Why doesn't std.file.exists follow symbolic links?

jfondren julian.fondren at gmail.com
Fri Jul 2 12:32:21 UTC 2021

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 
immediately after the test. If at all possible the better way to 
with a file system is to "ask for forgiveness" (gracefully react 
errors) rather than "ask for permission" (use tests like this and 
be surprised by an error that can still happen).

2. Saying that a symlink "doesn't exist" when it clearly does 
could also be confusing.

3. System software that's trying to make secure use of the 
should really be using the openat() and other *at syscalls with
dir fds. The kernel APIs have developed a lot in the past few 
and one reason I prefer D over traditional 'scripting languages' 
that those languages have all refused to track these 
developments, so
e.g. D but not Perl can swap two files atomically (with 
without worrying about race conditions where a process might 
that one of the files doesn't exist.

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 
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.

More information about the Digitalmars-d mailing list