コード例 #1
0
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;
}
コード例 #2
0
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);
    }
}
コード例 #3
0
ファイル: gvfsiconloadable.c プロジェクト: Alustriel/gvfs
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));
}
コード例 #4
0
ファイル: gvfsiconloadable.c プロジェクト: Alustriel/gvfs
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);
}
コード例 #5
0
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 */
}
コード例 #6
0
ファイル: udisksdaemonutil.c プロジェクト: jprvita/udisks
/**
 * 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
}
コード例 #7
0
/* 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 */
}
コード例 #8
0
ファイル: gunixfdlist.c プロジェクト: geoffyoungs/ruby-gnome2
static VALUE
unixfdlist_get_length(VALUE self)
{
        return GINT2RVAL(g_unix_fd_list_get_length(_SELF(self)));
}