Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit

Permalink
API tweaks to match latest updates to spec (#27102)
Browse files Browse the repository at this point in the history
* API tweaks to match latest updates to spec

Add a few new tests

See #25873

* Properly clear state when enumerating on Unix.
Make sure we don't include special directories in subdir processing. Add test.
Collapse helper that was only called in one place, and remove dead one.
  • Loading branch information
JeremyKuhne authored Feb 14, 2018
1 parent e6b5f11 commit 1c9cd81
Show file tree
Hide file tree
Showing 15 changed files with 186 additions and 72 deletions.
31 changes: 15 additions & 16 deletions src/System.IO.FileSystem/ref/System.IO.FileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,32 @@ public static void Delete(string path, bool recursive) { }
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.Enumeration.EnumerationOptions enumerationOptions) { 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.Enumeration.EnumerationOptions enumerationOptions) { 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.Enumeration.EnumerationOptions enumerationOptions) { 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; }
public static string GetCurrentDirectory() { throw null; }
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.Enumeration.EnumerationOptions enumerationOptions) { 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.Enumeration.EnumerationOptions enumerationOptions) { 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.Enumeration.EnumerationOptions enumerationOptions) { 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; }
Expand Down Expand Up @@ -73,29 +73,29 @@ public void Create() { }
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.Enumeration.EnumerationOptions enumerationOptions) { throw null; }
public System.Collections.Generic.IEnumerable<System.IO.FileSystemInfo> EnumerateFileSystemInfos(string searchPattern, System.IO.Enumeration.EnumerationOptions enumerationOptions) { 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.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.Enumeration.EnumerationOptions enumerationOptions) { 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.Enumeration.EnumerationOptions enumerationOptions) { 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.Enumeration.EnumerationOptions enumerationOptions) { 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.Enumeration.EnumerationOptions enumerationOptions) { 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; }
}
Expand Down Expand Up @@ -223,9 +223,6 @@ public enum SearchOption
AllDirectories = 1,
TopDirectoryOnly = 0,
}
}
namespace System.IO.Enumeration
{
public enum MatchType
{
Simple,
Expand All @@ -240,7 +237,6 @@ public enum MatchCasing
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 { } }
Expand All @@ -249,6 +245,9 @@ public EnumerationOptions() { }
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; } }
Expand Down
8 changes: 4 additions & 4 deletions src/System.IO.FileSystem/src/System.IO.FileSystem.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@
<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\Enumeration\MatchCasing.cs" />
<Compile Include="System\IO\Enumeration\MatchType.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\Enumeration\EnumerationOptions.cs" />
<Compile Include="System\IO\EnumerationOptions.cs" />
<Compile Include="System\IO\Iterator.cs" />
<Compile Include="System\IO\PathHelpers.cs" />
<Compile Include="System\IO\ReadLinesIterator.cs" />
Expand Down Expand Up @@ -422,4 +422,4 @@
<Reference Include="System.Threading" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ internal static bool Initialize(
entry.RootDirectory = rootDirectory;
entry.OriginalRootDirectory = originalRootDirectory;
entry._pathBuffer = pathBuffer;
entry._fullPath = ReadOnlySpan<char>.Empty;
entry._fileName = ReadOnlySpan<char>.Empty;

// Get from the dir entry whether the entry is a file or directory.
// We classify everything as a file unless we know it to be a directory.
Expand All @@ -48,6 +50,7 @@ internal static bool Initialize(
isDirectory = (targetStatus.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR;
}

entry._status = default;
FileStatus.Initialize(ref entry._status, isDirectory);
return isDirectory;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,20 @@ public bool MoveNext()

bool isDirectory = FileSystemEntry.Initialize(ref entry, _entry, _currentPath, _rootDirectory, _originalRootDirectory, new Span<char>(_pathBuffer));

if (_options.AttributesToSkip != 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.Directory | FileAttributes.Hidden | FileAttributes.ReparsePoint)) == 0)
{
Expand All @@ -119,23 +132,16 @@ public bool MoveNext()
|| ((_options.AttributesToSkip & FileAttributes.ReparsePoint) != 0 && _entry.InodeType == Interop.Sys.NodeType.DT_LNK))
continue;
}
else if ((_options.AttributesToSkip & entry.Attributes) != 0)
else if (entry.Attributes != (FileAttributes)(-1) && (_options.AttributesToSkip & entry.Attributes) != 0)
{
// Hitting Attributes on the FileSystemEntry will cause a stat call
continue;
}
}

if (isDirectory)
if (isDirectory && !isSpecialDirectory)
{
// 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;
}
else if (_options.RecurseSubdirectories && ShouldRecurseIntoEntry(ref entry))
if (_options.RecurseSubdirectories && ShouldRecurseIntoEntry(ref entry))
{
// Recursion is on and the directory was accepted, Queue it
if (_pending == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public bool MoveNext()
if ((_entry->FileAttributes & FileAttributes.Directory) != 0)
{
// Subdirectory found
if (PathHelpers.IsDotOrDotDot(_entry->FileName))
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@
// 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
namespace System.IO
{
public class EnumerationOptions
{
/// <summary>
/// For internal use. These are the options we want to use if calling the existing Directory/File APIs where you don't
/// explicitly specify EnumerationOptions.
/// </summary>
internal static EnumerationOptions Compatible { get; } = new EnumerationOptions { MatchType = MatchType.Dos };
internal static EnumerationOptions Compatible { get; } = new EnumerationOptions
{ MatchType = MatchType.Dos, AttributesToSkip = 0, IgnoreInaccessible = false };

private static EnumerationOptions CompatibleRecursive { get; } = new EnumerationOptions { RecurseSubdirectories = true, MatchType = MatchType.Dos };
private static EnumerationOptions CompatibleRecursive { get; } = new EnumerationOptions
{ RecurseSubdirectories = true, MatchType = MatchType.Dos, AttributesToSkip = 0, IgnoreInaccessible = false };

/// <summary>
/// Internal singleton for default options.
Expand All @@ -24,6 +26,8 @@ public class EnumerationOptions
/// </summary>
public EnumerationOptions()
{
IgnoreInaccessible = true;
AttributesToSkip = FileAttributes.Hidden | FileAttributes.System;
}

/// <summary>
Expand All @@ -39,16 +43,18 @@ internal static EnumerationOptions FromSearchOption(SearchOption searchOption)

/// <summary>
/// Should we recurse into subdirectories while enumerating?
/// Default is false.
/// </summary>
public bool RecurseSubdirectories { get; set; }

/// <summary>
/// Skip files/directories when access is denied (e.g. AccessDeniedException/SecurityException)
/// Skip files/directories when access is denied (e.g. AccessDeniedException/SecurityException).
/// Default is true.
/// </summary>
public bool IgnoreInaccessible { get; set; }

/// <summary>
/// Suggested buffer size, in bytes.
/// Suggested buffer size, in bytes. Default is 0 (no suggestion).
/// </summary>
/// <remarks>
/// Not all platforms use user allocated buffers, and some require either fixed buffers or a
Expand All @@ -63,7 +69,7 @@ internal static EnumerationOptions FromSearchOption(SearchOption searchOption)
public int BufferSize { get; set; }

/// <summary>
/// Skip entries with the given attributes.
/// Skip entries with the given attributes. Default is FileAttributes.Hidden | FileAttributes.System.
/// </summary>
public FileAttributes AttributesToSkip { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// 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
namespace System.IO
{
public enum MatchCasing
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// 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
namespace System.IO
{
public enum MatchType
{
Expand Down
Loading

0 comments on commit 1c9cd81

Please sign in to comment.