Skip to content

Commit

Permalink
Defering some more file checking actions to FileStatus. Addressing ac…
Browse files Browse the repository at this point in the history
…cessibility of methods/properties. Addressing suggestions.
  • Loading branch information
carlossanlop authored and carlossanlop committed May 5, 2021
1 parent 6ff6dcc commit 2423af0
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ internal static FileAttributes Initialize(
// directory.
if (isSymlink || isUnknown)
{
// DT_LNK: stat to it to see if we can resolve it to a directory
entry._status.TryRefreshSymbolicLinkCache(entry.FullPath);
isDirectory = entry._status.HasDirectoryFlag;
// DT_LNK and DT_UNKNOWN: stat to it to see if we can resolve it to a directory
isDirectory = entry._status.IsDirectory(entry.FullPath);
}

// Same idea as the directory check, just repeated for (and tweaked due to the
// nature of) symlinks.
if (isUnknown)
{
entry._status.TryRefreshFileCache(entry.FullPath);
isSymlink = entry._status.HasSymbolicLinkFlag;
isSymlink = entry._status.IsSymbolicLink(entry.FullPath);
}

entry._status.InitiallyDirectory = isDirectory;
Expand All @@ -63,10 +63,9 @@ internal static FileAttributes Initialize(
attributes |= FileAttributes.ReparsePoint;
if (isDirectory)
attributes |= FileAttributes.Directory;
if ((directoryEntry.NameLength > 0 && directoryEntry.Name[0] == '.') ||
(entry._status.IsFileCacheInitialized && entry._status.HasHiddenFlag)) // soft retrieval
if ((directoryEntry.NameLength > 0 && directoryEntry.Name[0] == '.') || entry._status.HasHiddenFlag) // soft retrieval
attributes |= FileAttributes.Hidden;
if (entry._status.IsFileCacheInitialized && entry._status.HasReadOnlyFlag) // soft retrieval
if (entry._status.HasReadOnlyFlag) // soft retrieval
attributes |= FileAttributes.ReadOnly;

return attributes;
Expand Down
30 changes: 18 additions & 12 deletions src/libraries/System.IO.FileSystem/src/System/IO/FileStatus.Unix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ internal struct FileStatus
// Exists as of the last refresh
private bool _exists;

internal bool IsFileCacheInitialized => _initializedFileCache == 0;
internal bool IsSymlinkCacheInitialized => _initializedSymlinkCache == 0;
private bool IsFileCacheInitialized => _initializedFileCache == 0;
private bool IsSymlinkCacheInitialized => _initializedSymlinkCache == 0;

internal bool AreCachesInitialized =>
private bool AreCachesInitialized =>
// The file cache should always be successfully refreshed
_initializedFileCache == 0 &&
// The symbolic link cache only gets refreshed when the path is detected
Expand All @@ -56,7 +56,8 @@ internal bool HasHiddenFlag
get
{
Debug.Assert(IsFileCacheInitialized);
return (_fileCache.UserFlags & (uint)Interop.Sys.UserFlags.UF_HIDDEN) == (uint)Interop.Sys.UserFlags.UF_HIDDEN;
return IsFileCacheInitialized &&
(_fileCache.UserFlags & (uint)Interop.Sys.UserFlags.UF_HIDDEN) == (uint)Interop.Sys.UserFlags.UF_HIDDEN;
}
}

Expand All @@ -67,6 +68,10 @@ internal bool HasReadOnlyFlag
get
{
Debug.Assert(IsFileCacheInitialized);
if (!IsFileCacheInitialized)
{
return false;
}
#if TARGET_BROWSER
const Interop.Sys.Permissions readBit = Interop.Sys.Permissions.S_IRUSR;
const Interop.Sys.Permissions writeBit = Interop.Sys.Permissions.S_IWUSR;
Expand All @@ -93,8 +98,8 @@ internal bool HasReadOnlyFlag
}
#endif

return ((_fileCache.Mode & (int)readBit) != 0 && // has read permission
(_fileCache.Mode & (int)writeBit) == 0); // but not write permission
return (_fileCache.Mode & (int)readBit) != 0 && // has read permission
(_fileCache.Mode & (int)writeBit) == 0; // but not write permission
}
}

Expand All @@ -105,7 +110,8 @@ internal bool HasSymbolicLinkFlag
get
{
Debug.Assert(IsFileCacheInitialized);
return (_fileCache.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFLNK;
return IsFileCacheInitialized &&
(_fileCache.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFLNK;
}
}

Expand Down Expand Up @@ -175,7 +181,7 @@ internal bool IsSymbolicLink(ReadOnlySpan<char> path, bool continueOnError = fal
return HasSymbolicLinkFlag;
}

public FileAttributes GetAttributes(ReadOnlySpan<char> path, ReadOnlySpan<char> fileName)
internal FileAttributes GetAttributes(ReadOnlySpan<char> path, ReadOnlySpan<char> fileName)
{
EnsureCachesInitialized(path);

Expand All @@ -199,7 +205,7 @@ public FileAttributes GetAttributes(ReadOnlySpan<char> path, ReadOnlySpan<char>
return attributes != default ? attributes : FileAttributes.Normal;
}

public void SetAttributes(string path, FileAttributes attributes)
internal void SetAttributes(string path, FileAttributes attributes)
{
// Validate that only flags from the attribute are being provided. This is an
// approximation for the validation done by the Win32 function.
Expand Down Expand Up @@ -368,7 +374,7 @@ internal long GetLength(ReadOnlySpan<char> path, bool continueOnError = false)

// Tries to refresh the lstat cache (_fileCache) and, if the file is pointing to a symbolic link, then also the stat cache (_symlinkCache)
// This method should not throw. Instead, we store the results, and we will throw when the user attempts to access any of the properties when there was a failure
public void RefreshCaches(ReadOnlySpan<char> path)
internal void RefreshCaches(ReadOnlySpan<char> path)
{
_isDirectory = false;
path = Path.TrimEndingDirectorySeparator(path);
Expand Down Expand Up @@ -436,10 +442,10 @@ private void ThrowOnCacheInitializationError(ReadOnlySpan<char> path)
}
}

internal bool TryRefreshFileCache(ReadOnlySpan<char> path, bool verify = true) =>
private bool TryRefreshFileCache(ReadOnlySpan<char> path) =>
VerifyStatCall(Interop.Sys.LStat(path, out _fileCache), out _initializedFileCache);

internal bool TryRefreshSymbolicLinkCache(ReadOnlySpan<char> path, bool verify = true) =>
private bool TryRefreshSymbolicLinkCache(ReadOnlySpan<char> path) =>
VerifyStatCall(Interop.Sys.Stat(path, out _symlinkCache), out _initializedSymlinkCache);

// Receives the return value of a stat or lstat call.
Expand Down

0 comments on commit 2423af0

Please sign in to comment.