From 5ce6618ed5690d4be6b943e36ffccfb09e4ee73a Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Mon, 17 Jan 2022 11:42:35 +0100 Subject: [PATCH] FileSystemEntry.Unix: don't make a syscall to check hidden on Linux. --- .../Interop/Unix/System.Native/Interop.LChflags.cs | 6 ++++++ .../System/IO/Enumeration/FileSystemEntry.Unix.cs | 2 +- .../src/System/IO/FileStatus.Unix.cs | 12 +++++++++--- src/native/libs/System.Native/entrypoints.c | 1 + src/native/libs/System.Native/pal_io.c | 11 ++++++++++- src/native/libs/System.Native/pal_io.h | 7 +++++++ 6 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs index 1353fbc3acec63..a5bc36dfa3d2fc 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs @@ -22,5 +22,11 @@ internal enum UserFlags : uint [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LChflagsCanSetHiddenFlag")] [SuppressGCTransition] private static partial int LChflagsCanSetHiddenFlag(); + + internal static readonly bool SupportsHiddenFlag = (CanGetHiddenFlag() != 0); + + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CanGetHiddenFlag")] + [SuppressGCTransition] + private static partial int CanGetHiddenFlag(); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Unix.cs index 1be3942011b2fd..89c38584eea320 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Unix.cs @@ -145,7 +145,7 @@ public FileAttributes Attributes public DateTimeOffset CreationTimeUtc => _status.GetCreationTime(FullPath, continueOnError: true); public DateTimeOffset LastAccessTimeUtc => _status.GetLastAccessTime(FullPath, continueOnError: true); public DateTimeOffset LastWriteTimeUtc => _status.GetLastWriteTime(FullPath, continueOnError: true); - public bool IsHidden => _status.IsHidden(FullPath, FileName, continueOnError: true); + public bool IsHidden => _status.IsFileSystemEntryHidden(FullPath, FileName); internal bool IsReadOnly => _status.IsReadOnly(FullPath, continueOnError: true); public bool IsDirectory => _status.InitiallyDirectory; 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 05b4bbcff6a2aa..20961a8fbbc2e4 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 @@ -145,14 +145,20 @@ internal bool IsReadOnly(ReadOnlySpan path, bool continueOnError = false) return HasReadOnlyFlag; } - internal bool IsHidden(ReadOnlySpan path, ReadOnlySpan fileName, bool continueOnError = false) + internal bool IsFileSystemEntryHidden(ReadOnlySpan path, ReadOnlySpan fileName) { - // Avoid disk hit first + // Because this is called for FileSystemEntry we can assume the entry exists and + // avoid initialization in some cases. if (IsNameHidden(fileName)) { return true; } - EnsureCachesInitialized(path, continueOnError); + if (!Interop.Sys.SupportsHiddenFlag) + { + return false; + } + + EnsureCachesInitialized(path, continueOnError: true); return HasHiddenFlag; } diff --git a/src/native/libs/System.Native/entrypoints.c b/src/native/libs/System.Native/entrypoints.c index 0e54f4b5f15193..9ac04de3e0d66f 100644 --- a/src/native/libs/System.Native/entrypoints.c +++ b/src/native/libs/System.Native/entrypoints.c @@ -109,6 +109,7 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_LockFileRegion) DllImportEntry(SystemNative_LChflags) DllImportEntry(SystemNative_LChflagsCanSetHiddenFlag) + DllImportEntry(SystemNative_CanGetHiddenFlag) DllImportEntry(SystemNative_ReadProcessStatusInfo) DllImportEntry(SystemNative_Log) DllImportEntry(SystemNative_LogError) diff --git a/src/native/libs/System.Native/pal_io.c b/src/native/libs/System.Native/pal_io.c index 66c934ed182fa0..d11ce950f12460 100644 --- a/src/native/libs/System.Native/pal_io.c +++ b/src/native/libs/System.Native/pal_io.c @@ -1553,7 +1553,16 @@ int32_t SystemNative_LChflags(const char* path, uint32_t flags) int32_t SystemNative_LChflagsCanSetHiddenFlag(void) { -#if defined(UF_HIDDEN) && defined(HAVE_STAT_FLAGS) && defined(HAVE_LCHFLAGS) +#if defined(HAVE_LCHFLAGS) + return SystemNative_CanGetHiddenFlag(); +#else + return false; +#endif +} + +int32_t SystemNative_CanGetHiddenFlag(void) +{ +#if defined(UF_HIDDEN) && defined(HAVE_STAT_FLAGS) return true; #else return false; diff --git a/src/native/libs/System.Native/pal_io.h b/src/native/libs/System.Native/pal_io.h index 726b097aff1332..6ebde79230af95 100644 --- a/src/native/libs/System.Native/pal_io.h +++ b/src/native/libs/System.Native/pal_io.h @@ -744,6 +744,13 @@ PALEXPORT int32_t SystemNative_LChflags(const char* path, uint32_t flags); */ PALEXPORT int32_t SystemNative_LChflagsCanSetHiddenFlag(void); +/** + * Determines if the current platform supports getting UF_HIDDEN (0x8000) flag + * + * Returns true (non-zero) if supported, false (zero) if not. + */ +PALEXPORT int32_t SystemNative_CanGetHiddenFlag(void); + /** * Reads the psinfo_t struct and converts into ProcessStatus. *