Skip to content
Snippets Groups Projects
Commit d0857ce8 authored by Simon McVittie's avatar Simon McVittie
Browse files

pressure-vessel: Remap $HOME for Flatpak correctly


Because we were testing for a prefix match with a trailing slash,
when FlatpakExports exports /home/me, we would not rewrite it to
/home/me/.var/app/com.valvesoftware.Steam.

Instead of adding the necessary special cases, use a slightly refactored
version of flatpak_has_path_prefix(), which already does what we need.

Signed-off-by: default avatarSimon McVittie <smcv@collabora.com>
parent f442b950
No related branches found
No related tags found
No related merge requests found
Pipeline #5904 passed
This commit is part of merge request !194. Comments created here will be created in the context of that merge request.
......@@ -795,6 +795,50 @@ 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
......@@ -807,40 +851,32 @@ gchar *
pv_current_namespace_path_to_host_path (const gchar *current_env_path)
{
gchar *path_on_host = NULL;
g_autofree gchar *home_env_guarded = NULL;
const gchar *home_env = g_getenv ("HOME");
g_return_val_if_fail (g_path_is_absolute (current_env_path),
g_strdup (current_env_path));
if (home_env == NULL)
home_env = g_get_home_dir ();
if (home_env != NULL)
{
/* Avoid the edge case where e.g. current_env_path is
* '/home/melanie/Games' and home_env is '/home/me' */
if (g_str_has_suffix (home_env, "/"))
home_env_guarded = g_strdup (home_env);
else
home_env_guarded = g_strdup_printf ("%s/", home_env);
}
if (g_file_test ("/.flatpak-info", G_FILE_TEST_IS_REGULAR))
{
struct stat via_current_env_stat;
struct stat via_persist_stat;
const gchar *home = g_getenv ("HOME");
const gchar *after = NULL;
if (home == NULL)
home = g_get_home_dir ();
if (home != NULL)
after = pv_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 */
if (home_env != NULL
&& g_str_has_prefix (current_env_path, home_env_guarded))
if (after != NULL)
{
path_on_host = g_build_filename (home_env,
path_on_host = g_build_filename (home,
".var",
"app",
g_getenv ("FLATPAK_ID"),
current_env_path + strlen (home_env),
after,
NULL);
if (lstat (path_on_host, &via_persist_stat) < 0)
......@@ -860,12 +896,12 @@ pv_current_namespace_path_to_host_path (const gchar *current_env_path)
}
}
after = pv_get_path_after (current_env_path, "/run/host");
/* In a Flatpak container, usually, '/run/host' is the root of the
* host system */
if (g_str_has_prefix (current_env_path, "/run/host/"))
path_on_host = g_strdup (current_env_path + strlen ("/run/host"));
else if (g_strcmp0 (current_env_path, "/run/host") == 0)
path_on_host = g_strdup ("/");
if (after != NULL && path_on_host == NULL)
path_on_host = g_build_filename ("/", after, NULL);
}
/* Either we are not in a Flatpak container or it's not obvious how the
* container to host translation should happen. Just keep the same path. */
......
......@@ -70,3 +70,6 @@ gboolean pv_terminate_all_child_processes (GTimeSpan wait_period,
GError **error);
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);
......@@ -182,6 +182,46 @@ 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_search_path_append (Fixture *f,
gconstpointer context)
......@@ -223,6 +263,8 @@ main (int argc,
g_test_add ("/capture-output", Fixture, NULL,
setup, test_capture_output, 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 ("/search-path-append", Fixture, NULL,
setup, test_search_path_append, teardown);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment