Remove Interop.ReadDir.cs (dotnet/corefx#34274)
authorEgor Bogatov <egorbo@gmail.com>
Mon, 31 Dec 2018 02:05:27 +0000 (05:05 +0300)
committerDan Moseley <danmose@microsoft.com>
Mon, 31 Dec 2018 02:05:27 +0000 (18:05 -0800)
* Remove Interop.ReadDir.cs

* pass bufferPtr to FindNextEntry

* Update src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs

Co-Authored-By: EgorBo <egorbo@gmail.com>
Commit migrated from https://github.com/dotnet/corefx/commit/91589339e6fd3da57d8e6c15937253037e727a04

src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadDir.cs [deleted file]
src/libraries/System.IO.FileSystem/src/System.IO.FileSystem.csproj
src/libraries/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs

diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadDir.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadDir.cs
deleted file mode 100644 (file)
index d64b804..0000000
+++ /dev/null
@@ -1,86 +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.Diagnostics;
-using System.Runtime.InteropServices;
-using System.Text;
-using Microsoft.Win32.SafeHandles;
-
-internal static partial class Interop
-{
-    internal static partial class Sys
-    {
-        internal static int ReadBufferSize { get; } = GetReadDirRBufferSize();
-
-        internal enum NodeType : int
-        {
-            DT_UNKNOWN  =  0,
-            DT_FIFO     =  1,
-            DT_CHR      =  2,
-            DT_DIR      =  4,
-            DT_BLK      =  6,
-            DT_REG      =  8,
-            DT_LNK      = 10,
-            DT_SOCK     = 12,
-            DT_WHT      = 14
-        }
-
-        [StructLayout(LayoutKind.Sequential)]
-        internal unsafe struct DirectoryEntry
-        {
-            internal byte* Name;
-            internal int NameLength;
-            internal NodeType InodeType;
-
-            internal ReadOnlySpan<char> GetName(Span<char> buffer)
-            {
-                Debug.Assert(buffer.Length >= Encoding.UTF8.GetMaxCharCount(255), "should have enough space for the max file name");
-                Debug.Assert(Name != null, "should not have a null name");
-
-                ReadOnlySpan<byte> nameBytes = (NameLength == -1)
-                    // In this case the struct was allocated via struct dirent *readdir(DIR *dirp);
-                    ? new ReadOnlySpan<byte>(Name, new ReadOnlySpan<byte>(Name, 255).IndexOf<byte>(0))
-                    : new ReadOnlySpan<byte>(Name, NameLength);
-
-                Debug.Assert(nameBytes.Length > 0, "we shouldn't have gotten a garbage value from the OS");
-                if (nameBytes.Length == 0)
-                    return buffer.Slice(0, 0);
-
-                int charCount = Encoding.UTF8.GetChars(nameBytes, buffer);
-                ReadOnlySpan<char> value = buffer.Slice(0, charCount);
-                Debug.Assert(NameLength != -1 || !value.Contains('\0'), "should not have embedded nulls if we parsed the end of string");
-                return value;
-            }
-        }
-
-        [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_OpenDir", SetLastError = true)]
-        internal static extern IntPtr OpenDir(string path);
-
-        [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetReadDirRBufferSize", SetLastError = false)]
-        internal static extern int GetReadDirRBufferSize();
-
-        [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReadDirR", SetLastError = false)]
-        private static extern unsafe int ReadDirR(IntPtr dir, ref byte buffer, int bufferSize, ref DirectoryEntry outputEntry);
-
-        [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CloseDir", SetLastError = true)]
-        internal static extern int CloseDir(IntPtr dir);
-
-        /// <summary>
-        /// Get the next directory entry for the given handle. **Note** the actual memory used may be allocated
-        /// by the OS and will be freed when the handle is closed. As such, the handle lifespan MUST be kept tightly
-        /// controlled. The DirectoryEntry name cannot be accessed after the handle is closed.
-        /// 
-        /// Call <see cref="ReadBufferSize"/> to see what size buffer to allocate.
-        /// </summary>
-        internal static int ReadDir(IntPtr dir, Span<byte> buffer, ref DirectoryEntry entry)
-        {
-            // The calling pattern for ReadDir is described in src/Native/Unix/System.Native/pal_io.cpp|.h
-            Debug.Assert(buffer.Length >= ReadBufferSize, "should have a big enough buffer for the raw data");
-
-            // ReadBufferSize is zero when the native implementation does not support reading into a buffer.
-            return ReadDirR(dir, ref MemoryMarshal.GetReference(buffer), ReadBufferSize, ref entry);
-        }
-    }
-}
index f75c8ba..fc49794 100644 (file)
     <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">
+    <Compile Include="$(CommonPath)\CoreLib\Interop\Unix\System.Native\Interop.ReadDir.cs">
       <Link>Common\Interop\Unix\Interop.ReadDir.cs</Link>
     </Compile>
     <Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Link.cs">
index 61f63cf..9983329 100644 (file)
@@ -55,7 +55,7 @@ namespace System.IO.Enumeration
             try
             {
                 _pathBuffer = ArrayPool<char>.Shared.Rent(StandardBufferSize);
-                int size = Interop.Sys.ReadBufferSize;
+                int size = Interop.Sys.GetReadDirRBufferSize();
                 _entryBuffer = size > 0 ? ArrayPool<byte>.Shared.Rent(size) : null;
             }
             catch
@@ -113,11 +113,11 @@ namespace System.IO.Enumeration
                 // 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)
+                fixed (byte* entryBufferPtr = _entryBuffer)
                 {
                     do
                     {
-                        FindNextEntry();
+                        FindNextEntry(entryBufferPtr, _entryBuffer == null ? 0 : _entryBuffer.Length);
                         if (_lastEntryFound)
                             return false;
 
@@ -175,8 +175,15 @@ namespace System.IO.Enumeration
 
         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);
+            fixed (byte* entryBufferPtr = _entryBuffer)
+            {
+                FindNextEntry(entryBufferPtr, _entryBuffer == null ? 0 : _entryBuffer.Length);
+            }
+        }
+
+        private unsafe void FindNextEntry(byte* entryBufferPtr, int bufferLength)
+        {
+            int result = Interop.Sys.ReadDirR(_directoryHandle, entryBufferPtr, bufferLength, out _entry);
             switch (result)
             {
                 case -1: