From a8f4fb8a076cb758d0ca3b1e7486c2452ec3d267 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Tue, 26 Apr 2016 08:55:43 -0700 Subject: [PATCH 1/5] For Symlinks to directories, fix Windows error on removal, and asking confirmation on Linux --- .../namespaces/FileSystemProvider.cs | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 79e92e995..b86716034 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -2848,13 +2848,16 @@ namespace Microsoft.PowerShell.Commands bool continueRemoval = true; - // We only want to confirm the removal if this is the root of the - // tree being removed or the recurse flag is specified. - if (rootOfRemoval || recurse) + if (Platform.IsWindows || (directory.Attributes & FileAttributes.ReparsePoint) == 0) { - // Confirm the user wants to remove the directory - string action = FileSystemProviderStrings.RemoveItemActionDirectory; - continueRemoval = ShouldProcess(directory.FullName, action); + // We only want to confirm the removal if this is the root of the + // tree being removed or the recurse flag is specified. + if (rootOfRemoval || recurse) + { + // Confirm the user wants to remove the directory + string action = FileSystemProviderStrings.RemoveItemActionDirectory; + continueRemoval = ShouldProcess(directory.FullName, action); + } } //if this is a reparse point and force is not specified then warn user but dont remove the directory. @@ -8452,10 +8455,24 @@ namespace Microsoft.PowerShell.Commands IntPtr dangerousHandle = handle.DangerousGetHandle(); int bytesReturned; + // Do a FSCTL_GET_REPARSE_POINT first because the ReparseTag could be + // IO_REPARSE_TAG_MOUNT_POINT or IO_REPARSE_TAG_SYMLINK. + // Using the wrote one results in mismatched-tag error. + REPARSE_GUID_DATA_BUFFER junctionData = new REPARSE_GUID_DATA_BUFFER(); + ClrFacade.StructureToPtr(junctionData, outBuffer, false); + + result = DeviceIoControl(dangerousHandle, FSCTL_GET_REPARSE_POINT, IntPtr.Zero, 0, + outBuffer, inOutBufferSize, out bytesReturned, IntPtr.Zero); + if (!result) + { + int lastError = Marshal.GetLastWin32Error(); + throw new Win32Exception(lastError); + } + + junctionData = ClrFacade.PtrToStructure(outBuffer); junctionData.ReparseDataLength = 0; junctionData.DataBuffer = new char[MAX_REPARSE_SIZE]; - junctionData.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; ClrFacade.StructureToPtr(junctionData, inBuffer, false); From 967634f732af01ebec8e6718fd5ed7af3f7eadca Mon Sep 17 00:00:00 2001 From: George Fleming Date: Tue, 26 Apr 2016 15:53:51 -0700 Subject: [PATCH 2/5] Don't ask for Linux --- .../commands/management/Navigation.cs | 26 ++++++++++++------- .../namespaces/FileSystemProvider.cs | 17 +++++------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs index d2ba941ee..c986672d1 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs @@ -3562,20 +3562,28 @@ namespace Microsoft.PowerShell.Commands } bool shouldRecurse = Recurse; - if (!Recurse && hasChildren) + System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(providerPath); + if (Platform.IsLinux && di != null && (di.Attributes & System.IO.FileAttributes.ReparsePoint) != 0) { - // Get the localized prompt string + shouldRecurse = false; + } + else + { + if (!Recurse && hasChildren) + { + // Get the localized prompt string - string prompt = StringUtil.Format(NavigationResources.RemoveItemWithChildren,resolvedPath.Path); + string prompt = StringUtil.Format(NavigationResources.RemoveItemWithChildren,resolvedPath.Path); - // Confirm the user wants to remove all children and the item even if - // they did not specify -recurse + // Confirm the user wants to remove all children and the item even if + // they did not specify -recurse - if (!ShouldContinue (prompt, null, ref yesToAll, ref noToAll)) - { - continue; + if (!ShouldContinue (prompt, null, ref yesToAll, ref noToAll)) + { + continue; + } + shouldRecurse = true; } - shouldRecurse = true; } // Now do the delete diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index b86716034..d94bc854c 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -2848,20 +2848,17 @@ namespace Microsoft.PowerShell.Commands bool continueRemoval = true; - if (Platform.IsWindows || (directory.Attributes & FileAttributes.ReparsePoint) == 0) + // We only want to confirm the removal if this is the root of the + // tree being removed or the recurse flag is specified. + if (rootOfRemoval || recurse) { - // We only want to confirm the removal if this is the root of the - // tree being removed or the recurse flag is specified. - if (rootOfRemoval || recurse) - { - // Confirm the user wants to remove the directory - string action = FileSystemProviderStrings.RemoveItemActionDirectory; - continueRemoval = ShouldProcess(directory.FullName, action); - } + // Confirm the user wants to remove the directory + string action = FileSystemProviderStrings.RemoveItemActionDirectory; + continueRemoval = ShouldProcess(directory.FullName, action); } //if this is a reparse point and force is not specified then warn user but dont remove the directory. - if (((directory.Attributes & FileAttributes.ReparsePoint) != 0) && !Force) + if (Platform.IsWindows && ((directory.Attributes & FileAttributes.ReparsePoint) != 0) && !Force) { String error = StringUtil.Format(FileSystemProviderStrings.DirectoryReparsePoint, directory.FullName); Exception e = new IOException(error); From 1b1858cf09d3ba0f3e4c197cdbbd833141bb705e Mon Sep 17 00:00:00 2001 From: George Fleming Date: Wed, 27 Apr 2016 08:35:01 -0700 Subject: [PATCH 3/5] Fix FileNotFoundException --- .../commands/management/Navigation.cs | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs index c986672d1..4d7a30c05 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs @@ -3562,29 +3562,36 @@ namespace Microsoft.PowerShell.Commands } bool shouldRecurse = Recurse; - System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(providerPath); - if (Platform.IsLinux && di != null && (di.Attributes & System.IO.FileAttributes.ReparsePoint) != 0) + bool linuxLink = false; + try { - shouldRecurse = false; - } - else - { - if (!Recurse && hasChildren) + System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(providerPath); + if (Platform.IsLinux && di != null && (di.Attributes & System.IO.FileAttributes.ReparsePoint) != 0) { - // Get the localized prompt string - - string prompt = StringUtil.Format(NavigationResources.RemoveItemWithChildren,resolvedPath.Path); - - // Confirm the user wants to remove all children and the item even if - // they did not specify -recurse - - if (!ShouldContinue (prompt, null, ref yesToAll, ref noToAll)) - { - continue; - } - shouldRecurse = true; + shouldRecurse = false; + linuxLink = true; } } + catch (System.IO.FileNotFoundException) + { + // not a directory + } + + if (!linuxLink && !Recurse && hasChildren) + { + // Get the localized prompt string + + string prompt = StringUtil.Format(NavigationResources.RemoveItemWithChildren,resolvedPath.Path); + + // Confirm the user wants to remove all children and the item even if + // they did not specify -recurse + + if (!ShouldContinue (prompt, null, ref yesToAll, ref noToAll)) + { + continue; + } + shouldRecurse = true; + } // Now do the delete // This calls the internal method since it is more efficient From 70884879dffd444ba88c72e1dd788af44456dec7 Mon Sep 17 00:00:00 2001 From: George Fleming Date: Thu, 28 Apr 2016 09:01:07 -0700 Subject: [PATCH 4/5] switch from Platform.IsLinux to Not Platform.IsWindows --- .../commands/management/Navigation.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs index 4d7a30c05..fb58250d3 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Navigation.cs @@ -3562,14 +3562,14 @@ namespace Microsoft.PowerShell.Commands } bool shouldRecurse = Recurse; - bool linuxLink = false; + bool treatAsFile = false; try { System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(providerPath); - if (Platform.IsLinux && di != null && (di.Attributes & System.IO.FileAttributes.ReparsePoint) != 0) + if (!Platform.IsWindows && di != null && (di.Attributes & System.IO.FileAttributes.ReparsePoint) != 0) { shouldRecurse = false; - linuxLink = true; + treatAsFile = true; } } catch (System.IO.FileNotFoundException) @@ -3577,7 +3577,7 @@ namespace Microsoft.PowerShell.Commands // not a directory } - if (!linuxLink && !Recurse && hasChildren) + if (!treatAsFile && !Recurse && hasChildren) { // Get the localized prompt string From b87c026bbe61504358c392f18dc5c8edfcfded4c Mon Sep 17 00:00:00 2001 From: George Fleming Date: Thu, 28 Apr 2016 09:01:26 -0700 Subject: [PATCH 5/5] Fix spelling --- .../namespaces/FileSystemProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index d94bc854c..6dc033623 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -8454,7 +8454,7 @@ namespace Microsoft.PowerShell.Commands // Do a FSCTL_GET_REPARSE_POINT first because the ReparseTag could be // IO_REPARSE_TAG_MOUNT_POINT or IO_REPARSE_TAG_SYMLINK. - // Using the wrote one results in mismatched-tag error. + // Using the wrong one results in mismatched-tag error. REPARSE_GUID_DATA_BUFFER junctionData = new REPARSE_GUID_DATA_BUFFER(); ClrFacade.StructureToPtr(junctionData, outBuffer, false);