1
0
Fork 0
gnome-software/lib/gs-os-release.c
Daniel Baumann 68ee05b3fd
Adding upstream version 48.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 21:00:23 +02:00

408 lines
9.3 KiB
C

/* -*- 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-or-later
*/
/**
* 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;
gchar *logo;
gchar *vendor_name;
};
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 void
gs_os_release_set_string_nonempty (gchar **inout_string,
const gchar *value)
{
if (*inout_string == value)
return;
g_clear_pointer (inout_string, g_free);
if (value != NULL && *value != '\0')
*inout_string = g_strdup (value);
}
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) {
gs_os_release_set_string_nonempty (&os_release->name, tmp);
continue;
}
if (g_strcmp0 (lines[i], "VERSION") == 0) {
gs_os_release_set_string_nonempty (&os_release->version, tmp);
continue;
}
if (g_strcmp0 (lines[i], "ID") == 0) {
gs_os_release_set_string_nonempty (&os_release->id, tmp);
continue;
}
if (g_strcmp0 (lines[i], "ID_LIKE") == 0) {
if (os_release->id_like != NULL)
g_strfreev (os_release->id_like);
os_release->id_like = g_strsplit (tmp, " ", 0);
continue;
}
if (g_strcmp0 (lines[i], "VERSION_ID") == 0) {
gs_os_release_set_string_nonempty (&os_release->version_id, tmp);
continue;
}
if (g_strcmp0 (lines[i], "PRETTY_NAME") == 0) {
gs_os_release_set_string_nonempty (&os_release->pretty_name, tmp);
continue;
}
if (g_strcmp0 (lines[i], "CPE_NAME") == 0) {
gs_os_release_set_string_nonempty (&os_release->cpe_name, tmp);
continue;
}
if (g_strcmp0 (lines[i], "UBUNTU_CODENAME") == 0) {
gs_os_release_set_string_nonempty (&os_release->distro_codename, tmp);
continue;
}
if (g_strcmp0 (lines[i], "HOME_URL") == 0) {
gs_os_release_set_string_nonempty (&os_release->home_url, tmp);
continue;
}
if (g_strcmp0 (lines[i], "LOGO") == 0) {
gs_os_release_set_string_nonempty (&os_release->logo, tmp);
continue;
}
if (g_strcmp0 (lines[i], "VENDOR_NAME") == 0) {
gs_os_release_set_string_nonempty (&os_release->vendor_name, 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;
}
/**
* gs_os_release_get_logo:
* @os_release: A #GsOsRelease
*
* Gets the logo icon name from the os-release parser.
*
* Returns: a string, or %NULL
*
* Since: 44
**/
const gchar *
gs_os_release_get_logo (GsOsRelease *os_release)
{
g_return_val_if_fail (GS_IS_OS_RELEASE (os_release), NULL);
return os_release->logo;
}
/**
* gs_os_release_get_vendor_name:
* @os_release: A #GsOsRelease
*
* Gets the vendor name from the os-release parser.
*
* Returns: (nullable): a string, or %NULL
*
* Since: 47
**/
const gchar *
gs_os_release_get_vendor_name (GsOsRelease *os_release)
{
g_return_val_if_fail (GS_IS_OS_RELEASE (os_release), NULL);
return os_release->vendor_name;
}
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_free (os_release->logo);
g_free (os_release->vendor_name);
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;
}
}