On Tue, Aug 31, 2021 at 11:00 AM Erich E. Hoover erich.e.hoover@gmail.com wrote:
On Tue, Aug 31, 2021 at 10:52 AM Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
... Is there a problem with collapse_path(), or is it just a matter of asking for the parent of the current directory? If the latter, wouldn't it just be a matter of storing the unresolved path in the TEB?
That's necessary but not sufficient, you also need to change the path resolution. It's completely valid (and common) to pass a relative path that does something "stupid". An extension of the Linux example: === ~/tmplnk$ cd link/.. ~/tmplnk$ ls link test ~/tmplnk$ ls link/.. target ===
Something about this didn't sit right with me, so I went back over my notes and this is incorrect at the API level. The working directory is only handled in this special way at the shell/console level, at the API level it is handled the same way as other paths (target-relative). This means that it is a lot easier to implement reparsing on a per-element level than I had attempted long-ago where I stupidly tried to resolve the paths right before passing them to the standard C routines.
So, back to the "how do we handle this?" question. I would like to keep my approach _mostly_ the same (using Unix symlinks) for these reasons: 1) it is easy to detect the existence of a symlink programmatically and work with data stored in the symlink (whether that data is interpreted properly by the OS or not) 2) it allows easier traversal of the directory structure when not in Wine for paths that are "convertible" (some tags, such as IO_REPARSE_TAG_APPEXECLINK, are not possibly convertible by the OS) 3) if/when we need to treat certain key folders as Junction Points then these folders will still work properly outside Wine (e.g. My Documents -> Documents)
What I would like to treat differently now is how the Wine prefix is stored inside the symlink. The current implementation rewrites the prefix path if it is incorrect (doesn't match the current prefix) and this solution is ... not ideal. So, I would like to suggest that instead of (<REPARSE-TAG> and <P> are slash/dot encoded): <REPARSE-TAG>/path/to/prefix<P>/remainder/of/path that we can, instead, use a BSD-style variadic symlink that looks like so: <REPARSE-TAG>${WINEPREFIX}/remainder/of/path
I did not use this solution before for several reasons: 1) This would break non-Wine usage of the symlinks 2) Linux does not support BSD-style variadic symlinks 3) I had misremembered that the relative path handling at the API level was complicated, so I thought that implementing this in Wine would be too difficult
However, it looks like I can now work around all of these issues: 1) On BSD systems 'symvar' can be used to set the value of ${WINEPREFIX} 2) On Linux an unprivileged namespace can be configured to effectively allow the same thing (note that this _only_ works for an absolute path*, such as is the case with ${WINEPREFIX}) 3) Wine can perform the reinterpretation of ${WINEPREFIX} when it parses paths, so it doesn't need to worry about #1 or #2
If this doesn't sound too crazy then I can put together the modifications to make this happen. As part of that I'd like to introduce a tool (command 'wineprefix'?) that configures the Unix environment properly for Linux/BSD to allow the shell to function with this variadic symlink so that users like Martin Storsjö (and myself) can just run the tool to be dropped into a shell where ${WINEPREFIX} inside a symlink will be treated appropriately. (Part of why it's taken me a while to respond to this thread has been putting together a "proof of concept" of this tool to make sure that the idea works, which I can now confirm.) Please let me know what you guys think, hopefully this sounds better to folks.
Best, Erich
* If this worked for relative paths then I would propose storing the reparse tag the same way (e.g. "symvar xA000000C=.")