diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index c67af683d..8c7923bfd 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -2086,6 +2086,20 @@ g_get_user_special_dir g_get_system_data_dirs g_get_system_config_dirs g_reload_user_special_dirs_cache +g_get_os_info + + +G_OS_INFO_KEY_NAME +G_OS_INFO_KEY_PRETTY_NAME +G_OS_INFO_KEY_VERSION +G_OS_INFO_KEY_VERSION_CODENAME +G_OS_INFO_KEY_VERSION_ID +G_OS_INFO_KEY_ID +G_OS_INFO_KEY_HOME_URL +G_OS_INFO_KEY_DOCUMENTATION_URL +G_OS_INFO_KEY_SUPPORT_URL +G_OS_INFO_KEY_BUG_REPORT_URL +G_OS_INFO_KEY_PRIVACY_POLICY_URL g_get_host_name diff --git a/glib/gutils.c b/glib/gutils.c index e2476a963..79ee24fff 100644 --- a/glib/gutils.c +++ b/glib/gutils.c @@ -1154,6 +1154,94 @@ g_set_application_name (const gchar *application_name) g_warning ("g_set_application_name() called multiple times"); } +/** + * g_get_os_info: + * @key_name: a key for the OS info being requested, for example %G_OS_INFO_KEY_NAME. + * + * Get information about the operating system. + * + * On Linux this comes from the /etc/os-release file. On other systems, it may + * come from a variety of sources. You can either use the standard key names + * like %G_OS_INFO_KEY_NAME or pass any UTF-8 string key name. For example, + * /etc/os-release provides a number of other less commonly used values that may + * be useful. No key is guaranteed to be provided, so the caller should always + * check if the result is %NULL. + * + * Returns: (nullable): The associated value for the requested key or %NULL if + * this information is not provided. + * + * Since: 2.64 + **/ +gchar * +g_get_os_info (const gchar *key_name) +{ +#if defined (__APPLE__) + if (g_strcmp0 (key_name, G_OS_INFO_KEY_NAME) == 0) + return g_strdup (_("macOS")); + else + return NULL; +#elif defined (G_OS_UNIX) + gchar *buffer; + gchar *prefix; + GStrv lines; + int i; + gchar *result = NULL; + GError *error = NULL; + + g_return_val_if_fail (key_name != NULL, NULL); + + if (!g_file_get_contents ("/etc/os-release", &buffer, NULL, &error)) + { + gboolean file_missing; + + file_missing = g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT); + g_clear_error (&error); + + if (!file_missing || + !g_file_get_contents ("/usr/lib/os-release", &buffer, NULL, NULL)) + return NULL; + } + + lines = g_strsplit (buffer, "\n", -1); + g_free (buffer); + prefix = g_strdup_printf ("%s=", key_name); + for (i = 0; lines[i] != NULL; i++) + { + const gchar *line = lines[i]; + const gchar *value; + + if (g_str_has_prefix (line, prefix)) + { + value = line + strlen (prefix); + result = g_shell_unquote (value, NULL); + if (result == NULL) + result = g_strdup (value); + break; + } + } + g_strfreev (lines); + g_free (prefix); + + /* Default values in spec */ + if (result == NULL) + { + if (g_str_equal (key_name, G_OS_INFO_KEY_NAME)) + return g_strdup ("Linux"); + if (g_str_equal (key_name, G_OS_INFO_KEY_ID)) + return g_strdup ("linux"); + if (g_str_equal (key_name, G_OS_INFO_KEY_PRETTY_NAME)) + return g_strdup ("Linux"); + } + + return g_steal_pointer (&result); +#elif defined (G_OS_WIN32) + if (g_strcmp0 (key_name, G_OS_INFO_KEY_NAME) == 0) + return g_strdup (_("Windows")); + else + return NULL; +#endif +} + /* Set @global_str to a copy of @new_value if it’s currently unset or has a * different value. If its current value matches @new_value, do nothing. If * replaced, we have to leak the old value as client code could still have diff --git a/glib/gutils.h b/glib/gutils.h index 560a84e3a..8a927d0b3 100644 --- a/glib/gutils.h +++ b/glib/gutils.h @@ -65,6 +65,129 @@ GLIB_AVAILABLE_IN_ALL const gchar * g_get_application_name (void); GLIB_AVAILABLE_IN_ALL void g_set_application_name (const gchar *application_name); +GLIB_AVAILABLE_IN_2_64 +gchar * g_get_os_info (const gchar *key_name); + +/** + * G_OS_INFO_KEY_NAME: + * + * A key to get the name of the operating system excluding version information suitable for presentation to the user, e.g. "YoYoOS" + * + * Since: 2.64 + */ +#define G_OS_INFO_KEY_NAME \ + GLIB_AVAILABLE_MACRO_IN_2_64 \ + "NAME" + +/** + * G_OS_INFO_KEY_PRETTY_NAME: + * + * A key to get the name of the operating system in a format suitable for presentation to the user, e.g. "YoYoOS Foo" + * + * Since: 2.64 + */ +#define G_OS_INFO_KEY_PRETTY_NAME \ + GLIB_AVAILABLE_MACRO_IN_2_64 \ + "PRETTY_NAME" + +/** + * G_OS_INFO_KEY_VERSION: + * + * A key to get the operating system version suitable for presentation to the user, e.g. "42 (Foo)" + * + * Since: 2.64 + */ +#define G_OS_INFO_KEY_VERSION \ + GLIB_AVAILABLE_MACRO_IN_2_64 \ + "VERSION" + +/** + * G_OS_INFO_KEY_VERSION_CODENAME: + * + * A key to get a codename identifying the operating system release suitable for processing by scripts or usage in generated filenames, e.g. "foo" + * + * Since: 2.64 + */ +#define G_OS_INFO_KEY_VERSION_CODENAME \ + GLIB_AVAILABLE_MACRO_IN_2_64 \ + "VERSION_CODENAME" + +/** + * G_OS_INFO_KEY_VERSION_ID: + * + * A key to get the version of the operating system suitable for processing by scripts or usage in generated filenames, e.g. "42" + * + * Since: 2.64 + */ +#define G_OS_INFO_KEY_VERSION_ID \ + GLIB_AVAILABLE_MACRO_IN_2_64 \ + "VERSION_ID" + +/** + * G_OS_INFO_KEY_ID: + * + * A key to get an ID identifying the operating system suitable for processing by scripts or usage in generated filenames, e.g. "yoyoos" + * + * Since: 2.64 + */ +#define G_OS_INFO_KEY_ID \ + GLIB_AVAILABLE_MACRO_IN_2_64 \ + "ID" + +/** + * G_OS_INFO_KEY_HOME_URL: + * + * A key to get the homepage for the operating system, e.g. "https://www.yoyo-os.com/" + * + * Since: 2.64 + */ +#define G_OS_INFO_KEY_HOME_URL \ + GLIB_AVAILABLE_MACRO_IN_2_64 \ + "HOME_URL" + +/** + * G_OS_INFO_KEY_DOCUMENTATION_URL: + * + * A key to get the documentation page for the operating system, e.g. "https://docs.yoyo-os.com/" + * + * Since: 2.64 + */ +#define G_OS_INFO_KEY_DOCUMENTATION_URL \ + GLIB_AVAILABLE_MACRO_IN_2_64 \ + "DOCUMENTATION_URL" + +/** + * G_OS_INFO_KEY_SUPPORT_URL: + * + * A key to get the support page for the operating system, e.g. "https://support.yoyo-os.com/" + * + * Since: 2.64 + */ +#define G_OS_INFO_KEY_SUPPORT_URL \ + GLIB_AVAILABLE_MACRO_IN_2_64 \ + "SUPPORT_URL" + +/** + * G_OS_INFO_KEY_BUG_REPORT_URL: + * + * A key to get the bug reporting page for the operating system, e.g. "https://bugs.yoyo-os.com/" + * + * Since: 2.64 + */ +#define G_OS_INFO_KEY_BUG_REPORT_URL \ + GLIB_AVAILABLE_MACRO_IN_2_64 \ + "BUG_REPORT_URL" + +/** + * G_OS_INFO_KEY_PRIVACY_POLICY_URL: + * + * A key to get the privacy policy for the operating system, e.g. "https://privacy.yoyo-os.com/" + * + * Since: 2.64 + */ +#define G_OS_INFO_KEY_PRIVACY_POLICY_URL \ + GLIB_AVAILABLE_MACRO_IN_2_64 \ + "PRIVACY_POLICY_URL" GLIB_AVAILABLE_IN_ALL void g_reload_user_special_dirs_cache (void); diff --git a/glib/tests/utils.c b/glib/tests/utils.c index d1ca0b633..7dbfb1e47 100644 --- a/glib/tests/utils.c +++ b/glib/tests/utils.c @@ -517,6 +517,20 @@ test_desktop_special_dir (void) g_assert (dir2 != NULL); } +static void +test_os_info (void) +{ +#if defined (G_OS_UNIX) || defined (G_OS_WIN32) + gchar *name; + + name = g_get_os_info (G_OS_INFO_KEY_NAME); + g_assert (name != NULL); + g_free (name); +#else + g_test_skip ("g_get_os_info() not supported on this platform"); +#endif +} + static gboolean source_test (gpointer data) { @@ -767,6 +781,7 @@ main (int argc, #endif g_test_add_func ("/utils/specialdir", test_special_dir); g_test_add_func ("/utils/specialdir/desktop", test_desktop_special_dir); + g_test_add_func ("/utils/os-info", test_os_info); g_test_add_func ("/utils/clear-pointer", test_clear_pointer); g_test_add_func ("/utils/clear-pointer-cast", test_clear_pointer_cast); g_test_add_func ("/utils/clear-pointer/side-effects", test_clear_pointer_side_effects);