diff --git a/common/flatpak-run.c b/common/flatpak-run.c index c13a2740..3e13a1a6 100644 --- a/common/flatpak-run.c +++ b/common/flatpak-run.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #ifdef ENABLE_SECCOMP #include @@ -48,6 +50,7 @@ #include "flatpak-utils.h" #include "flatpak-dir.h" #include "flatpak-systemd-dbus.h" +#include "document-portal/xdp-dbus.h" #define DEFAULT_SHELL "/bin/sh" @@ -4175,6 +4178,104 @@ child_setup (gpointer user_data) fcntl (g_array_index (fd_array, int, i), F_SETFD, 0); } +static gboolean +forward_file (XdpDbusDocuments *documents, + const char *app_id, + const char *file, + char **out_doc_id, + GError **error) +{ + int fd, fd_id; + g_autofree char *doc_id; + g_autoptr(GUnixFDList) fd_list = NULL; + const char *perms[] = { "read", "write", NULL }; + + fd = open (file, O_PATH | O_CLOEXEC); + if (fd == -1) + return flatpak_fail (error, "Failed to open '%s'", file); + + fd_list = g_unix_fd_list_new (); + fd_id = g_unix_fd_list_append (fd_list, fd, error); + close (fd); + + if (!xdp_dbus_documents_call_add_sync (documents, + g_variant_new ("h", fd_id), + TRUE, /* reuse */ + FALSE, /* not persistent */ + fd_list, + &doc_id, + NULL, + NULL, + error)) + return FALSE; + + if (!xdp_dbus_documents_call_grant_permissions_sync (documents, + doc_id, + app_id, + perms, + NULL, + error)) + return FALSE; + + *out_doc_id = g_steal_pointer (&doc_id); + + return TRUE; +} + +static gboolean +add_rest_args (const char *app_id, + gboolean file_forwarding, + GPtrArray *argv_array, + char *args[], + int n_args, + GError **error) +{ + g_autoptr(XdpDbusDocuments) documents = NULL; + g_autofree char *mountpoint = NULL; + gboolean forwarding = FALSE; + int i; + + documents = xdp_dbus_documents_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, 0, + "org.freedesktop.portal.Documents", + "/org/freedesktop/portal/documents", + NULL, + error); + if (documents == NULL) + return FALSE; + + if (!xdp_dbus_documents_call_get_mount_point_sync (documents, &mountpoint, NULL, error)) + return FALSE; + + for (i = 0; i < n_args; i++) + { + if (file_forwarding && strcmp (args[i], "@@") == 0) + { + forwarding = !forwarding; + continue; + } + + if (forwarding) + { + g_autofree char *doc_id = NULL; + g_autofree char *basename = NULL; + char *doc_path; + + if (!forward_file (documents, app_id, args[i], &doc_id, error)) + return FALSE; + + basename = g_path_get_basename (args[i]); + doc_path = g_build_filename (mountpoint, doc_id, basename, NULL); + + g_debug ("Forwarding file '%s' as '%s' to %s", args[i], doc_path, app_id); + + g_ptr_array_add (argv_array, doc_path); + } + else + g_ptr_array_add (argv_array, g_strdup (args[i])); + } + + return TRUE; +} gboolean flatpak_run_app (const char *app_ref, @@ -4210,6 +4311,7 @@ flatpak_run_app (const char *app_ref, g_autoptr(FlatpakContext) app_context = NULL; g_autoptr(FlatpakContext) overrides = NULL; g_auto(GStrv) app_ref_parts = NULL; + g_autofree char *commandline = NULL; app_ref_parts = flatpak_decompose_ref (app_ref, error); if (app_ref_parts == NULL) @@ -4390,11 +4492,15 @@ flatpak_run_app (const char *app_ref, } g_ptr_array_add (real_argv_array, g_strdup (command)); - for (i = 0; i < n_args; i++) - g_ptr_array_add (real_argv_array, g_strdup (args[i])); + if (!add_rest_args (app_ref_parts[1], (flags & FLATPAK_RUN_FLAG_FILE_FORWARDING) != 0, + real_argv_array, args, n_args, error)) + return FALSE; g_ptr_array_add (real_argv_array, NULL); + commandline = flatpak_quote_argv ((const char **) real_argv_array->pdata); + g_debug ("Running '%s'", commandline); + if ((flags & FLATPAK_RUN_FLAG_BACKGROUND) != 0) { if (!g_spawn_async (NULL, diff --git a/common/flatpak-run.h b/common/flatpak-run.h index b7304231..e81a0518 100644 --- a/common/flatpak-run.h +++ b/common/flatpak-run.h @@ -85,6 +85,7 @@ typedef enum { FLATPAK_RUN_FLAG_NO_SESSION_BUS_PROXY = (1 << 7), FLATPAK_RUN_FLAG_NO_SYSTEM_BUS_PROXY = (1 << 8), FLATPAK_RUN_FLAG_SET_PERSONALITY = (1 << 9), + FLATPAK_RUN_FLAG_FILE_FORWARDING = (1 << 10), } FlatpakRunFlags; gboolean flatpak_run_add_extension_args (GPtrArray *argv_array,