Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add assumptions for resolveWindows, resolvePosixand realpath #10988

Closed
wants to merge 1 commit into from

Conversation

matu3ba
Copy link
Contributor

@matu3ba matu3ba commented Feb 25, 2022

  • doc: realpath description
  • doc: resolveWindows, resolvePosix do not work with relative paths

@matu3ba
Copy link
Contributor Author

matu3ba commented Feb 25, 2022

This was quite abit surprising behavior on figuring out the problem with workarounds of matu3ba/chepa#1

@topolarity
Copy link
Contributor

Is the assumption for resolve() accurate?

Both resolvePosix and resolveWindows have logic to check whether they were given an absolute path and to make the path relative to CWD if not:

If all paths are relative it uses the current working directory as a starting point.

@topolarity
Copy link
Contributor

topolarity commented Mar 7, 2022

I'm not sure the realpath description is accurate either, or maybe I'm just misunderstanding it.

realpath currently gives me these results in the Zig repo (both with and without libc):

realpath("lib") = "/home/topolarity/repos/zig/lib"
realpath("lib/..") = "/home/topolarity/repos/zig"
realpath("build.zig") = "/home/topolarity/repos/zig/build.zig"
realpath("build.zig/..") = error.NotDir

Is the comment pointing out that "build.zig/.." fails, or are you hitting a different problem?

@matu3ba
Copy link
Contributor Author

matu3ba commented Mar 7, 2022

Is the comment pointing out that "build.zig/.." fails, or are you hitting a different problem?

Yes. Mostly its about pointing out that "build.zig/.." fails.

@topolarity
Copy link
Contributor

topolarity commented Mar 7, 2022

I don't personally find that behavior surprising. However, I do see how that could depend on one's familiarity with POSIX

I don't think the comment needs to mention the root path at all - Maybe clearer phrasing would be:

Note: All /-separated components of the supplied path must resolve to a
directory, or a symlink to a directory, except for the last component

@matu3ba matu3ba force-pushed the resolve branch 2 times, most recently from f6a51ec to a02f03d Compare March 7, 2022 18:51
@matu3ba
Copy link
Contributor Author

matu3ba commented Mar 7, 2022

@topolarity Do you think this good enough?
I dont want to mess with the other text right now.

+/// Note: All /-separated components of the supplied path must resolve to a
+/// directory, or a symlink to a directory, except for the last component
+/// Use `fs.path.resolve` or `fs.path.relative` to get dir of file (`file/..`).
+/// assume: if relative path used, then they are relative to `getcwd()`

@topolarity
Copy link
Contributor

topolarity commented Mar 7, 2022

Looking better 👍 Last nit is that I think we should either mention that path.resolve and .relative do not resolve symlinks, or we should not recommend them here because of that behavior difference

FWIW, the reason file-relative paths work on Windows is that symlinks and directories are resolved after ".." is resolved (roughly equivalent to doing path.resolve, followed by realpath). However, this changes how symlinks interact with ..: "./symlink/.." resolves to "." (the normal Windows behavior), rather than the parent of the symlink target (which is the normal POSIX behavior)

WASI is tackling the same behavioral differences in WebAssembly/wasi-filesystem#26 and so far seems to be leaning towards leaving this up to the Host OS

lib/std/fs/path.zig Outdated Show resolved Hide resolved
lib/std/fs/path.zig Outdated Show resolved Hide resolved
* doc `realpath`: specify requirements and hint to get dir of file
* doc `resolve`: behavior difference on Windows and Linux + consequence
@@ -468,6 +468,10 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool {
}

/// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`.
/// Note: Symlinks currently dont work and should not be used,
/// because Windows and Posix having different behavior.
/// On Windows, symlinks are resolved after `..` is resolved.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "Note: does not expand symlinks" is sufficient for the note here

The details on symlink resolution between platforms have to do with realpath and the other std.os calls, not this function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "Note: does not expand symlinks" is sufficient for the note here

agreed.

The details on symlink resolution between platforms have to do with realpath and the other std.os calls, not this function

Why does this not belong into the description of the portable method, if it is a portability restriction?
I would expect that users tend to do tests on one platform with the most portable method and extrapolate to the others.

@@ -5091,6 +5091,10 @@ pub const RealPathError = error{
/// extra `/` characters in `pathname`.
/// The return value is a slice of `out_buffer`, but not necessarily from the beginning.
/// See also `realpathZ` and `realpathW`.
/// Note: All /-separated components of the supplied path must resolve to a
/// directory, or a symlink to a directory, except for the last component
/// Use `fs.path.resolve` or `fs.path.relative` to get dir of file (`file/..`).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

realpath should fully resolve any path containing relative . and .. components on any POSIX-compliant system as far as I remember. It is only Windows that is the problem where the NT kernel call we issue is unable to deal with those which implies it is up to the user to resolve the relative components first.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The non-working semantics (pathtofolder/file/..) of fs.path.relative can be seen here matu3ba/chepa@f34084c#diff-d924ca21d81d7d5a59eb9e10d3e2689c4c58a7e28e6ecce6a064701666f5a730L173

It is only Windows that is the problem where the NT kernel call we issue is unable to deal with those which implies it is up to the user to resolve the relative components first.

Could we on Windows work around the problem with calling relative on the subpath and then call resolve for each extending subpath? If you can point me to the things I need for testing, I can play abit to see if that could work.
Kind related is #4812.

@andrewrk
Copy link
Member

The changes here are incorrect and unhelpful. I'll scrutinize these doc comments at some point, but at a glance this PR is not an improvement.

@andrewrk andrewrk closed this May 11, 2022
@matu3ba matu3ba deleted the resolve branch May 11, 2022 21:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants