diff --git a/bin/system-info.c b/bin/system-info.c index 14284cc5469bd57f4e2b403c8bbd80f96db35143..264599791a0590b857135fe5bfde8b823ef4e602 100644 --- a/bin/system-info.c +++ b/bin/system-info.c @@ -543,6 +543,101 @@ main (int argc, json_builder_end_array (builder); json_builder_end_object (builder); + json_builder_set_member_name (builder, "os-release"); + json_builder_begin_object (builder); + { + GStrv strv; + gsize i; + gchar *tmp; + + tmp = srt_system_info_dup_os_id (info); + + if (tmp != NULL) + { + json_builder_set_member_name (builder, "id"); + json_builder_add_string_value (builder, tmp); + g_free (tmp); + } + + strv = srt_system_info_dup_os_id_like (info, FALSE); + + if (strv != NULL) + { + json_builder_set_member_name (builder, "id_like"); + json_builder_begin_array (builder); + { + for (i = 0; strv[i] != NULL; i++) + json_builder_add_string_value (builder, strv[i]); + } + json_builder_end_array (builder); + g_strfreev (strv); + } + + tmp = srt_system_info_dup_os_name (info); + + if (tmp != NULL) + { + json_builder_set_member_name (builder, "name"); + json_builder_add_string_value (builder, tmp); + g_free (tmp); + } + + tmp = srt_system_info_dup_os_pretty_name (info); + + if (tmp != NULL) + { + json_builder_set_member_name (builder, "pretty_name"); + json_builder_add_string_value (builder, tmp); + g_free (tmp); + } + + tmp = srt_system_info_dup_os_version_id (info); + + if (tmp != NULL) + { + json_builder_set_member_name (builder, "version_id"); + json_builder_add_string_value (builder, tmp); + g_free (tmp); + } + + tmp = srt_system_info_dup_os_version_codename (info); + + if (tmp != NULL) + { + json_builder_set_member_name (builder, "version_codename"); + json_builder_add_string_value (builder, tmp); + g_free (tmp); + } + + tmp = srt_system_info_dup_os_build_id (info); + + if (tmp != NULL) + { + json_builder_set_member_name (builder, "build_id"); + json_builder_add_string_value (builder, tmp); + g_free (tmp); + } + + tmp = srt_system_info_dup_os_variant_id (info); + + if (tmp != NULL) + { + json_builder_set_member_name (builder, "variant_id"); + json_builder_add_string_value (builder, tmp); + g_free (tmp); + } + + tmp = srt_system_info_dup_os_variant (info); + + if (tmp != NULL) + { + json_builder_set_member_name (builder, "variant"); + json_builder_add_string_value (builder, tmp); + g_free (tmp); + } + } + json_builder_end_object (builder); + json_builder_set_member_name (builder, "architectures"); json_builder_begin_object (builder); diff --git a/bin/system-info.md b/bin/system-info.md index be107bbb16f05630c3c743e48685094535302d94..114929ff7ae5ded8bb0b93d64ad9c73146b2cf49 100644 --- a/bin/system-info.md +++ b/bin/system-info.md @@ -138,6 +138,112 @@ keys: likely to break the use of libraries from the host system, in particular the Mesa graphics drivers. +**os-release** +: An object describing the operating system or container in which + **steam-runtime-system-info** was run. The keys and values are + strings, and any field that is not known is omitted. + + **id** + : A short lower-case string identifying the operating system, + for example **debian** or **arch**. In a Steam Runtime + chroot or container this will be **steamrt**. + + This is the **ID** from **os-release**(5). + If **os-release**(5) is not available, future versions of this + library might derive a similar ID from **lsb_release**(1). + + **id_like** + : An array of short lower-case strings identifying operating systems + that this one was derived from. For example, Steam Runtime 1 'scout' + is derived from Ubuntu, which is itself derived from Debian, so + in a scout chroot or container this will be **["ubuntu", "debian"]**. + + This is the **ID_LIKE** field from **os-release**(5), split + at whitespace. It does not include the **id**. + + If **os-release**(5) is not available, future versions of this + library might derive a similar array from **lsb_release**(1) + or from hard-coded knowledge of particular operating systems. + + **name** + : A human-readable name for the operating system without its + version, for example **Debian GNU/Linux** or **Arch Linux**. + + This is the **NAME** from **os-release**(5). + If **os-release**(5) is not available, future versions of this + library might derive a similar name from **lsb_release**(1). + + **pretty_name** + : A human-readable name for the operating system, including its + version if applicable, for example + **Debian GNU/Linux 10 (buster)** or **Arch Linux**. For rolling + releases like Debian testing/unstable and Arch Linux, this + might be the same as **name**. + + This is the **PRETTY_NAME** from **os-release**(5). + If **os-release**(5) is not available, future versions of this + library might derive a similar name from **lsb_release**(1). + + **version_id** + : A short machine-readable string identifying the operating system, + for example **10** for Debian 10 'buster'. In a + Steam Runtime 1 'scout' chroot or container this will be **1**. + In rolling releases like Debian testing/unstable and Arch Linux, + this is likely to be omitted. It is not guaranteed to be numeric. + + This is the **VERSION_ID** from **os-release**(5). + If **os-release**(5) is not available, future versions of this + library might derive a similar ID from **lsb_release**(1). + + **version_codename** + : A short string identifying the operating system release codename, + for example **buster** for Debian 10 'buster'. In a + Steam Runtime 1 'scout' chroot or container this will be **scout** + if present. + + In rolling releases like Debian testing/unstable and Arch Linux, + and in operating systems like Fedora that have codenames but do + not use them in a machine-readable context, this is likely to be + omitted. + + This is the **VERSION_CODENAME** from **os-release**(5). + If **os-release**(5) is not available, future versions of this + library might derive a similar ID from **lsb_release**(1). + + **build_id** + : A short machine-readable string identifying the image from which + the operating system was installed (depending on the operating + system, it might have been upgraded since then). In operating + systems with only non-image-based installation methods this will + usually be omitted. + + In a Steam Runtime 1 'scout' chroot or container, if present this + identifies the Steam Runtime build on which the chroot or container + is based, such as **0.20190926.0** for an official build or + **tools-test-0.20190926.0** for an unofficial build (but, again, it + might have been upgraded since then). + + This is the **BUILD_ID** from **os-release**(5). + + **variant_id** + : A short machine-readable string identifying the variant or edition + of the operating system, such as **workstation**. + + In a Steam Runtime 1 'scout' chroot or container built from a + Flatpak-style runtime, this will currently be something like + **com.valvesoftware.steamruntime.platform-amd64_i386-scout**. + + This is the **VARIANT_ID** from **os-release**(5). + + **variant** + : A human-readable string identifying the variant or edition + of the operating system, such as **Workstation Edition**. + + In a Steam Runtime 1 'scout' chroot or container built from a + Flatpak-style runtime, this will usually be **Platform** or **SDK**. + + This is the **VARIANT** from **os-release**(5). + **architectures** : An object with architecture-specific information. The keys are Debian-style *multiarch tuples* describing ABIs, as returned by diff --git a/steam-runtime-tools/graphics.c b/steam-runtime-tools/graphics.c index 3aeaa10054ec98dc53f05f363a78c63a854dd685..615744918f0c57151b8741a9f262ead338cfff8f 100644 --- a/steam-runtime-tools/graphics.c +++ b/steam-runtime-tools/graphics.c @@ -1706,7 +1706,7 @@ _srt_load_egl_icds (gchar **envp, * https://github.com/NVIDIA/libglvnd/blob/master/src/EGL/icd_enumeration.md * for details of the search order. */ - sysroot = g_environ_getenv (envp, "SRT_TEST_ICD_SYSROOT"); + sysroot = g_environ_getenv (envp, "SRT_TEST_SYSROOT"); value = g_environ_getenv (envp, "__EGL_VENDOR_LIBRARY_FILENAMES"); if (value != NULL) @@ -2282,7 +2282,7 @@ _srt_load_vulkan_icds (gchar **envp, * documentation is not completely up to date (as of September 2019) * so you should also look at the reference implementation. */ - sysroot = g_environ_getenv (envp, "SRT_TEST_ICD_SYSROOT"); + sysroot = g_environ_getenv (envp, "SRT_TEST_SYSROOT"); value = g_environ_getenv (envp, "VK_ICD_FILENAMES"); if (value != NULL) diff --git a/steam-runtime-tools/meson.build b/steam-runtime-tools/meson.build index 2bdea03919a5f5dbe6075597e06498e5d9cbf5be..1e6abaefc1496e0ebe72016a159a9aa33b5c1000 100644 --- a/steam-runtime-tools/meson.build +++ b/steam-runtime-tools/meson.build @@ -30,6 +30,8 @@ libsteamrt_sources = [ 'library.c', 'locale-internal.h', 'locale.c', + 'os-internal.h', + 'os.c', 'runtime-internal.h', 'runtime.c', 'steam-internal.h', diff --git a/steam-runtime-tools/os-internal.h b/steam-runtime-tools/os-internal.h new file mode 100644 index 0000000000000000000000000000000000000000..ed65cae0a056b07472c5e321c9d7e6ee1eb32a17 --- /dev/null +++ b/steam-runtime-tools/os-internal.h @@ -0,0 +1,49 @@ +/*<private_header>*/ +/* + * Copyright © 2019 Collabora Ltd. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include <glib.h> +#include <glib-object.h> + +typedef struct +{ + gchar *build_id; + gchar *id; + gchar *id_like; + gchar *name; + gchar *pretty_name; + gchar *variant; + gchar *variant_id; + gchar *version_codename; + gchar *version_id; + gboolean populated; +} SrtOsRelease; + +G_GNUC_INTERNAL void _srt_os_release_init (SrtOsRelease *self); +G_GNUC_INTERNAL void _srt_os_release_populate (SrtOsRelease *self, + gchar **envp); +G_GNUC_INTERNAL void _srt_os_release_clear (SrtOsRelease *self); diff --git a/steam-runtime-tools/os.c b/steam-runtime-tools/os.c new file mode 100644 index 0000000000000000000000000000000000000000..d5334e675147a7f8e0030157b53f7d087b515b31 --- /dev/null +++ b/steam-runtime-tools/os.c @@ -0,0 +1,238 @@ +/* + * Copyright © 2019 Collabora Ltd. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "steam-runtime-tools/os-internal.h" + +#include <string.h> + +#include "steam-runtime-tools/glib-compat.h" + +#include <glib.h> + +#include "steam-runtime-tools/utils.h" + +G_GNUC_INTERNAL void +_srt_os_release_init (SrtOsRelease *self) +{ + self->build_id = NULL; + self->id = NULL; + self->id_like = NULL; + self->name = NULL; + self->pretty_name = NULL; + self->variant = NULL; + self->variant_id = NULL; + self->version_codename = NULL; + self->version_id = NULL; + self->populated = FALSE; +} + +static const char * const os_release_paths[] = +{ + "/etc/os-release", + "/usr/lib/os-release" +}; + +static void +do_line (SrtOsRelease *self, + const char *path, + gchar *line) +{ + char *equals; + gchar *unquoted = NULL; + gchar **dest = NULL; + GError *local_error = NULL; + + /* Modify line in-place to strip leading and trailing whitespace */ + g_strstrip (line); + + if (line[0] == '\0' || line[0] == '#') + return; + + g_debug ("%s: %s", path, line); + + equals = strchr (line, '='); + + if (equals == NULL) + { + g_debug ("Unable to parse line \"%s\" in %s: no \"=\" found", + line, path); + return; + } + + unquoted = g_shell_unquote (equals + 1, &local_error); + + if (unquoted == NULL) + { + g_debug ("Unable to parse line \"%s\" in %s: %s", + line, path, local_error->message); + g_clear_error (&local_error); + return; + } + + *equals = '\0'; + + if (strcmp (line, "BUILD_ID") == 0) + dest = &self->build_id; + else if (strcmp (line, "ID") == 0) + dest = &self->id; + else if (strcmp (line, "ID_LIKE") == 0) + dest = &self->id_like; + else if (strcmp (line, "NAME") == 0) + dest = &self->name; + else if (strcmp (line, "PRETTY_NAME") == 0) + dest = &self->pretty_name; + else if (strcmp (line, "VARIANT") == 0) + dest = &self->variant; + else if (strcmp (line, "VARIANT_ID") == 0) + dest = &self->variant_id; + else if (strcmp (line, "VERSION_CODENAME") == 0) + dest = &self->version_codename; + else if (strcmp (line, "VERSION_ID") == 0) + dest = &self->version_id; + + if (dest != NULL) + { + if (*dest != NULL) + { + /* Using the last one matches the behaviour of a shell script + * that uses ". /usr/lib/os-release" */ + g_debug ("%s appears more than once in %s, will use last instance", + line, path); + g_free (*dest); + } + + *dest = unquoted; + } + else + { + g_free (unquoted); + } +} + +G_GNUC_INTERNAL void +_srt_os_release_populate (SrtOsRelease *self, + gchar **envp) +{ + const char *sysroot = NULL; + gsize i; + + g_return_if_fail (_srt_check_not_setuid ()); + g_return_if_fail (!self->populated); + g_return_if_fail (self->build_id == NULL); + g_return_if_fail (self->id == NULL); + g_return_if_fail (self->name == NULL); + g_return_if_fail (self->pretty_name == NULL); + g_return_if_fail (self->variant == NULL); + g_return_if_fail (self->variant_id == NULL); + g_return_if_fail (self->version_codename == NULL); + g_return_if_fail (self->version_id == NULL); + + if (envp != NULL) + sysroot = g_environ_getenv (envp, "SRT_TEST_SYSROOT"); + else + sysroot = g_getenv ("SRT_TEST_SYSROOT"); + + for (i = 0; i < G_N_ELEMENTS (os_release_paths); i++) + { + gchar *built_path = NULL; + gchar *contents = NULL; + const char *path = NULL; + char *beginning_of_line; + GError *local_error = NULL; + gsize len; + gsize j; + + if (sysroot != NULL) + { + built_path = g_build_filename (sysroot, os_release_paths[i], NULL); + path = built_path; + } + else + { + path = os_release_paths[i]; + } + + if (!g_file_get_contents (path, &contents, &len, &local_error)) + { + g_debug ("Unable to open %s: %s", path, local_error->message); + g_clear_error (&local_error); + g_free (built_path); + continue; + } + + beginning_of_line = contents; + + for (j = 0; j < len; j++) + { + if (contents[j] == '\n') + { + contents[j] = '\0'; + do_line (self, path, beginning_of_line); + /* g_file_get_contents adds an extra \0 at contents[len], + * so this is safe to do without overrunning the buffer */ + beginning_of_line = contents + j + 1; + } + } + + /* Collect a possible partial line */ + do_line (self, path, beginning_of_line); + + g_free (contents); + g_free (built_path); + break; + } + + /* Special case for the Steam Runtime: Flatpak-style scout images have + * historically not had a VERSION_CODENAME in os-release(5), but + * we know that version 1 is scout, so let's add it. */ + if (self->version_codename == NULL + && g_strcmp0 (self->id, "steamrt") == 0 + && g_strcmp0 (self->version_id, "1") == 0) + self->version_codename = g_strdup ("scout"); + + /* Special case for the Steam Runtime: we got this wrong in the past. */ + if (g_strcmp0 (self->id_like, "ubuntu") == 0) + { + g_free (self->id_like); + self->id_like = g_strdup ("ubuntu debian"); + } + + self->populated = TRUE; +} + +G_GNUC_INTERNAL void +_srt_os_release_clear (SrtOsRelease *self) +{ + g_clear_pointer (&self->build_id, g_free); + g_clear_pointer (&self->id, g_free); + g_clear_pointer (&self->id_like, g_free); + g_clear_pointer (&self->name, g_free); + g_clear_pointer (&self->pretty_name, g_free); + g_clear_pointer (&self->variant, g_free); + g_clear_pointer (&self->variant_id, g_free); + g_clear_pointer (&self->version_codename, g_free); + g_clear_pointer (&self->version_id, g_free); + self->populated = FALSE; +} diff --git a/steam-runtime-tools/system-info.c b/steam-runtime-tools/system-info.c index dd5f7060f0231c22299fdf6c281810e9fe8d3cc2..7aef99565fccd8647e4ecbe0c332e24abf00a08f 100644 --- a/steam-runtime-tools/system-info.c +++ b/steam-runtime-tools/system-info.c @@ -32,6 +32,7 @@ #include "steam-runtime-tools/graphics-internal.h" #include "steam-runtime-tools/library-internal.h" #include "steam-runtime-tools/locale-internal.h" +#include "steam-runtime-tools/os-internal.h" #include "steam-runtime-tools/runtime-internal.h" #include "steam-runtime-tools/steam-internal.h" #include "steam-runtime-tools/utils-internal.h" @@ -123,6 +124,7 @@ struct _SrtSystemInfo gboolean have_egl; gboolean have_vulkan; } icds; + SrtOsRelease os_release; SrtTestFlags test_flags; Tristate can_write_uinput; /* (element-type Abi) */ @@ -248,6 +250,8 @@ srt_system_info_init (SrtSystemInfo *self) /* Assume that in practice we will usually add two ABIs: amd64 and i386 */ self->abis = g_ptr_array_new_full (2, abi_free); + + _srt_os_release_init (&self->os_release); } static void @@ -313,6 +317,16 @@ forget_runtime (SrtSystemInfo *self) self->runtime.issues = SRT_RUNTIME_ISSUES_NONE; } +/* + * Forget any cached information about the OS. + */ +static void +forget_os (SrtSystemInfo *self) +{ + _srt_os_release_clear (&self->os_release); + forget_runtime (self); +} + /* * Forget any cached information about the Steam installation. */ @@ -347,6 +361,7 @@ srt_system_info_finalize (GObject *object) forget_icds (self); forget_locales (self); + forget_os (self); forget_runtime (self); forget_steam (self); @@ -1028,6 +1043,7 @@ srt_system_info_set_environ (SrtSystemInfo *self, forget_libraries (self); forget_graphics_results (self); forget_locales (self); + forget_os (self); g_strfreev (self->env); self->env = g_strdupv ((gchar **) env); @@ -1150,6 +1166,274 @@ srt_system_info_dup_steam_data_path (SrtSystemInfo *self) return g_strdup (self->steam.data_path); } +static void +ensure_os_cached (SrtSystemInfo *self) +{ + if (!self->os_release.populated) + _srt_os_release_populate (&self->os_release, self->env); +} + +/** + * srt_system_info_dup_os_build_id: + * @self: The #SrtSystemInfo object + * + * Return a machine-readable identifier for the system image used as the + * origin for a distribution, for example `0.20190925.0`. If called + * from inside a Steam Runtime container, return the Steam Runtime build + * ID, which currently looks like `0.20190925.0`. + * + * In operating systems that do not use image-based installation, such + * as Debian, this will be %NULL. + * + * This is the `BUILD_ID` from os-release(5). + * + * Returns: (transfer full) (type utf8): The build ID, or %NULL if not known. + * Free with g_free(). + */ +gchar * +srt_system_info_dup_os_build_id (SrtSystemInfo *self) +{ + g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL); + + ensure_os_cached (self); + return g_strdup (self->os_release.build_id); +} + +/** + * srt_system_info_dup_os_id: + * @self: The #SrtSystemInfo object + * + * Return a lower-case machine-readable operating system identifier, + * for example `debian` or `arch`. If called from inside a Steam Runtime + * container, return `steamrt`. + * + * This is the `ID` in os-release(5). If os-release(5) is not available, + * future versions of this library might derive a similar ID from + * lsb_release(1). + * + * Returns: (transfer full) (type utf8): The OS ID, or %NULL if not known. + * Free with g_free(). + */ +gchar * +srt_system_info_dup_os_id (SrtSystemInfo *self) +{ + g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL); + + ensure_os_cached (self); + return g_strdup (self->os_release.id); +} + +static const char WHITESPACE[] = " \t\n\r"; + +/** + * srt_system_info_dup_os_id_like: + * @self: The #SrtSystemInfo object + * @include_self: If %TRUE, include srt_system_info_dup_os_id() in the + * returned array (if known) + * + * Return an array of lower-case machine-readable operating system + * identifiers similar to srt_system_info_dup_os_id() describing OSs + * that this one resembles or is derived from. + * + * For example, the Steam Runtime 1 'scout' is derived from Ubuntu, + * which is itself derived from Debian, so srt_system_info_dup_os_id_like() + * would return `{ "debian", "ubuntu", NULL }` if @include_self is false, + * `{ "steamrt", "debian", "ubuntu", NULL }` otherwise. + * + * This is the `ID_LIKE` field from os-release(5), possibly combined + * with the `ID` field. + * + * Returns: (array zero-terminated=1) (transfer full) (element-type utf8) (nullable): An + * array of OS IDs, or %NULL if nothing is known. + * Free with g_strfreev(). + */ +gchar ** +srt_system_info_dup_os_id_like (SrtSystemInfo *self, + gboolean include_self) +{ + GPtrArray *builder; + g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL); + + ensure_os_cached (self); + + builder = g_ptr_array_new_with_free_func (g_free); + + if (self->os_release.id != NULL && include_self) + g_ptr_array_add (builder, g_strdup (self->os_release.id)); + + if (self->os_release.id_like != NULL) + { + GStrv split; + gsize i; + + split = g_strsplit_set (self->os_release.id_like, WHITESPACE, -1); + + for (i = 0; split != NULL && split[i] != NULL; i++) + g_ptr_array_add (builder, g_steal_pointer (&split[i])); + + /* We already transferred ownership of the contents */ + g_free (split); + } + + if (builder->len > 0) + { + g_ptr_array_add (builder, NULL); + return (gchar **) g_ptr_array_free (builder, FALSE); + } + else + { + g_ptr_array_free (builder, TRUE); + return NULL; + } +} + +/** + * srt_system_info_dup_os_name: + * @self: The #SrtSystemInfo object + * + * Return a human-readable identifier for the operating system without + * its version, for example `Debian GNU/Linux` or `Arch Linux`. + * + * This is the `NAME` in os-release(5). If os-release(5) is not + * available, future versions of this library might derive a similar + * name from lsb_release(1). + * + * Returns: (transfer full) (type utf8): The name, or %NULL if not known. + * Free with g_free(). + */ +gchar * +srt_system_info_dup_os_name (SrtSystemInfo *self) +{ + g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL); + + ensure_os_cached (self); + return g_strdup (self->os_release.name); +} + +/** + * srt_system_info_dup_os_pretty_name: + * @self: The #SrtSystemInfo object + * + * Return a human-readable identifier for the operating system, + * including its version if any, for example `Debian GNU/Linux 10 (buster)` + * or `Arch Linux`. + * + * If the OS uses rolling releases, this will probably be the same as + * or similar to srt_system_info_dup_os_name(). + * + * This is the `PRETTY_NAME` in os-release(5). If os-release(5) is not + * available, future versions of this library might derive a similar + * name from lsb_release(1). + * + * Returns: (transfer full) (type utf8): The name, or %NULL if not known. + * Free with g_free(). + */ +gchar * +srt_system_info_dup_os_pretty_name (SrtSystemInfo *self) +{ + g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL); + + ensure_os_cached (self); + return g_strdup (self->os_release.pretty_name); +} + +/** + * srt_system_info_dup_os_variant: + * @self: The #SrtSystemInfo object + * + * Return a human-readable identifier for the operating system variant, + * for example `Workstation Edition`, `Server Edition` or + * `Raspberry Pi Edition`. In operating systems that do not have + * formal variants this will usually be %NULL. + * + * This is the `VARIANT` in os-release(5). + * + * Returns: (transfer full) (type utf8): The name, or %NULL if not known. + * Free with g_free(). + */ +gchar * +srt_system_info_dup_os_variant (SrtSystemInfo *self) +{ + g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL); + + ensure_os_cached (self); + return g_strdup (self->os_release.variant); +} + +/** + * srt_system_info_dup_os_variant_id: + * @self: The #SrtSystemInfo object + * + * Return a lower-case machine-readable identifier for the operating system + * variant in a form suitable for use in filenames, for example + * `workstation`, `server` or `rpi`. In operating systems that do not + * have formal variants this will usually be %NULL. + * + * This is the `VARIANT_ID` in os-release(5). + * + * Returns: (transfer full) (type utf8): The variant ID, or %NULL if not known. + * Free with g_free(). + */ +gchar * +srt_system_info_dup_os_variant_id (SrtSystemInfo *self) +{ + g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL); + + ensure_os_cached (self); + return g_strdup (self->os_release.variant_id); +} + +/** + * srt_system_info_dup_os_version_codename: + * @self: The #SrtSystemInfo object + * + * Return a lower-case machine-readable identifier for the operating + * system version codename, for example `buster` for Debian 10 "buster". + * In operating systems that do not use codenames in machine-readable + * contexts, this will usually be %NULL. + * + * This is the `VERSION_CODENAME` in os-release(5). If os-release(5) is not + * available, future versions of this library might derive a similar + * codename from lsb_release(1). + * + * Returns: (transfer full) (type utf8): The codename, or %NULL if not known. + * Free with g_free(). + */ +gchar * +srt_system_info_dup_os_version_codename (SrtSystemInfo *self) +{ + g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL); + + ensure_os_cached (self); + return g_strdup (self->os_release.version_codename); +} + +/** + * srt_system_info_dup_os_version_id: + * @self: The #SrtSystemInfo object + * + * Return a machine-readable identifier for the operating system version, + * for example `10` for Debian 10 "buster". In operating systems that + * only have rolling releases, such as Arch Linux, or in OS branches + * that behave like rolling releases, such as Debian unstable, this + * will usually be %NULL. + * + * This is the `VERSION_ID` in os-release(5). If os-release(5) is not + * available, future versions of this library might derive a similar + * identifier from lsb_release(1). + * + * Returns: (transfer full) (type utf8): The ID, or %NULL if not known. + * Free with g_free(). + */ +gchar * +srt_system_info_dup_os_version_id (SrtSystemInfo *self) +{ + g_return_val_if_fail (SRT_IS_SYSTEM_INFO (self), NULL); + + ensure_os_cached (self); + return g_strdup (self->os_release.version_id); +} + /** * srt_system_info_set_expected_runtime_version: * @self: The #SrtSystemInfo object @@ -1193,23 +1477,54 @@ srt_system_info_dup_expected_runtime_version (SrtSystemInfo *self) static void ensure_runtime_cached (SrtSystemInfo *self) { + ensure_os_cached (self); ensure_steam_cached (self); if (self->runtime.issues == SRT_RUNTIME_ISSUES_NONE && self->runtime.path == NULL) - self->runtime.issues = _srt_runtime_check (self->steam.bin32, - self->runtime.expected_version, - self->env, - &self->runtime.version, - &self->runtime.path); + { + if (g_strcmp0 (self->os_release.id, "steamrt") == 0) + { + self->runtime.path = g_strdup ("/"); + self->runtime.version = g_strdup (self->os_release.build_id); + + if (self->runtime.expected_version != NULL + && g_strcmp0 (self->runtime.expected_version, self->runtime.version) != 0) + { + self->runtime.issues |= SRT_RUNTIME_ISSUES_UNEXPECTED_VERSION; + } + + if (self->runtime.version == NULL) + { + self->runtime.issues |= SRT_RUNTIME_ISSUES_NOT_RUNTIME; + } + else + { + const char *p; + + for (p = self->runtime.version; *p != '\0'; p++) + { + if (!g_ascii_isdigit (*p) && *p != '.') + self->runtime.issues |= SRT_RUNTIME_ISSUES_UNOFFICIAL; + } + } + } + else + { + self->runtime.issues = _srt_runtime_check (self->steam.bin32, + self->runtime.expected_version, + self->env, + &self->runtime.version, + &self->runtime.path); + } + } } /** * srt_system_info_get_runtime_issues: * @self: The #SrtSystemInfo object * - * Detect and return any problems encountered with the - * `LD_LIBRARY_PATH`-based Steam Runtime. + * Detect and return any problems encountered with the Steam Runtime. * * Returns: Any problems detected with the Steam Runtime, * or %SRT_RUNTIME_ISSUES_NONE if no problems were detected @@ -1228,9 +1543,13 @@ srt_system_info_get_runtime_issues (SrtSystemInfo *self) * srt_system_info_dup_runtime_path: * @self: The #SrtSystemInfo object * - * Return the absolute path to the `LD_LIBRARY_PATH`-based Steam Runtime - * in use (the directory containing `run.sh`, `version.txt` and - * similar files). + * Return the absolute path to the Steam Runtime in use. + * + * For the `LD_LIBRARY_PATH`-based Steam Runtime, this is the directory + * containing `run.sh`, `version.txt` and similar files. + * + * If running in a Steam Runtime container or chroot, this function + * returns `/` to indicate that the entire container is the Steam Runtime. * * This will typically be below * srt_system_info_dup_steam_installation_path(), unless overridden. @@ -1256,9 +1575,10 @@ srt_system_info_dup_runtime_path (SrtSystemInfo *self) * srt_system_info_dup_runtime_version: * @self: The #SrtSystemInfo object * - * Return the version number of the `LD_LIBRARY_PATH`-based Steam Runtime + * Return the version number of the Steam Runtime * in use, for example `0.20190711.3`, or %NULL if it could not be - * determined. + * determined. This could either be the `LD_LIBRARY_PATH`-based Steam + * Runtime, or a Steam Runtime container or chroot. * * If the Steam Runtime has been disabled or could not be found, or its * version number could not be read, then at least one flag will be set diff --git a/steam-runtime-tools/system-info.h b/steam-runtime-tools/system-info.h index b6f9e7d735422d325d8aac5a089cd654f9033b6c..4aabb3b7332dc2aeeac270d1c52f385ec2852cdf 100644 --- a/steam-runtime-tools/system-info.h +++ b/steam-runtime-tools/system-info.h @@ -118,6 +118,17 @@ SrtLocale *srt_system_info_check_locale (SrtSystemInfo *self, const char *requested_name, GError **error); +gchar *srt_system_info_dup_os_build_id (SrtSystemInfo *self); +gchar *srt_system_info_dup_os_id (SrtSystemInfo *self); +gchar **srt_system_info_dup_os_id_like (SrtSystemInfo *self, + gboolean include_self); +gchar *srt_system_info_dup_os_name (SrtSystemInfo *self); +gchar *srt_system_info_dup_os_pretty_name (SrtSystemInfo *self); +gchar *srt_system_info_dup_os_variant (SrtSystemInfo *self); +gchar *srt_system_info_dup_os_variant_id (SrtSystemInfo *self); +gchar *srt_system_info_dup_os_version_codename (SrtSystemInfo *self); +gchar *srt_system_info_dup_os_version_id (SrtSystemInfo *self); + #ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtSystemInfo, g_object_unref) #endif diff --git a/tests/fake-home.c b/tests/fake-home.c index 80ef0811bf2ff19e206d94eac3f152cc66c01abb..e5887212989de5757bd4a149e0fde579ad9f17fc 100644 --- a/tests/fake-home.c +++ b/tests/fake-home.c @@ -236,6 +236,9 @@ fake_home_create_structure (FakeHome *f) f->env = g_get_environ (); f->env = g_environ_setenv (f->env, "HOME", f->home, TRUE); f->env = g_environ_setenv (f->env, "XDG_DATA_HOME", local_share, TRUE); + /* Make sure we don't find /etc/os-release or /usr/lib/os-release + * if we happen to be in a Steam Runtime container */ + f->env = g_environ_setenv (f->env, "SRT_TEST_SYSROOT", f->home, TRUE); if (f->add_environments) { diff --git a/tests/graphics.c b/tests/graphics.c index 7199c5369049cb00ef4b8bd86a2a1a7c59c60c2d..f94020b9cf00e3e7943047dddc99164b1737fc4c 100644 --- a/tests/graphics.c +++ b/tests/graphics.c @@ -84,7 +84,7 @@ setup (Fixture *f, { tmp = g_build_filename (f->srcdir, "fake-icds", NULL); f->fake_icds_envp = g_environ_setenv (f->fake_icds_envp, - "SRT_TEST_ICD_SYSROOT", tmp, TRUE); + "SRT_TEST_SYSROOT", tmp, TRUE); g_free (tmp); } diff --git a/tests/meson.build b/tests/meson.build index f52bd91f45d3c6609b34a24951e5f820c1b0a67f..110f8687cf620085049bd65d7c0b1498fb27b5b3 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -60,6 +60,7 @@ install_subdir('expectations_with_missings', install_dir : tests_dir) # Vulkan *.json files. (The order of EGL *.json files is well-defined.) install_subdir('fake-icds', install_dir : tests_dir) install_subdir('fake-steam-runtime', install_dir : tests_dir) +install_subdir('sysroots', install_dir : tests_dir) executable( 'mock-true', diff --git a/tests/sysroots/debian-unstable/etc/os-release b/tests/sysroots/debian-unstable/etc/os-release new file mode 100644 index 0000000000000000000000000000000000000000..55f123897e199d8115372e4ff3bb6fb3b5643221 --- /dev/null +++ b/tests/sysroots/debian-unstable/etc/os-release @@ -0,0 +1,6 @@ +PRETTY_NAME="Debian GNU/Linux bullseye/sid" +NAME="Debian GNU/Linux" +ID=debian +HOME_URL="https://www.debian.org/" +SUPPORT_URL="https://www.debian.org/support" +BUG_REPORT_URL="https://bugs.debian.org/" diff --git a/tests/sysroots/debian10/usr/lib/os-release b/tests/sysroots/debian10/usr/lib/os-release new file mode 100644 index 0000000000000000000000000000000000000000..9b5419df8bfb3ee0266ea3f6b46b6d349c06ce97 --- /dev/null +++ b/tests/sysroots/debian10/usr/lib/os-release @@ -0,0 +1,9 @@ +PRETTY_NAME="Debian GNU/Linux 10 (buster)" +NAME="Debian GNU/Linux" +VERSION_ID="10" +VERSION="10 (buster)" +VERSION_CODENAME=buster +ID=debian +HOME_URL="https://www.debian.org/" +SUPPORT_URL="https://www.debian.org/support" +BUG_REPORT_URL="https://bugs.debian.org/" diff --git a/tests/sysroots/invalid-os-release/usr/lib/os-release b/tests/sysroots/invalid-os-release/usr/lib/os-release new file mode 100644 index 0000000000000000000000000000000000000000..c951a991f894bd325018b2ece0b997fffdb715df --- /dev/null +++ b/tests/sysroots/invalid-os-release/usr/lib/os-release @@ -0,0 +1,6 @@ +ID=steamrt +PRETTY_NAME="The first name" +VERSION_CODENAME +VERSION_ID="foo +PRETTY_NAME="The second name" +NAME="This file does not end with a newline" \ No newline at end of file diff --git a/tests/sysroots/no-os-release/.gitignore b/tests/sysroots/no-os-release/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/sysroots/steamrt-unofficial/etc/os-release b/tests/sysroots/steamrt-unofficial/etc/os-release new file mode 120000 index 0000000000000000000000000000000000000000..c4c75b419cfd1a831f48769e8b4ac8680f728654 --- /dev/null +++ b/tests/sysroots/steamrt-unofficial/etc/os-release @@ -0,0 +1 @@ +../usr/lib/os-release \ No newline at end of file diff --git a/tests/sysroots/steamrt-unofficial/usr/lib/os-release b/tests/sysroots/steamrt-unofficial/usr/lib/os-release new file mode 100644 index 0000000000000000000000000000000000000000..75e8b300d70fcd5b4a6b8a8906b0cd3fff79c783 --- /dev/null +++ b/tests/sysroots/steamrt-unofficial/usr/lib/os-release @@ -0,0 +1,9 @@ +NAME="Steam Runtime" +VERSION="1 (scout)" +ID=steamrt +ID_LIKE=ubuntu +PRETTY_NAME="Steam Runtime 1 (scout)" +VERSION_ID="1" +BUILD_ID="unofficial-0.20190924.0" +VARIANT=Platform +VARIANT_ID="com.valvesoftware.steamruntime.platform-amd64_i386-scout" diff --git a/tests/sysroots/steamrt/etc/os-release b/tests/sysroots/steamrt/etc/os-release new file mode 120000 index 0000000000000000000000000000000000000000..c4c75b419cfd1a831f48769e8b4ac8680f728654 --- /dev/null +++ b/tests/sysroots/steamrt/etc/os-release @@ -0,0 +1 @@ +../usr/lib/os-release \ No newline at end of file diff --git a/tests/sysroots/steamrt/usr/lib/os-release b/tests/sysroots/steamrt/usr/lib/os-release new file mode 100644 index 0000000000000000000000000000000000000000..064dec3e50ce858cccfac132e4b198ed87ef1bd4 --- /dev/null +++ b/tests/sysroots/steamrt/usr/lib/os-release @@ -0,0 +1,9 @@ +NAME="Steam Runtime" +VERSION="1 (scout)" +ID=steamrt +ID_LIKE=ubuntu +PRETTY_NAME="Steam Runtime 1 (scout)" +VERSION_ID="1" +BUILD_ID="0.20190924.0" +VARIANT=Platform +VARIANT_ID="com.valvesoftware.steamruntime.platform-amd64_i386-scout" diff --git a/tests/system-info.c b/tests/system-info.c index 34d842c91a8feb528e6a760662e9b2156223ce96..e74622c5e9a5db29f1c3899190ee420fb3785092 100644 --- a/tests/system-info.c +++ b/tests/system-info.c @@ -1225,6 +1225,445 @@ testing_beta_client (Fixture *f, g_free (data_path); } +static void +os_debian10 (Fixture *f, + gconstpointer context) +{ + SrtSystemInfo *info; + gchar **envp; + gchar **strv; + gchar *sysroot; + gchar *s; + + sysroot = g_build_filename (f->srcdir, "sysroots", "debian10", NULL); + envp = g_get_environ (); + envp = g_environ_setenv (envp, "SRT_TEST_SYSROOT", sysroot, TRUE); + + info = srt_system_info_new (NULL); + srt_system_info_set_environ (info, envp); + + s = srt_system_info_dup_os_build_id (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_id (info); + g_assert_cmpstr (s, ==, "debian"); + g_free (s); + + strv = srt_system_info_dup_os_id_like (info, FALSE); + g_assert_null (strv); + g_strfreev (strv); + + strv = srt_system_info_dup_os_id_like (info, TRUE); + g_assert_nonnull (strv); + g_assert_cmpstr (strv[0], ==, "debian"); + g_assert_cmpstr (strv[1], ==, NULL); + g_strfreev (strv); + + s = srt_system_info_dup_os_name (info); + g_assert_cmpstr (s, ==, "Debian GNU/Linux"); + g_free (s); + + s = srt_system_info_dup_os_pretty_name (info); + g_assert_cmpstr (s, ==, "Debian GNU/Linux 10 (buster)"); + g_free (s); + + s = srt_system_info_dup_os_variant (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_variant_id (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_version_codename (info); + g_assert_cmpstr (s, ==, "buster"); + g_free (s); + + s = srt_system_info_dup_os_version_id (info); + g_assert_cmpstr (s, ==, "10"); + g_free (s); + + g_object_unref (info); + g_free (sysroot); + g_strfreev (envp); +} + +static void +os_debian_unstable (Fixture *f, + gconstpointer context) +{ + SrtSystemInfo *info; + gchar **envp; + gchar **strv; + gchar *sysroot; + gchar *s; + + sysroot = g_build_filename (f->srcdir, "sysroots", "debian-unstable", NULL); + envp = g_get_environ (); + envp = g_environ_setenv (envp, "SRT_TEST_SYSROOT", sysroot, TRUE); + + info = srt_system_info_new (NULL); + srt_system_info_set_environ (info, envp); + + s = srt_system_info_dup_os_build_id (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_id (info); + g_assert_cmpstr (s, ==, "debian"); + g_free (s); + + strv = srt_system_info_dup_os_id_like (info, FALSE); + g_assert_null (strv); + g_strfreev (strv); + + strv = srt_system_info_dup_os_id_like (info, TRUE); + g_assert_nonnull (strv); + g_assert_cmpstr (strv[0], ==, "debian"); + g_assert_cmpstr (strv[1], ==, NULL); + g_strfreev (strv); + + s = srt_system_info_dup_os_name (info); + g_assert_cmpstr (s, ==, "Debian GNU/Linux"); + g_free (s); + + s = srt_system_info_dup_os_pretty_name (info); + g_assert_cmpstr (s, ==, "Debian GNU/Linux bullseye/sid"); + g_free (s); + + s = srt_system_info_dup_os_variant (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_variant_id (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_version_codename (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_version_id (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + g_object_unref (info); + g_free (sysroot); + g_strfreev (envp); +} + +static void +os_steamrt (Fixture *f, + gconstpointer context) +{ + SrtSystemInfo *info; + gchar **envp; + gchar **strv; + gchar *sysroot; + gchar *s; + SrtRuntimeIssues runtime_issues; + + sysroot = g_build_filename (f->srcdir, "sysroots", "steamrt", NULL); + envp = g_get_environ (); + envp = g_environ_setenv (envp, "SRT_TEST_SYSROOT", sysroot, TRUE); + envp = g_environ_unsetenv (envp, "STEAM_RUNTIME"); + + info = srt_system_info_new (NULL); + srt_system_info_set_environ (info, envp); + + s = srt_system_info_dup_os_build_id (info); + g_assert_cmpstr (s, ==, "0.20190924.0"); + g_free (s); + + s = srt_system_info_dup_os_id (info); + g_assert_cmpstr (s, ==, "steamrt"); + g_free (s); + + strv = srt_system_info_dup_os_id_like (info, FALSE); + g_assert_nonnull (strv); + g_assert_cmpstr (strv[0], ==, "ubuntu"); + g_assert_cmpstr (strv[1], ==, "debian"); + g_assert_cmpstr (strv[2], ==, NULL); + g_strfreev (strv); + + strv = srt_system_info_dup_os_id_like (info, TRUE); + g_assert_nonnull (strv); + g_assert_cmpstr (strv[0], ==, "steamrt"); + g_assert_cmpstr (strv[1], ==, "ubuntu"); + g_assert_cmpstr (strv[2], ==, "debian"); + g_assert_cmpstr (strv[3], ==, NULL); + g_strfreev (strv); + + s = srt_system_info_dup_os_name (info); + g_assert_cmpstr (s, ==, "Steam Runtime"); + g_free (s); + + s = srt_system_info_dup_os_pretty_name (info); + g_assert_cmpstr (s, ==, "Steam Runtime 1 (scout)"); + g_free (s); + + s = srt_system_info_dup_os_variant (info); + g_assert_cmpstr (s, ==, "Platform"); + g_free (s); + + s = srt_system_info_dup_os_variant_id (info); + g_assert_cmpstr (s, ==, "com.valvesoftware.steamruntime.platform-amd64_i386-scout"); + g_free (s); + + s = srt_system_info_dup_os_version_codename (info); + /* It isn't in os-release(5), but we infer it from the ID and VERSION_ID */ + g_assert_cmpstr (s, ==, "scout"); + g_free (s); + + s = srt_system_info_dup_os_version_id (info); + g_assert_cmpstr (s, ==, "1"); + g_free (s); + + runtime_issues = srt_system_info_get_runtime_issues (info); + g_assert_cmpint (runtime_issues, ==, SRT_RUNTIME_ISSUES_NONE); + + s = srt_system_info_dup_runtime_path (info); + g_assert_cmpstr (s, ==, "/"); + g_free (s); + + s = srt_system_info_dup_runtime_version (info); + g_assert_cmpstr (s, ==, "0.20190924.0"); + g_free (s); + + g_object_unref (info); + g_free (sysroot); + g_strfreev (envp); +} + +static void +os_steamrt_unofficial (Fixture *f, + gconstpointer context) +{ + SrtSystemInfo *info; + gchar **envp; + gchar **strv; + gchar *sysroot; + gchar *s; + SrtRuntimeIssues runtime_issues; + + sysroot = g_build_filename (f->srcdir, "sysroots", "steamrt-unofficial", NULL); + envp = g_get_environ (); + envp = g_environ_setenv (envp, "SRT_TEST_SYSROOT", sysroot, TRUE); + envp = g_environ_unsetenv (envp, "STEAM_RUNTIME"); + + info = srt_system_info_new (NULL); + srt_system_info_set_environ (info, envp); + srt_system_info_set_expected_runtime_version (info, "0.20190711.3"); + + s = srt_system_info_dup_os_build_id (info); + g_assert_cmpstr (s, ==, "unofficial-0.20190924.0"); + g_free (s); + + s = srt_system_info_dup_os_id (info); + g_assert_cmpstr (s, ==, "steamrt"); + g_free (s); + + strv = srt_system_info_dup_os_id_like (info, FALSE); + g_assert_nonnull (strv); + g_assert_cmpstr (strv[0], ==, "ubuntu"); + g_assert_cmpstr (strv[1], ==, "debian"); + g_assert_cmpstr (strv[2], ==, NULL); + g_strfreev (strv); + + strv = srt_system_info_dup_os_id_like (info, TRUE); + g_assert_nonnull (strv); + g_assert_cmpstr (strv[0], ==, "steamrt"); + g_assert_cmpstr (strv[1], ==, "ubuntu"); + g_assert_cmpstr (strv[2], ==, "debian"); + g_assert_cmpstr (strv[3], ==, NULL); + g_strfreev (strv); + + s = srt_system_info_dup_os_name (info); + g_assert_cmpstr (s, ==, "Steam Runtime"); + g_free (s); + + s = srt_system_info_dup_os_pretty_name (info); + g_assert_cmpstr (s, ==, "Steam Runtime 1 (scout)"); + g_free (s); + + s = srt_system_info_dup_os_variant (info); + g_assert_cmpstr (s, ==, "Platform"); + g_free (s); + + s = srt_system_info_dup_os_variant_id (info); + g_assert_cmpstr (s, ==, "com.valvesoftware.steamruntime.platform-amd64_i386-scout"); + g_free (s); + + s = srt_system_info_dup_os_version_codename (info); + /* It isn't in os-release(5), but we infer it from the ID and VERSION_ID */ + g_assert_cmpstr (s, ==, "scout"); + g_free (s); + + s = srt_system_info_dup_os_version_id (info); + g_assert_cmpstr (s, ==, "1"); + g_free (s); + + runtime_issues = srt_system_info_get_runtime_issues (info); + g_assert_cmpint (runtime_issues, ==, + (SRT_RUNTIME_ISSUES_UNOFFICIAL + | SRT_RUNTIME_ISSUES_UNEXPECTED_VERSION)); + + s = srt_system_info_dup_runtime_path (info); + g_assert_cmpstr (s, ==, "/"); + g_free (s); + + s = srt_system_info_dup_runtime_version (info); + g_assert_cmpstr (s, ==, "unofficial-0.20190924.0"); + g_free (s); + + g_object_unref (info); + g_free (sysroot); + g_strfreev (envp); +} + +static void +os_invalid_os_release (Fixture *f, + gconstpointer context) +{ + SrtSystemInfo *info; + gchar **envp; + gchar **strv; + gchar *sysroot; + gchar *s; + SrtRuntimeIssues runtime_issues; + + sysroot = g_build_filename (f->srcdir, "sysroots", "invalid-os-release", NULL); + envp = g_get_environ (); + envp = g_environ_setenv (envp, "SRT_TEST_SYSROOT", sysroot, TRUE); + envp = g_environ_unsetenv (envp, "STEAM_RUNTIME"); + + info = srt_system_info_new (NULL); + srt_system_info_set_environ (info, envp); + srt_system_info_set_expected_runtime_version (info, "0.20190711.3"); + + s = srt_system_info_dup_os_build_id (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_id (info); + g_assert_cmpstr (s, ==, "steamrt"); + g_free (s); + + strv = srt_system_info_dup_os_id_like (info, FALSE); + g_assert_null (strv); + g_strfreev (strv); + + strv = srt_system_info_dup_os_id_like (info, TRUE); + g_assert_nonnull (strv); + g_assert_cmpstr (strv[0], ==, "steamrt"); + g_assert_cmpstr (strv[1], ==, NULL); + g_strfreev (strv); + + s = srt_system_info_dup_os_name (info); + g_assert_cmpstr (s, ==, "This file does not end with a newline"); + g_free (s); + + s = srt_system_info_dup_os_pretty_name (info); + g_assert_cmpstr (s, ==, "The second name"); + g_free (s); + + s = srt_system_info_dup_os_variant (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_variant_id (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_version_codename (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_version_id (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + runtime_issues = srt_system_info_get_runtime_issues (info); + g_assert_cmpint (runtime_issues, ==, + (SRT_RUNTIME_ISSUES_UNEXPECTED_VERSION + | SRT_RUNTIME_ISSUES_NOT_RUNTIME)); + + s = srt_system_info_dup_runtime_path (info); + g_assert_cmpstr (s, ==, "/"); + g_free (s); + + s = srt_system_info_dup_runtime_version (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + g_object_unref (info); + g_free (sysroot); + g_strfreev (envp); +} + +static void +os_no_os_release (Fixture *f, + gconstpointer context) +{ + SrtSystemInfo *info; + gchar **envp; + gchar **strv; + gchar *sysroot; + gchar *s; + + sysroot = g_build_filename (f->srcdir, "sysroots", "no-os-release", NULL); + envp = g_get_environ (); + envp = g_environ_setenv (envp, "SRT_TEST_SYSROOT", sysroot, TRUE); + + info = srt_system_info_new (NULL); + srt_system_info_set_environ (info, envp); + + s = srt_system_info_dup_os_build_id (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_id (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + strv = srt_system_info_dup_os_id_like (info, FALSE); + g_assert_null (strv); + g_strfreev (strv); + + strv = srt_system_info_dup_os_id_like (info, TRUE); + g_assert_null (strv); + g_strfreev (strv); + + s = srt_system_info_dup_os_name (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_pretty_name (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_variant (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_variant_id (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_version_codename (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + s = srt_system_info_dup_os_version_id (info); + g_assert_cmpstr (s, ==, NULL); + g_free (s); + + g_object_unref (info); + g_free (sysroot); + g_strfreev (envp); +} + int main (int argc, char **argv) @@ -1266,5 +1705,18 @@ main (int argc, g_test_add ("/system-info/testing_beta_client", Fixture, NULL, setup, testing_beta_client, teardown); + g_test_add ("/system-info/os/debian10", Fixture, NULL, + setup, os_debian10, teardown); + g_test_add ("/system-info/os/debian-unstable", Fixture, NULL, + setup, os_debian_unstable, teardown); + g_test_add ("/system-info/os/steamrt", Fixture, NULL, + setup, os_steamrt, teardown); + g_test_add ("/system-info/os/steamrt-unofficial", Fixture, NULL, + setup, os_steamrt_unofficial, teardown); + g_test_add ("/system-info/os/invalid-os-release", Fixture, NULL, + setup, os_invalid_os_release, teardown); + g_test_add ("/system-info/os/no-os-release", Fixture, NULL, + setup, os_no_os_release, teardown); + return g_test_run (); }