-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Enable New-Item creates symlinks to non-existent targets #13082
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
e7450f5
824cc9a
1155056
dc80aa6
c31ea16
edde025
94e2706
d1754e0
0427aa6
06d6056
a1fbc96
0e546fd
2cda01b
beb7251
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 |
|---|---|---|
|
|
@@ -3433,7 +3433,6 @@ internal void NewItem( | |
| } | ||
|
|
||
| ProviderInfo provider = null; | ||
| PSDriveInfo driveInfo; | ||
| CmdletProvider providerInstance = null; | ||
|
|
||
| Collection<string> providerPaths = new Collection<string>(); | ||
|
|
@@ -3443,7 +3442,7 @@ internal void NewItem( | |
| if (string.IsNullOrEmpty(name)) | ||
| { | ||
| string providerPath = | ||
| Globber.GetProviderPath(resolvePath, context, out provider, out driveInfo); | ||
| Globber.GetProviderPath(resolvePath, context, out provider, out _); | ||
|
|
||
| providerInstance = GetProviderInstance(provider); | ||
| providerPaths.Add(providerPath); | ||
|
|
@@ -3459,86 +3458,56 @@ internal void NewItem( | |
| out providerInstance); | ||
| } | ||
|
|
||
| // Don't support 'New-Item -Type Directory' on the Function provider | ||
| // if the runspace has ever been in constrained language mode, as the mkdir | ||
| // function can be abused | ||
| if (context.ExecutionContext.HasRunspaceEverUsedConstrainedLanguageMode && | ||
| (providerInstance is Microsoft.PowerShell.Commands.FunctionProvider) && | ||
| (string.Equals(type, "Directory", StringComparison.OrdinalIgnoreCase))) | ||
| { | ||
| throw | ||
| PSTraceSource.NewNotSupportedException(SessionStateStrings.DriveCmdletProvider_NotSupported); | ||
| } | ||
|
|
||
| // Symbolic link targets are allowed to not exist on both Windows and Linux | ||
| bool allowNonexistingPath = false; | ||
| bool isSymbolicJunctionOrHardLink = false; | ||
|
|
||
| if (type != null) | ||
| { | ||
| WildcardPattern typeEvaluator = WildcardPattern.Get(type + "*", WildcardOptions.IgnoreCase | WildcardOptions.Compiled); | ||
|
Member
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 don't understand the use of the wildcardpattern here,
Collaborator
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. It is not new code. It is moved code. |
||
|
|
||
| allowNonexistingPath = typeEvaluator.IsMatch("symboliclink"); | ||
|
|
||
| isSymbolicJunctionOrHardLink = | ||
| typeEvaluator.IsMatch("symboliclink") | ||
| || typeEvaluator.IsMatch("junction") | ||
| || typeEvaluator.IsMatch("hardlink"); | ||
| } | ||
|
|
||
| foreach (string providerPath in providerPaths) | ||
| { | ||
| // Compose the globbed container and the name together to get a path | ||
| // to pass on to the provider. | ||
|
|
||
| string composedPath = providerPath; | ||
| if (!string.IsNullOrEmpty(name)) | ||
| { | ||
| composedPath = MakePath(providerInstance, providerPath, name, context); | ||
| } | ||
|
|
||
| // Don't support 'New-Item -Type Directory' on the Function provider | ||
| // if the runspace has ever been in constrained language mode, as the mkdir | ||
| // function can be abused | ||
| if (context.ExecutionContext.HasRunspaceEverUsedConstrainedLanguageMode && | ||
| (providerInstance is Microsoft.PowerShell.Commands.FunctionProvider) && | ||
| (string.Equals(type, "Directory", StringComparison.OrdinalIgnoreCase))) | ||
| { | ||
| throw | ||
| PSTraceSource.NewNotSupportedException(SessionStateStrings.DriveCmdletProvider_NotSupported); | ||
| } | ||
|
|
||
| bool isSymbolicJunctionOrHardLink = false; | ||
| // Symbolic link targets are allowed to not exist on both Windows and Linux | ||
| bool allowNonexistingPath = false; | ||
|
|
||
| if (type != null) | ||
| { | ||
| WildcardPattern typeEvaluator = WildcardPattern.Get(type + "*", WildcardOptions.IgnoreCase | WildcardOptions.Compiled); | ||
|
|
||
| if (typeEvaluator.IsMatch("symboliclink") || typeEvaluator.IsMatch("junction") || typeEvaluator.IsMatch("hardlink")) | ||
| { | ||
| isSymbolicJunctionOrHardLink = true; | ||
| allowNonexistingPath = typeEvaluator.IsMatch("symboliclink"); | ||
| } | ||
| } | ||
| string targetPath = content?.ToString(); | ||
|
|
||
| if (isSymbolicJunctionOrHardLink) | ||
| { | ||
| string targetPath; | ||
|
|
||
| if (content is null || string.IsNullOrEmpty(targetPath = content.ToString())) | ||
| if (string.IsNullOrEmpty(targetPath)) | ||
| { | ||
| throw PSTraceSource.NewArgumentNullException(nameof(content), SessionStateStrings.NewLinkTargetNotSpecified, path); | ||
| } | ||
|
|
||
| ProviderInfo targetProvider = null; | ||
| CmdletProvider targetProviderInstance = null; | ||
|
|
||
| var globbedTarget = Globber.GetGlobbedProviderPathsFromMonadPath( | ||
| targetPath, | ||
| allowNonexistingPath, | ||
| context, | ||
| out targetProvider, | ||
| out targetProviderInstance); | ||
|
|
||
| if (!string.Equals(targetProvider.Name, "filesystem", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| throw PSTraceSource.NewNotSupportedException(SessionStateStrings.MustBeFileSystemPath); | ||
| } | ||
|
|
||
| if (globbedTarget.Count > 1) | ||
| { | ||
| throw PSTraceSource.NewInvalidOperationException(SessionStateStrings.PathResolvedToMultiple, targetPath); | ||
| } | ||
|
|
||
| if (globbedTarget.Count == 0) | ||
| { | ||
| throw PSTraceSource.NewInvalidOperationException(SessionStateStrings.PathNotFound, targetPath); | ||
| } | ||
|
|
||
| // If the original target was a relative path, we want to leave it as relative if it did not require | ||
| // globbing to resolve. | ||
| if (WildcardPattern.ContainsWildcardCharacters(targetPath)) | ||
| { | ||
| content = globbedTarget[0]; | ||
| } | ||
| targetPath = targetPath?.Replace(StringLiterals.AlternatePathSeparator, StringLiterals.DefaultPathSeparator); | ||
| } | ||
|
|
||
| NewItemPrivate(providerInstance, composedPath, type, content, context); | ||
| NewItemPrivate(providerInstance, composedPath, type, targetPath, context); | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -3574,7 +3543,7 @@ private void NewItemPrivate( | |
| CmdletProvider providerInstance, | ||
| string path, | ||
| string type, | ||
| object content, | ||
| string content, | ||
| CmdletProviderContext context) | ||
| { | ||
| // All parameters should have been validated by caller | ||
|
|
||
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.
You should add a test case to cover this
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.
It is not new code. It is moved code.