diff options
Diffstat (limited to '')
-rw-r--r-- | lib/gs-os-release.c | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/lib/gs-os-release.c b/lib/gs-os-release.c new file mode 100644 index 0000000..191a385 --- /dev/null +++ b/lib/gs-os-release.c @@ -0,0 +1,347 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * vi:set noexpandtab tabstop=8 shiftwidth=8: + * + * Copyright (C) 2016 Kalev Lember <klember@redhat.com> + * Copyright (C) 2016 Richard Hughes <richard@hughsie.com> + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +/** + * SECTION:gs-os-release + * @title: GsOsRelease + * @include: gnome-software.h + * @stability: Unstable + * @short_description: Data from os-release + * + * This object allows plugins to parse /etc/os-release for distribution + * metadata information. + */ + +#include "config.h" + +#include <glib.h> + +#include "gs-os-release.h" + +struct _GsOsRelease +{ + GObject parent_instance; + gchar *name; + gchar *version; + gchar *id; + gchar **id_like; + gchar *version_id; + gchar *pretty_name; + gchar *cpe_name; + gchar *distro_codename; + gchar *home_url; +}; + +static void gs_os_release_initable_iface_init (GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (GsOsRelease, gs_os_release, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE, gs_os_release_initable_iface_init)) + +static gboolean +gs_os_release_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + GsOsRelease *os_release = GS_OS_RELEASE (initable); + const gchar *filename; + g_autofree gchar *data = NULL; + g_auto(GStrv) lines = NULL; + guint i; + + g_return_val_if_fail (GS_IS_OS_RELEASE (os_release), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* get contents */ + filename = g_getenv ("GS_SELF_TEST_OS_RELEASE_FILENAME"); + if (filename == NULL) { + filename = "/etc/os-release"; + if (!g_file_test (filename, G_FILE_TEST_EXISTS)) + filename = "/usr/lib/os-release"; + } + if (!g_file_get_contents (filename, &data, NULL, error)) + return FALSE; + + /* parse */ + lines = g_strsplit (data, "\n", -1); + for (i = 0; lines[i] != NULL; i++) { + gchar *tmp; + + /* split the line up into two halves */ + tmp = g_strstr_len (lines[i], -1, "="); + if (tmp == NULL) + continue; + *tmp = '\0'; + tmp++; + + /* ignore trailing quote */ + if (tmp[0] == '\"') + tmp++; + + /* ignore trailing quote */ + g_strdelimit (tmp, "\"", '\0'); + + /* match fields we're interested in */ + if (g_strcmp0 (lines[i], "NAME") == 0) { + os_release->name = g_strdup (tmp); + continue; + } + if (g_strcmp0 (lines[i], "VERSION") == 0) { + os_release->version = g_strdup (tmp); + continue; + } + if (g_strcmp0 (lines[i], "ID") == 0) { + os_release->id = g_strdup (tmp); + continue; + } + if (g_strcmp0 (lines[i], "ID_LIKE") == 0) { + os_release->id_like = g_strsplit (tmp, " ", 0); + continue; + } + if (g_strcmp0 (lines[i], "VERSION_ID") == 0) { + os_release->version_id = g_strdup (tmp); + continue; + } + if (g_strcmp0 (lines[i], "PRETTY_NAME") == 0) { + os_release->pretty_name = g_strdup (tmp); + continue; + } + if (g_strcmp0 (lines[i], "CPE_NAME") == 0) { + os_release->cpe_name = g_strdup (tmp); + continue; + } + if (g_strcmp0 (lines[i], "UBUNTU_CODENAME") == 0) { + os_release->distro_codename = g_strdup (tmp); + continue; + } + if (g_strcmp0 (lines[i], "HOME_URL") == 0) { + os_release->home_url = g_strdup (tmp); + continue; + } + } + return TRUE; +} + +/** + * gs_os_release_get_name: + * @os_release: A #GsOsRelease + * + * Gets the name from the os-release parser. + * + * Returns: a string, or %NULL + * + * Since: 3.22 + **/ +const gchar * +gs_os_release_get_name (GsOsRelease *os_release) +{ + g_return_val_if_fail (GS_IS_OS_RELEASE (os_release), NULL); + return os_release->name; +} + +/** + * gs_os_release_get_version: + * @os_release: A #GsOsRelease + * + * Gets the version from the os-release parser. + * + * Returns: a string, or %NULL + * + * Since: 3.22 + **/ +const gchar * +gs_os_release_get_version (GsOsRelease *os_release) +{ + g_return_val_if_fail (GS_IS_OS_RELEASE (os_release), NULL); + return os_release->version; +} + +/** + * gs_os_release_get_id: + * @os_release: A #GsOsRelease + * + * Gets the ID from the os-release parser. + * + * Returns: a string, or %NULL + * + * Since: 3.22 + **/ +const gchar * +gs_os_release_get_id (GsOsRelease *os_release) +{ + g_return_val_if_fail (GS_IS_OS_RELEASE (os_release), NULL); + return os_release->id; +} + +/** + * gs_os_release_get_id_like: + * @os_release: A #GsOsRelease + * + * Gets the ID_LIKE from the os-release parser. This is a list of operating + * systems that are "closely related" to the local operating system, possibly + * by being a derivative distribution. + * + * Returns: a %NULL terminated list + * + * Since: 3.26.2 + **/ +const gchar * const * +gs_os_release_get_id_like (GsOsRelease *os_release) +{ + g_return_val_if_fail (GS_IS_OS_RELEASE (os_release), NULL); + return (const gchar * const *) os_release->id_like; +} + +/** + * gs_os_release_get_version_id: + * @os_release: A #GsOsRelease + * + * Gets the version ID from the os-release parser. + * + * Returns: a string, or %NULL + * + * Since: 3.22 + **/ +const gchar * +gs_os_release_get_version_id (GsOsRelease *os_release) +{ + g_return_val_if_fail (GS_IS_OS_RELEASE (os_release), NULL); + return os_release->version_id; +} + +/** + * gs_os_release_get_pretty_name: + * @os_release: A #GsOsRelease + * + * Gets the pretty name from the os-release parser. + * + * Returns: a string, or %NULL + * + * Since: 3.22 + **/ +const gchar * +gs_os_release_get_pretty_name (GsOsRelease *os_release) +{ + g_return_val_if_fail (GS_IS_OS_RELEASE (os_release), NULL); + return os_release->pretty_name; +} + +/** + * gs_os_release_get_cpe_name: + * @os_release: A #GsOsRelease + * + * Gets the pretty name from the os-release parser. + * + * Returns: a string, or %NULL + * + * Since: 3.22 + **/ +const gchar * +gs_os_release_get_cpe_name (GsOsRelease *os_release) +{ + g_return_val_if_fail (GS_IS_OS_RELEASE (os_release), NULL); + return os_release->cpe_name; +} + +/** + * gs_os_release_get_distro_codename: + * @os_release: A #GsOsRelease + * + * Gets the distro codename from the os-release parser. + * + * Returns: a string, or %NULL + * + * Since: 3.22 + **/ +const gchar * +gs_os_release_get_distro_codename (GsOsRelease *os_release) +{ + g_return_val_if_fail (GS_IS_OS_RELEASE (os_release), NULL); + return os_release->distro_codename; +} + +/** + * gs_os_release_get_home_url: + * @os_release: A #GsOsRelease + * + * Gets the home URL from the os-release parser. + * + * Returns: a string, or %NULL + * + * Since: 3.22 + **/ +const gchar * +gs_os_release_get_home_url (GsOsRelease *os_release) +{ + g_return_val_if_fail (GS_IS_OS_RELEASE (os_release), NULL); + return os_release->home_url; +} + +static void +gs_os_release_finalize (GObject *object) +{ + GsOsRelease *os_release = GS_OS_RELEASE (object); + g_free (os_release->name); + g_free (os_release->version); + g_free (os_release->id); + g_strfreev (os_release->id_like); + g_free (os_release->version_id); + g_free (os_release->pretty_name); + g_free (os_release->cpe_name); + g_free (os_release->distro_codename); + g_free (os_release->home_url); + G_OBJECT_CLASS (gs_os_release_parent_class)->finalize (object); +} + +static void +gs_os_release_class_init (GsOsReleaseClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->finalize = gs_os_release_finalize; +} + +static void +gs_os_release_initable_iface_init (GInitableIface *iface) +{ + iface->init = gs_os_release_initable_init; +} + +static void +gs_os_release_init (GsOsRelease *os_release) +{ +} + +/** + * gs_os_release_new: + * @error: a #GError, or %NULL + * + * Returns a new reference to a #GsOsRelease. The information may be cached. + * + * Returns: (transfer full): A new reference to a #GsOsRelease, or %NULL for error + * + * Since: 3.22 + **/ +GsOsRelease * +gs_os_release_new (GError **error) +{ + static gsize initialised = 0; + static GsOsRelease *os_release = NULL; + static GError *os_release_error = NULL; + + if (g_once_init_enter (&initialised)) { + os_release = g_initable_new (GS_TYPE_OS_RELEASE, NULL, &os_release_error, NULL); + g_once_init_leave (&initialised, 1); + } + + if (os_release != NULL) { + return g_object_ref (os_release); + } else { + g_propagate_error (error, g_error_copy (os_release_error)); + return NULL; + } +} |