-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Make CreateSubdirectory() work in root directory #49414
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -74,20 +74,15 @@ public DirectoryInfo CreateSubdirectory(string path) | |||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| string newPath = Path.GetFullPath(Path.Combine(FullPath, path)); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ReadOnlySpan<char> trimmedNewPath = Path.TrimEndingDirectorySeparator(newPath.AsSpan()); | ||||||||||||||||||||||||||||||
| ReadOnlySpan<char> trimmedCurrentPath = Path.TrimEndingDirectorySeparator(FullPath.AsSpan()); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // We want to make sure the requested directory is actually under the subdirectory. | ||||||||||||||||||||||||||||||
| if (trimmedNewPath.StartsWith(trimmedCurrentPath, PathInternal.StringComparison) | ||||||||||||||||||||||||||||||
| // Allow the exact same path, but prevent allowing "..\FooBar" through when the directory is "Foo" | ||||||||||||||||||||||||||||||
| && ((trimmedNewPath.Length == trimmedCurrentPath.Length) || PathInternal.IsDirectorySeparator(newPath[trimmedCurrentPath.Length]))) | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| FileSystem.CreateDirectory(newPath); | ||||||||||||||||||||||||||||||
| return new DirectoryInfo(newPath); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // We weren't nested | ||||||||||||||||||||||||||||||
| throw new ArgumentException(SR.Format(SR.Argument_InvalidSubPath, path, FullPath), nameof(path)); | ||||||||||||||||||||||||||||||
| // Allow the exact same path, but prevent allowing "..\FooBar" through when the directory is "Foo" | ||||||||||||||||||||||||||||||
| string newPathWithTrailingSeparator = PathInternal.EnsureTrailingSeparator(newPath); | ||||||||||||||||||||||||||||||
| string currentPathWithTrailingSeparator = PathInternal.EnsureTrailingSeparator(FullPath); | ||||||||||||||||||||||||||||||
| if (!newPathWithTrailingSeparator.StartsWith(currentPathWithTrailingSeparator, PathInternal.StringComparison)) | ||||||||||||||||||||||||||||||
| throw new ArgumentException(SR.Format(SR.Argument_InvalidSubPath, newPath, FullPath), nameof(path)); | ||||||||||||||||||||||||||||||
|
Comment on lines
+81
to
+82
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is perfectly fine with me, but out of curiosity, what's the reason we'd add braces around this one when all the other
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could use (this was fixed in #45139) runtime/src/libraries/Microsoft.Extensions.FileSystemGlobbing/src/InMemoryDirectoryInfo.cs Lines 120 to 127 in 72e41f9
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @iSazonov - Thanks for the suggestion. How are you proposing we put that function to use? The solution I've proposed up to this point doesn't actually do a special-case check for being a root directory at all; instead, it adjusts the logic for one of the forbidden cases so that it doesn't accidentally also disallow creating subdirectories of the root directory.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The comment in line 77 suggests otherwise. Actually FullPath must be a root path for newPath.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, when you say "root path" do you mean "parent path" of another path? Because "IsRootDirectory" to me is a method name that suggests it checks to see if a path is an actual root directory, an absolute root, as in "/" or "C:" or the like. Especially since this bug we're addressing here is specifically a failure in the case where it is used on a drive root directory, I was thrown off by the ambiguity of the term "root". (In fact, I'd suggest maybe the above method should be called "IsParentDirectory" instead.) In any case, I'll take a look at that- need to make sure using it doesn't regress what was being fixed by 6c41cc9.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that the method name confuses. |
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| FileSystem.CreateDirectory(newPath); | ||||||||||||||||||||||||||||||
| return new DirectoryInfo(newPath); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| public void Create() | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you verified that this behavior is not being regressed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Best I can tell, that comment was added, and behavior fixed, here: 6c41cc9
Which added or touched three tests:
SubDirectoryIsParentDirectory_ThrowsArgumentException()ValidPathWithTrailingSlash()ValidPathWithoutTrailingSlash()All three of those do still pass. (At least on Linux. I've had only headaches trying to build this project on Windows so far, so haven't yet verified on that platform.)