From 71d131a4157c05d8d784e4140884c6db5d245cb8 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Wed, 7 Jul 2021 11:58:08 +0200 Subject: [PATCH 01/15] use fstatfs to detect whether current file system supports shared locks for files opened for writing --- .../Unix/System.Native/Interop.Fstatfs.cs | 14 ++++++++++ .../Native/Unix/Common/pal_config.h.in | 2 ++ .../Native/Unix/System.Native/entrypoints.c | 1 + .../Native/Unix/System.Native/pal_io.c | 16 ++++++++++++ .../Native/Unix/System.Native/pal_io.h | 5 ++++ src/libraries/Native/Unix/configure.cmake | 22 ++++++++++++++++ .../Win32/SafeHandles/SafeFileHandle.Unix.cs | 26 ++++++++++++++++++- .../System.Private.CoreLib.Shared.projitems | 3 +++ 8 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fstatfs.cs diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fstatfs.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fstatfs.cs new file mode 100644 index 00000000000000..08d206b17e9097 --- /dev/null +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fstatfs.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetFileSystemType")] + internal static extern long GetFileSystemType(SafeFileHandle fd); + } +} diff --git a/src/libraries/Native/Unix/Common/pal_config.h.in b/src/libraries/Native/Unix/Common/pal_config.h.in index 2b86ed15d4cae7..39e73f5c0cce45 100644 --- a/src/libraries/Native/Unix/Common/pal_config.h.in +++ b/src/libraries/Native/Unix/Common/pal_config.h.in @@ -5,6 +5,8 @@ #cmakedefine01 HAVE_MMAP64 #cmakedefine01 HAVE_FTRUNCATE64 #cmakedefine01 HAVE_POSIX_FADVISE64 +#cmakedefine01 HAVE_STATFS64 +#cmakedefine01 HAVE_STATFS #cmakedefine01 HAVE_FLOCK64 #cmakedefine01 HAVE_F_DUPFD_CLOEXEC #cmakedefine01 HAVE_F_FULLFSYNC diff --git a/src/libraries/Native/Unix/System.Native/entrypoints.c b/src/libraries/Native/Unix/System.Native/entrypoints.c index cf6485ecf8430a..e205a9187f359a 100644 --- a/src/libraries/Native/Unix/System.Native/entrypoints.c +++ b/src/libraries/Native/Unix/System.Native/entrypoints.c @@ -103,6 +103,7 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_INotifyRemoveWatch) DllImportEntry(SystemNative_RealPath) DllImportEntry(SystemNative_GetPeerID) + DllImportEntry(SystemNative_GetFileSystemType) DllImportEntry(SystemNative_LockFileRegion) DllImportEntry(SystemNative_LChflags) DllImportEntry(SystemNative_LChflagsCanSetHiddenFlag) diff --git a/src/libraries/Native/Unix/System.Native/pal_io.c b/src/libraries/Native/Unix/System.Native/pal_io.c index d7eb6c4ab23aca..034e7a7bd7bd64 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.c +++ b/src/libraries/Native/Unix/System.Native/pal_io.c @@ -35,6 +35,9 @@ #if HAVE_INOTIFY #include #endif +#if HAVE_STATFS64 || HAVE_STATFS +#include +#endif #ifdef _AIX #include @@ -1379,6 +1382,19 @@ static int16_t ConvertLockType(int16_t managedLockType) } } +int64_t SystemNative_GetFileSystemType(intptr_t fd) +{ +#if HAVE_STATFS64 + struct statfs64 statfsArgs; + return fstatfs64(ToFileDescriptor(fd), &statfsArgs) == -1 ? -1 : statfsArgs.f_type; +#elif HAVE_STATFS + struct statfs statfsArgs; + return fstatfs(ToFileDescriptor(fd), &statfsArgs) == -1 ? -1 : statfsArgs.f_type; +#else + return 0; +#endif +} + int32_t SystemNative_LockFileRegion(intptr_t fd, int64_t offset, int64_t length, int16_t lockType) { int16_t unixLockType = ConvertLockType(lockType); diff --git a/src/libraries/Native/Unix/System.Native/pal_io.h b/src/libraries/Native/Unix/System.Native/pal_io.h index 1dc70387ad5eac..2ad6cebe1a0e58 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.h +++ b/src/libraries/Native/Unix/System.Native/pal_io.h @@ -710,6 +710,11 @@ PALEXPORT char* SystemNative_RealPath(const char* path); */ PALEXPORT int32_t SystemNative_GetPeerID(intptr_t socket, uid_t* euid); +/** +* returns false for NFS and CIFS, otherwise true +*/ +PALEXPORT int64_t SystemNative_GetFileSystemType(intptr_t fd); + /** * Attempts to lock/unlock the region of the file "fd" specified by the offset and length. lockType * can be set to F_UNLCK (2) for unlock or F_WRLCK (3) for lock. diff --git a/src/libraries/Native/Unix/configure.cmake b/src/libraries/Native/Unix/configure.cmake index b2cfdb3bc40c2a..743fd39c22998a 100644 --- a/src/libraries/Native/Unix/configure.cmake +++ b/src/libraries/Native/Unix/configure.cmake @@ -108,6 +108,28 @@ check_c_source_compiles( # /in_pktinfo +check_c_source_compiles( + " + #include + int main(void) + { + struct statfs64 s; + return 0; + } + " + HAVE_STATFS64) + +check_c_source_compiles( + " + #include + int main(void) + { + struct statfs s; + return 0; + } + " + HAVE_STATFS) + check_c_source_compiles( " #include 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 1ce14b82abe99c..aa643c990538ed 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 @@ -258,7 +258,7 @@ private void Init(string path, FileMode mode, FileAccess access, FileShare share // lock on the file and all other modes use a shared lock. While this is not as granular as Windows, not mandatory, // and not atomic with file opening, it's better than nothing. Interop.Sys.LockOperations lockOperation = (share == FileShare.None) ? Interop.Sys.LockOperations.LOCK_EX : Interop.Sys.LockOperations.LOCK_SH; - if (Interop.Sys.FLock(this, lockOperation | Interop.Sys.LockOperations.LOCK_NB) < 0) + if (CanLockTheFile(lockOperation, access) && Interop.Sys.FLock(this, lockOperation | Interop.Sys.LockOperations.LOCK_NB) < 0) { // The only error we care about is EWOULDBLOCK, which indicates that the file is currently locked by someone // else and we would block trying to access it. Other errors, such as ENOTSUP (locking isn't supported) or @@ -319,6 +319,30 @@ private void Init(string path, FileMode mode, FileAccess access, FileShare share } } + private bool CanLockTheFile(Interop.Sys.LockOperations lockOperation, FileAccess access) + { + Debug.Assert(lockOperation == Interop.Sys.LockOperations.LOCK_EX || lockOperation == Interop.Sys.LockOperations.LOCK_SH); + + if (lockOperation == Interop.Sys.LockOperations.LOCK_EX) + { + return true; // LOCK_EX is always OK + } + else if ((access & FileAccess.Write) == 0) + { + return true; // LOCK_SH is always OK when reading + } + + switch (Interop.Sys.GetFileSystemType(this)) + { + case 0x6969: // NFS_SUPER_MAGIC + case 0xFF534D42: // CIFS_MAGIC_NUMBER + case 0x517B: // SMB_SUPER_MAGIC + return false; // LOCK_SH is not OK when writing to NFS, CIFS or SMB + default: + return true; // in all other situations it should be OK + } + } + private bool GetCanSeek() { Debug.Assert(!IsClosed); diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index f344b005f933aa..4a1313f4e4f871 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -1910,6 +1910,9 @@ Common\Interop\Unix\System.Native\Interop.ErrNo.cs + + Common\Interop\Unix\System.Native\Interop.Fstatfs.cs + Common\Interop\Unix\System.Native\Interop.FLock.cs From 7980cc885e38e81447b38434037c6b6c6ee1e654 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Wed, 7 Jul 2021 12:29:28 +0200 Subject: [PATCH 02/15] improve comments --- src/libraries/Native/Unix/System.Native/pal_io.c | 1 + src/libraries/Native/Unix/System.Native/pal_io.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libraries/Native/Unix/System.Native/pal_io.c b/src/libraries/Native/Unix/System.Native/pal_io.c index 034e7a7bd7bd64..9b7468c1370efc 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.c +++ b/src/libraries/Native/Unix/System.Native/pal_io.c @@ -1391,6 +1391,7 @@ int64_t SystemNative_GetFileSystemType(intptr_t fd) struct statfs statfsArgs; return fstatfs(ToFileDescriptor(fd), &statfsArgs) == -1 ? -1 : statfsArgs.f_type; #else + // since this is just best effort, we return 0 if fstatfs is not supported return 0; #endif } diff --git a/src/libraries/Native/Unix/System.Native/pal_io.h b/src/libraries/Native/Unix/System.Native/pal_io.h index 2ad6cebe1a0e58..62c460a9e3d30a 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.h +++ b/src/libraries/Native/Unix/System.Native/pal_io.h @@ -711,7 +711,7 @@ PALEXPORT char* SystemNative_RealPath(const char* path); PALEXPORT int32_t SystemNative_GetPeerID(intptr_t socket, uid_t* euid); /** -* returns false for NFS and CIFS, otherwise true +* Returns file system type on success, or -1 on error or 0 when fstatfs is not supported. */ PALEXPORT int64_t SystemNative_GetFileSystemType(intptr_t fd); From 97c15443b5a70173944d24c138cb116afa2042ec Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Wed, 7 Jul 2021 13:31:05 +0200 Subject: [PATCH 03/15] cast in explicit way --- src/libraries/Native/Unix/System.Native/pal_io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/Native/Unix/System.Native/pal_io.c b/src/libraries/Native/Unix/System.Native/pal_io.c index 9b7468c1370efc..353ea87ee9b3b2 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.c +++ b/src/libraries/Native/Unix/System.Native/pal_io.c @@ -1386,10 +1386,10 @@ int64_t SystemNative_GetFileSystemType(intptr_t fd) { #if HAVE_STATFS64 struct statfs64 statfsArgs; - return fstatfs64(ToFileDescriptor(fd), &statfsArgs) == -1 ? -1 : statfsArgs.f_type; + return fstatfs64(ToFileDescriptor(fd), &statfsArgs) == -1 ? (int64_t)-1 : (int64_t)statfsArgs.f_type; #elif HAVE_STATFS struct statfs statfsArgs; - return fstatfs(ToFileDescriptor(fd), &statfsArgs) == -1 ? -1 : statfsArgs.f_type; + return fstatfs(ToFileDescriptor(fd), &statfsArgs) == -1 ? (int64_t)-1 : (int64_t)statfsArgs.f_type; #else // since this is just best effort, we return 0 if fstatfs is not supported return 0; From 5d95af81cc4568490b8ff9901a9ee54c13af10bd Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Wed, 7 Jul 2021 14:45:04 +0200 Subject: [PATCH 04/15] hopefully fix the BSD build(s) --- .../Native/Unix/Common/pal_config.h.in | 6 +++-- .../Native/Unix/System.Native/pal_io.c | 18 ++++++++----- src/libraries/Native/Unix/configure.cmake | 26 +++++++++++++++++-- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/libraries/Native/Unix/Common/pal_config.h.in b/src/libraries/Native/Unix/Common/pal_config.h.in index 39e73f5c0cce45..26641996107099 100644 --- a/src/libraries/Native/Unix/Common/pal_config.h.in +++ b/src/libraries/Native/Unix/Common/pal_config.h.in @@ -5,8 +5,10 @@ #cmakedefine01 HAVE_MMAP64 #cmakedefine01 HAVE_FTRUNCATE64 #cmakedefine01 HAVE_POSIX_FADVISE64 -#cmakedefine01 HAVE_STATFS64 -#cmakedefine01 HAVE_STATFS +#cmakedefine01 HAVE_STATFS64_VFS +#cmakedefine01 HAVE_STATFS64_MOUNT +#cmakedefine01 HAVE_STATFS_VFS +#cmakedefine01 HAVE_STATFS_MOUNT #cmakedefine01 HAVE_FLOCK64 #cmakedefine01 HAVE_F_DUPFD_CLOEXEC #cmakedefine01 HAVE_F_FULLFSYNC diff --git a/src/libraries/Native/Unix/System.Native/pal_io.c b/src/libraries/Native/Unix/System.Native/pal_io.c index 353ea87ee9b3b2..7aafcdbc635413 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.c +++ b/src/libraries/Native/Unix/System.Native/pal_io.c @@ -35,8 +35,10 @@ #if HAVE_INOTIFY #include #endif -#if HAVE_STATFS64 || HAVE_STATFS +#if HAVE_STATFS64_VFS || HAVE_STATFS_VFS // Linux #include +#elif HAVE_STATFS64_MOUNT || HAVE_STATFS_MOUNT // BSD +#include #endif #ifdef _AIX @@ -1384,16 +1386,18 @@ static int16_t ConvertLockType(int16_t managedLockType) int64_t SystemNative_GetFileSystemType(intptr_t fd) { -#if HAVE_STATFS64 + int statfsRes; +#if HAVE_STATFS64_VFS || HAVE_STATFS64_MOUNT struct statfs64 statfsArgs; - return fstatfs64(ToFileDescriptor(fd), &statfsArgs) == -1 ? (int64_t)-1 : (int64_t)statfsArgs.f_type; -#elif HAVE_STATFS + while ((statfsRes = fstatfs64(ToFileDescriptor(fd), &statfsArgs)) == -1 && errno == EINTR) ; +#elif HAVE_STATFS_VFS || HAVE_STATFS_MOUNT struct statfs statfsArgs; - return fstatfs(ToFileDescriptor(fd), &statfsArgs) == -1 ? (int64_t)-1 : (int64_t)statfsArgs.f_type; + while ((statfsRes = fstatfs(ToFileDescriptor(fd), &statfsArgs)) == -1 && errno == EINTR) ; #else - // since this is just best effort, we return 0 if fstatfs is not supported - return 0; + #error "Platform doesn't support fstatfs64 or fstatfs" #endif + + return statfsRes == -1 ? (int64_t)-1 : (int64_t)statfsArgs.f_type; } int32_t SystemNative_LockFileRegion(intptr_t fd, int64_t offset, int64_t length, int16_t lockType) diff --git a/src/libraries/Native/Unix/configure.cmake b/src/libraries/Native/Unix/configure.cmake index 743fd39c22998a..7543413c3fe979 100644 --- a/src/libraries/Native/Unix/configure.cmake +++ b/src/libraries/Native/Unix/configure.cmake @@ -117,7 +117,7 @@ check_c_source_compiles( return 0; } " - HAVE_STATFS64) + HAVE_STATFS64_VFS) check_c_source_compiles( " @@ -128,7 +128,29 @@ check_c_source_compiles( return 0; } " - HAVE_STATFS) + HAVE_STATFS_VFS) + +check_c_source_compiles( + " + #include + int main(void) + { + struct statfs64 s; + return 0; + } + " + HAVE_STATFS64_MOUNT) + +check_c_source_compiles( + " + #include + int main(void) + { + struct statfs s; + return 0; + } + " + HAVE_STATFS_MOUNT) check_c_source_compiles( " From d64374fdf158f6709d2ac0f4714953e35c97668a Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Wed, 7 Jul 2021 15:00:08 +0200 Subject: [PATCH 05/15] fix OSX build --- src/libraries/Native/Unix/System.Native/pal_io.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libraries/Native/Unix/System.Native/pal_io.c b/src/libraries/Native/Unix/System.Native/pal_io.c index 7aafcdbc635413..20ffa4b5257e64 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.c +++ b/src/libraries/Native/Unix/System.Native/pal_io.c @@ -1387,7 +1387,10 @@ static int16_t ConvertLockType(int16_t managedLockType) int64_t SystemNative_GetFileSystemType(intptr_t fd) { int statfsRes; -#if HAVE_STATFS64_VFS || HAVE_STATFS64_MOUNT +#if HAVE_STATFS_MOUNT && defined(TARGET_OSX) // In macOS 10.6+ statfs64 is deprecated, in favor of statfs + struct statfs statfsArgs; + while ((statfsRes = fstatfs(ToFileDescriptor(fd), &statfsArgs)) == -1 && errno == EINTR) ; +#elif HAVE_STATFS64_VFS || HAVE_STATFS64_MOUNT struct statfs64 statfsArgs; while ((statfsRes = fstatfs64(ToFileDescriptor(fd), &statfsArgs)) == -1 && errno == EINTR) ; #elif HAVE_STATFS_VFS || HAVE_STATFS_MOUNT From c687e6a67b743a16e3f48c1d4e9562616c6d7146 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Wed, 7 Jul 2021 15:45:48 +0200 Subject: [PATCH 06/15] assume we should not acquire the lock if we don't know the File System --- .../src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs | 2 ++ 1 file changed, 2 insertions(+) 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 aa643c990538ed..79413d25956b38 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 @@ -338,6 +338,8 @@ private bool CanLockTheFile(Interop.Sys.LockOperations lockOperation, FileAccess case 0xFF534D42: // CIFS_MAGIC_NUMBER case 0x517B: // SMB_SUPER_MAGIC return false; // LOCK_SH is not OK when writing to NFS, CIFS or SMB + case -1: // error + return false; // assume we should not acquire the lock if we don't know the File System default: return true; // in all other situations it should be OK } From 9c481edb060617cf882b576e63f3626dc4b50938 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Wed, 7 Jul 2021 15:52:34 +0200 Subject: [PATCH 07/15] try to fix the maccatalyst build --- src/libraries/Native/Unix/System.Native/pal_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Native/Unix/System.Native/pal_io.c b/src/libraries/Native/Unix/System.Native/pal_io.c index 20ffa4b5257e64..505f8f9264269c 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.c +++ b/src/libraries/Native/Unix/System.Native/pal_io.c @@ -1387,7 +1387,7 @@ static int16_t ConvertLockType(int16_t managedLockType) int64_t SystemNative_GetFileSystemType(intptr_t fd) { int statfsRes; -#if HAVE_STATFS_MOUNT && defined(TARGET_OSX) // In macOS 10.6+ statfs64 is deprecated, in favor of statfs +#if HAVE_STATFS_MOUNT && (defined(TARGET_IOS) || defined(TARGET_OSX) || defined(TARGET_WATCHOS) || defined(TARGET_TVOS) || defined(HOST_MACCAT)) // In macOS 10.6+ statfs64 is deprecated, in favor of statfs struct statfs statfsArgs; while ((statfsRes = fstatfs(ToFileDescriptor(fd), &statfsArgs)) == -1 && errno == EINTR) ; #elif HAVE_STATFS64_VFS || HAVE_STATFS64_MOUNT From 1c890ec8f6e949df45ef5388b3925c8dab0820f8 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Thu, 8 Jul 2021 10:13:53 +0200 Subject: [PATCH 08/15] always use fstatfs as it's available on every platform and can get use correct file system type --- .../Native/Unix/Common/pal_config.h.in | 2 -- .../Native/Unix/System.Native/pal_io.c | 19 ++++++---------- src/libraries/Native/Unix/configure.cmake | 22 ------------------- 3 files changed, 7 insertions(+), 36 deletions(-) diff --git a/src/libraries/Native/Unix/Common/pal_config.h.in b/src/libraries/Native/Unix/Common/pal_config.h.in index 26641996107099..9a02610534101b 100644 --- a/src/libraries/Native/Unix/Common/pal_config.h.in +++ b/src/libraries/Native/Unix/Common/pal_config.h.in @@ -5,8 +5,6 @@ #cmakedefine01 HAVE_MMAP64 #cmakedefine01 HAVE_FTRUNCATE64 #cmakedefine01 HAVE_POSIX_FADVISE64 -#cmakedefine01 HAVE_STATFS64_VFS -#cmakedefine01 HAVE_STATFS64_MOUNT #cmakedefine01 HAVE_STATFS_VFS #cmakedefine01 HAVE_STATFS_MOUNT #cmakedefine01 HAVE_FLOCK64 diff --git a/src/libraries/Native/Unix/System.Native/pal_io.c b/src/libraries/Native/Unix/System.Native/pal_io.c index 505f8f9264269c..13f052974688b2 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.c +++ b/src/libraries/Native/Unix/System.Native/pal_io.c @@ -35,9 +35,9 @@ #if HAVE_INOTIFY #include #endif -#if HAVE_STATFS64_VFS || HAVE_STATFS_VFS // Linux +#if HAVE_STATFS_VFS // Linux #include -#elif HAVE_STATFS64_MOUNT || HAVE_STATFS_MOUNT // BSD +#elif HAVE_STATFS_MOUNT // BSD #include #endif @@ -1386,21 +1386,16 @@ static int16_t ConvertLockType(int16_t managedLockType) int64_t SystemNative_GetFileSystemType(intptr_t fd) { +#if HAVE_STATFS_VFS || HAVE_STATFS_MOUNT int statfsRes; -#if HAVE_STATFS_MOUNT && (defined(TARGET_IOS) || defined(TARGET_OSX) || defined(TARGET_WATCHOS) || defined(TARGET_TVOS) || defined(HOST_MACCAT)) // In macOS 10.6+ statfs64 is deprecated, in favor of statfs - struct statfs statfsArgs; - while ((statfsRes = fstatfs(ToFileDescriptor(fd), &statfsArgs)) == -1 && errno == EINTR) ; -#elif HAVE_STATFS64_VFS || HAVE_STATFS64_MOUNT - struct statfs64 statfsArgs; - while ((statfsRes = fstatfs64(ToFileDescriptor(fd), &statfsArgs)) == -1 && errno == EINTR) ; -#elif HAVE_STATFS_VFS || HAVE_STATFS_MOUNT struct statfs statfsArgs; + // for our needs (get file system type) statfs is always enough and there is no need to use statfs64 + // which got deprecated in macOS 10.6, in favor of statfs while ((statfsRes = fstatfs(ToFileDescriptor(fd), &statfsArgs)) == -1 && errno == EINTR) ; + return statfsRes == -1 ? (int64_t)-1 : (int64_t)statfsArgs.f_type; #else - #error "Platform doesn't support fstatfs64 or fstatfs" + #error "Platform doesn't support fstatfs" #endif - - return statfsRes == -1 ? (int64_t)-1 : (int64_t)statfsArgs.f_type; } int32_t SystemNative_LockFileRegion(intptr_t fd, int64_t offset, int64_t length, int16_t lockType) diff --git a/src/libraries/Native/Unix/configure.cmake b/src/libraries/Native/Unix/configure.cmake index 7543413c3fe979..18afacc2dbc59c 100644 --- a/src/libraries/Native/Unix/configure.cmake +++ b/src/libraries/Native/Unix/configure.cmake @@ -108,17 +108,6 @@ check_c_source_compiles( # /in_pktinfo -check_c_source_compiles( - " - #include - int main(void) - { - struct statfs64 s; - return 0; - } - " - HAVE_STATFS64_VFS) - check_c_source_compiles( " #include @@ -130,17 +119,6 @@ check_c_source_compiles( " HAVE_STATFS_VFS) -check_c_source_compiles( - " - #include - int main(void) - { - struct statfs64 s; - return 0; - } - " - HAVE_STATFS64_MOUNT) - check_c_source_compiles( " #include From 04eced6414f39399ac8783aaa2d9ff2725efa4b7 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Thu, 8 Jul 2021 10:22:02 +0200 Subject: [PATCH 09/15] handle SMB2_SUPER_MAGIC as well (#53182) --- .../src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs | 1 + 1 file changed, 1 insertion(+) 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 79413d25956b38..09512c10d1ffa1 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 @@ -337,6 +337,7 @@ private bool CanLockTheFile(Interop.Sys.LockOperations lockOperation, FileAccess case 0x6969: // NFS_SUPER_MAGIC case 0xFF534D42: // CIFS_MAGIC_NUMBER case 0x517B: // SMB_SUPER_MAGIC + case 0xFE534D42: // SMB2_SUPER_MAGIC (#53182) return false; // LOCK_SH is not OK when writing to NFS, CIFS or SMB case -1: // error return false; // assume we should not acquire the lock if we don't know the File System From 79b6def1dd53799f1da022eec776215acd40676a Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Thu, 8 Jul 2021 12:23:03 +0200 Subject: [PATCH 10/15] introduce a flag that allows to disable file locking on Unix --- .../Win32/SafeHandles/SafeFileHandle.Unix.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) 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 09512c10d1ffa1..7482e1b1f9144c 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 @@ -10,6 +10,8 @@ namespace Microsoft.Win32.SafeHandles { public sealed partial class SafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid { + internal static bool DisableFileLocking { get; } = AppContextConfigHelper.GetBooleanConfig("System.IO.DisableFileLocking", "DOTNET_SYSTEM_IO_DISABLEFILELOCKING", defaultValue: false); + // not using bool? as it's not thread safe private volatile NullableBool _canSeek = NullableBool.Undefined; private bool _deleteOnClose; @@ -122,7 +124,10 @@ protected override bool ReleaseHandle() // which could prevent subsequent usage of the file until this process dies. To avoid that, we proactively // try to release the lock before we close the handle. (If it's not locked, there's no behavioral // problem trying to unlock it.) - Interop.Sys.FLock(handle, Interop.Sys.LockOperations.LOCK_UN); // ignore any errors + if (!DisableFileLocking) + { + Interop.Sys.FLock(handle, Interop.Sys.LockOperations.LOCK_UN); // ignore any errors + } // If DeleteOnClose was requested when constructed, delete the file now. // (Unix doesn't directly support DeleteOnClose, so we mimic it here.) @@ -323,7 +328,11 @@ private bool CanLockTheFile(Interop.Sys.LockOperations lockOperation, FileAccess { Debug.Assert(lockOperation == Interop.Sys.LockOperations.LOCK_EX || lockOperation == Interop.Sys.LockOperations.LOCK_SH); - if (lockOperation == Interop.Sys.LockOperations.LOCK_EX) + if (DisableFileLocking) + { + return false; + } + else if (lockOperation == Interop.Sys.LockOperations.LOCK_EX) { return true; // LOCK_EX is always OK } From ba6d027297107d49d32c587936c777b79a1fddde Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Thu, 8 Jul 2021 12:23:47 +0200 Subject: [PATCH 11/15] Emscripten does not support file locking, so there is no need to check the file system type --- .../src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 7482e1b1f9144c..d645f36fc960de 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 @@ -328,7 +328,11 @@ private bool CanLockTheFile(Interop.Sys.LockOperations lockOperation, FileAccess { Debug.Assert(lockOperation == Interop.Sys.LockOperations.LOCK_EX || lockOperation == Interop.Sys.LockOperations.LOCK_SH); - if (DisableFileLocking) + if (OperatingSystem.IsBrowser()) + { + return false; // #40065: Emscripten does not support file locking + } + else if (DisableFileLocking) { return false; } From 731e65c56eb688598d364c0809945cb7839f50bb Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Thu, 8 Jul 2021 18:21:29 +0200 Subject: [PATCH 12/15] some polishing --- src/libraries/Native/Unix/System.Native/pal_io.h | 2 +- .../Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/libraries/Native/Unix/System.Native/pal_io.h b/src/libraries/Native/Unix/System.Native/pal_io.h index 62c460a9e3d30a..2af2eb3fa4bdd5 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.h +++ b/src/libraries/Native/Unix/System.Native/pal_io.h @@ -711,7 +711,7 @@ PALEXPORT char* SystemNative_RealPath(const char* path); PALEXPORT int32_t SystemNative_GetPeerID(intptr_t socket, uid_t* euid); /** -* Returns file system type on success, or -1 on error or 0 when fstatfs is not supported. +* Returns file system type on success, or -1 on error. */ PALEXPORT int64_t SystemNative_GetFileSystemType(intptr_t fd); 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 d645f36fc960de..bdc975087bf5b0 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 @@ -10,7 +10,8 @@ namespace Microsoft.Win32.SafeHandles { public sealed partial class SafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid { - internal static bool DisableFileLocking { get; } = AppContextConfigHelper.GetBooleanConfig("System.IO.DisableFileLocking", "DOTNET_SYSTEM_IO_DISABLEFILELOCKING", defaultValue: false); + internal static bool DisableFileLocking { get; } = OperatingSystem.IsBrowser() // #40065: Emscripten does not support file locking + || AppContextConfigHelper.GetBooleanConfig("System.IO.DisableFileLocking", "DOTNET_SYSTEM_IO_DISABLEFILELOCKING", defaultValue: false); // not using bool? as it's not thread safe private volatile NullableBool _canSeek = NullableBool.Undefined; @@ -328,11 +329,7 @@ private bool CanLockTheFile(Interop.Sys.LockOperations lockOperation, FileAccess { Debug.Assert(lockOperation == Interop.Sys.LockOperations.LOCK_EX || lockOperation == Interop.Sys.LockOperations.LOCK_SH); - if (OperatingSystem.IsBrowser()) - { - return false; // #40065: Emscripten does not support file locking - } - else if (DisableFileLocking) + if (DisableFileLocking) { return false; } From c752b93702cdc4ac967e0ac5ea9a0b8c1e29cf97 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Fri, 9 Jul 2021 06:37:11 +0200 Subject: [PATCH 13/15] reuse the UnixFileSystemTypes enum, move it to a separate file so CoreLib does not need to references other types related to DriveInfo --- .../Unix/System.Native/Interop.Fstatfs.cs | 14 -- .../Interop.MountPoints.FormatInfo.cs | 123 --------------- .../Interop.UnixFileSystemTypes.cs | 144 ++++++++++++++++++ .../src/System.IO.FileSystem.DriveInfo.csproj | 2 + .../Win32/SafeHandles/SafeFileHandle.Unix.cs | 17 ++- .../System.Private.CoreLib.Shared.projitems | 4 +- 6 files changed, 158 insertions(+), 146 deletions(-) delete mode 100644 src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fstatfs.cs create mode 100644 src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fstatfs.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fstatfs.cs deleted file mode 100644 index 08d206b17e9097..00000000000000 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fstatfs.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Runtime.InteropServices; -using Microsoft.Win32.SafeHandles; - -internal static partial class Interop -{ - internal static partial class Sys - { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetFileSystemType")] - internal static extern long GetFileSystemType(SafeFileHandle fd); - } -} diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs index fb59b175346807..05d74c84e789d5 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs @@ -22,129 +22,6 @@ static Sys() private const int MountPointFormatBufferSizeInBytes = 32; - /// - /// Internal FileSystem names and magic numbers taken from man(2) statfs - /// - /// - /// These value names MUST be kept in sync with those in GetDriveType below, - /// where this enum must be a subset of the GetDriveType list, with the enum - /// values here exactly matching a string there. - /// - internal enum UnixFileSystemTypes : long - { - adfs = 0xADF5, - affs = 0xADFF, - afs = 0x5346414F, - anoninode = 0x09041934, - aufs = 0x61756673, - autofs = 0x0187, - autofs4 = 0x6D4A556D, - befs = 0x42465331, - bdevfs = 0x62646576, - bfs = 0x1BADFACE, - binfmt_misc = 0x42494E4D, - bootfs = 0xA56D3FF9, - btrfs = 0x9123683E, - ceph = 0x00C36400, - cgroupfs = 0x0027E0EB, - cgroup2fs = 0x63677270, - cifs = 0xFF534D42, - coda = 0x73757245, - coherent = 0x012FF7B7, - configfs = 0x62656570, - cramfs = 0x28CD3D45, - debugfs = 0x64626720, - devfs = 0x1373, - devpts = 0x1CD1, - ecryptfs = 0xF15F, - efs = 0x00414A53, - exofs = 0x5DF5, - ext = 0x137D, - ext2_old = 0xEF51, - ext2 = 0xEF53, - ext3 = 0xEF53, - ext4 = 0xEF53, - fat = 0x4006, - fd = 0xF00D1E, - fhgfs = 0x19830326, - fuse = 0x65735546, - fuseblk = 0x65735546, - fusectl = 0x65735543, - futexfs = 0x0BAD1DEA, - gfsgfs2 = 0x1161970, - gfs2 = 0x01161970, - gpfs = 0x47504653, - hfs = 0x4244, - hfsplus = 0x482B, - hpfs = 0xF995E849, - hugetlbfs = 0x958458F6, - inodefs = 0x11307854, - inotifyfs = 0x2BAD1DEA, - isofs = 0x9660, - // isofs = 0x4004, // R_WIN - // isofs = 0x4000, // WIN - jffs = 0x07C0, - jffs2 = 0x72B6, - jfs = 0x3153464A, - kafs = 0x6B414653, - lofs = 0xEF53, /* loopback filesystem, magic same as ext2 */ - logfs = 0xC97E8168, - lustre = 0x0BD00BD0, - minix_old = 0x137F, /* orig. minix */ - minix = 0x138F, /* 30 char minix */ - minix2 = 0x2468, /* minix V2 */ - minix2v2 = 0x2478, /* MINIX V2, 30 char names */ - minix3 = 0x4D5A, - mqueue = 0x19800202, - msdos = 0x4D44, - nfs = 0x6969, - nfsd = 0x6E667364, - nilfs = 0x3434, - novell = 0x564C, - ntfs = 0x5346544E, - openprom = 0x9FA1, - ocfs2 = 0x7461636F, - omfs = 0xC2993D87, - overlay = 0x794C7630, - overlayfs = 0x794C764F, - panfs = 0xAAD7AAEA, - pipefs = 0x50495045, - proc = 0x9FA0, - pstorefs = 0x6165676C, - qnx4 = 0x002F, - qnx6 = 0x68191122, - ramfs = 0x858458F6, - reiserfs = 0x52654973, - romfs = 0x7275, - rootfs = 0x53464846, - rpc_pipefs = 0x67596969, - samba = 0x517B, - securityfs = 0x73636673, - selinux = 0xF97CFF8C, - smb = 0x517B, - sockfs = 0x534F434B, - squashfs = 0x73717368, - sysfs = 0x62656572, - sysv2 = 0x012FF7B6, - sysv4 = 0x012FF7B5, - tmpfs = 0x01021994, - ubifs = 0x24051905, - udf = 0x15013346, - ufs = 0x00011954, - ufscigam = 0x54190100, // ufs byteswapped - ufs2 = 0x19540119, - usbdevice = 0x9FA2, - v9fs = 0x01021997, - vmhgfs = 0xBACBACBC, - vxfs = 0xA501FCF5, - vzfs = 0x565A4653, - xenfs = 0xABBA1974, - xenix = 0x012FF7B4, - xfs = 0x58465342, - xia = 0x012FD16D, - zfs = 0x2FC12FC1, - } - [StructLayout(LayoutKind.Sequential)] internal struct MountPointInformation { diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs new file mode 100644 index 00000000000000..5e846883424f42 --- /dev/null +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs @@ -0,0 +1,144 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +internal static partial class Interop +{ + internal static partial class Sys + { + /// + /// Internal FileSystem names and magic numbers taken from man(2) statfs + /// + /// + /// These value names MUST be kept in sync with those in GetDriveType (moved to Interop.MountPoints.FormatInfo.cs), + /// where this enum must be a subset of the GetDriveType list, with the enum + /// values here exactly matching a string there. + /// + internal enum UnixFileSystemTypes : long + { + adfs = 0xADF5, + affs = 0xADFF, + afs = 0x5346414F, + anoninode = 0x09041934, + aufs = 0x61756673, + autofs = 0x0187, + autofs4 = 0x6D4A556D, + befs = 0x42465331, + bdevfs = 0x62646576, + bfs = 0x1BADFACE, + binfmt_misc = 0x42494E4D, + bootfs = 0xA56D3FF9, + btrfs = 0x9123683E, + ceph = 0x00C36400, + cgroupfs = 0x0027E0EB, + cgroup2fs = 0x63677270, + cifs = 0xFF534D42, + coda = 0x73757245, + coherent = 0x012FF7B7, + configfs = 0x62656570, + cramfs = 0x28CD3D45, + debugfs = 0x64626720, + devfs = 0x1373, + devpts = 0x1CD1, + ecryptfs = 0xF15F, + efs = 0x00414A53, + exofs = 0x5DF5, + ext = 0x137D, + ext2_old = 0xEF51, + ext2 = 0xEF53, + ext3 = 0xEF53, + ext4 = 0xEF53, + fat = 0x4006, + fd = 0xF00D1E, + fhgfs = 0x19830326, + fuse = 0x65735546, + fuseblk = 0x65735546, + fusectl = 0x65735543, + futexfs = 0x0BAD1DEA, + gfsgfs2 = 0x1161970, + gfs2 = 0x01161970, + gpfs = 0x47504653, + hfs = 0x4244, + hfsplus = 0x482B, + hpfs = 0xF995E849, + hugetlbfs = 0x958458F6, + inodefs = 0x11307854, + inotifyfs = 0x2BAD1DEA, + isofs = 0x9660, + // isofs = 0x4004, // R_WIN + // isofs = 0x4000, // WIN + jffs = 0x07C0, + jffs2 = 0x72B6, + jfs = 0x3153464A, + kafs = 0x6B414653, + lofs = 0xEF53, /* loopback filesystem, magic same as ext2 */ + logfs = 0xC97E8168, + lustre = 0x0BD00BD0, + minix_old = 0x137F, /* orig. minix */ + minix = 0x138F, /* 30 char minix */ + minix2 = 0x2468, /* minix V2 */ + minix2v2 = 0x2478, /* MINIX V2, 30 char names */ + minix3 = 0x4D5A, + mqueue = 0x19800202, + msdos = 0x4D44, + nfs = 0x6969, + nfsd = 0x6E667364, + nilfs = 0x3434, + novell = 0x564C, + ntfs = 0x5346544E, + openprom = 0x9FA1, + ocfs2 = 0x7461636F, + omfs = 0xC2993D87, + overlay = 0x794C7630, + overlayfs = 0x794C764F, + panfs = 0xAAD7AAEA, + pipefs = 0x50495045, + proc = 0x9FA0, + pstorefs = 0x6165676C, + qnx4 = 0x002F, + qnx6 = 0x68191122, + ramfs = 0x858458F6, + reiserfs = 0x52654973, + romfs = 0x7275, + rootfs = 0x53464846, + rpc_pipefs = 0x67596969, + samba = 0x517B, + securityfs = 0x73636673, + selinux = 0xF97CFF8C, + smb = 0x517B, + sockfs = 0x534F434B, + squashfs = 0x73717368, + sysfs = 0x62656572, + sysv2 = 0x012FF7B6, + sysv4 = 0x012FF7B5, + tmpfs = 0x01021994, + ubifs = 0x24051905, + udf = 0x15013346, + ufs = 0x00011954, + ufscigam = 0x54190100, // ufs byteswapped + ufs2 = 0x19540119, + usbdevice = 0x9FA2, + v9fs = 0x01021997, + vmhgfs = 0xBACBACBC, + vxfs = 0xA501FCF5, + vzfs = 0x565A4653, + xenfs = 0xABBA1974, + xenix = 0x012FF7B4, + xfs = 0x58465342, + xia = 0x012FD16D, + zfs = 0x2FC12FC1, + } + + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetFileSystemType")] + private static extern long GetFileSystemType(SafeFileHandle fd); + + internal static bool TryGetFileSystemType(SafeFileHandle fd, out UnixFileSystemTypes fileSystemType) + { + long fstatfsResult = GetFileSystemType(fd); + fileSystemType = (UnixFileSystemTypes)fstatfsResult; + return fstatfsResult != -1; + } + } +} diff --git a/src/libraries/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj b/src/libraries/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj index c516eb543e3347..d07e89ec979be1 100644 --- a/src/libraries/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj +++ b/src/libraries/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj @@ -56,6 +56,8 @@ Link="Common\Interop\Unix\Interop.Libraries.cs" /> + Common\Interop\Unix\System.Native\Interop.ErrNo.cs - - Common\Interop\Unix\System.Native\Interop.Fstatfs.cs + + Common\Interop\Unix\System.Native\Interop.UnixFileSystemTypes.cs Common\Interop\Unix\System.Native\Interop.FLock.cs From 7443a5ec34ec50c70a8e60a216ca9ac28b584c74 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Fri, 9 Jul 2021 06:41:14 +0200 Subject: [PATCH 14/15] add SMB2_SUPER_MAGIC to the enum --- .../Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs | 1 + .../src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs index 5e846883424f42..fd34f87418223f 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs @@ -108,6 +108,7 @@ internal enum UnixFileSystemTypes : long securityfs = 0x73636673, selinux = 0xF97CFF8C, smb = 0x517B, + smb2 = 0xFE534D42, sockfs = 0x534F434B, squashfs = 0x73717368, sysfs = 0x62656572, 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 c43eeef32c993c..5f98a162824afc 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 @@ -352,8 +352,8 @@ private bool CanLockTheFile(Interop.Sys.LockOperations lockOperation, FileAccess { case Interop.Sys.UnixFileSystemTypes.nfs: case Interop.Sys.UnixFileSystemTypes.smb: + case Interop.Sys.UnixFileSystemTypes.smb2: // (#53182) case Interop.Sys.UnixFileSystemTypes.cifs: - // case 0xFE534D42: // SMB2_SUPER_MAGIC (#53182) return false; // LOCK_SH is not OK when writing to NFS, CIFS or SMB default: return true; // in all other situations it should be OK From 1e3878c005b95c4638cd5b095d329d0deca07ed4 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Fri, 9 Jul 2021 09:26:13 +0200 Subject: [PATCH 15/15] don't try to unlock the file if it has not been locked --- .../Win32/SafeHandles/SafeFileHandle.Unix.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) 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 5f98a162824afc..10dd1eabee0107 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 @@ -17,6 +17,7 @@ public sealed partial class SafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid // not using bool? as it's not thread safe private volatile NullableBool _canSeek = NullableBool.Undefined; private bool _deleteOnClose; + private bool _isLocked; public SafeFileHandle() : this(ownsHandle: true) { @@ -124,11 +125,11 @@ protected override bool ReleaseHandle() // an advisory lock. This lock should be removed via closing the file descriptor, but close can be // interrupted, and we don't retry closes. As such, we could end up leaving the file locked, // which could prevent subsequent usage of the file until this process dies. To avoid that, we proactively - // try to release the lock before we close the handle. (If it's not locked, there's no behavioral - // problem trying to unlock it.) - if (!DisableFileLocking) + // try to release the lock before we close the handle. + if (_isLocked) { Interop.Sys.FLock(handle, Interop.Sys.LockOperations.LOCK_UN); // ignore any errors + _isLocked = false; } // If DeleteOnClose was requested when constructed, delete the file now. @@ -265,7 +266,7 @@ private void Init(string path, FileMode mode, FileAccess access, FileShare share // lock on the file and all other modes use a shared lock. While this is not as granular as Windows, not mandatory, // and not atomic with file opening, it's better than nothing. Interop.Sys.LockOperations lockOperation = (share == FileShare.None) ? Interop.Sys.LockOperations.LOCK_EX : Interop.Sys.LockOperations.LOCK_SH; - if (CanLockTheFile(lockOperation, access) && Interop.Sys.FLock(this, lockOperation | Interop.Sys.LockOperations.LOCK_NB) < 0) + if (CanLockTheFile(lockOperation, access) && !(_isLocked = Interop.Sys.FLock(this, lockOperation | Interop.Sys.LockOperations.LOCK_NB) >= 0)) { // The only error we care about is EWOULDBLOCK, which indicates that the file is currently locked by someone // else and we would block trying to access it. Other errors, such as ENOTSUP (locking isn't supported) or @@ -350,9 +351,9 @@ private bool CanLockTheFile(Interop.Sys.LockOperations lockOperation, FileAccess switch (unixFileSystemType) { - case Interop.Sys.UnixFileSystemTypes.nfs: + case Interop.Sys.UnixFileSystemTypes.nfs: // #44546 case Interop.Sys.UnixFileSystemTypes.smb: - case Interop.Sys.UnixFileSystemTypes.smb2: // (#53182) + case Interop.Sys.UnixFileSystemTypes.smb2: // #53182 case Interop.Sys.UnixFileSystemTypes.cifs: return false; // LOCK_SH is not OK when writing to NFS, CIFS or SMB default: