diff --git a/pressure-vessel/launch.c b/pressure-vessel/launch.c index d0c337995b97b5e26ad1bcd9001a88e61a9082df..7a4f72b72cd96a98a0e2b574c239a47194cc930b 100644 --- a/pressure-vessel/launch.c +++ b/pressure-vessel/launch.c @@ -512,7 +512,7 @@ path_to_handle (GUnixFDList *fd_list, real = realpath (path, NULL); if (real != NULL) - after = pv_get_path_after (real, home_realpath); + after = _srt_get_path_after (real, home_realpath); if (after != NULL) { diff --git a/pressure-vessel/utils.c b/pressure-vessel/utils.c index ae76f8ff153bfb849b27a911269d16237c9a3585..322ca0ff62632909dece050f3323f2a4225455f9 100644 --- a/pressure-vessel/utils.c +++ b/pressure-vessel/utils.c @@ -743,50 +743,6 @@ pv_terminate_all_child_processes (GTimeSpan wait_period, return TRUE; } -/* - * @str: A path - * @prefix: A possible prefix - * - * The same as flatpak_has_path_prefix(), but instead of a boolean, - * return the part of @str after @prefix (non-%NULL but possibly empty) - * if @str has prefix @prefix, or %NULL if it does not. - * - * Returns: (nullable) (transfer none): the part of @str after @prefix, - * or %NULL if @str is not below @prefix - */ -const char * -pv_get_path_after (const char *str, - const char *prefix) -{ - while (TRUE) - { - /* Skip consecutive slashes to reach next path - element */ - while (*str == '/') - str++; - while (*prefix == '/') - prefix++; - - /* No more prefix path elements? Done! */ - if (*prefix == 0) - return str; - - /* Compare path element */ - while (*prefix != 0 && *prefix != '/') - { - if (*str != *prefix) - return NULL; - str++; - prefix++; - } - - /* Matched prefix path element, - must be entire str path element */ - if (*str != '/' && *str != 0) - return NULL; - } -} - /** * pv_current_namespace_path_to_host_path: * @current_env_path: a path in the current environment @@ -814,7 +770,7 @@ pv_current_namespace_path_to_host_path (const gchar *current_env_path) home = g_get_home_dir (); if (home != NULL) - after = pv_get_path_after (current_env_path, home); + after = _srt_get_path_after (current_env_path, home); /* If we are inside a Flatpak container, usually, the home * folder is '${HOME}/.var/app/${FLATPAK_ID}' on the host system */ @@ -844,7 +800,7 @@ pv_current_namespace_path_to_host_path (const gchar *current_env_path) } } - after = pv_get_path_after (current_env_path, "/run/host"); + after = _srt_get_path_after (current_env_path, "/run/host"); /* In a Flatpak container, usually, '/run/host' is the root of the * host system */ diff --git a/pressure-vessel/utils.h b/pressure-vessel/utils.h index a2d11fb230424fbb37f47d3acc3c86ccc6f3ece8..97e1a0a8d3faafa034df6ee0d625af869f5b8875 100644 --- a/pressure-vessel/utils.h +++ b/pressure-vessel/utils.h @@ -76,9 +76,6 @@ gboolean pv_terminate_all_child_processes (GTimeSpan wait_period, gchar *pv_current_namespace_path_to_host_path (const gchar *current_env_path); -const char *pv_get_path_after (const char *str, - const char *prefix); - void pv_set_up_logging (gboolean opt_verbose); void pv_delete_dangling_symlink (int dirfd, diff --git a/steam-runtime-tools/system-info.c b/steam-runtime-tools/system-info.c index 0c85ebb9daa3725678d9e2ade825a42445a08f51..3074de02366f6239d1915cf43ff0b876feb364a3 100644 --- a/steam-runtime-tools/system-info.c +++ b/steam-runtime-tools/system-info.c @@ -1234,12 +1234,7 @@ ensure_overrides_cached (SrtSystemInfo *self) "overrides/", "usr/lib/pressure-vessel/overrides/", }; - g_autoptr(GError) error = NULL; - g_autofree gchar *output = NULL; - g_autofree gchar *messages = NULL; g_autofree gchar *runtime = NULL; - const gchar *argv[] = {"find", NULL, "-ls", NULL}; - int exit_status = -1; gsize i; self->overrides.have_data = TRUE; @@ -1255,46 +1250,14 @@ ensure_overrides_cached (SrtSystemInfo *self) if (_srt_file_test_in_sysroot (self->sysroot, self->sysroot_fd, paths[i], G_FILE_TEST_EXISTS)) { - argv[1] = paths[i]; + self->overrides.values = _srt_recursive_list_content (self->sysroot, + self->sysroot_fd, + paths[i], + self->env, + &self->overrides.messages); break; } } - - if (argv[1] == NULL) - return; - - if (!g_spawn_sync (self->sysroot, /* working directory */ - (gchar **) argv, - self->env, - G_SPAWN_SEARCH_PATH, - _srt_child_setup_unblock_signals, - NULL, /* user data */ - &output, /* stdout */ - &messages, /* stderr */ - &exit_status, - &error)) - { - g_debug ("An error occurred calling the \"find\" binary: %s", error->message); - self->overrides.messages = g_new0 (gchar *, 2); - self->overrides.messages[0] = g_strdup_printf ("%s %d: %s", g_quark_to_string (error->domain), error->code, error->message); - self->overrides.messages[1] = NULL; - return; - } - - if (exit_status != 0) - g_debug ("... wait status %d", exit_status); - - if (output != NULL) - { - g_strchomp (output); - self->overrides.values = g_strsplit (output, "\n", -1); - } - - if (messages != NULL) - { - g_strchomp (messages); - self->overrides.messages = g_strsplit (messages, "\n", -1); - } } } @@ -1311,11 +1274,10 @@ ensure_overrides_cached (SrtSystemInfo *self) * * The output is intended to be human-readable debugging information, * rather than something to use programmatically, and its format is - * not guaranteed. It is currently in `find -ls` format. + * not guaranteed. * * Similarly, @messages is intended to be human-readable debugging - * information. It is currently whatever was output on standard error - * by `find -ls`. + * information. * * Returns: (array zero-terminated=1) (transfer full) (nullable): A * %NULL-terminated array of libraries that have been overridden, @@ -1340,11 +1302,7 @@ srt_system_info_list_pressure_vessel_overrides (SrtSystemInfo *self, static void ensure_pinned_libs_cached (SrtSystemInfo *self) { - gchar *output = NULL; - gchar *messages = NULL; - gchar *runtime = NULL; - int exit_status = -1; - GError *error = NULL; + g_autofree gchar *runtime = NULL; g_return_if_fail (_srt_check_not_setuid ()); @@ -1357,86 +1315,18 @@ ensure_pinned_libs_cached (SrtSystemInfo *self) if (runtime == NULL || g_strcmp0 (runtime, "/") == 0) return; - const gchar *argv[] = {"find", "pinned_libs_32", "-ls", NULL}; - - if (!g_spawn_sync (runtime, /* working directory */ - (gchar **) argv, - self->env, - G_SPAWN_SEARCH_PATH, - _srt_child_setup_unblock_signals, - NULL, /* user data */ - &output, /* stdout */ - &messages, /* stderr */ - &exit_status, - &error)) - { - g_debug ("An error occurred calling the \"find\" binary: %s", error->message); - self->pinned_libs.messages_32 = g_new0 (gchar *, 2); - self->pinned_libs.messages_32[0] = g_strdup_printf ("%s %d: %s", g_quark_to_string (error->domain), error->code, error->message); - self->pinned_libs.messages_32[1] = NULL; - goto out; - } - - if (exit_status != 0) - g_debug ("... wait status %d", exit_status); - - if (output != NULL) - { - g_strchomp (output); - self->pinned_libs.values_32 = g_strsplit (output, "\n", -1); - } - - if (messages != NULL) - { - g_strchomp (messages); - self->pinned_libs.messages_32 = g_strsplit (messages, "\n", -1); - } - - g_free (output); - g_free (messages); - - /* Do the same check for `pinned_libs_64` */ - argv[1] = "pinned_libs_64"; - - if (!g_spawn_sync (runtime, /* working directory */ - (gchar **) argv, - self->env, - G_SPAWN_SEARCH_PATH, - _srt_child_setup_unblock_signals, - NULL, /* user data */ - &output, /* stdout */ - &messages, /* stderr */ - &exit_status, - &error)) - { - g_debug ("An error occurred calling the \"find\" binary: %s", error->message); - self->pinned_libs.messages_64 = g_new0 (gchar *, 2); - self->pinned_libs.messages_64[0] = g_strdup_printf ("%s %d: %s", g_quark_to_string (error->domain), error->code, error->message); - self->pinned_libs.messages_64[1] = NULL; - goto out; - } - - if (exit_status != 0) - g_debug ("... wait status %d", exit_status); - - if (output != NULL) - { - g_strchomp (output); - self->pinned_libs.values_64 = g_strsplit (output, "\n", -1); - } - - if (messages != NULL) - { - g_strchomp (messages); - self->pinned_libs.messages_64 = g_strsplit (messages, "\n", -1); - } + self->pinned_libs.values_32 = _srt_recursive_list_content (runtime, + -1, + "pinned_libs_32", + self->env, + &self->pinned_libs.messages_32); + + self->pinned_libs.values_64 = _srt_recursive_list_content (runtime, + -1, + "pinned_libs_64", + self->env, + &self->pinned_libs.messages_64); } - - out: - g_clear_error (&error); - g_free (output); - g_free (messages); - g_free (runtime); } /** @@ -1461,14 +1351,14 @@ ensure_pinned_libs_cached (SrtSystemInfo *self) * * The output is intended to be human-readable debugging information, * rather than something to use programmatically, and its format is - * not guaranteed. It is currently in `find -ls` format. + * not guaranteed. * * Similarly, @messages is intended to be human-readable debugging - * information. It is currently whatever was output on standard error - * by `find -ls`. + * information. * * Returns: (array zero-terminated=1) (transfer full) (element-type utf8) (nullable): - * An array of strings, or %NULL if we were unable to call "find". + * An array of strings, or %NULL if not in an `LD_LIBRARY_PATH`-based Steam + * Runtime or if it was not possible to list the pinned libs. * Free with g_strfreev(). */ gchar ** @@ -1507,14 +1397,14 @@ srt_system_info_list_pinned_libs_32 (SrtSystemInfo *self, * * The output is intended to be human-readable debugging information, * rather than something to use programmatically, and its format is - * not guaranteed. It is currently in `find -ls` format. + * not guaranteed. * * Similarly, @messages is intended to be human-readable debugging - * information. It is currently whatever was output on standard error - * by `find -ls`. + * information. * * Returns: (array zero-terminated=1) (transfer full) (element-type utf8) (nullable): - * An array of strings, or %NULL if we were unable to call "find". + * An array of strings, or %NULL if not in an `LD_LIBRARY_PATH`-based Steam + * Runtime or if it was not possible to list the pinned libs. * Free with g_strfreev(). */ gchar ** diff --git a/steam-runtime-tools/utils-internal.h b/steam-runtime-tools/utils-internal.h index 36f4e242785a9f238e574d8eda24504e0478bbec..91603348647277daf4767cac51bfa2b1af4ea031 100644 --- a/steam-runtime-tools/utils-internal.h +++ b/steam-runtime-tools/utils-internal.h @@ -114,6 +114,15 @@ G_GNUC_INTERNAL gboolean _srt_steam_command_via_pipe (const char * const *argume gssize n_arguments, GError **error); +G_GNUC_INTERNAL gchar **_srt_recursive_list_content (const gchar *sysroot, + int sysroot_fd, + const gchar *directory, + gchar **envp, + gchar ***messages_out); + +G_GNUC_INTERNAL const char *_srt_get_path_after (const char *str, + const char *prefix); + /* * _srt_is_same_stat: * @a: a stat buffer diff --git a/steam-runtime-tools/utils.c b/steam-runtime-tools/utils.c index 3a80cb2fdcd9f415ff7768dec051b19b82978dd6..7e2d0b837968f4ef7f5c3f4802beef7828d192b1 100644 --- a/steam-runtime-tools/utils.c +++ b/steam-runtime-tools/utils.c @@ -1129,3 +1129,290 @@ _srt_steam_command_via_pipe (const char * const *arguments, return TRUE; } + +typedef struct +{ + const char *from; + const char *to; +} CommonReplacements; + +/* + * _srt_list_directory_content: + * @working_dir_fd: File descriptor to the current working directory + * @working_dir_path: (not nullable) (type filename): Working directory in + * the sysroot + * @sub_directory: (nullable) (type filename): If %NULL, the @working_dir_path + * itself will be opened + * @common_replacements: (nullable): If not %NULL, perform these replacements + * to the beginning of the targets paths for symlinks that have been found + * @level: Current level of recursion + * @result: (not nullable): The elements that @directory contains are appended + * to this array + * @messages: (not nullable): Human-readable debug information are appended + * to this array + */ +static void +_srt_list_directory_content (int working_dir_fd, + const gchar *working_dir_path, + const gchar *sub_directory, + const CommonReplacements *common_replacements, + int level, + GPtrArray *result, + GPtrArray *messages) +{ + g_autofree gchar *full_working_path = NULL; + g_auto(GLnxDirFdIterator) iter = { FALSE }; + g_autoptr(GError) error = NULL; + gsize i; + + g_return_if_fail (working_dir_path != NULL); + g_return_if_fail (result != NULL); + g_return_if_fail (messages != NULL); + + if (sub_directory != NULL) + full_working_path = g_build_filename (working_dir_path, sub_directory, NULL); + else + full_working_path = g_strdup (working_dir_path); + + /* Arbitrary limit. If we reach this level of recursion it's a sign that + * something went wrong and it's better to bail out. */ + if (level > 9) + { + g_ptr_array_add (messages, g_strdup_printf ("%s/... (too much recursion, not shown)", + full_working_path)); + return; + } + + if (!glnx_dirfd_iterator_init_at (working_dir_fd, + sub_directory != NULL ? sub_directory : ".", + FALSE, + &iter, + &error)) + { + glnx_prefix_error (&error, + "An error occurred trying to initialize an iterator for \"%s\"", + full_working_path); + g_debug ("%s", error->message); + g_ptr_array_add (messages, g_strdup_printf ("%s %d: %s", + g_quark_to_string (error->domain), + error->code, error->message)); + return; + } + + while (error == NULL) + { + struct dirent *dent; + g_autofree gchar *full_name = NULL; + + if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&iter, &dent, NULL, &error)) + { + glnx_prefix_error (&error, "An error occurred trying to initerate through \"%s\"", + full_working_path); + g_debug ("%s", error->message); + g_ptr_array_add (messages, g_strdup_printf ("%s %d: %s", + g_quark_to_string (error->domain), + error->code, error->message)); + return; + } + + if (dent == NULL) + break; + + full_name = g_build_filename (full_working_path, dent->d_name, NULL); + + if (dent->d_type == DT_LNK) + { + g_autofree gchar *target = NULL; + + target = glnx_readlinkat_malloc (iter.fd, dent->d_name, NULL, &error); + if (target == NULL) + { + glnx_prefix_error (&error, "An error occurred trying to read the symlink \"%s\"", + full_name); + g_debug ("%s", error->message); + g_ptr_array_add (messages, g_strdup_printf ("%s %d: %s", + g_quark_to_string (error->domain), + error->code, error->message)); + g_clear_error (&error); + target = g_strdup ("(unknown)"); + } + + for (i = 0; common_replacements != NULL && common_replacements[i].to != NULL; i++) + { + if (common_replacements[i].from == NULL) + continue; + + const gchar *after = _srt_get_path_after (target, common_replacements[i].from); + + if (after != NULL) + { + g_autofree gchar *new_target = NULL; + new_target = g_build_filename (common_replacements[i].to, after, NULL); + g_clear_pointer (&target, g_free); + target = g_steal_pointer (&new_target); + break; + } + } + + g_ptr_array_add (result, g_strdup_printf ("%s -> %s", full_name, target)); + } + else if (dent->d_type == DT_DIR) + { + g_ptr_array_add (result, g_strdup_printf ("%s/", full_name)); + + _srt_list_directory_content (iter.fd, full_working_path, dent->d_name, + common_replacements, level + 1, result, messages); + } + else + { + g_ptr_array_add (result, g_steal_pointer (&full_name)); + } + + } +} + +/* + * _srt_recursive_list_content: + * @sysroot: (not nullable) (type filename): A path used as the root + * @sysroot_fd: A file descriptor opened on @sysroot, or negative to + * reopen it + * @directory: (not nullable) (type filename): A path below the root directory, + * either absolute or relative (to the root) + * @envp: (array zero-terminated=1) (not nullable): Behave as though `environ` + * was this array + * @messages_out: (optional) (out) (array zero-terminated=1) (transfer full): + * If not %NULL, used to return a %NULL-terminated array of diagnostic + * messages. Free with g_strfreev(). + * + * Returns: (array zero-terminated=1) (transfer full) (nullable): A + * %NULL-terminated array of files, symbolic links and directories, that + * are present in the provided @directory. Free with g_strfreev(). + */ +gchar ** +_srt_recursive_list_content (const gchar *sysroot, + int sysroot_fd, + const gchar *directory, + gchar **envp, + gchar ***messages_out) +{ + g_autoptr(GPtrArray) content = NULL; + g_autoptr(GPtrArray) messages = NULL; + glnx_autofd int local_sysroot_fd = -1; + glnx_autofd int top_fd = -1; + g_autoptr(GError) error = NULL; + const gchar *steam_runtime = NULL; + + g_return_val_if_fail (sysroot != NULL, NULL); + g_return_val_if_fail (directory != NULL, NULL); + g_return_val_if_fail (envp != NULL, NULL); + g_return_val_if_fail (messages_out == NULL || *messages_out == NULL, NULL); + + steam_runtime = g_environ_getenv (envp, "STEAM_RUNTIME"); + /* If STEAM_RUNTIME is just the root directory we don't want to replace + * every leading '/' with $STEAM_RUNTIME */ + if (g_strcmp0 (steam_runtime, "/") == 0) + steam_runtime = NULL; + + const CommonReplacements common_replacements[] = + { + { steam_runtime, "$STEAM_RUNTIME" }, + { g_environ_getenv (envp, "HOME"), "$HOME" }, + { NULL, NULL }, + }; + + content = g_ptr_array_new_with_free_func (g_free); + messages = g_ptr_array_new_with_free_func (g_free); + + if (sysroot_fd < 0) + { + if (!glnx_opendirat (-1, sysroot, FALSE, &local_sysroot_fd, &error)) + { + glnx_prefix_error (&error, "An error occurred trying to open sysroot \"%s\"", + sysroot); + g_debug ("%s", error->message); + g_ptr_array_add (messages, g_strdup_printf ("%s %d: %s", + g_quark_to_string (error->domain), + error->code, error->message)); + goto out; + } + sysroot_fd = local_sysroot_fd; + } + + top_fd = _srt_resolve_in_sysroot (sysroot_fd, + directory, + SRT_RESOLVE_FLAGS_DIRECTORY, + NULL, + &error); + + if (top_fd < 0) + { + glnx_prefix_error (&error, "An error occurred trying to resolve \"%s\" in sysroot", + directory); + g_debug ("%s", error->message); + g_ptr_array_add (messages, g_strdup_printf ("%s %d: %s", + g_quark_to_string (error->domain), + error->code, error->message)); + goto out; + } + + _srt_list_directory_content (top_fd, directory, NULL, common_replacements, 0, + content, messages); + + g_ptr_array_sort (content, _srt_indirect_strcmp0); + +out: + if (content->len > 0) + g_ptr_array_add (content, NULL); + + if (messages_out != NULL && messages->len > 0) + { + g_ptr_array_add (messages, NULL); + *messages_out = (GStrv) g_ptr_array_free (g_steal_pointer (&messages), FALSE); + } + + return (GStrv) g_ptr_array_free (g_steal_pointer (&content), FALSE); +} + +/* + * @str: A path + * @prefix: A possible prefix + * + * The same as flatpak_has_path_prefix(), but instead of a boolean, + * return the part of @str after @prefix (non-%NULL but possibly empty) + * if @str has prefix @prefix, or %NULL if it does not. + * + * Returns: (nullable) (transfer none): the part of @str after @prefix, + * or %NULL if @str is not below @prefix + */ +const char * +_srt_get_path_after (const char *str, + const char *prefix) +{ + while (TRUE) + { + /* Skip consecutive slashes to reach next path + element */ + while (*str == '/') + str++; + while (*prefix == '/') + prefix++; + + /* No more prefix path elements? Done! */ + if (*prefix == 0) + return str; + + /* Compare path element */ + while (*prefix != 0 && *prefix != '/') + { + if (*str != *prefix) + return NULL; + str++; + prefix++; + } + + /* Matched prefix path element, + must be entire str path element */ + if (*str != '/' && *str != 0) + return NULL; + } +} diff --git a/tests/json-report/full-good-report.json b/tests/json-report/full-good-report.json index 985a3eb9363a7dad76ade3a38b8e978ebccd7dea..e7f8db19f3239a01d10ecc1649edf899b704a25e 100644 --- a/tests/json-report/full-good-report.json +++ b/tests/json-report/full-good-report.json @@ -17,16 +17,17 @@ ], "pinned_libs_32" : { "list" : [ - " 13902790 4 drwxr-xr-x 2 me me 4096 Apr 24 21:32 pinned_libs_32", - " 13902813 4 -rw-r--r-- 1 me me 50 Apr 24 21:32 pinned_libs_32/system_libGLU.so.1", - " 13902814 4 lrwxrwxrwx 1 me me 107 Apr 24 21:32 pinned_libs_32/libdbusmenu-gtk.so.4 -> /home/me/.local/share/Steam/ubuntu12_32/steam-runtime/usr/lib/i386-linux-gnu/libdbusmenu-gtk.so.4.0.13" + "pinned_libs_32/has_pins", + "pinned_libs_32/libdbusmenu-gtk.so.4 -> /home/me/.local/share/Steam/ubuntu12_32/steam-runtime/usr/lib/i386-linux-gnu/libdbusmenu-gtk.so.4.0.13", + "pinned_libs_32/system_libGLU.so.1" + ] }, "pinned_libs_64" : { "list" : [ - " 13902791 4 drwxr-xr-x 2 me me 4096 Apr 24 21:32 pinned_libs_64", - " 13902805 4 -rw-r--r-- 1 me me 46 Apr 24 21:32 pinned_libs_64/system_libGLU.so.1", - " 13902795 4 lrwxrwxrwx 1 me me 100 Apr 24 21:32 pinned_libs_64/libjack.so.0 -> /home/me/.local/share/Steam/ubuntu12_32/steam-runtime/usr/lib/x86_64-linux-gnu/libjack.so.0.1.0" + "pinned_libs_64/has_pins", + "pinned_libs_64/libjack.so.0 -> /home/me/.local/share/Steam/ubuntu12_32/steam-runtime/usr/lib/x86_64-linux-gnu/libjack.so.0.1.0", + "pinned_libs_64/system_libGLU.so.1" ] } }, diff --git a/tests/pressure-vessel/utils.c b/tests/pressure-vessel/utils.c index b10ac4dc7d055c729a4cf7e4cd49136b212ef3af..b70475b575cc920904beb946a42262d378767e30 100644 --- a/tests/pressure-vessel/utils.c +++ b/tests/pressure-vessel/utils.c @@ -306,46 +306,6 @@ test_envp_cmp (Fixture *f, g_free (sort_this); } -static void -test_get_path_after (Fixture *f, - gconstpointer context) -{ - static const struct - { - const char *str; - const char *prefix; - const char *expected; - } tests[] = - { - { "/run/host/usr", "/run/host", "usr" }, - { "/run/host/usr", "/run/host/", "usr" }, - { "/run/host", "/run/host", "" }, - { "////run///host////usr", "//run//host", "usr" }, - { "////run///host////usr", "//run//host////", "usr" }, - { "/run/hostage", "/run/host", NULL }, - /* Any number of leading slashes is ignored, even zero */ - { "foo/bar", "/foo", "bar" }, - { "/foo/bar", "foo", "bar" }, - }; - gsize i; - - for (i = 0; i < G_N_ELEMENTS (tests); i++) - { - const char *str = tests[i].str; - const char *prefix = tests[i].prefix; - const char *expected = tests[i].expected; - - if (expected == NULL) - g_test_message ("%s should not have path prefix %s", - str, prefix); - else - g_test_message ("%s should have path prefix %s followed by %s", - str, prefix, expected); - - g_assert_cmpstr (pv_get_path_after (str, prefix), ==, expected); - } -} - static void test_mtree_entry_parse (Fixture *f, gconstpointer context) @@ -508,8 +468,6 @@ main (int argc, g_test_add ("/delete-dangling-symlink", Fixture, NULL, setup, test_delete_dangling_symlink, teardown); g_test_add ("/envp-cmp", Fixture, NULL, setup, test_envp_cmp, teardown); - g_test_add ("/get-path-after", Fixture, NULL, - setup, test_get_path_after, teardown); g_test_add ("/mtree-entry-parse", Fixture, NULL, setup, test_mtree_entry_parse, teardown); g_test_add ("/search-path-append", Fixture, NULL, diff --git a/tests/system-info.c b/tests/system-info.c index 268b2937ccf33106786e4bda13783d882cd93934..0bdcdcd3936c88d70fd103cf3ef024fcc430f058 100644 --- a/tests/system-info.c +++ b/tests/system-info.c @@ -1864,15 +1864,12 @@ overrides (Fixture *f, if (strstr (output[i], "/run/host/usr/lib/libgcc_s.so.1") != NULL) seen_link = TRUE; } - /* The overrides folder contains 4 folders plus the root folder, plus 4 files, - * plus one ".keep" file */ - g_assert_cmpint (i, ==, 10); + /* The overrides folder contains 4 folders, plus 4 files, plus one ".keep" file */ + g_assert_cmpint (i, ==, 9); g_assert_true (seen_link); g_strfreev (output); - g_assert_nonnull (issues); - g_assert_cmpstr (issues[0], ==, NULL); - g_strfreev (issues); + g_assert_null (issues); /* Repeat the same check, this time using the cached result */ output = srt_system_info_list_pressure_vessel_overrides (info, &issues); @@ -1883,13 +1880,11 @@ overrides (Fixture *f, if (strstr (output[i], "/run/host/usr/lib/libgcc_s.so.1") != NULL) seen_link = TRUE; } - g_assert_cmpint (i, ==, 10); + g_assert_cmpint (i, ==, 9); g_assert_true (seen_link); g_strfreev (output); - g_assert_nonnull (issues); - g_assert_cmpstr (issues[0], ==, NULL); - g_strfreev (issues); + g_assert_null (issues); g_object_unref (info); g_free (sysroot); @@ -1939,11 +1934,10 @@ overrides_issues (Fixture *f, if (strstr (output[i], "/run/host/usr/lib/libgcc_s.so.1") != NULL) seen_link = TRUE; } - /* The overrides folder contains 4 folders plus the root folder, plus one symlink, - * plus 2 ".keep" files. + /* The overrides folder contains 4 folders, plus one symlink, plus 2 ".keep" files. * We expect to not be able to open the "lib" folder, so we should have 4 less items than * a "normal" scenario */ - g_assert_cmpint (i, ==, 4); + g_assert_cmpint (i, ==, 3); /* We expect not to be able to reach the symlink */ g_assert_false (seen_link); g_strfreev (output); @@ -2038,15 +2032,12 @@ pinned_libraries (Fixture *f, if (strstr (values[i], "has_pins") != NULL) seen_pins = TRUE; } - /* We placed 3 files in `pinned_libs_32`. We expect to have 3 files plus the folder - * itself */ - g_assert_cmpint (i, ==, 4); + /* We placed 3 files in `pinned_libs_32` */ + g_assert_cmpint (i, ==, 3); g_assert_true (seen_pins); g_strfreev (values); - g_assert_nonnull (messages); - g_assert_cmpstr (messages[0], ==, NULL); - g_strfreev (messages); + g_assert_null (messages); /* Repeat the same check, this time using the cached values */ values = srt_system_info_list_pinned_libs_32 (info, &messages); @@ -2057,13 +2048,11 @@ pinned_libraries (Fixture *f, if (strstr (values[i], "has_pins") != NULL) seen_pins = TRUE; } - g_assert_cmpint (i, ==, 4); + g_assert_cmpint (i, ==, 3); g_assert_true (seen_pins); g_strfreev (values); - g_assert_nonnull (messages); - g_assert_cmpstr (messages[0], ==, NULL); - g_strfreev (messages); + g_assert_null (messages); g_free (target1); g_free (target2); @@ -2103,13 +2092,11 @@ pinned_libraries (Fixture *f, if (strstr (values[i], "has_pins") != NULL) seen_pins = TRUE; } - g_assert_cmpint (i, ==, 4); + g_assert_cmpint (i, ==, 3); g_assert_true (seen_pins); g_strfreev (values); - g_assert_nonnull (messages); - g_assert_cmpstr (messages[0], ==, NULL); - g_strfreev (messages); + g_assert_null (messages); /* Repeat the same check, this time using the cached values */ values = srt_system_info_list_pinned_libs_64 (info, &messages); @@ -2120,13 +2107,11 @@ pinned_libraries (Fixture *f, if (strstr (values[i], "has_pins") != NULL) seen_pins = TRUE; } - g_assert_cmpint (i, ==, 4); + g_assert_cmpint (i, ==, 3); g_assert_true (seen_pins); g_strfreev (values); - g_assert_nonnull (messages); - g_assert_cmpstr (messages[0], ==, NULL); - g_strfreev (messages); + g_assert_null (messages); g_free (target1); g_free (target2); @@ -2177,9 +2162,8 @@ pinned_libraries_permission (Fixture *f, if (strstr (values[i], "no_access") != NULL) seen_no_access = TRUE; } - /* We placed 1 folder in `pinned_libs_32`. We expect to have 1 folder plus the - * parent folder itself */ - g_assert_cmpint (i, ==, 2); + /* We placed 1 folder in `pinned_libs_32` */ + g_assert_cmpint (i, ==, 1); g_assert_true (seen_no_access); g_strfreev (values); @@ -2208,9 +2192,8 @@ pinned_libraries_permission (Fixture *f, if (strstr (values[i], "no_access") != NULL) seen_no_access = TRUE; } - /* We placed 1 folder in `pinned_libs_32`. We expect to have 1 folder plus the - * parent folder itself */ - g_assert_cmpint (i, ==, 2); + /* We placed 1 folder in `pinned_libs_32` */ + g_assert_cmpint (i, ==, 1); g_assert_true (seen_no_access); g_strfreev (values); @@ -2242,9 +2225,7 @@ pinned_libraries_missing (Fixture *f, g_assert_cmpint (g_rmdir (fake_home->pinned_32), ==, 0); values = srt_system_info_list_pinned_libs_32 (info, &messages); - g_assert_nonnull (values); - g_assert_cmpstr (values[0], ==, NULL); - g_strfreev (values); + g_assert_null (values); g_assert_nonnull (messages); g_assert_cmpstr (strstr (messages[0], "pinned_libs_32"), !=, NULL); @@ -2257,9 +2238,7 @@ pinned_libraries_missing (Fixture *f, g_assert_cmpint (g_rmdir (fake_home->pinned_64), ==, 0); values = srt_system_info_list_pinned_libs_64 (info, &messages); - g_assert_nonnull (values); - g_assert_cmpstr (values[0], ==, NULL); - g_strfreev (values); + g_assert_null (values); g_assert_nonnull (messages); g_assert_cmpstr (strstr (messages[0], "pinned_libs_64"), !=, NULL); @@ -2633,16 +2612,16 @@ static const JsonTest json_test[] = .issues = SRT_RUNTIME_ISSUES_NONE, .pinned_libs_32 = { - " 13902790 4 drwxr-xr-x 2 me me 4096 Apr 24 21:32 pinned_libs_32", - " 13902813 4 -rw-r--r-- 1 me me 50 Apr 24 21:32 pinned_libs_32/system_libGLU.so.1", - " 13902814 4 lrwxrwxrwx 1 me me 107 Apr 24 21:32 pinned_libs_32/libdbusmenu-gtk.so.4 -> /home/me/.local/share/Steam/ubuntu12_32/steam-runtime/usr/lib/i386-linux-gnu/libdbusmenu-gtk.so.4.0.13", + "pinned_libs_32/has_pins", + "pinned_libs_32/libdbusmenu-gtk.so.4 -> /home/me/.local/share/Steam/ubuntu12_32/steam-runtime/usr/lib/i386-linux-gnu/libdbusmenu-gtk.so.4.0.13", + "pinned_libs_32/system_libGLU.so.1", NULL, }, .pinned_libs_64 = { - " 13902791 4 drwxr-xr-x 2 me me 4096 Apr 24 21:32 pinned_libs_64", - " 13902805 4 -rw-r--r-- 1 me me 46 Apr 24 21:32 pinned_libs_64/system_libGLU.so.1", - " 13902795 4 lrwxrwxrwx 1 me me 100 Apr 24 21:32 pinned_libs_64/libjack.so.0 -> /home/me/.local/share/Steam/ubuntu12_32/steam-runtime/usr/lib/x86_64-linux-gnu/libjack.so.0.1.0", + "pinned_libs_64/has_pins", + "pinned_libs_64/libjack.so.0 -> /home/me/.local/share/Steam/ubuntu12_32/steam-runtime/usr/lib/x86_64-linux-gnu/libjack.so.0.1.0", + "pinned_libs_64/system_libGLU.so.1", NULL, }, }, diff --git a/tests/utils.c b/tests/utils.c index 312913182662f1900d3c155cddb6754ed1417226..1e9140bf1d9fa9d6e6968456bd52fdb269693eb2 100644 --- a/tests/utils.c +++ b/tests/utils.c @@ -264,6 +264,46 @@ test_file_in_sysroot (Fixture *f, } } +static void +test_get_path_after (Fixture *f, + gconstpointer context) +{ + static const struct + { + const char *str; + const char *prefix; + const char *expected; + } tests[] = + { + { "/run/host/usr", "/run/host", "usr" }, + { "/run/host/usr", "/run/host/", "usr" }, + { "/run/host", "/run/host", "" }, + { "////run///host////usr", "//run//host", "usr" }, + { "////run///host////usr", "//run//host////", "usr" }, + { "/run/hostage", "/run/host", NULL }, + /* Any number of leading slashes is ignored, even zero */ + { "foo/bar", "/foo", "bar" }, + { "/foo/bar", "foo", "bar" }, + }; + gsize i; + + for (i = 0; i < G_N_ELEMENTS (tests); i++) + { + const char *str = tests[i].str; + const char *prefix = tests[i].prefix; + const char *expected = tests[i].expected; + + if (expected == NULL) + g_test_message ("%s should not have path prefix %s", + str, prefix); + else + g_test_message ("%s should have path prefix %s followed by %s", + str, prefix, expected); + + g_assert_cmpstr (_srt_get_path_after (str, prefix), ==, expected); + } +} + /* * Test _srt_filter_gameoverlayrenderer function. */ @@ -430,6 +470,8 @@ main (int argc, setup, test_file_in_sysroot, teardown); g_test_add ("/utils/filter_gameoverlayrenderer", Fixture, NULL, setup, filter_gameoverlayrenderer, teardown); + g_test_add ("/utils/get-path-after", Fixture, NULL, + setup, test_get_path_after, teardown); g_test_add ("/utils/same-file", Fixture, NULL, setup, test_same_file, teardown); g_test_add ("/utils/str_is_integer", Fixture, NULL,