Skip to content

Commit

Permalink
SafeFileHandle.Unix: omit stat call when opening file with write acce…
Browse files Browse the repository at this point in the history
…ss. (#55206)
  • Loading branch information
tmds authored Jul 7, 2021
1 parent 9ce467f commit c6b61fb
Showing 1 changed file with 23 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,26 +64,31 @@ private static SafeFileHandle Open(string path, Interop.Sys.OpenFlags flags, int

// Make sure it's not a directory; we do this after opening it once we have a file descriptor
// to avoid race conditions.
Interop.Sys.FileStatus status;
if (Interop.Sys.FStat(handle, out status) != 0)
//
// We can omit the check when write access is requested. open will have failed with EISDIR.
if ((flags & (Interop.Sys.OpenFlags.O_WRONLY | Interop.Sys.OpenFlags.O_RDWR)) == 0)
{
Interop.ErrorInfo error = Interop.Sys.GetLastErrorInfo();
handle.Dispose();
throw Interop.GetExceptionForIoErrno(error, path);
}
if ((status.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR)
{
handle.Dispose();
throw Interop.GetExceptionForIoErrno(Interop.Error.EACCES.Info(), path, isDirectory: true);
}
Interop.Sys.FileStatus status;
if (Interop.Sys.FStat(handle, out status) != 0)
{
Interop.ErrorInfo error = Interop.Sys.GetLastErrorInfo();
handle.Dispose();
throw Interop.GetExceptionForIoErrno(error, path);
}
if ((status.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR)
{
handle.Dispose();
throw Interop.GetExceptionForIoErrno(Interop.Error.EACCES.Info(), path, isDirectory: true);
}

if ((status.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFREG)
{
// we take advantage of the information provided by the fstat syscall
// and for regular files (most common case)
// avoid one extra sys call for determining whether file can be seeked
handle._canSeek = NullableBool.True;
Debug.Assert(Interop.Sys.LSeek(handle, 0, Interop.Sys.SeekWhence.SEEK_CUR) >= 0);
if ((status.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFREG)
{
// we take advantage of the information provided by the fstat syscall
// and for regular files (most common case)
// avoid one extra sys call for determining whether file can be seeked
handle._canSeek = NullableBool.True;
Debug.Assert(Interop.Sys.LSeek(handle, 0, Interop.Sys.SeekWhence.SEEK_CUR) >= 0);
}
}

return handle;
Expand Down

0 comments on commit c6b61fb

Please sign in to comment.