From 7e7f3686e4572e277f1780b6b168aa21f87ce3d3 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Wed, 4 Sep 2024 19:34:23 +0200 Subject: [PATCH 01/23] Fix wrong drive format on Unix Change GetFormatInfoForMountPoint method to "use /proc/self/mountinfo" file - Replaced system calls (`statfs`/`statvfs`) with a simplified parsing of `/proc/self/mountinfo`. - Removed native SystemNative_GetFormatInfoForMountPoint as we don't need anymore - Parsing the mount info file allows for efficient retrieval of filesystem format and type. - No functional changes; the method continues to return the correct filesystem format and drive type for the given mount point. FIX #95099 --- .../Interop.MountPoints.FormatInfo.cs | 64 +++++++++++-------- src/native/libs/System.Native/entrypoints.c | 1 - src/native/libs/System.Native/pal_mount.c | 47 -------------- src/native/libs/System.Native/pal_mount.h | 12 ---- .../libs/System.Native/pal_mount_wasi.c | 8 --- 5 files changed, 37 insertions(+), 95 deletions(-) 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 4cc682139c3a6c..4c4662db7acc40 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 @@ -33,13 +33,6 @@ internal struct MountPointInformation [LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSpaceInfoForMountPoint", SetLastError = true)] internal static partial int GetSpaceInfoForMountPoint([MarshalAs(UnmanagedType.LPUTF8Str)] string name, out MountPointInformation mpi); - [LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetFormatInfoForMountPoint", SetLastError = true)] - internal static unsafe partial int GetFormatInfoForMountPoint( - [MarshalAs(UnmanagedType.LPUTF8Str)] string name, - byte* formatNameBuffer, - int bufferLength, - long* formatType); - internal static int GetFormatInfoForMountPoint(string name, out string format) { return GetFormatInfoForMountPoint(name, out format, out _); @@ -49,28 +42,45 @@ internal static int GetFormatInfoForMountPoint(string name, out DriveType type) { return GetFormatInfoForMountPoint(name, out _, out type); } + + private static int GetFormatInfoForMountPoint(string name, out string format, out DriveType type) + { + const string mountInfoFilePath = "/proc/self/mountinfo"; + var mountInfoFileContent = File.ReadAllLines(mountInfoFilePath); + foreach (var line in mountInfoFileContent) + { + var parser = new StringParser(line, ' '); - private static unsafe int GetFormatInfoForMountPoint(string name, out string format, out DriveType type) - { - byte* formatBuffer = stackalloc byte[MountPointFormatBufferSizeInBytes]; // format names should be small - long numericFormat; - int result = GetFormatInfoForMountPoint(name, formatBuffer, MountPointFormatBufferSizeInBytes, &numericFormat); - if (result == 0) - { - // Check if we have a numeric answer or string - format = numericFormat != -1 ? - Enum.GetName(typeof(UnixFileSystemTypes), numericFormat) ?? string.Empty : - Marshal.PtrToStringUTF8((IntPtr)formatBuffer)!; - type = GetDriveType(format); - } - else - { - format = string.Empty; - type = DriveType.Unknown; - } + // Skip fields we don't care about (Fields 1-4) + parser.MoveNext(); // Skip Mount ID + parser.MoveNext(); // Skip Parent ID + parser.MoveNext(); // Skip Major:Minor + parser.MoveNext(); // Skip Root - return result; - } + // Get the mount point (Field 5) + string mountPoint = parser.MoveAndExtractNext(); + + // Skip to the separator which is end of optional fields (Field 8) + while (parser.MoveAndExtractNext() != "-") + { + } + + // Get filesystem type (Field 9) + string filesystemType = parser.MoveAndExtractNext(); + + if (mountPoint.Equals(name, StringComparison.Ordinal)) + { + format = filesystemType; + type = GetDriveType(filesystemType); + return 0; + } + } + + format = string.Empty; + type = DriveType.Unknown; + return -1; + } + /// Categorizes a file system name into a drive type. /// The name to categorize. diff --git a/src/native/libs/System.Native/entrypoints.c b/src/native/libs/System.Native/entrypoints.c index 2165430d65f56a..f7c0ef9a4bad5b 100644 --- a/src/native/libs/System.Native/entrypoints.c +++ b/src/native/libs/System.Native/entrypoints.c @@ -131,7 +131,6 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_Malloc) DllImportEntry(SystemNative_Realloc) DllImportEntry(SystemNative_GetSpaceInfoForMountPoint) - DllImportEntry(SystemNative_GetFormatInfoForMountPoint) DllImportEntry(SystemNative_GetAllMountPoints) DllImportEntry(SystemNative_ReadEvents) DllImportEntry(SystemNative_CreateNetworkChangeListenerSocket) diff --git a/src/native/libs/System.Native/pal_mount.c b/src/native/libs/System.Native/pal_mount.c index 2453bdfe9ede3f..99ca2928796a03 100644 --- a/src/native/libs/System.Native/pal_mount.c +++ b/src/native/libs/System.Native/pal_mount.c @@ -130,50 +130,3 @@ int32_t SystemNative_GetSpaceInfoForMountPoint(const char* name, MountPointInfor return result; } - -int32_t -SystemNative_GetFormatInfoForMountPoint(const char* name, char* formatNameBuffer, int32_t bufferLength, int64_t* formatType) -{ - assert((formatNameBuffer != NULL) && (formatType != NULL)); - assert(bufferLength > 0); - -#if HAVE_NON_LEGACY_STATFS - struct statfs stats; - int result = statfs(name, &stats); -#else - struct statvfs stats; - int result = statvfs(name, &stats); -#endif - if (result == 0) - { - -#if HAVE_STATFS_FSTYPENAME || HAVE_STATVFS_FSTYPENAME -#ifdef VFS_NAMELEN - if (bufferLength < VFS_NAMELEN) -#else - if (bufferLength < MFSNAMELEN) -#endif - { - result = ERANGE; - *formatType = 0; - } - else - { - SafeStringCopy(formatNameBuffer, Int32ToSizeT(bufferLength), stats.f_fstypename); - *formatType = -1; - } -#elif HAVE_NON_LEGACY_STATFS - assert(formatType != NULL); - *formatType = (int64_t)(stats.f_type); - SafeStringCopy(formatNameBuffer, Int32ToSizeT(bufferLength), ""); -#else - *formatType = 0; -#endif - } - else - { - *formatType = 0; - } - - return result; -} diff --git a/src/native/libs/System.Native/pal_mount.h b/src/native/libs/System.Native/pal_mount.h index 3afef9b3ca0662..bd906c4933973e 100644 --- a/src/native/libs/System.Native/pal_mount.h +++ b/src/native/libs/System.Native/pal_mount.h @@ -28,18 +28,6 @@ typedef void (*MountPointFound)(void* context, const char* name); */ PALEXPORT int32_t SystemNative_GetSpaceInfoForMountPoint(const char* name, MountPointInformation* mpi); -/** - * Gets the format information about the given mount point. - * We separate format info from space info because format information is given back differently per-platform - * so keep the space information simple (above) and do all the platform logic here. - * Ubuntu (and most Linux systems) will provide the mount point format as a long int in statfs while - * OS X and BSD-like systems will provide the information in a char buffer. - * Since C# is much better at enum and string handling, pass either the char buffer or the long type - * back, depending on what the platform gives us, and let C# reason on it in an easy way. - */ -PALEXPORT int32_t SystemNative_GetFormatInfoForMountPoint( - const char* name, char* formatNameBuffer, int32_t bufferLength, int64_t* formatType); - /** * Enumerate all mount points on the system and call the input * function pointer once-per-mount-point to prevent heap allocs diff --git a/src/native/libs/System.Native/pal_mount_wasi.c b/src/native/libs/System.Native/pal_mount_wasi.c index 61b776160eace6..5c06cec4be6850 100644 --- a/src/native/libs/System.Native/pal_mount_wasi.c +++ b/src/native/libs/System.Native/pal_mount_wasi.c @@ -20,11 +20,3 @@ int32_t SystemNative_GetSpaceInfoForMountPoint(const char* name, MountPointInfor assert(mpi != NULL); return -1; } - -int32_t -SystemNative_GetFormatInfoForMountPoint(const char* name, char* formatNameBuffer, int32_t bufferLength, int64_t* formatType) -{ - assert((formatNameBuffer != NULL) && (formatType != NULL)); - assert(bufferLength > 0); - return -1; -} From fec07ce85204a5f6ff4cf7a4e4070fbacf8e946c Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Thu, 5 Sep 2024 10:50:34 +0200 Subject: [PATCH 02/23] Add support for reading filesystem type from /proc/self/mountinfo on Linux Add support for reading filesystem type from /proc/self/mountinfo on Linux - Prioritize reading the filesystem type from `/proc/self/mountinfo` on Linux. - Retain the existing P/Invoke fallback for non-Linux platforms and as a fallback on Linux. - Added `try/catch` block to handle potential but unlikely access issues or unrecognized data. Although `/proc/self/mountinfo` is process-specific and should generally be accessible, this ensures robustness in case of unexpected errors (e.g., temporary unavailability, corrupted data). - Updated documentation to reflect the reasoning and kernel behavior regarding procfs on different platforms. --- .../Interop.MountPoints.FormatInfo.cs | 107 +++++++++++++----- src/native/libs/System.Native/entrypoints.c | 1 + src/native/libs/System.Native/pal_mount.c | 47 ++++++++ src/native/libs/System.Native/pal_mount.h | 12 ++ .../libs/System.Native/pal_mount_wasi.c | 8 ++ 5 files changed, 147 insertions(+), 28 deletions(-) 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 4c4662db7acc40..f4e2aa6f1cbf77 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 @@ -33,6 +33,13 @@ internal struct MountPointInformation [LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSpaceInfoForMountPoint", SetLastError = true)] internal static partial int GetSpaceInfoForMountPoint([MarshalAs(UnmanagedType.LPUTF8Str)] string name, out MountPointInformation mpi); + [LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetFormatInfoForMountPoint", SetLastError = true)] + internal static unsafe partial int GetFormatInfoForMountPoint( + [MarshalAs(UnmanagedType.LPUTF8Str)] string name, + byte* formatNameBuffer, + int bufferLength, + long* formatType); + internal static int GetFormatInfoForMountPoint(string name, out string format) { return GetFormatInfoForMountPoint(name, out format, out _); @@ -43,42 +50,86 @@ internal static int GetFormatInfoForMountPoint(string name, out DriveType type) return GetFormatInfoForMountPoint(name, out _, out type); } - private static int GetFormatInfoForMountPoint(string name, out string format, out DriveType type) + /// + /// Retrieves format information for the specified mount point. + /// + /// + /// This method uses a two-step approach to retrieve filesystem information: + /// 1. On Linux systems, it first attempts to read from `/proc/self/mountinfo`. + /// 2. If step 1 fails or on non-Linux systems, it falls back to a P/Invoke call. + /// + /// The `/proc/self/mountinfo` approach is preferred on Linux because + /// it's more reliable when procfs is available and functioning correctly. + /// + /// For other systems: + /// - SunOS and similar: procfs provides a binary interface, not suitable for this method. + /// - macOS: procfs is not available. + /// - FreeBSD: procfs is optional and not enabled by default. + /// + /// The method uses try/catch blocks to ensure robustness, even though `/proc/self/mountinfo` + /// should be specific to each process according to kernel documentation. + /// + /// The mount point name to query. + /// Output parameter for the filesystem format. + /// Output parameter for the drive type. + /// 0 if successful, otherwise an error code. + private static unsafe int GetFormatInfoForMountPoint(string name, out string format, out DriveType type) { - const string mountInfoFilePath = "/proc/self/mountinfo"; - var mountInfoFileContent = File.ReadAllLines(mountInfoFilePath); - foreach (var line in mountInfoFileContent) - { - var parser = new StringParser(line, ' '); + #if TARGET_LINUX + try + { + const string mountInfoFilePath = "/proc/self/mountinfo"; + var mountInfoFileContent = File.ReadAllLines(mountInfoFilePath); + foreach (var line in mountInfoFileContent) + { + var parser = new StringParser(line, ' '); - // Skip fields we don't care about (Fields 1-4) - parser.MoveNext(); // Skip Mount ID - parser.MoveNext(); // Skip Parent ID - parser.MoveNext(); // Skip Major:Minor - parser.MoveNext(); // Skip Root + // Skip fields we don't care about (Fields 1-4) + parser.MoveNext(); // Skip Mount ID + parser.MoveNext(); // Skip Parent ID + parser.MoveNext(); // Skip Major:Minor + parser.MoveNext(); // Skip Root - // Get the mount point (Field 5) - string mountPoint = parser.MoveAndExtractNext(); + // Get the mount point (Field 5) + string mountPoint = parser.MoveAndExtractNext(); - // Skip to the separator which is end of optional fields (Field 8) - while (parser.MoveAndExtractNext() != "-") - { - } + // Skip to the separator which is end of optional fields (Field 8) + while (parser.MoveAndExtractNext() != "-") + { + } - // Get filesystem type (Field 9) - string filesystemType = parser.MoveAndExtractNext(); + // Get filesystem type (Field 9) + string filesystemType = parser.MoveAndExtractNext(); - if (mountPoint.Equals(name, StringComparison.Ordinal)) - { - format = filesystemType; - type = GetDriveType(filesystemType); - return 0; + if (mountPoint.Equals(name, StringComparison.Ordinal)) + { + format = filesystemType; + type = GetDriveType(filesystemType); + return 0; + } + } } - } + catch { /* ignored */ } + #endif + + byte* formatBuffer = stackalloc byte[MountPointFormatBufferSizeInBytes]; // format names should be small + long numericFormat; + int result = GetFormatInfoForMountPoint(name, formatBuffer, MountPointFormatBufferSizeInBytes, &numericFormat); + if (result == 0) + { + // Check if we have a numeric answer or string + format = numericFormat != -1 ? + Enum.GetName(typeof(UnixFileSystemTypes), numericFormat) ?? string.Empty : + Marshal.PtrToStringUTF8((IntPtr)formatBuffer)!; + type = GetDriveType(format); + } + else + { + format = string.Empty; + type = DriveType.Unknown; + } - format = string.Empty; - type = DriveType.Unknown; - return -1; + return result; } diff --git a/src/native/libs/System.Native/entrypoints.c b/src/native/libs/System.Native/entrypoints.c index f7c0ef9a4bad5b..2eca9f7ff13289 100644 --- a/src/native/libs/System.Native/entrypoints.c +++ b/src/native/libs/System.Native/entrypoints.c @@ -131,6 +131,7 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_Malloc) DllImportEntry(SystemNative_Realloc) DllImportEntry(SystemNative_GetSpaceInfoForMountPoint) + DllImportEntry(SystemNative_GetFormatInfoForMountPoint) DllImportEntry(SystemNative_GetAllMountPoints) DllImportEntry(SystemNative_ReadEvents) DllImportEntry(SystemNative_CreateNetworkChangeListenerSocket) diff --git a/src/native/libs/System.Native/pal_mount.c b/src/native/libs/System.Native/pal_mount.c index 99ca2928796a03..fceec76676255a 100644 --- a/src/native/libs/System.Native/pal_mount.c +++ b/src/native/libs/System.Native/pal_mount.c @@ -130,3 +130,50 @@ int32_t SystemNative_GetSpaceInfoForMountPoint(const char* name, MountPointInfor return result; } + +int32_t +SystemNative_GetFormatInfoForMountPoint(const char* name, char* formatNameBuffer, int32_t bufferLength, int64_t* formatType) +{ + assert((formatNameBuffer != NULL) && (formatType != NULL)); + assert(bufferLength > 0); + +#if HAVE_NON_LEGACY_STATFS + struct statfs stats; + int result = statfs(name, &stats); +#else + struct statvfs stats; + int result = statvfs(name, &stats); +#endif + if (result == 0) + { + +#if HAVE_STATFS_FSTYPENAME || HAVE_STATVFS_FSTYPENAME +#ifdef VFS_NAMELEN + if (bufferLength < VFS_NAMELEN) +#else + if (bufferLength < MFSNAMELEN) +#endif + { + result = ERANGE; + *formatType = 0; + } + else + { + SafeStringCopy(formatNameBuffer, Int32ToSizeT(bufferLength), stats.f_fstypename); + *formatType = -1; + } +#elif HAVE_NON_LEGACY_STATFS + assert(formatType != NULL); + *formatType = (int64_t)(stats.f_type); + SafeStringCopy(formatNameBuffer, Int32ToSizeT(bufferLength), ""); +#else + *formatType = 0; +#endif + } + else + { + *formatType = 0; + } + + return result; +} \ No newline at end of file diff --git a/src/native/libs/System.Native/pal_mount.h b/src/native/libs/System.Native/pal_mount.h index bd906c4933973e..3afef9b3ca0662 100644 --- a/src/native/libs/System.Native/pal_mount.h +++ b/src/native/libs/System.Native/pal_mount.h @@ -28,6 +28,18 @@ typedef void (*MountPointFound)(void* context, const char* name); */ PALEXPORT int32_t SystemNative_GetSpaceInfoForMountPoint(const char* name, MountPointInformation* mpi); +/** + * Gets the format information about the given mount point. + * We separate format info from space info because format information is given back differently per-platform + * so keep the space information simple (above) and do all the platform logic here. + * Ubuntu (and most Linux systems) will provide the mount point format as a long int in statfs while + * OS X and BSD-like systems will provide the information in a char buffer. + * Since C# is much better at enum and string handling, pass either the char buffer or the long type + * back, depending on what the platform gives us, and let C# reason on it in an easy way. + */ +PALEXPORT int32_t SystemNative_GetFormatInfoForMountPoint( + const char* name, char* formatNameBuffer, int32_t bufferLength, int64_t* formatType); + /** * Enumerate all mount points on the system and call the input * function pointer once-per-mount-point to prevent heap allocs diff --git a/src/native/libs/System.Native/pal_mount_wasi.c b/src/native/libs/System.Native/pal_mount_wasi.c index 5c06cec4be6850..be6ab88cc0f291 100644 --- a/src/native/libs/System.Native/pal_mount_wasi.c +++ b/src/native/libs/System.Native/pal_mount_wasi.c @@ -20,3 +20,11 @@ int32_t SystemNative_GetSpaceInfoForMountPoint(const char* name, MountPointInfor assert(mpi != NULL); return -1; } + +int32_t +SystemNative_GetFormatInfoForMountPoint(const char* name, char* formatNameBuffer, int32_t bufferLength, int64_t* formatType) +{ + assert((formatNameBuffer != NULL) && (formatType != NULL)); + assert(bufferLength > 0); + return -1; +} \ No newline at end of file From 080825d0b251a64d6a5dbb984b4efff90643c701 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Thu, 5 Sep 2024 12:17:21 +0200 Subject: [PATCH 03/23] Fix whitespaces and replace tabs with 4 spaces --- .../Interop.MountPoints.FormatInfo.cs | 131 +++++++++--------- src/native/libs/System.Native/entrypoints.c | 2 +- src/native/libs/System.Native/pal_mount.c | 2 +- .../libs/System.Native/pal_mount_wasi.c | 2 +- 4 files changed, 68 insertions(+), 69 deletions(-) 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 f4e2aa6f1cbf77..dd77b22dbd322c 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 @@ -39,7 +39,7 @@ internal static unsafe partial int GetFormatInfoForMountPoint( byte* formatNameBuffer, int bufferLength, long* formatType); - + internal static int GetFormatInfoForMountPoint(string name, out string format) { return GetFormatInfoForMountPoint(name, out format, out _); @@ -49,69 +49,69 @@ internal static int GetFormatInfoForMountPoint(string name, out DriveType type) { return GetFormatInfoForMountPoint(name, out _, out type); } - - /// - /// Retrieves format information for the specified mount point. - /// - /// - /// This method uses a two-step approach to retrieve filesystem information: - /// 1. On Linux systems, it first attempts to read from `/proc/self/mountinfo`. - /// 2. If step 1 fails or on non-Linux systems, it falls back to a P/Invoke call. - /// - /// The `/proc/self/mountinfo` approach is preferred on Linux because - /// it's more reliable when procfs is available and functioning correctly. - /// - /// For other systems: - /// - SunOS and similar: procfs provides a binary interface, not suitable for this method. - /// - macOS: procfs is not available. - /// - FreeBSD: procfs is optional and not enabled by default. - /// - /// The method uses try/catch blocks to ensure robustness, even though `/proc/self/mountinfo` - /// should be specific to each process according to kernel documentation. - /// - /// The mount point name to query. - /// Output parameter for the filesystem format. - /// Output parameter for the drive type. - /// 0 if successful, otherwise an error code. - private static unsafe int GetFormatInfoForMountPoint(string name, out string format, out DriveType type) - { - #if TARGET_LINUX - try - { - const string mountInfoFilePath = "/proc/self/mountinfo"; - var mountInfoFileContent = File.ReadAllLines(mountInfoFilePath); - foreach (var line in mountInfoFileContent) - { - var parser = new StringParser(line, ' '); - - // Skip fields we don't care about (Fields 1-4) - parser.MoveNext(); // Skip Mount ID - parser.MoveNext(); // Skip Parent ID - parser.MoveNext(); // Skip Major:Minor - parser.MoveNext(); // Skip Root - - // Get the mount point (Field 5) - string mountPoint = parser.MoveAndExtractNext(); - - // Skip to the separator which is end of optional fields (Field 8) - while (parser.MoveAndExtractNext() != "-") - { - } - - // Get filesystem type (Field 9) - string filesystemType = parser.MoveAndExtractNext(); - - if (mountPoint.Equals(name, StringComparison.Ordinal)) - { - format = filesystemType; - type = GetDriveType(filesystemType); - return 0; - } - } - } - catch { /* ignored */ } - #endif + /// + /// Retrieves format information for the specified mount point. + /// + /// + /// This method uses a two-step approach to retrieve filesystem information: + /// 1. On Linux systems, it first attempts to read from `/proc/self/mountinfo`. + /// 2. If step 1 fails or on non-Linux systems, it falls back to a P/Invoke call. + /// + /// The `/proc/self/mountinfo` approach is preferred on Linux because + /// it's more reliable when procfs is available and functioning correctly. + /// + /// For other systems: + /// - SunOS and similar: procfs provides a binary interface, not suitable for this method. + /// - macOS: procfs is not available. + /// - FreeBSD: procfs is optional and not enabled by default. + /// + /// The method uses try/catch blocks to ensure robustness, even though `/proc/self/mountinfo` + /// should be specific to each process according to kernel documentation. + /// + /// The mount point name to query. + /// Output parameter for the filesystem format. + /// Output parameter for the drive type. + /// 0 if successful, otherwise an error code. + private static unsafe int GetFormatInfoForMountPoint(string name, out string format, out DriveType type) + { + #if TARGET_LINUX + try + { + const string mountInfoFilePath = "/proc/self/mountinfo"; + var mountInfoFileContent = File.ReadAllLines(mountInfoFilePath); + foreach (var line in mountInfoFileContent) + { + var parser = new StringParser(line, ' '); + + // Skip fields we don't care about (Fields 1-4) + parser.MoveNext(); // Skip Mount ID + parser.MoveNext(); // Skip Parent ID + parser.MoveNext(); // Skip Major:Minor + parser.MoveNext(); // Skip Root + + // Get the mount point (Field 5) + string mountPoint = parser.MoveAndExtractNext(); + + // Skip to the separator which is end of optional fields (Field 8) + while (parser.MoveAndExtractNext() != "-") + { + } + + // Get filesystem type (Field 9) + string filesystemType = parser.MoveAndExtractNext(); + + if (mountPoint.Equals(name, StringComparison.Ordinal)) + { + format = filesystemType; + type = GetDriveType(filesystemType); + return 0; + } + } + } + catch { /* ignored */ } + #endif + byte* formatBuffer = stackalloc byte[MountPointFormatBufferSizeInBytes]; // format names should be small long numericFormat; int result = GetFormatInfoForMountPoint(name, formatBuffer, MountPointFormatBufferSizeInBytes, &numericFormat); @@ -128,10 +128,9 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for format = string.Empty; type = DriveType.Unknown; } - + return result; - } - + } /// Categorizes a file system name into a drive type. /// The name to categorize. diff --git a/src/native/libs/System.Native/entrypoints.c b/src/native/libs/System.Native/entrypoints.c index 2eca9f7ff13289..2165430d65f56a 100644 --- a/src/native/libs/System.Native/entrypoints.c +++ b/src/native/libs/System.Native/entrypoints.c @@ -131,7 +131,7 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_Malloc) DllImportEntry(SystemNative_Realloc) DllImportEntry(SystemNative_GetSpaceInfoForMountPoint) - DllImportEntry(SystemNative_GetFormatInfoForMountPoint) + DllImportEntry(SystemNative_GetFormatInfoForMountPoint) DllImportEntry(SystemNative_GetAllMountPoints) DllImportEntry(SystemNative_ReadEvents) DllImportEntry(SystemNative_CreateNetworkChangeListenerSocket) diff --git a/src/native/libs/System.Native/pal_mount.c b/src/native/libs/System.Native/pal_mount.c index fceec76676255a..2453bdfe9ede3f 100644 --- a/src/native/libs/System.Native/pal_mount.c +++ b/src/native/libs/System.Native/pal_mount.c @@ -176,4 +176,4 @@ SystemNative_GetFormatInfoForMountPoint(const char* name, char* formatNameBuffer } return result; -} \ No newline at end of file +} diff --git a/src/native/libs/System.Native/pal_mount_wasi.c b/src/native/libs/System.Native/pal_mount_wasi.c index be6ab88cc0f291..61b776160eace6 100644 --- a/src/native/libs/System.Native/pal_mount_wasi.c +++ b/src/native/libs/System.Native/pal_mount_wasi.c @@ -27,4 +27,4 @@ SystemNative_GetFormatInfoForMountPoint(const char* name, char* formatNameBuffer assert((formatNameBuffer != NULL) && (formatType != NULL)); assert(bufferLength > 0); return -1; -} \ No newline at end of file +} From 1171819e235e9b9c24006571a2867a2d5bd6203b Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Thu, 5 Sep 2024 12:19:29 +0200 Subject: [PATCH 04/23] Remove pre-processor directives indention --- .../Interop.MountPoints.FormatInfo.cs | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) 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 dd77b22dbd322c..b5b0f737499f38 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 @@ -75,42 +75,42 @@ internal static int GetFormatInfoForMountPoint(string name, out DriveType type) /// 0 if successful, otherwise an error code. private static unsafe int GetFormatInfoForMountPoint(string name, out string format, out DriveType type) { - #if TARGET_LINUX - try + #if TARGET_LINUX + try + { + const string mountInfoFilePath = "/proc/self/mountinfo"; + var mountInfoFileContent = File.ReadAllLines(mountInfoFilePath); + foreach (var line in mountInfoFileContent) { - const string mountInfoFilePath = "/proc/self/mountinfo"; - var mountInfoFileContent = File.ReadAllLines(mountInfoFilePath); - foreach (var line in mountInfoFileContent) - { - var parser = new StringParser(line, ' '); + var parser = new StringParser(line, ' '); - // Skip fields we don't care about (Fields 1-4) - parser.MoveNext(); // Skip Mount ID - parser.MoveNext(); // Skip Parent ID - parser.MoveNext(); // Skip Major:Minor - parser.MoveNext(); // Skip Root + // Skip fields we don't care about (Fields 1-4) + parser.MoveNext(); // Skip Mount ID + parser.MoveNext(); // Skip Parent ID + parser.MoveNext(); // Skip Major:Minor + parser.MoveNext(); // Skip Root - // Get the mount point (Field 5) - string mountPoint = parser.MoveAndExtractNext(); + // Get the mount point (Field 5) + string mountPoint = parser.MoveAndExtractNext(); - // Skip to the separator which is end of optional fields (Field 8) - while (parser.MoveAndExtractNext() != "-") - { - } + // Skip to the separator which is end of optional fields (Field 8) + while (parser.MoveAndExtractNext() != "-") + { + } - // Get filesystem type (Field 9) - string filesystemType = parser.MoveAndExtractNext(); + // Get filesystem type (Field 9) + string filesystemType = parser.MoveAndExtractNext(); - if (mountPoint.Equals(name, StringComparison.Ordinal)) - { - format = filesystemType; - type = GetDriveType(filesystemType); - return 0; - } + if (mountPoint.Equals(name, StringComparison.Ordinal)) + { + format = filesystemType; + type = GetDriveType(filesystemType); + return 0; } } - catch { /* ignored */ } - #endif + } + catch { /* ignored */ } + #endif byte* formatBuffer = stackalloc byte[MountPointFormatBufferSizeInBytes]; // format names should be small long numericFormat; From d43dd7b78f6b9aa255a89bf8a329fc85dd17f2c9 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Thu, 5 Sep 2024 12:20:43 +0200 Subject: [PATCH 05/23] Fix whitespaces --- .../Unix/System.Native/Interop.MountPoints.FormatInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 b5b0f737499f38..47aa2606cf8d8c 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 @@ -39,7 +39,7 @@ internal static unsafe partial int GetFormatInfoForMountPoint( byte* formatNameBuffer, int bufferLength, long* formatType); - + internal static int GetFormatInfoForMountPoint(string name, out string format) { return GetFormatInfoForMountPoint(name, out format, out _); @@ -128,7 +128,7 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for format = string.Empty; type = DriveType.Unknown; } - + return result; } From 3542fd8e9bd4a5f7e5d2f5c2f76d47cc5b333237 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Thu, 5 Sep 2024 12:38:20 +0200 Subject: [PATCH 06/23] Update src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> --- .../Unix/System.Native/Interop.MountPoints.FormatInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 47aa2606cf8d8c..b22fcb2a04022c 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 @@ -75,7 +75,7 @@ internal static int GetFormatInfoForMountPoint(string name, out DriveType type) /// 0 if successful, otherwise an error code. private static unsafe int GetFormatInfoForMountPoint(string name, out string format, out DriveType type) { - #if TARGET_LINUX +#if TARGET_LINUX try { const string mountInfoFilePath = "/proc/self/mountinfo"; From 1607833416829d759943a46ea9fb84cea2f880a5 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Thu, 5 Sep 2024 12:39:34 +0200 Subject: [PATCH 07/23] fix indention --- .../Unix/System.Native/Interop.MountPoints.FormatInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 b22fcb2a04022c..2784143068f8b4 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 @@ -110,7 +110,7 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for } } catch { /* ignored */ } - #endif +#endif byte* formatBuffer = stackalloc byte[MountPointFormatBufferSizeInBytes]; // format names should be small long numericFormat; From 2fd5836705bec6bfbd858e5401b9e9b6b47de60e Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Fri, 6 Sep 2024 05:23:10 +0200 Subject: [PATCH 08/23] Update src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> --- .../Unix/System.Native/Interop.MountPoints.FormatInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2784143068f8b4..0502c457f7a04d 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 @@ -58,7 +58,7 @@ internal static int GetFormatInfoForMountPoint(string name, out DriveType type) /// 1. On Linux systems, it first attempts to read from `/proc/self/mountinfo`. /// 2. If step 1 fails or on non-Linux systems, it falls back to a P/Invoke call. /// - /// The `/proc/self/mountinfo` approach is preferred on Linux because + /// The `/proc/self/mountinfo` approach is preferred on Linux because /// it's more reliable when procfs is available and functioning correctly. /// /// For other systems: From 49ac57ecb7546bc6551f6c7554ad6f5d82b44af5 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Fri, 6 Sep 2024 05:23:16 +0200 Subject: [PATCH 09/23] Update src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> --- .../Unix/System.Native/Interop.MountPoints.FormatInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 0502c457f7a04d..78a21bc22e4704 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 @@ -111,7 +111,7 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for } catch { /* ignored */ } #endif - + byte* formatBuffer = stackalloc byte[MountPointFormatBufferSizeInBytes]; // format names should be small long numericFormat; int result = GetFormatInfoForMountPoint(name, formatBuffer, MountPointFormatBufferSizeInBytes, &numericFormat); From eafc91bbb60448484477a1f2139846ed020794dc Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Fri, 6 Sep 2024 05:57:33 +0200 Subject: [PATCH 10/23] Use actual type instead of var --- .../Unix/System.Native/Interop.MountPoints.FormatInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 78a21bc22e4704..fc7d0cae4b2402 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 @@ -82,7 +82,7 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for var mountInfoFileContent = File.ReadAllLines(mountInfoFilePath); foreach (var line in mountInfoFileContent) { - var parser = new StringParser(line, ' '); + StringParser parser = new StringParser(line, ' '); // Skip fields we don't care about (Fields 1-4) parser.MoveNext(); // Skip Mount ID From 4a17349d944f1766d7a320d66b231cccf6498562 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Fri, 6 Sep 2024 05:57:57 +0200 Subject: [PATCH 11/23] Update src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs Co-authored-by: Huo Yaoyuan --- .../Unix/System.Native/Interop.MountPoints.FormatInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 fc7d0cae4b2402..4301fbca9fa4dc 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 @@ -101,7 +101,7 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for // Get filesystem type (Field 9) string filesystemType = parser.MoveAndExtractNext(); - if (mountPoint.Equals(name, StringComparison.Ordinal)) + if (mountPoint == name) { format = filesystemType; type = GetDriveType(filesystemType); From 3505c12666604866995cc409f0cf190273b62503 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Fri, 6 Sep 2024 10:11:59 +0200 Subject: [PATCH 12/23] Update src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> --- .../Interop.MountPoints.FormatInfo.cs | 50 +++++++++---------- 1 file changed, 23 insertions(+), 27 deletions(-) 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 4301fbca9fa4dc..6cd5d2f4a1dc71 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 @@ -78,36 +78,32 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for #if TARGET_LINUX try { - const string mountInfoFilePath = "/proc/self/mountinfo"; - var mountInfoFileContent = File.ReadAllLines(mountInfoFilePath); - foreach (var line in mountInfoFileContent) + using StreamReader reader = new("/proc/self/mountinfo"); + + string rawLine; + while ((rawLine = reader.ReadLine()) is not null) { - StringParser parser = new StringParser(line, ' '); - + ReadOnlySpan line = rawLine.AsSpan(); + MemoryExtensions.SpanSplitEnumerator fields = line.Split(' '); + // Skip fields we don't care about (Fields 1-4) - parser.MoveNext(); // Skip Mount ID - parser.MoveNext(); // Skip Parent ID - parser.MoveNext(); // Skip Major:Minor - parser.MoveNext(); // Skip Root - - // Get the mount point (Field 5) - string mountPoint = parser.MoveAndExtractNext(); - + fields.MoveNext(); // Skip Mount ID + fields.MoveNext(); // Skip Parent ID + fields.MoveNext(); // Skip Major:Minor + fields.MoveNext(); // Skip Root + + if (!MemoryExtensions.Equals(line[fields.Current], name, StringComparison.Ordinal)) continue; + // Skip to the separator which is end of optional fields (Field 8) - while (parser.MoveAndExtractNext() != "-") - { - } - - // Get filesystem type (Field 9) - string filesystemType = parser.MoveAndExtractNext(); - - if (mountPoint == name) - { - format = filesystemType; - type = GetDriveType(filesystemType); - return 0; - } - } + while (fields.MoveNext() && !MemoryExtensions.Equals(line[fields.Current], "-", StringComparison.Ordinal)); + + fields.MoveNext(); + format = line[fields.Current].ToString(); + + fields.MoveNext(); + type = GetDriveType(line[fields.Current].ToString()); + + return 0; } catch { /* ignored */ } #endif From c8c0a849ccebde5e615fd627ccbbec46ec505907 Mon Sep 17 00:00:00 2001 From: MojtabaTajik Date: Fri, 6 Sep 2024 11:23:51 +0200 Subject: [PATCH 13/23] Simplify checks --- .../Unix/System.Native/Interop.MountPoints.FormatInfo.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 6cd5d2f4a1dc71..3693ffbe1703a3 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 @@ -92,11 +92,10 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for fields.MoveNext(); // Skip Major:Minor fields.MoveNext(); // Skip Root - if (!MemoryExtensions.Equals(line[fields.Current], name, StringComparison.Ordinal)) continue; + if (!line[fields.Current].Equals(name, StringComparison.Ordinal)) continue; // Skip to the separator which is end of optional fields (Field 8) - while (fields.MoveNext() && !MemoryExtensions.Equals(line[fields.Current], "-", StringComparison.Ordinal)); - + while (fields.MoveNext() && !line[fields.Current].Equals("-", StringComparison.Ordinal)); fields.MoveNext(); format = line[fields.Current].ToString(); From eba6e78aab3f4f61e36176ec1e99325dab609de7 Mon Sep 17 00:00:00 2001 From: MojtabaTajik Date: Fri, 6 Sep 2024 11:25:00 +0200 Subject: [PATCH 14/23] add new line --- .../Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs | 1 + 1 file changed, 1 insertion(+) 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 3693ffbe1703a3..fc618bb0c40f43 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 @@ -97,6 +97,7 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for // Skip to the separator which is end of optional fields (Field 8) while (fields.MoveNext() && !line[fields.Current].Equals("-", StringComparison.Ordinal)); fields.MoveNext(); + format = line[fields.Current].ToString(); fields.MoveNext(); From 5da14ac1c5b955f94e451696d3fed1722fcd0f46 Mon Sep 17 00:00:00 2001 From: MojtabaTajik Date: Fri, 6 Sep 2024 11:27:02 +0200 Subject: [PATCH 15/23] fix spaces --- .../System.Native/Interop.MountPoints.FormatInfo.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 fc618bb0c40f43..3209260614bfb7 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 @@ -79,13 +79,13 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for try { using StreamReader reader = new("/proc/self/mountinfo"); - + string rawLine; while ((rawLine = reader.ReadLine()) is not null) { ReadOnlySpan line = rawLine.AsSpan(); MemoryExtensions.SpanSplitEnumerator fields = line.Split(' '); - + // Skip fields we don't care about (Fields 1-4) fields.MoveNext(); // Skip Mount ID fields.MoveNext(); // Skip Parent ID @@ -95,14 +95,14 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for if (!line[fields.Current].Equals(name, StringComparison.Ordinal)) continue; // Skip to the separator which is end of optional fields (Field 8) - while (fields.MoveNext() && !line[fields.Current].Equals("-", StringComparison.Ordinal)); + while (fields.MoveNext() && !line[fields.Current].Equals("-", StringComparison.Ordinal)); + fields.MoveNext(); - format = line[fields.Current].ToString(); fields.MoveNext(); type = GetDriveType(line[fields.Current].ToString()); - + return 0; } catch { /* ignored */ } From ab1e2f41496f0064ca3229bb22e101d251c30ac1 Mon Sep 17 00:00:00 2001 From: MojtabaTajik Date: Fri, 6 Sep 2024 11:37:11 +0200 Subject: [PATCH 16/23] Revert "fix spaces" This reverts commit 5da14ac1c5b955f94e451696d3fed1722fcd0f46. --- .../System.Native/Interop.MountPoints.FormatInfo.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 3209260614bfb7..fc618bb0c40f43 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 @@ -79,13 +79,13 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for try { using StreamReader reader = new("/proc/self/mountinfo"); - + string rawLine; while ((rawLine = reader.ReadLine()) is not null) { ReadOnlySpan line = rawLine.AsSpan(); MemoryExtensions.SpanSplitEnumerator fields = line.Split(' '); - + // Skip fields we don't care about (Fields 1-4) fields.MoveNext(); // Skip Mount ID fields.MoveNext(); // Skip Parent ID @@ -95,14 +95,14 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for if (!line[fields.Current].Equals(name, StringComparison.Ordinal)) continue; // Skip to the separator which is end of optional fields (Field 8) - while (fields.MoveNext() && !line[fields.Current].Equals("-", StringComparison.Ordinal)); - + while (fields.MoveNext() && !line[fields.Current].Equals("-", StringComparison.Ordinal)); fields.MoveNext(); + format = line[fields.Current].ToString(); fields.MoveNext(); type = GetDriveType(line[fields.Current].ToString()); - + return 0; } catch { /* ignored */ } From d52fe86bc3ab78950f6e21f2df233f23a42277a8 Mon Sep 17 00:00:00 2001 From: MojtabaTajik Date: Fri, 6 Sep 2024 11:37:17 +0200 Subject: [PATCH 17/23] Revert "add new line" This reverts commit eba6e78aab3f4f61e36176ec1e99325dab609de7. --- .../Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs | 1 - 1 file changed, 1 deletion(-) 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 fc618bb0c40f43..3693ffbe1703a3 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 @@ -97,7 +97,6 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for // Skip to the separator which is end of optional fields (Field 8) while (fields.MoveNext() && !line[fields.Current].Equals("-", StringComparison.Ordinal)); fields.MoveNext(); - format = line[fields.Current].ToString(); fields.MoveNext(); From 4bbceac4064173b0c5a4663c51e9c70821935230 Mon Sep 17 00:00:00 2001 From: MojtabaTajik Date: Fri, 6 Sep 2024 11:37:22 +0200 Subject: [PATCH 18/23] Revert "Simplify checks" This reverts commit c8c0a849ccebde5e615fd627ccbbec46ec505907. --- .../Unix/System.Native/Interop.MountPoints.FormatInfo.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 3693ffbe1703a3..6cd5d2f4a1dc71 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 @@ -92,10 +92,11 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for fields.MoveNext(); // Skip Major:Minor fields.MoveNext(); // Skip Root - if (!line[fields.Current].Equals(name, StringComparison.Ordinal)) continue; + if (!MemoryExtensions.Equals(line[fields.Current], name, StringComparison.Ordinal)) continue; // Skip to the separator which is end of optional fields (Field 8) - while (fields.MoveNext() && !line[fields.Current].Equals("-", StringComparison.Ordinal)); + while (fields.MoveNext() && !MemoryExtensions.Equals(line[fields.Current], "-", StringComparison.Ordinal)); + fields.MoveNext(); format = line[fields.Current].ToString(); From 459d1a60a934e9d457af2e4cc016b15475e463c5 Mon Sep 17 00:00:00 2001 From: MojtabaTajik Date: Fri, 6 Sep 2024 11:37:26 +0200 Subject: [PATCH 19/23] Revert "Update src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs" This reverts commit 3505c12666604866995cc409f0cf190273b62503. --- .../Interop.MountPoints.FormatInfo.cs | 50 ++++++++++--------- 1 file changed, 27 insertions(+), 23 deletions(-) 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 6cd5d2f4a1dc71..4301fbca9fa4dc 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 @@ -78,32 +78,36 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for #if TARGET_LINUX try { - using StreamReader reader = new("/proc/self/mountinfo"); - - string rawLine; - while ((rawLine = reader.ReadLine()) is not null) + const string mountInfoFilePath = "/proc/self/mountinfo"; + var mountInfoFileContent = File.ReadAllLines(mountInfoFilePath); + foreach (var line in mountInfoFileContent) { - ReadOnlySpan line = rawLine.AsSpan(); - MemoryExtensions.SpanSplitEnumerator fields = line.Split(' '); - + StringParser parser = new StringParser(line, ' '); + // Skip fields we don't care about (Fields 1-4) - fields.MoveNext(); // Skip Mount ID - fields.MoveNext(); // Skip Parent ID - fields.MoveNext(); // Skip Major:Minor - fields.MoveNext(); // Skip Root - - if (!MemoryExtensions.Equals(line[fields.Current], name, StringComparison.Ordinal)) continue; - + parser.MoveNext(); // Skip Mount ID + parser.MoveNext(); // Skip Parent ID + parser.MoveNext(); // Skip Major:Minor + parser.MoveNext(); // Skip Root + + // Get the mount point (Field 5) + string mountPoint = parser.MoveAndExtractNext(); + // Skip to the separator which is end of optional fields (Field 8) - while (fields.MoveNext() && !MemoryExtensions.Equals(line[fields.Current], "-", StringComparison.Ordinal)); - - fields.MoveNext(); - format = line[fields.Current].ToString(); - - fields.MoveNext(); - type = GetDriveType(line[fields.Current].ToString()); - - return 0; + while (parser.MoveAndExtractNext() != "-") + { + } + + // Get filesystem type (Field 9) + string filesystemType = parser.MoveAndExtractNext(); + + if (mountPoint == name) + { + format = filesystemType; + type = GetDriveType(filesystemType); + return 0; + } + } } catch { /* ignored */ } #endif From b5e287357487dd47b403e5e34cd0460d30718436 Mon Sep 17 00:00:00 2001 From: Mojtaba Tajik Date: Fri, 6 Sep 2024 13:43:19 +0200 Subject: [PATCH 20/23] Update src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> --- .../Interop.MountPoints.FormatInfo.cs | 50 +++++++++---------- 1 file changed, 23 insertions(+), 27 deletions(-) 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 4301fbca9fa4dc..6cd5d2f4a1dc71 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 @@ -78,36 +78,32 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for #if TARGET_LINUX try { - const string mountInfoFilePath = "/proc/self/mountinfo"; - var mountInfoFileContent = File.ReadAllLines(mountInfoFilePath); - foreach (var line in mountInfoFileContent) + using StreamReader reader = new("/proc/self/mountinfo"); + + string rawLine; + while ((rawLine = reader.ReadLine()) is not null) { - StringParser parser = new StringParser(line, ' '); - + ReadOnlySpan line = rawLine.AsSpan(); + MemoryExtensions.SpanSplitEnumerator fields = line.Split(' '); + // Skip fields we don't care about (Fields 1-4) - parser.MoveNext(); // Skip Mount ID - parser.MoveNext(); // Skip Parent ID - parser.MoveNext(); // Skip Major:Minor - parser.MoveNext(); // Skip Root - - // Get the mount point (Field 5) - string mountPoint = parser.MoveAndExtractNext(); - + fields.MoveNext(); // Skip Mount ID + fields.MoveNext(); // Skip Parent ID + fields.MoveNext(); // Skip Major:Minor + fields.MoveNext(); // Skip Root + + if (!MemoryExtensions.Equals(line[fields.Current], name, StringComparison.Ordinal)) continue; + // Skip to the separator which is end of optional fields (Field 8) - while (parser.MoveAndExtractNext() != "-") - { - } - - // Get filesystem type (Field 9) - string filesystemType = parser.MoveAndExtractNext(); - - if (mountPoint == name) - { - format = filesystemType; - type = GetDriveType(filesystemType); - return 0; - } - } + while (fields.MoveNext() && !MemoryExtensions.Equals(line[fields.Current], "-", StringComparison.Ordinal)); + + fields.MoveNext(); + format = line[fields.Current].ToString(); + + fields.MoveNext(); + type = GetDriveType(line[fields.Current].ToString()); + + return 0; } catch { /* ignored */ } #endif From 542c24442c1d740f2474028d14d67c97596286c4 Mon Sep 17 00:00:00 2001 From: MojtabaTajik Date: Fri, 6 Sep 2024 14:04:16 +0200 Subject: [PATCH 21/23] Skip to mount point --- .../Unix/System.Native/Interop.MountPoints.FormatInfo.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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 6cd5d2f4a1dc71..5bddab527dd9ba 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 @@ -91,18 +91,19 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for fields.MoveNext(); // Skip Parent ID fields.MoveNext(); // Skip Major:Minor fields.MoveNext(); // Skip Root + fields.MoveNext(); // Move next to MountPoint field - if (!MemoryExtensions.Equals(line[fields.Current], name, StringComparison.Ordinal)) continue; + if (!line[fields.Current].Equals(name, StringComparison.Ordinal)) continue; // Skip to the separator which is end of optional fields (Field 8) - while (fields.MoveNext() && !MemoryExtensions.Equals(line[fields.Current], "-", StringComparison.Ordinal)); + while (fields.MoveNext() && !line[fields.Current].Equals("-", StringComparison.Ordinal)) ; fields.MoveNext(); format = line[fields.Current].ToString(); fields.MoveNext(); type = GetDriveType(line[fields.Current].ToString()); - + return 0; } catch { /* ignored */ } From 171c068d2d13fbbb9062648c1cc6fe1bc4d47b96 Mon Sep 17 00:00:00 2001 From: MojtabaTajik Date: Fri, 6 Sep 2024 14:05:36 +0200 Subject: [PATCH 22/23] Update comment --- .../Unix/System.Native/Interop.MountPoints.FormatInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 5bddab527dd9ba..a9828269eab1f7 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 @@ -91,7 +91,7 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for fields.MoveNext(); // Skip Parent ID fields.MoveNext(); // Skip Major:Minor fields.MoveNext(); // Skip Root - fields.MoveNext(); // Move next to MountPoint field + fields.MoveNext(); // Skip to MountPoint field if (!line[fields.Current].Equals(name, StringComparison.Ordinal)) continue; From 1ea70974c3232fa2f33e1ba565542e0372225763 Mon Sep 17 00:00:00 2001 From: MojtabaTajik Date: Fri, 6 Sep 2024 14:34:10 +0200 Subject: [PATCH 23/23] Use MemoryExtensions.Equals --- .../Unix/System.Native/Interop.MountPoints.FormatInfo.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 a9828269eab1f7..f48ea6d58acbc6 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 @@ -79,13 +79,13 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for try { using StreamReader reader = new("/proc/self/mountinfo"); - + string rawLine; while ((rawLine = reader.ReadLine()) is not null) { ReadOnlySpan line = rawLine.AsSpan(); MemoryExtensions.SpanSplitEnumerator fields = line.Split(' '); - + // Skip fields we don't care about (Fields 1-4) fields.MoveNext(); // Skip Mount ID fields.MoveNext(); // Skip Parent ID @@ -93,10 +93,10 @@ private static unsafe int GetFormatInfoForMountPoint(string name, out string for fields.MoveNext(); // Skip Root fields.MoveNext(); // Skip to MountPoint field - if (!line[fields.Current].Equals(name, StringComparison.Ordinal)) continue; + if (!MemoryExtensions.Equals(line[fields.Current], name, StringComparison.Ordinal)) continue; // Skip to the separator which is end of optional fields (Field 8) - while (fields.MoveNext() && !line[fields.Current].Equals("-", StringComparison.Ordinal)) ; + while (fields.MoveNext() && !MemoryExtensions.Equals(line[fields.Current], "-", StringComparison.Ordinal)); fields.MoveNext(); format = line[fields.Current].ToString();