static void take_inhibit_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { GVariant *result = NULL; GError *error = NULL; GUnixFDList *fd_list; gint32 fd_index = 0; Context *context = (Context *)user_data; result = g_dbus_proxy_call_with_unix_fd_list_finish(context->proxy, &fd_list, res, &error); if (!result) { log_warn("Error taking lid inhibitor lock: %s", error->message); g_error_free(error); return; } g_variant_get(result, "(h)", &fd_index); context->state.lid_inhibit_fd = g_unix_fd_list_get(fd_list, fd_index, &error); if (context->state.lid_inhibit_fd == -1) { log_warn("Error getting file descriptor for lid inhibitor lock: %s", error->message); g_error_free(error); } g_variant_unref(result); g_object_unref(fd_list); }
static void inhibit_done (GObject *source, GAsyncResult *result, gpointer user_data) { GDBusProxy *sd_proxy = G_DBUS_PROXY (source); NMSleepMonitor *self = user_data; GError *error = NULL; GVariant *res; GUnixFDList *fd_list; res = g_dbus_proxy_call_with_unix_fd_list_finish (sd_proxy, &fd_list, result, &error); if (!res) { g_dbus_error_strip_remote_error (error); nm_log_warn (LOGD_SUSPEND, "Inhibit failed: %s", error->message); g_error_free (error); } else { if (!fd_list || g_unix_fd_list_get_length (fd_list) != 1) nm_log_warn (LOGD_SUSPEND, "Didn't get a single fd back"); self->inhibit_fd = g_unix_fd_list_get (fd_list, 0, NULL); nm_log_dbg (LOGD_SUSPEND, "Inhibitor fd is %d", self->inhibit_fd); g_object_unref (fd_list); g_variant_unref (res); } }
static GInputStream * g_vfs_icon_load (GLoadableIcon *icon, int size, char **type, GCancellable *cancellable, GError **error) { GVfsIcon *vfs_icon = G_VFS_ICON (icon); GVfsDBusMount *proxy; gboolean res; gboolean can_seek; GUnixFDList *fd_list; int fd; GVariant *fd_id_val = NULL; GError *local_error = NULL; proxy = create_proxy_for_icon (vfs_icon, cancellable, error); if (proxy == NULL) return NULL; res = gvfs_dbus_mount_call_open_icon_for_read_sync (proxy, vfs_icon->icon_id, NULL, &fd_id_val, &can_seek, &fd_list, cancellable, &local_error); if (! res) { if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy))); _g_propagate_error_stripped (error, local_error); } g_object_unref (proxy); if (! res) return NULL; if (fd_list == NULL || fd_id_val == NULL || g_unix_fd_list_get_length (fd_list) != 1 || (fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (fd_id_val), NULL)) == -1) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Didn't get stream file descriptor")); return NULL; } g_variant_unref (fd_id_val); g_object_unref (fd_list); return G_INPUT_STREAM (g_daemon_file_input_stream_new (fd, can_seek)); }
static gboolean fu_plugin_thunderbolt_power_bolt_force_power (FuPlugin *plugin, GError **error) { FuPluginData *data = fu_plugin_get_data (plugin); g_autoptr(GDBusConnection) connection = NULL; g_autoptr(GDBusProxy) proxy = NULL; g_autoptr(GUnixFDList) fds = NULL; g_autoptr(GVariant) val = NULL; GVariant *input; input = g_variant_new ("(ss)", "fwupd", /* who */ ""); /* flags */ connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error); if (connection == NULL) return FALSE; proxy = g_dbus_proxy_new_sync (connection, G_DBUS_PROXY_FLAGS_NONE, NULL, BOLT_DBUS_SERVICE, BOLT_DBUS_PATH, BOLT_DBUS_INTERFACE, NULL, error); if (proxy == NULL) return FALSE; val = g_dbus_proxy_call_with_unix_fd_list_sync (proxy, "ForcePower", input, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &fds, NULL, error); if (val == NULL) return FALSE; if (g_unix_fd_list_get_length (fds) != 1) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, "invalid number of file descriptors returned: %d", g_unix_fd_list_get_length (fds)); return FALSE; } data->bolt_fd = g_unix_fd_list_get (fds, 0, NULL); return TRUE; }
static VALUE unixfdlist_get(VALUE self, VALUE index) { GError *error = NULL; gint fd; fd = g_unix_fd_list_get(_SELF(self), RVAL2GINT(index), &error); if (fd == -1) rbgio_raise_error(error); /* TODO: This fd must be closed properly. How do we deal with that? */ return FD2RVAL(fd); }
static void set_running_settings (OfficeRunner *run, gboolean running) { if (running) { GVariant *ret; GUnixFDList *fd_list; gint idx; GError *error = NULL; if (run->lid_switch_fd != -1) { g_debug ("Already blocked"); return; } g_debug ("Blocking lid action"); ret = g_dbus_connection_call_with_unix_fd_list_sync (run->connection, LOGIND_DBUS_NAME, LOGIND_DBUS_PATH, LOGIND_DBUS_INTERFACE, "Inhibit", g_variant_new ("(ssss)", "handle-lid-switch", g_get_user_name(), _("Office Runner is running"), "block"), NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &fd_list, NULL, &error); if (ret == NULL) g_error ("Failed to inhibit: %s", error->message); g_variant_get (ret, "(h)", &idx); run->lid_switch_fd = g_unix_fd_list_get (fd_list, idx, NULL); g_object_unref (fd_list); g_variant_unref (ret); } else { if (run->lid_switch_fd != -1) { close (run->lid_switch_fd); run->lid_switch_fd = -1; g_debug ("Unblocking lid action"); } else { g_debug ("Already released the blocking inhibitor"); } } }
/* see gdbus-example-server.c for the server implementation */ static gint get_server_stdout (GDBusConnection *connection, const gchar *name_owner, GError **error) { GDBusMessage *method_call_message; GDBusMessage *method_reply_message; GUnixFDList *fd_list; gint fd; fd = -1; method_call_message = NULL; method_reply_message = NULL; method_call_message = g_dbus_message_new_method_call (name_owner, "/org/gtk/GDBus/TestObject", "org.gtk.GDBus.TestInterface", "GimmeStdout"); method_reply_message = g_dbus_connection_send_message_with_reply_sync (connection, method_call_message, -1, NULL, /* out_serial */ NULL, /* cancellable */ error); if (method_reply_message == NULL) goto out; if (g_dbus_message_get_message_type (method_reply_message) == G_DBUS_MESSAGE_TYPE_ERROR) { g_dbus_message_to_gerror (method_reply_message, error); goto out; } fd_list = g_dbus_message_get_unix_fd_list (method_reply_message); fd = g_unix_fd_list_get (fd_list, 0, error); out: g_object_unref (method_call_message); g_object_unref (method_reply_message); return fd; }
static void open_icon_read_cb (GVfsDBusMount *proxy, GAsyncResult *res, gpointer user_data) { AsyncPathCall *data = user_data; GError *error = NULL; gboolean can_seek; GUnixFDList *fd_list; int fd; GVariant *fd_id_val; guint fd_id; GFileInputStream *stream; if (! gvfs_dbus_mount_call_open_icon_for_read_finish (proxy, &fd_id_val, &can_seek, &fd_list, res, &error)) { _g_simple_async_result_take_error_stripped (data->result, error); goto out; } fd_id = g_variant_get_handle (fd_id_val); g_variant_unref (fd_id_val); if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1 || (fd = g_unix_fd_list_get (fd_list, fd_id, NULL)) == -1) { g_simple_async_result_set_error (data->result, G_IO_ERROR, G_IO_ERROR_FAILED, _("Couldn't get stream file descriptor")); } else { stream = g_daemon_file_input_stream_new (fd, can_seek); g_simple_async_result_set_op_res_gpointer (data->result, stream, g_object_unref); g_object_unref (fd_list); } out: _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable); _g_dbus_async_unsubscribe_cancellable (data->cancellable, data->cancelled_tag); async_path_call_free (data); }
static gboolean handle_trash_file (XdpTrash *object, GDBusMethodInvocation *invocation, GUnixFDList *fd_list, GVariant *arg_fd) { Request *request = request_from_invocation (invocation); int idx, fd; guint result; REQUEST_AUTOLOCK (request); g_variant_get (arg_fd, "h", &idx); fd = g_unix_fd_list_get (fd_list, idx, NULL); result = trash_file (request->app_info, request->sender, fd); xdp_trash_complete_trash_file (object, invocation, NULL, result); return TRUE; }
/** * udisks_daemon_util_inhibit_system_sync: * @reason: A human readable explanation of why the system is being inhibited. * * Tries to inhibit the system. * * Right now only * <ulink url="http://www.freedesktop.org/wiki/Software/systemd/inhibit">systemd</ulink> * inhibitors are supported but other inhibitors can be added in the future. * * Returns: A cookie that can be used with udisks_daemon_util_uninhibit_system_sync(). */ UDisksInhibitCookie * udisks_daemon_util_inhibit_system_sync (const gchar *reason) { #ifdef HAVE_LIBSYSTEMD_LOGIN UDisksInhibitCookie *ret = NULL; GDBusConnection *connection = NULL; GVariant *value = NULL; GUnixFDList *fd_list = NULL; gint32 index = -1; GError *error = NULL; g_return_val_if_fail (reason != NULL, NULL); connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); if (connection == NULL) { udisks_error ("Error getting system bus: %s (%s, %d)", error->message, g_quark_to_string (error->domain), error->code); g_clear_error (&error); goto out; } value = g_dbus_connection_call_with_unix_fd_list_sync (connection, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "Inhibit", g_variant_new ("(ssss)", "sleep:shutdown:idle", /* what */ "Disk Manager", /* who */ reason, /* why */ "block"), /* mode */ G_VARIANT_TYPE ("(h)"), G_DBUS_CALL_FLAGS_NONE, -1, /* default timeout */ NULL, /* fd_list */ &fd_list, /* out_fd_list */ NULL, /* GCancellable */ &error); if (value == NULL) { udisks_error ("Error inhibiting: %s (%s, %d)", error->message, g_quark_to_string (error->domain), error->code); g_clear_error (&error); goto out; } g_variant_get (value, "(h)", &index); g_assert (index >= 0 && index < g_unix_fd_list_get_length (fd_list)); ret = g_new0 (UDisksInhibitCookie, 1); ret->magic = 0xdeadbeef; ret->fd = g_unix_fd_list_get (fd_list, index, &error); if (ret->fd == -1) { udisks_error ("Error getting fd: %s (%s, %d)", error->message, g_quark_to_string (error->domain), error->code); g_clear_error (&error); g_free (ret); ret = NULL; goto out; } out: if (value != NULL) g_variant_unref (value); g_clear_object (&fd_list); g_clear_object (&connection); return ret; #else /* non-systemd: just return a dummy pointer */ g_return_val_if_fail (reason != NULL, NULL); return (UDisksInhibitCookie* ) &udisks_daemon_util_inhibit_system_sync; #endif }
/* runs in thread dedicated to handling @invocation */ static gboolean handle_loop_setup (StoragedManager *object, GDBusMethodInvocation *invocation, GUnixFDList *fd_list, GVariant *fd_index, GVariant *options) { StoragedLinuxManager *manager = STORAGED_LINUX_MANAGER (object); GError *error; gint fd_num; gint fd = -1; gchar proc_path[64]; gchar path[8192]; ssize_t path_len; gint loop_fd = -1; gint loop_control_fd = -1; gint allocated_loop_number = -1; gchar *loop_device = NULL; struct loop_info64 li64; StoragedObject *loop_object = NULL; gboolean option_read_only = FALSE; gboolean option_no_part_scan = FALSE; guint64 option_offset = 0; guint64 option_size = 0; uid_t caller_uid; struct stat fd_statbuf; gboolean fd_statbuf_valid = FALSE; WaitForLoopData wait_data; /* we need the uid of the caller for the loop file */ error = NULL; if (!storaged_daemon_util_get_caller_uid_sync (manager->daemon, invocation, NULL /* GCancellable */, &caller_uid, NULL, NULL, &error)) { g_dbus_method_invocation_return_gerror (invocation, error); g_error_free (error); goto out; } /* Check if the user is authorized to create a loop device */ if (!storaged_daemon_util_check_authorization_sync (manager->daemon, NULL, "org.storaged.Storaged.loop-setup", options, /* Translators: Shown in authentication dialog when the user * requests setting up a loop device. */ N_("Authentication is required to set up a loop device"), invocation)) goto out; fd_num = g_variant_get_handle (fd_index); if (fd_list == NULL || fd_num >= g_unix_fd_list_get_length (fd_list)) { g_dbus_method_invocation_return_error (invocation, STORAGED_ERROR, STORAGED_ERROR_FAILED, "Expected to use fd at index %d, but message has only %d fds", fd_num, fd_list == NULL ? 0 : g_unix_fd_list_get_length (fd_list)); goto out; } error = NULL; fd = g_unix_fd_list_get (fd_list, fd_num, &error); if (fd == -1) { g_prefix_error (&error, "Error getting file descriptor %d from message: ", fd_num); g_dbus_method_invocation_take_error (invocation, error); goto out; } snprintf (proc_path, sizeof (proc_path), "/proc/%d/fd/%d", getpid (), fd); path_len = readlink (proc_path, path, sizeof (path) - 1); if (path_len < 1) { g_dbus_method_invocation_return_error (invocation, STORAGED_ERROR, STORAGED_ERROR_FAILED, "Error determing path: %m"); goto out; } path[path_len] = '\0'; g_variant_lookup (options, "read-only", "b", &option_read_only); g_variant_lookup (options, "offset", "t", &option_offset); g_variant_lookup (options, "size", "t", &option_size); g_variant_lookup (options, "no-part-scan", "b", &option_no_part_scan); /* it's not a problem if fstat fails... for example, this can happen if the user * passes a fd to a file on the GVfs fuse mount */ if (fstat (fd, &fd_statbuf) == 0) fd_statbuf_valid = TRUE; /* serialize access to /dev/loop-control */ g_mutex_lock (&(manager->lock)); loop_control_fd = open ("/dev/loop-control", O_RDWR); if (loop_control_fd == -1) { g_dbus_method_invocation_return_error (invocation, STORAGED_ERROR, STORAGED_ERROR_FAILED, "Error opening /dev/loop-control: %m"); g_mutex_unlock (&(manager->lock)); goto out; } allocated_loop_number = ioctl (loop_control_fd, LOOP_CTL_GET_FREE); if (allocated_loop_number < 0) { g_dbus_method_invocation_return_error (invocation, STORAGED_ERROR, STORAGED_ERROR_FAILED, "Error allocating free loop device: %m"); g_mutex_unlock (&(manager->lock)); goto out; } loop_device = g_strdup_printf ("/dev/loop%d", allocated_loop_number); loop_fd = open (loop_device, option_read_only ? O_RDONLY : O_RDWR); if (loop_fd == -1) { g_dbus_method_invocation_return_error (invocation, STORAGED_ERROR, STORAGED_ERROR_FAILED, "Cannot open %s: %m", loop_device); g_mutex_unlock (&(manager->lock)); goto out; } /* update the loop file - need to do this before getting the uevent for the device */ storaged_state_add_loop (storaged_daemon_get_state (manager->daemon), loop_device, path, fd_statbuf_valid ? fd_statbuf.st_dev : 0, caller_uid); memset (&li64, '\0', sizeof (li64)); strncpy ((char *) li64.lo_file_name, path, LO_NAME_SIZE - 1); if (option_read_only) li64.lo_flags |= LO_FLAGS_READ_ONLY; if (!option_no_part_scan) li64.lo_flags |= 8; /* Use LO_FLAGS_PARTSCAN when 3.2 has been out for a while */ li64.lo_offset = option_offset; li64.lo_sizelimit = option_size; if (ioctl (loop_fd, LOOP_SET_FD, fd) < 0 || ioctl (loop_fd, LOOP_SET_STATUS64, &li64) < 0) { g_dbus_method_invocation_return_error (invocation, STORAGED_ERROR, STORAGED_ERROR_FAILED, "Error setting up loop device %s: %m", loop_device); g_mutex_unlock (&(manager->lock)); goto out; } g_mutex_unlock (&(manager->lock)); /* Determine the resulting object */ error = NULL; wait_data.loop_device = loop_device; wait_data.path = path; loop_object = storaged_daemon_wait_for_object_sync (manager->daemon, wait_for_loop_object, &wait_data, NULL, 10, /* timeout_seconds */ &error); if (loop_object == NULL) { g_prefix_error (&error, "Error waiting for loop object after creating %s", loop_device); g_dbus_method_invocation_take_error (invocation, error); goto out; } storaged_notice ("Set up loop device %s (backed by %s)", loop_device, path); storaged_manager_complete_loop_setup (object, invocation, NULL, /* fd_list */ g_dbus_object_get_object_path (G_DBUS_OBJECT (loop_object))); out: if (loop_object != NULL) g_object_unref (loop_object); g_free (loop_device); if (loop_control_fd != -1) close (loop_control_fd); if (loop_fd != -1) close (loop_fd); if (fd != -1) close (fd); return TRUE; /* returning TRUE means that we handled the method invocation */ }