diff --git a/steam-runtime-tools/system-info.c b/steam-runtime-tools/system-info.c index bf07f719dcc4bf15ea1dfa108ee656634825cbde..0b6179d1cee47b8d71c0c5e01977c7956611312c 100644 --- a/steam-runtime-tools/system-info.c +++ b/steam-runtime-tools/system-info.c @@ -75,7 +75,10 @@ struct _SrtSystemInfo { /*< private >*/ GObject parent; + /* "" if we have tried and failed to auto-detect */ gchar *expectations; + /* Fake environment variables, or %NULL to use the real environment */ + gchar **env; Tristate can_write_uinput; /* (element-type Abi) */ GPtrArray *abis; @@ -199,6 +202,7 @@ srt_system_info_finalize (GObject *object) g_clear_pointer (&self->abis, g_ptr_array_unref); g_free (self->expectations); + g_strfreev (self->env); G_OBJECT_CLASS (srt_system_info_parent_class)->finalize (object); } @@ -347,6 +351,43 @@ library_compare (SrtLibrary *a, SrtLibrary *b) return g_strcmp0 (srt_library_get_soname (a), srt_library_get_soname (b)); } +static gchar ** +get_environ (SrtSystemInfo *self) +{ + if (self->env != NULL) + return self->env; + else + return environ; +} + +static gboolean +ensure_expectations (SrtSystemInfo *self) +{ + if (self->expectations == NULL) + { + const char *runtime; + const char *sysroot = "/"; + gchar *def; + + runtime = g_environ_getenv (get_environ (self), "STEAM_RUNTIME"); + + if (runtime != NULL && runtime[0] == '/') + sysroot = runtime; + + def = g_build_filename (sysroot, "usr", "lib", "steamrt", + "expectations", NULL); + + if (g_file_test (def, G_FILE_TEST_IS_DIR)) + self->expectations = g_steal_pointer (&def); + else + self->expectations = g_strdup (""); + + g_free (def); + } + + return self->expectations[0] != '\0'; +} + /** * srt_system_info_check_libraries: * @self: The #SrtSystemInfo object to use. @@ -384,7 +425,7 @@ srt_system_info_check_libraries (SrtSystemInfo *self, g_return_val_if_fail (libraries_out == NULL || *libraries_out == NULL, SRT_LIBRARY_ISSUES_INTERNAL_ERROR); - if (self->expectations == NULL) + if (!ensure_expectations (self)) { /* We don't know which libraries to check. */ return SRT_LIBRARY_ISSUES_UNKNOWN_EXPECTATIONS; @@ -538,7 +579,7 @@ srt_system_info_check_library (SrtSystemInfo *self, return srt_library_get_issues (library); } - if (self->expectations != NULL) + if (ensure_expectations (self)) { dir_path = g_build_filename (self->expectations, multiarch_tuple, NULL); dir = g_dir_open (dir_path, 0, &error); @@ -628,3 +669,43 @@ srt_system_info_check_library (SrtSystemInfo *self, return ret; } + +/* + * Forget whether we can load libraries. + */ +static void +forget_libraries (SrtSystemInfo *self) +{ + gsize i; + + for (i = 0; i < self->abis->len; i++) + { + Abi *abi = g_ptr_array_index (self->abis, i); + + g_hash_table_remove_all (abi->cached_results); + abi->cached_combined_issues = SRT_LIBRARY_ISSUES_NONE; + abi->libraries_cache_available = FALSE; + } +} + +/** + * srt_system_info_set_environ: + * @self: The #SrtSystemInfo + * @env: (nullable) (array zero-terminated=1) (element-type filename) (transfer none): An + * array of environment variables + * + * Use @env instead of the real environment variable block `environ` + * when locating the Steam Runtime. + * + * If @env is %NULL, go back to using the real environment variables. + */ +void +srt_system_info_set_environ (SrtSystemInfo *self, + gchar * const *env) +{ + g_return_if_fail (SRT_IS_SYSTEM_INFO (self)); + + forget_libraries (self); + g_strfreev (self->env); + self->env = g_strdupv ((gchar **) env); +} diff --git a/steam-runtime-tools/system-info.h b/steam-runtime-tools/system-info.h index 6213b2d145bda9146f5867ce94e6721f57bbffd1..33b6132b3b25235e320bfd201b54b85dafd5bcdd 100644 --- a/steam-runtime-tools/system-info.h +++ b/steam-runtime-tools/system-info.h @@ -58,3 +58,6 @@ SrtLibraryIssues srt_system_info_check_library (SrtSystemInfo *self, const gchar *multiarch_tuple, const gchar *soname, SrtLibrary **more_details_out); + +void srt_system_info_set_environ (SrtSystemInfo *self, + gchar * const *env); diff --git a/tests/fake-steam-runtime/usr/lib/steamrt/expectations/i386-linux-gnu/libglib2.0-0.symbols b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/i386-linux-gnu/libglib2.0-0.symbols new file mode 100644 index 0000000000000000000000000000000000000000..17fc854ac6138920c30c24ddbc20ce719c88917f --- /dev/null +++ b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/i386-linux-gnu/libglib2.0-0.symbols @@ -0,0 +1,11 @@ +# Cut-down version of libglib2.0-0:amd64.symbols, to illustrate what we expect +# to find here +libgio-2.0.so.0 libglib2.0-0 #MINVER# +* Build-Depends-Package: libglib2.0-dev + g_action_activate@Base 2.28.0 + g_action_change_state@Base 2.30.0 +libglib-2.0.so.0 libglib2.0-0 #MINVER# +* Build-Depends-Package: libglib2.0-dev + g_access@Base 2.12.0 + g_allocator_free@Base 2.12.0 + g_allocator_new@Base 2.12.0 diff --git a/tests/fake-steam-runtime/usr/lib/steamrt/expectations/i386-linux-gnu/zlib1g.symbols b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/i386-linux-gnu/zlib1g.symbols new file mode 100644 index 0000000000000000000000000000000000000000..63be790e3612555c3aae70b905be7b349964ee34 --- /dev/null +++ b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/i386-linux-gnu/zlib1g.symbols @@ -0,0 +1,4 @@ +# Cut-down version of zlib1g:amd64.symbols, to illustrate what we expect +# to find here +libz.so.1 zlib1g #MINVER# + adler32@Base 1:1.1.4 diff --git a/tests/fake-steam-runtime/usr/lib/steamrt/expectations/x86_64-linux-gnu/libglib2.0-0.symbols b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/x86_64-linux-gnu/libglib2.0-0.symbols new file mode 100644 index 0000000000000000000000000000000000000000..17fc854ac6138920c30c24ddbc20ce719c88917f --- /dev/null +++ b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/x86_64-linux-gnu/libglib2.0-0.symbols @@ -0,0 +1,11 @@ +# Cut-down version of libglib2.0-0:amd64.symbols, to illustrate what we expect +# to find here +libgio-2.0.so.0 libglib2.0-0 #MINVER# +* Build-Depends-Package: libglib2.0-dev + g_action_activate@Base 2.28.0 + g_action_change_state@Base 2.30.0 +libglib-2.0.so.0 libglib2.0-0 #MINVER# +* Build-Depends-Package: libglib2.0-dev + g_access@Base 2.12.0 + g_allocator_free@Base 2.12.0 + g_allocator_new@Base 2.12.0 diff --git a/tests/fake-steam-runtime/usr/lib/steamrt/expectations/x86_64-linux-gnu/zlib1g.symbols b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/x86_64-linux-gnu/zlib1g.symbols new file mode 100644 index 0000000000000000000000000000000000000000..63be790e3612555c3aae70b905be7b349964ee34 --- /dev/null +++ b/tests/fake-steam-runtime/usr/lib/steamrt/expectations/x86_64-linux-gnu/zlib1g.symbols @@ -0,0 +1,4 @@ +# Cut-down version of zlib1g:amd64.symbols, to illustrate what we expect +# to find here +libz.so.1 zlib1g #MINVER# + adler32@Base 1:1.1.4 diff --git a/tests/meson.build b/tests/meson.build index de2c93df2b67e2029951d62e3cb5d9314750aea7..53a323a8aaf07477412fdbcad6ae68cad1947451 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -47,6 +47,7 @@ tests_metadir = join_paths( install_subdir('expectations', install_dir : tests_dir) install_subdir('expectations_with_missings', install_dir : tests_dir) +install_subdir('fake-steam-runtime', install_dir : tests_dir) foreach test_name : tests exe = executable( diff --git a/tests/system-info.c b/tests/system-info.c index 8edd66108331dca32c78c64596beb8cd71c1289c..afe4d58b1c1a9da6bc8c40b04630d6eb941dcda9 100644 --- a/tests/system-info.c +++ b/tests/system-info.c @@ -286,6 +286,44 @@ libraries_presence (Fixture *f, g_object_unref (info); } +/* + * Check that the expectations can be auto-detected from the + * `STEAM_RUNTIME` environment variable. + */ +static void +auto_expectations (Fixture *f, + gconstpointer context) +{ + SrtSystemInfo *info; + gchar *steam_runtime = NULL; + GList *libraries = NULL; + SrtLibraryIssues issues; + gchar **env; + + if (strcmp (_SRT_MULTIARCH, "") == 0) + { + g_test_skip ("Unsupported architecture"); + return; + } + + env = g_get_environ (); + steam_runtime = g_build_filename (f->srcdir, "fake-steam-runtime", NULL); + env = g_environ_setenv (env, "STEAM_RUNTIME", steam_runtime, TRUE); + + info = srt_system_info_new (NULL); + srt_system_info_set_environ (info, env); + issues = srt_system_info_check_libraries (info, + _SRT_MULTIARCH, + &libraries); + g_assert_cmpint (issues, ==, SRT_LIBRARY_ISSUES_NONE); + check_libraries_result (libraries); + g_list_free_full (libraries, g_object_unref); + + g_object_unref (info); + g_strfreev (env); + g_free (steam_runtime); +} + static void check_library_result (SrtLibrary *library) { @@ -623,9 +661,9 @@ wrong_expectations (Fixture *f, return; } - /* Set the expectations folder to NULL. - * We expect the library checks to fail. */ - info = srt_system_info_new (NULL); + /* Set the expectations folder to one that does not contain the + * necessary files. We expect the library checks to fail. */ + info = srt_system_info_new ("/dev"); issues = srt_system_info_check_libraries (info, _SRT_MULTIARCH, @@ -652,6 +690,8 @@ main (int argc, setup, test_object, teardown); g_test_add ("/system-info/libraries_presence", Fixture, NULL, setup, libraries_presence, teardown); + g_test_add ("/system-info/auto_expectations", Fixture, NULL, + setup, auto_expectations, teardown); g_test_add ("/system-info/library_presence", Fixture, NULL, setup, library_presence, teardown); g_test_add ("/system-info/libraries_missing", Fixture, NULL,