RFC: Junction Point/NT Symlink Support

Erich E. Hoover erich.e.hoover at gmail.com
Mon Mar 25 12:55:11 CDT 2019


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.



More information about the wine-devel mailing list