using System;
using System.Runtime.InteropServices;
+using System.Text;
internal static partial class Interop
{
internal static partial class Sys
{
- [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_MkDir", CharSet = CharSet.Ansi, SetLastError = true)]
- internal static partial int MkDir(string path, int mode);
+ [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_MkDir", SetLastError = true)]
+ private static partial int MkDir(ref byte path, int mode);
+
+ internal static int MkDir(ReadOnlySpan<char> path, int mode)
+ {
+ using ValueUtf8Converter converter = new(stackalloc byte[DefaultPathBufferSize]);
+ int result = MkDir(ref MemoryMarshal.GetReference(converter.ConvertAndTerminateString(path)), mode);
+ return result;
+ }
}
}
Link="Common\Interop\Unix\Interop.GetHostName.cs" />
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetPeerUserName.cs"
Link="Common\Interop\Unix\Interop.GetPeerUserName.cs" />
- <Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.MkDir.cs"
- Link="Common\Interop\Unix\Interop.MkDir.cs" />
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.Open.cs"
Link="Common\Interop\Unix\Interop.Open.cs" />
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.OpenFlags.cs"
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(LibrariesProjectRoot)System.Security.AccessControl\src\System.Security.AccessControl.csproj" />
- <ProjectReference Include="$(LibrariesProjectRoot)System.Security.Principal.Windows\src\System.Security.Principal.Windows.csproj" />
+ <ProjectReference Include="$(LibrariesProjectRoot)System.Security.Principal.Windows\src\System.Security.Principal.Windows.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.Collections" />
return LazyInitializer.EnsureInitialized(ref _asyncActiveSemaphore, () => new SemaphoreSlim(1, 1));
}
- private static void CreateDirectory(string directoryPath)
- {
- int result = Interop.Sys.MkDir(directoryPath, (int)Interop.Sys.Permissions.Mask);
-
- // If successful created, we're done.
- if (result >= 0)
- return;
-
- // If the directory already exists, consider it a success.
- Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
- if (errorInfo.Error == Interop.Error.EEXIST)
- return;
-
- // Otherwise, fail.
- throw Interop.GetExceptionForIoErrno(errorInfo, directoryPath, isDirectory: true);
- }
-
/// <summary>Creates an anonymous pipe.</summary>
/// <param name="reader">The resulting reader end of the pipe.</param>
/// <param name="writer">The resulting writer end of the pipe.</param>
{
return; // Path already exists and it's a directory.
}
- else if (errorInfo.Error == Interop.Error.ENOENT)
+ else if (errorInfo.Error == Interop.Error.ENOENT) // Some parts of the path don't exist yet.
{
- // Some parts of the path don't exist yet.
CreateParentsAndDirectory(fullPath);
}
else
}
}
- public static void CreateParentsAndDirectory(string fullPath)
+ private static void CreateParentsAndDirectory(string fullPath)
{
// Try create parents bottom to top and track those that could not
// be created due to missing parents. Then create them top to bottom.
- List<string> stackDir = new List<string>();
-
- stackDir.Add(fullPath);
+ using ValueListBuilder<int> stackDir = new(stackalloc int[32]); // 32 arbitrarily chosen
+ stackDir.Append(fullPath.Length);
int i = fullPath.Length - 1;
- // Trim trailing separator.
if (PathInternal.IsDirectorySeparator(fullPath[i]))
{
- i--;
+ i--; // Trim trailing separator.
}
+
do
{
// Find the end of the parent directory.
i--;
}
- // Try create it.
- string mkdirPath = fullPath.Substring(0, i);
+ ReadOnlySpan<char> mkdirPath = fullPath.AsSpan(0, i);
int result = Interop.Sys.MkDir(mkdirPath, (int)Interop.Sys.Permissions.Mask);
if (result == 0)
{
- // Created parent.
- break;
+ break; // Created parent.
}
Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
// We'll try to create its parent on the next iteration.
// Track this path for later creation.
- stackDir.Add(mkdirPath);
+ stackDir.Append(mkdirPath.Length);
}
else if (errorInfo.Error == Interop.Error.EEXIST)
{
}
else
{
- throw Interop.GetExceptionForIoErrno(errorInfo, mkdirPath, isDirectory: true);
+ throw Interop.GetExceptionForIoErrno(errorInfo, mkdirPath.ToString(), isDirectory: true);
}
i--;
} while (i > 0);
// Create directories that had missing parents.
- for (i = stackDir.Count - 1; i >= 0; i--)
+ for (i = stackDir.Length - 1; i >= 0; i--)
{
- string mkdirPath = stackDir[i];
+ ReadOnlySpan<char> mkdirPath = fullPath.AsSpan(0, stackDir[i]);
int result = Interop.Sys.MkDir(mkdirPath, (int)Interop.Sys.Permissions.Mask);
if (result < 0)
{
}
}
- throw Interop.GetExceptionForIoErrno(errorInfo, mkdirPath, isDirectory: true);
+ throw Interop.GetExceptionForIoErrno(errorInfo, mkdirPath.ToString(), isDirectory: true);
}
}
}