-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Description
- The IsPathRoot() method does double check for UNC
PowerShell/src/System.Management.Automation/namespaces/FileSystemProvider.cs
Lines 5026 to 5047 in 281b437
/// <summary> /// Determines if the specified path is either a drive root or a UNC root. /// </summary> /// <param name="path"> /// The path /// </param> /// <returns> /// True if the path is either a drive root or a UNC root, or false otherwise. /// </returns> private static bool IsPathRoot(string path) { if (string.IsNullOrEmpty(path)) { return false; } bool isDriveRoot = string.Equals(path, Path.GetPathRoot(path), StringComparison.OrdinalIgnoreCase); bool isUNCRoot = IsUNCRoot(path); bool result = isDriveRoot || isUNCRoot; s_tracer.WriteLine("result = {0}; isDriveRoot = {1}; isUNCRoot = {2}", result, isDriveRoot, isUNCRoot); return result; }
and could be replaced with more short and fast code. Proposal from @mklement0 Tracking FileSystem provider performance issues #14497 (comment)
Also we need to review GetFileSystemItem(string path, ref bool isContainer, bool showHidden) - there is a root check and maybe a bug (no UNC share check)
PowerShell/src/System.Management.Automation/namespaces/FileSystemProvider.cs
Lines 1426 to 1430 in 281b437
| bool isRootPath = | |
| string.Equals( | |
| Path.GetPathRoot(path), | |
| result.FullName, | |
| StringComparison.OrdinalIgnoreCase); |
-
PR Reduce aggressive correcting casing of file system paths #14469 Reduce aggressive correcting casing of file system paths
On Windows we do case normalizations even if results are not used. -
No need to allocate FileInfo and extra strings in IsSameWindowsVolume():
PowerShell/src/System.Management.Automation/namespaces/FileSystemProvider.cs
Lines 6141 to 6147 in 281b437
private static bool IsSameWindowsVolume(string source, string destination) { FileInfo src = new FileInfo(source); FileInfo dest = new FileInfo(destination); return (src.Directory.Root.Name == dest.Directory.Root.Name); }
We can useGetDirectoryName(ReadOnlySpan<char> path). Also we should use Ordinal comparison. -
EnsureDriveIsRooted() method does extra path.IndexOf(':') - we can simply check last char
PowerShell/src/System.Management.Automation/namespaces/FileSystemProvider.cs
Lines 5709 to 5727 in 281b437
private static string EnsureDriveIsRooted(string path) { string result = path; // Find the drive separator int index = path.IndexOf(':'); if (index != -1) { // if the drive separator is the end of the path, add // the root path separator back if (index + 1 == path.Length) { result = path + StringLiterals.DefaultPathSeparator; } } return result; } -
We need to review semantic of IsValidPath() method. If it is exactly about path validity the method could be simplified but we need to measure a performance. In common case it is impossible to validate path by parsing but only by opening.
PowerShell/src/System.Management.Automation/namespaces/FileSystemProvider.cs
Lines 1192 to 1246 in 281b437
protected override bool IsValidPath(string path) { // Path passed should be fully qualified path. if (string.IsNullOrEmpty(path)) { return false; } // Normalize the path path = NormalizePath(path); path = EnsureDriveIsRooted(path); #if !UNIX // Remove alternate data stream references // See if they've used the inline stream syntax. They have more than one colon. int firstColon = path.IndexOf(':'); int secondColon = path.IndexOf(':', firstColon + 1); if (secondColon > 0) { path = path.Substring(0, secondColon); } #endif // Make sure the path is either drive rooted or UNC Path if (!IsAbsolutePath(path) && !Utils.PathIsUnc(path)) { return false; } // Exceptions should only deal with exceptional circumstances, // but unfortunately, FileInfo offers no Try() methods that // let us check if we _could_ open the file. try { FileInfo testFile = new FileInfo(path); } catch (Exception e) { if ((e is ArgumentNullException) || (e is ArgumentException) || (e is System.Security.SecurityException) || (e is UnauthorizedAccessException) || (e is PathTooLongException) || (e is NotSupportedException)) { return false; } else { throw; } } return true; } -
Statistic shows:
dir -Recurse 'C:\Program Files (x86)\' | Select -ExpandProperty Mode | Sort-Object | Group-Object -NoElement
Count Name
----- ----
1 -----
3 --r--
44263 -a---
6 -ar--
8136 d----
3 d---s
2 d-r--
1044 la---and we could add "la---" as a static element in
PowerShell/src/System.Management.Automation/namespaces/FileSystemProvider.cs
Lines 2024 to 2040 in 281b437
| if (!isLink) | |
| { | |
| // special casing for the common cases - no allocations | |
| switch (fileAttributes) | |
| { | |
| case FileAttributes.Archive: | |
| return "-a---"; | |
| case FileAttributes.Directory: | |
| return "d----"; | |
| case FileAttributes.Normal: | |
| return "-----"; | |
| case FileAttributes.Directory | FileAttributes.ReadOnly: | |
| return "d-r--"; | |
| case FileAttributes.Archive | FileAttributes.ReadOnly: | |
| return "-ar--"; | |
| } | |
| } |
if (!isLink)
{
// special casing for the common cases - no allocations
switch (fileAttributes)
{
case FileAttributes.Archive:
return "-a---";
case FileAttributes.Directory:
return "d----";
case FileAttributes.Normal:
return "-----";
case FileAttributes.Directory | FileAttributes.ReadOnly:
return "d-r--";
case FileAttributes.Archive | FileAttributes.ReadOnly:
return "-ar--";
}
}
else if (fileAttributes == FileAttributes.ReadOnly)
{
return "la---";
}
...- Remove double check ItemExists();
PowerShell/src/System.Management.Automation/namespaces/FileSystemProvider.cs
Lines 6105 to 6112 in 281b437
private void CopyAndDelete(DirectoryInfo directory, string destination, bool force) { if (!ItemExists(destination)) { CreateDirectory(destination, false); } else if (ItemExists(destination) && !IsItemContainer(destination)) {