diff --git a/pressure-vessel/runtime.c b/pressure-vessel/runtime.c index 5c5cbe9187926c3c45a934bcd9fb03a89ab727b0..f2729e8341a7420ddf29486aab78f177d31892f8 100644 --- a/pressure-vessel/runtime.c +++ b/pressure-vessel/runtime.c @@ -68,9 +68,7 @@ struct _PvRuntime gchar *bubblewrap; gchar *source; - gchar *id; - gchar *deployment; - gchar *source_files; /* either deployment or that + "/files" */ + gchar *source_files; /* either source or that + "/files" */ const gchar *pv_prefix; const gchar *helpers_path; PvBwrapLock *runtime_lock; @@ -128,7 +126,6 @@ enum { PROP_SOURCE, PROP_ORIGINAL_ENVIRON, PROP_FLAGS, - PROP_ID, PROP_VARIABLE_DIR, N_PROPERTIES }; @@ -716,10 +713,6 @@ pv_runtime_get_property (GObject *object, g_value_set_flags (value, self->flags); break; - case PROP_ID: - g_value_set_string (value, self->id); - break; - case PROP_VARIABLE_DIR: g_value_set_string (value, self->variable_dir); break; @@ -792,12 +785,6 @@ pv_runtime_set_property (GObject *object, break; - case PROP_ID: - /* Construct-only */ - g_return_if_fail (self->id == NULL); - self->id = g_value_dup_string (value); - break; - case PROP_SOURCE: /* Construct-only */ g_return_if_fail (self->source == NULL); @@ -954,7 +941,7 @@ pv_runtime_garbage_collect (PvRuntime *self, if (_srt_fstatat_is_same_file (self->variable_dir_fd, dent->d_name, AT_FDCWD, - self->deployment)) + self->source)) { g_debug ("Ignoring %s/%s: is the current version", self->variable_dir, dent->d_name); @@ -1199,204 +1186,6 @@ pv_runtime_create_copy (PvRuntime *self, return TRUE; } -static gboolean -gstring_replace_suffix (GString *s, - const char *suffix, - const char *replacement) -{ - gsize len = strlen (suffix); - - if (s->len >= len - && strcmp (&s->str[s->len - len], suffix) == 0) - { - g_string_truncate (s, s->len - len); - g_string_append (s, replacement); - return TRUE; - } - - return FALSE; -} - -/* - * mutable_lock: (out) (not optional): - */ -static gboolean -pv_runtime_unpack (PvRuntime *self, - PvBwrapLock **mutable_lock, - GError **error) -{ - g_autoptr(GString) debug_tarball = NULL; - G_GNUC_UNUSED g_autoptr(SrtProfilingTimer) timer = NULL; - g_autofree gchar *deploy_basename = NULL; - g_autofree gchar *unpack_dir = NULL; - - g_return_val_if_fail (PV_IS_RUNTIME (self), FALSE); - g_return_val_if_fail (mutable_lock != NULL, FALSE); - g_return_val_if_fail (*mutable_lock == NULL, FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - g_return_val_if_fail (self->source != NULL, FALSE); - g_return_val_if_fail (self->variable_dir != NULL, FALSE); - g_return_val_if_fail (self->variable_dir_fd >= 0, FALSE); - g_return_val_if_fail (self->deployment == NULL, FALSE); - - if (!g_file_test (self->source, G_FILE_TEST_IS_REGULAR)) - return glnx_throw (error, "\"%s\" is not a regular file", self->source); - - if (!g_str_has_suffix (self->source, ".tar.gz")) - return glnx_throw (error, "\"%s\" is not a .tar.gz file", self->source); - - if (self->id == NULL) - { - g_autoptr(GString) build_id_file = g_string_new (self->source); - g_autofree char *id = NULL; - gsize len; - gsize i; - - if (gstring_replace_suffix (build_id_file, "-runtime.tar.gz", - "-buildid.txt") - || gstring_replace_suffix (build_id_file, "-sysroot.tar.gz", - "-buildid.txt")) - { - if (!g_file_get_contents (build_id_file->str, &id, &len, error)) - { - g_prefix_error (error, "Unable to determine build ID from \"%s\": ", - build_id_file->str); - return FALSE; - } - - if (len == 0) - return glnx_throw (error, "Build ID in \"%s\" is empty", - build_id_file->str); - - for (i = 0; i < len; i++) - { - /* Ignore a trailing newline */ - if (i + 1 == len && id[i] == '\n') - { - id[i] = '\0'; - break; - } - - /* Allow dot, dash or underscore, but not at the beginning */ - if (i > 0 && strchr (".-_", id[i]) != NULL) - continue; - - if (!g_ascii_isalnum (id[i])) - return glnx_throw (error, "Build ID in \"%s\" is invalid", - build_id_file->str); - } - - self->id = g_steal_pointer (&id); - } - } - - if (self->id == NULL) - return glnx_throw (error, "Cannot unpack archive without unique ID"); - - deploy_basename = g_strdup_printf ("deploy-%s", self->id); - self->deployment = g_build_filename (self->variable_dir, - deploy_basename, NULL); - - /* Fast path: if we already unpacked it, nothing more to do! */ - if (g_file_test (self->deployment, G_FILE_TEST_IS_DIR)) - return TRUE; - - /* Lock the parent directory. Anything that directly manipulates the - * unpacked runtimes is expected to do the same, so that - * it cannot be deleting unpacked runtimes at the same time we're - * creating them. - * - * This is an exclusive lock, to avoid two concurrent processes trying - * to unpack the same runtime. */ - *mutable_lock = pv_bwrap_lock_new (self->variable_dir_fd, ".ref", - (PV_BWRAP_LOCK_FLAGS_CREATE - | PV_BWRAP_LOCK_FLAGS_WAIT), - error); - - if (*mutable_lock == NULL) - return FALSE; - - /* Slow path: we need to do this the hard way. */ - timer = _srt_profiling_start ("Unpacking %s", self->source); - unpack_dir = g_build_filename (self->variable_dir, "tmp-XXXXXX", NULL); - - if (g_mkdtemp (unpack_dir) == NULL) - return glnx_throw_errno_prefix (error, - "Cannot create temporary directory \"%s\"", - unpack_dir); - - g_info ("Unpacking \"%s\" into \"%s\"...", self->source, unpack_dir); - - { - g_autoptr(FlatpakBwrap) tar = flatpak_bwrap_new (NULL); - - flatpak_bwrap_add_args (tar, - "tar", - "--force-local", - "-C", unpack_dir, - NULL); - - if (self->flags & PV_RUNTIME_FLAGS_VERBOSE) - flatpak_bwrap_add_arg (tar, "-v"); - - flatpak_bwrap_add_args (tar, - "-xf", self->source, - NULL); - flatpak_bwrap_finish (tar); - - if (!pv_bwrap_run_sync (tar, NULL, error)) - { - glnx_shutil_rm_rf_at (-1, unpack_dir, NULL, NULL); - return FALSE; - } - } - - debug_tarball = g_string_new (self->source); - - if (gstring_replace_suffix (debug_tarball, "-runtime.tar.gz", - "-debug.tar.gz") - && g_file_test (debug_tarball->str, G_FILE_TEST_EXISTS)) - { - g_autoptr(FlatpakBwrap) tar = flatpak_bwrap_new (NULL); - g_autoptr(GError) local_error = NULL; - g_autofree char *files_lib_debug = NULL; - - files_lib_debug = g_build_filename (unpack_dir, "files", "lib", - "debug", NULL); - - flatpak_bwrap_add_args (tar, - "tar", - "--force-local", - "-C", files_lib_debug, - NULL); - - if (self->flags & PV_RUNTIME_FLAGS_VERBOSE) - flatpak_bwrap_add_arg (tar, "-v"); - - flatpak_bwrap_add_args (tar, - "-xf", debug_tarball->str, - "files/", - NULL); - flatpak_bwrap_finish (tar); - - if (!pv_bwrap_run_sync (tar, NULL, &local_error)) - g_debug ("Ignoring error unpacking detached debug symbols: %s", - local_error->message); - } - - g_info ("Renaming \"%s\" to \"%s\"...", unpack_dir, deploy_basename); - - if (!glnx_renameat (self->variable_dir_fd, unpack_dir, - self->variable_dir_fd, deploy_basename, - error)) - { - glnx_shutil_rm_rf_at (-1, unpack_dir, NULL, NULL); - return FALSE; - } - - return TRUE; -} - typedef struct { const PvMultiarchDetails *details; @@ -1732,30 +1521,13 @@ pv_runtime_initable_init (GInitable *initable, if (!pv_runtime_init_variable_dir (self, error)) return FALSE; - if (self->flags & PV_RUNTIME_FLAGS_UNPACK_ARCHIVE) - { - if (self->variable_dir_fd < 0) - return glnx_throw (error, - "Cannot unpack archive without variable directory"); - - if (!pv_runtime_unpack (self, &mutable_lock, error)) - return FALSE; - - /* Set by pv_runtime_unpack */ - g_assert (self->deployment != NULL); - } - else - { - self->deployment = g_strdup (self->source); - } - - if (!g_file_test (self->deployment, G_FILE_TEST_IS_DIR)) + if (!g_file_test (self->source, G_FILE_TEST_IS_DIR)) { return glnx_throw (error, "\"%s\" is not a directory", - self->deployment); + self->source); } - /* If the deployment contains usr-mtree.txt, assume that it's a + /* If the runtime directory contains usr-mtree.txt, assume that it's a * Flatpak-style merged-/usr runtime, and usr-mtree.txt describes * what's in the runtime. The content is taken from the files/ * directory, but files not listed in the mtree are not included. @@ -1763,7 +1535,7 @@ pv_runtime_initable_init (GInitable *initable, * The manifest compresses well (about 3:1 if sha256sums are included) * so try to read a compressed version first, falling back to * uncompressed. */ - usr_mtree = g_build_filename (self->deployment, "usr-mtree.txt.gz", NULL); + usr_mtree = g_build_filename (self->source, "usr-mtree.txt.gz", NULL); if (g_file_test (usr_mtree, G_FILE_TEST_IS_REGULAR)) { @@ -1772,7 +1544,7 @@ pv_runtime_initable_init (GInitable *initable, else { g_clear_pointer (&usr_mtree, g_free); - usr_mtree = g_build_filename (self->deployment, "usr-mtree.txt", NULL); + usr_mtree = g_build_filename (self->source, "usr-mtree.txt", NULL); } if (!g_file_test (usr_mtree, G_FILE_TEST_IS_REGULAR)) @@ -1780,23 +1552,23 @@ pv_runtime_initable_init (GInitable *initable, /* Or, if it contains ./files/, assume it's a Flatpak-style runtime where * ./files is a merged /usr and ./metadata is an optional GKeyFile. */ - self->source_files = g_build_filename (self->deployment, "files", NULL); + self->source_files = g_build_filename (self->source, "files", NULL); if (usr_mtree != NULL) { g_debug ("Assuming %s is a merged-/usr runtime because it has " "a /usr mtree", - self->deployment); + self->source); } else if (g_file_test (self->source_files, G_FILE_TEST_IS_DIR)) { - g_debug ("Assuming %s is a Flatpak-style runtime", self->deployment); + g_debug ("Assuming %s is a Flatpak-style runtime", self->source); } else { - g_debug ("Assuming %s is a sysroot or merged /usr", self->deployment); + g_debug ("Assuming %s is a sysroot or merged /usr", self->source); g_clear_pointer (&self->source_files, g_free); - self->source_files = g_strdup (self->deployment); + self->source_files = g_strdup (self->source); } g_debug ("Taking runtime files from: %s", self->source_files); @@ -2071,8 +1843,6 @@ pv_runtime_finalize (GObject *object) pv_runtime_cleanup (self); g_free (self->bubblewrap); - g_free (self->deployment); - g_free (self->id); g_free (self->libcapsule_knowledge); g_strfreev (self->original_environ); glnx_close_fd (&self->overrides_fd); @@ -2138,13 +1908,6 @@ pv_runtime_class_init (PvRuntimeClass *cls) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - properties[PROP_ID] = - g_param_spec_string ("id", "ID", - "Unique identifier of runtime to be unpacked", - NULL, - (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - properties[PROP_VARIABLE_DIR] = g_param_spec_string ("variable-dir", "Variable directory", ("Path to directory for temporary files, or NULL"), @@ -2155,7 +1918,7 @@ pv_runtime_class_init (PvRuntimeClass *cls) properties[PROP_SOURCE] = g_param_spec_string ("source", "Source", ("Path to read-only runtime files (merged-/usr " - "or sysroot) or archive, in current namespace"), + "or sysroot), in current namespace"), NULL, (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); @@ -2165,7 +1928,6 @@ pv_runtime_class_init (PvRuntimeClass *cls) PvRuntime * pv_runtime_new (const char *source, - const char *id, const char *variable_dir, const char *bubblewrap, PvGraphicsProvider *provider, @@ -2186,7 +1948,6 @@ pv_runtime_new (const char *source, "original-environ", original_environ, "variable-dir", variable_dir, "source", source, - "id", id, "flags", flags, NULL); } diff --git a/pressure-vessel/runtime.h b/pressure-vessel/runtime.h index 54bf124dc4641f6f4715c45fe4192af5ce9aafed..d80cd3bcebc95c1b2a6efa7fcbadc4b9351d3ba4 100644 --- a/pressure-vessel/runtime.h +++ b/pressure-vessel/runtime.h @@ -43,7 +43,6 @@ * @PV_RUNTIME_FLAGS_VERBOSE: Be more verbose * @PV_RUNTIME_FLAGS_IMPORT_VULKAN_LAYERS: Include host Vulkan layers * @PV_RUNTIME_FLAGS_COPY_RUNTIME: Copy the runtime and modify the copy - * @PV_RUNTIME_FLAGS_UNPACK_ARCHIVE: Source is an archive, not a deployment * @PV_RUNTIME_FLAGS_FLATPAK_SUBSANDBOX: The runtime will be used in a * Flatpak subsandbox * @PV_RUNTIME_FLAGS_INTERPRETER_ROOT: The runtime is being set up as a @@ -107,7 +106,6 @@ typedef struct _PvRuntimeClass PvRuntimeClass; GType pv_runtime_get_type (void); PvRuntime *pv_runtime_new (const char *source, - const char *id, const char *variable_dir, const char *bubblewrap, PvGraphicsProvider *provider, diff --git a/pressure-vessel/wrap.1.md b/pressure-vessel/wrap.1.md index 39e56a13c753952406297bb6417c7e614816066a..b86dd347c9a74457eb69586ea388620e2e2a5e8b 100644 --- a/pressure-vessel/wrap.1.md +++ b/pressure-vessel/wrap.1.md @@ -164,43 +164,10 @@ pressure-vessel-wrap - run programs in a bubblewrap container (containing bin/sh, bin/env and many other OS files). For example, a Flatpak runtime is a suitable value for *PATH*. -`--runtime-archive` *ARCHIVE* -: Unpack *ARCHIVE* and use it to provide /usr in the container, similar - to `--runtime`. The `--runtime-id` option is also required, unless - the filename of the *ARCHIVE* ends with a supported suffix - (`-runtime.tar.gz` or `-sysroot.tar.gz`) and it is accompanied by a - `-buildid.txt` file. - - If this option is used, then `--variable-dir` - (or its environment variable equivalent) is also required. - This option and `--runtime` cannot both be used. - - The archive will be unpacked into a subdirectory of the `--variable-dir`. - Any other subdirectories of the `--variable-dir` that appear to be - different runtimes will be deleted, unless they contain a file - at the top level named `keep` or are currently in use. - - The archive must currently be a gzipped tar file whose name ends - with `.tar.gz`. Other formats might be allowed in future. - `--runtime-base` *PATH* -: If `--runtime` or `--runtime-archive` is specified as a relative path, +: If `--runtime` is specified as a relative path, look for it relative to *PATH*. -`--runtime-id` *ID* -: Use *ID* to construct a directory into which the `--runtime-archive` - will be unpacked, overriding an accompanying `-buildid.txt` file - if present. The *ID* must match the regular expression - `^[A-Za-z0-9_][-A-Za-z0-9_.]*$` (a non-empty sequence of ASCII - letters, digits, underscores, dots and dashes, starting with a - letter, digit or underscore). It will typically be in a format - similar to `0.20210301.0` or `soldier_0.20210301.0`. - - If the *ID* is the same as in a previous run of pressure-vessel-wrap, - the content of the `--runtime-archive` will be assumed to be the - same as in that previous run, resulting in the previous runtime - being reused. - `--share-home`, `--unshare-home` : If `--unshare-home` is specified, use the home directory given by `--home`, `--freedesktop-app-id`, `--steam-app-id` or their @@ -400,15 +367,9 @@ The following environment variables (among others) are read by `PRESSURE_VESSEL_RUNTIME` (path, filename or empty string) : Equivalent to `--runtime="$PRESSURE_VESSEL_RUNTIME"`. -`PRESSURE_VESSEL_RUNTIME_ARCHIVE` (path, filename or empty string) -: Equivalent to `--runtime-archive="$PRESSURE_VESSEL_RUNTIME_ARCHIVE"`. - `PRESSURE_VESSEL_RUNTIME_BASE` (path, filename or empty string) : Equivalent to `--runtime-base="$PRESSURE_VESSEL_RUNTIME_BASE"`. -`PRESSURE_VESSEL_RUNTIME_ID` (string matching `^[A-Za-z0-9_][-A-Za-z0-9_.]*$`) -: Equivalent to `--runtime-id="$PRESSURE_VESSEL_RUNTIME_ID"`. - `PRESSURE_VESSEL_SHARE_HOME` (boolean) : If set to `1`, equivalent to `--share-home`. If set to `0`, equivalent to `--unshare-home`. diff --git a/pressure-vessel/wrap.c b/pressure-vessel/wrap.c index 17e9cf1b80a36ef44c0c79d58ddb2564a34468c0..4b0b90f36feeffc59260ae57629f866656e849e8 100644 --- a/pressure-vessel/wrap.c +++ b/pressure-vessel/wrap.c @@ -250,9 +250,7 @@ static PvShell opt_shell = PV_SHELL_NONE; static GArray *opt_pass_fds = NULL; static GArray *opt_preload_modules = NULL; static char *opt_runtime = NULL; -static char *opt_runtime_archive = NULL; static char *opt_runtime_base = NULL; -static char *opt_runtime_id = NULL; static Tristate opt_share_home = TRISTATE_MAYBE; static gboolean opt_share_pid = TRUE; static gboolean opt_single_thread = FALSE; @@ -788,22 +786,12 @@ static GOptionEntry options[] = "it with the provider's graphics stack. The empty string " "means don't use a runtime. [Default: $PRESSURE_VESSEL_RUNTIME or '']", "RUNTIME" }, - { "runtime-archive", '\0', - G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &opt_runtime_archive, - "Unpack the ARCHIVE and use it as the runtime, using --runtime-id to " - "avoid repeatedly unpacking the same archive. " - "[Default: $PRESSURE_VESSEL_RUNTIME_ARCHIVE]", - "ARCHIVE" }, { "runtime-base", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &opt_runtime_base, - "If a --runtime or --runtime-archive is a relative path, look for " + "If a --runtime is a relative path, look for " "it relative to BASE. " "[Default: $PRESSURE_VESSEL_RUNTIME_BASE or '.']", "BASE" }, - { "runtime-id", '\0', - G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &opt_runtime_id, - "Reuse a previously-unpacked --runtime-archive if its ID matched this", - "ID" }, { "share-home", '\0', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, opt_share_home_cb, "Use the real home directory. " @@ -1021,7 +1009,6 @@ main (int argc, opt_deterministic = _srt_boolean_environment ("PRESSURE_VESSEL_DETERMINISTIC", FALSE); opt_devel = _srt_boolean_environment ("PRESSURE_VESSEL_DEVEL", FALSE); - opt_runtime_id = g_strdup (g_getenv ("PRESSURE_VESSEL_RUNTIME_ID")); { const char *value = g_getenv ("PRESSURE_VESSEL_VARIABLE_DIR"); @@ -1097,53 +1084,18 @@ main (int argc, pv_wrap_detect_virtualization (&interpreter_root, &host_machine); - /* Specifying either one of these mutually-exclusive options as a - * command-line option disables use of the environment variable for - * the other one */ - if (opt_runtime == NULL && opt_runtime_archive == NULL) + if (opt_runtime == NULL) { opt_runtime = g_strdup (g_getenv ("PRESSURE_VESSEL_RUNTIME")); /* Normalize empty string to NULL to simplify later code */ if (opt_runtime != NULL && opt_runtime[0] == '\0') g_clear_pointer (&opt_runtime, g_free); - - opt_runtime_archive = g_strdup (g_getenv ("PRESSURE_VESSEL_RUNTIME_ARCHIVE")); - - if (opt_runtime_archive != NULL && opt_runtime_archive[0] == '\0') - g_clear_pointer (&opt_runtime_archive, g_free); - } - - if (opt_runtime_id != NULL) - { - const char *p; - - if (opt_runtime_id[0] == '-' || opt_runtime_id[0] == '.') - { - usage_error ("--runtime-id must not start with dash or dot"); - goto out; - } - - for (p = opt_runtime_id; *p != '\0'; p++) - { - if (!g_ascii_isalnum (*p) && *p != '_' && *p != '-' && *p != '.') - { - usage_error ("--runtime-id may only contain " - "alphanumerics, underscore, dash or dot"); - goto out; - } - } } if (opt_runtime_base == NULL) opt_runtime_base = g_strdup (g_getenv ("PRESSURE_VESSEL_RUNTIME_BASE")); - if (opt_runtime != NULL && opt_runtime_archive != NULL) - { - usage_error ("--runtime and --runtime-archive cannot both be used"); - goto out; - } - if (opt_graphics_provider == NULL) opt_graphics_provider = g_strdup (g_getenv ("PRESSURE_VESSEL_GRAPHICS_PROVIDER")); @@ -1580,7 +1532,7 @@ main (int argc, } } - if (opt_runtime != NULL || opt_runtime_archive != NULL) + if (opt_runtime != NULL) { G_GNUC_UNUSED g_autoptr(SrtProfilingTimer) timer = _srt_profiling_start ("Setting up runtime"); @@ -1644,17 +1596,7 @@ main (int argc, } } - if (opt_runtime != NULL) - { - /* already checked for mutually exclusive options */ - g_assert (opt_runtime_archive == NULL); - runtime_path = opt_runtime; - } - else - { - flags |= PV_RUNTIME_FLAGS_UNPACK_ARCHIVE; - runtime_path = opt_runtime_archive; - } + runtime_path = opt_runtime; if (!g_path_is_absolute (runtime_path) && opt_runtime_base != NULL @@ -1676,7 +1618,6 @@ main (int argc, } runtime = pv_runtime_new (runtime_path, - opt_runtime_id, opt_variable_dir, bwrap_executable, graphics_provider, @@ -2468,9 +2409,7 @@ out: g_clear_pointer (&opt_steam_app_id, g_free); g_clear_pointer (&opt_home, g_free); g_clear_pointer (&opt_runtime, g_free); - g_clear_pointer (&opt_runtime_archive, g_free); g_clear_pointer (&opt_runtime_base, g_free); - g_clear_pointer (&opt_runtime_id, g_free); g_clear_pointer (&opt_pass_fds, g_array_unref); g_clear_pointer (&opt_variable_dir, g_free); diff --git a/tests/pressure-vessel/wrap-setup.c b/tests/pressure-vessel/wrap-setup.c index a0166582173d63c4a6ac3f52f7689717cbb78e98..daa7e28abbe7581c0a97267a00153b4a31b32136 100644 --- a/tests/pressure-vessel/wrap-setup.c +++ b/tests/pressure-vessel/wrap-setup.c @@ -179,7 +179,6 @@ fixture_create_runtime (Fixture *f, g_assert_nonnull (graphics_provider); runtime = pv_runtime_new (f->mock_runtime, - "mock_platform_1.0", f->var, NULL, graphics_provider,