#include <utils/mono-threads-debug.h>
static const char *
-os_version_string (void)
+kernel_version_string (void)
{
#ifdef HAVE_SYS_UTSNAME_H
static struct utsname name;
return "";
}
+static gboolean
+starts_with (const char *pre, size_t pre_sz, const char *str)
+{
+ return strncmp (pre, str, pre_sz) == 0;
+}
+
+static const char *
+macos_version_string (void)
+{
+ /* Can't allocate in here, could be called from a signal handler in a
+ * crashed process.
+ */
+ static const char *version_string;
+ static char buf[256];
+ static const size_t buf_size = sizeof (buf);
+
+ if (version_string)
+ return version_string;
+
+ /* macOS 10.13.6 or later */
+ if (!version_string) {
+ size_t size = 0;
+ if (sysctlbyname ("kern.osproductversion", NULL, &size, NULL, 0) < 0 || size >= buf_size) {
+ /* if we couldn't get the size or if it needs more space that we have in buf, leave it empty */
+ version_string = "";
+ return version_string;
+ }
+
+ if (sysctlbyname ("kern.osproductversion", (char*)buf, &size, NULL, 0) >= 0)
+ version_string = &buf[0];
+ }
+ /* macOS 10.13.5 or older */
+ if (!version_string) {
+ const char *kv_string = kernel_version_string ();
+ if (starts_with (G_STRING_CONSTANT_AND_LENGTH ("17"), kv_string))
+ version_string = "10.13"; // High Sierra
+ else if (starts_with (G_STRING_CONSTANT_AND_LENGTH ("16"), kv_string))
+ version_string = "10.12"; // Sierra
+ else if (starts_with (G_STRING_CONSTANT_AND_LENGTH ("15"), kv_string))
+ version_string = "10.11"; // El Capitan
+ else if (starts_with (G_STRING_CONSTANT_AND_LENGTH ("14"), kv_string))
+ version_string = "10.10"; // Yosemite
+ else if (starts_with (G_STRING_CONSTANT_AND_LENGTH ("13"), kv_string))
+ version_string = "10.9"; // Mavericks
+ else if (starts_with (G_STRING_CONSTANT_AND_LENGTH ("12"), kv_string))
+ version_string = "10.8"; // Mountain Lion
+ else if (starts_with (G_STRING_CONSTANT_AND_LENGTH ("11"), kv_string))
+ version_string = "10.7"; // Lion
+ }
+ if (!version_string)
+ version_string = "";
+
+ return version_string;
+}
+
// To get the path of the running process
#include <libproc.h>
merp->moduleOffset = 0;
merp->uiLidArg = MONO_LOCALE_INVARIANT;
-
- merp->osVersion = os_version_string ();
+#if defined (TARGET_OSX)
+ merp->osVersion = macos_version_string ();
+#else
+ merp->osVersion = kernel_version_string ();
+#endif
// FIXME: THis is apple-only for now
merp->systemManufacturer = "apple";