diff --git a/src/libraries/Common/src/Interop/Unix/Interop.IOErrors.cs b/src/libraries/Common/src/Interop/Unix/Interop.IOErrors.cs
index 137b39405962ed..56c82686621b04 100644
--- a/src/libraries/Common/src/Interop/Unix/Interop.IOErrors.cs
+++ b/src/libraries/Common/src/Interop/Unix/Interop.IOErrors.cs
@@ -8,19 +8,19 @@
internal static partial class Interop
{
- private static void ThrowExceptionForIoErrno(ErrorInfo errorInfo, string? path, bool isDirectory)
+ private static void ThrowExceptionForIoErrno(ErrorInfo errorInfo, string? path, bool isDirError)
{
Debug.Assert(errorInfo.Error != Error.SUCCESS);
Debug.Assert(errorInfo.Error != Error.EINTR, "EINTR errors should be handled by the native shim and never bubble up to managed code");
- throw Interop.GetExceptionForIoErrno(errorInfo, path, isDirectory);
+ throw Interop.GetExceptionForIoErrno(errorInfo, path, isDirError);
}
- internal static void CheckIo(Error error, string? path = null, bool isDirectory = false)
+ internal static void CheckIo(Error error, string? path = null, bool isDirError = false)
{
if (error != Interop.Error.SUCCESS)
{
- ThrowExceptionForIoErrno(error.Info(), path, isDirectory);
+ ThrowExceptionForIoErrno(error.Info(), path, isDirError);
}
}
@@ -31,15 +31,15 @@ internal static void CheckIo(Error error, string? path = null, bool isDirectory
///
/// The result of the system call.
/// The path with which this error is associated. This may be null.
- /// true if the is known to be a directory; otherwise, false.
+ /// true if error is caused by a directory issue.
///
/// On success, returns the non-negative result long that was validated.
///
- internal static long CheckIo(long result, string? path = null, bool isDirectory = false)
+ internal static long CheckIo(long result, string? path = null, bool isDirError = false)
{
if (result < 0)
{
- ThrowExceptionForIoErrno(Sys.GetLastErrorInfo(), path, isDirectory);
+ ThrowExceptionForIoErrno(Sys.GetLastErrorInfo(), path, isDirError);
}
return result;
@@ -53,9 +53,9 @@ internal static long CheckIo(long result, string? path = null, bool isDirectory
///
/// On success, returns the non-negative result int that was validated.
///
- internal static int CheckIo(int result, string? path = null, bool isDirectory = false)
+ internal static int CheckIo(int result, string? path = null, bool isDirError = false)
{
- CheckIo((long)result, path, isDirectory);
+ CheckIo((long)result, path, isDirError);
return result;
}
@@ -68,9 +68,9 @@ internal static int CheckIo(int result, string? path = null, bool isDirectory =
///
/// On success, returns the non-negative result IntPtr that was validated.
///
- internal static IntPtr CheckIo(IntPtr result, string? path = null, bool isDirectory = false)
+ internal static IntPtr CheckIo(IntPtr result, string? path = null, bool isDirError = false)
{
- CheckIo((long)result, path, isDirectory);
+ CheckIo((long)result, path, isDirError);
return result;
}
@@ -83,12 +83,12 @@ internal static IntPtr CheckIo(IntPtr result, string? path = null, bool isDirect
///
/// On success, returns the valid SafeFileHandle that was validated.
///
- internal static TSafeHandle CheckIo(TSafeHandle handle, string? path = null, bool isDirectory = false)
+ internal static TSafeHandle CheckIo(TSafeHandle handle, string? path = null, bool isDirError = false)
where TSafeHandle : SafeHandle
{
if (handle.IsInvalid)
{
- Exception e = Interop.GetExceptionForIoErrno(Sys.GetLastErrorInfo(), path, isDirectory);
+ Exception e = Interop.GetExceptionForIoErrno(Sys.GetLastErrorInfo(), path, isDirError);
handle.Dispose();
throw e;
}
@@ -101,27 +101,29 @@ internal static TSafeHandle CheckIo(TSafeHandle handle, string? pat
///
/// The error info
/// The path with which this error is associated. This may be null.
- /// true if the is known to be a directory; otherwise, false.
+ /// true if error is caused by a directory issue.
///
- internal static Exception GetExceptionForIoErrno(ErrorInfo errorInfo, string? path = null, bool isDirectory = false)
+ internal static Exception GetExceptionForIoErrno(ErrorInfo errorInfo, string? path = null, bool isDirError = false)
{
// Translate the errno into a known set of exception types. For cases where multiple errnos map
// to the same exception type, include an inner exception with the details.
switch (errorInfo.Error)
{
case Error.ENOENT:
- if (isDirectory)
- {
- return !string.IsNullOrEmpty(path) ?
- new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, path)) :
- new DirectoryNotFoundException(SR.IO_PathNotFound_NoPathName);
- }
- else
+ // For Windows compatibility, throw DirectoryNotFoundException instead of FileNotFoundException
+ // when the parent folder does not exist.
+ if (!isDirError && (path is null || ParentDirectoryExists(path)))
{
return !string.IsNullOrEmpty(path) ?
new FileNotFoundException(SR.Format(SR.IO_FileNotFound_FileName, path), path) :
new FileNotFoundException(SR.IO_FileNotFound);
}
+ goto case Error.ENOTDIR;
+
+ case Error.ENOTDIR:
+ return !string.IsNullOrEmpty(path) ?
+ new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, path)) :
+ new DirectoryNotFoundException(SR.IO_PathNotFound_NoPathName);
case Error.EACCES:
case Error.EBADF:
@@ -156,6 +158,13 @@ internal static Exception GetExceptionForIoErrno(ErrorInfo errorInfo, string? pa
default:
return GetIOException(errorInfo, path);
+
+ static bool ParentDirectoryExists(string fullPath)
+ {
+ string? parentPath = Path.GetDirectoryName(Path.TrimEndingDirectorySeparator(fullPath));
+
+ return Directory.Exists(parentPath);
+ }
}
}
diff --git a/src/libraries/System.IO.FileSystem.DriveInfo/src/System/IO/DriveInfo.Unix.cs b/src/libraries/System.IO.FileSystem.DriveInfo/src/System/IO/DriveInfo.Unix.cs
index e1eb1b53e0ee43..dc42bde044b0c6 100644
--- a/src/libraries/System.IO.FileSystem.DriveInfo/src/System/IO/DriveInfo.Unix.cs
+++ b/src/libraries/System.IO.FileSystem.DriveInfo/src/System/IO/DriveInfo.Unix.cs
@@ -90,7 +90,7 @@ private void CheckStatfsResultAndThrowIfNecessary(int result)
}
else
{
- throw Interop.GetExceptionForIoErrno(errorInfo, isDirectory: true);
+ throw Interop.GetExceptionForIoErrno(errorInfo);
}
}
}
diff --git a/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs b/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs
index 6439e2496ad616..2cc4226613ff26 100644
--- a/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs
+++ b/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs
@@ -787,8 +787,7 @@ private bool TryReadEvent(out NotifyEvent notifyEvent)
{
fixed (byte* buf = &_buffer[0])
{
- _bufferAvailable = Interop.CheckIo(Interop.Sys.Read(_inotifyHandle, buf, this._buffer.Length),
- isDirectory: true);
+ _bufferAvailable = Interop.CheckIo(Interop.Sys.Read(_inotifyHandle, buf, this._buffer.Length));
Debug.Assert(_bufferAvailable <= this._buffer.Length);
}
}
diff --git a/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs b/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs
index ba8cc8f4ee1ece..c561022ed66c87 100644
--- a/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs
+++ b/src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs
@@ -160,7 +160,7 @@ internal unsafe RunningInstance(
_fullDirectory = Interop.Sys.RealPath(_fullDirectory);
if (_fullDirectory is null)
{
- throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), _fullDirectory, isDirectory: true);
+ throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), _fullDirectory, isDirError: true);
}
// Also ensure it has a trailing slash.
diff --git a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
index b30b9ffc44129c..fb5c8faad46880 100644
--- a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
+++ b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
@@ -105,43 +105,17 @@ private static SafeFileHandle Open(string path, Interop.Sys.OpenFlags flags, int
throw ex;
}
- // If we fail to open the file due to a path not existing, we need to know whether to blame
- // the file itself or its directory. If we're creating the file, then we blame the directory,
- // otherwise we blame the file.
- //
- // When opening, we need to align with Windows, which considers a missing path to be
- // FileNotFound only if the containing directory exists.
-
- bool isDirectory = (error.Error == Interop.Error.ENOENT) &&
- ((flags & Interop.Sys.OpenFlags.O_CREAT) != 0
- || !DirectoryExists(System.IO.Path.GetDirectoryName(System.IO.Path.TrimEndingDirectorySeparator(path!))!));
-
if (error.Error == Interop.Error.EISDIR)
{
error = Interop.Error.EACCES.Info();
}
- Interop.CheckIo(
- error.Error,
- path,
- isDirectory);
+ Interop.CheckIo(error.Error, path);
}
return handle;
}
- private static bool DirectoryExists(string fullPath)
- {
- Interop.Sys.FileStatus fileinfo;
-
- if (Interop.Sys.Stat(fullPath, out fileinfo) < 0)
- {
- return false;
- }
-
- return ((fileinfo.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR);
- }
-
// Each thread will have its own copy. This prevents race conditions if the handle had the last error.
[ThreadStatic]
internal static Interop.ErrorInfo? t_lastCloseErrorInfo;
@@ -336,7 +310,7 @@ private bool Init(string path, FileMode mode, FileAccess access, FileShare share
if ((status.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR)
{
- throw Interop.GetExceptionForIoErrno(Interop.Error.EACCES.Info(), path, isDirectory: true);
+ throw Interop.GetExceptionForIoErrno(Interop.Error.EACCES.Info(), path);
}
if ((status.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFREG)
@@ -367,7 +341,7 @@ private bool Init(string path, FileMode mode, FileAccess access, FileShare share
Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
if (errorInfo.Error == Interop.Error.EWOULDBLOCK)
{
- throw Interop.GetExceptionForIoErrno(errorInfo, path, isDirectory: false);
+ throw Interop.GetExceptionForIoErrno(errorInfo, path);
}
}
@@ -434,7 +408,7 @@ private bool Init(string path, FileMode mode, FileAccess access, FileShare share
// We know the file descriptor is valid and we know the size argument to FTruncate is correct,
// so if EBADF or EINVAL is returned, it means we're dealing with a special file that can't be
// truncated. Ignore the error in such cases; in all others, throw.
- throw Interop.GetExceptionForIoErrno(errorInfo, path, isDirectory: false);
+ throw Interop.GetExceptionForIoErrno(errorInfo, path);
}
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.UnixOrBrowser.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.UnixOrBrowser.cs
index 846147ec3a7bc6..3f04333e6b3932 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Environment.UnixOrBrowser.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Environment.UnixOrBrowser.cs
@@ -17,7 +17,7 @@ public static partial class Environment
private static string CurrentDirectoryCore
{
get => Interop.Sys.GetCwd();
- set => Interop.CheckIo(Interop.Sys.ChDir(value), value, isDirectory: true);
+ set => Interop.CheckIo(Interop.Sys.ChDir(value), value, isDirError: true);
}
private static string ExpandEnvironmentVariablesCore(string name)
diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs
index 7262476bee23df..a13ed274b7e640 100644
--- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs
@@ -76,7 +76,7 @@ private IntPtr CreateDirectoryHandle(string path, bool ignoreNotFound = false)
{
return IntPtr.Zero;
}
- throw Interop.GetExceptionForIoErrno(info, path, isDirectory: true);
+ throw Interop.GetExceptionForIoErrno(info, path, isDirError: true);
}
return handle;
}
@@ -198,7 +198,7 @@ private unsafe void FindNextEntry(byte* entryBufferPtr, int bufferLength)
}
else
{
- throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(result), _currentPath, isDirectory: true);
+ throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(result), _currentPath, isDirError: true);
}
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.Unix.cs
index 1adeaa5decb85b..fe14a0aa99a19f 100644
--- a/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.Unix.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileStatus.Unix.cs
@@ -11,14 +11,15 @@ internal partial struct FileStatus
{
private const int NanosecondsPerTick = 100;
- private const int InitializedExistsBrokenLink = -4; // target is link with no target.
- private const int InitializedExistsDir = -3; // target is directory.
- private const int InitializedExistsFile = -2; // target is file.
+ private const int InitializedExistsBrokenLink = -5; // target is link with no target.
+ private const int InitializedExistsDir = -4; // target is directory.
+ private const int InitializedExistsFile = -3; // target is file.
+ private const int InitializedNotExistsNotADir = -2; // entry parent path is not a dir.
private const int InitializedNotExists = -1; // entry does not exist.
private const int Uninitialized = 0; // uninitialized, '0' to make default(FileStatus) uninitialized.
// Tracks the initialization state.
- // < 0 : initialized successfully. Value is InitializedNotExists, InitializedExistsFile, InitializedExistsDir or InitializedExistsBrokenLink.
+ // < 0 : initialized succesfully. Value is one of the Initialized* consts.
// 0 : uninitialized.
// > 0 : initialized with error. Value is raw errno.
private int _state;
@@ -240,7 +241,7 @@ private void SetAttributes(SafeFileHandle? handle, string? path, FileAttributes
EnsureCachesInitialized(handle, path);
if (!EntryExists)
- FileSystemInfo.ThrowNotFound(path);
+ ThrowNotFound(path);
if (Interop.Sys.CanSetHiddenFlag)
{
@@ -385,7 +386,7 @@ private unsafe void SetAccessOrWriteTimeCore(SafeFileHandle? handle, string? pat
EnsureCachesInitialized(handle, path);
if (!EntryExists)
- FileSystemInfo.ThrowNotFound(path);
+ ThrowNotFound(path);
// we use utimes()/utimensat() to set the accessTime and writeTime
Interop.Sys.TimeSpec* buf = stackalloc Interop.Sys.TimeSpec[2];
@@ -480,15 +481,6 @@ private void SetUnixFileMode(SafeFileHandle? handle, string? path, UnixFileMode
throw new ArgumentException(SR.Arg_InvalidUnixFileMode, nameof(UnixFileMode));
}
- // Use ThrowNotFound to throw the appropriate exception when the file doesn't exist.
- if (handle is null && path is not null)
- {
- EnsureCachesInitialized(path);
-
- if (!EntryExists || IsBrokenLink)
- FileSystemInfo.ThrowNotFound(path);
- }
-
// Linux does not support link permissions.
// To have consistent cross-platform behavior we operate on the link target.
int rv = handle is not null ? Interop.Sys.FChMod(handle, (int)mode)
@@ -518,15 +510,18 @@ internal void RefreshCaches(SafeFileHandle? handle, ReadOnlySpan path)
{
Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
- if (errorInfo.Error == Interop.Error.ENOENT || // A component of the path does not exist, or path is an empty string
- errorInfo.Error == Interop.Error.ENOTDIR) // A component of the path prefix of path is not a directory
+ switch (errorInfo.Error)
{
- _state = InitializedNotExists;
- }
- else
- {
- Debug.Assert(errorInfo.RawErrno > 0); // Expect a positive integer
- _state = errorInfo.RawErrno; // Initialized with error.
+ case Interop.Error.ENOENT:
+ _state = InitializedNotExists;
+ break;
+ case Interop.Error.ENOTDIR:
+ _state = InitializedNotExistsNotADir;
+ break;
+ default:
+ Debug.Assert(errorInfo.RawErrno > 0); // Expect a positive integer
+ _state = errorInfo.RawErrno; // Initialized with error.
+ break;
}
return;
@@ -591,5 +586,11 @@ private static long UnixTimeSecondsToNanoseconds(DateTimeOffset time, long secon
const long TicksPerSecond = TicksPerMillisecond * 1000;
return (time.UtcDateTime.Ticks - DateTimeOffset.UnixEpoch.Ticks - seconds * TicksPerSecond) * NanosecondsPerTick;
}
+
+ private void ThrowNotFound(string? path)
+ {
+ Interop.Error error = _state == InitializedNotExistsNotADir ? Interop.Error.ENOTDIR : Interop.Error.ENOENT;
+ throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(error), path);
+ }
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs
index dd28e27822605d..67237805c3a744 100644
--- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs
@@ -89,34 +89,23 @@ private static void LinkOrCopyFile (string sourceFullPath, string destFullPath)
{
// The operation failed. Within reason, try to determine which path caused the problem
// so we can throw a detailed exception.
- string? path = null;
- bool isDirectory = false;
if (errorInfo.Error == Interop.Error.ENOENT)
{
if (!Directory.Exists(Path.GetDirectoryName(destFullPath)))
{
- // The parent directory of destFile can't be found.
- // Windows distinguishes between whether the directory or the file isn't found,
- // and throws a different exception in these cases. We attempt to approximate that
- // here; there is a race condition here, where something could change between
- // when the error occurs and our checks, but it's the best we can do, and the
- // worst case in such a race condition (which could occur if the file system is
- // being manipulated concurrently with these checks) is that we throw a
- // FileNotFoundException instead of DirectoryNotFoundexception.
- path = destFullPath;
- isDirectory = true;
+ throw Interop.GetExceptionForIoErrno(errorInfo, destFullPath, isDirError: true);
}
else
{
- path = sourceFullPath;
+ throw Interop.GetExceptionForIoErrno(errorInfo, sourceFullPath);
}
}
else if (errorInfo.Error == Interop.Error.EEXIST)
{
- path = destFullPath;
+ throw Interop.GetExceptionForIoErrno(errorInfo, destFullPath);
}
- throw Interop.GetExceptionForIoErrno(errorInfo, path, isDirectory);
+ throw Interop.GetExceptionForIoErrno(errorInfo);
}
}
@@ -125,12 +114,8 @@ public static void ReplaceFile(string sourceFullPath, string destFullPath, strin
{
// Unix rename works in more cases, we limit to what is allowed by Windows File.Replace.
// These checks are not atomic, the file could change after a check was performed and before it is renamed.
- Interop.Sys.FileStatus sourceStat;
- if (Interop.Sys.LStat(sourceFullPath, out sourceStat) != 0)
- {
- Interop.ErrorInfo errno = Interop.Sys.GetLastErrorInfo();
- throw Interop.GetExceptionForIoErrno(errno, sourceFullPath);
- }
+ Interop.CheckIo(Interop.Sys.LStat(sourceFullPath, out Interop.Sys.FileStatus sourceStat), sourceFullPath);
+
// Check source is not a directory.
if ((sourceStat.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR)
{
@@ -208,16 +193,7 @@ public static void MoveFile(string sourceFullPath, string destFullPath, bool ove
}
else
{
- // Windows distinguishes between whether the directory or the file isn't found,
- // and throws a different exception in these cases. We attempt to approximate that
- // here; there is a race condition here, where something could change between
- // when the error occurs and our checks, but it's the best we can do, and the
- // worst case in such a race condition (which could occur if the file system is
- // being manipulated concurrently with these checks) is that we throw a
- // FileNotFoundException instead of DirectoryNotFoundException.
- throw Interop.GetExceptionForIoErrno(errorInfo, destFullPath,
- isDirectory: errorInfo.Error == Interop.Error.ENOENT && !Directory.Exists(Path.GetDirectoryName(destFullPath)) // The parent directory of destFile can't be found
- );
+ throw Interop.GetExceptionForIoErrno(errorInfo, destFullPath);
}
}
@@ -305,7 +281,10 @@ public static void CreateDirectory(string fullPath, UnixFileMode unixCreateMode)
return; // fullPath is '/'.
}
- int result = Interop.Sys.MkDir(fullPath, (int)unixCreateMode);
+ // macOS returns ENOTDIR when the path refers to a file and ends with '/'.
+ // Trim the separator so we get EEXIST instead.
+ ReadOnlySpan path = PathInternal.TrimEndingDirectorySeparator(fullPath.AsSpan());
+ int result = Interop.Sys.MkDir(path, (int)unixCreateMode);
if (result == 0)
{
return; // Created directory.
@@ -322,7 +301,7 @@ public static void CreateDirectory(string fullPath, UnixFileMode unixCreateMode)
}
else
{
- throw Interop.GetExceptionForIoErrno(errorInfo, fullPath, isDirectory: true);
+ throw Interop.GetExceptionForIoErrno(errorInfo, fullPath);
}
}
@@ -372,7 +351,7 @@ private static void CreateParentsAndDirectory(string fullPath, UnixFileMode unix
}
else
{
- throw Interop.GetExceptionForIoErrno(errorInfo, mkdirPath.ToString(), isDirectory: true);
+ throw Interop.GetExceptionForIoErrno(errorInfo, mkdirPath.ToString());
}
i--;
} while (i > 0);
@@ -400,7 +379,7 @@ private static void CreateParentsAndDirectory(string fullPath, UnixFileMode unix
}
}
- throw Interop.GetExceptionForIoErrno(errorInfo, mkdirPath.ToString(), isDirectory: true);
+ throw Interop.GetExceptionForIoErrno(errorInfo, mkdirPath.ToString());
}
}
}
@@ -469,7 +448,7 @@ private static void MoveDirectory(string sourceFullPath, string destFullPath, bo
case Interop.Error.ENOTDIR: // sourceFullPath exists and it's not a directory
throw new IOException(SR.Format(SR.IO_PathNotFound_Path, sourceFullPath));
default:
- throw Interop.GetExceptionForIoErrno(errorInfo, isDirectory: true);
+ throw Interop.GetExceptionForIoErrno(errorInfo);
}
}
}
@@ -576,7 +555,7 @@ private static bool RemoveEmptyDirectory(string fullPath, bool topLevel = false,
throw new IOException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, fullPath));
}
- throw Interop.GetExceptionForIoErrno(errorInfo, fullPath, isDirectory: true);
+ throw Interop.GetExceptionForIoErrno(errorInfo, fullPath, isDirError: true);
}
return true;
@@ -595,7 +574,7 @@ public static FileAttributes GetAttributes(string fullPath)
FileAttributes attributes = new FileInfo(fullPath, null).Attributes;
if (attributes == (FileAttributes)(-1))
- FileSystemInfo.ThrowNotFound(fullPath);
+ throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(Interop.Error.ENOENT), fullPath);
return attributes;
}
@@ -614,7 +593,7 @@ public static UnixFileMode GetUnixFileMode(string fullPath)
UnixFileMode mode = default(FileStatus).GetUnixFileMode(fullPath);
if (mode == (UnixFileMode)(-1))
- FileSystemInfo.ThrowNotFound(fullPath);
+ throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(Interop.Error.ENOENT), fullPath);
return mode;
}
@@ -675,7 +654,7 @@ public static string[] GetLogicalDrives()
internal static void CreateSymbolicLink(string path, string pathToTarget, bool isDirectory)
{
- Interop.CheckIo(Interop.Sys.SymLink(pathToTarget, path), path, isDirectory);
+ Interop.CheckIo(Interop.Sys.SymLink(pathToTarget, path), path);
}
internal static FileSystemInfo? ResolveLinkTarget(string linkPath, bool returnFinalTarget, bool isDirectory)
diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs
index fbea595b861f3d..faf3af387cc00c 100644
--- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs
@@ -289,7 +289,7 @@ private static void GetFindData(string fullPath, bool isDirectory, bool ignoreAc
// File not found doesn't make much sense coming from a directory.
if (isDirectory && errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND)
errorCode = Interop.Errors.ERROR_PATH_NOT_FOUND;
- if (isDirectory && errorCode == Interop.Errors.ERROR_ACCESS_DENIED && ignoreAccessDenied)
+ if (ignoreAccessDenied && errorCode == Interop.Errors.ERROR_ACCESS_DENIED)
return;
throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.Unix.cs
index 30242825dbf8d2..0c3dc399a0874d 100644
--- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.Unix.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.Unix.cs
@@ -75,24 +75,6 @@ public void Refresh()
_fileStatus.RefreshCaches(FullPath);
}
- internal static void ThrowNotFound(ReadOnlySpan path)
- {
- ThrowNotFound(path.Length == 0 ? default : path.ToString());
- }
-
- internal static void ThrowNotFound(string? path)
- {
- // Windows distinguishes between whether the directory or the file isn't found,
- // and throws a different exception in these cases. We attempt to approximate that
- // here; there is a race condition here, where something could change between
- // when the error occurs and our checks, but it's the best we can do, and the
- // worst case in such a race condition (which could occur if the file system is
- // being manipulated concurrently with these checks) is that we throw a
- // FileNotFoundException instead of DirectoryNotFoundException.
- bool directoryError = path is not null && !FileSystem.DirectoryExists(Path.GetDirectoryName(Path.TrimEndingDirectorySeparator(path.AsSpan())));
- throw Interop.GetExceptionForIoErrno(new Interop.ErrorInfo(Interop.Error.ENOENT), path, directoryError);
- }
-
// There is no special handling for Unix- see Windows code for the reason we do this
internal string NormalizedPath => FullPath;
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Unix.cs
index 534a49217408cb..9e2f06d2d015ff 100644
--- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Unix.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Unix.cs
@@ -23,7 +23,7 @@ internal static long CheckFileCall(long result, string? path, bool ignoreNotSupp
Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
if (!(ignoreNotSupported && errorInfo.Error == Interop.Error.ENOTSUP))
{
- throw Interop.GetExceptionForIoErrno(errorInfo, path, isDirectory: false);
+ throw Interop.GetExceptionForIoErrno(errorInfo, path);
}
}
@@ -51,7 +51,7 @@ internal static void FlushToDisk(SafeFileHandle handle)
// In such cases there's nothing to flush.
break;
default:
- throw Interop.GetExceptionForIoErrno(errorInfo, handle.Path, isDirectory: false);
+ throw Interop.GetExceptionForIoErrno(errorInfo, handle.Path);
}
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs
index a36afb7aa0d295..a9d6c462610fe6 100644
--- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs
@@ -194,7 +194,7 @@ private static unsafe void EnumerateFilesRecursively(string path, Predicate