| |
| Posted by Jack Applegame in reply to jfondren | PermalinkReply |
|
Jack Applegame
Posted in reply to jfondren
| 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:
> 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:
- 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.
>
- 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.
>
- 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.
>
-
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...
-
... 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.
|