Skip to content

win32: don't canonicalize relative paths#5435

Merged
ethomson merged 4 commits intomasterfrom
ethomson/canonical
Mar 10, 2020
Merged

win32: don't canonicalize relative paths#5435
ethomson merged 4 commits intomasterfrom
ethomson/canonical

Conversation

@ethomson
Copy link
Member

@ethomson ethomson commented Mar 2, 2020

Our path canonicalization (beginning in cceae9a) was meant to deal with absolute paths, converting things like C:\Foo\Bar into \\?\C:\Foo\Bar so that we could avoid some of the dangers of NTFS (like eliding trailing dots in filenames). But by using those paths, we need to do canonicalization ourselves, as giving \\?\C:\Foo\..\Bar to the filesystem APIs will return an error instead of resolving the path.

These canonicalization function were not meant to deal with relative paths. In particular, this means that leading ".." segments at the beginning of paths were removed, to translate C:\..\..\..\ into the correct \\?\C:\. (This is despite having some tests around relative path components, they were not well thought out since they were not intended to be used.)

Update the documentation on the function to point out that it's not to be used for relative paths, and remove the tests that suggest that it should be used that way.

Add a new function that will keep relative paths relative, while converting them to UTF-16 and translating / to \\.

Use this new relative path handling function when creating Windows symlinks.

@ethomson
Copy link
Member Author

ethomson commented Mar 2, 2020

Note that it feels a little weird to jam relative path handling into this. I considered splitting it out into two different functions, especially since this function is a bit hairy already. But in the end I just modified this one instead of trying to duplicate hairy code.

The path canonicalization functions on win32 are intended to
canonicalize absolute paths; those with prefixes.  In other words,
things start with drive letters (`C:\`), share names (`\\server\share`),
or other prefixes (`\\?\`).

This function removes leading `..` that occur after the prefix but
before the directory/file portion (eg, turning `C:\..\..\..\foo` into
`C:\foo`).  This translation is not appropriate for local paths.
@ethomson ethomson force-pushed the ethomson/canonical branch from 9d03aa7 to 6ee3b2c Compare March 8, 2020 18:38
@ethomson ethomson changed the title win32: canonicalize relative paths win32: don't canonicalize relative paths Mar 8, 2020
@ethomson
Copy link
Member Author

ethomson commented Mar 8, 2020

/cc @pks-t updated with a saner approach

Copy link
Member

@pks-t pks-t left a comment

Choose a reason for hiding this comment

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

This does look a lot better to me, thanks @ethomson! One minor nit, but please feel free to just merge this. 👍

* @param src The UTF-8 string to convert.
* @return The length of the wide string, in characters (not counting the NULL terminator), or < 0 for failure
*/
extern int git_win32_path_relative_from_utf8(git_win32_path dest, const char* src);
Copy link
Member

Choose a reason for hiding this comment

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

Sorry, but minor nit: the * is with the name, not with the type ;)

Copy link
Member Author

Choose a reason for hiding this comment

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

oops! fixed, thanks!

ethomson and others added 3 commits March 10, 2020 20:10
Add a function that takes a (possibly) relative UTF-8 path and emits a
UTF-16 path with forward slashes translated to backslashes.  If the
given path is, in fact, absolute, it will be translated to absolute path
handling rules.
Don't canonicalize symlink targets; our win32 path canonicalization
routines expect an absolute path.  In particular, using the path
canonicalization routines for symlink targets (introduced in commit
7d55bee, "win32: fix relative symlinks pointing into dirs",
2020-01-10).

Now, use the utf8 -> utf16 relative path handling functions, so that
paths like "../foo" will be translated to "..\foo".
Ensure that we don't canonicalize symlink targets.
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.

2 participants