You've already forked linux-packaging-mono
Imported Upstream version 5.16.0.100
Former-commit-id: 38faa55fb9669e35e7d8448b15c25dc447f25767
This commit is contained in:
parent
0a9828183b
commit
7d7f676260
@@ -20,12 +20,15 @@ namespace System.IO
|
||||
public static System.Collections.Generic.IEnumerable<string> EnumerateDirectories(string path) { throw null; }
|
||||
public static System.Collections.Generic.IEnumerable<string> EnumerateDirectories(string path, string searchPattern) { throw null; }
|
||||
public static System.Collections.Generic.IEnumerable<string> EnumerateDirectories(string path, string searchPattern, System.IO.SearchOption searchOption) { throw null; }
|
||||
public static System.Collections.Generic.IEnumerable<string> EnumerateDirectories(string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; }
|
||||
public static System.Collections.Generic.IEnumerable<string> EnumerateFiles(string path) { throw null; }
|
||||
public static System.Collections.Generic.IEnumerable<string> EnumerateFiles(string path, string searchPattern) { throw null; }
|
||||
public static System.Collections.Generic.IEnumerable<string> EnumerateFiles(string path, string searchPattern, System.IO.SearchOption searchOption) { throw null; }
|
||||
public static System.Collections.Generic.IEnumerable<string> EnumerateFiles(string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; }
|
||||
public static System.Collections.Generic.IEnumerable<string> EnumerateFileSystemEntries(string path) { throw null; }
|
||||
public static System.Collections.Generic.IEnumerable<string> EnumerateFileSystemEntries(string path, string searchPattern) { throw null; }
|
||||
public static System.Collections.Generic.IEnumerable<string> EnumerateFileSystemEntries(string path, string searchPattern, System.IO.SearchOption searchOption) { throw null; }
|
||||
public static System.Collections.Generic.IEnumerable<string> EnumerateFileSystemEntries(string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; }
|
||||
public static bool Exists(string path) { throw null; }
|
||||
public static System.DateTime GetCreationTime(string path) { throw null; }
|
||||
public static System.DateTime GetCreationTimeUtc(string path) { throw null; }
|
||||
@@ -33,13 +36,16 @@ namespace System.IO
|
||||
public static string[] GetDirectories(string path) { throw null; }
|
||||
public static string[] GetDirectories(string path, string searchPattern) { throw null; }
|
||||
public static string[] GetDirectories(string path, string searchPattern, System.IO.SearchOption searchOption) { throw null; }
|
||||
public static string[] GetDirectories(string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; }
|
||||
public static string GetDirectoryRoot(string path) { throw null; }
|
||||
public static string[] GetFiles(string path) { throw null; }
|
||||
public static string[] GetFiles(string path, string searchPattern) { throw null; }
|
||||
public static string[] GetFiles(string path, string searchPattern, System.IO.SearchOption searchOption) { throw null; }
|
||||
public static string[] GetFiles(string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; }
|
||||
public static string[] GetFileSystemEntries(string path) { throw null; }
|
||||
public static string[] GetFileSystemEntries(string path, string searchPattern) { throw null; }
|
||||
public static string[] GetFileSystemEntries(string path, string searchPattern, System.IO.SearchOption searchOption) { throw null; }
|
||||
public static string[] GetFileSystemEntries(string path, string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; }
|
||||
public static System.DateTime GetLastAccessTime(string path) { throw null; }
|
||||
public static System.DateTime GetLastAccessTimeUtc(string path) { throw null; }
|
||||
public static System.DateTime GetLastWriteTime(string path) { throw null; }
|
||||
@@ -67,23 +73,29 @@ namespace System.IO
|
||||
public override void Delete() { }
|
||||
public void Delete(bool recursive) { }
|
||||
public System.Collections.Generic.IEnumerable<System.IO.DirectoryInfo> EnumerateDirectories() { throw null; }
|
||||
public System.Collections.Generic.IEnumerable<System.IO.DirectoryInfo> EnumerateDirectories(string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; }
|
||||
public System.Collections.Generic.IEnumerable<System.IO.FileSystemInfo> EnumerateFileSystemInfos(string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; }
|
||||
public System.Collections.Generic.IEnumerable<System.IO.DirectoryInfo> EnumerateDirectories(string searchPattern) { throw null; }
|
||||
public System.Collections.Generic.IEnumerable<System.IO.DirectoryInfo> EnumerateDirectories(string searchPattern, System.IO.SearchOption searchOption) { throw null; }
|
||||
public System.Collections.Generic.IEnumerable<System.IO.FileInfo> EnumerateFiles() { throw null; }
|
||||
public System.Collections.Generic.IEnumerable<System.IO.FileInfo> EnumerateFiles(string searchPattern) { throw null; }
|
||||
public System.Collections.Generic.IEnumerable<System.IO.FileInfo> EnumerateFiles(string searchPattern, System.IO.SearchOption searchOption) { throw null; }
|
||||
public System.Collections.Generic.IEnumerable<System.IO.FileInfo> EnumerateFiles(string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; }
|
||||
public System.Collections.Generic.IEnumerable<System.IO.FileSystemInfo> EnumerateFileSystemInfos() { throw null; }
|
||||
public System.Collections.Generic.IEnumerable<System.IO.FileSystemInfo> EnumerateFileSystemInfos(string searchPattern) { throw null; }
|
||||
public System.Collections.Generic.IEnumerable<System.IO.FileSystemInfo> EnumerateFileSystemInfos(string searchPattern, System.IO.SearchOption searchOption) { throw null; }
|
||||
public System.Collections.Generic.IEnumerable<System.IO.DirectoryInfo> EnumerateDirectories(string searchPattern, System.IO.SearchOption searchOption) { throw null; }
|
||||
public System.IO.DirectoryInfo[] GetDirectories() { throw null; }
|
||||
public System.IO.DirectoryInfo[] GetDirectories(string searchPattern) { throw null; }
|
||||
public System.IO.DirectoryInfo[] GetDirectories(string searchPattern, System.IO.SearchOption searchOption) { throw null; }
|
||||
public System.IO.DirectoryInfo[] GetDirectories(string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; }
|
||||
public System.IO.FileInfo[] GetFiles() { throw null; }
|
||||
public System.IO.FileInfo[] GetFiles(string searchPattern) { throw null; }
|
||||
public System.IO.FileInfo[] GetFiles(string searchPattern, System.IO.SearchOption searchOption) { throw null; }
|
||||
public System.IO.FileInfo[] GetFiles(string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; }
|
||||
public System.IO.FileSystemInfo[] GetFileSystemInfos() { throw null; }
|
||||
public System.IO.FileSystemInfo[] GetFileSystemInfos(string searchPattern) { throw null; }
|
||||
public System.IO.FileSystemInfo[] GetFileSystemInfos(string searchPattern, System.IO.SearchOption searchOption) { throw null; }
|
||||
public System.IO.FileSystemInfo[] GetFileSystemInfos(string searchPattern, System.IO.EnumerationOptions enumerationOptions) { throw null; }
|
||||
public void MoveTo(string destDirName) { }
|
||||
public override string ToString() { throw null; }
|
||||
}
|
||||
@@ -211,4 +223,83 @@ namespace System.IO
|
||||
AllDirectories = 1,
|
||||
TopDirectoryOnly = 0,
|
||||
}
|
||||
public enum MatchType
|
||||
{
|
||||
Simple,
|
||||
Win32
|
||||
}
|
||||
public enum MatchCasing
|
||||
{
|
||||
PlatformDefault,
|
||||
CaseSensitive,
|
||||
CaseInsensitive
|
||||
}
|
||||
public class EnumerationOptions
|
||||
{
|
||||
public EnumerationOptions() { }
|
||||
public bool RecurseSubdirectories { get { throw null; } set { } }
|
||||
public bool IgnoreInaccessible { get { throw null; } set { } }
|
||||
public int BufferSize { get { throw null; } set { } }
|
||||
public FileAttributes AttributesToSkip { get { throw null; } set { } }
|
||||
public MatchType MatchType { get { throw null; } set { } }
|
||||
public MatchCasing MatchCasing { get { throw null; } set { } }
|
||||
public bool ReturnSpecialDirectories { get { throw null; } set { } }
|
||||
}
|
||||
}
|
||||
namespace System.IO.Enumeration
|
||||
{
|
||||
public ref struct FileSystemEntry
|
||||
{
|
||||
public ReadOnlySpan<char> Directory { get { throw null; } }
|
||||
public ReadOnlySpan<char> RootDirectory { get { throw null; } }
|
||||
public ReadOnlySpan<char> OriginalRootDirectory { get { throw null; } }
|
||||
public ReadOnlySpan<char> FileName { get { throw null; } }
|
||||
public FileAttributes Attributes { get { throw null; } }
|
||||
public long Length { get { throw null; } }
|
||||
public DateTimeOffset CreationTimeUtc { get { throw null; } }
|
||||
public DateTimeOffset LastAccessTimeUtc { get { throw null; } }
|
||||
public DateTimeOffset LastWriteTimeUtc { get { throw null; } }
|
||||
public bool IsDirectory { get { throw null; } }
|
||||
public bool IsHidden { get { throw null; } }
|
||||
public FileSystemInfo ToFileSystemInfo() { throw null; }
|
||||
public string ToSpecifiedFullPath() { throw null; }
|
||||
public string ToFullPath() { throw null; }
|
||||
}
|
||||
public abstract class FileSystemEnumerator<TResult> : Runtime.ConstrainedExecution.CriticalFinalizerObject, Collections.Generic.IEnumerator<TResult>
|
||||
{
|
||||
public FileSystemEnumerator(string directory, EnumerationOptions options = null) { }
|
||||
|
||||
protected virtual bool ShouldIncludeEntry(ref FileSystemEntry entry) { throw null; }
|
||||
protected virtual bool ShouldRecurseIntoEntry(ref FileSystemEntry entry) { throw null; }
|
||||
protected abstract TResult TransformEntry(ref FileSystemEntry entry);
|
||||
protected virtual void OnDirectoryFinished(ReadOnlySpan<char> directory) { throw null; }
|
||||
protected virtual bool ContinueOnError(int error) { throw null; }
|
||||
|
||||
public TResult Current { get { throw null; } }
|
||||
object System.Collections.IEnumerator.Current { get { throw null; } }
|
||||
public bool MoveNext() { throw null; }
|
||||
public void Reset() { throw null; }
|
||||
public void Dispose() { throw null; }
|
||||
protected virtual void Dispose(bool disposing) { throw null; }
|
||||
}
|
||||
public class FileSystemEnumerable<TResult> : Collections.Generic.IEnumerable<TResult>
|
||||
{
|
||||
public FileSystemEnumerable(string directory, FindTransform transform, EnumerationOptions options = null) { }
|
||||
|
||||
public FindPredicate ShouldRecursePredicate { get { throw null; } set { } }
|
||||
public FindPredicate ShouldIncludePredicate { get { throw null; } set { } }
|
||||
|
||||
public Collections.Generic.IEnumerator<TResult> GetEnumerator() { throw null; }
|
||||
Collections.IEnumerator Collections.IEnumerable.GetEnumerator() { throw null; }
|
||||
|
||||
|
||||
public delegate bool FindPredicate(ref FileSystemEntry entry);
|
||||
public delegate TResult FindTransform(ref FileSystemEntry entry);
|
||||
}
|
||||
public static class FileSystemName
|
||||
{
|
||||
public static string TranslateWin32Expression(string expression) { throw null; }
|
||||
public static bool MatchesWin32Expression(ReadOnlySpan<char> expression, ReadOnlySpan<char> name, bool ignoreCase = true) { throw null; }
|
||||
public static bool MatchesSimpleExpression(ReadOnlySpan<char> expression, ReadOnlySpan<char> name, bool ignoreCase = true) { throw null; }
|
||||
}
|
||||
}
|
||||
|
||||
8
external/corefx/src/System.IO.FileSystem/src/MatchingRefApiCompatBaseline.txt
vendored
Normal file
8
external/corefx/src/System.IO.FileSystem/src/MatchingRefApiCompatBaseline.txt
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
Compat issues with assembly System.IO.FileSystem:
|
||||
# These are now virtual in the implementation, which should be ok.
|
||||
CannotMakeMemberAbstract : Member 'System.IO.FileSystemInfo.Exists' is abstract in the implementation but is not abstract in the contract.
|
||||
CannotMakeMemberAbstract : Member 'System.IO.FileSystemInfo.Name' is abstract in the implementation but is not abstract in the contract.
|
||||
CannotMakeMemberAbstract : Member 'System.IO.FileSystemInfo.Exists.get()' is abstract in the implementation but is not abstract in the contract.
|
||||
CannotMakeMemberAbstract : Member 'System.IO.FileSystemInfo.Name.get()' is abstract in the implementation but is not abstract in the contract.
|
||||
# C# generates backing fields for fixed buffers as public.
|
||||
TypesMustExist : Type 'System.IO.Enumeration.FileSystemEntry.<_fileNameBuffer>e__FixedBuffer' does not exist in the implementation but it does exist in the contract.
|
||||
@@ -3,10 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Security;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Microsoft.Win32.SafeHandles
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<IsPartialFacadeAssembly>true</IsPartialFacadeAssembly>
|
||||
<UWPCompatible Condition="'$(TargetGroup)' == 'uap' or '$(TargetGroup)' == 'uapaot'">true</UWPCompatible>
|
||||
<ILLinkClearInitLocals>true</ILLinkClearInitLocals>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(TargetsUnix)' == 'true'">
|
||||
<NoWarn>$(NoWarn);414</NoWarn>
|
||||
@@ -18,63 +19,43 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Release|AnyCPU'" />
|
||||
<ItemGroup>
|
||||
<Compile Include="System\IO\CharSpanExtensions.cs" />
|
||||
<Compile Include="System\IO\DosMatcher.cs" />
|
||||
<Compile Include="System\IO\Enumeration\FileSystemEntry.cs" />
|
||||
<Compile Include="System\IO\Enumeration\FileSystemEnumerable.cs" />
|
||||
<Compile Include="System\IO\Enumeration\FileSystemEnumerableFactory.cs" />
|
||||
<Compile Include="System\IO\Enumeration\FileSystemEnumerator.cs" />
|
||||
<Compile Include="System\IO\Enumeration\FileSystemName.cs" />
|
||||
<Compile Include="System\IO\MatchCasing.cs" />
|
||||
<Compile Include="System\IO\MatchType.cs" />
|
||||
<Compile Include="System\IO\Error.cs" />
|
||||
<Compile Include="System\IO\Directory.cs" />
|
||||
<Compile Include="System\IO\DirectoryInfo.cs" />
|
||||
<Compile Include="System\IO\File.cs" />
|
||||
<Compile Include="System\IO\FileInfo.cs" />
|
||||
<Compile Include="System\IO\FileSystemInfo.cs" />
|
||||
<Compile Include="System\IO\EnumerationOptions.cs" />
|
||||
<Compile Include="System\IO\Iterator.cs" />
|
||||
<Compile Include="System\IO\PathHelpers.cs" />
|
||||
<Compile Include="System\IO\PathPair.cs" />
|
||||
<Compile Include="System\IO\ReadLinesIterator.cs" />
|
||||
<Compile Include="System\IO\SearchOption.cs" />
|
||||
<Compile Include="System\IO\SearchTarget.cs" />
|
||||
<Compile Include="$(CommonPath)\System\Collections\Generic\ArrayBuilder.cs">
|
||||
<Link>Common\System\Collections\Generic\ArrayBuilder.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\Collections\Generic\EnumerableHelpers.cs">
|
||||
<Link>Common\System\Collections\Generic\EnumerableHelpers.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\Collections\Generic\LargeArrayBuilder.cs">
|
||||
<Link>Common\System\Collections\Generic\LargeArrayBuilder.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\IO\StringBuilderCache.cs">
|
||||
<Link>Common\System\IO\StringBuilderCache.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\Text\ValueStringBuilder.cs">
|
||||
<Link>Common\System\Text\ValueStringBuilder.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\IO\PathInternal.cs">
|
||||
<Link>Common\System\IO\PathInternal.cs</Link>
|
||||
<Compile Include="$(CommonPath)\CoreLib\System\Text\ValueStringBuilder.cs">
|
||||
<Link>Common\CoreLib\System\Text\ValueStringBuilder.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\IO\PathInternal.CaseSensitivity.cs">
|
||||
<Link>Common\System\IO\PathInternal.CaseSensitivity.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\Threading\Tasks\TaskToApm.cs">
|
||||
<Link>Common\System\Threading\Tasks\TaskToApm.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\IO\StreamHelpers.CopyValidation.cs">
|
||||
<Link>Common\System\IO\StreamHelpers.CopyValidation.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\CoreLib\System\IO\PathInternal.cs">
|
||||
<Link>Common\CoreLib\System\IO\PathInternal.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<!-- Windows -->
|
||||
<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
|
||||
<Compile Include="System\IO\CharSpanExtensions.Windows.cs" />
|
||||
<Compile Include="System\IO\Enumeration\FileSystemEnumerator.Windows.cs" />
|
||||
<Compile Include="System\IO\DisableMediaInsertionPrompt.cs" />
|
||||
<Compile Include="System\IO\DirectoryInfo.Windows.cs" />
|
||||
<Compile Include="System\IO\FileInfo.Windows.cs" />
|
||||
<Compile Include="System\IO\FindEnumerable.Windows.cs" />
|
||||
<Compile Include="System\IO\FindEnumerableFactory.cs" />
|
||||
<Compile Include="System\IO\FindPredicate.cs" />
|
||||
<Compile Include="System\IO\FindTransform.cs" />
|
||||
<Compile Include="System\IO\FindPredicates.cs" />
|
||||
<Compile Include="System\IO\FindTransforms.cs" />
|
||||
<Compile Include="System\IO\FileSystemInfo.Windows.cs" />
|
||||
<Compile Include="System\IO\PathHelpers.Windows.cs" />
|
||||
<Compile Include="System\IO\RawFindData.cs" />
|
||||
<Compile Include="System\IO\Enumeration\FileSystemEntry.Windows.cs" />
|
||||
<Compile Include="System\IO\FileSystem.Windows.cs" />
|
||||
<Compile Include="Microsoft\Win32\SafeHandles\SafeFindHandle.Windows.cs" />
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\Interop.Libraries.cs">
|
||||
@@ -95,11 +76,11 @@
|
||||
<Compile Include="$(CommonPath)\System\IO\DriveInfoInternal.Win32.cs">
|
||||
<Link>Common\System\IO\DriveInfoInternal.Win32.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\IO\PathInternal.Windows.cs">
|
||||
<Link>Common\System\IO\PathInternal.Windows.cs</Link>
|
||||
<Compile Include="$(CommonPath)\CoreLib\System\IO\PathInternal.Windows.cs">
|
||||
<Link>Common\CoreLib\System\IO\PathInternal.Windows.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\IO\Win32Marshal.cs">
|
||||
<Link>Common\System\IO\Win32Marshal.cs</Link>
|
||||
<Compile Include="$(CommonPath)\CoreLib\System\IO\Win32Marshal.cs">
|
||||
<Link>Common\CoreLib\System\IO\Win32Marshal.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\Interop.BOOL.cs">
|
||||
<Link>Common\Interop\Windows\Interop.BOOL.cs</Link>
|
||||
@@ -107,51 +88,9 @@
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SECURITY_ATTRIBUTES.cs">
|
||||
<Link>Common\Interop\Windows\Interop.SECURITY_ATTRIBUTES.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SecurityOptions.cs">
|
||||
<Link>Common\Interop\Windows\Interop.SecurityOptions.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.FileTypes.cs">
|
||||
<Link>Common\Interop\Windows\Interop.FileTypes.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetFileType_SafeHandle.cs">
|
||||
<Link>Common\Interop\Windows\Interop.GetFileType.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.FlushFileBuffers.cs">
|
||||
<Link>Common\Interop\Windows\Interop.FlushFileBuffers.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetEndOfFile.cs">
|
||||
<Link>Common\Interop\Windows\Interop.SetEndOfFile.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetFilePointerEx.cs">
|
||||
<Link>Common\Interop\Windows\Interop.SetFilePointerEx.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.CancelIoEx.cs">
|
||||
<Link>Common\Interop\Windows\Interop.CancelIoEx.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.ReadFile_SafeHandle_NativeOverlapped.cs">
|
||||
<Link>Common\Interop\Windows\Interop.ReadFile_NativeOverlapped.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.WriteFile_SafeHandle_NativeOverlapped.cs">
|
||||
<Link>Common\Interop\Windows\Interop.WriteFile_NativeOverlapped.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.ReadFile_SafeHandle_IntPtr.cs">
|
||||
<Link>Common\Interop\Windows\Interop.ReadFile_IntPtr.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.WriteFile_SafeHandle_IntPtr.cs">
|
||||
<Link>Common\Interop\Windows\Interop.WriteFile_IntPtr.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetFileInformationByHandle.cs">
|
||||
<Link>Common\Interop\Windows\Interop.SetFileInformationByHandle.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetCurrentDirectory.cs">
|
||||
<Link>Common\Interop\Windows\Interop.GetCurrentDirectory.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetCurrentDirectory.cs">
|
||||
<Link>Common\Interop\Windows\Interop.SetCurrentDirectory.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GetLongPathName.cs">
|
||||
<Link>Common\Interop\Windows\Interop.GetLongPathName.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.FindNextFile.cs">
|
||||
<Link>Common\Interop\Windows\Interop.FindNextFile.cs</Link>
|
||||
</Compile>
|
||||
@@ -188,7 +127,6 @@
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.GET_FILEEX_INFO_LEVELS.cs">
|
||||
<Link>Common\Interop\Windows\Interop.GET_FILEEX_INFO_LEVELS.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="System\IO\FileSystemInfo.Win32.cs" />
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetThreadErrorMode.cs">
|
||||
<Link>Common\Interop\Windows\Interop.SetThreadErrorMode.cs</Link>
|
||||
</Compile>
|
||||
@@ -246,7 +184,7 @@
|
||||
</ItemGroup>
|
||||
<!-- Windows : Win32 only -->
|
||||
<ItemGroup Condition="'$(TargetsWindows)' == 'true' and '$(UWPCompatible)' != 'true'">
|
||||
<Compile Include="System\IO\FindEnumerable.Win32.cs" />
|
||||
<Compile Include="System\IO\Enumeration\FileSystemEnumerator.Win32.cs" />
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.CreateFile.cs">
|
||||
<Link>Common\Interop\Windows\Interop.CreateFile.cs</Link>
|
||||
</Compile>
|
||||
@@ -262,6 +200,9 @@
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\NtDll\Interop.NtQueryDirectoryFile.cs">
|
||||
<Link>Common\Interop\Windows\Interop.NtQueryDirectoryFile.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\NtDll\Interop.NtCreateFile.cs">
|
||||
<Link>Common\Interop\Windows\Interop.NtCreateFile.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\NtDll\Interop.FILE_INFORMATION_CLASS.cs">
|
||||
<Link>Common\Interop\Windows\Interop.FILE_INFORMATION_CLASS.cs</Link>
|
||||
</Compile>
|
||||
@@ -274,7 +215,7 @@
|
||||
</ItemGroup>
|
||||
<!-- Windows : UAP - Win32 + WinRT -->
|
||||
<ItemGroup Condition="'$(TargetsWindows)' == 'true' and '$(UWPCompatible)' == 'true'">
|
||||
<Compile Include="System\IO\FindEnumerable.WinRT.cs" />
|
||||
<Compile Include="System\IO\Enumeration\FileSystemEnumerator.WinRT.cs" />
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.CreateFile2.cs">
|
||||
<Link>Common\Interop\Windows\Interop.CreateFile2.cs</Link>
|
||||
</Compile>
|
||||
@@ -290,9 +231,10 @@
|
||||
</ItemGroup>
|
||||
<!-- Unix -->
|
||||
<ItemGroup Condition="'$(TargetsUnix)' == 'true'">
|
||||
<Compile Include="System\IO\CharSpanExtensions.Unix.cs" />
|
||||
<Compile Include="System\IO\FileStatus.Unix.cs" />
|
||||
<Compile Include="System\IO\Enumeration\FileSystemEntry.Unix.cs" />
|
||||
<Compile Include="System\IO\Enumeration\FileSystemEnumerator.Unix.cs" />
|
||||
<Compile Include="System\IO\FileSystemInfo.Unix.cs" />
|
||||
<Compile Include="System\IO\PathHelpers.Unix.cs" />
|
||||
<Compile Include="System\IO\FileSystem.Unix.cs" />
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\Interop.Libraries.cs">
|
||||
<Link>Common\Interop\Unix\Interop.Libraries.cs</Link>
|
||||
@@ -306,30 +248,12 @@
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.ChMod.cs">
|
||||
<Link>Common\Interop\Unix\Interop.ChMod.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Close.cs">
|
||||
<Link>Common\Interop\Unix\Interop.Close.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.CopyFile.cs">
|
||||
<Link>Common\Interop\Unix\Interop.CopyFile.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.FTruncate.cs">
|
||||
<Link>Common\Interop\Unix\Interop.FTruncate.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.GetCwd.cs">
|
||||
<Link>Common\Interop\Unix\Interop.GetCwd.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Open.cs">
|
||||
<Link>Common\Interop\Unix\Interop.Open.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.OpenFlags.cs">
|
||||
<Link>Common\Interop\Unix\Interop.OpenFlags.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.MkDir.cs">
|
||||
<Link>Common\Interop\Unix\Interop.MkDir.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.PathConf.cs">
|
||||
<Link>Common\Interop\Unix\Interop.PathConf.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Permissions.cs">
|
||||
<Link>Common\Interop\Unix\Interop.Permissions.cs</Link>
|
||||
</Compile>
|
||||
@@ -345,36 +269,18 @@
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Stat.cs">
|
||||
<Link>Common\Interop\Unix\Interop.Stat.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Stat.Span.cs">
|
||||
<Link>Common\Interop\Unix\Interop.Stat.Span.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.ReadDir.cs">
|
||||
<Link>Common\Interop\Unix\Interop.ReadDir.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Access.cs">
|
||||
<Link>Common\Interop\Unix\Interop.Access.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.ChDir.cs">
|
||||
<Link>Common\Interop\Unix\Interop.ChDir.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.FLock.cs">
|
||||
<Link>Common\Interop\Unix\Interop.FLock.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.FnMatch.cs">
|
||||
<Link>Common\Interop\Unix\Interop.FnMatch.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.FSync.cs">
|
||||
<Link>Common\Interop\Unix\Interop.FSync.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.LSeek.cs">
|
||||
<Link>Common\Interop\Unix\Interop.LSeek.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Link.cs">
|
||||
<Link>Common\Interop\Unix\Interop.Link.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.MountPoints.cs">
|
||||
<Link>Common\Interop\Unix\Interop.MountPoints.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.PosixFAdvise.cs">
|
||||
<Link>Common\Interop\Unix\Interop.PosixFAdvise.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Read.cs">
|
||||
<Link>Common\Interop\Unix\Interop.Read.cs</Link>
|
||||
</Compile>
|
||||
@@ -384,27 +290,25 @@
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.RmDir.cs">
|
||||
<Link>Common\Interop\Unix\Interop.RmDir.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Write.cs">
|
||||
<Link>Common\Interop\Unix\Interop.Write.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.UTime.cs">
|
||||
<Link>Common\Interop\Unix\Interop.UTime.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeDirectoryHandle.Unix.cs">
|
||||
<Link>Common\Microsoft\Win32\SafeHandles\SafeDirectoryHandle.Unix.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\IO\PathInternal.Unix.cs">
|
||||
<Link>Common\System\IO\PathInternal.Unix.cs</Link>
|
||||
<Compile Include="$(CommonPath)\CoreLib\System\IO\PathInternal.Unix.cs">
|
||||
<Link>Common\CoreLib\System\IO\PathInternal.Unix.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\IO\DriveInfoInternal.Unix.cs">
|
||||
<Link>Common\System\IO\DriveInfoInternal.Unix.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\Text\ValueUtf8Converter.cs">
|
||||
<Link>Common\System\Text\ValueUtf8Converter.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Buffers" />
|
||||
<Reference Include="System.Collections" />
|
||||
<Reference Include="System.Diagnostics.Debug" />
|
||||
<Reference Include="System.Diagnostics.Tools" />
|
||||
<Reference Include="System.Linq" />
|
||||
<Reference Include="System.Memory" />
|
||||
<Reference Include="System.Resources.ResourceManager" />
|
||||
<Reference Include="System.Runtime" />
|
||||
@@ -419,4 +323,4 @@
|
||||
<Reference Include="System.Threading" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -1,38 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace System.IO
|
||||
{
|
||||
internal static partial class CharSpanExtensions
|
||||
{
|
||||
internal static unsafe bool EqualsOrdinal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, bool ignoreCase = false)
|
||||
{
|
||||
if (first.Length != second.Length)
|
||||
return false;
|
||||
|
||||
if (!ignoreCase)
|
||||
return first.SequenceEqual(second);
|
||||
|
||||
fixed (char* fp = &MemoryMarshal.GetReference(first))
|
||||
fixed (char* sp = &MemoryMarshal.GetReference(second))
|
||||
{
|
||||
char* f = fp;
|
||||
char* s = sp;
|
||||
|
||||
for (int i = 0; i < first.Length; i++)
|
||||
{
|
||||
if (*f != *s && char.ToUpperInvariant(*f) != char.ToUpperInvariant(*s))
|
||||
return false;
|
||||
f++;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace System.IO
|
||||
{
|
||||
internal static partial class CharSpanExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static unsafe int CompareOrdinal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, bool ignoreCase = false)
|
||||
{
|
||||
int result = Interop.Kernel32.CompareStringOrdinal(
|
||||
ref MemoryMarshal.GetReference(first),
|
||||
first.Length,
|
||||
ref MemoryMarshal.GetReference(second),
|
||||
second.Length,
|
||||
ignoreCase);
|
||||
|
||||
if (result == 0)
|
||||
throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
|
||||
|
||||
// CSTR_LESS_THAN 1 // string 1 less than string 2
|
||||
// CSTR_EQUAL 2 // string 1 equal to string 2
|
||||
// CSTR_GREATER_THAN 3 // string 1 greater than string 2
|
||||
|
||||
return result - 2;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static bool EqualsOrdinal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, bool ignoreCase = false)
|
||||
{
|
||||
if (first.Length != second.Length)
|
||||
return false;
|
||||
|
||||
if (!ignoreCase)
|
||||
return first.SequenceEqual(second);
|
||||
|
||||
return CompareOrdinal(first, second, ignoreCase) == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace System.IO
|
||||
{
|
||||
internal static partial class CharSpanExtensions
|
||||
{
|
||||
public static bool EndsWithOrdinal(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, bool ignoreCase = false)
|
||||
{
|
||||
if (value.Length == 0)
|
||||
return true;
|
||||
else if (value.Length > span.Length)
|
||||
return false;
|
||||
|
||||
span = span.Slice(span.Length - value.Length);
|
||||
|
||||
if (ignoreCase == false)
|
||||
return span.SequenceEqual(value);
|
||||
|
||||
return EqualsOrdinal(span, value, ignoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Security;
|
||||
using System.IO.Enumeration;
|
||||
using System.Linq;
|
||||
|
||||
namespace System.IO
|
||||
{
|
||||
@@ -40,26 +40,7 @@ namespace System.IO
|
||||
return new DirectoryInfo(fullPath, null);
|
||||
}
|
||||
|
||||
// Input to this method should already be fullpath. This method will ensure that we append
|
||||
// the trailing slash only when appropriate.
|
||||
internal static string EnsureTrailingDirectorySeparator(string fullPath)
|
||||
{
|
||||
string fullPathWithTrailingDirectorySeparator;
|
||||
|
||||
if (!PathHelpers.EndsInDirectorySeparator(fullPath))
|
||||
fullPathWithTrailingDirectorySeparator = fullPath + PathHelpers.DirectorySeparatorCharAsString;
|
||||
else
|
||||
fullPathWithTrailingDirectorySeparator = fullPath;
|
||||
|
||||
return fullPathWithTrailingDirectorySeparator;
|
||||
}
|
||||
|
||||
|
||||
// Tests if the given path refers to an existing DirectoryInfo on disk.
|
||||
//
|
||||
// Your application must have Read permission to the directory's
|
||||
// contents.
|
||||
//
|
||||
public static bool Exists(string path)
|
||||
{
|
||||
try
|
||||
@@ -74,8 +55,6 @@ namespace System.IO
|
||||
return FileSystem.DirectoryExists(fullPath);
|
||||
}
|
||||
catch (ArgumentException) { }
|
||||
catch (NotSupportedException) { } // Security can throw this on ":"
|
||||
catch (SecurityException) { }
|
||||
catch (IOException) { }
|
||||
catch (UnauthorizedAccessException) { }
|
||||
|
||||
@@ -148,286 +127,94 @@ namespace System.IO
|
||||
return File.GetLastAccessTimeUtc(path);
|
||||
}
|
||||
|
||||
// Returns an array of filenames in the DirectoryInfo specified by path
|
||||
public static string[] GetFiles(string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
public static string[] GetFiles(string path) => GetFiles(path, "*", enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
return InternalGetFiles(path, "*", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
public static string[] GetFiles(string path, string searchPattern) => GetFiles(path, searchPattern, enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
// Returns an array of Files in the current DirectoryInfo matching the
|
||||
// given search pattern (i.e. "*.txt").
|
||||
public static string[] GetFiles(string path, string searchPattern)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
|
||||
return InternalGetFiles(path, searchPattern, SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
|
||||
// Returns an array of Files in the current DirectoryInfo matching the
|
||||
// given search pattern (i.e. "*.txt") and search option
|
||||
public static string[] GetFiles(string path, string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
|
||||
throw new ArgumentOutOfRangeException(nameof(searchOption), SR.ArgumentOutOfRange_Enum);
|
||||
=> GetFiles(path, searchPattern, EnumerationOptions.FromSearchOption(searchOption));
|
||||
|
||||
return InternalGetFiles(path, searchPattern, searchOption);
|
||||
}
|
||||
public static string[] GetFiles(string path, string searchPattern, EnumerationOptions enumerationOptions)
|
||||
=> InternalEnumeratePaths(path, searchPattern, SearchTarget.Files, enumerationOptions).ToArray();
|
||||
|
||||
// Returns an array of Files in the current DirectoryInfo matching the
|
||||
// given search pattern (i.e. "*.txt") and search option
|
||||
private static string[] InternalGetFiles(string path, string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
Debug.Assert(path != null);
|
||||
Debug.Assert(searchPattern != null);
|
||||
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
|
||||
public static string[] GetDirectories(string path) => GetDirectories(path, "*", enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
return InternalGetFileDirectoryNames(path, path, searchPattern, true, false, searchOption);
|
||||
}
|
||||
public static string[] GetDirectories(string path, string searchPattern) => GetDirectories(path, searchPattern, enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
// Returns an array of Directories in the current directory.
|
||||
public static string[] GetDirectories(string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
|
||||
return InternalGetDirectories(path, "*", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
|
||||
// Returns an array of Directories in the current DirectoryInfo matching the
|
||||
// given search criteria (i.e. "*.txt").
|
||||
public static string[] GetDirectories(string path, string searchPattern)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
|
||||
return InternalGetDirectories(path, searchPattern, SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
|
||||
// Returns an array of Directories in the current DirectoryInfo matching the
|
||||
// given search criteria (i.e. "*.txt").
|
||||
public static string[] GetDirectories(string path, string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
|
||||
throw new ArgumentOutOfRangeException(nameof(searchOption), SR.ArgumentOutOfRange_Enum);
|
||||
=> GetDirectories(path, searchPattern, EnumerationOptions.FromSearchOption(searchOption));
|
||||
|
||||
return InternalGetDirectories(path, searchPattern, searchOption);
|
||||
}
|
||||
public static string[] GetDirectories(string path, string searchPattern, EnumerationOptions enumerationOptions)
|
||||
=> InternalEnumeratePaths(path, searchPattern, SearchTarget.Directories, enumerationOptions).ToArray();
|
||||
|
||||
// Returns an array of Directories in the current DirectoryInfo matching the
|
||||
// given search criteria (i.e. "*.txt").
|
||||
private static string[] InternalGetDirectories(string path, string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
Debug.Assert(path != null);
|
||||
Debug.Assert(searchPattern != null);
|
||||
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
|
||||
public static string[] GetFileSystemEntries(string path) => GetFileSystemEntries(path, "*", enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
return InternalGetFileDirectoryNames(path, path, searchPattern, false, true, searchOption);
|
||||
}
|
||||
public static string[] GetFileSystemEntries(string path, string searchPattern) => GetFileSystemEntries(path, searchPattern, enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
// Returns an array of strongly typed FileSystemInfo entries in the path
|
||||
public static string[] GetFileSystemEntries(string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
|
||||
return InternalGetFileSystemEntries(path, "*", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
|
||||
// Returns an array of strongly typed FileSystemInfo entries in the path with the
|
||||
// given search criteria (i.e. "*.txt"). We disallow .. as a part of the search criteria
|
||||
public static string[] GetFileSystemEntries(string path, string searchPattern)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
|
||||
return InternalGetFileSystemEntries(path, searchPattern, SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
|
||||
// Returns an array of strongly typed FileSystemInfo entries in the path with the
|
||||
// given search criteria (i.e. "*.txt"). We disallow .. as a part of the search criteria
|
||||
public static string[] GetFileSystemEntries(string path, string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
|
||||
throw new ArgumentOutOfRangeException(nameof(searchOption), SR.ArgumentOutOfRange_Enum);
|
||||
=> GetFileSystemEntries(path, searchPattern, EnumerationOptions.FromSearchOption(searchOption));
|
||||
|
||||
return InternalGetFileSystemEntries(path, searchPattern, searchOption);
|
||||
}
|
||||
public static string[] GetFileSystemEntries(string path, string searchPattern, EnumerationOptions enumerationOptions)
|
||||
=> InternalEnumeratePaths(path, searchPattern, SearchTarget.Both, enumerationOptions).ToArray();
|
||||
|
||||
private static string[] InternalGetFileSystemEntries(string path, string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
Debug.Assert(path != null);
|
||||
Debug.Assert(searchPattern != null);
|
||||
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
|
||||
|
||||
return InternalGetFileDirectoryNames(path, path, searchPattern, true, true, searchOption);
|
||||
}
|
||||
|
||||
// Returns fully qualified user path of dirs/files that matches the search parameters.
|
||||
// For recursive search this method will search through all the sub dirs and execute
|
||||
// the given search criteria against every dir.
|
||||
// For all the dirs/files returned, it will then demand path discovery permission for
|
||||
// their parent folders (it will avoid duplicate permission checks)
|
||||
internal static string[] InternalGetFileDirectoryNames(string path, string userPathOriginal, string searchPattern, bool includeFiles, bool includeDirs, SearchOption searchOption)
|
||||
{
|
||||
Debug.Assert(path != null);
|
||||
Debug.Assert(userPathOriginal != null);
|
||||
Debug.Assert(searchPattern != null);
|
||||
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
|
||||
|
||||
IEnumerable<string> enumerable = FileSystem.EnumeratePaths(path, searchPattern, searchOption,
|
||||
(includeFiles ? SearchTarget.Files : 0) | (includeDirs ? SearchTarget.Directories : 0));
|
||||
return EnumerableHelpers.ToArray(enumerable);
|
||||
}
|
||||
|
||||
public static IEnumerable<string> EnumerateDirectories(string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
|
||||
return InternalEnumerateDirectories(path, "*", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
|
||||
public static IEnumerable<string> EnumerateDirectories(string path, string searchPattern)
|
||||
internal static IEnumerable<string> InternalEnumeratePaths(
|
||||
string path,
|
||||
string searchPattern,
|
||||
SearchTarget searchTarget,
|
||||
EnumerationOptions options)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
|
||||
return InternalEnumerateDirectories(path, searchPattern, SearchOption.TopDirectoryOnly);
|
||||
FileSystemEnumerableFactory.NormalizeInputs(ref path, ref searchPattern, options);
|
||||
|
||||
switch (searchTarget)
|
||||
{
|
||||
case SearchTarget.Files:
|
||||
return FileSystemEnumerableFactory.UserFiles(path, searchPattern, options);
|
||||
case SearchTarget.Directories:
|
||||
return FileSystemEnumerableFactory.UserDirectories(path, searchPattern, options);
|
||||
case SearchTarget.Both:
|
||||
return FileSystemEnumerableFactory.UserEntries(path, searchPattern, options);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(searchTarget));
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<string> EnumerateDirectories(string path) => EnumerateDirectories(path, "*", enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
public static IEnumerable<string> EnumerateDirectories(string path, string searchPattern) => EnumerateDirectories(path, searchPattern, enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
public static IEnumerable<string> EnumerateDirectories(string path, string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
|
||||
throw new ArgumentOutOfRangeException(nameof(searchOption), SR.ArgumentOutOfRange_Enum);
|
||||
=> EnumerateDirectories(path, searchPattern, EnumerationOptions.FromSearchOption(searchOption));
|
||||
|
||||
return InternalEnumerateDirectories(path, searchPattern, searchOption);
|
||||
}
|
||||
public static IEnumerable<string> EnumerateDirectories(string path, string searchPattern, EnumerationOptions enumerationOptions)
|
||||
=> InternalEnumeratePaths(path, searchPattern, SearchTarget.Directories, enumerationOptions);
|
||||
|
||||
private static IEnumerable<string> InternalEnumerateDirectories(string path, string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
Debug.Assert(path != null);
|
||||
Debug.Assert(searchPattern != null);
|
||||
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
|
||||
|
||||
return EnumerateFileSystemNames(path, searchPattern, searchOption, false, true);
|
||||
}
|
||||
|
||||
public static IEnumerable<string> EnumerateFiles(string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
|
||||
return InternalEnumerateFiles(path, "*", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
public static IEnumerable<string> EnumerateFiles(string path) => EnumerateFiles(path, "*", enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
public static IEnumerable<string> EnumerateFiles(string path, string searchPattern)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
|
||||
return InternalEnumerateFiles(path, searchPattern, SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
=> EnumerateFiles(path, searchPattern, enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
public static IEnumerable<string> EnumerateFiles(string path, string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
|
||||
throw new ArgumentOutOfRangeException(nameof(searchOption), SR.ArgumentOutOfRange_Enum);
|
||||
=> EnumerateFiles(path, searchPattern, EnumerationOptions.FromSearchOption(searchOption));
|
||||
|
||||
return InternalEnumerateFiles(path, searchPattern, searchOption);
|
||||
}
|
||||
|
||||
private static IEnumerable<string> InternalEnumerateFiles(string path, string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
Debug.Assert(path != null);
|
||||
Debug.Assert(searchPattern != null);
|
||||
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
|
||||
|
||||
return EnumerateFileSystemNames(path, searchPattern, searchOption, true, false);
|
||||
}
|
||||
public static IEnumerable<string> EnumerateFiles(string path, string searchPattern, EnumerationOptions enumerationOptions)
|
||||
=> InternalEnumeratePaths(path, searchPattern, SearchTarget.Files, enumerationOptions);
|
||||
|
||||
public static IEnumerable<string> EnumerateFileSystemEntries(string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
|
||||
return InternalEnumerateFileSystemEntries(path, "*", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
=> EnumerateFileSystemEntries(path, "*", enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
public static IEnumerable<string> EnumerateFileSystemEntries(string path, string searchPattern)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
|
||||
return InternalEnumerateFileSystemEntries(path, searchPattern, SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
=> EnumerateFileSystemEntries(path, searchPattern, enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
public static IEnumerable<string> EnumerateFileSystemEntries(string path, string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
|
||||
throw new ArgumentOutOfRangeException(nameof(searchOption), SR.ArgumentOutOfRange_Enum);
|
||||
=> EnumerateFileSystemEntries(path, searchPattern, EnumerationOptions.FromSearchOption(searchOption));
|
||||
|
||||
return InternalEnumerateFileSystemEntries(path, searchPattern, searchOption);
|
||||
}
|
||||
|
||||
private static IEnumerable<string> InternalEnumerateFileSystemEntries(string path, string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
Debug.Assert(path != null);
|
||||
Debug.Assert(searchPattern != null);
|
||||
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
|
||||
|
||||
return EnumerateFileSystemNames(path, searchPattern, searchOption, true, true);
|
||||
}
|
||||
|
||||
private static IEnumerable<string> EnumerateFileSystemNames(string path, string searchPattern, SearchOption searchOption,
|
||||
bool includeFiles, bool includeDirs)
|
||||
{
|
||||
Debug.Assert(path != null);
|
||||
Debug.Assert(searchPattern != null);
|
||||
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
|
||||
|
||||
return FileSystem.EnumeratePaths(path, searchPattern, searchOption,
|
||||
(includeFiles ? SearchTarget.Files : 0) | (includeDirs ? SearchTarget.Directories : 0));
|
||||
}
|
||||
public static IEnumerable<string> EnumerateFileSystemEntries(string path, string searchPattern, EnumerationOptions enumerationOptions)
|
||||
=> InternalEnumeratePaths(path, searchPattern, SearchTarget.Both, enumerationOptions);
|
||||
|
||||
public static string GetDirectoryRoot(string path)
|
||||
{
|
||||
@@ -446,17 +233,7 @@ namespace System.IO
|
||||
return path.Substring(0, PathInternal.GetRootLength(path));
|
||||
}
|
||||
|
||||
/*===============================CurrentDirectory===============================
|
||||
**Action: Provides a getter and setter for the current directory. The original
|
||||
** current DirectoryInfo is the one from which the process was started.
|
||||
**Returns: The current DirectoryInfo (from the getter). Void from the setter.
|
||||
**Arguments: The current DirectoryInfo to which to switch to the setter.
|
||||
**Exceptions:
|
||||
==============================================================================*/
|
||||
public static string GetCurrentDirectory()
|
||||
{
|
||||
return FileSystem.GetCurrentDirectory();
|
||||
}
|
||||
public static string GetCurrentDirectory() => Environment.CurrentDirectory;
|
||||
|
||||
public static void SetCurrentDirectory(string path)
|
||||
{
|
||||
@@ -465,9 +242,7 @@ namespace System.IO
|
||||
if (path.Length == 0)
|
||||
throw new ArgumentException(SR.Argument_PathEmpty, nameof(path));
|
||||
|
||||
string fulldestDirName = Path.GetFullPath(path);
|
||||
|
||||
FileSystem.SetCurrentDirectory(fulldestDirName);
|
||||
Environment.CurrentDirectory = Path.GetFullPath(path);
|
||||
}
|
||||
|
||||
public static void Move(string sourceDirName, string destDirName)
|
||||
@@ -483,10 +258,10 @@ namespace System.IO
|
||||
throw new ArgumentException(SR.Argument_EmptyFileName, nameof(destDirName));
|
||||
|
||||
string fullsourceDirName = Path.GetFullPath(sourceDirName);
|
||||
string sourcePath = EnsureTrailingDirectorySeparator(fullsourceDirName);
|
||||
string sourcePath = PathInternal.EnsureTrailingSeparator(fullsourceDirName);
|
||||
|
||||
string fulldestDirName = Path.GetFullPath(destDirName);
|
||||
string destPath = EnsureTrailingDirectorySeparator(fulldestDirName);
|
||||
string destPath = PathInternal.EnsureTrailingSeparator(fulldestDirName);
|
||||
|
||||
StringComparison pathComparison = PathInternal.StringComparison;
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace System.IO
|
||||
{
|
||||
partial class DirectoryInfo
|
||||
{
|
||||
internal unsafe DirectoryInfo(string fullPath, string fileName, ref RawFindData findData)
|
||||
: this(fullPath, fileName: fileName, isNormalized: true)
|
||||
{
|
||||
Debug.Assert(fileName.Equals(Path.GetFileName(fullPath)));
|
||||
Init(findData._info);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,17 +4,17 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Enumeration;
|
||||
using System.Linq;
|
||||
|
||||
namespace System.IO
|
||||
{
|
||||
[Serializable]
|
||||
public sealed partial class DirectoryInfo : FileSystemInfo
|
||||
{
|
||||
private string _name;
|
||||
|
||||
public DirectoryInfo(string path)
|
||||
{
|
||||
Init(originalPath: PathHelpers.ShouldReviseDirectoryPathToCurrent(path) ? "." : path,
|
||||
Init(originalPath: path,
|
||||
fullPath: Path.GetFullPath(path),
|
||||
isNormalized: true);
|
||||
}
|
||||
@@ -30,328 +30,155 @@ namespace System.IO
|
||||
OriginalPath = originalPath ?? throw new ArgumentNullException("path");
|
||||
|
||||
fullPath = fullPath ?? originalPath;
|
||||
Debug.Assert(!isNormalized || !PathInternal.IsPartiallyQualified(fullPath), "should be fully qualified if normalized");
|
||||
fullPath = isNormalized ? fullPath : Path.GetFullPath(fullPath);
|
||||
|
||||
_name = fileName ?? (PathHelpers.IsRoot(fullPath) ?
|
||||
_name = fileName ?? (PathInternal.IsRoot(fullPath) ?
|
||||
fullPath :
|
||||
Path.GetFileName(PathHelpers.TrimEndingDirectorySeparator(fullPath)));
|
||||
Path.GetFileName(PathInternal.TrimEndingDirectorySeparator(fullPath.AsSpan()))).ToString();
|
||||
|
||||
FullPath = fullPath;
|
||||
DisplayPath = PathHelpers.ShouldReviseDirectoryPathToCurrent(originalPath) ? "." : originalPath;
|
||||
}
|
||||
|
||||
public override string Name => _name;
|
||||
|
||||
public DirectoryInfo Parent
|
||||
{
|
||||
get
|
||||
{
|
||||
string s = FullPath;
|
||||
|
||||
// FullPath might end in either "parent\child" or "parent\child", and in either case we want
|
||||
// FullPath might end in either "parent\child" or "parent\child\", and in either case we want
|
||||
// the parent of child, not the child. Trim off an ending directory separator if there is one,
|
||||
// but don't mangle the root.
|
||||
if (!PathHelpers.IsRoot(s))
|
||||
{
|
||||
s = PathHelpers.TrimEndingDirectorySeparator(s);
|
||||
}
|
||||
|
||||
string parentName = Path.GetDirectoryName(s);
|
||||
string parentName = Path.GetDirectoryName(PathInternal.IsRoot(FullPath) ? FullPath : PathInternal.TrimEndingDirectorySeparator(FullPath));
|
||||
return parentName != null ?
|
||||
new DirectoryInfo(parentName, null) :
|
||||
null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public DirectoryInfo CreateSubdirectory(string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (PathInternal.IsEffectivelyEmpty(path))
|
||||
throw new ArgumentException(SR.Argument_PathEmpty, nameof(path));
|
||||
if (Path.IsPathRooted(path))
|
||||
throw new ArgumentException(SR.Arg_Path2IsRooted, nameof(path));
|
||||
|
||||
return CreateSubdirectoryHelper(path);
|
||||
}
|
||||
string fullPath = Path.GetFullPath(Path.Combine(FullPath, path));
|
||||
|
||||
private DirectoryInfo CreateSubdirectoryHelper(string path)
|
||||
{
|
||||
Debug.Assert(path != null);
|
||||
|
||||
PathHelpers.ThrowIfEmptyOrRootedPath(path);
|
||||
|
||||
string newDirs = Path.Combine(FullPath, path);
|
||||
string fullPath = Path.GetFullPath(newDirs);
|
||||
|
||||
if (0 != string.Compare(FullPath, 0, fullPath, 0, FullPath.Length, PathInternal.StringComparison))
|
||||
if (fullPath.Length < FullPath.Length
|
||||
|| (fullPath.Length > FullPath.Length && !PathInternal.IsDirectorySeparator(fullPath[FullPath.Length]))
|
||||
|| string.Compare(FullPath, 0, fullPath, 0, FullPath.Length, PathInternal.StringComparison) != 0)
|
||||
{
|
||||
throw new ArgumentException(SR.Format(SR.Argument_InvalidSubPath, path, DisplayPath), nameof(path));
|
||||
throw new ArgumentException(SR.Format(SR.Argument_InvalidSubPath, path, FullPath), nameof(path));
|
||||
}
|
||||
|
||||
FileSystem.CreateDirectory(fullPath);
|
||||
|
||||
// Check for read permission to directory we hand back by calling this constructor.
|
||||
return new DirectoryInfo(fullPath);
|
||||
}
|
||||
|
||||
public void Create()
|
||||
{
|
||||
FileSystem.CreateDirectory(FullPath);
|
||||
}
|
||||
|
||||
// Tests if the given path refers to an existing DirectoryInfo on disk.
|
||||
//
|
||||
// Your application must have Read permission to the directory's
|
||||
// contents.
|
||||
//
|
||||
public override bool Exists
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return ExistsCore;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns an array of Files in the current DirectoryInfo matching the
|
||||
// given search criteria (i.e. "*.txt").
|
||||
public FileInfo[] GetFiles(string searchPattern)
|
||||
{
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
|
||||
return InternalGetFiles(searchPattern, SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
|
||||
// Returns an array of Files in the current DirectoryInfo matching the
|
||||
// given search criteria (i.e. "*.txt").
|
||||
public FileInfo[] GetFiles(string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
|
||||
throw new ArgumentOutOfRangeException(nameof(searchOption), SR.ArgumentOutOfRange_Enum);
|
||||
|
||||
return InternalGetFiles(searchPattern, searchOption);
|
||||
}
|
||||
|
||||
// Returns an array of Files in the current DirectoryInfo matching the
|
||||
// given search criteria (i.e. "*.txt").
|
||||
private FileInfo[] InternalGetFiles(string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
Debug.Assert(searchPattern != null);
|
||||
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
|
||||
|
||||
IEnumerable<FileInfo> enumerable = (IEnumerable<FileInfo>)FileSystem.EnumerateFileSystemInfos(FullPath, searchPattern, searchOption, SearchTarget.Files);
|
||||
return EnumerableHelpers.ToArray(enumerable);
|
||||
}
|
||||
public void Create() => FileSystem.CreateDirectory(FullPath);
|
||||
|
||||
// Returns an array of Files in the DirectoryInfo specified by path
|
||||
public FileInfo[] GetFiles()
|
||||
{
|
||||
return InternalGetFiles("*", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
public FileInfo[] GetFiles() => GetFiles("*", enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
// Returns an array of Directories in the current directory.
|
||||
public DirectoryInfo[] GetDirectories()
|
||||
{
|
||||
return InternalGetDirectories("*", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
// Returns an array of Files in the current DirectoryInfo matching the
|
||||
// given search criteria (i.e. "*.txt").
|
||||
public FileInfo[] GetFiles(string searchPattern) => GetFiles(searchPattern, enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
public FileInfo[] GetFiles(string searchPattern, SearchOption searchOption)
|
||||
=> GetFiles(searchPattern, EnumerationOptions.FromSearchOption(searchOption));
|
||||
|
||||
public FileInfo[] GetFiles(string searchPattern, EnumerationOptions enumerationOptions)
|
||||
=> ((IEnumerable<FileInfo>)InternalEnumerateInfos(FullPath, searchPattern, SearchTarget.Files, enumerationOptions)).ToArray();
|
||||
|
||||
// Returns an array of strongly typed FileSystemInfo entries which will contain a listing
|
||||
// of all the files and directories.
|
||||
public FileSystemInfo[] GetFileSystemInfos() => GetFileSystemInfos("*", enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
// Returns an array of strongly typed FileSystemInfo entries in the path with the
|
||||
// given search criteria (i.e. "*.txt").
|
||||
public FileSystemInfo[] GetFileSystemInfos(string searchPattern)
|
||||
{
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
=> GetFileSystemInfos(searchPattern, enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
return InternalGetFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
|
||||
// Returns an array of strongly typed FileSystemInfo entries in the path with the
|
||||
// given search criteria (i.e. "*.txt").
|
||||
public FileSystemInfo[] GetFileSystemInfos(string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
|
||||
throw new ArgumentOutOfRangeException(nameof(searchOption), SR.ArgumentOutOfRange_Enum);
|
||||
=> GetFileSystemInfos(searchPattern, EnumerationOptions.FromSearchOption(searchOption));
|
||||
|
||||
return InternalGetFileSystemInfos(searchPattern, searchOption);
|
||||
}
|
||||
public FileSystemInfo[] GetFileSystemInfos(string searchPattern, EnumerationOptions enumerationOptions)
|
||||
=> InternalEnumerateInfos(FullPath, searchPattern, SearchTarget.Both, enumerationOptions).ToArray();
|
||||
|
||||
// Returns an array of strongly typed FileSystemInfo entries in the path with the
|
||||
// given search criteria (i.e. "*.txt").
|
||||
private FileSystemInfo[] InternalGetFileSystemInfos(string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
Debug.Assert(searchPattern != null);
|
||||
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
|
||||
|
||||
IEnumerable<FileSystemInfo> enumerable = FileSystem.EnumerateFileSystemInfos(FullPath, searchPattern, searchOption, SearchTarget.Both);
|
||||
return EnumerableHelpers.ToArray(enumerable);
|
||||
}
|
||||
|
||||
// Returns an array of strongly typed FileSystemInfo entries which will contain a listing
|
||||
// of all the files and directories.
|
||||
public FileSystemInfo[] GetFileSystemInfos()
|
||||
{
|
||||
return InternalGetFileSystemInfos("*", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
// Returns an array of Directories in the current directory.
|
||||
public DirectoryInfo[] GetDirectories() => GetDirectories("*", enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
// Returns an array of Directories in the current DirectoryInfo matching the
|
||||
// given search criteria (i.e. "System*" could match the System & System32
|
||||
// directories).
|
||||
public DirectoryInfo[] GetDirectories(string searchPattern)
|
||||
{
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
// given search criteria (i.e. "System*" could match the System & System32 directories).
|
||||
public DirectoryInfo[] GetDirectories(string searchPattern) => GetDirectories(searchPattern, enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
return InternalGetDirectories(searchPattern, SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
|
||||
// Returns an array of Directories in the current DirectoryInfo matching the
|
||||
// given search criteria (i.e. "System*" could match the System & System32
|
||||
// directories).
|
||||
public DirectoryInfo[] GetDirectories(string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
|
||||
throw new ArgumentOutOfRangeException(nameof(searchOption), SR.ArgumentOutOfRange_Enum);
|
||||
=> GetDirectories(searchPattern, EnumerationOptions.FromSearchOption(searchOption));
|
||||
|
||||
return InternalGetDirectories(searchPattern, searchOption);
|
||||
}
|
||||
|
||||
// Returns an array of Directories in the current DirectoryInfo matching the
|
||||
// given search criteria (i.e. "System*" could match the System & System32
|
||||
// directories).
|
||||
private DirectoryInfo[] InternalGetDirectories(string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
Debug.Assert(searchPattern != null);
|
||||
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
|
||||
|
||||
IEnumerable<DirectoryInfo> enumerable = (IEnumerable<DirectoryInfo>)FileSystem.EnumerateFileSystemInfos(FullPath, searchPattern, searchOption, SearchTarget.Directories);
|
||||
return EnumerableHelpers.ToArray(enumerable);
|
||||
}
|
||||
public DirectoryInfo[] GetDirectories(string searchPattern, EnumerationOptions enumerationOptions)
|
||||
=> ((IEnumerable<DirectoryInfo>)InternalEnumerateInfos(FullPath, searchPattern, SearchTarget.Directories, enumerationOptions)).ToArray();
|
||||
|
||||
public IEnumerable<DirectoryInfo> EnumerateDirectories()
|
||||
{
|
||||
return InternalEnumerateDirectories("*", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
=> EnumerateDirectories("*", enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
public IEnumerable<DirectoryInfo> EnumerateDirectories(string searchPattern)
|
||||
{
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
|
||||
return InternalEnumerateDirectories(searchPattern, SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
=> EnumerateDirectories(searchPattern, enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
public IEnumerable<DirectoryInfo> EnumerateDirectories(string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
|
||||
throw new ArgumentOutOfRangeException(nameof(searchOption), SR.ArgumentOutOfRange_Enum);
|
||||
=> EnumerateDirectories(searchPattern, EnumerationOptions.FromSearchOption(searchOption));
|
||||
|
||||
return InternalEnumerateDirectories(searchPattern, searchOption);
|
||||
}
|
||||
|
||||
private IEnumerable<DirectoryInfo> InternalEnumerateDirectories(string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
Debug.Assert(searchPattern != null);
|
||||
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
|
||||
|
||||
return (IEnumerable<DirectoryInfo>)FileSystem.EnumerateFileSystemInfos(FullPath, searchPattern, searchOption, SearchTarget.Directories);
|
||||
}
|
||||
public IEnumerable<DirectoryInfo> EnumerateDirectories(string searchPattern, EnumerationOptions enumerationOptions)
|
||||
=> (IEnumerable<DirectoryInfo>)InternalEnumerateInfos(FullPath, searchPattern, SearchTarget.Directories, enumerationOptions);
|
||||
|
||||
public IEnumerable<FileInfo> EnumerateFiles()
|
||||
{
|
||||
return InternalEnumerateFiles("*", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
=> EnumerateFiles("*", enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
public IEnumerable<FileInfo> EnumerateFiles(string searchPattern)
|
||||
{
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
|
||||
return InternalEnumerateFiles(searchPattern, SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
public IEnumerable<FileInfo> EnumerateFiles(string searchPattern) => EnumerateFiles(searchPattern, enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
public IEnumerable<FileInfo> EnumerateFiles(string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
|
||||
throw new ArgumentOutOfRangeException(nameof(searchOption), SR.ArgumentOutOfRange_Enum);
|
||||
=> EnumerateFiles(searchPattern, EnumerationOptions.FromSearchOption(searchOption));
|
||||
|
||||
return InternalEnumerateFiles(searchPattern, searchOption);
|
||||
}
|
||||
public IEnumerable<FileInfo> EnumerateFiles(string searchPattern, EnumerationOptions enumerationOptions)
|
||||
=> (IEnumerable<FileInfo>)InternalEnumerateInfos(FullPath, searchPattern, SearchTarget.Files, enumerationOptions);
|
||||
|
||||
private IEnumerable<FileInfo> InternalEnumerateFiles(string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
Debug.Assert(searchPattern != null);
|
||||
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
|
||||
|
||||
return (IEnumerable<FileInfo>)FileSystem.EnumerateFileSystemInfos(FullPath, searchPattern, searchOption, SearchTarget.Files);
|
||||
}
|
||||
|
||||
public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos()
|
||||
{
|
||||
return InternalEnumerateFileSystemInfos("*", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos() => EnumerateFileSystemInfos("*", enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos(string searchPattern)
|
||||
{
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
|
||||
return InternalEnumerateFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
=> EnumerateFileSystemInfos(searchPattern, enumerationOptions: EnumerationOptions.Compatible);
|
||||
|
||||
public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos(string searchPattern, SearchOption searchOption)
|
||||
=> EnumerateFileSystemInfos(searchPattern, EnumerationOptions.FromSearchOption(searchOption));
|
||||
|
||||
public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos(string searchPattern, EnumerationOptions enumerationOptions)
|
||||
=> InternalEnumerateInfos(FullPath, searchPattern, SearchTarget.Both, enumerationOptions);
|
||||
|
||||
internal static IEnumerable<FileSystemInfo> InternalEnumerateInfos(
|
||||
string path,
|
||||
string searchPattern,
|
||||
SearchTarget searchTarget,
|
||||
EnumerationOptions options)
|
||||
{
|
||||
Debug.Assert(path != null);
|
||||
if (searchPattern == null)
|
||||
throw new ArgumentNullException(nameof(searchPattern));
|
||||
if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
|
||||
throw new ArgumentOutOfRangeException(nameof(searchOption), SR.ArgumentOutOfRange_Enum);
|
||||
|
||||
return InternalEnumerateFileSystemInfos(searchPattern, searchOption);
|
||||
}
|
||||
FileSystemEnumerableFactory.NormalizeInputs(ref path, ref searchPattern, options);
|
||||
|
||||
private IEnumerable<FileSystemInfo> InternalEnumerateFileSystemInfos(string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
Debug.Assert(searchPattern != null);
|
||||
Debug.Assert(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
|
||||
|
||||
return FileSystem.EnumerateFileSystemInfos(FullPath, searchPattern, searchOption, SearchTarget.Both);
|
||||
}
|
||||
|
||||
// Returns the root portion of the given path. The resulting string
|
||||
// consists of those rightmost characters of the path that constitute the
|
||||
// root of the path. Possible patterns for the resulting string are: An
|
||||
// empty string (a relative path on the current drive), "\" (an absolute
|
||||
// path on the current drive), "X:" (a relative path on a given drive,
|
||||
// where X is the drive letter), "X:\" (an absolute path on a given drive),
|
||||
// and "\\server\share" (a UNC path for a given server and share name).
|
||||
// The resulting string is null if path is null.
|
||||
//
|
||||
|
||||
public DirectoryInfo Root
|
||||
{
|
||||
get
|
||||
switch (searchTarget)
|
||||
{
|
||||
string rootPath = Path.GetPathRoot(FullPath);
|
||||
|
||||
return new DirectoryInfo(rootPath);
|
||||
case SearchTarget.Directories:
|
||||
return FileSystemEnumerableFactory.DirectoryInfos(path, searchPattern, options);
|
||||
case SearchTarget.Files:
|
||||
return FileSystemEnumerableFactory.FileInfos(path, searchPattern, options);
|
||||
case SearchTarget.Both:
|
||||
return FileSystemEnumerableFactory.FileSystemInfos(path, searchPattern, options);
|
||||
default:
|
||||
throw new ArgumentException(SR.ArgumentOutOfRange_Enum, nameof(searchTarget));
|
||||
}
|
||||
}
|
||||
|
||||
public DirectoryInfo Root => new DirectoryInfo(Path.GetPathRoot(FullPath));
|
||||
|
||||
public void MoveTo(string destDirName)
|
||||
{
|
||||
if (destDirName == null)
|
||||
@@ -360,24 +187,17 @@ namespace System.IO
|
||||
throw new ArgumentException(SR.Argument_EmptyFileName, nameof(destDirName));
|
||||
|
||||
string destination = Path.GetFullPath(destDirName);
|
||||
string destinationWithSeparator = destination;
|
||||
if (destinationWithSeparator[destinationWithSeparator.Length - 1] != Path.DirectorySeparatorChar)
|
||||
destinationWithSeparator = destinationWithSeparator + PathHelpers.DirectorySeparatorCharAsString;
|
||||
|
||||
string fullSourcePath;
|
||||
if (FullPath.Length > 0 && FullPath[FullPath.Length - 1] == Path.DirectorySeparatorChar)
|
||||
fullSourcePath = FullPath;
|
||||
else
|
||||
fullSourcePath = FullPath + PathHelpers.DirectorySeparatorCharAsString;
|
||||
string destinationWithSeparator = PathInternal.EnsureTrailingSeparator(destination);
|
||||
string sourceWithSeparator = PathInternal.EnsureTrailingSeparator(FullPath);
|
||||
|
||||
StringComparison pathComparison = PathInternal.StringComparison;
|
||||
if (string.Equals(fullSourcePath, destinationWithSeparator, pathComparison))
|
||||
if (string.Equals(sourceWithSeparator, destinationWithSeparator, PathInternal.StringComparison))
|
||||
throw new IOException(SR.IO_SourceDestMustBeDifferent);
|
||||
|
||||
string sourceRoot = Path.GetPathRoot(fullSourcePath);
|
||||
string sourceRoot = Path.GetPathRoot(sourceWithSeparator);
|
||||
string destinationRoot = Path.GetPathRoot(destinationWithSeparator);
|
||||
|
||||
if (!string.Equals(sourceRoot, destinationRoot, pathComparison))
|
||||
if (!string.Equals(sourceRoot, destinationRoot, PathInternal.StringComparison))
|
||||
throw new IOException(SR.IO_SourceDestMustHaveSameRoot);
|
||||
|
||||
// Windows will throw if the source file/directory doesn't exist, we preemptively check
|
||||
@@ -385,7 +205,7 @@ namespace System.IO
|
||||
if (!Exists && !FileSystem.FileExists(FullPath))
|
||||
throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, FullPath));
|
||||
|
||||
if (FileSystem.DirectoryExists(destinationWithSeparator))
|
||||
if (FileSystem.DirectoryExists(destination))
|
||||
throw new IOException(SR.Format(SR.IO_AlreadyExists_Name, destinationWithSeparator));
|
||||
|
||||
FileSystem.MoveDirectory(FullPath, destination);
|
||||
@@ -399,22 +219,8 @@ namespace System.IO
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
public override void Delete()
|
||||
{
|
||||
FileSystem.RemoveDirectory(FullPath, false);
|
||||
}
|
||||
public override void Delete() => FileSystem.RemoveDirectory(FullPath, recursive: false);
|
||||
|
||||
public void Delete(bool recursive)
|
||||
{
|
||||
FileSystem.RemoveDirectory(FullPath, recursive);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the original path. Use FullPath or Name properties for the path / directory name.
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
return DisplayPath;
|
||||
}
|
||||
public void Delete(bool recursive) => FileSystem.RemoveDirectory(FullPath, recursive);
|
||||
}
|
||||
}
|
||||
|
||||
150
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.Unix.cs
vendored
Normal file
150
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.Unix.cs
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace System.IO.Enumeration
|
||||
{
|
||||
/// <summary>
|
||||
/// Lower level view of FileSystemInfo used for processing and filtering find results.
|
||||
/// </summary>
|
||||
public unsafe ref partial struct FileSystemEntry
|
||||
{
|
||||
private const int FileNameBufferSize = 256;
|
||||
internal Interop.Sys.DirectoryEntry _directoryEntry;
|
||||
private FileStatus _status;
|
||||
private Span<char> _pathBuffer;
|
||||
private ReadOnlySpan<char> _fullPath;
|
||||
private ReadOnlySpan<char> _fileName;
|
||||
private fixed char _fileNameBuffer[FileNameBufferSize];
|
||||
private FileAttributes _initialAttributes;
|
||||
|
||||
internal static FileAttributes Initialize(
|
||||
ref FileSystemEntry entry,
|
||||
Interop.Sys.DirectoryEntry directoryEntry,
|
||||
ReadOnlySpan<char> directory,
|
||||
ReadOnlySpan<char> rootDirectory,
|
||||
ReadOnlySpan<char> originalRootDirectory,
|
||||
Span<char> pathBuffer)
|
||||
{
|
||||
entry._directoryEntry = directoryEntry;
|
||||
entry.Directory = directory;
|
||||
entry.RootDirectory = rootDirectory;
|
||||
entry.OriginalRootDirectory = originalRootDirectory;
|
||||
entry._pathBuffer = pathBuffer;
|
||||
entry._fullPath = ReadOnlySpan<char>.Empty;
|
||||
entry._fileName = ReadOnlySpan<char>.Empty;
|
||||
|
||||
// IMPORTANT: Attribute logic must match the logic in FileStatus
|
||||
|
||||
bool isDirectory = false;
|
||||
if (directoryEntry.InodeType == Interop.Sys.NodeType.DT_DIR)
|
||||
{
|
||||
// We know it's a directory.
|
||||
isDirectory = true;
|
||||
}
|
||||
else if ((directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK
|
||||
|| directoryEntry.InodeType == Interop.Sys.NodeType.DT_UNKNOWN)
|
||||
&& (Interop.Sys.Stat(entry.FullPath, out Interop.Sys.FileStatus targetStatus) >= 0
|
||||
|| Interop.Sys.LStat(entry.FullPath, out targetStatus) >= 0))
|
||||
{
|
||||
// Symlink or unknown: Stat to it to see if we can resolve it to a directory. If Stat fails,
|
||||
// it could be because the symlink is broken, we don't have permissions, etc., in which
|
||||
// case fall back to using LStat to evaluate based on the symlink itself.
|
||||
isDirectory = (targetStatus.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR;
|
||||
}
|
||||
|
||||
entry._status = default;
|
||||
FileStatus.Initialize(ref entry._status, isDirectory);
|
||||
|
||||
FileAttributes attributes = default;
|
||||
if (directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK)
|
||||
attributes |= FileAttributes.ReparsePoint;
|
||||
if (isDirectory)
|
||||
attributes |= FileAttributes.Directory;
|
||||
if (directoryEntry.Name[0] == '.')
|
||||
attributes |= FileAttributes.Hidden;
|
||||
|
||||
if (attributes == default)
|
||||
attributes = FileAttributes.Normal;
|
||||
|
||||
entry._initialAttributes = attributes;
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private ReadOnlySpan<char> FullPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_fullPath.Length == 0)
|
||||
{
|
||||
Debug.Assert(Directory.Length + FileName.Length < _pathBuffer.Length,
|
||||
$"directory ({Directory.Length} chars) & name ({Directory.Length} chars) too long for buffer ({_pathBuffer.Length} chars)");
|
||||
Path.TryJoin(Directory, FileName, _pathBuffer, out int charsWritten);
|
||||
Debug.Assert(charsWritten > 0, "didn't write any chars to buffer");
|
||||
_fullPath = _pathBuffer.Slice(0, charsWritten);
|
||||
}
|
||||
return _fullPath;
|
||||
}
|
||||
}
|
||||
|
||||
public ReadOnlySpan<char> FileName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_directoryEntry.NameLength != 0 && _fileName.Length == 0)
|
||||
{
|
||||
fixed (char* c = _fileNameBuffer)
|
||||
{
|
||||
Span<char> buffer = new Span<char>(c, FileNameBufferSize);
|
||||
_fileName = _directoryEntry.GetName(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
return _fileName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The full path of the directory this entry resides in.
|
||||
/// </summary>
|
||||
public ReadOnlySpan<char> Directory { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The full path of the root directory used for the enumeration.
|
||||
/// </summary>
|
||||
public ReadOnlySpan<char> RootDirectory { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The root directory for the enumeration as specified in the constructor.
|
||||
/// </summary>
|
||||
public ReadOnlySpan<char> OriginalRootDirectory { get; private set; }
|
||||
|
||||
// Windows never fails getting attributes, length, or time as that information comes back
|
||||
// with the native enumeration struct. As such we must not throw here.
|
||||
|
||||
public FileAttributes Attributes
|
||||
// It would be hard to rationalize if the attributes change after our initial find.
|
||||
=> _initialAttributes | (_status.IsReadOnly(FullPath, continueOnError: true) ? FileAttributes.ReadOnly : 0);
|
||||
|
||||
public long Length => _status.GetLength(FullPath, continueOnError: true);
|
||||
public DateTimeOffset CreationTimeUtc => _status.GetCreationTime(FullPath, continueOnError: true);
|
||||
public DateTimeOffset LastAccessTimeUtc => _status.GetLastAccessTime(FullPath, continueOnError: true);
|
||||
public DateTimeOffset LastWriteTimeUtc => _status.GetLastWriteTime(FullPath, continueOnError: true);
|
||||
public bool IsDirectory => _status.InitiallyDirectory;
|
||||
public bool IsHidden => _directoryEntry.Name[0] == '.';
|
||||
|
||||
public FileSystemInfo ToFileSystemInfo()
|
||||
{
|
||||
string fullPath = ToFullPath();
|
||||
return FileSystemInfo.Create(fullPath, new string(FileName), ref _status);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the full path of the find result.
|
||||
/// </summary>
|
||||
public string ToFullPath() =>
|
||||
new string(FullPath);
|
||||
}
|
||||
}
|
||||
84
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.Windows.cs
vendored
Normal file
84
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.Windows.cs
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace System.IO.Enumeration
|
||||
{
|
||||
/// <summary>
|
||||
/// Lower level view of FileSystemInfo used for processing and filtering find results.
|
||||
/// </summary>
|
||||
public unsafe ref partial struct FileSystemEntry
|
||||
{
|
||||
internal static void Initialize(
|
||||
ref FileSystemEntry entry,
|
||||
Interop.NtDll.FILE_FULL_DIR_INFORMATION* info,
|
||||
ReadOnlySpan<char> directory,
|
||||
ReadOnlySpan<char> rootDirectory,
|
||||
ReadOnlySpan<char> originalRootDirectory)
|
||||
{
|
||||
entry._info = info;
|
||||
entry.Directory = directory;
|
||||
entry.RootDirectory = rootDirectory;
|
||||
entry.OriginalRootDirectory = originalRootDirectory;
|
||||
}
|
||||
|
||||
internal unsafe Interop.NtDll.FILE_FULL_DIR_INFORMATION* _info;
|
||||
|
||||
/// <summary>
|
||||
/// The full path of the directory this entry resides in.
|
||||
/// </summary>
|
||||
public ReadOnlySpan<char> Directory { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The full path of the root directory used for the enumeration.
|
||||
/// </summary>
|
||||
public ReadOnlySpan<char> RootDirectory { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The root directory for the enumeration as specified in the constructor.
|
||||
/// </summary>
|
||||
public ReadOnlySpan<char> OriginalRootDirectory { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The file name for this entry.
|
||||
/// </summary>
|
||||
public ReadOnlySpan<char> FileName => _info->FileName;
|
||||
|
||||
/// <summary>
|
||||
/// The attributes for this entry.
|
||||
/// </summary>
|
||||
public FileAttributes Attributes => _info->FileAttributes;
|
||||
|
||||
/// <summary>
|
||||
/// The length of file in bytes.
|
||||
/// </summary>
|
||||
public long Length => _info->EndOfFile;
|
||||
|
||||
/// <summary>
|
||||
/// The creation time for the entry or the oldest available time stamp if the
|
||||
/// operating system does not support creation time stamps.
|
||||
/// </summary>
|
||||
public DateTimeOffset CreationTimeUtc => _info->CreationTime.ToDateTimeOffset();
|
||||
public DateTimeOffset LastAccessTimeUtc => _info->LastAccessTime.ToDateTimeOffset();
|
||||
public DateTimeOffset LastWriteTimeUtc => _info->LastWriteTime.ToDateTimeOffset();
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this entry is a directory.
|
||||
/// </summary>
|
||||
public bool IsDirectory => (Attributes & FileAttributes.Directory) != 0;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the file has the hidden attribute.
|
||||
/// </summary>
|
||||
public bool IsHidden => (Attributes & FileAttributes.Hidden) != 0;
|
||||
|
||||
public FileSystemInfo ToFileSystemInfo()
|
||||
=> FileSystemInfo.Create(Path.Join(Directory, FileName), ref this);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the full path of the find result.
|
||||
/// </summary>
|
||||
public string ToFullPath() =>
|
||||
Path.Join(Directory, FileName);
|
||||
}
|
||||
}
|
||||
43
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.cs
vendored
Normal file
43
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.cs
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace System.IO.Enumeration
|
||||
{
|
||||
public ref partial struct FileSystemEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the full path for find results, based on the initially provided path.
|
||||
/// </summary>
|
||||
public string ToSpecifiedFullPath()
|
||||
{
|
||||
// We want to provide the enumerated segment of the path appended to the originally specified path. This is
|
||||
// the behavior of the various Directory APIs that return a list of strings.
|
||||
//
|
||||
// RootDirectory has the final separator trimmed, OriginalRootDirectory does not. Our legacy behavior would
|
||||
// effectively account for this by appending subdirectory names as it recursed. As such we need to trim one
|
||||
// separator when combining with the relative path (Directory.Slice(RootDirectory.Length)).
|
||||
//
|
||||
// Original => Root => Directory => FileName => relativePath => Specified
|
||||
// C:\foo C:\foo C:\foo bar "" C:\foo\bar
|
||||
// C:\foo\ C:\foo C:\foo bar "" C:\foo\bar
|
||||
// C:\foo/ C:\foo C:\foo bar "" C:\foo/bar
|
||||
// C:\foo\\ C:\foo C:\foo bar "" C:\foo\\bar
|
||||
// C:\foo C:\foo C:\foo\bar jar "bar" C:\foo\bar\jar
|
||||
// C:\foo\ C:\foo C:\foo\bar jar "bar" C:\foo\bar\jar
|
||||
// C:\foo/ C:\foo C:\foo\bar jar "bar" C:\foo/bar\jar
|
||||
|
||||
|
||||
// If we're at the top level directory the Directory and RootDirectory will be identical. As there are no
|
||||
// trailing slashes in play, once we're in a subdirectory, slicing off the root will leave us with an
|
||||
// initial separator. We need to trim that off if it exists, but it isn't needed if the original root
|
||||
// didn't have a separator. Join() would handle it if we did trim it, not doing so is an optimization.
|
||||
|
||||
ReadOnlySpan<char> relativePath = Directory.Slice(RootDirectory.Length);
|
||||
if (PathInternal.EndsInDirectorySeparator(OriginalRootDirectory) && PathInternal.StartsWithDirectorySeparator(relativePath))
|
||||
relativePath = relativePath.Slice(1);
|
||||
|
||||
return Path.Join(OriginalRootDirectory, relativePath, FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
69
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerable.cs
vendored
Normal file
69
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerable.cs
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace System.IO.Enumeration
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerable that allows utilizing custom filter predicates and tranform delegates.
|
||||
/// </summary>
|
||||
public class FileSystemEnumerable<TResult> : IEnumerable<TResult>
|
||||
{
|
||||
private DelegateEnumerator _enumerator;
|
||||
private readonly FindTransform _transform;
|
||||
private readonly EnumerationOptions _options;
|
||||
private readonly string _directory;
|
||||
|
||||
public FileSystemEnumerable(string directory, FindTransform transform, EnumerationOptions options = null)
|
||||
{
|
||||
_directory = directory ?? throw new ArgumentNullException(nameof(directory));
|
||||
_transform = transform ?? throw new ArgumentNullException(nameof(transform));
|
||||
_options = options ?? EnumerationOptions.Default;
|
||||
|
||||
// We need to create the enumerator up front to ensure that we throw I/O exceptions for
|
||||
// the root directory on creation of the enumerable.
|
||||
_enumerator = new DelegateEnumerator(this);
|
||||
}
|
||||
|
||||
public FindPredicate ShouldIncludePredicate { get; set; }
|
||||
public FindPredicate ShouldRecursePredicate { get; set; }
|
||||
|
||||
public IEnumerator<TResult> GetEnumerator()
|
||||
{
|
||||
return Interlocked.Exchange(ref _enumerator, null) ?? new DelegateEnumerator(this);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for filtering out find results.
|
||||
/// </summary>
|
||||
public delegate bool FindPredicate(ref FileSystemEntry entry);
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for transforming raw find data into a result.
|
||||
/// </summary>
|
||||
public delegate TResult FindTransform(ref FileSystemEntry entry);
|
||||
|
||||
private sealed class DelegateEnumerator : FileSystemEnumerator<TResult>
|
||||
{
|
||||
private readonly FileSystemEnumerable<TResult> _enumerable;
|
||||
|
||||
public DelegateEnumerator(FileSystemEnumerable<TResult> enumerable)
|
||||
: base(enumerable._directory, enumerable._options)
|
||||
{
|
||||
_enumerable = enumerable;
|
||||
}
|
||||
|
||||
protected override TResult TransformEntry(ref FileSystemEntry entry) => _enumerable._transform(ref entry);
|
||||
protected override bool ShouldRecurseIntoEntry(ref FileSystemEntry entry)
|
||||
=> _enumerable.ShouldRecursePredicate?.Invoke(ref entry) ?? true;
|
||||
protected override bool ShouldIncludeEntry(ref FileSystemEntry entry)
|
||||
=> _enumerable.ShouldIncludePredicate?.Invoke(ref entry) ?? true;
|
||||
}
|
||||
}
|
||||
}
|
||||
173
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerableFactory.cs
vendored
Normal file
173
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerableFactory.cs
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file ref the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System.IO.Enumeration
|
||||
{
|
||||
internal static class FileSystemEnumerableFactory
|
||||
{
|
||||
// These all have special meaning in DOS name matching. '\' is the escaping character (which conveniently
|
||||
// is the directory separator and cannot be part of any path segment in Windows). The other three are the
|
||||
// special case wildcards that we'll convert some * and ? into. They're also valid as filenames on Unix,
|
||||
// which is not true in Windows and as such we'll escape any that occur on the input string.
|
||||
private readonly static char[] s_unixEscapeChars = { '\\', '"', '<', '>' };
|
||||
|
||||
internal static void NormalizeInputs(ref string directory, ref string expression, EnumerationOptions options)
|
||||
{
|
||||
if (Path.IsPathRooted(expression))
|
||||
throw new ArgumentException(SR.Arg_Path2IsRooted, nameof(expression));
|
||||
|
||||
// We always allowed breaking the passed ref directory and filter to be separated
|
||||
// any way the user wanted. Looking for "C:\foo\*.cs" could be passed as "C:\" and
|
||||
// "foo\*.cs" or "C:\foo" and "*.cs", for example. As such we need to combine and
|
||||
// split the inputs if the expression contains a directory separator.
|
||||
//
|
||||
// We also allowed for expression to be "foo\" which would translate to "foo\*".
|
||||
|
||||
ReadOnlySpan<char> directoryName = Path.GetDirectoryName(expression.AsSpan());
|
||||
|
||||
if (directoryName.Length != 0)
|
||||
{
|
||||
// Need to fix up the input paths
|
||||
directory = Path.Join(directory, directoryName);
|
||||
expression = expression.Substring(directoryName.Length + 1);
|
||||
}
|
||||
|
||||
switch (options.MatchType)
|
||||
{
|
||||
case MatchType.Win32:
|
||||
if (string.IsNullOrEmpty(expression) || expression == "." || expression == "*.*")
|
||||
{
|
||||
// Historically we always treated "." as "*"
|
||||
expression = "*";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Path.DirectorySeparatorChar != '\\' && expression.IndexOfAny(s_unixEscapeChars) != -1)
|
||||
{
|
||||
// Backslash isn't the default separator, need to escape (e.g. Unix)
|
||||
expression = expression.Replace("\\", "\\\\");
|
||||
|
||||
// Also need to escape the other special wild characters ('"', '<', and '>')
|
||||
expression = expression.Replace("\"", "\\\"");
|
||||
expression = expression.Replace(">", "\\>");
|
||||
expression = expression.Replace("<", "\\<");
|
||||
}
|
||||
|
||||
// Need to convert the expression to match Win32 behavior
|
||||
expression = FileSystemName.TranslateWin32Expression(expression);
|
||||
}
|
||||
break;
|
||||
case MatchType.Simple:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(options));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool MatchesPattern(string expression, ReadOnlySpan<char> name, EnumerationOptions options)
|
||||
{
|
||||
bool ignoreCase = (options.MatchCasing == MatchCasing.PlatformDefault && !PathInternal.IsCaseSensitive)
|
||||
|| options.MatchCasing == MatchCasing.CaseInsensitive;
|
||||
|
||||
switch (options.MatchType)
|
||||
{
|
||||
case MatchType.Simple:
|
||||
return FileSystemName.MatchesSimpleExpression(expression, name, ignoreCase);
|
||||
case MatchType.Win32:
|
||||
return FileSystemName.MatchesWin32Expression(expression, name, ignoreCase);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(options));
|
||||
}
|
||||
}
|
||||
|
||||
internal static IEnumerable<string> UserFiles(string directory,
|
||||
string expression,
|
||||
EnumerationOptions options)
|
||||
{
|
||||
return new FileSystemEnumerable<string>(
|
||||
directory,
|
||||
(ref FileSystemEntry entry) => entry.ToSpecifiedFullPath(),
|
||||
options)
|
||||
{
|
||||
ShouldIncludePredicate = (ref FileSystemEntry entry) =>
|
||||
!entry.IsDirectory && MatchesPattern(expression, entry.FileName, options)
|
||||
};
|
||||
}
|
||||
|
||||
internal static IEnumerable<string> UserDirectories(string directory,
|
||||
string expression,
|
||||
EnumerationOptions options)
|
||||
{
|
||||
return new FileSystemEnumerable<string>(
|
||||
directory,
|
||||
(ref FileSystemEntry entry) => entry.ToSpecifiedFullPath(),
|
||||
options)
|
||||
{
|
||||
ShouldIncludePredicate = (ref FileSystemEntry entry) =>
|
||||
entry.IsDirectory && MatchesPattern(expression, entry.FileName, options)
|
||||
};
|
||||
}
|
||||
|
||||
internal static IEnumerable<string> UserEntries(string directory,
|
||||
string expression,
|
||||
EnumerationOptions options)
|
||||
{
|
||||
return new FileSystemEnumerable<string>(
|
||||
directory,
|
||||
(ref FileSystemEntry entry) => entry.ToSpecifiedFullPath(),
|
||||
options)
|
||||
{
|
||||
ShouldIncludePredicate = (ref FileSystemEntry entry) =>
|
||||
MatchesPattern(expression, entry.FileName, options)
|
||||
};
|
||||
}
|
||||
|
||||
internal static IEnumerable<FileInfo> FileInfos(
|
||||
string directory,
|
||||
string expression,
|
||||
EnumerationOptions options)
|
||||
{
|
||||
return new FileSystemEnumerable<FileInfo>(
|
||||
directory,
|
||||
(ref FileSystemEntry entry) => (FileInfo)entry.ToFileSystemInfo(),
|
||||
options)
|
||||
{
|
||||
ShouldIncludePredicate = (ref FileSystemEntry entry) =>
|
||||
!entry.IsDirectory && MatchesPattern(expression, entry.FileName, options)
|
||||
};
|
||||
}
|
||||
|
||||
internal static IEnumerable<DirectoryInfo> DirectoryInfos(
|
||||
string directory,
|
||||
string expression,
|
||||
EnumerationOptions options)
|
||||
{
|
||||
return new FileSystemEnumerable<DirectoryInfo>(
|
||||
directory,
|
||||
(ref FileSystemEntry entry) => (DirectoryInfo)entry.ToFileSystemInfo(),
|
||||
options)
|
||||
{
|
||||
ShouldIncludePredicate = (ref FileSystemEntry entry) =>
|
||||
entry.IsDirectory && MatchesPattern(expression, entry.FileName, options)
|
||||
};
|
||||
}
|
||||
|
||||
internal static IEnumerable<FileSystemInfo> FileSystemInfos(
|
||||
string directory,
|
||||
string expression,
|
||||
EnumerationOptions options)
|
||||
{
|
||||
return new FileSystemEnumerable<FileSystemInfo>(
|
||||
directory,
|
||||
(ref FileSystemEntry entry) => entry.ToFileSystemInfo(),
|
||||
options)
|
||||
{
|
||||
ShouldIncludePredicate = (ref FileSystemEntry entry) =>
|
||||
MatchesPattern(expression, entry.FileName, options)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
230
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs
vendored
Normal file
230
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Threading;
|
||||
|
||||
namespace System.IO.Enumeration
|
||||
{
|
||||
public unsafe abstract partial class FileSystemEnumerator<TResult> : CriticalFinalizerObject, IEnumerator<TResult>
|
||||
{
|
||||
// The largest supported path on Unix is 4K bytes of UTF-8 (most only support 1K)
|
||||
private const int StandardBufferSize = 4096;
|
||||
|
||||
private readonly string _originalRootDirectory;
|
||||
private readonly string _rootDirectory;
|
||||
private readonly EnumerationOptions _options;
|
||||
|
||||
private readonly object _lock = new object();
|
||||
|
||||
private string _currentPath;
|
||||
private IntPtr _directoryHandle;
|
||||
private bool _lastEntryFound;
|
||||
private Queue<string> _pending;
|
||||
|
||||
private Interop.Sys.DirectoryEntry _entry;
|
||||
private TResult _current;
|
||||
|
||||
// Used for creating full paths
|
||||
private char[] _pathBuffer;
|
||||
// Used to get the raw entry data
|
||||
private byte[] _entryBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates a find operation.
|
||||
/// </summary>
|
||||
/// <param name="directory">The directory to search in.</param>
|
||||
/// <param name="options">Enumeration options to use.</param>
|
||||
public FileSystemEnumerator(string directory, EnumerationOptions options = null)
|
||||
{
|
||||
_originalRootDirectory = directory ?? throw new ArgumentNullException(nameof(directory));
|
||||
_rootDirectory = PathInternal.TrimEndingDirectorySeparator(Path.GetFullPath(directory));
|
||||
_options = options ?? EnumerationOptions.Default;
|
||||
|
||||
// We need to initialize the directory handle up front to ensure
|
||||
// we immediately throw IO exceptions for missing directory/etc.
|
||||
_directoryHandle = CreateDirectoryHandle(_rootDirectory);
|
||||
if (_directoryHandle == IntPtr.Zero)
|
||||
_lastEntryFound = true;
|
||||
|
||||
_currentPath = _rootDirectory;
|
||||
|
||||
try
|
||||
{
|
||||
_pathBuffer = ArrayPool<char>.Shared.Rent(StandardBufferSize);
|
||||
int size = Interop.Sys.ReadBufferSize;
|
||||
_entryBuffer = size > 0 ? ArrayPool<byte>.Shared.Rent(size) : null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Close the directory handle right away if we fail to allocate
|
||||
CloseDirectoryHandle();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private bool InternalContinueOnError(int error)
|
||||
=> (_options.IgnoreInaccessible && IsAccessError(error)) || ContinueOnError(error);
|
||||
|
||||
private static bool IsAccessError(int error)
|
||||
=> error == (int)Interop.Error.EACCES || error == (int)Interop.Error.EBADF
|
||||
|| error == (int)Interop.Error.EPERM;
|
||||
|
||||
private IntPtr CreateDirectoryHandle(string path)
|
||||
{
|
||||
IntPtr handle = Interop.Sys.OpenDir(path);
|
||||
if (handle == IntPtr.Zero)
|
||||
{
|
||||
Interop.ErrorInfo info = Interop.Sys.GetLastErrorInfo();
|
||||
if (InternalContinueOnError(info.RawErrno))
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
throw Interop.GetExceptionForIoErrno(info, path, isDirectory: true);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
private void CloseDirectoryHandle()
|
||||
{
|
||||
IntPtr handle = Interlocked.Exchange(ref _directoryHandle, IntPtr.Zero);
|
||||
if (handle != IntPtr.Zero)
|
||||
Interop.Sys.CloseDir(handle);
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_lastEntryFound)
|
||||
return false;
|
||||
|
||||
FileSystemEntry entry = default;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_lastEntryFound)
|
||||
return false;
|
||||
|
||||
// If HAVE_READDIR_R is defined for the platform FindNextEntry depends on _entryBuffer being fixed since
|
||||
// _entry will point to a string in the middle of the array. If the array is not fixed GC can move it after
|
||||
// the native call and _entry will point to a bogus file name.
|
||||
fixed (byte* _ = _entryBuffer)
|
||||
{
|
||||
do
|
||||
{
|
||||
FindNextEntry();
|
||||
if (_lastEntryFound)
|
||||
return false;
|
||||
|
||||
FileAttributes attributes = FileSystemEntry.Initialize(
|
||||
ref entry, _entry, _currentPath, _rootDirectory, _originalRootDirectory, new Span<char>(_pathBuffer));
|
||||
bool isDirectory = (attributes & FileAttributes.Directory) != 0;
|
||||
|
||||
bool isSpecialDirectory = false;
|
||||
if (isDirectory)
|
||||
{
|
||||
// Subdirectory found
|
||||
if (_entry.Name[0] == '.' && (_entry.Name[1] == 0 || (_entry.Name[1] == '.' && _entry.Name[2] == 0)))
|
||||
{
|
||||
// "." or "..", don't process unless the option is set
|
||||
if (!_options.ReturnSpecialDirectories)
|
||||
continue;
|
||||
isSpecialDirectory = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isSpecialDirectory && _options.AttributesToSkip != 0)
|
||||
{
|
||||
if ((_options.AttributesToSkip & FileAttributes.ReadOnly) != 0)
|
||||
{
|
||||
// ReadOnly is the only attribute that requires hitting entry.Attributes (which hits the disk)
|
||||
attributes = entry.Attributes;
|
||||
}
|
||||
|
||||
if ((_options.AttributesToSkip & attributes) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (isDirectory && !isSpecialDirectory)
|
||||
{
|
||||
if (_options.RecurseSubdirectories && ShouldRecurseIntoEntry(ref entry))
|
||||
{
|
||||
// Recursion is on and the directory was accepted, Queue it
|
||||
if (_pending == null)
|
||||
_pending = new Queue<string>();
|
||||
_pending.Enqueue(Path.Join(_currentPath, entry.FileName));
|
||||
}
|
||||
}
|
||||
|
||||
if (ShouldIncludeEntry(ref entry))
|
||||
{
|
||||
_current = TransformEntry(ref entry);
|
||||
return true;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void FindNextEntry()
|
||||
{
|
||||
Span<byte> buffer = _entryBuffer == null ? Span<byte>.Empty : new Span<byte>(_entryBuffer);
|
||||
int result = Interop.Sys.ReadDir(_directoryHandle, buffer, ref _entry);
|
||||
switch (result)
|
||||
{
|
||||
case -1:
|
||||
// End of directory
|
||||
DirectoryFinished();
|
||||
break;
|
||||
case 0:
|
||||
// Success
|
||||
break;
|
||||
default:
|
||||
// Error
|
||||
if (InternalContinueOnError(result))
|
||||
{
|
||||
DirectoryFinished();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(result), _currentPath, isDirectory: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DequeueNextDirectory()
|
||||
{
|
||||
_currentPath = _pending.Dequeue();
|
||||
_directoryHandle = CreateDirectoryHandle(_currentPath);
|
||||
}
|
||||
|
||||
private void InternalDispose(bool disposing)
|
||||
{
|
||||
// It is possible to fail to allocate the lock, but the finalizer will still run
|
||||
if (_lock != null)
|
||||
{
|
||||
lock(_lock)
|
||||
{
|
||||
_lastEntryFound = true;
|
||||
_pending = null;
|
||||
|
||||
CloseDirectoryHandle();
|
||||
|
||||
if (_pathBuffer != null)
|
||||
ArrayPool<char>.Shared.Return(_pathBuffer);
|
||||
_pathBuffer = null;
|
||||
if (_entryBuffer != null)
|
||||
ArrayPool<byte>.Shared.Return(_entryBuffer);
|
||||
_entryBuffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
78
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Win32.cs
vendored
Normal file
78
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Win32.cs
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace System.IO.Enumeration
|
||||
{
|
||||
public partial class FileSystemEnumerator<TResult>
|
||||
{
|
||||
/// <returns>'true' if new data was found</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private unsafe bool GetData()
|
||||
{
|
||||
Debug.Assert(_directoryHandle != (IntPtr)(-1) && _directoryHandle != IntPtr.Zero && !_lastEntryFound);
|
||||
|
||||
int status = Interop.NtDll.NtQueryDirectoryFile(
|
||||
FileHandle: _directoryHandle,
|
||||
Event: IntPtr.Zero,
|
||||
ApcRoutine: IntPtr.Zero,
|
||||
ApcContext: IntPtr.Zero,
|
||||
IoStatusBlock: out Interop.NtDll.IO_STATUS_BLOCK statusBlock,
|
||||
FileInformation: _buffer,
|
||||
Length: (uint)_buffer.Length,
|
||||
FileInformationClass: Interop.NtDll.FILE_INFORMATION_CLASS.FileFullDirectoryInformation,
|
||||
ReturnSingleEntry: Interop.BOOLEAN.FALSE,
|
||||
FileName: null,
|
||||
RestartScan: Interop.BOOLEAN.FALSE);
|
||||
|
||||
switch ((uint)status)
|
||||
{
|
||||
case Interop.StatusOptions.STATUS_NO_MORE_FILES:
|
||||
DirectoryFinished();
|
||||
return false;
|
||||
case Interop.StatusOptions.STATUS_SUCCESS:
|
||||
Debug.Assert(statusBlock.Information.ToInt64() != 0);
|
||||
return true;
|
||||
default:
|
||||
int error = (int)Interop.NtDll.RtlNtStatusToDosError(status);
|
||||
|
||||
// Note that there are many NT status codes that convert to ERROR_ACCESS_DENIED.
|
||||
if ((error == Interop.Errors.ERROR_ACCESS_DENIED && _options.IgnoreInaccessible) || ContinueOnError(error))
|
||||
{
|
||||
DirectoryFinished();
|
||||
return false;
|
||||
}
|
||||
throw Win32Marshal.GetExceptionForWin32Error(error, _currentPath);
|
||||
}
|
||||
}
|
||||
|
||||
private IntPtr CreateRelativeDirectoryHandle(ReadOnlySpan<char> relativePath, string fullPath)
|
||||
{
|
||||
(int status, IntPtr handle) = Interop.NtDll.CreateFile(
|
||||
relativePath,
|
||||
_directoryHandle,
|
||||
Interop.NtDll.CreateDisposition.FILE_OPEN,
|
||||
Interop.NtDll.DesiredAccess.FILE_LIST_DIRECTORY | Interop.NtDll.DesiredAccess.SYNCHRONIZE,
|
||||
createOptions: Interop.NtDll.CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | Interop.NtDll.CreateOptions.FILE_DIRECTORY_FILE
|
||||
| Interop.NtDll.CreateOptions.FILE_OPEN_FOR_BACKUP_INTENT);
|
||||
|
||||
switch ((uint)status)
|
||||
{
|
||||
case Interop.StatusOptions.STATUS_SUCCESS:
|
||||
return handle;
|
||||
default:
|
||||
int error = (int)Interop.NtDll.RtlNtStatusToDosError(status);
|
||||
|
||||
// Note that there are many NT status codes that convert to ERROR_ACCESS_DENIED.
|
||||
if ((error == Interop.Errors.ERROR_ACCESS_DENIED && _options.IgnoreInaccessible) || ContinueOnError(error))
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
throw Win32Marshal.GetExceptionForWin32Error(error, fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,12 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace System.IO
|
||||
namespace System.IO.Enumeration
|
||||
{
|
||||
internal partial class FindEnumerable<TResult, TState>
|
||||
public partial class FileSystemEnumerator<TResult>
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe bool GetData()
|
||||
private unsafe bool GetData()
|
||||
{
|
||||
if (!Interop.Kernel32.GetFileInformationByHandleEx(
|
||||
_directoryHandle,
|
||||
@@ -24,12 +24,26 @@ namespace System.IO
|
||||
case Interop.Errors.ERROR_NO_MORE_FILES:
|
||||
DirectoryFinished();
|
||||
return false;
|
||||
default:
|
||||
throw Win32Marshal.GetExceptionForWin32Error(error, _currentPath);
|
||||
case Interop.Errors.ERROR_ACCESS_DENIED:
|
||||
if (_options.IgnoreInaccessible)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ContinueOnError(error))
|
||||
throw Win32Marshal.GetExceptionForWin32Error(error, _currentPath);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private IntPtr CreateRelativeDirectoryHandle(ReadOnlySpan<char> relativePath, string fullPath)
|
||||
{
|
||||
// We don't have access to any APIs that allow us to pass in a base handle in UAP,
|
||||
// just call our "normal" handle open.
|
||||
return CreateDirectoryHandle(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
234
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs
vendored
Normal file
234
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace System.IO.Enumeration
|
||||
{
|
||||
public unsafe abstract partial class FileSystemEnumerator<TResult> : CriticalFinalizerObject, IEnumerator<TResult>
|
||||
{
|
||||
private const int StandardBufferSize = 4096;
|
||||
|
||||
// We need to have enough room for at least a single entry. The filename alone can be 512 bytes, we'll ensure we have
|
||||
// a reasonable buffer for all of the other metadata as well.
|
||||
private const int MinimumBufferSize = 1024;
|
||||
|
||||
private readonly string _originalRootDirectory;
|
||||
private readonly string _rootDirectory;
|
||||
private readonly EnumerationOptions _options;
|
||||
|
||||
private readonly object _lock = new object();
|
||||
|
||||
private Interop.NtDll.FILE_FULL_DIR_INFORMATION* _entry;
|
||||
private TResult _current;
|
||||
|
||||
private byte[] _buffer;
|
||||
private IntPtr _directoryHandle;
|
||||
private string _currentPath;
|
||||
private bool _lastEntryFound;
|
||||
private Queue<(IntPtr Handle, string Path)> _pending;
|
||||
private GCHandle _pinnedBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates a find operation.
|
||||
/// </summary>
|
||||
/// <param name="directory">The directory to search in.</param>
|
||||
/// <param name="options">Enumeration options to use.</param>
|
||||
public FileSystemEnumerator(string directory, EnumerationOptions options = null)
|
||||
{
|
||||
_originalRootDirectory = directory ?? throw new ArgumentNullException(nameof(directory));
|
||||
_rootDirectory = PathInternal.TrimEndingDirectorySeparator(Path.GetFullPath(directory));
|
||||
_options = options ?? EnumerationOptions.Default;
|
||||
|
||||
// We'll only suppress the media insertion prompt on the topmost directory as that is the
|
||||
// most likely scenario and we don't want to take the perf hit for large enumerations.
|
||||
// (We weren't consistent with how we handled this historically.)
|
||||
using (new DisableMediaInsertionPrompt())
|
||||
{
|
||||
// We need to initialize the directory handle up front to ensure
|
||||
// we immediately throw IO exceptions for missing directory/etc.
|
||||
_directoryHandle = CreateDirectoryHandle(_rootDirectory);
|
||||
if (_directoryHandle == IntPtr.Zero)
|
||||
_lastEntryFound = true;
|
||||
}
|
||||
|
||||
_currentPath = _rootDirectory;
|
||||
|
||||
int requestedBufferSize = _options.BufferSize;
|
||||
int bufferSize = requestedBufferSize <= 0 ? StandardBufferSize
|
||||
: Math.Max(MinimumBufferSize, requestedBufferSize);
|
||||
|
||||
try
|
||||
{
|
||||
_buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
|
||||
_pinnedBuffer = GCHandle.Alloc(_buffer, GCHandleType.Pinned);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Close the directory handle right away if we fail to allocate
|
||||
CloseDirectoryHandle();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseDirectoryHandle()
|
||||
{
|
||||
// As handles can be reused we want to be extra careful to close handles only once
|
||||
IntPtr handle = Interlocked.Exchange(ref _directoryHandle, IntPtr.Zero);
|
||||
if (handle != IntPtr.Zero)
|
||||
Interop.Kernel32.CloseHandle(handle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple wrapper to allow creating a file handle for an existing directory.
|
||||
/// </summary>
|
||||
private IntPtr CreateDirectoryHandle(string path)
|
||||
{
|
||||
IntPtr handle = Interop.Kernel32.CreateFile_IntPtr(
|
||||
path,
|
||||
Interop.Kernel32.FileOperations.FILE_LIST_DIRECTORY,
|
||||
FileShare.ReadWrite | FileShare.Delete,
|
||||
FileMode.Open,
|
||||
Interop.Kernel32.FileOperations.FILE_FLAG_BACKUP_SEMANTICS);
|
||||
|
||||
if (handle == IntPtr.Zero || handle == (IntPtr)(-1))
|
||||
{
|
||||
int error = Marshal.GetLastWin32Error();
|
||||
|
||||
if ((error == Interop.Errors.ERROR_ACCESS_DENIED &&
|
||||
_options.IgnoreInaccessible) || ContinueOnError(error))
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (error == Interop.Errors.ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
// Historically we throw directory not found rather than file not found
|
||||
error = Interop.Errors.ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
throw Win32Marshal.GetExceptionForWin32Error(error, path);
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_lastEntryFound)
|
||||
return false;
|
||||
|
||||
FileSystemEntry entry = default;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_lastEntryFound)
|
||||
return false;
|
||||
|
||||
do
|
||||
{
|
||||
FindNextEntry();
|
||||
if (_lastEntryFound)
|
||||
return false;
|
||||
|
||||
// Calling the constructor inside the try block would create a second instance on the stack.
|
||||
FileSystemEntry.Initialize(ref entry, _entry, _currentPath, _rootDirectory, _originalRootDirectory);
|
||||
|
||||
// Skip specified attributes
|
||||
if ((_entry->FileAttributes & _options.AttributesToSkip) != 0)
|
||||
continue;
|
||||
|
||||
if ((_entry->FileAttributes & FileAttributes.Directory) != 0)
|
||||
{
|
||||
// Subdirectory found
|
||||
if (!(_entry->FileName.Length > 2 || _entry->FileName[0] != '.' || (_entry->FileName.Length == 2 && _entry->FileName[1] != '.')))
|
||||
{
|
||||
// "." or "..", don't process unless the option is set
|
||||
if (!_options.ReturnSpecialDirectories)
|
||||
continue;
|
||||
}
|
||||
else if (_options.RecurseSubdirectories && ShouldRecurseIntoEntry(ref entry))
|
||||
{
|
||||
// Recursion is on and the directory was accepted, Queue it
|
||||
string subDirectory = Path.Join(_currentPath, _entry->FileName);
|
||||
IntPtr subDirectoryHandle = CreateRelativeDirectoryHandle(_entry->FileName, subDirectory);
|
||||
if (subDirectoryHandle != IntPtr.Zero)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_pending == null)
|
||||
_pending = new Queue<(IntPtr, string)>();
|
||||
_pending.Enqueue((subDirectoryHandle, subDirectory));
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Couldn't queue the handle, close it and rethrow
|
||||
Interop.Kernel32.CloseHandle(subDirectoryHandle);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ShouldIncludeEntry(ref entry))
|
||||
{
|
||||
_current = TransformEntry(ref entry);
|
||||
return true;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void FindNextEntry()
|
||||
{
|
||||
_entry = Interop.NtDll.FILE_FULL_DIR_INFORMATION.GetNextInfo(_entry);
|
||||
if (_entry != null)
|
||||
return;
|
||||
|
||||
// We need more data
|
||||
if (GetData())
|
||||
_entry = (Interop.NtDll.FILE_FULL_DIR_INFORMATION*)_pinnedBuffer.AddrOfPinnedObject();
|
||||
}
|
||||
|
||||
private void DequeueNextDirectory()
|
||||
{
|
||||
(_directoryHandle, _currentPath) = _pending.Dequeue();
|
||||
}
|
||||
|
||||
private void InternalDispose(bool disposing)
|
||||
{
|
||||
// It is possible to fail to allocate the lock, but the finalizer will still run
|
||||
if (_lock != null)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_lastEntryFound = true;
|
||||
|
||||
CloseDirectoryHandle();
|
||||
|
||||
if (_pending != null)
|
||||
{
|
||||
while (_pending.Count > 0)
|
||||
Interop.Kernel32.CloseHandle(_pending.Dequeue().Handle);
|
||||
_pending = null;
|
||||
}
|
||||
|
||||
if (_pinnedBuffer.IsAllocated)
|
||||
_pinnedBuffer.Free();
|
||||
|
||||
if (_buffer != null)
|
||||
ArrayPool<byte>.Shared.Return(_buffer);
|
||||
|
||||
_buffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
89
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.cs
vendored
Normal file
89
external/corefx/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.cs
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
|
||||
namespace System.IO.Enumeration
|
||||
{
|
||||
public unsafe abstract partial class FileSystemEnumerator<TResult> : CriticalFinalizerObject, IEnumerator<TResult>
|
||||
{
|
||||
/// <summary>
|
||||
/// Return true if the given file system entry should be included in the results.
|
||||
/// </summary>
|
||||
protected virtual bool ShouldIncludeEntry(ref FileSystemEntry entry) => true;
|
||||
|
||||
/// <summary>
|
||||
/// Return true if the directory entry given should be recursed into.
|
||||
/// </summary>
|
||||
protected virtual bool ShouldRecurseIntoEntry(ref FileSystemEntry entry) => true;
|
||||
|
||||
/// <summary>
|
||||
/// Generate the result type from the current entry;
|
||||
/// </summary>
|
||||
protected abstract TResult TransformEntry(ref FileSystemEntry entry);
|
||||
|
||||
/// <summary>
|
||||
/// Called whenever the end of a directory is reached.
|
||||
/// </summary>
|
||||
/// <param name="directory">The path of the directory that finished.</param>
|
||||
protected virtual void OnDirectoryFinished(ReadOnlySpan<char> directory) { }
|
||||
|
||||
/// <summary>
|
||||
/// Called when a native API returns an error. Return true to continue, or false
|
||||
/// to throw the default exception for the given error.
|
||||
/// </summary>
|
||||
/// <param name="error">The native error code.</param>
|
||||
protected virtual bool ContinueOnError(int error) => false;
|
||||
|
||||
public TResult Current => _current;
|
||||
|
||||
object IEnumerator.Current => Current;
|
||||
|
||||
private void DirectoryFinished()
|
||||
{
|
||||
_entry = default;
|
||||
|
||||
// Close the handle now that we're done
|
||||
CloseDirectoryHandle();
|
||||
OnDirectoryFinished(_currentPath);
|
||||
|
||||
if (_pending == null || _pending.Count == 0)
|
||||
{
|
||||
_lastEntryFound = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Grab the next directory to parse
|
||||
DequeueNextDirectory();
|
||||
FindNextEntry();
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
InternalDispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override for any additional cleanup.
|
||||
/// </summary>
|
||||
/// <param name="disposing">True if called while disposing. False if called from finalizer.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
}
|
||||
|
||||
~FileSystemEnumerator()
|
||||
{
|
||||
InternalDispose(disposing: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user