A number of years ago I put together a patchset for Junction Points that was rejected for two very good reasons: 1) there was no mechanism to atomically replace a directory with a Unix Symlink 2) there was no way to tell the difference between Junction Points and NT Symlinks
The first issue has been addressed in the kernel by the implementation of renameat2 with the RENAME_EXCHANGE flag. I've actually been maintaining a version of my patches with support for this for a few years, but renameat2 kernel support has only recently been included in long-term releases of the major distributions and it wasn't added to glibc until late last year (2.28). So, this issue is finally resolvable.
It's the second issue that has been more of a problem. The major difference between Junction Points and NT Symlinks is that JPs are resolved by the "server" system and NT Symlinks are resolved by the "client" system. For Wine this doesn't matter so much, since we never have a "server" situation, so both can be treated as Unix Symlinks. The problem with this approach is that many applications that create and use Junction Points and NT Symlinks _do_ care what type they are. If such an application creates a Junction Point, reads it back, and we report an NT Symlink then the application can have a variety of issues (the struct returned by FSCTL_GET_REPARSE_POINT is completely different between the two object types). So, it seems that we cannot properly implement either Junction Points or NT Symlinks until we have a way to implement both.
Proposed Solution: Since the operating system treats symlinks as special files, we do not have the ability to apply extended attributes, access controls, or permissions* to these files. This severely restricts our options, and for a number of years I have been struggling with finding solutions that don't involve some sort of brittle record keeping. However, I recently realized that the OS does "keep track of" file access and modification times for Unix Symlinks and that they are never updated when they are "accessed" or moved (the file times are only changed when the link itself is changed, as one would expect). So, I would like to propose that we store the "ReparseTag" in the st_atime for the link (since the modification time is reported by "ls") and the additional NT Symlink-specific flags in the OS-specific tv_usec/tv_nsec portion of the access time (in microseconds, for greatest portability).
This solution provides a variety of benefits: 1) the type of link (JP/Symlink) is retained when the link is moved 2) no additional record keeping on Wine's part is required 3) the link behaves correctly outside of Wine (it's not a special text file, or something similar) 4) the "ls" command still reports the "correct" time for the link
But has one downside: 1) tar-ing/untar-ing does not retain the type of the link (to my knowledge, tar has no way to store access times)
Another choice, of course, is to use the modification time instead of the access time. This has the benefit of having tar retain the link type with the downside of "ls" reporting an "incorrect" time for the link. This option may be a better choice, since it allows tar-ing/untar-ing prefixes without losing the link type.
So, I have some questions for the group: 1) Does this approach seem reasonable in general? 2) Should the information be stored in the access time (correct "ls" behavior) or the modification time (correct "tar" behavior)? 3) Is there anything else that I'm missing?
Best, Erich
*Some Unix systems apparently allow different permissions on symlinks (and ignore them), but Linux does not.