ninxsoft / mist-cli

A Mac command-line tool that automatically downloads macOS Firmwares / Installers.
MIT License
620 stars 29 forks source link

volumeAvailableCapacityForImportantUsageKey returns 0 when no user is logged in #129

Closed PicoMitchell closed 1 year ago

PicoMitchell commented 1 year ago

Thanks so much for updating mist-cli to use volumeAvailableCapacityForImportantUsageKey instead of systemFreeSize to properly calculate free space in a way that matches Finder!

But, there is one odd quirk with volumeAvailableCapacityForImportantUsageKey which is that it returns 0 when no user is logged in. I don't think this means volumeAvailableCapacityForImportantUsageKey should not be used since it is the better/correct thing to use when a user is logged in, but if someone tries to run mist-cli in a scripted way when no user is logged in there would need to be a fallback since currently mist-cli would not be able to download anything since it would always think there is no free space when there could be.

I would suggest falling back on volumeAvailableCapacityKey which matches what systemFreeSize returns and works properly when no user is logged in. Since you're already using let values: URLResourceValues = try url.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey]) you can easily add .volumeAvailableCapacityKey to the array of keys you're retrieving and then check if values.volumeAvailableCapacityForImportantUsage is 0 and use values.volumeAvailableCapacityKey instead if so to properly get some free space value whether or not a user is logged in.

Here is some more info about this issue this same described solution with code in JavaScript for Automation (JXA): https://macadmins.slack.com/archives/C0619KJQY/p1663642814450849

ninxsoft commented 1 year ago

I have a fix in https://github.com/ninxsoft/mist-cli/pull/130, @PicoMitchell if you have time I would love some fresh eyes to test and confirm everything is working as expected 🙏

PicoMitchell commented 1 year ago

I believe that new code would use the volumeAvailableCapacityKey when Mist is running as root even if a user is actually logged in and volumeAvailableCapacityForImportantUsage could be used.

I would recommend not checking the running user with NSUserName or anything like that and instead always retrieve both values and then check if volumeAvailableCapacityForImportantUsage is 0 and fallback on volumeAvailableCapacityKey if so. Doing it that way would guarantee always using volumeAvailableCapacityForImportantUsage when it has been properly loaded.

PicoMitchell commented 1 year ago

Here is a JXA example of how volumeAvailableCapacityForImportantUsage still works properly when run as root as long as a user is currently logged in:

sudo osascript -l JavaScript -e 'console.log($.NSUserName().js); ObjC.deepUnwrap($.NSURL.fileURLWithPath("/").resourceValuesForKeysError(ObjC.wrap([$.NSURLVolumeAvailableCapacityForImportantUsageKey]), ObjC.wrap())).NSURLVolumeAvailableCapacityForImportantUsageKey'

When run from Terminal, that will output "root" for the NSUserName since the osascript command is run as sudo and then also output the current available space from the volumeAvailableCapacityForImportantUsage key since a user is currently logged in.

volumeAvailableCapacityForImportantUsage would only not work when run via script in such a way that it's running very early on boot before login or when the system is sitting at the login window (such as via LaunchDaemon).

ninxsoft commented 1 year ago

@PicoMitchell thanks for the info, works for me!