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 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 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 terminal_receiver_impl_exec (TerminalReceiver *receiver, GDBusMethodInvocation *invocation, GUnixFDList *fd_list, GVariant *options, GVariant *arguments) { TerminalReceiverImpl *impl = TERMINAL_RECEIVER_IMPL (receiver); TerminalReceiverImplPrivate *priv = impl->priv; const char *working_directory; gboolean shell; char **exec_argv, **envv; gsize exec_argc; GVariant *fd_array; GError *error; if (priv->screen == NULL) { g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Terminal already closed"); goto out; } if (!g_variant_lookup (options, "cwd", "^&ay", &working_directory)) working_directory = NULL; if (!g_variant_lookup (options, "shell", "b", &shell)) shell = FALSE; if (!g_variant_lookup (options, "environ", "^a&ay", &envv)) envv = NULL; if (!g_variant_lookup (options, "fd-set", "@a(ih)", &fd_array)) fd_array = NULL; /* Check FD passing */ if ((fd_list != NULL) ^ (fd_array != NULL)) { g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Must pass both fd-set options and a FD list"); goto out; } if (fd_list != NULL && fd_array != NULL) { const int *fd_array_data; gsize fd_array_data_len, i; int n_fds; fd_array_data = g_variant_get_fixed_array (fd_array, &fd_array_data_len, 2 * sizeof (int)); n_fds = g_unix_fd_list_get_length (fd_list); for (i = 0; i < fd_array_data_len; i++) { const int fd = fd_array_data[2 * i]; const int idx = fd_array_data[2 * i + 1]; if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Passing of std%s not supported", fd == STDIN_FILENO ? "in" : fd == STDOUT_FILENO ? "out" : "err"); goto out; } if (idx < 0 || idx >= n_fds) { g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Handle out of range"); goto out; } } } if (working_directory != NULL) _terminal_debug_print (TERMINAL_DEBUG_SERVER, "CWD is '%s'\n", working_directory); exec_argv = (char **) g_variant_get_bytestring_array (arguments, &exec_argc); error = NULL; if (!terminal_screen_exec (priv->screen, exec_argc > 0 ? exec_argv : NULL, envv, shell, working_directory, fd_list, fd_array, &error)) { g_dbus_method_invocation_take_error (invocation, error); } else { terminal_receiver_complete_exec (receiver, invocation, NULL /* outfdlist */); } g_free (exec_argv); g_free (envv); if (fd_array) g_variant_unref (fd_array); out: return TRUE; /* handled */ }
/** * 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 */ }
static VALUE unixfdlist_get_length(VALUE self) { return GINT2RVAL(g_unix_fd_list_get_length(_SELF(self))); }