From 2dac15634f72fa1d926940d0bd8fb91b908b14f5 Mon Sep 17 00:00:00 2001 From: Ariel Abreu Date: Wed, 5 May 2021 15:42:26 -0400 Subject: [PATCH] Implement os_system_version_get_current_version --- src/misc.m | 63 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/src/misc.m b/src/misc.m index 3134425..eb8a83c 100644 --- a/src/misc.m +++ b/src/misc.m @@ -24,6 +24,24 @@ #import #import +#include + +struct os_system_version { + unsigned int major; + unsigned int minor; + unsigned int patch; +}; + +XPC_EXPORT +struct os_system_version _system_version_fallback = { + .major = 10, + .minor = 15, + .patch = 0, +}; + +static struct os_system_version current_version = {0}; +static dispatch_once_t current_version_once; + XPC_EXPORT bool _availability_version_check(size_t version_count, dyld_build_version_t* versions) { // i'm *pretty* sure the second argument is an array of `dyld_build_version_t` @@ -43,26 +61,41 @@ bool _system_version_copy_string_plist(char* out_string) { return false; }; +// provided string MUST have at least 48 characters XPC_EXPORT bool _system_version_copy_string_sysctl(char* out_string) { - xpc_stub(); - return false; -}; - -XPC_EXPORT uint32_t _system_version_fallback[] = { 10, 15, 0 }; - -XPC_EXPORT -bool _system_version_parse_string(const char* string, uint32_t* out_version) { - // `version` is an array of 3 `uint32_t`s (or `int`s) - xpc_stub(); - return false; + size_t out_string_length = 48; + return sysctlbyname("kern.osproductversion", out_string, &out_string_length, NULL, 0) == 0; }; XPC_EXPORT -int os_system_version_get_current_version(uint32_t* out_version) { - // parameter 1's type is a good guess, but i'm unsure - xpc_stub(); - return -1; +bool _system_version_parse_string(const char* string, struct os_system_version* out_version) { + sscanf(string, "%u.%u.%u", &out_version->major, &out_version->minor, &out_version->patch); + return true; +}; + +XPC_EXPORT +int os_system_version_get_current_version(struct os_system_version* out_version) { + dispatch_once(¤t_version_once, ^{ + char version_string[48] = {0}; + + if (!_system_version_copy_string_sysctl(version_string)) { + goto fallback; + } + + if (!_system_version_parse_string(version_string, ¤t_version)) { + goto fallback; + } + + return; + + fallback: + memcpy(¤t_version, &_system_version_fallback, sizeof(struct os_system_version)); + }); + + memcpy(out_version, ¤t_version, sizeof(struct os_system_version)); + + return 0; }; XPC_EXPORT