diff --git a/meson.build b/meson.build index 42daa055ff00a99faab493a64e03beebea7f3115..d400fe01eb1891ccdb8229a6477cc950522106a1 100644 --- a/meson.build +++ b/meson.build @@ -182,6 +182,8 @@ executable( 'src/flatpak-bwrap-private.h', 'src/flatpak-utils.c', 'src/flatpak-utils-private.h', + 'src/utils.c', + 'src/utils.h', 'src/wrap.c', ], c_args : [ diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000000000000000000000000000000000000..ab3ab24745ad1ac64a061f60a9f207b5c313cd45 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,176 @@ +/* + * Contains code taken from Flatpak. + * + * Copyright © 2014-2019 Red Hat, Inc + * Copyright © 2017-2019 Collabora Ltd. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" +#include "subprojects/libglnx/config.h" +#include "utils.h" + +#include <glib.h> +#include <glib/gstdio.h> +#include <gio/gio.h> + +#include "libglnx.h" + +#include "glib-backports.h" +#include "flatpak-bwrap-private.h" +#include "flatpak-utils-private.h" + +/** + * pv_avoid_gvfs: + * + * Disable gvfs. This function must be called from main() before + * starting any threads. + */ +void +pv_avoid_gvfs (void) +{ + g_autofree gchar *old_env = NULL; + + /* avoid gvfs (http://bugzilla.gnome.org/show_bug.cgi?id=526454) */ + old_env = g_strdup (g_getenv ("GIO_USE_VFS")); + g_setenv ("GIO_USE_VFS", "local", TRUE); + g_vfs_get_default (); + if (old_env) + g_setenv ("GIO_USE_VFS", old_env, TRUE); + else + g_unsetenv ("GIO_USE_VFS"); +} + +/** + * pv_envp_cmp: + * @p1: a `const char * const *` + * @p2: a `const char * const *` + * + * Compare two environment variables, given as pointers to pointers + * to the actual `KEY=value` string. + * + * In particular this is suitable for sorting a #GStrv using `qsort`. + * + * Returns: negative, 0 or positive if `*p1` compares before, equal to + * or after `*p2` + */ +int +pv_envp_cmp (const void *p1, + const void *p2) +{ + const char * const * s1 = p1; + const char * const * s2 = p2; + size_t l1 = strlen (*s1); + size_t l2 = strlen (*s2); + size_t min; + const char *tmp; + int ret; + + tmp = strchr (*s1, '='); + + if (tmp != NULL) + l1 = tmp - *s1; + + tmp = strchr (*s2, '='); + + if (tmp != NULL) + l2 = tmp - *s2; + + min = MIN (l1, l2); + ret = strncmp (*s1, *s2, min); + + if (ret != 0) + return ret; + + if ((*s1)[min] == '\0') + return -1; + + if ((*s2)[min] == '\0') + return 1; + + if ((*s1)[min] == '=') + return -1; + + if ((*s2)[min] == '=') + return 1; + + return strcmp (*s1, *s2); +} + +/** + * pv_get_current_dirs: + * @cwd_p: (out) (transfer full) (optional): Used to return the + * current physical working directory, equivalent to `$(pwd -P)` + * in a shell + * @cwd_l: (out) (transfer full) (optional): Used to return the + * current logical working directory, equivalent to `$(pwd -L)` + * in a shell + * + * Return the physical and/or logical working directory. + * + * Equivalent to `$(pwd -L)` in a shell. + */ +void +pv_get_current_dirs (gchar **cwd_p, + gchar **cwd_l) +{ + g_autofree gchar *cwd = NULL; + const gchar *pwd; + + g_return_if_fail (cwd_p == NULL || *cwd_p == NULL); + g_return_if_fail (cwd_l == NULL || *cwd_l == NULL); + + cwd = g_get_current_dir (); + + if (cwd_p != NULL) + *cwd_p = flatpak_canonicalize_filename (cwd); + + if (cwd_l != NULL) + { + pwd = g_getenv ("PWD"); + + if (pwd != NULL && pv_is_same_file (pwd, cwd)) + *cwd_l = g_strdup (pwd); + else + *cwd_l = g_strdup (cwd); + } +} + +/** + * pv_is_same_file: + * @a: a path + * @b: a path + * + * Returns: %TRUE if a and b are names for the same inode. + */ +gboolean +pv_is_same_file (const gchar *a, + const gchar *b) +{ + GStatBuf a_buffer, b_buffer; + + g_return_val_if_fail (a != NULL, FALSE); + g_return_val_if_fail (b != NULL, FALSE); + + if (strcmp (a, b) == 0) + return TRUE; + + return (stat (a, &a_buffer) == 0 + && stat (b, &b_buffer) == 0 + && a_buffer.st_dev == b_buffer.st_dev + && a_buffer.st_ino == b_buffer.st_ino); +} diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000000000000000000000000000000000000..3c2f50f956d7e1ba895c2fe469de790f6e6c8977 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,36 @@ +/* + * Contains code taken from Flatpak. + * + * Copyright © 2014-2019 Red Hat, Inc + * Copyright © 2017-2019 Collabora Ltd. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <glib.h> + +void pv_avoid_gvfs (void); + +int pv_envp_cmp (const void *p1, + const void *p2); + +void pv_get_current_dirs (gchar **cwd_p, + gchar **cwd_l); + +gboolean pv_is_same_file (const gchar *a, + const gchar *b); diff --git a/src/wrap.c b/src/wrap.c index 9cccc972c2a561bf7604fb281bc99291967117ed..1789185209dea365f09dec264d82759e0c4475ae 100644 --- a/src/wrap.c +++ b/src/wrap.c @@ -39,6 +39,7 @@ #include "glib-backports.h" #include "flatpak-bwrap-private.h" #include "flatpak-utils-private.h" +#include "utils.h" static const char * const multiarch_tuples[] = { @@ -49,21 +50,6 @@ static const char * const multiarch_tuples[] = /* In Flatpak this is optional, in pressure-vessel not so much */ #define ENABLE_XAUTH -static void -avoid_gvfs (void) -{ - g_autofree gchar *old_env = NULL; - - /* avoid gvfs (http://bugzilla.gnome.org/show_bug.cgi?id=526454) */ - old_env = g_strdup (g_getenv ("GIO_USE_VFS")); - g_setenv ("GIO_USE_VFS", "local", TRUE); - g_vfs_get_default (); - if (old_env) - g_setenv ("GIO_USE_VFS", old_env, TRUE); - else - g_unsetenv ("GIO_USE_VFS"); -} - static gchar * find_executable_dir (GError **error) { @@ -86,49 +72,6 @@ search_path_append (GString *search_path, g_string_append (search_path, item); } -static int -envp_cmp (const void *p1, - const void *p2) -{ - const char * const * s1 = p1; - const char * const * s2 = p2; - size_t l1 = strlen (*s1); - size_t l2 = strlen (*s2); - size_t min; - const char *tmp; - int ret; - - tmp = strchr (*s1, '='); - - if (tmp != NULL) - l1 = tmp - *s1; - - tmp = strchr (*s2, '='); - - if (tmp != NULL) - l2 = tmp - *s2; - - min = MIN (l1, l2); - ret = strncmp (*s1, *s2, min); - - if (ret != 0) - return ret; - - if ((*s1)[min] == '\0') - return -1; - - if ((*s2)[min] == '\0') - return 1; - - if ((*s1)[min] == '=') - return -1; - - if ((*s2)[min] == '=') - return 1; - - return strcmp (*s1, *s2); -} - static gchar * find_bwrap (const char *tools_dir) { @@ -1544,46 +1487,6 @@ static GOptionEntry options[] = { NULL } }; -/* Return TRUE if a and b are names for the same inode. */ -static gboolean -is_same_file (const gchar *a, - const gchar *b) -{ - GStatBuf a_buffer, b_buffer; - - g_return_val_if_fail (a != NULL, FALSE); - g_return_val_if_fail (b != NULL, FALSE); - - if (strcmp (a, b) == 0) - return TRUE; - - return (stat (a, &a_buffer) == 0 - && stat (b, &b_buffer) == 0 - && a_buffer.st_dev == b_buffer.st_dev - && a_buffer.st_ino == b_buffer.st_ino); -} - -/* - * If the environment variable `PWD` contains a path to `cwd`, return - * a copy of `PWD`. Otherwise return a copy of `cwd`. - * - * Equivalent to `$(pwd -L)` in a shell. - */ -static gchar * -get_logical_current_dir (const gchar *cwd) -{ - const gchar *pwd; - - g_return_val_if_fail (cwd != NULL, NULL); - - pwd = g_getenv ("PWD"); - - if (pwd != NULL && is_same_file (pwd, cwd)) - return g_strdup (pwd); - else - return g_strdup (cwd); -} - static void cli_log_func (const gchar *log_domain, GLogLevelFlags log_level, @@ -1614,7 +1517,6 @@ main (int argc, g_autoptr(GString) adjusted_ld_preload = g_string_new (""); GPid child_pid; ChildExitedClosure child_exited_closure = { FALSE, 0 }; - g_autofree gchar *cwd = NULL; g_autofree gchar *cwd_p = NULL; g_autofree gchar *cwd_l = NULL; const gchar *home; @@ -1623,7 +1525,7 @@ main (int argc, const gchar *bwrap_help_argv[] = { "<bwrap>", "--help", NULL }; GSpawnFlags spawn_flags = G_SPAWN_DO_NOT_REAP_CHILD; - avoid_gvfs (); + pv_avoid_gvfs (); g_set_prgname ("pressure-vessel-wrap"); @@ -1721,9 +1623,7 @@ main (int argc, * us exit 1. */ ret = 1; - cwd = g_get_current_dir (); - cwd_p = flatpak_canonicalize_filename (cwd); - cwd_l = get_logical_current_dir (cwd); + pv_get_current_dirs (&cwd_p, &cwd_l); if (opt_verbose) { @@ -1748,7 +1648,7 @@ main (int argc, g_message ("Environment variables:"); - qsort (env, g_strv_length (env), sizeof (char *), envp_cmp); + qsort (env, g_strv_length (env), sizeof (char *), pv_envp_cmp); for (i = 0; env[i] != NULL; i++) { @@ -2015,7 +1915,7 @@ main (int argc, g_debug ("Making home directory available..."); - if (is_same_file (home, cwd_l)) + if (pv_is_same_file (home, cwd_l)) { g_debug ("Not making logical working directory \"%s\" available to " "container because it is the home directory", @@ -2036,7 +1936,7 @@ main (int argc, { g_debug ("Physical and logical working directory coincide"); } - else if (is_same_file (home, cwd_p)) + else if (pv_is_same_file (home, cwd_p)) { g_debug ("Not making physical working directory \"%s\" available to " "container because it is the home directory",