diff --git a/pressure-vessel/pressure-vessel-test-ui b/pressure-vessel/pressure-vessel-test-ui index 61f9e5c2079c2e02be9586b35ab3f8cd7a6b6445..b00a6d9ffb96697b790265a5925c8a7cf9c4a384 100755 --- a/pressure-vessel/pressure-vessel-test-ui +++ b/pressure-vessel/pressure-vessel-test-ui @@ -395,18 +395,47 @@ class Gui: self.grid.attach(label, 1, row, 1, 1) row += 1 - self.host_graphics_check = Gtk.CheckButton.new_with_label( - 'Use host-system graphics stack' - ) - value = boolean_environment('PRESSURE_VESSEL_HOST_GRAPHICS', True) - self.host_graphics_check.set_active(value) - self.grid.attach(self.host_graphics_check, 1, row, 1, 1) + label = Gtk.Label.new('Graphics stack') + self.grid.attach(label, 0, row, 1, 1) + + self.graphics_provider_combo = Gtk.ComboBoxText.new() + + env = os.getenv('PRESSURE_VESSEL_GRAPHICS_PROVIDER') + + if env is not None: + self.graphics_provider_combo.append( + env, '$PRESSURE_VESSEL_GRAPHICS_PROVIDER ({})'.format( + env or 'empty' + ), + ) + + if env is None or env != '/': + self.graphics_provider_combo.append( + '/', 'Current execution environment', + ) + + if ( + (env is None or env != '/run/host') + and os.path.isdir('/run/host/etc') + and os.path.isdir('/run/host/usr') + ): + self.graphics_provider_combo.append( + '/run/host', 'Host system', + ) + + if env is None or env != '': + self.graphics_provider_combo.append( + '', "Container's own libraries (probably won't work)", + ) + + self.graphics_provider_combo.set_active(0) + self.grid.attach(self.graphics_provider_combo, 1, row, 1, 1) row += 1 label = Gtk.Label.new('') label.set_markup( '<small><i>' - "Most games and GPUs won't work when this is disabled." + "Most games and GPUs won't work if this is changed." '</i></small>' ) label.set_halign(Gtk.Align.START) @@ -602,11 +631,11 @@ class Gui: if combo.get_active_id() == '/': self.copy_runtime_check.set_sensitive(False) self.gc_runtimes_check.set_sensitive(False) - self.host_graphics_check.set_sensitive(False) + self.graphics_provider_combo.set_sensitive(False) else: self.copy_runtime_check.set_sensitive(True) self.gc_runtimes_check.set_sensitive(True) - self.host_graphics_check.set_sensitive(True) + self.graphics_provider_combo.set_sensitive(True) def run_cb(self, _ignored=None): # type: (typing.Any) -> None @@ -633,13 +662,10 @@ class Gui: else: argv.append('--runtime=' + id) - if self.host_graphics_check.get_active(): - if os.path.isdir('/run/host'): - argv.append('--graphics-provider=/run/host') - else: - argv.append('--graphics-provider=/') - else: - argv.append('--graphics-provider=') + argv.append( + '--graphics-provider=' + + self.graphics_provider_combo.get_active_id() + ) if self.copy_runtime_check.get_active(): os.makedirs(self.var_path, mode=0o755, exist_ok=True) diff --git a/pressure-vessel/runtime.c b/pressure-vessel/runtime.c index 7f67231a47db9c444a2b5d0fbab026d029a46efc..e4e036c82f484a28ae8aa563fbc3435ecbe30640 100644 --- a/pressure-vessel/runtime.c +++ b/pressure-vessel/runtime.c @@ -1431,13 +1431,16 @@ pv_runtime_initable_init (GInitable *initable, } } - if (!glnx_opendirat (-1, self->provider_in_current_namespace, FALSE, - &self->provider_fd, error)) - return FALSE; + if (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK) + { + if (!glnx_opendirat (-1, self->provider_in_current_namespace, FALSE, + &self->provider_fd, error)) + return FALSE; - /* Path that, when resolved in the host namespace, points to the provider */ - self->provider_in_host_namespace = - pv_current_namespace_path_to_host_path (self->provider_in_current_namespace); + /* Path that, when resolved in the host namespace, points to the provider */ + self->provider_in_host_namespace = + pv_current_namespace_path_to_host_path (self->provider_in_current_namespace); + } /* If we are in a Flatpak environment we expect to have the host system * mounted in `/run/host`. Otherwise we assume that the host system, in the @@ -1788,7 +1791,11 @@ pv_runtime_get_capsule_capture_libs (PvRuntime *self, const gchar *ld_library_path; g_autofree gchar *remap_usr = NULL; g_autofree gchar *remap_lib = NULL; - FlatpakBwrap *ret = pv_bwrap_copy (self->container_access_adverb); + FlatpakBwrap *ret; + + g_return_val_if_fail (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK, NULL); + + ret = pv_bwrap_copy (self->container_access_adverb); /* If we have a custom "LD_LIBRARY_PATH", we want to preserve * it when calling capsule-capture-libs */ @@ -1835,6 +1842,8 @@ collect_s2tc (PvRuntime *self, s2tc, NULL); + g_return_val_if_fail (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK, FALSE); + if (g_file_test (s2tc_in_current_namespace, G_FILE_TEST_EXISTS)) { g_autoptr(FlatpakBwrap) temp_bwrap = NULL; @@ -1940,6 +1949,7 @@ pv_runtime_capture_libraries (PvRuntime *self, g_autoptr(FlatpakBwrap) temp_bwrap = NULL; gsize i; + g_return_val_if_fail (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK, FALSE); g_return_val_if_fail (runtime_architecture_check_valid (arch), FALSE); g_return_val_if_fail (destination != NULL, FALSE); g_return_val_if_fail (patterns != NULL, FALSE); @@ -2006,6 +2016,7 @@ bind_icd (PvRuntime *self, gsize dir_elements_after = 0; const gchar *subdir = requested_subdir; + g_return_val_if_fail (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK, FALSE); g_return_val_if_fail (runtime_architecture_check_valid (arch), FALSE); g_return_val_if_fail (subdir != NULL, FALSE); g_return_val_if_fail (details != NULL, FALSE); @@ -2235,8 +2246,9 @@ bind_runtime_base (PvRuntime *self, pv_environ_lock_env (container_env, "XDG_RUNTIME_DIR", xrd); - if (g_strcmp0 (self->provider_in_host_namespace, "/") != 0 - || g_strcmp0 (self->provider_in_container_namespace, "/run/host") != 0) + if ((self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK) + && (g_strcmp0 (self->provider_in_host_namespace, "/") != 0 + || g_strcmp0 (self->provider_in_container_namespace, "/run/host") != 0)) { g_autofree gchar *provider_etc = NULL; @@ -2293,7 +2305,8 @@ bind_runtime_base (PvRuntime *self, if (g_strv_contains (from_host, dest)) continue; - if (g_strv_contains (from_provider, dest)) + if ((self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK) + && g_strv_contains (from_provider, dest)) continue; full = g_build_filename (self->runtime_files, @@ -2392,34 +2405,37 @@ bind_runtime_base (PvRuntime *self, NULL); } - for (i = 0; from_provider[i] != NULL; i++) + if (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK) { - const char *item = from_provider[i]; - g_autoptr(GError) local_error = NULL; - g_autofree char *path_in_provider = NULL; - glnx_autofd int fd = -1; + for (i = 0; from_provider[i] != NULL; i++) + { + const char *item = from_provider[i]; + g_autoptr(GError) local_error = NULL; + g_autofree char *path_in_provider = NULL; + glnx_autofd int fd = -1; - fd = _srt_resolve_in_sysroot (self->provider_fd, item, - SRT_RESOLVE_FLAGS_NONE, - &path_in_provider, - &local_error); + fd = _srt_resolve_in_sysroot (self->provider_fd, item, + SRT_RESOLVE_FLAGS_NONE, + &path_in_provider, + &local_error); - if (fd >= 0) - { - g_autofree char *host_path = NULL; + if (fd >= 0) + { + g_autofree char *host_path = NULL; - host_path = g_build_filename (self->provider_in_host_namespace, - path_in_provider, NULL); - flatpak_bwrap_add_args (bwrap, - "--ro-bind", host_path, item, - NULL); - } - else - { - g_debug ("Cannot resolve \"%s\" in \"%s\": %s", - item, self->provider_in_current_namespace, - local_error->message); - g_clear_error (&local_error); + host_path = g_build_filename (self->provider_in_host_namespace, + path_in_provider, NULL); + flatpak_bwrap_add_args (bwrap, + "--ro-bind", host_path, item, + NULL); + } + else + { + g_debug ("Cannot resolve \"%s\" in \"%s\": %s", + item, self->provider_in_current_namespace, + local_error->message); + g_clear_error (&local_error); + } } } @@ -2513,6 +2529,7 @@ pv_runtime_take_from_provider (PvRuntime *self, GError **error) { g_return_val_if_fail (PV_IS_RUNTIME (self), FALSE); + g_return_val_if_fail (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK, FALSE); g_return_val_if_fail (bwrap == NULL || !pv_bwrap_was_finished (bwrap), FALSE); g_return_val_if_fail (bwrap != NULL || self->mutable_sysroot != NULL, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); @@ -2943,6 +2960,7 @@ pv_runtime_take_ld_so_from_provider (PvRuntime *self, g_autofree gchar *ld_so_relative_to_provider = NULL; g_autofree gchar *ld_so_in_provider = NULL; + g_return_val_if_fail (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK, FALSE); g_return_val_if_fail (bwrap != NULL || self->mutable_sysroot != NULL, FALSE); g_debug ("Making provider's ld.so visible in container"); @@ -3061,6 +3079,7 @@ setup_json_manifest (PvRuntime *self, gboolean need_provider_json = FALSE; gsize i; + g_return_val_if_fail (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK, FALSE); g_return_val_if_fail (bwrap != NULL || self->mutable_sysroot != NULL, FALSE); if (SRT_IS_VULKAN_LAYER (details->icd)) @@ -3205,6 +3224,7 @@ setup_each_json_manifest (PvRuntime *self, gsize j; g_autofree gchar *write_to_dir = NULL; + g_return_val_if_fail (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK, FALSE); g_return_val_if_fail (bwrap != NULL || self->mutable_sysroot != NULL, FALSE); write_to_dir = g_build_filename (self->overrides, @@ -3237,6 +3257,7 @@ collect_vulkan_layers (PvRuntime *self, { gsize j; + g_return_val_if_fail (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK, FALSE); g_return_val_if_fail (dependency_patterns != NULL, FALSE); g_return_val_if_fail (dir_name != NULL, FALSE); @@ -3358,8 +3379,6 @@ pv_runtime_get_ld_so (PvRuntime *self, { g_autoptr(FlatpakBwrap) temp_bwrap = NULL; g_autofree gchar *etc = NULL; - g_autofree gchar *provider_etc = NULL; - g_autofree gchar *provider_etc_dest = NULL; /* Do it the hard way, by asking a process running in the * container (or at least a container resembling the one we @@ -3384,22 +3403,28 @@ pv_runtime_get_ld_so (PvRuntime *self, "/etc", NULL); - if (!pv_bwrap_bind_usr (temp_bwrap, - self->provider_in_host_namespace, - self->provider_in_current_namespace, - self->provider_in_container_namespace, - error)) - return FALSE; + if (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK) + { + g_autofree gchar *provider_etc = NULL; + g_autofree gchar *provider_etc_dest = NULL; + + if (!pv_bwrap_bind_usr (temp_bwrap, + self->provider_in_host_namespace, + self->provider_in_current_namespace, + self->provider_in_container_namespace, + error)) + return FALSE; - provider_etc = g_build_filename (self->provider_in_host_namespace, - "etc", NULL); - provider_etc_dest = g_build_filename (self->provider_in_container_namespace, - "etc", NULL); - flatpak_bwrap_add_args (temp_bwrap, - "--ro-bind", - provider_etc, - provider_etc_dest, - NULL); + provider_etc = g_build_filename (self->provider_in_host_namespace, + "etc", NULL); + provider_etc_dest = g_build_filename (self->provider_in_container_namespace, + "etc", NULL); + flatpak_bwrap_add_args (temp_bwrap, + "--ro-bind", + provider_etc, + provider_etc_dest, + NULL); + } flatpak_bwrap_set_env (temp_bwrap, "PATH", "/usr/bin:/bin", TRUE); flatpak_bwrap_add_args (temp_bwrap, @@ -3508,6 +3533,7 @@ pv_runtime_collect_libc_family (PvRuntime *self, g_autoptr(FlatpakBwrap) temp_bwrap = NULL; g_autofree char *libc_target = NULL; + g_return_val_if_fail (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK, FALSE); g_return_val_if_fail (bwrap != NULL || self->mutable_sysroot != NULL, FALSE); if (!pv_runtime_take_ld_so_from_provider (self, arch, @@ -3621,6 +3647,8 @@ pv_runtime_collect_libdrm_data (PvRuntime *self, g_autofree char *target = NULL; target = glnx_readlinkat_malloc (-1, libdrm, NULL, NULL); + g_return_if_fail (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK); + if (target != NULL) { g_autofree gchar *dir = NULL; @@ -3672,6 +3700,7 @@ pv_runtime_finish_libdrm_data (PvRuntime *self, { g_autofree gchar *best_libdrm_data_in_provider = NULL; + g_return_val_if_fail (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK, FALSE); g_return_val_if_fail (bwrap != NULL || self->mutable_sysroot != NULL, FALSE); if (g_hash_table_size (libdrm_data_in_provider) > 0 && !all_libdrm_from_provider) @@ -3725,6 +3754,7 @@ pv_runtime_finish_libc_family (PvRuntime *self, GHashTableIter iter; const gchar *gconv_path; + g_return_val_if_fail (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK, FALSE); g_return_val_if_fail (bwrap != NULL || self->mutable_sysroot != NULL, FALSE); if (self->any_libc_from_provider && !self->all_libc_from_provider) @@ -3871,6 +3901,7 @@ pv_runtime_use_provider_graphics_stack (PvRuntime *self, g_strdup_printf ("%s/", self->provider_in_container_namespace); g_return_val_if_fail (PV_IS_RUNTIME (self), FALSE); + g_return_val_if_fail (self->flags & PV_RUNTIME_FLAGS_PROVIDER_GRAPHICS_STACK, FALSE); g_return_val_if_fail (bwrap != NULL || self->mutable_sysroot != NULL, FALSE); g_return_val_if_fail (bwrap == NULL || !pv_bwrap_was_finished (bwrap), FALSE); g_return_val_if_fail (container_env != NULL, FALSE); diff --git a/pressure-vessel/wrap.c b/pressure-vessel/wrap.c index fbe9436dc4600042d1c62f6016704cfef84a769f..1c86297deb184706b686d2a84c06baa328f29d92 100644 --- a/pressure-vessel/wrap.c +++ b/pressure-vessel/wrap.c @@ -970,7 +970,8 @@ opt_with_host_graphics_cb (const gchar *option_name, /* This is the old way to get the graphics from the host system */ if (g_strcmp0 (option_name, "--with-host-graphics") == 0) { - if (g_file_test ("/run/host", G_FILE_TEST_IS_DIR)) + if (g_file_test ("/run/host/usr", G_FILE_TEST_IS_DIR) + && g_file_test ("/run/host/etc", G_FILE_TEST_IS_DIR)) opt_graphics_provider = g_strdup ("/run/host"); else opt_graphics_provider = g_strdup ("/"); @@ -1074,7 +1075,7 @@ static GOptionEntry options[] = "and will be adjusted for use on the host system if pressure-vessel " "is run in a container. The empty string means use the graphics " "stack from container." - "[Default: $PRESSURE_VESSEL_GRAPHICS_PROVIDER or '/run/host' or '/']", "PATH" }, + "[Default: $PRESSURE_VESSEL_GRAPHICS_PROVIDER or '/']", "PATH" }, { "launcher", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_launcher, "Instead of specifying a command with its arguments to execute, all the " @@ -1431,12 +1432,25 @@ main (int argc, if (opt_graphics_provider == NULL) { /* Also check the deprecated 'PRESSURE_VESSEL_HOST_GRAPHICS' */ - if (!pv_boolean_environment ("PRESSURE_VESSEL_HOST_GRAPHICS", TRUE)) - opt_graphics_provider = g_strdup (""); - else if (g_file_test ("/run/host", G_FILE_TEST_IS_DIR)) - opt_graphics_provider = g_strdup ("/run/host"); + Tristate value = tristate_environment ("PRESSURE_VESSEL_HOST_GRAPHICS"); + + if (value == TRISTATE_MAYBE) + { + opt_graphics_provider = g_strdup ("/"); + } else - opt_graphics_provider = g_strdup ("/"); + { + g_warning ("$PRESSURE_VESSEL_HOST_GRAPHICS is deprecated, " + "please use PRESSURE_VESSEL_GRAPHICS_PROVIDER instead"); + + if (value == TRISTATE_NO) + opt_graphics_provider = g_strdup (""); + else if (g_file_test ("/run/host/usr", G_FILE_TEST_IS_DIR) + && g_file_test ("/run/host/etc", G_FILE_TEST_IS_DIR)) + opt_graphics_provider = g_strdup ("/run/host"); + else + opt_graphics_provider = g_strdup ("/"); + } } g_assert (opt_graphics_provider != NULL);