7 ms·
I'm sorry symlinks are a thorn in Jeremy's side, but they are useful from a user's perspective. Hard links don't fill the same need. You can't normally hard lin
by js2 4y ago
I'm sorry symlinks are a thorn in Jeremy's side, but they are useful from a user's perspective. Hard links don't fill the same need. You can't normally hard link directories. If a file has multiple links, finding them all normally requires scanning the entire file system, so deleting a file now becomes harder. A file with multiple links doesn't have an obvious canonical path.
As an example of all these issues, I manage a bunch of Mac build hosts with multiple Xcode versions installed. We only retain the most recent patch release of each major.minor version, but drop compatibility symlinks in place for the other versions. On macOS, an application is just a directory. So for example we'll have:
Xcode-13.0.app -> Xcode-13.0.1.app
Xcode-13.0.1.app
From a simple "ls" it's obvious which versions are installed and which are just compatibility shims. Symlinks are just so damn convenient for use cases like this. Hard links don't cut the mustard here.
So there are more reasons for symlinks than just "hard links are restricted to linking within the same filesystem", but yes, that too.
Probably I'm just lacking imagination and there's a solution that offers the advantages of symlinks with none of the downsides, but in my experience, we see this sort of indirection all over the computing landscape, so it seems like there's a fundamental need for it.
- OnlyMortal 4y agoI take it an “alias” isn’t good in this case? An alias does follow a move of the original - usually.
- yjftsjthsd-h 4y agoInteresting; how does that work under the hood?
- OnlyMortal 4y agohttps://en.m.wikipedia.org/wiki/Alias_(Mac_OS) https://en.m.wikipedia.org/wiki/Alias_(Mac_OS)
- js2 4y agoIt's macOS magic that requires HFS/APFS and doesn't work at the POSIX layer. It would not work for my use case, no. An alias is like a hybrid between a symbolic link and a hard link. Like a symbolic link, it's its own file type whose contents point to the original, but like a hard link it points to the original using its ID, not its path. So an alias works even if the original is moved, but it does not increase the original's link count and is its own distinct entity in the file system.
- lxgr 4y ago> You can't normally hard link directories. That's only to avoid loops, as far as I understand. Symlinks do allow loops, but require application programmers to handle them. So maybe we just need better APIs/API contracts around loops, rather than two types of links? > If a file has multiple links, finding them all normally requires scanning the entire file system Couldn't this pretty easily be solved at the file system level? Just store a back pointer from a file to each of its names. The fact that it's possible to break symlinks very easily by deleting the pointed-to file (name) is a problem as well: Wouldn't application developers usually, or at least sometimes, want to know about the fact that they are about to break a link (or conversely, not deleting the final copy of a file and not just a reference to it)? > So there are more reasons for symlinks than just "hard links are restricted to linking within the same filesystem" I think this might be the only real (technical/historical) limitation. The rest could probably be worked around, but maybe having two distinct types of links, with these other binary decisions (allowing loops, making deletion explicit vs. a matter of referenc counting) being more or less arbitrarily bucketed into those two types based on what was easier to implement.
- mzs 4y agoELOOP errno
- deleted 4y ago[deleted]
- XorNot 4y agoHard links don't have a canonical name though - they're all equally the same file, and this is really a problem: opening and editing a file in one location, edits it in all of them without you knowing what those locations might be. Symlinks at least explicitly declare the dependency and how it should mutate. A classic being /etc/resolve.conf symlinks - if I'm untarring and restore a symlink for it, I'm currently saying the file should have content from somewhere else on the system - not that the file is specific content.
- masklinn 4y ago> Hard links don't have a canonical name though - they're all equally the same file, and this is really a problem: opening and editing a file in one location, edits it in all of them without you knowing what those locations might be. That is something the filesystem could store tho, in the same way it stores the number of links to a file it could be a bit more capable and store the links themselves (possibly in a xattr). > Symlinks at least explicitly declare the dependency and how it should mutate. They only declare one dependency one way, it's not like a symlink gives you all the other symlinks to the terminal location it will affect.
- waynesonfire 4y agosymlinks are great, I don't see why we would remove such feature. The author pointed out a bunch of issues around atomic operations related to symlinks which in my view are valid. Similar TOCTOU race exists with PIDs, see https://lwn.net/Articles/773459/ https://lwn.net/Articles/773459/ Not sure whether the pid issue was ever resolved, havn't checked in on that in a while.
- GoblinSlayer 4y agohttps://man7.org/linux/man-pages/man2/pidfd_open.2.html https://man7.org/linux/man-pages/man2/pidfd_open.2.html
- IshKebab 4y agoSymlinks are great from a "just make it work!" point of view but they're absolutely terrible from a "make it robust, sane and secure" point of view. All of the points in the article are valid but there's even simpler stuff like the fact that you can't canonicalise paths (resolve ..) without reading the filesystem. This should be required reading: https://9p.io/sys/doc/lexnames.html https://9p.io/sys/doc/lexnames.html
- kazinator 4y agoYou can resolve some .. components without reading the filesystem and there are situations where it is useful to do that, while refusing to treat .. that cannot be resolved without accessing the filesystem. One example is inside the implementation of a function that calculates relative paths: 1> (rel-path "a/b" "../c") "../../../c" 2> (rel-path "../c" "a/b") ** rel-path: from path uses .. to escape common prefix: "../c" "a/b" ** during evaluation at expr-2:1 of form (rel-path "../c" "a/b") The relative path from ../c to a/b cannot be calculated as a pure function of just the two strings, because we do not know what the current directory is called in the .. parent; that would require searching the file system. The function is very useful with this restriction, which can be externally worked around if ever necessary, e.g. by tacking the absolute path of the current directory onto both arguments: 3> (rel-path `@(pwd)/../c` `@(pwd)/a/b`) "../kaz/a/b"