private Collection<PSObject> GetChildNamesInDir(string dir, string leafElement, bool getAllContainers, CmdletProviderContext context, bool dirIsProviderPath, PSDriveInfo drive, ContainerCmdletProvider provider, out string modifiedDirPath) { string updatedPath = null; string updatedFilter = null; Collection<PSObject> collection4; string filter = context.Filter; bool flag = provider.ConvertPath(leafElement, context.Filter, ref updatedPath, ref updatedFilter, context); if (flag) { tracer.WriteLine("Provider converted path and filter.", new object[0]); tracer.WriteLine("Original path: " + leafElement, new object[0]); tracer.WriteLine("Converted path: " + updatedPath, new object[0]); tracer.WriteLine("Original filter: " + context.Filter, new object[0]); tracer.WriteLine("Converted filter: " + updatedFilter, new object[0]); leafElement = updatedPath; context.Filter = updatedFilter; } ReturnContainers returnAllContainers = ReturnContainers.ReturnAllContainers; if (!getAllContainers) { returnAllContainers = ReturnContainers.ReturnMatchingContainers; } CmdletProviderContext context2 = new CmdletProviderContext(context); context2.SetFilters(new Collection<string>(), new Collection<string>(), context.Filter); try { string path = null; modifiedDirPath = null; if (dirIsProviderPath) { modifiedDirPath = path = context.SuppressWildcardExpansion ? dir : RemoveGlobEscaping(dir); } else { modifiedDirPath = GetMshQualifiedPath(dir, drive); ProviderInfo info = null; CmdletProvider providerInstance = null; Collection<string> collection = this.GetGlobbedProviderPathsFromMonadPath(modifiedDirPath, false, context2, out info, out providerInstance); modifiedDirPath = context.SuppressWildcardExpansion ? modifiedDirPath : RemoveGlobEscaping(modifiedDirPath); if (collection.Count > 0) { path = collection[0]; } else { if (flag) { context.Filter = filter; } return new Collection<PSObject>(); } } if (provider.HasChildItems(path, context2)) { provider.GetChildNames(path, returnAllContainers, context2); } if (context2.HasErrors()) { Collection<ErrorRecord> accumulatedErrorObjects = context2.GetAccumulatedErrorObjects(); if ((accumulatedErrorObjects != null) && (accumulatedErrorObjects.Count > 0)) { foreach (ErrorRecord record in accumulatedErrorObjects) { context.WriteError(record); } } } Collection<PSObject> accumulatedObjects = context2.GetAccumulatedObjects(); if (flag) { context.Filter = filter; } collection4 = accumulatedObjects; } finally { context2.RemoveStopReferral(); } return collection4; }
} // SetLocation /// <summary> /// Changes the current working directory to the path specified /// </summary> /// /// <param name="path"> /// The path of the new current working directory /// </param> /// /// <param name="context"> /// The context the provider uses when performing the operation. /// </param> /// /// <returns> /// The PathInfo object representing the path of the location /// that was set. /// </returns> /// /// <exception cref="ArgumentNullException"> /// If <paramref name="path"/> is null. /// </exception> /// /// <exception cref="ArgumentException"> /// If <paramref name="path"/> does not exist, is not a container, or /// resolved to multiple containers. /// </exception> /// /// <exception cref="ProviderNotFoundException"> /// If <paramref name="path"/> refers to a provider that does not exist. /// </exception> /// /// <exception cref="DriveNotFoundException"> /// If <paramref name="path"/> refers to a drive that does not exist. /// </exception> /// /// <exception cref="ProviderInvocationException"> /// If the provider associated with <paramref name="path"/> threw an /// exception. /// </exception> /// /// <exception cref="ItemNotFoundException"> /// If the <paramref name="path"/> could not be resolved. /// </exception> /// internal PathInfo SetLocation(string path, CmdletProviderContext context) { if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } string originalPath = path; string driveName = null; ProviderInfo provider = null; string providerId = null; PSDriveInfo previousWorkingDrive = CurrentDrive; // First check to see if the path is a home path if (LocationGlobber.IsHomePath(path)) { path = Globber.GetHomeRelativePath(path); } if (LocationGlobber.IsProviderDirectPath(path)) { // The path is a provider-direct path so use the current // provider and its hidden drive but don't modify the path // at all. provider = CurrentLocation.Provider; CurrentDrive = provider.HiddenDrive; } else if (LocationGlobber.IsProviderQualifiedPath(path, out providerId)) { provider = GetSingleProvider(providerId); CurrentDrive = provider.HiddenDrive; } else { // See if the path is a relative or absolute // path. if (Globber.IsAbsolutePath(path, out driveName)) { // Since the path is an absolute path // we need to change the current working // drive PSDriveInfo newWorkingDrive = GetDrive(driveName); CurrentDrive = newWorkingDrive; // Now that the current working drive is set, // process the rest of the path as a relative path. } } if (context == null) { context = new CmdletProviderContext(this.ExecutionContext); } if (CurrentDrive != null) { context.Drive = CurrentDrive; } CmdletProvider providerInstance = null; Collection <PathInfo> workingPath = null; try { workingPath = Globber.GetGlobbedMonadPathsFromMonadPath( path, false, context, out providerInstance); } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception) // Catch-all OK, 3rd party callout { // Reset the drive to the previous drive and // then rethrow the error CurrentDrive = previousWorkingDrive; throw; } if (workingPath.Count == 0) { // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; throw new ItemNotFoundException( path, "PathNotFound", SessionStateStrings.PathNotFound); } // We allow globbing the location as long as it only resolves a single container. bool foundContainer = false; bool pathIsContainer = false; bool pathIsProviderQualifiedPath = false; bool currentPathisProviderQualifiedPath = false; for (int index = 0; index < workingPath.Count; ++index) { CmdletProviderContext normalizePathContext = new CmdletProviderContext(context); PathInfo resolvedPath = workingPath[index]; string currentPath = path; try { string providerName = null; currentPathisProviderQualifiedPath = LocationGlobber.IsProviderQualifiedPath(resolvedPath.Path, out providerName); if (currentPathisProviderQualifiedPath) { // The path should be the provider-qualified path without the provider ID // or :: string providerInternalPath = LocationGlobber.RemoveProviderQualifier(resolvedPath.Path); try { currentPath = NormalizeRelativePath(GetSingleProvider(providerName), providerInternalPath, String.Empty, normalizePathContext); } catch (NotSupportedException) { // Since the provider does not support normalizing the path, just // use the path we currently have. } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception) // Catch-all OK, 3rd party callout { // Reset the drive to the previous drive and // then rethrow the error CurrentDrive = previousWorkingDrive; throw; } } else { try { currentPath = NormalizeRelativePath(resolvedPath.Path, CurrentDrive.Root, normalizePathContext); } catch (NotSupportedException) { // Since the provider does not support normalizing the path, just // use the path we currently have. } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception) // Catch-all OK, 3rd party callout { // Reset the drive to the previous drive and // then rethrow the error CurrentDrive = previousWorkingDrive; throw; } } // Now see if there was errors while normalizing the path if (normalizePathContext.HasErrors()) { // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; normalizePathContext.ThrowFirstErrorOrDoNothing(); } } finally { normalizePathContext.RemoveStopReferral(); } // Check to see if the path is a container bool isContainer = false; CmdletProviderContext itemContainerContext = new CmdletProviderContext(context); itemContainerContext.SuppressWildcardExpansion = true; try { isContainer = IsItemContainer( resolvedPath.Path, itemContainerContext); if (itemContainerContext.HasErrors()) { // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; itemContainerContext.ThrowFirstErrorOrDoNothing(); } } catch (NotSupportedException) { if (currentPath.Length == 0) { // Treat this as a container because providers that only // support the ContainerCmdletProvider interface are really // containers at their root. isContainer = true; } } finally { itemContainerContext.RemoveStopReferral(); } if (isContainer) { if (foundContainer) { // The path resolved to more than one container // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; throw PSTraceSource.NewArgumentException( "path", SessionStateStrings.PathResolvedToMultiple, originalPath); } else { // Set the path to use path = currentPath; // Mark it as a container pathIsContainer = true; // Mark whether or not it was provider-qualified pathIsProviderQualifiedPath = currentPathisProviderQualifiedPath; // Mark that we have already found one container. Finding additional // should be an error foundContainer = true; } } } if (pathIsContainer) { // Remove the root slash since it is implied that the // current working directory is relative to the root. if (!LocationGlobber.IsProviderDirectPath(path) && path.StartsWith(StringLiterals.DefaultPathSeparatorString, StringComparison.CurrentCulture) && !pathIsProviderQualifiedPath) { path = path.Substring(1); } s_tracer.WriteLine( "New working path = {0}", path); CurrentDrive.CurrentLocation = path; } else { // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; throw new ItemNotFoundException( originalPath, "PathNotFound", SessionStateStrings.PathNotFound); } // Now make sure the current drive is set in the provider's // current working drive hashtable ProvidersCurrentWorkingDrive[CurrentDrive.Provider] = CurrentDrive; // Set the $PWD variable to the new location this.SetVariable(SpecialVariables.PWDVarPath, this.CurrentLocation, false, true, CommandOrigin.Internal); return(this.CurrentLocation); } // SetLocation
} // SetLocation /// <summary> /// Determines if the specified path is the current working directory /// or a parent of the current working directory. /// </summary> /// /// <param name="path"> /// A monad namespace absolute or relative path. /// </param> /// /// <param name="context"> /// The context the provider uses when performing the operation. /// </param> /// /// <returns> /// true, if the path is the current working directory or a parent of the current /// working directory. false, otherwise. /// </returns> /// /// <exception cref="ArgumentNullException"> /// If <paramref name="path"/> is null. /// </exception> /// /// <exception cref="ProviderNotFoundException"> /// If the path is a provider-qualified path for a provider that is /// not loaded into the system. /// </exception> /// /// <exception cref="DriveNotFoundException"> /// If the <paramref name="path"/> refers to a drive that could not be found. /// </exception> /// /// <exception cref="ProviderInvocationException"> /// If the provider used to build the path threw an exception. /// </exception> /// /// <exception cref="NotSupportedException"> /// If the provider that the <paramref name="path"/> represents is not a NavigationCmdletProvider /// or ContainerCmdletProvider. /// </exception> /// /// <exception cref="InvalidOperationException"> /// If the <paramref name="path"/> starts with "~" and the home location is not set for /// the provider. /// </exception> /// /// <exception cref="ProviderInvocationException"> /// If the provider specified by <paramref name="providerId"/> threw an /// exception when its GetParentPath or MakePath was called while /// processing the <paramref name="path"/>. /// </exception> /// internal bool IsCurrentLocationOrAncestor(string path, CmdletProviderContext context) { bool result = false; if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } PSDriveInfo drive = null; ProviderInfo provider = null; string providerSpecificPath = Globber.GetProviderPath( path, context, out provider, out drive); if (drive != null) { s_tracer.WriteLine("Tracing drive"); drive.Trace(); } Dbg.Diagnostics.Assert( providerSpecificPath != null, "There should always be a way to generate a provider path for a " + "given path"); if (drive != null) { context.Drive = drive; } // Check to see if the path that was specified is within the current // working drive if (drive == CurrentDrive) { // The path needs to be normalized to get rid of relative path tokens // so they don't interfere with our path comparisons below CmdletProviderContext normalizePathContext = new CmdletProviderContext(context); try { providerSpecificPath = NormalizeRelativePath(path, null, normalizePathContext); } catch (NotSupportedException) { // Since the provider does not support normalizing the path, just // use the path we currently have. } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } finally { normalizePathContext.RemoveStopReferral(); } if (normalizePathContext.HasErrors()) { normalizePathContext.ThrowFirstErrorOrDoNothing(); } s_tracer.WriteLine("Provider path = {0}", providerSpecificPath); // Get the current working directory provider specific path PSDriveInfo currentWorkingDrive = null; ProviderInfo currentDriveProvider = null; string currentWorkingPath = Globber.GetProviderPath( ".", context, out currentDriveProvider, out currentWorkingDrive); Dbg.Diagnostics.Assert( currentWorkingDrive == CurrentDrive, "The current working drive should be the CurrentDrive."); s_tracer.WriteLine( "Current working path = {0}", currentWorkingPath); // See if the path is the current working directory or a parent // of the current working directory s_tracer.WriteLine( "Comparing {0} to {1}", providerSpecificPath, currentWorkingPath); if (String.Compare(providerSpecificPath, currentWorkingPath, StringComparison.CurrentCultureIgnoreCase) == 0) { // The path is the current working directory so // return true s_tracer.WriteLine("The path is the current working directory"); result = true; } else { // Check to see if the specified path is a parent // of the current working directory string lockedDirectory = currentWorkingPath; while (lockedDirectory.Length > 0) { // We need to allow the provider to go as far up the tree // as it can even if that means it has to traverse higher // than the mount point for this drive. That is // why we are passing the empty string as the root here. lockedDirectory = GetParentPath( drive.Provider, lockedDirectory, String.Empty, context); s_tracer.WriteLine( "Comparing {0} to {1}", lockedDirectory, providerSpecificPath); if (String.Compare(lockedDirectory, providerSpecificPath, StringComparison.CurrentCultureIgnoreCase) == 0) { // The path is a parent of the current working // directory s_tracer.WriteLine( "The path is a parent of the current working directory: {0}", lockedDirectory); result = true; break; } } } } else { s_tracer.WriteLine("Drives are not the same"); } return result; } // IsCurrentLocationOrAncestor
} // GenerateNewPathsWithGlobLeaf /// <summary> /// Gets the child names in the specified path by using the provider /// </summary> /// /// <param name="dir"> /// The path of the directory to get the child names from. If this is an Msh Path, /// dirIsProviderPath must be false, If this is a provider-internal path, /// dirIsProviderPath must be true. /// </param> /// /// <param name="leafElement"> /// The element that we are ultimately looking for. Used to set filters on the context /// if desired. /// </param> /// /// <param name="getAllContainers"> /// Determines if the GetChildNames call should get all containers even if they don't /// match the filter. /// </param> /// /// <param name="context"> /// The context to be used for the command. The context is copied to a new context, the /// results are accumulated and then returned. /// </param> /// /// <param name="dirIsProviderPath"> /// Specifies whether the dir parameter is a provider-internal path (true) or Msh Path (false). /// </param> /// /// <param name="drive"> /// The drive to use to qualify the Msh path if dirIsProviderPath is false. /// </param> /// /// <param name="provider"> /// The provider to use to get the child names. /// </param> /// /// <param name="modifiedDirPath"> /// Returns the modified dir path. If dirIsProviderPath is true, this is the unescaped dir path. /// If dirIsProviderPath is false, this is the unescaped resolved provider path. /// </param> /// /// <returns> /// A collection of PSObjects whose BaseObject is a string that contains the name of the child. /// </returns> /// /// <exception cref="ArgumentNullException"> /// If <paramref name="dir"/> or <paramref name="drive"/> is null. /// </exception> /// /// <exception cref="ProviderNotFoundException"> /// If the path is a provider-qualified path for a provider that is /// not loaded into the system. /// </exception> /// /// <exception cref="DriveNotFoundException"> /// If the <paramref name="path"/> refers to a drive that could not be found. /// </exception> /// /// <exception cref="ProviderInvocationException"> /// If the provider used to build the path threw an exception. /// </exception> /// /// <exception cref="NotSupportedException"> /// If the provider that the <paramref name="path"/> represents is not a NavigationCmdletProvider /// or ContainerCmdletProvider. /// </exception> /// /// <exception cref="InvalidOperationException"> /// If the <paramref name="path"/> starts with "~" and the home location is not set for /// the provider. /// </exception> /// /// <exception cref="ProviderInvocationException"> /// If the provider associated with the <paramref name="path"/> threw an /// exception when its GetParentPath or MakePath was called while /// processing the <paramref name="path"/>. /// </exception> /// /// <exception cref="PipelineStoppedException"> /// If <paramref name="context"/> has been signaled for /// StopProcessing. /// </exception> /// /// <exception> /// Any exception can be thrown by the provider that is called to build /// the provider path. /// </exception> /// private Collection<PSObject> GetChildNamesInDir( string dir, string leafElement, bool getAllContainers, CmdletProviderContext context, bool dirIsProviderPath, PSDriveInfo drive, ContainerCmdletProvider provider, out string modifiedDirPath) { // See if the provider wants to convert the path and filter string convertedPath = null; string convertedFilter = null; string originalFilter = context.Filter; bool changedPathOrFilter = provider.ConvertPath(leafElement, context.Filter, ref convertedPath, ref convertedFilter, context); if (changedPathOrFilter) { if (s_tracer.IsEnabled) { s_tracer.WriteLine("Provider converted path and filter."); s_tracer.WriteLine("Original path: {0}", leafElement); s_tracer.WriteLine("Converted path: {0}", convertedPath); s_tracer.WriteLine("Original filter: {0}", context.Filter); s_tracer.WriteLine("Converted filter: {0}", convertedFilter); } leafElement = convertedPath; context.Filter = convertedFilter; } ReturnContainers returnContainers = ReturnContainers.ReturnAllContainers; if (!getAllContainers) { returnContainers = ReturnContainers.ReturnMatchingContainers; } CmdletProviderContext getChildNamesContext = new CmdletProviderContext(context); // Remove the include/exclude filters from the new context getChildNamesContext.SetFilters( new Collection<string>(), new Collection<string>(), context.Filter); try { // Use the provider to get the children string unescapedDir = null; modifiedDirPath = null; if (dirIsProviderPath) { modifiedDirPath = unescapedDir = context.SuppressWildcardExpansion ? dir : RemoveGlobEscaping(dir); } else { Dbg.Diagnostics.Assert( drive != null, "Caller should verify that drive is not null when dirIsProviderPath is false"); // If the directory is an MSH path we must resolve it before calling GetChildNames() // -- If the path is passed in by LiteralPath (context.SuppressWildcardExpansion == false), we surely should use 'dir' unchanged. // -- If the path is passed in by Path (context.SuppressWildcardExpansion == true), we still should use 'dir' unchanged, in case that the special character // in 'dir' is escaped modifiedDirPath = GetMshQualifiedPath(dir, drive); ProviderInfo providerIgnored = null; CmdletProvider providerInstanceIgnored = null; Collection<string> resolvedPaths = GetGlobbedProviderPathsFromMonadPath( modifiedDirPath, false, getChildNamesContext, out providerIgnored, out providerInstanceIgnored); // After resolving the path, we unescape the modifiedDirPath if necessary. modifiedDirPath = context.SuppressWildcardExpansion ? modifiedDirPath : RemoveGlobEscaping(modifiedDirPath); if (resolvedPaths.Count > 0) { unescapedDir = resolvedPaths[0]; } else { // If there were no results from globbing but no // exception was thrown, that means there was filtering. // So return an empty collection and let the caller deal // with it. if (changedPathOrFilter) { context.Filter = originalFilter; } return new Collection<PSObject>(); } } if (provider.HasChildItems(unescapedDir, getChildNamesContext)) { provider.GetChildNames( unescapedDir, returnContainers, getChildNamesContext); } // First check to see if there were any errors, and write them // to the real context if there are. if (getChildNamesContext.HasErrors()) { Collection<ErrorRecord> errors = getChildNamesContext.GetAccumulatedErrorObjects(); if (errors != null && errors.Count > 0) { foreach (ErrorRecord errorRecord in errors) { context.WriteError(errorRecord); } } } Collection<PSObject> childNamesObjectArray = getChildNamesContext.GetAccumulatedObjects(); if (changedPathOrFilter) { context.Filter = originalFilter; } return childNamesObjectArray; } finally { getChildNamesContext.RemoveStopReferral(); } } // GetChildNamesInDir
internal PathInfo SetLocation (string path, CmdletProviderContext context) { if (string.IsNullOrEmpty (path) && OSHelper.IsUnix) path = "/"; else if (path == null) { throw PSTraceSource.NewArgumentNullException ("path"); } string str = path; string driveName = null; ProviderInfo provider = null; string providerId = null; PSDriveInfo currentDrive = this.CurrentDrive; if (LocationGlobber.IsHomePath (path)) { path = this.Globber.GetHomeRelativePath (path); } if (LocationGlobber.IsProviderDirectPath (path)) { provider = this.CurrentLocation.Provider; PSDriveInfo drive = null; if (PathIntrinsics.FinDriveFromPath (path, provider, out drive)) { this.CurrentDrive = drive; } else if (LocationGlobber.IsProviderQualifiedPath (path, out providerId)) { provider = this.GetSingleProvider (providerId); if (PathIntrinsics.FinDriveFromPath (path, provider, out drive)) { this.CurrentDrive = drive; } else if (this.Globber.IsAbsolutePath(path, out driveName)) { drive = this.GetDrive(driveName); this.CurrentDrive = drive; } } } else if (LocationGlobber.IsProviderQualifiedPath (path, out providerId)) { provider = this.GetSingleProvider (providerId); PSDriveInfo drive = null; if (PathIntrinsics.FinDriveFromPath (path, provider, out drive)) { this.CurrentDrive = drive; } else if (this.Globber.IsAbsolutePath(path, out driveName)) { drive = this.GetDrive(driveName); this.CurrentDrive = drive; } } else if (this.Globber.IsAbsolutePath(path, out driveName)) { PSDriveInfo drive = this.GetDrive(driveName); this.CurrentDrive = drive; } if (context == null) { context = new CmdletProviderContext(this.ExecutionContext); } if (this.CurrentDrive != null) { context.Drive = this.CurrentDrive; } CmdletProvider providerInstance = null; Collection<PathInfo> collection = null; try { collection = this.Globber.GetGlobbedMonadPathsFromMonadPath(path, false, context, out providerInstance); } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception exception) { CommandProcessorBase.CheckForSevereException(exception); this.CurrentDrive = currentDrive; throw; } if (collection.Count == 0) { this.CurrentDrive = currentDrive; throw new ItemNotFoundException(path, "PathNotFound", SessionStateStrings.PathNotFound); } bool flag = false; bool flag2 = false; bool flag3 = false; bool flag4 = false; for (int i = 0; i < collection.Count; i++) { CmdletProviderContext context2 = new CmdletProviderContext(context); PathInfo info4 = collection[i]; string str4 = path; try { string str5 = null; flag4 = LocationGlobber.IsProviderQualifiedPath(info4.Path, out str5); if (flag4) { string str6 = LocationGlobber.RemoveProviderQualifier(info4.Path); try { str4 = this.NormalizeRelativePath(this.GetSingleProvider(str5), str6, string.Empty, context2); goto Label_01DF; } catch (NotSupportedException) { goto Label_01DF; } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception exception2) { CommandProcessorBase.CheckForSevereException(exception2); this.CurrentDrive = currentDrive; throw; } } try { str4 = this.NormalizeRelativePath(info4.Path, this.CurrentDrive.Root, context2); } catch (NotSupportedException) { } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception exception3) { CommandProcessorBase.CheckForSevereException(exception3); this.CurrentDrive = currentDrive; throw; } Label_01DF: if (context2.HasErrors()) { this.CurrentDrive = currentDrive; context2.ThrowFirstErrorOrDoNothing(); } } finally { context2.RemoveStopReferral(); } bool flag5 = false; CmdletProviderContext context3 = new CmdletProviderContext(context) { SuppressWildcardExpansion = true }; try { flag5 = this.IsItemContainer(info4.Path, context3); if (context3.HasErrors()) { this.CurrentDrive = currentDrive; context3.ThrowFirstErrorOrDoNothing(); } } catch (NotSupportedException) { if (str4.Length == 0) { flag5 = true; } } finally { context3.RemoveStopReferral(); } if (flag5) { if (flag) { this.CurrentDrive = currentDrive; throw PSTraceSource.NewArgumentException("path", "SessionStateStrings", "PathResolvedToMultiple", new object[] { str }); } path = str4; flag2 = true; flag3 = flag4; flag = true; } } if (flag2) { if (!OSHelper.IsUnix) { if (!LocationGlobber.IsProviderDirectPath(path)) { char ch = '\\'; if (path.StartsWith(ch.ToString(), StringComparison.CurrentCulture) && !flag3) { path = path.Substring(1); } } } tracer.WriteLine("New working path = {0}", new object[] { path }); this.CurrentDrive.CurrentLocation = path; } else { this.CurrentDrive = currentDrive; throw new ItemNotFoundException(str, "PathNotFound", SessionStateStrings.PathNotFound); } this.ProvidersCurrentWorkingDrive[this.CurrentDrive.Provider] = this.CurrentDrive; this.SetVariable(SpecialVariables.PWDVarPath, this.CurrentLocation, false, true, CommandOrigin.Internal); return this.CurrentLocation; }
} // SetLocation /// <summary> /// Changes the current working directory to the path specified /// </summary> /// /// <param name="path"> /// The path of the new current working directory /// </param> /// /// <param name="context"> /// The context the provider uses when performing the operation. /// </param> /// /// <returns> /// The PathInfo object representing the path of the location /// that was set. /// </returns> /// /// <exception cref="ArgumentNullException"> /// If <paramref name="path"/> is null. /// </exception> /// /// <exception cref="ArgumentException"> /// If <paramref name="path"/> does not exist, is not a container, or /// resolved to multiple containers. /// </exception> /// /// <exception cref="ProviderNotFoundException"> /// If <paramref name="path"/> refers to a provider that does not exist. /// </exception> /// /// <exception cref="DriveNotFoundException"> /// If <paramref name="path"/> refers to a drive that does not exist. /// </exception> /// /// <exception cref="ProviderInvocationException"> /// If the provider associated with <paramref name="path"/> threw an /// exception. /// </exception> /// /// <exception cref="ItemNotFoundException"> /// If the <paramref name="path"/> could not be resolved. /// </exception> /// internal PathInfo SetLocation(string path, CmdletProviderContext context) { if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } string originalPath = path; string driveName = null; ProviderInfo provider = null; string providerId = null; PSDriveInfo previousWorkingDrive = CurrentDrive; // First check to see if the path is a home path if (LocationGlobber.IsHomePath(path)) { path = Globber.GetHomeRelativePath(path); } if (LocationGlobber.IsProviderDirectPath(path)) { // The path is a provider-direct path so use the current // provider and its hidden drive but don't modify the path // at all. provider = CurrentLocation.Provider; CurrentDrive = provider.HiddenDrive; } else if (LocationGlobber.IsProviderQualifiedPath(path, out providerId)) { provider = GetSingleProvider(providerId); CurrentDrive = provider.HiddenDrive; } else { // See if the path is a relative or absolute // path. if (Globber.IsAbsolutePath(path, out driveName)) { // Since the path is an absolute path // we need to change the current working // drive PSDriveInfo newWorkingDrive = GetDrive(driveName); CurrentDrive = newWorkingDrive; // Now that the current working drive is set, // process the rest of the path as a relative path. } } if (context == null) { context = new CmdletProviderContext(this.ExecutionContext); } if (CurrentDrive != null) { context.Drive = CurrentDrive; } CmdletProvider providerInstance = null; Collection<PathInfo> workingPath = null; try { workingPath = Globber.GetGlobbedMonadPathsFromMonadPath( path, false, context, out providerInstance); } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception e) // Catch-all OK, 3rd party callout { CommandProcessorBase.CheckForSevereException(e); // Reset the drive to the previous drive and // then rethrow the error CurrentDrive = previousWorkingDrive; throw; } if (workingPath.Count == 0) { // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; throw new ItemNotFoundException( path, "PathNotFound", SessionStateStrings.PathNotFound); } // We allow globbing the location as long as it only resolves a single container. bool foundContainer = false; bool pathIsContainer = false; bool pathIsProviderQualifiedPath = false; bool currentPathisProviderQualifiedPath = false; for (int index = 0; index < workingPath.Count; ++index) { CmdletProviderContext normalizePathContext = new CmdletProviderContext(context); PathInfo resolvedPath = workingPath[index]; string currentPath = path; try { string providerName = null; currentPathisProviderQualifiedPath = LocationGlobber.IsProviderQualifiedPath(resolvedPath.Path, out providerName); if (currentPathisProviderQualifiedPath) { // The path should be the provider-qualified path without the provider ID // or :: string providerInternalPath = LocationGlobber.RemoveProviderQualifier(resolvedPath.Path); try { currentPath = NormalizeRelativePath(GetSingleProvider(providerName), providerInternalPath, String.Empty, normalizePathContext); } catch (NotSupportedException) { // Since the provider does not support normalizing the path, just // use the path we currently have. } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception e) // Catch-all OK, 3rd party callout { CommandProcessorBase.CheckForSevereException(e); // Reset the drive to the previous drive and // then rethrow the error CurrentDrive = previousWorkingDrive; throw; } } else { try { currentPath = NormalizeRelativePath(resolvedPath.Path, CurrentDrive.Root, normalizePathContext); } catch (NotSupportedException) { // Since the provider does not support normalizing the path, just // use the path we currently have. } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception e) // Catch-all OK, 3rd party callout { CommandProcessorBase.CheckForSevereException(e); // Reset the drive to the previous drive and // then rethrow the error CurrentDrive = previousWorkingDrive; throw; } } // Now see if there was errors while normalizing the path if (normalizePathContext.HasErrors()) { // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; normalizePathContext.ThrowFirstErrorOrDoNothing(); } } finally { normalizePathContext.RemoveStopReferral(); } // Check to see if the path is a container bool isContainer = false; CmdletProviderContext itemContainerContext = new CmdletProviderContext(context); itemContainerContext.SuppressWildcardExpansion = true; try { isContainer = IsItemContainer( resolvedPath.Path, itemContainerContext); if (itemContainerContext.HasErrors()) { // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; itemContainerContext.ThrowFirstErrorOrDoNothing(); } } catch (NotSupportedException) { if (currentPath.Length == 0) { // Treat this as a container because providers that only // support the ContainerCmdletProvider interface are really // containers at their root. isContainer = true; } } finally { itemContainerContext.RemoveStopReferral(); } if (isContainer) { if (foundContainer) { // The path resolved to more than one container // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; throw PSTraceSource.NewArgumentException( "path", SessionStateStrings.PathResolvedToMultiple, originalPath); } else { // Set the path to use path = currentPath; // Mark it as a container pathIsContainer = true; // Mark whether or not it was provider-qualified pathIsProviderQualifiedPath = currentPathisProviderQualifiedPath; // Mark that we have already found one container. Finding additional // should be an error foundContainer = true; } } } if (pathIsContainer) { // Remove the root slash since it is implied that the // current working directory is relative to the root. if (!LocationGlobber.IsProviderDirectPath(path) && path.StartsWith(StringLiterals.DefaultPathSeparatorString, StringComparison.CurrentCulture) && !pathIsProviderQualifiedPath) { path = path.Substring(1); } s_tracer.WriteLine( "New working path = {0}", path); CurrentDrive.CurrentLocation = path; } else { // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; throw new ItemNotFoundException( originalPath, "PathNotFound", SessionStateStrings.PathNotFound); } // Now make sure the current drive is set in the provider's // current working drive hashtable ProvidersCurrentWorkingDrive[CurrentDrive.Provider] = CurrentDrive; // Set the $PWD variable to the new location this.SetVariable(SpecialVariables.PWDVarPath, this.CurrentLocation, false, true, CommandOrigin.Internal); return this.CurrentLocation; } // SetLocation
internal bool IsCurrentLocationOrAncestor(string path, CmdletProviderContext context) { bool flag = false; if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } PSDriveInfo drive = null; ProviderInfo provider = null; string strA = this.Globber.GetProviderPath(path, context, out provider, out drive); if (drive != null) { tracer.WriteLine("Tracing drive", new object[0]); drive.Trace(); } if (drive != null) { context.Drive = drive; } if (drive == this.CurrentDrive) { CmdletProviderContext context2 = new CmdletProviderContext(context); try { strA = this.NormalizeRelativePath(path, null, context2); } catch (NotSupportedException) { } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } finally { context2.RemoveStopReferral(); } if (context2.HasErrors()) { context2.ThrowFirstErrorOrDoNothing(); } tracer.WriteLine("Provider path = {0}", new object[] { strA }); PSDriveInfo info3 = null; ProviderInfo info4 = null; string strB = this.Globber.GetProviderPath(".", context, out info4, out info3); tracer.WriteLine("Current working path = {0}", new object[] { strB }); tracer.WriteLine("Comparing {0} to {1}", new object[] { strA, strB }); if (string.Compare(strA, strB, true, Thread.CurrentThread.CurrentCulture) == 0) { tracer.WriteLine("The path is the current working directory", new object[0]); flag = true; } else { string str3 = strB; while (str3.Length > 0) { str3 = this.GetParentPath(drive.Provider, str3, string.Empty, context); tracer.WriteLine("Comparing {0} to {1}", new object[] { str3, strA }); if (string.Compare(str3, strA, true, Thread.CurrentThread.CurrentCulture) == 0) { tracer.WriteLine("The path is a parent of the current working directory: {0}", new object[] { str3 }); flag = true; break; } } } } else { tracer.WriteLine("Drives are not the same", new object[0]); } tracer.WriteLine("result = {0}", new object[] { flag }); return flag; }
} // GetChildNames /// <summary> /// Gets the child names of the item at the specified path by /// manually recursing through all the containers instead of /// allowing the provider to do the recursion. /// </summary> /// /// <param name="providerInstance"> /// The provider instance to use. /// </param> /// /// <param name="providerPath"> /// The path to the item if it was specified on the command line. /// </param> /// /// <param name="relativePath"> /// The path the name is relative to. /// </param> /// /// <param name="recurse"> /// If true all names in the subtree should be returned. /// </param> /// /// <param name="depth"> /// Current depth of recursion; special case uint.MaxValue performs full recursion. /// </param> /// /// <param name="returnContainers"> /// Determines if all containers should be returned or only those containers that match the /// filter(s). /// </param> /// /// <param name="includeMatcher"> /// A set of filters that the names must match to be returned. /// </param> /// /// <param name="excludeMatcher"> /// A set of filters that the names cannot match to be returned. /// </param> /// /// <param name="context"> /// The context which the core command is running. /// </param> /// /// <exception cref="NotSupportedException"> /// If the <paramref name="providerInstance"/> does not support this operation. /// </exception> /// /// <exception cref="PipelineStoppedException"> /// If the pipeline is being stopped while executing the command. /// </exception> /// /// <exception cref="ProviderInvocationException"> /// If the provider threw an exception. /// </exception> /// private void DoGetChildNamesManually( CmdletProvider providerInstance, string providerPath, string relativePath, ReturnContainers returnContainers, Collection<WildcardPattern> includeMatcher, Collection<WildcardPattern> excludeMatcher, CmdletProviderContext context, bool recurse, uint depth) { Dbg.Diagnostics.Assert( providerInstance != null, "The providerInstance should have been verified by the caller"); Dbg.Diagnostics.Assert( providerPath != null, "The paths should have been verified by the caller"); Dbg.Diagnostics.Assert( context != null, "The context should have been verified by the caller"); string newProviderPath = MakePath( providerInstance, providerPath, relativePath, context); CmdletProviderContext childNamesContext = new CmdletProviderContext(context); try { // First get all children that match the filters and write them out GetChildNames( providerInstance, newProviderPath, ReturnContainers.ReturnMatchingContainers, childNamesContext); Collection<PSObject> results = childNamesContext.GetAccumulatedObjects(); foreach (PSObject result in results) { // Making sure to obey the StopProcessing. if (context.Stopping) { return; } string name = result.BaseObject as string; if (name == null) { continue; } bool isIncludeMatch = SessionStateUtilities.MatchesAnyWildcardPattern( name, includeMatcher, true); if (isIncludeMatch) { if (!SessionStateUtilities.MatchesAnyWildcardPattern( name, excludeMatcher, false)) { string resultPath = MakePath(providerInstance, relativePath, name, context); context.WriteObject(resultPath); } } } if (recurse) { // Now get all the children that are containers and recurse into them // Limiter for recursion if (depth > 0) // this includes special case 'depth == uint.MaxValue' for unlimited recursion { GetChildNames( providerInstance, newProviderPath, ReturnContainers.ReturnAllContainers, childNamesContext); results = childNamesContext.GetAccumulatedObjects(); foreach (PSObject result in results) { // Making sure to obey the StopProcessing. if (context.Stopping) { return; } string name = result.BaseObject as string; if (name == null) { continue; } // Generate the relative path from the provider path string resultRelativePath = MakePath( providerInstance, relativePath, name, context); // Generate the provider path for the child item to see // if it is a container string resultProviderPath = MakePath( providerInstance, providerPath, resultRelativePath, context); // If the item is a container recurse into it and output its // child names if (IsItemContainer(providerInstance, resultProviderPath, context)) { DoGetChildNamesManually( providerInstance, providerPath, resultRelativePath, returnContainers, includeMatcher, excludeMatcher, context, true, depth - 1); } } // foreach } // if } // recurse } finally { childNamesContext.RemoveStopReferral(); } } // DoGetChildNamesRecurseManually
private void DoManualGetChildItems(CmdletProvider providerInstance, string path, bool recurse, CmdletProviderContext context, bool skipIsItemContainerCheck = false) { Collection<WildcardPattern> patterns = SessionStateUtilities.CreateWildcardsFromStrings(context.Include, WildcardOptions.IgnoreCase); Collection<WildcardPattern> collection2 = SessionStateUtilities.CreateWildcardsFromStrings(context.Exclude, WildcardOptions.IgnoreCase); if (skipIsItemContainerCheck || this.IsItemContainer(providerInstance, path, context)) { CmdletProviderContext context2 = new CmdletProviderContext(context); Collection<PSObject> accumulatedObjects = null; Dictionary<string, bool> dictionary = null; try { this.GetChildNames(providerInstance, path, recurse ? ReturnContainers.ReturnAllContainers : ReturnContainers.ReturnMatchingContainers, context2); context2.WriteErrorsToContext(context); accumulatedObjects = context2.GetAccumulatedObjects(); if (recurse && providerInstance.IsFilterSet()) { context2.RemoveStopReferral(); context2 = new CmdletProviderContext(context); Collection<PSObject> collection4 = new Collection<PSObject>(); dictionary = new Dictionary<string, bool>(); this.GetChildNames(providerInstance, path, ReturnContainers.ReturnMatchingContainers, context2); foreach (PSObject obj2 in context2.GetAccumulatedObjects()) { string baseObject = obj2.BaseObject as string; if (baseObject != null) { dictionary[baseObject] = true; } } } } finally { context2.RemoveStopReferral(); } for (int i = 0; i < accumulatedObjects.Count; i++) { if (context.Stopping) { return; } string child = accumulatedObjects[i].BaseObject as string; if (child != null) { string str3 = this.MakePath(providerInstance, path, child, context); if (str3 != null) { if (SessionStateUtilities.MatchesAnyWildcardPattern(child, patterns, true) && !SessionStateUtilities.MatchesAnyWildcardPattern(child, collection2, false)) { bool flag2 = true; if (dictionary != null) { bool flag3 = false; flag2 = dictionary.TryGetValue(child, out flag3); } if (flag2) { this.GetItemPrivate(providerInstance, str3, context); } } if (this.IsItemContainer(providerInstance, str3, context) && recurse) { if (context.Stopping) { return; } this.DoManualGetChildItems(providerInstance, str3, recurse, context, true); } } } } } else { string text = path; text = this.GetChildName(providerInstance, path, context, true); if (SessionStateUtilities.MatchesAnyWildcardPattern(text, patterns, true) && !SessionStateUtilities.MatchesAnyWildcardPattern(text, collection2, false)) { this.GetItemPrivate(providerInstance, path, context); } } }
internal string GetParentPath(string path, string root, CmdletProviderContext context, bool useDefaultProvider) { string str4; if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } CmdletProviderContext context2 = new CmdletProviderContext(context); try { PSDriveInfo drive = null; ProviderInfo provider = null; try { this.Globber.GetProviderPath(path, context2, out provider, out drive); } catch (System.Management.Automation.DriveNotFoundException) { if (!useDefaultProvider) { throw; } provider = this.PublicSessionState.Internal.GetSingleProvider("FileSystem"); } if (context2.HasErrors()) { context2.WriteErrorsToContext(context); return null; } if (drive != null) { context.Drive = drive; } bool isProviderQualified = false; bool isDriveQualified = false; string qualifier = null; string str2 = this.RemoveQualifier(path, out qualifier, out isProviderQualified, out isDriveQualified); string str3 = this.GetParentPath(provider, str2, root, context); if (!string.IsNullOrEmpty(qualifier) && !string.IsNullOrEmpty(str3)) { str3 = this.AddQualifier(str3, qualifier, isProviderQualified, isDriveQualified); } tracer.WriteLine("result = {0}", new object[] { str3 }); str4 = str3; } finally { context2.RemoveStopReferral(); } return str4; }
private void DoGetChildNamesManually(CmdletProvider providerInstance, string providerPath, string relativePath, ReturnContainers returnContainers, Collection<WildcardPattern> includeMatcher, Collection<WildcardPattern> excludeMatcher, CmdletProviderContext context, bool recurse) { string path = this.MakePath(providerInstance, providerPath, relativePath, context); CmdletProviderContext context2 = new CmdletProviderContext(context); try { this.GetChildNames(providerInstance, path, ReturnContainers.ReturnMatchingContainers, context2); foreach (PSObject obj2 in context2.GetAccumulatedObjects()) { if (context.Stopping) { return; } string baseObject = obj2.BaseObject as string; if (((baseObject != null) && SessionStateUtilities.MatchesAnyWildcardPattern(baseObject, includeMatcher, true)) && !SessionStateUtilities.MatchesAnyWildcardPattern(baseObject, excludeMatcher, false)) { string str3 = this.MakePath(providerInstance, relativePath, baseObject, context); context.WriteObject(str3); } } if (recurse) { this.GetChildNames(providerInstance, path, ReturnContainers.ReturnAllContainers, context2); foreach (PSObject obj3 in context2.GetAccumulatedObjects()) { if (context.Stopping) { return; } string child = obj3.BaseObject as string; if (child != null) { string str5 = this.MakePath(providerInstance, relativePath, child, context); string str6 = this.MakePath(providerInstance, providerPath, str5, context); if (this.IsItemContainer(providerInstance, str6, context)) { this.DoGetChildNamesManually(providerInstance, providerPath, str5, returnContainers, includeMatcher, excludeMatcher, context, true); } } } } } finally { context2.RemoveStopReferral(); } }
} //NormalizeRelativePath /// <summary> /// Normalizes the path that was passed in and returns the normalized path /// as a relative path to the basePath that was passed. /// </summary> /// /// <param name="path"> /// An MSH path to an item. The item should exist /// or the provider should write out an error. /// </param> /// /// <param name="basePath"> /// The path that the return value should be relative to. /// </param> /// /// <param name="context"> /// The context under which the command is running. /// </param> /// /// <returns> /// A normalized path that is relative to the basePath that was passed. /// </returns> /// /// <exception cref="ArgumentNullException"> /// If <paramref name="path"/> is null. /// </exception> /// /// <exception cref="NotSupportedException"> /// If the <paramref name="providerInstance"/> does not support this operation. /// </exception> /// /// <exception cref="PipelineStoppedException"> /// If the pipeline is being stopped while executing the command. /// </exception> /// /// <exception cref="ProviderInvocationException"> /// If the provider threw an exception. /// </exception> /// internal string NormalizeRelativePath( string path, string basePath, CmdletProviderContext context) { if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } CmdletProviderContext getProviderPathContext = new CmdletProviderContext(context); try { PSDriveInfo drive = null; ProviderInfo provider = null; string workingPath = Globber.GetProviderPath( path, getProviderPathContext, out provider, out drive); if (getProviderPathContext.HasErrors()) { getProviderPathContext.WriteErrorsToContext(context); return null; } if (workingPath == null || provider == null) { // Since the provider didn't write an error, and we didn't get any // results ourselves, we need to write out our own error. Exception e = PSTraceSource.NewArgumentException("path"); context.WriteError(new ErrorRecord(e, "NormalizePathNullResult", ErrorCategory.InvalidArgument, path)); return null; } if (basePath != null) { PSDriveInfo baseDrive = null; ProviderInfo baseProvider = null; Globber.GetProviderPath( basePath, getProviderPathContext, out baseProvider, out baseDrive); if (drive != null && baseDrive != null) { if (!drive.Name.Equals(baseDrive.Name, StringComparison.OrdinalIgnoreCase)) { // Make sure they are from physically different drives // Doing StartsWith from both directions covers the following cases // C:\ and C:\Temp // C:\Temp and C:\ if (!(drive.Root.StartsWith(baseDrive.Root, StringComparison.OrdinalIgnoreCase) || (baseDrive.Root.StartsWith(drive.Root, StringComparison.OrdinalIgnoreCase)))) { // In this case, no normalization is necessary return path; } } } } if (drive != null) { context.Drive = drive; // Detect if the original path was already a // provider path. This happens when a drive doesn't // have a rooted root -- such as HKEY_LOCAL_MACHINE instead of // \\HKEY_LOCAL_MACHINE if ( (GetProviderInstance(provider) is NavigationCmdletProvider) && (!String.IsNullOrEmpty(drive.Root)) && (path.StartsWith(drive.Root, StringComparison.OrdinalIgnoreCase))) { // // If the drive root doesn't end with a path separator then there is a chance the // path starts with the drive root name but doesn't actually refer to it. For example, // (see Win8 bug 922001) consider drive with root HKEY_LOCAL_MACHINE named // HKEY_LOCAL_MACHINE_foo. The path would start with the drive root but is not a provider // path. // // We will remediate this by only considering this a provider path if // 1. The drive root ends with a path separator. // OR // 2. The path starts with the drive root followed by a path separator // OR // 3. The path exactly matches the drive root. // // 1. Test for the drive root ending with a path separator. bool driveRootEndsWithPathSeparator = IsPathSeparator(drive.Root[drive.Root.Length - 1]); // 2. Test for the path starting with the drive root followed by a path separator int indexAfterDriveRoot = drive.Root.Length; bool pathStartsWithDriveRootAndPathSeparator = indexAfterDriveRoot < path.Length && IsPathSeparator(path[indexAfterDriveRoot]); // 3. Test for the drive root exactly matching the path. // Since we know the path starts with the drive root then they are equal if the lengths are equal. bool pathEqualsDriveRoot = drive.Root.Length == path.Length; if (driveRootEndsWithPathSeparator || pathStartsWithDriveRootAndPathSeparator || pathEqualsDriveRoot) { workingPath = path; } } } return NormalizeRelativePath(provider, workingPath, basePath, context); } finally { getProviderPathContext.RemoveStopReferral(); } } // NormalizeRelativePath
/// <summary> /// Gets the path to the parent object for the given object. /// Allow to use FileSystem as the default provider when the /// given path is drive-qualified and the drive cannot be found. /// </summary> /// /// <param name="path"> /// The path to the object to get the parent path from /// </param> /// /// <param name="root"> /// The root of the drive. Namespace providers should /// return the root if GetParentPath is called for the root. /// </param> /// /// <param name="context"> /// The context which the core command is running. /// </param> /// /// <param name="useDefaultProvider"> /// Specify whether to use default provider when needed. /// </param> /// /// <returns> /// The path to the parent object /// </returns> internal string GetParentPath( string path, string root, CmdletProviderContext context, bool useDefaultProvider) { if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } CmdletProviderContext getProviderPathContext = new CmdletProviderContext(context); try { PSDriveInfo drive = null; ProviderInfo provider = null; try { Globber.GetProviderPath( path, getProviderPathContext, out provider, out drive); } catch (DriveNotFoundException) { // the path is sure to be drive_qualified and it is absolute path, otherwise the // drive would be set to the current drive and the DriveNotFoundException will not happen if (useDefaultProvider) { // the default provider is FileSystem provider = PublicSessionState.Internal.GetSingleProvider(Microsoft.PowerShell.Commands.FileSystemProvider.ProviderName); } else { throw; } } if (getProviderPathContext.HasErrors()) { getProviderPathContext.WriteErrorsToContext(context); return null; } if (drive != null) { context.Drive = drive; } bool isProviderQualified = false; bool isDriveQualified = false; string qualifier = null; string pathNoQualifier = RemoveQualifier(path, provider, out qualifier, out isProviderQualified, out isDriveQualified); string result = GetParentPath(provider, pathNoQualifier, root, context); if (!String.IsNullOrEmpty(qualifier) && !String.IsNullOrEmpty(result)) { result = AddQualifier(result, provider, qualifier, isProviderQualified, isDriveQualified); } return result; } finally { getProviderPathContext.RemoveStopReferral(); } } // GetParentPath
/// <summary> /// Changes the current working directory to the path specified. /// </summary> /// <param name="path"> /// The path of the new current working directory. /// </param> /// <param name="context"> /// The context the provider uses when performing the operation. /// </param> /// <param name="literalPath"> /// Indicate if the path is a literal path. /// </param> /// <returns> /// The PathInfo object representing the path of the location /// that was set. /// </returns> /// <exception cref="ArgumentNullException"> /// If <paramref name="path"/> is null. /// </exception> /// <exception cref="ArgumentException"> /// If <paramref name="path"/> does not exist, is not a container, or /// resolved to multiple containers. /// </exception> /// <exception cref="ProviderNotFoundException"> /// If <paramref name="path"/> refers to a provider that does not exist. /// </exception> /// <exception cref="DriveNotFoundException"> /// If <paramref name="path"/> refers to a drive that does not exist. /// </exception> /// <exception cref="ProviderInvocationException"> /// If the provider associated with <paramref name="path"/> threw an /// exception. /// </exception> /// <exception cref="ItemNotFoundException"> /// If the <paramref name="path"/> could not be resolved. /// </exception> internal PathInfo SetLocation(string path, CmdletProviderContext context, bool literalPath) { if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } PathInfo current = CurrentLocation; string originalPath = path; string driveName = null; ProviderInfo provider = null; string providerId = null; switch (originalPath) { case string originalPathSwitch when !literalPath && originalPathSwitch.Equals("-", StringComparison.Ordinal): if (_setLocationHistory.UndoCount <= 0) { throw new InvalidOperationException(SessionStateStrings.LocationUndoStackIsEmpty); } path = _setLocationHistory.Undo(this.CurrentLocation).Path; break; case string originalPathSwitch when !literalPath && originalPathSwitch.Equals("+", StringComparison.Ordinal): if (_setLocationHistory.RedoCount <= 0) { throw new InvalidOperationException(SessionStateStrings.LocationRedoStackIsEmpty); } path = _setLocationHistory.Redo(this.CurrentLocation).Path; break; default: var pushPathInfo = GetNewPushPathInfo(); _setLocationHistory.Push(pushPathInfo); break; } PSDriveInfo previousWorkingDrive = CurrentDrive; // First check to see if the path is a home path if (LocationGlobber.IsHomePath(path)) { path = Globber.GetHomeRelativePath(path); } if (LocationGlobber.IsProviderDirectPath(path)) { // The path is a provider-direct path so use the current // provider and its hidden drive but don't modify the path // at all. provider = CurrentLocation.Provider; CurrentDrive = provider.HiddenDrive; } else if (LocationGlobber.IsProviderQualifiedPath(path, out providerId)) { provider = GetSingleProvider(providerId); CurrentDrive = provider.HiddenDrive; } else { // See if the path is a relative or absolute // path. if (Globber.IsAbsolutePath(path, out driveName)) { // Since the path is an absolute path // we need to change the current working // drive PSDriveInfo newWorkingDrive = GetDrive(driveName); CurrentDrive = newWorkingDrive; // If the path is simply a colon-terminated drive, // not a slash-terminated path to the root of a drive, // set the path to the current working directory of that drive. string colonTerminatedVolume = CurrentDrive.Name + ':'; if (CurrentDrive.VolumeSeparatedByColon && (path.Length == colonTerminatedVolume.Length)) { path = Path.Combine(colonTerminatedVolume + Path.DirectorySeparatorChar, CurrentDrive.CurrentLocation); } // Now that the current working drive is set, // process the rest of the path as a relative path. } } if (context == null) { context = new CmdletProviderContext(this.ExecutionContext); } if (CurrentDrive != null) { context.Drive = CurrentDrive; } CmdletProvider providerInstance = null; Collection <PathInfo> workingPath = null; try { workingPath = Globber.GetGlobbedMonadPathsFromMonadPath( path, false, context, out providerInstance); } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception) { // Reset the drive to the previous drive and // then rethrow the error CurrentDrive = previousWorkingDrive; throw; } if (workingPath.Count == 0) { // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; throw new ItemNotFoundException( path, "PathNotFound", SessionStateStrings.PathNotFound); } // We allow globbing the location as long as it only resolves a single container. bool foundContainer = false; bool pathIsContainer = false; bool pathIsProviderQualifiedPath = false; bool currentPathisProviderQualifiedPath = false; for (int index = 0; index < workingPath.Count; ++index) { CmdletProviderContext normalizePathContext = new CmdletProviderContext(context); PathInfo resolvedPath = workingPath[index]; string currentPath = path; try { string providerName = null; currentPathisProviderQualifiedPath = LocationGlobber.IsProviderQualifiedPath(resolvedPath.Path, out providerName); if (currentPathisProviderQualifiedPath) { // The path should be the provider-qualified path without the provider ID // or :: string providerInternalPath = LocationGlobber.RemoveProviderQualifier(resolvedPath.Path); try { currentPath = NormalizeRelativePath(GetSingleProvider(providerName), providerInternalPath, string.Empty, normalizePathContext); } catch (NotSupportedException) { // Since the provider does not support normalizing the path, just // use the path we currently have. } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception) { // Reset the drive to the previous drive and // then rethrow the error CurrentDrive = previousWorkingDrive; throw; } } else { try { currentPath = NormalizeRelativePath(resolvedPath.Path, CurrentDrive.Root, normalizePathContext); } catch (NotSupportedException) { // Since the provider does not support normalizing the path, just // use the path we currently have. } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } catch (Exception) { // Reset the drive to the previous drive and // then rethrow the error CurrentDrive = previousWorkingDrive; throw; } } // Now see if there was errors while normalizing the path if (normalizePathContext.HasErrors()) { // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; normalizePathContext.ThrowFirstErrorOrDoNothing(); } } finally { normalizePathContext.RemoveStopReferral(); } bool isContainer = false; CmdletProviderContext itemContainerContext = new CmdletProviderContext(context); itemContainerContext.SuppressWildcardExpansion = true; try { isContainer = IsItemContainer( resolvedPath.Path, itemContainerContext); if (itemContainerContext.HasErrors()) { // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; itemContainerContext.ThrowFirstErrorOrDoNothing(); } } catch (NotSupportedException) { if (currentPath.Length == 0) { // Treat this as a container because providers that only // support the ContainerCmdletProvider interface are really // containers at their root. isContainer = true; } } finally { itemContainerContext.RemoveStopReferral(); } if (isContainer) { if (foundContainer) { // The path resolved to more than one container // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; throw PSTraceSource.NewArgumentException( "path", SessionStateStrings.PathResolvedToMultiple, originalPath); } else { // Set the path to use path = currentPath; // Mark it as a container pathIsContainer = true; // Mark whether or not it was provider-qualified pathIsProviderQualifiedPath = currentPathisProviderQualifiedPath; // Mark that we have already found one container. Finding additional // should be an error foundContainer = true; } } } if (pathIsContainer) { // Remove the root slash since it is implied that the // current working directory is relative to the root. if (!LocationGlobber.IsProviderDirectPath(path) && path.StartsWith(StringLiterals.DefaultPathSeparator) && !pathIsProviderQualifiedPath) { path = path.Substring(1); } s_tracer.WriteLine( "New working path = {0}", path); CurrentDrive.CurrentLocation = path; } else { // Set the current working drive back to the previous // one in case it was changed. CurrentDrive = previousWorkingDrive; throw new ItemNotFoundException( originalPath, "PathNotFound", SessionStateStrings.PathNotFound); } // Now make sure the current drive is set in the provider's // current working drive hashtable ProvidersCurrentWorkingDrive[CurrentDrive.Provider] = CurrentDrive; // Set the $PWD variable to the new location this.SetVariable(SpecialVariables.PWDVarPath, this.CurrentLocation, false, true, CommandOrigin.Internal); // If an action has been defined for location changes, invoke it now. if (PublicSessionState.InvokeCommand.LocationChangedAction != null) { var eventArgs = new LocationChangedEventArgs(PublicSessionState, current, CurrentLocation); PublicSessionState.InvokeCommand.LocationChangedAction.Invoke(ExecutionContext.CurrentRunspace, eventArgs); s_tracer.WriteLine("Invoked LocationChangedAction"); } return(this.CurrentLocation); }
internal string NormalizeRelativePath(string path, string basePath, CmdletProviderContext context) { string str2; if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } CmdletProviderContext context2 = new CmdletProviderContext(context); try { PSDriveInfo drive = null; ProviderInfo provider = null; string str = this.Globber.GetProviderPath(path, context2, out provider, out drive); if (context2.HasErrors()) { context2.WriteErrorsToContext(context); return null; } if ((str == null) || (provider == null)) { Exception exception = PSTraceSource.NewArgumentException("path"); context.WriteError(new ErrorRecord(exception, "NormalizePathNullResult", ErrorCategory.InvalidArgument, path)); return null; } if (drive != null) { context.Drive = drive; if (((this.GetProviderInstance(provider) is NavigationCmdletProvider) && !string.IsNullOrEmpty(drive.Root)) && path.StartsWith(drive.Root, StringComparison.OrdinalIgnoreCase)) { str = path; } } str2 = this.NormalizeRelativePath(provider, str, basePath, context); } finally { context2.RemoveStopReferral(); } return str2; }
/// <summary> /// Determines if the specified path is the current working directory /// or a parent of the current working directory. /// </summary> /// <param name="path"> /// A monad namespace absolute or relative path. /// </param> /// <param name="context"> /// The context the provider uses when performing the operation. /// </param> /// <returns> /// true, if the path is the current working directory or a parent of the current /// working directory. false, otherwise. /// </returns> /// <exception cref="ArgumentNullException"> /// If <paramref name="path"/> is null. /// </exception> /// <exception cref="ProviderNotFoundException"> /// If the path is a provider-qualified path for a provider that is /// not loaded into the system. /// </exception> /// <exception cref="DriveNotFoundException"> /// If the <paramref name="path"/> refers to a drive that could not be found. /// </exception> /// <exception cref="ProviderInvocationException"> /// If the provider used to build the path threw an exception. /// </exception> /// <exception cref="NotSupportedException"> /// If the provider that the <paramref name="path"/> represents is not a NavigationCmdletProvider /// or ContainerCmdletProvider. /// </exception> /// <exception cref="InvalidOperationException"> /// If the <paramref name="path"/> starts with "~" and the home location is not set for /// the provider. /// </exception> /// <exception cref="ProviderInvocationException"> /// If the provider specified by <paramref name="providerId"/> threw an /// exception when its GetParentPath or MakePath was called while /// processing the <paramref name="path"/>. /// </exception> internal bool IsCurrentLocationOrAncestor(string path, CmdletProviderContext context) { bool result = false; if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } PSDriveInfo drive = null; ProviderInfo provider = null; string providerSpecificPath = Globber.GetProviderPath( path, context, out provider, out drive); if (drive != null) { s_tracer.WriteLine("Tracing drive"); drive.Trace(); } Dbg.Diagnostics.Assert( providerSpecificPath != null, "There should always be a way to generate a provider path for a " + "given path"); if (drive != null) { context.Drive = drive; } // Check to see if the path that was specified is within the current // working drive if (drive == CurrentDrive) { // The path needs to be normalized to get rid of relative path tokens // so they don't interfere with our path comparisons below CmdletProviderContext normalizePathContext = new CmdletProviderContext(context); try { providerSpecificPath = NormalizeRelativePath(path, null, normalizePathContext); } catch (NotSupportedException) { // Since the provider does not support normalizing the path, just // use the path we currently have. } catch (LoopFlowException) { throw; } catch (PipelineStoppedException) { throw; } catch (ActionPreferenceStopException) { throw; } finally { normalizePathContext.RemoveStopReferral(); } if (normalizePathContext.HasErrors()) { normalizePathContext.ThrowFirstErrorOrDoNothing(); } s_tracer.WriteLine("Provider path = {0}", providerSpecificPath); // Get the current working directory provider specific path PSDriveInfo currentWorkingDrive = null; ProviderInfo currentDriveProvider = null; string currentWorkingPath = Globber.GetProviderPath( ".", context, out currentDriveProvider, out currentWorkingDrive); Dbg.Diagnostics.Assert( currentWorkingDrive == CurrentDrive, "The current working drive should be the CurrentDrive."); s_tracer.WriteLine( "Current working path = {0}", currentWorkingPath); // See if the path is the current working directory or a parent // of the current working directory s_tracer.WriteLine( "Comparing {0} to {1}", providerSpecificPath, currentWorkingPath); if (String.Compare(providerSpecificPath, currentWorkingPath, StringComparison.CurrentCultureIgnoreCase) == 0) { // The path is the current working directory so // return true s_tracer.WriteLine("The path is the current working directory"); result = true; } else { // Check to see if the specified path is a parent // of the current working directory string lockedDirectory = currentWorkingPath; while (lockedDirectory.Length > 0) { // We need to allow the provider to go as far up the tree // as it can even if that means it has to traverse higher // than the mount point for this drive. That is // why we are passing the empty string as the root here. lockedDirectory = GetParentPath( drive.Provider, lockedDirectory, String.Empty, context); s_tracer.WriteLine( "Comparing {0} to {1}", lockedDirectory, providerSpecificPath); if (String.Compare(lockedDirectory, providerSpecificPath, StringComparison.CurrentCultureIgnoreCase) == 0) { // The path is a parent of the current working // directory s_tracer.WriteLine( "The path is a parent of the current working directory: {0}", lockedDirectory); result = true; break; } } } } else { s_tracer.WriteLine("Drives are not the same"); } return(result); }
} // GetChildItems /// <summary> /// Since we can't do include and exclude filtering on items we have to /// do the recursion ourselves. We get each child name and see if it matches /// the include and exclude filters. If the child is a container we recurse /// into that container. /// </summary> /// /// <param name="providerInstance"> /// The instance of the provider to use. /// </param> /// /// <param name="path"> /// The path to the item to get the children from. /// </param> /// /// <param name="recurse"> /// Recurse into sub-containers when getting children. /// </param> /// /// <param name="context"> /// The context under which the command is running. /// </param> /// /// <param name="childrenNotMatchingFilterCriteria"> /// The count of items that do not match any include/exclude criteria. /// </param> /// /// <param name="processMode">Indicates if this is a Enumerate/Remove operation</param> /// /// <param name="skipIsItemContainerCheck">a hint used to skip IsItemContainer checks</param> /// /// <exception cref="ProviderNotFoundException"> /// If the <paramref name="path"/> refers to a provider that could not be found. /// </exception> /// /// <exception cref="DriveNotFoundException"> /// If the <paramref name="path"/> refers to a drive that could not be found. /// </exception> /// /// <exception cref="NotSupportedException"> /// If the provider that the <paramref name="path"/> refers to does /// not support this operation. /// </exception> /// /// <exception cref="ProviderInvocationException"> /// If the provider threw an exception. /// </exception> /// private void ProcessPathItems( CmdletProvider providerInstance, string path, bool recurse, CmdletProviderContext context, out int childrenNotMatchingFilterCriteria, ProcessMode processMode = ProcessMode.Enumerate, bool skipIsItemContainerCheck = false) { ContainerCmdletProvider containerCmdletProvider = GetContainerProviderInstance(providerInstance); childrenNotMatchingFilterCriteria = 0; Dbg.Diagnostics.Assert( providerInstance != null, "The caller should have verified the providerInstance"); Dbg.Diagnostics.Assert( path != null, "The caller should have verified the path"); Dbg.Diagnostics.Assert( context != null, "The caller should have verified the context"); // Construct the include filter Collection<WildcardPattern> includeMatcher = SessionStateUtilities.CreateWildcardsFromStrings( context.Include, WildcardOptions.IgnoreCase); // Construct the exclude filter Collection<WildcardPattern> excludeMatcher = SessionStateUtilities.CreateWildcardsFromStrings( context.Exclude, WildcardOptions.IgnoreCase); // If the item is a container we have to filter its children // Use a hint + lazy evaluation to skip a container check if (skipIsItemContainerCheck || IsItemContainer(providerInstance, path, context)) { CmdletProviderContext newContext = new CmdletProviderContext(context); Collection<PSObject> childNameObjects = null; System.Collections.Generic.Dictionary<string, bool> filteredChildNameDictionary = null; try { // Get all the child names GetChildNames( providerInstance, path, (recurse) ? ReturnContainers.ReturnAllContainers : ReturnContainers.ReturnMatchingContainers, newContext); newContext.WriteErrorsToContext(context); childNameObjects = newContext.GetAccumulatedObjects(); // The code above initially retrieves all of the containers so that it doesn't limit the recursion, // but then emits the non-matching container further down. The public API doesn't support a way to // differentiate the two, so we need to do a diff. // So if there was a filter, do it again to get the fully filtered items. if (recurse && (providerInstance.IsFilterSet())) { newContext.RemoveStopReferral(); newContext = new CmdletProviderContext(context); filteredChildNameDictionary = new System.Collections.Generic.Dictionary<string, bool>(); GetChildNames( providerInstance, path, ReturnContainers.ReturnMatchingContainers, newContext); var filteredChildNameObjects = newContext.GetAccumulatedObjects(); foreach (PSObject filteredChildName in filteredChildNameObjects) { string filteredName = filteredChildName.BaseObject as string; if (filteredName != null) { filteredChildNameDictionary[filteredName] = true; } } } } finally { newContext.RemoveStopReferral(); } // Now loop through all the child objects matching the filters and recursing // into containers for (int index = 0; index < childNameObjects.Count; ++index) { // Making sure to obey the StopProcessing. if (context.Stopping) { return; } string childName = childNameObjects[index].BaseObject as string; if (childName == null) { continue; } // Generate the provider path for the child string qualifiedPath = MakePath(providerInstance, path, childName, context); if (qualifiedPath == null) { continue; } bool isIncludeMatch = !context.SuppressWildcardExpansion && SessionStateUtilities.MatchesAnyWildcardPattern( childName, includeMatcher, true); if (isIncludeMatch) { if (!SessionStateUtilities.MatchesAnyWildcardPattern( childName, excludeMatcher, false)) { bool emitItem = true; if (filteredChildNameDictionary != null) { bool isChildNameInDictionary = false; emitItem = filteredChildNameDictionary.TryGetValue(childName, out isChildNameInDictionary); } if (emitItem) { if (processMode == ProcessMode.Delete) { containerCmdletProvider.RemoveItem(qualifiedPath, false, context); } else if (processMode != ProcessMode.Delete) { // The object is a match so get it and write it out. GetItemPrivate(providerInstance, qualifiedPath, context); } } } else { childrenNotMatchingFilterCriteria++; } } else { childrenNotMatchingFilterCriteria++; } // Now recurse if it is a container if (recurse && IsItemContainer(providerInstance, qualifiedPath, context)) { // Making sure to obey the StopProcessing. if (context.Stopping) { return; } // The item is a container so recurse into it. ProcessPathItems(providerInstance, qualifiedPath, recurse, context, out childrenNotMatchingFilterCriteria, processMode, skipIsItemContainerCheck: true); } } // for each childName } else { // The path is not a container so write it out if its name // matches the filter string childName = path; childName = GetChildName(providerInstance, path, context, true); // Write out the object if it is a match bool isIncludeMatch = SessionStateUtilities.MatchesAnyWildcardPattern( childName, includeMatcher, true); if (isIncludeMatch) { if (!SessionStateUtilities.MatchesAnyWildcardPattern( childName, excludeMatcher, false)) { if (processMode != ProcessMode.Delete) { // The object is a match so get it and write it out. GetItemPrivate(providerInstance, path, context); } else { // The object is a match so, remove it. containerCmdletProvider.RemoveItem(path, recurse, context); } } } } } // ProcessPathItems