[PATCH 0/2] MR10014: ntdll, mountmgr.sys: Report free space for "important" data on macOS.
Brings the number in line with that reported by Finder. --- fstatvfs on macOS returns the immediately available space on-disk, but the Finder shows a different number, which accounts for "reclaimable" space (i.e., that used by purgeable caches and other temporary data). That reclaimable space is available for Wine to use, and the difference between the two figures can sometimes be dramatic. We should ideally show what Finder shows. It is unfortunate to have to resort to `fcntl(F_GETPATH)` here, but the CF functions require CFURLs for paths and do not operate on fds. There does not seem to be a way to get the reclaimable space figures taking quotas into account (i.e. the difference between bfree and bavail). However there is AFAIK no supported way to enable quotas on macOS, so it strikes me as exceedingly unlikely that that would matter. I'm effectively setting CallerAvailableAllocationUnits and ActualAvailableAllocationUnits to the same value. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10014
From: Tim Clem <tclem@codeweavers.com> Brings the number in line with that reported by Finder. --- dlls/ntdll/unix/file.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 488de37b508..00df4bbaa2c 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -103,6 +103,9 @@ #undef XATTR_ADDITIONAL_OPTIONS #include <sys/extattr.h> #endif +#ifdef __APPLE__ +#include <CoreFoundation/CoreFoundation.h> +#endif #include <time.h> #include <unistd.h> @@ -2173,6 +2176,28 @@ static NTSTATUS server_get_name_info( HANDLE handle, FILE_NAME_INFORMATION *info } +#ifdef __APPLE__ +static LONGLONG get_free_bytes_for_important_data(int fd) +{ + CFURLRef url = NULL; + CFNumberRef num = NULL; + char *path = NULL; + LONGLONG space = -1; + + if (!(path = malloc( MAXPATHLEN ))) goto done; + if (fcntl( fd, F_GETPATH, path ) == -1) goto done; + if (!(url = CFURLCreateFromFileSystemRepresentation( NULL, (UInt8 *)path, strlen( path ), false ))) goto done; + if (!CFURLCopyResourcePropertyForKey( url, kCFURLVolumeAvailableCapacityForImportantUsageKey, &num, NULL )) goto done; + CFNumberGetValue( num, kCFNumberLongLongType, &space ); + +done: + free( path ); + if (url) CFRelease( url ); + if (num) CFRelease( num ); + return space; +} +#endif + static NTSTATUS get_full_size_info(int fd, FILE_FS_FULL_SIZE_INFORMATION *info) { struct stat st; ULONGLONG bsize; @@ -2183,6 +2208,10 @@ static NTSTATUS get_full_size_info(int fd, FILE_FS_FULL_SIZE_INFORMATION *info) struct statfs stfs; #endif +#ifdef __APPLE__ + LONGLONG important_free_bytes; +#endif + if (fstat( fd, &st ) < 0) return errno_to_status( errno ); if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) return STATUS_INVALID_DEVICE_REQUEST; @@ -2194,6 +2223,12 @@ static NTSTATUS get_full_size_info(int fd, FILE_FS_FULL_SIZE_INFORMATION *info) if (fstatfs( fd, &stfs ) < 0) return errno_to_status( errno ); bsize = stfs.f_bsize; #endif + +#ifdef __APPLE__ + important_free_bytes = get_free_bytes_for_important_data( fd ); + if (important_free_bytes != -1) stfs.f_bavail = stfs.f_bfree = important_free_bytes / bsize; +#endif + if (bsize == 2048) /* assume CD-ROM */ { info->BytesPerSector = 2048; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10014
From: Tim Clem <tclem@codeweavers.com> Brings the number in line with that reported by Finder. --- dlls/mountmgr.sys/unixlib.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/dlls/mountmgr.sys/unixlib.c b/dlls/mountmgr.sys/unixlib.c index bcc36383834..2a5fd272db6 100644 --- a/dlls/mountmgr.sys/unixlib.c +++ b/dlls/mountmgr.sys/unixlib.c @@ -36,6 +36,10 @@ #ifdef HAVE_SYS_STATVFS_H # include <sys/statvfs.h> #endif +#ifdef __APPLE__ +# include <CoreFoundation/CoreFoundation.h> +# include <sys/param.h> +#endif #include <unistd.h> #include "unixlib.h" @@ -311,6 +315,28 @@ static NTSTATUS set_dosdev_symlink( void *args ) return status; } +#ifdef __APPLE__ +static LONGLONG get_free_bytes_for_important_data(int fd) +{ + CFURLRef url = NULL; + CFNumberRef num = NULL; + char *path = NULL; + LONGLONG space = -1; + + if (!(path = malloc( MAXPATHLEN ))) goto done; + if (fcntl( fd, F_GETPATH, path ) == -1) goto done; + if (!(url = CFURLCreateFromFileSystemRepresentation( NULL, (UInt8 *)path, strlen( path ), false ))) goto done; + if (!CFURLCopyResourcePropertyForKey( url, kCFURLVolumeAvailableCapacityForImportantUsageKey, &num, NULL )) goto done; + CFNumberGetValue( num, kCFNumberLongLongType, &space ); + +done: + free( path ); + if (url) CFRelease( url ); + if (num) CFRelease( num ); + return space; +} +#endif + static NTSTATUS get_volume_size_info( void *args ) { const struct get_volume_size_info_params *params = args; @@ -328,6 +354,10 @@ static NTSTATUS get_volume_size_info( void *args ) struct statfs stfs; #endif +#ifdef __APPLE__ + LONGLONG important_free_bytes; +#endif + if (!unix_mount) return STATUS_NO_SUCH_DEVICE; if (unix_mount[0] != '/') @@ -365,6 +395,12 @@ static NTSTATUS get_volume_size_info( void *args ) } bsize = stfs.f_bsize; #endif + +#ifdef __APPLE__ + important_free_bytes = get_free_bytes_for_important_data( fd ); + if (important_free_bytes != -1) stfs.f_bavail = stfs.f_bfree = important_free_bytes / bsize; +#endif + if (bsize == 2048) /* assume CD-ROM */ { info->bytes_per_sector = 2048; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10014
This merge request was approved by Brendan Shanks. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10014
participants (3)
-
Brendan Shanks (@bshanks) -
Tim Clem -
Tim Clem (@tclem)