From f8b8a2561f75c200cf950cf18ffbec3019fc2fe8 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Wed, 25 Sep 2019 20:29:46 +0100
Subject: [PATCH] runtime: Use os-release(5) to detect Steam Runtime
 container/chroot

Instead of inspecting the LD_LIBRARY_PATH runtime with
_srt_runtime_check(), we open-code a small partial reimplementation of
that function to inspect os-release(5) and provide information about
a Steam Runtime container.

Signed-off-by: Simon McVittie <smcv@collabora.com>
---
 steam-runtime-tools/system-info.c | 60 ++++++++++++++++++++++++-------
 tests/fake-home.c                 |  3 ++
 tests/system-info.c               | 40 +++++++++++++++++++++
 3 files changed, 91 insertions(+), 12 deletions(-)

diff --git a/steam-runtime-tools/system-info.c b/steam-runtime-tools/system-info.c
index 1bcc1149b..7aef99565 100644
--- a/steam-runtime-tools/system-info.c
+++ b/steam-runtime-tools/system-info.c
@@ -1477,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
@@ -1512,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.
@@ -1540,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/tests/fake-home.c b/tests/fake-home.c
index 80ef0811b..e58872129 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/system-info.c b/tests/system-info.c
index 04334ac0a..e74622c5e 100644
--- a/tests/system-info.c
+++ b/tests/system-info.c
@@ -1362,6 +1362,7 @@ os_steamrt (Fixture *f,
   gchar **strv;
   gchar *sysroot;
   gchar *s;
+  SrtRuntimeIssues runtime_issues;
 
   sysroot = g_build_filename (f->srcdir, "sysroots", "steamrt", NULL);
   envp = g_get_environ ();
@@ -1419,6 +1420,17 @@ os_steamrt (Fixture *f,
   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);
@@ -1433,6 +1445,7 @@ os_steamrt_unofficial (Fixture *f,
   gchar **strv;
   gchar *sysroot;
   gchar *s;
+  SrtRuntimeIssues runtime_issues;
 
   sysroot = g_build_filename (f->srcdir, "sysroots", "steamrt-unofficial", NULL);
   envp = g_get_environ ();
@@ -1491,6 +1504,19 @@ os_steamrt_unofficial (Fixture *f,
   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);
@@ -1505,6 +1531,7 @@ os_invalid_os_release (Fixture *f,
   gchar **strv;
   gchar *sysroot;
   gchar *s;
+  SrtRuntimeIssues runtime_issues;
 
   sysroot = g_build_filename (f->srcdir, "sysroots", "invalid-os-release", NULL);
   envp = g_get_environ ();
@@ -1557,6 +1584,19 @@ os_invalid_os_release (Fixture *f,
   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);
-- 
GitLab