A Wine user has requested the ability to interact with Unix symlinks from Win32 code.
While the generic functionality of NT reparse points is still not implemented upstream, it will probably involve a completely different code path than this, so there does not seem to me to be any point in waiting for that to be done before submitting these patches.
This does not implement all the relevant functionality. FILE_OPEN_REPARSE_POINT is now respected, but returns an fd with no fd->unix_fd. Thus far only file disposition (i.e. deletion), renaming and hardlinking are implemented, and all other operations return the no_fd_status, for which STATUS_REPARSE_POINT_NOT_RESOLVED is arbitrarily chosen.
This is probably going to be controversial. As controversial patches tend to get deferred forever, I'm going to at least try to pose some questions related to concept and implementation which may be easier to answer.
* Do we want to expose Unix symlinks at all? This was requested by a Wine user, and it does seem a strong argument that Wine, in general, supports some measure of integration with the host, including exposing custom interfaces for programs written to take advantage of it.
We also, currently, already expose Unix *directory* symlinks via NtQueryAttributesFile(). We don't currently expose such file symlinks (and this series does not change that particular point, but it would be done by follow-up patches). In a sense we are expanding existing partial support.
On the other hand, Unix symlinks which are completely opaque can be useful, and some downstream distributions (CrossOver and Proton) currently rely on them to reduce disk space usage while keeping the application unaware of a symlink (even if it were to use FILE_OPEN_REPARSE_POINT. Not that any applications are currently known that would break if this were to change, and in any case they could simply revert these patches.)
* Implementation-wise, is having unix_fd == -1 a non-starter? This can be true of other real fds in some specific cases...
* It's also true that this current implementation suffers from some degree of TOCTOU problems: because we only store the name and not the FD anymore, the actual underlying object at that path can change. This would not be true on Windows. Is this a problem?
* One alternate approach would be to use O_PATH (Linux, FreeBSD) and O_SYMLINK (Mac). I don't see any equivalent flag for NetBSD or Solaris, so we would probably just not be able to expose this functionality there.
Note that while the documentation seems to imply that O_PATH only stores the path, manual testing shows that (at least on Linux) a fd opened with O_PATH will remain pointing at the same *inode* even if it is moved or deleted. So this would avoid the aforementioned TOCTOU problem.