Skip to content

Commit

Permalink
Directory.Delete: prefer DirectoryNotFoundException over Unauthorized…
Browse files Browse the repository at this point in the history
…Access IOException. (#62396)

* Directory.Delete: prefer DirectoryNotFoundException over UnauthorizedAccess IOException.

* Refactor error handling.
  • Loading branch information
tmds committed Dec 16, 2021
1 parent 99d82c2 commit a4f169c
Showing 1 changed file with 36 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -492,43 +492,45 @@ private static bool RemoveEmptyDirectory(string fullPath, bool topLevel = false,
if (Interop.Sys.RmDir(fullPath) < 0)
{
Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
switch (errorInfo.Error)

if (errorInfo.Error == Interop.Error.ENOTEMPTY)
{
case Interop.Error.EACCES:
case Interop.Error.EPERM:
case Interop.Error.EROFS:
case Interop.Error.EISDIR:
throw new IOException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, fullPath)); // match Win32 exception
case Interop.Error.ENOENT:
// When we're recursing, don't throw for items that go missing.
if (!topLevel)
{
return true;
}
goto default;
case Interop.Error.ENOTDIR:
// When the top-level path is a symlink to a directory, delete the link.
// In other cases, throw because we expect path to be a real directory.
if (topLevel)
{
if (!DirectoryExists(fullPath))
{
throw Interop.GetExceptionForIoErrno(Interop.Error.ENOENT.Info(), fullPath, isDirectory: true);
}
if (!throwWhenNotEmpty)
{
return false;
}
}
else if (errorInfo.Error == Interop.Error.ENOENT)
{
// When we're recursing, don't throw for items that go missing.
if (!topLevel)
{
return true;
}
}
else if (DirectoryExists(fullPath, out Interop.ErrorInfo existErr))
{
// Top-level path is a symlink to a directory, delete the link.
if (topLevel && errorInfo.Error == Interop.Error.ENOTDIR)
{
DeleteFile(fullPath);
return true;
}
}
else if (existErr.Error == Interop.Error.ENOENT)
{
// Prefer throwing DirectoryNotFoundException over other exceptions.
errorInfo = existErr;
}

DeleteFile(fullPath);
return true;
}
goto default;
case Interop.Error.ENOTEMPTY:
if (!throwWhenNotEmpty)
{
return false;
}
goto default;
default:
throw Interop.GetExceptionForIoErrno(errorInfo, fullPath, isDirectory: true);
if (errorInfo.Error == Interop.Error.EACCES ||
errorInfo.Error == Interop.Error.EPERM ||
errorInfo.Error == Interop.Error.EROFS)
{
throw new IOException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, fullPath));
}

throw Interop.GetExceptionForIoErrno(errorInfo, fullPath, isDirectory: true);
}

return true;
Expand Down

0 comments on commit a4f169c

Please sign in to comment.