static void portal_job_complete (GtkPrintJob *job, gpointer data, const GError *error) { GtkPrintOperation *op = data; GtkPrintOperationPortal *op_portal = op->priv->platform_data; GtkPrintSettings *settings; const char *uri; char *filename; int fd, idx; GVariantBuilder opt_builder; GUnixFDList *fd_list; if (error != NULL && op->priv->error == NULL) { g_warning ("Print job failed: %s", error->message); op->priv->error = g_error_copy (error); return; } op_portal->file_written = TRUE; settings = gtk_print_job_get_settings (job); uri = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_URI); filename = g_filename_from_uri (uri, NULL, NULL); fd = open (filename, O_RDONLY|O_CLOEXEC); fd_list = g_unix_fd_list_new (); idx = g_unix_fd_list_append (fd_list, fd, NULL); close (fd); g_free (filename); g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT); g_variant_builder_add (&opt_builder, "{sv}", "token", g_variant_new_uint32 (op_portal->token)); g_dbus_proxy_call_with_unix_fd_list (op_portal->proxy, "Print", g_variant_new ("(ssh@a{sv})", "", /* window */ _("Print"), /* title */ idx, g_variant_builder_end (&opt_builder)), G_DBUS_CALL_FLAGS_NONE, -1, fd_list, NULL, print_file_done, op); g_object_unref (fd_list); }
static gboolean get_modifiers_variant (const char *set_refspec, const char *set_revision, const char *const* install_pkgs, const char *const* uninstall_pkgs, const char *const* override_replace_pkgs, const char *const* override_remove_pkgs, const char *const* override_reset_pkgs, GVariant **out_modifiers, GUnixFDList **out_fd_list, GError **error) { GVariantDict dict; g_variant_dict_init (&dict, NULL); g_autoptr(GUnixFDList) fd_list = g_unix_fd_list_new (); if (install_pkgs) { if (!vardict_sort_and_insert_pkgs (&dict, "install", fd_list, install_pkgs, error)) return FALSE; } if (override_replace_pkgs) { if (!vardict_sort_and_insert_pkgs (&dict, "override-replace", fd_list, override_replace_pkgs, error)) return FALSE; } if (set_refspec) g_variant_dict_insert (&dict, "set-refspec", "s", set_refspec); if (set_revision) g_variant_dict_insert (&dict, "set-revision", "s", set_revision); vardict_insert_strv (&dict, "uninstall-packages", uninstall_pkgs); vardict_insert_strv (&dict, "override-remove-packages", override_remove_pkgs); vardict_insert_strv (&dict, "override-reset-packages", override_reset_pkgs); *out_fd_list = g_steal_pointer (&fd_list); *out_modifiers = g_variant_ref_sink (g_variant_dict_end (&dict)); return TRUE; }
static VALUE unixfdlist_initialize(int argc, VALUE *argv, VALUE self) { VALUE rbfds; gint i, n_fds; gint *fds; rb_scan_args(argc, argv, "0*", &rbfds); n_fds = RARRAY_LEN(rbfds); if (n_fds == 0) { G_INITIALIZE(self, g_unix_fd_list_new()); return Qnil; } fds = ALLOCA_N(gint, n_fds); for (i = 0; i < n_fds; i++) fds[0] = RVAL2FD(RARRAY_PTR(rbfds)[i]); G_INITIALIZE(self, g_unix_fd_list_new_from_array(fds, n_fds)); return Qnil; }
static VALUE unixfdlist_initialize(int argc, VALUE *argv, VALUE self) { VALUE rbfds; long n; gint *fds; GUnixFDList *list; rb_scan_args(argc, argv, "0*", &rbfds); fds = RVAL2FDS(rbfds, &n); if (n == 0) { G_INITIALIZE(self, g_unix_fd_list_new()); return Qnil; } list = g_unix_fd_list_new_from_array(fds, n); g_free(fds); G_INITIALIZE(self, list); return Qnil; }
gboolean builder_host_spawnv (GFile *dir, char **output, GError **error, const gchar * const *argv) { guint32 client_pid; GVariantBuilder *fd_builder = g_variant_builder_new (G_VARIANT_TYPE("a{uh}")); GVariantBuilder *env_builder = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); g_autoptr(GUnixFDList) fd_list = g_unix_fd_list_new (); gint stdout_handle, stdin_handle, stderr_handle; g_autoptr(GDBusConnection) connection = NULL; g_autoptr(GVariant) ret = NULL; g_autoptr(GMainLoop) loop = NULL; g_auto(GStrv) env_vars = NULL; guint subscription; HostCommandCallData data = { NULL }; guint sigterm_id = 0, sigint_id = 0; g_autofree gchar *commandline = NULL; g_autoptr(GOutputStream) out = NULL; int pipefd[2]; int i; commandline = flatpak_quote_argv ((const char **) argv); g_debug ("Running '%s' on host", commandline); connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error); if (connection == NULL) return FALSE; loop = g_main_loop_new (NULL, FALSE); data.connection = connection; data.loop = loop; data.refs = 1; subscription = g_dbus_connection_signal_subscribe (connection, NULL, "org.freedesktop.Flatpak.Development", "HostCommandExited", "/org/freedesktop/Flatpak/Development", NULL, G_DBUS_SIGNAL_FLAGS_NONE, host_command_exited_cb, &data, NULL); stdin_handle = g_unix_fd_list_append (fd_list, 0, error); if (stdin_handle == -1) return FALSE; if (output) { g_autoptr(GInputStream) in = NULL; if (pipe2 (pipefd, O_CLOEXEC) != 0) { glnx_set_error_from_errno (error); return FALSE; } data.refs++; in = g_unix_input_stream_new (pipefd[0], TRUE); out = g_memory_output_stream_new_resizable (); g_output_stream_splice_async (out, in, G_OUTPUT_STREAM_SPLICE_NONE, 0, NULL, output_spliced_cb, &data); stdout_handle = g_unix_fd_list_append (fd_list, pipefd[1], error); close (pipefd[1]); if (stdout_handle == -1) return FALSE; } else { stdout_handle = g_unix_fd_list_append (fd_list, 1, error); if (stdout_handle == -1) return FALSE; } stderr_handle = g_unix_fd_list_append (fd_list, 2, error); if (stderr_handle == -1) return FALSE; g_variant_builder_add (fd_builder, "{uh}", 0, stdin_handle); g_variant_builder_add (fd_builder, "{uh}", 1, stdout_handle); g_variant_builder_add (fd_builder, "{uh}", 2, stderr_handle); env_vars = g_listenv (); for (i = 0; env_vars[i] != NULL; i++) { const char *env_var = env_vars[i]; g_variant_builder_add (env_builder, "{ss}", env_var, g_getenv (env_var)); } sigterm_id = g_unix_signal_add (SIGTERM, sigterm_handler, &data); sigint_id = g_unix_signal_add (SIGINT, sigint_handler, &data); ret = g_dbus_connection_call_with_unix_fd_list_sync (connection, "org.freedesktop.Flatpak", "/org/freedesktop/Flatpak/Development", "org.freedesktop.Flatpak.Development", "HostCommand", g_variant_new ("(^ay^aay@a{uh}@a{ss}u)", dir ? flatpak_file_get_path_cached (dir) : "", argv, g_variant_builder_end (fd_builder), g_variant_builder_end (env_builder), FLATPAK_HOST_COMMAND_FLAGS_CLEAR_ENV), G_VARIANT_TYPE ("(u)"), G_DBUS_CALL_FLAGS_NONE, -1, fd_list, NULL, NULL, error); if (ret == NULL) return FALSE; g_variant_get (ret, "(u)", &client_pid); data.client_pid = client_pid; g_main_loop_run (loop); g_source_remove (sigterm_id); g_source_remove (sigint_id); g_dbus_connection_signal_unsubscribe (connection, subscription); if (!g_spawn_check_exit_status (data.exit_status, error)) return FALSE; if (out) { if (data.splice_error) { g_propagate_error (error, data.splice_error); return FALSE; } /* Null terminate */ g_output_stream_write (out, "\0", 1, NULL, NULL); g_output_stream_close (out, NULL, NULL); *output = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (out)); } return TRUE; }
/** * fu_util_refresh_internal: **/ static gboolean fu_util_refresh_internal (FuUtilPrivate *priv, const gchar *data_fn, const gchar *sig_fn, GError **error) { GVariant *body; gint fd; gint fd_sig; _cleanup_object_unref_ GDBusMessage *request = NULL; _cleanup_object_unref_ GUnixFDList *fd_list = NULL; /* open file */ fd = open (data_fn, O_RDONLY); if (fd < 0) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "failed to open %s", data_fn); return FALSE; } fd_sig = open (sig_fn, O_RDONLY); if (fd_sig < 0) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "failed to open %s", sig_fn); return FALSE; } /* set out of band file descriptor */ fd_list = g_unix_fd_list_new (); g_unix_fd_list_append (fd_list, fd, NULL); g_unix_fd_list_append (fd_list, fd_sig, NULL); request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE, FWUPD_DBUS_PATH, FWUPD_DBUS_INTERFACE, "UpdateMetadata"); g_dbus_message_set_unix_fd_list (request, fd_list); /* g_unix_fd_list_append did a dup() already */ close (fd); close (fd_sig); /* send message */ body = g_variant_new ("(hh)", fd, fd_sig); g_dbus_message_set_body (request, body); g_dbus_connection_send_message_with_reply (priv->conn, request, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, fu_util_update_cb, priv); g_main_loop_run (priv->loop); if (priv->message == NULL) { g_dbus_error_strip_remote_error (priv->error); g_propagate_error (error, priv->error); return FALSE; } if (g_dbus_message_to_gerror (priv->message, error)) { g_dbus_error_strip_remote_error (*error); return FALSE; } return TRUE; }
/** * fu_util_get_details: **/ static gboolean fu_util_get_details (FuUtilPrivate *priv, gchar **values, GError **error) { GVariant *body; GVariant *val; gint fd; gint retval; _cleanup_object_unref_ GDBusMessage *message = NULL; _cleanup_object_unref_ GDBusMessage *request = NULL; _cleanup_object_unref_ GUnixFDList *fd_list = NULL; /* check args */ if (g_strv_length (values) != 1) { g_set_error_literal (error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL, "Invalid arguments: expected 'filename'"); return FALSE; } /* open file */ fd = open (values[0], O_RDONLY); if (fd < 0) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "failed to open %s", values[0]); return FALSE; } /* set out of band file descriptor */ fd_list = g_unix_fd_list_new (); retval = g_unix_fd_list_append (fd_list, fd, NULL); g_assert (retval != -1); request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE, FWUPD_DBUS_PATH, FWUPD_DBUS_INTERFACE, "GetDetails"); g_dbus_message_set_unix_fd_list (request, fd_list); /* g_unix_fd_list_append did a dup() already */ close (fd); /* send message */ body = g_variant_new ("(h)", fd > -1 ? 0 : -1); g_dbus_message_set_body (request, body); message = g_dbus_connection_send_message_with_reply_sync (priv->conn, request, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, error); if (message == NULL) { g_dbus_error_strip_remote_error (*error); return FALSE; } if (g_dbus_message_to_gerror (message, error)) { g_dbus_error_strip_remote_error (*error); return FALSE; } /* print results */ val = g_dbus_message_get_body (message); fu_util_print_metadata (val); return TRUE; }
/** * fu_util_install_internal: **/ static gboolean fu_util_install_internal (FuUtilPrivate *priv, const gchar *id, const gchar *filename, GError **error) { GVariant *body; GVariantBuilder builder; gint retval; gint fd; _cleanup_object_unref_ GDBusMessage *request = NULL; _cleanup_object_unref_ GUnixFDList *fd_list = NULL; /* set options */ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); g_variant_builder_add (&builder, "{sv}", "reason", g_variant_new_string ("user-action")); g_variant_builder_add (&builder, "{sv}", "filename", g_variant_new_string (filename)); if (priv->flags & FU_PROVIDER_UPDATE_FLAG_OFFLINE) { g_variant_builder_add (&builder, "{sv}", "offline", g_variant_new_boolean (TRUE)); } if (priv->flags & FU_PROVIDER_UPDATE_FLAG_ALLOW_OLDER) { g_variant_builder_add (&builder, "{sv}", "allow-older", g_variant_new_boolean (TRUE)); } if (priv->flags & FU_PROVIDER_UPDATE_FLAG_ALLOW_REINSTALL) { g_variant_builder_add (&builder, "{sv}", "allow-reinstall", g_variant_new_boolean (TRUE)); } /* open file */ fd = open (filename, O_RDONLY); if (fd < 0) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "failed to open %s", filename); return FALSE; } /* set out of band file descriptor */ fd_list = g_unix_fd_list_new (); retval = g_unix_fd_list_append (fd_list, fd, NULL); g_assert (retval != -1); request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE, FWUPD_DBUS_PATH, FWUPD_DBUS_INTERFACE, "Install"); g_dbus_message_set_unix_fd_list (request, fd_list); /* g_unix_fd_list_append did a dup() already */ close (fd); /* send message */ body = g_variant_new ("(sha{sv})", id, fd > -1 ? 0 : -1, &builder); g_dbus_message_set_body (request, body); g_dbus_connection_send_message_with_reply (priv->conn, request, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, fu_util_update_cb, priv); g_main_loop_run (priv->loop); if (priv->message == NULL) { g_dbus_error_strip_remote_error (priv->error); g_propagate_error (error, priv->error); return FALSE; } if (g_dbus_message_to_gerror (priv->message, error)) { g_dbus_error_strip_remote_error (*error); return FALSE; } /* TRANSLATORS: update completed, no errors */ g_print ("%s\n", _("Done!")); return TRUE; }
static void handle_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { if (g_strcmp0 (method_name, "HelloWorld") == 0) { const gchar *greeting; g_variant_get (parameters, "(&s)", &greeting); if (g_strcmp0 (greeting, "Return Unregistered") == 0) { g_dbus_method_invocation_return_error (invocation, G_IO_ERROR, G_IO_ERROR_FAILED_HANDLED, "As requested, here's a GError not registered (G_IO_ERROR_FAILED_HANDLED)"); } else if (g_strcmp0 (greeting, "Return Registered") == 0) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_NOT_FOUND, "As requested, here's a GError that is registered (G_DBUS_ERROR_MATCH_RULE_NOT_FOUND)"); } else if (g_strcmp0 (greeting, "Return Raw") == 0) { g_dbus_method_invocation_return_dbus_error (invocation, "org.gtk.GDBus.SomeErrorName", "As requested, here's a raw D-Bus error"); } else { gchar *response; response = g_strdup_printf ("You greeted me with '%s'. Thanks!", greeting); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", response)); g_free (response); } } else if (g_strcmp0 (method_name, "EmitSignal") == 0) { GError *local_error; gdouble speed_in_mph; gchar *speed_as_string; g_variant_get (parameters, "(d)", &speed_in_mph); speed_as_string = g_strdup_printf ("%g mph!", speed_in_mph); local_error = NULL; g_dbus_connection_emit_signal (connection, NULL, object_path, interface_name, "VelocityChanged", g_variant_new ("(ds)", speed_in_mph, speed_as_string), &local_error); g_assert_no_error (local_error); g_free (speed_as_string); g_dbus_method_invocation_return_value (invocation, NULL); } else if (g_strcmp0 (method_name, "GimmeStdout") == 0) { #ifdef G_OS_UNIX if (g_dbus_connection_get_capabilities (connection) & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING) { GDBusMessage *reply; GUnixFDList *fd_list; GError *error; fd_list = g_unix_fd_list_new (); error = NULL; g_unix_fd_list_append (fd_list, STDOUT_FILENO, &error); g_assert_no_error (error); reply = g_dbus_message_new_method_reply (g_dbus_method_invocation_get_message (invocation)); g_dbus_message_set_unix_fd_list (reply, fd_list); error = NULL; g_dbus_connection_send_message (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, /* out_serial */ &error); g_assert_no_error (error); g_object_unref (invocation); g_object_unref (fd_list); g_object_unref (reply); } else { g_dbus_method_invocation_return_dbus_error (invocation, "org.gtk.GDBus.Failed", "Your message bus daemon does not support file descriptor passing (need D-Bus >= 1.3.0)"); } #else g_dbus_method_invocation_return_dbus_error (invocation, "org.gtk.GDBus.NotOnUnix", "Your OS does not support file descriptor passing"); #endif } }