Skip to content

implement nt path conversion for windows #7664

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

Merged
merged 4 commits into from
May 22, 2021

Conversation

marler8997
Copy link
Contributor

@marler8997 marler8997 commented Jan 3, 2021

Second attempt to fix #6044 (previous attempt #7537)

The first attempt leveraged the functionality in ntdll to perform the Dos to NT path conversion, however, that API requires heap allocation which @andrewrk has indicated we don't want (see #7537 (comment)).

So this PR implements the logic to convert a DOS file path into an NT-compatible path in Zig's std lib.

@marler8997 marler8997 marked this pull request as draft January 3, 2021 03:31
@marler8997 marler8997 force-pushed the fixWindowsPaths branch 3 times, most recently from ba5677a to 344553f Compare January 3, 2021 04:05
/// The error type for `removeDotDirsSanitized`
pub const RemoveDotDirsError = error { TooManyParentDirs };

/// Removes '.' and '..' path components from a "sanitized relative path".
Copy link
Contributor

Choose a reason for hiding this comment

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

this function looks like it belongs in std.fs.path. it might be a duple of resolveWindows?

Copy link
Contributor Author

@marler8997 marler8997 Jan 3, 2021

Choose a reason for hiding this comment

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

It's specific to windows...only works with backslashes. We could also make it work with forward slashes but I think posix has other better ways to perform this operation. resolveWindows does alot more than this function, it uses CWD and touches the filesystem (and I think resolves symlinks). This function does none of that, it just removes the . and .. directories from the path name.

Copy link
Contributor

@daurnimator daurnimator Jan 3, 2021

Choose a reason for hiding this comment

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

It's specific to windows...only works with backslashes

Os-specific code is all over the standard library: it doesn't need to all get dumped into os/windows.zig.

@daurnimator daurnimator added os-windows standard library This issue involves writing Zig code for the standard library. labels Jan 3, 2021
@marler8997 marler8997 marked this pull request as ready for review January 3, 2021 08:12
lib/std/mem.zig Outdated
}

/// Collapse consecutive duplicate elements into one entry.
pub fn collapseRepeats(comptime T: type, slice: []T, needle: T) usize {
Copy link
Contributor

Choose a reason for hiding this comment

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

Not much of a needle, it's more a element no?
And given it squishes slice contents it makes sense for this to return a slice of it.

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've changed needle to elem.

As for returning a slice, such an interface could be supported with a wrapper function at no runtime cost. In the current uses, only the resulting size is used and this same interface is propagated in a handful of places which makes the code simpler.

Copy link
Contributor

Choose a reason for hiding this comment

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

You can get the old behaviour by simply adding a .len at the end.
Returning a slice makes the API much easier to use as f(collapseRepeats(..)), throwing indices around is error-prone.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Returning a slice makes the API much easier to use

In some cases yes. If such a use case comes up we can add a wrapper function that does this.

Copy link
Contributor

Choose a reason for hiding this comment

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

It should be the other way around, returning a slice returns a pointer and the adjusted length.

Copy link
Contributor Author

@marler8997 marler8997 Jan 6, 2021

Choose a reason for hiding this comment

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

It should be the other way around, returning a slice returns a pointer and the adjusted length.

My philosphy is to do less, and then only do more if you need to. Going the other way around means always doing more even if you don't need to, and then undoing what you don't need.

I believe my pattern here is also already established in other functions in this codebase, so I don't think I'm alone in this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Another example of an API that uses this methodology is the Allocator resizeFn function.

Copy link
Contributor

Choose a reason for hiding this comment

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

If you're adding new public-facing APIs you can't just think in terms of "do less" or think of your single use-case.
Returning the length makes using this function with sliced inputs hard to use, consider the following example:

const x = collapseRepeats(foo[bar..Baz], ...)

If you return a sub-slice the user is able to quickly use the modified chunk of input, while if the length is returned instead another slicing operation is required.

But given that opinions are like assholes I'll rest my case, I'm getting too old for this shit.

Copy link
Contributor Author

@marler8997 marler8997 Jan 7, 2021

Choose a reason for hiding this comment

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

Ok the fact that this is a public facing "general" function is a good point. How about creating a collapseRepeatsLen that only returns the length and collapseRepeats that wraps it?

@marler8997 marler8997 force-pushed the fixWindowsPaths branch 4 times, most recently from f90bc87 to cd84d96 Compare January 7, 2021 18:35
Copy link
Member

@andrewrk andrewrk left a comment

Choose a reason for hiding this comment

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

Thanks for the patch. This solution involves manipulating path strings, however Windows has symlinks, and on other platforms, when opening files with std.fs, ".." path components respect symlinks, so we need to do it here, too.

Comment on lines -1293 to -1374
// If you're looking to contribute to zig and fix this, see here for an example of how to
// implement this: https://git.midipix.org/ntapi/tree/src/fs/ntapi_tt_open_physical_parent_directory.c
Copy link
Member

@andrewrk andrewrk Apr 2, 2021

Choose a reason for hiding this comment

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

I don't see this addressed in the PR description - did you look into using this technique to resolve .. in a way that respects following symlinks?

Related: NtQueryObject #1840

Copy link
Contributor Author

Choose a reason for hiding this comment

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

On windows symlinks are resolved after resolving ".." (#7751)

@marler8997 marler8997 force-pushed the fixWindowsPaths branch 2 times, most recently from 11162fa to b11bb6e Compare April 3, 2021 17:01
@marler8997 marler8997 force-pushed the fixWindowsPaths branch 2 times, most recently from 813ce22 to d68ea4a Compare May 21, 2021 05:38
@marler8997 marler8997 deleted the fixWindowsPaths branch May 22, 2021 23:31
squeek502 added a commit to squeek502/zig that referenced this pull request May 23, 2021
These tests check that . and .. are able to be handled by the std.fs functions. Before ziglang#7664, these tests would have failed on Windows.

Closes ziglang#4659
squeek502 added a commit to squeek502/zig that referenced this pull request May 23, 2021
@squeek502
Copy link
Collaborator

Nice work @marler8997! This hugely improves std.fs on Windows.

@andrewrk
Copy link
Member

Thanks for the clean-up PRs @squeek502!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
os-windows standard library This issue involves writing Zig code for the standard library.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

'.' and '..' components in relative paths in std.os.windows.OpenFile
5 participants