Commit message: Bug 27494 — publicly exports dm key information

Change udisks-dm-export to only export UDISKS_DM_TARGETS_PARAMS for "linear"
types. It is the only one we care about for now and know how to interpret.
"crypto" types have information about the encryption key in the target
parameters, which we must not leak.

Also add appropriate comments to the two places which currently evaluate
UDISKS_DM_TARGETS_PARAMS.
CVE: CVE-2010-1149
CWE: CWE-200
Vulnerability description: probers/udisks-dm-export.c in udisks before 1.0.1 exports UDISKS_DM_TARGETS_PARAMS information to udev even for a crypt UDISKS_DM_TARGETS_TYPE, which allows local users to discover encryption keys by (1) running a certain udevadm command or (2) reading a certain file under /dev/.udev/db/.

Project: udisks
File: device.c

_dupv8 (const char *s)
{
  const char *end_valid;

  if (!g_utf8_validate (s, -1, &end_valid))
    {
      g_print ("**** NOTE: The string '%s' is not valid UTF-8. Invalid characters begins at '%s'\n", s, end_valid);
      return g_strndup (s, end_valid - s);
    }
  else
    {
      return g_strdup (s);
    }
}

Project: udisks
File: device.c

compute_object_path (const char *native_path)
{
  const gchar *basename;
  GString *s;
  guint n;

  g_return_val_if_fail (native_path != NULL, NULL);

  basename = strrchr (native_path, '/');
  if (basename != NULL)
    {
      basename++;
    }
  else
    {
      basename = native_path;
    }

  s = g_string_new ("/org/freedesktop/UDisks/devices/");
  for (n = 0; basename[n] != '\0'; n++)
    {
      gint c = basename[n];

      /* D-Bus spec sez:
       *
       * Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_"
       */
      if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))
        {
          g_string_append_c (s, c);
        }
      else
        {
          /* Escape bytes not in [A-Z][a-z][0-9] as _<hex-with-two-digits> */
          g_string_append_printf (s, "_%02x", c);
        }
    }

  return g_string_free (s, FALSE);
}

Project: udisks
File: device.c

daemon_linux_lvm2_lv_create (Daemon *daemon,
                             const gchar *group_uuid,
                             const gchar *name,
                             guint64 size,
                             guint num_stripes,
                             guint64 stripe_size,
                             guint num_mirrors,
                             gchar **options,
                             char *fstype,
                             char **fsoptions,
                             DBusGMethodInvocation *context)
{
  daemon_local_check_auth (daemon,
                           NULL,
                           "org.freedesktop.udisks.linux-lvm2",
                           "LinuxLvm2LVCreate",
                           TRUE,
                           daemon_linux_lvm2_lv_create_authorized_cb,
                           context,
                           9,
                           g_strdup (group_uuid),
                           g_free,
                           g_strdup (name),
                           g_free,
                           g_memdup (&size, sizeof (guint64)),
                           g_free,
                           GUINT_TO_POINTER (num_stripes),
                           NULL,
                           g_memdup (&stripe_size, sizeof (guint64)),
                           g_free,
                           GUINT_TO_POINTER (num_mirrors),
                           NULL,
                           g_strdupv (options),
                           g_strfreev,
                           g_strdup (fstype),
                           g_free,
                           g_strdupv (fsoptions),
                           g_strfreev);

  return TRUE;
}

Project: udisks
File: device.c

daemon_linux_lvm2_lv_remove (Daemon *daemon,
                             const gchar *group_uuid,
                             const gchar *uuid,
                             gchar **options,
                             DBusGMethodInvocation *context)
{
  daemon_local_check_auth (daemon,
                           NULL,
                           "org.freedesktop.udisks.linux-lvm2",
                           "LinuxLvm2LVRemove",
                           TRUE,
                           daemon_linux_lvm2_lv_remove_authorized_cb,
                           context,
                           3,
                           g_strdup (group_uuid),
                           g_free,
                           g_strdup (uuid),
                           g_free,
                           g_strdupv (options),
                           g_strfreev);

  return TRUE;
}

Project: udisks
File: device.c

daemon_linux_lvm2_lv_remove_authorized_cb (Daemon *daemon,
                                           Device *device,
                                           DBusGMethodInvocation *context,
                                           const gchar *action_id,
                                           guint num_user_data,
                                           gpointer *user_data_elements)
{
  const gchar *group_uuid = user_data_elements[0];
  const gchar *uuid = user_data_elements[1];
  /* TODO: use options: gchar **options = user_data_elements[2]; */
  gchar *lv_name;
  guint n;
  gchar *argv[10];

  /* Unfortunately lvchange does not (yet - file a bug) accept UUIDs - so find the LV name for this
   * UUID by looking at PVs
   */
  lv_name = find_lvm2_lv_name_for_uuids (daemon, group_uuid, uuid);
  if (lv_name == NULL)
    {
      throw_error (context, ERROR_FAILED, "Cannot find LV with UUID `%s'", uuid);
      goto out;
    }

  n = 0;
  argv[n++] = "lvremove";
  argv[n++] = lv_name;
  argv[n++] = "--force";
  argv[n++] = NULL;

  if (!job_new (context, "LinuxLvm2LVRemove", TRUE, NULL, argv, NULL, linux_lvm2_lv_remove_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  g_free (lv_name);
}

Project: udisks
File: device.c

daemon_linux_lvm2_lv_set_name (Daemon *daemon,
                               const gchar *group_uuid,
                               const gchar *uuid,
                               const gchar *new_name,
                               DBusGMethodInvocation *context)
{
  daemon_local_check_auth (daemon,
                           NULL,
                           "org.freedesktop.udisks.linux-lvm2",
                           "LinuxLvm2LVSetName",
                           TRUE,
                           daemon_linux_lvm2_lv_set_name_authorized_cb,
                           context,
                           3,
                           g_strdup (group_uuid),
                           g_free,
                           g_strdup (uuid),
                           g_free,
                           g_strdup (new_name),
                           g_free);

  return TRUE;
}

Project: udisks
File: device.c

daemon_linux_lvm2_lv_set_name_authorized_cb (Daemon *daemon,
                                             Device *device,
                                             DBusGMethodInvocation *context,
                                             const gchar *action_id,
                                             guint num_user_data,
                                             gpointer *user_data_elements)
{
  const gchar *group_uuid = user_data_elements[0];
  const gchar *uuid = user_data_elements[1];
  const gchar *new_name = user_data_elements[2];
  const gchar *vg_name;
  gchar *lv_name;
  guint n;
  gchar *argv[10];

  /* Unfortunately lvchange does not (yet - file a bug) accept UUIDs - so find the LV name for this
   * UUID by looking at PVs
   */

  lv_name = NULL;

  vg_name = find_lvm2_vg_name_for_uuid (daemon, group_uuid);
  if (vg_name == NULL)
    {
      throw_error (context, ERROR_FAILED, "Cannot find VG with UUID `%s'", group_uuid);
      goto out;
    }

  lv_name = find_lvm2_lv_name_for_uuids (daemon, group_uuid, uuid);
  if (lv_name == NULL)
    {
      throw_error (context, ERROR_FAILED, "Cannot find LV with UUID `%s'", uuid);
      goto out;
    }

  n = 0;
  argv[n++] = "lvrename";
  argv[n++] = (gchar *) vg_name;
  argv[n++] = lv_name;
  argv[n++] = (gchar *) new_name;
  argv[n++] = NULL;

  if (!job_new (context, "LinuxLvm2LVSetName", TRUE, NULL, argv, NULL, linux_lvm2_lv_set_name_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  g_free (lv_name);
}

Project: udisks
File: device.c

daemon_linux_lvm2_lv_start (Daemon *daemon,
                            const gchar *group_uuid,
                            const gchar *uuid,
                            char **options,
                            DBusGMethodInvocation *context)
{
  daemon_local_check_auth (daemon,
                           NULL,
                           "org.freedesktop.udisks.linux-lvm2",
                           "LinuxLvm2LVStart",
                           TRUE,
                           daemon_linux_lvm2_lv_start_authorized_cb,
                           context,
                           3,
                           g_strdup (group_uuid),
                           g_free,
                           g_strdup (uuid),
                           g_free,
                           g_strdupv (options),
                           g_strfreev);

  return TRUE;
}

Project: udisks

daemon_linux_lvm2_lv_start_authorized_cb (Daemon *daemon,
                                          Device *device,
                                          DBusGMethodInvocation *context,
                                          const gchar *action_id,
                                          guint num_user_data,
                                          gpointer *user_data_elements)
{
  const gchar *group_uuid = user_data_elements[0];
  const gchar *uuid = user_data_elements[1];
  gchar *lv_name;
  /* TODO: use options */
  guint n;
  gchar *argv[10];

  /* Unfortunately vgchange does not (yet - file a bug) accept UUIDs - so find the VG name for this
   * UUID by looking at PVs
   */

  lv_name = find_lvm2_lv_name_for_uuids (daemon, group_uuid, uuid);
  if (lv_name == NULL)
    {
      throw_error (context, ERROR_FAILED, "Cannot find Logical Volume with Group UUID `%s' and UUID `%s'", group_uuid, uuid);
      goto out;
    }

  n = 0;
  argv[n++] = "lvchange";
  argv[n++] = "-ay";
  argv[n++] = lv_name;
  argv[n++] = NULL;

  if (!job_new (context, "LinuxLvm2LVStart", TRUE, NULL, argv, NULL, linux_lvm2_lv_start_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  g_free (lv_name);
}

Project: udisks

daemon_linux_lvm2_lv_stop_authorized_cb (Daemon *daemon,
                                         Device *device,
                                         DBusGMethodInvocation *context,
                                         const gchar *action_id,
                                         guint num_user_data,
                                         gpointer *user_data_elements)
{
  gchar *name;
  /* TODO: use options */
  guint n;
  gchar *argv[10];

  name = NULL;

  if (!device->priv->device_is_linux_lvm2_lv)
    {
      throw_error (context, ERROR_FAILED, "Device is not a Linux LVM2 Logical Volume");
      goto out;
    }

  /* Unfortunately lvchange does not (yet - file a bug) accept UUIDs
   */
  name = g_strdup_printf ("%s/%s", device->priv->linux_lvm2_lv_group_name, device->priv->linux_lvm2_lv_name);

  n = 0;
  argv[n++] = "lvchange";
  argv[n++] = "-an";
  argv[n++] = name;
  argv[n++] = NULL;

  if (!job_new (context, "LinuxLvm2LVStop", TRUE, NULL, argv, NULL, linux_lvm2_lv_stop_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  g_free (name);
}

Project: udisks
File: device.c

daemon_linux_lvm2_vg_add_pv (Daemon *daemon,
                             const gchar *uuid,
                             const gchar *object_path,
                             gchar **options,
                             DBusGMethodInvocation *context)
{
  daemon_local_check_auth (daemon,
                           NULL,
                           "org.freedesktop.udisks.linux-lvm2",
                           "LinuxLvm2VGAddPV",
                           TRUE,
                           daemon_linux_lvm2_vg_add_pv_authorized_cb,
                           context,
                           3,
                           g_strdup (uuid),
                           g_free,
                           g_strdup (object_path),
                           g_free,
                           g_strdupv (options),
                           g_strfreev);

  return TRUE;
}

Project: udisks
File: device.c

daemon_linux_lvm2_vg_add_pv_authorized_cb (Daemon *daemon,
                                             Device *device,
                                             DBusGMethodInvocation *context,
                                             const gchar *action_id,
                                             guint num_user_data,
                                             gpointer *user_data_elements)
{
  const gchar *uuid = user_data_elements[0];
  const gchar *physical_volume = user_data_elements[1];
  /* TODO: use options: gchar **options = user_data_elements[2]; */
  const gchar *vg_name;
  guint n;
  gchar *argv[10];
  Device *pv;
  GError *error;

  /* Unfortunately vgchange does not (yet - file a bug) accept UUIDs - so find the VG name for this
   * UUID by looking at PVs
   */

  vg_name = find_lvm2_vg_name_for_uuid (daemon, uuid);
  if (vg_name == NULL)
    {
      throw_error (context, ERROR_FAILED, "Cannot find VG with UUID `%s'", uuid);
      goto out;
    }

  pv = daemon_local_find_by_object_path (daemon, physical_volume);
  if (pv == NULL)
    {
      throw_error (context, ERROR_FAILED, "physical volume doesn't exist");
      goto out;
    }

  error = NULL;
  if (device_local_is_busy (pv, TRUE, &error))
    {
      dbus_g_method_return_error (context, error);
      g_error_free (error);
      goto out;
    }


  n = 0;
  argv[n++] = "vgextend";
  argv[n++] = (gchar *) vg_name;
  argv[n++] = (gchar *) pv->priv->device_file;
  argv[n++] = NULL;

  if (!job_new (context, "LinuxLvm2VGAddPV", TRUE, NULL, argv, NULL, linux_lvm2_vg_add_pv_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

daemon_linux_lvm2_vg_remove_pv (Daemon *daemon,
                                const gchar *vg_uuid,
                                const gchar *pv_uuid,
                                gchar **options,
                                DBusGMethodInvocation *context)
{
  daemon_local_check_auth (daemon,
                           NULL,
                           "org.freedesktop.udisks.linux-lvm2",
                           "LinuxLvm2VGRemovePV",
                           TRUE,
                           daemon_linux_lvm2_vg_remove_pv_authorized_cb,
                           context,
                           3,
                           g_strdup (vg_uuid),
                           g_free,
                           g_strdup (pv_uuid),
                           g_free,
                           g_strdupv (options),
                           g_strfreev);

  return TRUE;
}

Project: udisks
File: device.c

daemon_linux_lvm2_vg_remove_pv_authorized_cb (Daemon *daemon,
                                              Device *device,
                                              DBusGMethodInvocation *context,
                                              const gchar *action_id,
                                              guint num_user_data,
                                              gpointer *user_data_elements)
{
  const gchar *vg_uuid = user_data_elements[0];
  const gchar *pv_uuid = user_data_elements[1];
  /* TODO: use options: gchar **options = user_data_elements[2]; */
  const gchar *vg_name;
  guint n;
  gchar *argv[10];
  Device *pv;
  GError *error;
  GList *devices;
  GList *l;

  /* Unfortunately vgchange does not (yet - file a bug) accept UUIDs - so find the VG name for this
   * UUID by looking at PVs
   */
  pv = NULL;

  vg_name = find_lvm2_vg_name_for_uuid (daemon, vg_uuid);
  if (vg_name == NULL)
    {
      throw_error (context, ERROR_FAILED, "Cannot find VG with UUID `%s'", vg_uuid);
      goto out;
    }

  devices = daemon_local_get_all_devices (daemon);
  for (l = devices; l != NULL; l = l->next)
    {
      Device *d = DEVICE (l->data);

      if (d->priv->device_is_linux_lvm2_pv && g_strcmp0 (d->priv->linux_lvm2_pv_uuid, pv_uuid) == 0)
        {
          pv = d;
          break;
        }
    }

  if (pv == NULL)
    {
      throw_error (context, ERROR_FAILED, "Cannot find PV with UUID `%s'", pv_uuid);
      goto out;
    }

  error = NULL;
  if (device_local_is_busy (pv, TRUE, &error))
    {
      dbus_g_method_return_error (context, error);
      g_error_free (error);
      goto out;
    }

  n = 0;
  argv[n++] = "vgreduce";
  argv[n++] = (gchar *) vg_name;
  argv[n++] = (gchar *) pv->priv->device_file;
  argv[n++] = NULL;

  if (!job_new (context, "LinuxLvm2VGRemovePV", TRUE, NULL, argv, NULL, linux_lvm2_vg_remove_pv_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

daemon_linux_lvm2_vg_set_name (Daemon *daemon,
                               const gchar *uuid,
                               const gchar *new_name,
                               DBusGMethodInvocation *context)
{
  daemon_local_check_auth (daemon,
                           NULL,
                           "org.freedesktop.udisks.linux-lvm2",
                           "LinuxLvm2VGSetName",
                           TRUE,
                           daemon_linux_lvm2_vg_set_name_authorized_cb,
                           context,
                           2,
                           g_strdup (uuid),
                           g_free,
                           g_strdup (new_name),
                           g_free);

  return TRUE;
}

Project: udisks
File: device.c

daemon_linux_lvm2_vg_set_name_authorized_cb (Daemon *daemon,
                                             Device *device,
                                             DBusGMethodInvocation *context,
                                             const gchar *action_id,
                                             guint num_user_data,
                                             gpointer *user_data_elements)
{
  const gchar *uuid = user_data_elements[0];
  const gchar *new_name = user_data_elements[1];
  const gchar *vg_name;
  guint n;
  gchar *argv[10];

  /* Unfortunately vgchange does not (yet - file a bug) accept UUIDs - so find the VG name for this
   * UUID by looking at PVs
   */

  vg_name = find_lvm2_vg_name_for_uuid (daemon, uuid);
  if (vg_name == NULL)
    {
      throw_error (context, ERROR_FAILED, "Cannot find VG with UUID `%s'", uuid);
      goto out;
    }

  n = 0;
  argv[n++] = "vgrename";
  argv[n++] = (gchar *) vg_name;
  argv[n++] = (gchar *) new_name;
  argv[n++] = NULL;

  if (!job_new (context, "LinuxLvm2VGSetName", TRUE, NULL, argv, NULL, linux_lvm2_vg_set_name_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

daemon_linux_lvm2_vg_start (Daemon *daemon,
                            const gchar *uuid,
                            char **options,
                            DBusGMethodInvocation *context)
{
  daemon_local_check_auth (daemon,
                           NULL,
                           "org.freedesktop.udisks.linux-lvm2",
                           "LinuxLvm2VGStart",
                           TRUE,
                           daemon_linux_lvm2_vg_start_authorized_cb,
                           context,
                           2,
                           g_strdup (uuid),
                           g_free,
                           g_strdupv (options),
                           g_strfreev);

  return TRUE;
}

Project: udisks

daemon_linux_lvm2_vg_start_authorized_cb (Daemon *daemon,
                                          Device *device,
                                          DBusGMethodInvocation *context,
                                          const gchar *action_id,
                                          guint num_user_data,
                                          gpointer *user_data_elements)
{
  const gchar *uuid = user_data_elements[0];
  const gchar *vg_name;
  /* TODO: use options */
  guint n;
  gchar *argv[10];

  /* Unfortunately vgchange does not (yet - file a bug) accept UUIDs - so find the VG name for this
   * UUID by looking at PVs
   */

  vg_name = find_lvm2_vg_name_for_uuid (daemon, uuid);
  if (vg_name == NULL)
    {
      throw_error (context, ERROR_FAILED, "Cannot find VG with UUID `%s'", uuid);
      goto out;
    }

  n = 0;
  argv[n++] = "vgchange";
  argv[n++] = "-ay";
  argv[n++] = (gchar *) vg_name;
  argv[n++] = NULL;

  if (!job_new (context, "LinuxLvm2VGStart", TRUE, NULL, argv, NULL, linux_lvm2_vg_start_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

daemon_linux_lvm2_vg_stop (Daemon *daemon,
                           const gchar *uuid,
                           char **options,
                           DBusGMethodInvocation *context)
{
  daemon_local_check_auth (daemon,
                           NULL,
                           "org.freedesktop.udisks.linux-lvm2",
                           "LinuxLvm2VGStop",
                           TRUE,
                           daemon_linux_lvm2_vg_stop_authorized_cb,
                           context,
                           2,
                           g_strdup (uuid),
                           g_free,
                           g_strdupv (options),
                           g_strfreev);

  return TRUE;
}

Project: udisks

daemon_linux_lvm2_vg_stop_authorized_cb (Daemon *daemon,
                                         Device *device,
                                         DBusGMethodInvocation *context,
                                         const gchar *action_id,
                                         guint num_user_data,
                                         gpointer *user_data_elements)
{
  const gchar *uuid = user_data_elements[0];
  const gchar *vg_name;
  /* TODO: use options */
  guint n;
  gchar *argv[10];

  /* Unfortunately vgchange does not (yet - file a bug) accept UUIDs - so find the VG name for this
   * UUID by looking at PVs
   */
  vg_name = find_lvm2_vg_name_for_uuid (daemon, uuid);
  if (vg_name == NULL)
    {
      throw_error (context, ERROR_FAILED, "Cannot find VG with UUID `%s'", uuid);
      goto out;
    }

  n = 0;
  argv[n++] = "vgchange";
  argv[n++] = "-an";
  argv[n++] = (gchar *) vg_name;
  argv[n++] = NULL;

  if (!job_new (context, "LinuxLvm2VGStop", TRUE, NULL, argv, NULL, linux_lvm2_vg_stop_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

daemon_linux_md_create (Daemon *daemon,
                        GPtrArray *components,
                        char *level,
                        guint64 stripe_size,
                        char *name,
                        char **options,
                        DBusGMethodInvocation *context)
{
  gchar **components_as_strv;
  guint n;

  components_as_strv = g_new0 (gchar *, components->len + 1);
  for (n = 0; n < components->len; n++)
    components_as_strv[n] = g_strdup (components->pdata[n]);

  daemon_local_check_auth (daemon,
                           NULL,
                           "org.freedesktop.udisks.linux-md",
                           "LinuxMdCreate",
                           TRUE,
                           daemon_linux_md_create_authorized_cb,
                           context,
                           4,
                           components_as_strv,
                           g_strfreev,
                           g_strdup (level),
                           g_free,
                           g_memdup (&stripe_size, sizeof(guint64)),
                           g_free,
                           g_strdup (name),
                           g_free,
                           g_strdupv (options),
                           g_strfreev);

  return TRUE;
}

Project: udisks

daemon_linux_md_create_authorized_cb (Daemon *daemon,
                                      Device *device,
                                      DBusGMethodInvocation *context,
                                      const gchar *action_id,
                                      guint num_user_data,
                                      gpointer *user_data_elements)
{
  gchar **components_as_strv = user_data_elements[0];
  gchar *level = user_data_elements[1];
  guint64 stripe_size = *((guint64*) user_data_elements[2]);
  gchar *name = user_data_elements[3];
  /* TODO: use options */
  int n;
  int m;
  char *argv[128];
  GError *error;
  gchar *md_device_file;
  gchar *num_raid_devices_as_str;
  gchar *stripe_size_as_str;
  gboolean use_bitmap;
  gboolean use_chunk;

  md_device_file = NULL;
  num_raid_devices_as_str = NULL;
  stripe_size_as_str = NULL;
  error = NULL;

  /* sanity-check level */
  use_bitmap = FALSE;
  use_chunk = FALSE;
  if (g_strcmp0 (level, "raid0") == 0)
    {
      use_chunk = TRUE;
    }
  else if (g_strcmp0 (level, "raid1") == 0)
    {
      if (stripe_size > 0)
        {
          throw_error (context, ERROR_FAILED, "Stripe size doesn't make sense for RAID-1");
          goto out;
        }
    }
  else if (g_strcmp0 (level, "raid4") == 0 || g_strcmp0 (level, "raid5") == 0 || g_strcmp0 (level, "raid6") == 0
           || g_strcmp0 (level, "raid10") == 0)
    {
      use_bitmap = TRUE;
      use_chunk = TRUE;
    }
  else
    {
      throw_error (context, ERROR_FAILED, "Invalid level `%s'", level);
      goto out;
    }

  /* check that all given components exist and that they are not busy
   */
  for (n = 0; components_as_strv[n] != NULL; n++)
    {
      Device *slave;
      const char *component_objpath = components_as_strv[n];

      slave = daemon_local_find_by_object_path (daemon, component_objpath);
      if (slave == NULL)
        {
          throw_error (context, ERROR_FAILED, "Component %s doesn't exist", component_objpath);
          goto out;
        }

      if (device_local_is_busy (slave, FALSE, &error))
        {
          dbus_g_method_return_error (context, error);
          g_error_free (error);
          goto out;
        }
    }

  /* find an unused md minor... Man, I wish mdadm could do this itself; this is slightly racy */
  for (n = 0; TRUE; n++)
    {
      char *native_path;
      char *array_state;

      /* TODO: move to /sys/class/block instead */
      native_path = g_strdup_printf ("/sys/block/md%d", n);
      if (!sysfs_file_exists (native_path, "md/array_state"))
        {
          /* Apparently this slot is free since there is no such file. So let's peruse it. */
          g_free (native_path);
          break;
        }
      else
        {
          array_state = sysfs_get_string (native_path, "md/array_state");
          g_strstrip (array_state);
          if (strcmp (array_state, "clear") == 0)
            {
              /* It's clear! Let's use it! */
              g_free (array_state);
              g_free (native_path);
              break;
            }
          g_free (array_state);
        }
      g_free (native_path);
    }

  md_device_file = g_strdup_printf ("/dev/md%d", n);

  num_raid_devices_as_str = g_strdup_printf ("%d", g_strv_length (components_as_strv));

  if (stripe_size > 0)
    stripe_size_as_str = g_strdup_printf ("%d", ((gint) stripe_size) / 1024);

  n = 0;
  argv[n++] = "mdadm";
  argv[n++] = "--create";
  argv[n++] = md_device_file;
  argv[n++] = "--level";
  argv[n++] = level;
  argv[n++] = "--raid-devices";
  argv[n++] = num_raid_devices_as_str;
  argv[n++] = "--metadata";
  argv[n++] = "1.2";
  argv[n++] = "--name";
  argv[n++] = name;
  argv[n++] = "--homehost";
  argv[n++] = "";
  if (use_bitmap)
    {
      argv[n++] = "--bitmap";
      argv[n++] = "internal";
    }
  if (use_chunk && stripe_size_as_str != NULL)
    {
      argv[n++] = "--chunk";
      argv[n++] = stripe_size_as_str;
    }
  for (m = 0; components_as_strv[m] != NULL; m++)
    {
      Device *slave;
      const char *component_objpath = components_as_strv[m];

      slave = daemon_local_find_by_object_path (daemon, component_objpath);
      if (slave == NULL)
        {
          throw_error (context, ERROR_FAILED, "Component %s doesn't exist", component_objpath);
          goto out;
        }

      if (n >= (int) sizeof(argv) - 1)
        {
          throw_error (context, ERROR_FAILED, "Too many components");
          goto out;
        }

      argv[n++] = (char *) slave->priv->device_file;
    }
  argv[n++] = NULL;


  if (!job_new (context,
                "LinuxMdCreate",
                TRUE,
                NULL,
                argv,
                NULL,
                linux_md_create_completed_cb,
                FALSE,
                linux_md_create_data_new (context, daemon, components_as_strv[0]),
                (GDestroyNotify) linux_md_create_data_unref))
    {
      goto out;
    }

 out:
  g_free (md_device_file);
  g_free (num_raid_devices_as_str);
  g_free (stripe_size_as_str);
}

Project: udisks
File: device.c

daemon_linux_md_start (Daemon *daemon,
                       GPtrArray *components,
                       char **options,
                       DBusGMethodInvocation *context)
{
  gchar **components_as_strv;
  guint n;

  components_as_strv = g_new0 (gchar *, components->len + 1);
  for (n = 0; n < components->len; n++)
    components_as_strv[n] = g_strdup (components->pdata[n]);

  daemon_local_check_auth (daemon,
                           NULL,
                           "org.freedesktop.udisks.linux-md",
                           "LinuxMdStart",
                           TRUE,
                           daemon_linux_md_start_authorized_cb,
                           context,
                           2,
                           components_as_strv,
                           g_strfreev,
                           g_strdupv (options),
                           g_strfreev);

  return TRUE;
}

Project: udisks

daemon_linux_md_start_authorized_cb (Daemon *daemon,
                                     Device *device,
                                     DBusGMethodInvocation *context,
                                     const gchar *action_id,
                                     guint num_user_data,
                                     gpointer *user_data_elements)
{
  gchar **components_as_strv = user_data_elements[0];
  /* TODO: use options */
  int n;
  int m;
  char *argv[128];
  GError *error;
  char *uuid;
  char *md_device_file;

  uuid = NULL;
  md_device_file = NULL;
  error = NULL;

  /* check that all given components exist, that they are indeed linux-md-components and
   * that their uuid agrees
   */
  for (n = 0; components_as_strv[n] != NULL; n++)
    {
      Device *slave;
      const char *component_objpath = components_as_strv[n];

      slave = daemon_local_find_by_object_path (daemon, component_objpath);
      if (slave == NULL)
        {
          throw_error (context, ERROR_FAILED, "Component %s doesn't exist", component_objpath);
          goto out;
        }

      if (!slave->priv->device_is_linux_md_component)
        {
          throw_error (context, ERROR_FAILED, "%s is not a linux-md component", component_objpath);
          goto out;
        }

      if (n == 0)
        {
          uuid = g_strdup (slave->priv->linux_md_component_uuid);
          if (uuid == NULL)
            {
              throw_error (context, ERROR_FAILED, "no uuid for one of the components");
              goto out;
            }
        }
      else
        {
          const char *this_uuid;
          this_uuid = slave->priv->linux_md_component_uuid;

          if (this_uuid == NULL || strcmp (uuid, this_uuid) != 0)
            {
              throw_error (context, ERROR_FAILED, "uuid mismatch between given components");
              goto out;
            }
        }

      if (device_local_is_busy (slave, FALSE, &error))
        {
          dbus_g_method_return_error (context, error);
          g_error_free (error);
          goto out;
        }
    }

  /* find an unused md minor... Man, I wish mdadm could do this itself; this is slightly racy */
  for (n = 0; TRUE; n++)
    {
      char *native_path;
      char *array_state;

      /* TODO: move to /sys/class/block instead */
      native_path = g_strdup_printf ("/sys/block/md%d", n);
      if (!sysfs_file_exists (native_path, "md/array_state"))
        {
          /* Apparently this slot is free since there is no such file. So let's peruse it. */
          g_free (native_path);
          break;
        }
      else
        {
          array_state = sysfs_get_string (native_path, "md/array_state");
          g_strstrip (array_state);
          if (strcmp (array_state, "clear") == 0)
            {
              /* It's clear! Let's use it! */
              g_free (array_state);
              g_free (native_path);
              break;
            }
          g_free (array_state);
        }
      g_free (native_path);
    }

  md_device_file = g_strdup_printf ("/dev/md%d", n);

  n = 0;
  argv[n++] = "mdadm";
  argv[n++] = "--assemble";
  argv[n++] = md_device_file;
  argv[n++] = "--run";
  for (m = 0; components_as_strv[m] != NULL; m++)
    {
      Device *slave;
      const char *component_objpath = components_as_strv[m];

      slave = daemon_local_find_by_object_path (daemon, component_objpath);
      if (slave == NULL)
        {
          throw_error (context, ERROR_FAILED, "Component %s doesn't exist", component_objpath);
          goto out;
        }

      if (n >= (int) sizeof(argv) - 1)
        {
          throw_error (context, ERROR_FAILED, "Too many components");
          goto out;
        }

      argv[n++] = (char *) slave->priv->device_file;
    }
  argv[n++] = NULL;

  if (!job_new (context,
                "LinuxMdStart",
                TRUE,
                NULL,
                argv,
                NULL,
                linux_md_start_completed_cb,
                FALSE,
                linux_md_start_data_new (context, daemon, uuid),
                (GDestroyNotify) linux_md_start_data_unref))
    {
      goto out;
    }

 out:
  g_free (uuid);
  g_free (md_device_file);
}

Project: udisks
File: device.c

decode_udev_encoded_string (const gchar *str)
{
  GString *s;
  gchar *ret;
  const gchar *end_valid;
  guint n;

  s = g_string_new (NULL);
  for (n = 0; str[n] != '\0'; n++)
    {
      if (str[n] == '\\')
        {
          gint val;

          if (str[n + 1] != 'x' || str[n + 2] == '\0' || str[n + 3] == '\0')
            {
              g_print ("**** NOTE: malformed encoded string '%s'\n", str);
              break;
            }

          val = (g_ascii_xdigit_value (str[n + 2]) << 4) | g_ascii_xdigit_value (str[n + 3]);

          g_string_append_c (s, val);

          n += 3;
        }
      else
        {
          g_string_append_c (s, str[n]);
        }
    }

  if (!g_utf8_validate (s->str, -1, &end_valid))
    {
      g_print ("**** NOTE: The string '%s' is not valid UTF-8. Invalid characters begins at '%s'\n", s->str, end_valid);
      ret = g_strndup (s->str, end_valid - s->str);
      g_string_free (s, TRUE);
    }
  else
    {
      ret = g_string_free (s, FALSE);
    }

  return ret;
}

Project: udisks
File: device.c

device_changed (Device *device,
                GUdevDevice *d,
                gboolean synthesized)
{
  gboolean keep_device;

  g_object_unref (device->priv->d);
  device->priv->d = g_object_ref (d);

  keep_device = update_info (device);

  /* this 'change' event might prompt us to remove the device */
  if (!keep_device)
    goto out;

  /* no, it's good .. keep it.. and always force a 'change' signal if the event isn't synthesized */
  drain_pending_changes (device, !synthesized);

  /* Check if media was removed. If so, we possibly need to clean up
   * if the device itself is busy. This includes
   *
   *  - force unmounting the device
   *
   *  - tearing down a luks mapping if it's a cleartext device
   *    backed by a crypted device
   *
   * but see force_removal() for details.
   *
   * This is the normally the path where the media is removed but the enclosing
   * device is still present. Compare with device_removed() for
   * the other path.
   */
  if (!device->priv->device_is_media_available)
    {
      GList *l;
      GList *devices;

      force_removal (device, NULL, NULL);

      /* check all partitions */
      devices = daemon_local_get_all_devices (device->priv->daemon);
      for (l = devices; l != NULL; l = l->next)
        {
          Device *d = DEVICE (l->data);

          if (d->priv->device_is_partition && d->priv->partition_slave != NULL && strcmp (d->priv->partition_slave,
                                                                                          device->priv->object_path)
              == 0)
            {

              force_removal (d, NULL, NULL);
            }
        }

      g_list_free (devices);
    }
 out:
  return keep_device;
}

Project: udisks
File: device.c

device_class_init (DeviceClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  object_class->constructor = device_constructor;
  object_class->finalize = device_finalize;
  object_class->get_property = get_property;

  g_type_class_add_private (klass, sizeof(DevicePrivate));

  signals[CHANGED_SIGNAL] = g_signal_new ("changed",
                                          G_OBJECT_CLASS_TYPE (klass),
                                          G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
                                          0,
                                          NULL,
                                          NULL,
                                          g_cclosure_marshal_VOID__VOID,
                                          G_TYPE_NONE,
                                          0);

  signals[JOB_CHANGED_SIGNAL] = g_signal_new ("job-changed",
                                              G_OBJECT_CLASS_TYPE (klass),
                                              G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
                                              0,
                                              NULL,
                                              NULL,
                                              marshal_VOID__BOOLEAN_STRING_UINT_BOOLEAN_DOUBLE,
                                              G_TYPE_NONE,
                                              5,
                                              G_TYPE_BOOLEAN,
                                              G_TYPE_STRING,
                                              G_TYPE_UINT,
                                              G_TYPE_BOOLEAN,
                                              G_TYPE_DOUBLE);

  dbus_g_object_type_install_info (TYPE_DEVICE, &dbus_glib_device_object_info);

  g_object_class_install_property (object_class, PROP_NATIVE_PATH, g_param_spec_string ("native-path",
                                                                                        NULL,
                                                                                        NULL,
                                                                                        NULL,
                                                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_DETECTION_TIME,
                                   g_param_spec_uint64 ("device-detection-time",
                                                        NULL,
                                                        NULL,
                                                        0,
                                                        G_MAXUINT64,
                                                        0,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_MEDIA_DETECTION_TIME,
                                   g_param_spec_uint64 ("device-media-detection-time",
                                                        NULL,
                                                        NULL,
                                                        0,
                                                        G_MAXUINT64,
                                                        0,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DEVICE_MAJOR, g_param_spec_int64 ("device-major",
                                                                                        NULL,
                                                                                        NULL,
                                                                                        -G_MAXINT64,
                                                                                        G_MAXINT64,
                                                                                        0,
                                                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DEVICE_MINOR, g_param_spec_int64 ("device-minor",
                                                                                        NULL,
                                                                                        NULL,
                                                                                        -G_MAXINT64,
                                                                                        G_MAXINT64,
                                                                                        0,
                                                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_FILE,
                                   g_param_spec_string ("device-file",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_FILE_PRESENTATION,
                                   g_param_spec_string ("device-file-presentation",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_FILE_BY_ID,
                                   g_param_spec_boxed ("device-file-by-id",
                                                       NULL,
                                                       NULL,
                                                       dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
                                                       G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_FILE_BY_PATH,
                                   g_param_spec_boxed ("device-file-by-path",
                                                       NULL,
                                                       NULL,
                                                       dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
                                                       G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_SYSTEM_INTERNAL,
                                   g_param_spec_boolean ("device-is-system-internal",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DEVICE_IS_PARTITION, g_param_spec_boolean ("device-is-partition",
                                                                                                 NULL,
                                                                                                 NULL,
                                                                                                 FALSE,
                                                                                                 G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_PARTITION_TABLE,
                                   g_param_spec_boolean ("device-is-partition-table",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DEVICE_IS_REMOVABLE, g_param_spec_boolean ("device-is-removable",
                                                                                                 NULL,
                                                                                                 NULL,
                                                                                                 FALSE,
                                                                                                 G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_MEDIA_AVAILABLE,
                                   g_param_spec_boolean ("device-is-media-available",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_MEDIA_CHANGE_DETECTED,
                                   g_param_spec_boolean ("device-is-media-change-detected",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_POLLING,
                                   g_param_spec_boolean ("device-is-media-change-detection-polling",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_INHIBITABLE,
                                   g_param_spec_boolean ("device-is-media-change-detection-inhibitable",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_MEDIA_CHANGE_DETECTION_INHIBITED,
                                   g_param_spec_boolean ("device-is-media-change-detection-inhibited",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DEVICE_IS_READ_ONLY, g_param_spec_boolean ("device-is-read-only",
                                                                                                 NULL,
                                                                                                 NULL,
                                                                                                 FALSE,
                                                                                                 G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DEVICE_IS_DRIVE, g_param_spec_boolean ("device-is-drive",
                                                                                             NULL,
                                                                                             NULL,
                                                                                             FALSE,
                                                                                             G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_OPTICAL_DISC,
                                   g_param_spec_boolean ("device-is-optical-disc", NULL, NULL, FALSE, G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DEVICE_IS_LUKS, g_param_spec_boolean ("device-is-luks",
                                                                                            NULL,
                                                                                            NULL,
                                                                                            FALSE,
                                                                                            G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_LUKS_CLEARTEXT,
                                   g_param_spec_boolean ("device-is-luks-cleartext",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_LINUX_MD_COMPONENT,
                                   g_param_spec_boolean ("device-is-linux-md-component",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DEVICE_IS_LINUX_MD, g_param_spec_boolean ("device-is-linux-md",
                                                                                                NULL,
                                                                                                NULL,
                                                                                                FALSE,
                                                                                                G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_LINUX_LVM2_LV,
                                   g_param_spec_boolean ("device-is-linux-lvm2-lv",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_LINUX_LVM2_PV,
                                   g_param_spec_boolean ("device-is-linux-lvm2-pv",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_LINUX_DMMP,
                                   g_param_spec_boolean ("device-is-linux-dmmp",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_LINUX_DMMP_COMPONENT,
                                   g_param_spec_boolean ("device-is-linux-dmmp-component",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_IS_LINUX_LOOP,
                                   g_param_spec_boolean ("device-is-linux-loop",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));

  g_object_class_install_property (object_class, PROP_DEVICE_SIZE, g_param_spec_uint64 ("device-size",
                                                                                        NULL,
                                                                                        NULL,
                                                                                        0,
                                                                                        G_MAXUINT64,
                                                                                        0,
                                                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DEVICE_BLOCK_SIZE, g_param_spec_uint64 ("device-block-size",
                                                                                              NULL,
                                                                                              NULL,
                                                                                              0,
                                                                                              G_MAXUINT64,
                                                                                              0,
                                                                                              G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DEVICE_IS_MOUNTED, g_param_spec_boolean ("device-is-mounted",
                                                                                               NULL,
                                                                                               NULL,
                                                                                               FALSE,
                                                                                               G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_MOUNT_PATHS,
                                   g_param_spec_boxed ("device-mount-paths",
                                                       NULL,
                                                       NULL,
                                                       dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
                                                       G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_MOUNTED_BY_UID,
                                   g_param_spec_uint ("device-mounted-by-uid",
                                                      NULL,
                                                      NULL,
                                                      0,
                                                      G_MAXUINT,
                                                      0,
                                                      G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_PRESENTATION_HIDE,
                                   g_param_spec_boolean ("device-presentation-hide",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_PRESENTATION_NOPOLICY,
                                   g_param_spec_boolean ("device-presentation-nopolicy",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_PRESENTATION_NAME,
                                   g_param_spec_string ("device-presentation-name", NULL, NULL, NULL, G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DEVICE_PRESENTATION_ICON_NAME,
                                   g_param_spec_string ("device-presentation-icon-name",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));

  g_object_class_install_property (object_class, PROP_JOB_IN_PROGRESS, g_param_spec_boolean ("job-in-progress",
                                                                                             NULL,
                                                                                             NULL,
                                                                                             FALSE,
                                                                                             G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_JOB_ID, g_param_spec_string ("job-id",
                                                                                   NULL,
                                                                                   NULL,
                                                                                   NULL,
                                                                                   G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_JOB_INITIATED_BY_UID, g_param_spec_uint ("job-initiated-by-uid",
                                                                                               NULL,
                                                                                               NULL,
                                                                                               0,
                                                                                               G_MAXUINT,
                                                                                               0,
                                                                                               G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_JOB_IS_CANCELLABLE, g_param_spec_boolean ("job-is-cancellable",
                                                                                                NULL,
                                                                                                NULL,
                                                                                                FALSE,
                                                                                                G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_JOB_PERCENTAGE, g_param_spec_double ("job-percentage",
                                                                                           NULL,
                                                                                           NULL,
                                                                                           -1,
                                                                                           100,
                                                                                           -1,
                                                                                           G_PARAM_READABLE));

  g_object_class_install_property (object_class, PROP_ID_USAGE, g_param_spec_string ("id-usage",
                                                                                     NULL,
                                                                                     NULL,
                                                                                     NULL,
                                                                                     G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_ID_TYPE, g_param_spec_string ("id-type",
                                                                                    NULL,
                                                                                    NULL,
                                                                                    NULL,
                                                                                    G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_ID_VERSION, g_param_spec_string ("id-version",
                                                                                       NULL,
                                                                                       NULL,
                                                                                       NULL,
                                                                                       G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_ID_UUID, g_param_spec_string ("id-uuid",
                                                                                    NULL,
                                                                                    NULL,
                                                                                    NULL,
                                                                                    G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_ID_LABEL, g_param_spec_string ("id-label",
                                                                                     NULL,
                                                                                     NULL,
                                                                                     NULL,
                                                                                     G_PARAM_READABLE));

  g_object_class_install_property (object_class, PROP_PARTITION_SLAVE, g_param_spec_boxed ("partition-slave",
                                                                                           NULL,
                                                                                           NULL,
                                                                                           DBUS_TYPE_G_OBJECT_PATH,
                                                                                           G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_PARTITION_SCHEME, g_param_spec_string ("partition-scheme",
                                                                                             NULL,
                                                                                             NULL,
                                                                                             NULL,
                                                                                             G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_PARTITION_TYPE, g_param_spec_string ("partition-type",
                                                                                           NULL,
                                                                                           NULL,
                                                                                           NULL,
                                                                                           G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_PARTITION_LABEL, g_param_spec_string ("partition-label",
                                                                                            NULL,
                                                                                            NULL,
                                                                                            NULL,
                                                                                            G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_PARTITION_UUID, g_param_spec_string ("partition-uuid",
                                                                                           NULL,
                                                                                           NULL,
                                                                                           NULL,
                                                                                           G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_PARTITION_FLAGS,
                                   g_param_spec_boxed ("partition-flags",
                                                       NULL,
                                                       NULL,
                                                       dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
                                                       G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_PARTITION_NUMBER, g_param_spec_int ("partition-number",
                                                                                          NULL,
                                                                                          NULL,
                                                                                          0,
                                                                                          G_MAXINT,
                                                                                          0,
                                                                                          G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_PARTITION_OFFSET, g_param_spec_uint64 ("partition-offset",
                                                                                             NULL,
                                                                                             NULL,
                                                                                             0,
                                                                                             G_MAXUINT64,
                                                                                             0,
                                                                                             G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_PARTITION_SIZE, g_param_spec_uint64 ("partition-size",
                                                                                           NULL,
                                                                                           NULL,
                                                                                           0,
                                                                                           G_MAXUINT64,
                                                                                           0,
                                                                                           G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_PARTITION_ALIGNMENT_OFFSET,
                                   g_param_spec_uint64 ("partition-alignment-offset",
                                                        NULL,
                                                        NULL,
                                                        0,
                                                        G_MAXUINT64,
                                                        0,
                                                        G_PARAM_READABLE));

  g_object_class_install_property (object_class,
                                   PROP_PARTITION_TABLE_SCHEME,
                                   g_param_spec_string ("partition-table-scheme", NULL, NULL, NULL, G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_PARTITION_TABLE_COUNT, g_param_spec_int ("partition-table-count",
                                                                                               NULL,
                                                                                               NULL,
                                                                                               0,
                                                                                               G_MAXINT,
                                                                                               0,
                                                                                               G_PARAM_READABLE));

  g_object_class_install_property (object_class, PROP_LUKS_HOLDER, g_param_spec_boxed ("luks-holder",
                                                                                       NULL,
                                                                                       NULL,
                                                                                       DBUS_TYPE_G_OBJECT_PATH,
                                                                                       G_PARAM_READABLE));

  g_object_class_install_property (object_class,
                                   PROP_LUKS_CLEARTEXT_SLAVE,
                                   g_param_spec_boxed ("luks-cleartext-slave",
                                                       NULL,
                                                       NULL,
                                                       DBUS_TYPE_G_OBJECT_PATH,
                                                       G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LUKS_CLEARTEXT_UNLOCKED_BY_UID,
                                   g_param_spec_uint ("luks-cleartext-unlocked-by-uid",
                                                      NULL,
                                                      NULL,
                                                      0,
                                                      G_MAXUINT,
                                                      0,
                                                      G_PARAM_READABLE));

  g_object_class_install_property (object_class, PROP_DRIVE_VENDOR, g_param_spec_string ("drive-vendor",
                                                                                         NULL,
                                                                                         NULL,
                                                                                         NULL,
                                                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DRIVE_MODEL, g_param_spec_string ("drive-model",
                                                                                        NULL,
                                                                                        NULL,
                                                                                        NULL,
                                                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DRIVE_REVISION, g_param_spec_string ("drive-revision",
                                                                                           NULL,
                                                                                           NULL,
                                                                                           NULL,
                                                                                           G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DRIVE_SERIAL, g_param_spec_string ("drive-serial",
                                                                                         NULL,
                                                                                         NULL,
                                                                                         NULL,
                                                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DRIVE_WWN, g_param_spec_string ("drive-wwn",
                                                                                      NULL,
                                                                                      NULL,
                                                                                      NULL,
                                                                                      G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DRIVE_CONNECTION_INTERFACE,
                                   g_param_spec_string ("drive-connection-interface",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DRIVE_CONNECTION_SPEED,
                                   g_param_spec_uint64 ("drive-connection-speed",
                                                        NULL,
                                                        NULL,
                                                        0,
                                                        G_MAXUINT64,
                                                        0,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DRIVE_MEDIA_COMPATIBILITY,
                                   g_param_spec_boxed ("drive-media-compatibility",
                                                       NULL,
                                                       NULL,
                                                       dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
                                                       G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DRIVE_MEDIA, g_param_spec_string ("drive-media",
                                                                                        NULL,
                                                                                        NULL,
                                                                                        NULL,
                                                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DRIVE_IS_MEDIA_EJECTABLE,
                                   g_param_spec_boolean ("drive-is-media-ejectable",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DRIVE_CAN_DETACH, g_param_spec_boolean ("drive-can-detach",
                                                                                              NULL,
                                                                                              NULL,
                                                                                              FALSE,
                                                                                              G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DRIVE_CAN_SPINDOWN, g_param_spec_boolean ("drive-can-spindown",
                                                                                                NULL,
                                                                                                NULL,
                                                                                                FALSE,
                                                                                                G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DRIVE_IS_ROTATIONAL, g_param_spec_boolean ("drive-is-rotational",
                                                                                                 NULL,
                                                                                                 NULL,
                                                                                                 FALSE,
                                                                                                 G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DRIVE_ROTATION_RATE, g_param_spec_uint ("drive-rotation-rate",
                                                                                              NULL,
                                                                                              NULL,
                                                                                              0,
                                                                                              G_MAXUINT,
                                                                                              0,
                                                                                              G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DRIVE_WRITE_CACHE, g_param_spec_string ("drive-write-cache",
                                                                                              NULL,
                                                                                              NULL,
                                                                                              FALSE,
                                                                                              G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_DRIVE_ADAPTER, g_param_spec_boxed ("drive-adapter",
                                                                                         NULL,
                                                                                         NULL,
                                                                                         DBUS_TYPE_G_OBJECT_PATH,
                                                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DRIVE_PORTS,
                                   g_param_spec_boxed ("drive-ports",
                                                       NULL,
                                                       NULL,
                                                       dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
                                                       G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DRIVE_SIMILAR_DEVICES,
                                   g_param_spec_boxed ("drive-similar-devices",
                                                       NULL,
                                                       NULL,
                                                       dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
                                                       G_PARAM_READABLE));

  g_object_class_install_property (object_class,
                                   PROP_OPTICAL_DISC_IS_BLANK,
                                   g_param_spec_boolean ("optical-disc-is-blank", NULL, NULL, FALSE, G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_OPTICAL_DISC_IS_APPENDABLE,
                                   g_param_spec_boolean ("optical-disc-is-appendable",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_OPTICAL_DISC_IS_CLOSED,
                                   g_param_spec_boolean ("optical-disc-is-closed", NULL, NULL, FALSE, G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_OPTICAL_DISC_NUM_TRACKS,
                                   g_param_spec_uint ("optical-disc-num-tracks",
                                                      NULL,
                                                      NULL,
                                                      0,
                                                      G_MAXUINT,
                                                      0,
                                                      G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_OPTICAL_DISC_NUM_AUDIO_TRACKS,
                                   g_param_spec_uint ("optical-disc-num-audio-tracks",
                                                      NULL,
                                                      NULL,
                                                      0,
                                                      G_MAXUINT,
                                                      0,
                                                      G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_OPTICAL_DISC_NUM_SESSIONS,
                                   g_param_spec_uint ("optical-disc-num-sessions",
                                                      NULL,
                                                      NULL,
                                                      0,
                                                      G_MAXUINT,
                                                      0,
                                                      G_PARAM_READABLE));

  g_object_class_install_property (object_class,
                                   PROP_DRIVE_ATA_SMART_IS_AVAILABLE,
                                   g_param_spec_boolean ("drive-ata-smart-is-available",
                                                         NULL,
                                                         NULL,
                                                         FALSE,
                                                         G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DRIVE_ATA_SMART_TIME_COLLECTED,
                                   g_param_spec_uint64 ("drive-ata-smart-time-collected",
                                                        NULL,
                                                        NULL,
                                                        0,
                                                        G_MAXUINT64,
                                                        0,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DRIVE_ATA_SMART_STATUS,
                                   g_param_spec_string ("drive-ata-smart-status", NULL, NULL, NULL, G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_DRIVE_ATA_SMART_BLOB,
                                   g_param_spec_boxed ("drive-ata-smart-blob",
                                                       NULL,
                                                       NULL,
                                                       dbus_g_type_get_collection ("GArray", G_TYPE_UCHAR),
                                                       G_PARAM_READABLE));

  g_object_class_install_property (object_class,
                                   PROP_LINUX_MD_COMPONENT_LEVEL,
                                   g_param_spec_string ("linux-md-component-level", NULL, NULL, NULL, G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_MD_COMPONENT_POSITION,
                                   g_param_spec_int ("linux-md-component-position",
                                                     NULL,
                                                     NULL,
                                                     0,
                                                     G_MAXINT,
                                                     0,
                                                     G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_MD_COMPONENT_NUM_RAID_DEVICES,
                                   g_param_spec_int ("linux-md-component-num-raid-devices",
                                                     NULL,
                                                     NULL,
                                                     0,
                                                     G_MAXINT,
                                                     0,
                                                     G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_MD_COMPONENT_UUID,
                                   g_param_spec_string ("linux-md-component-uuid", NULL, NULL, NULL, G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_MD_COMPONENT_HOME_HOST,
                                   g_param_spec_string ("linux-md-component-home-host",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_MD_COMPONENT_NAME,
                                   g_param_spec_string ("linux-md-component-name", NULL, NULL, NULL, G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_MD_COMPONENT_VERSION,
                                   g_param_spec_string ("linux-md-component-version",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_MD_COMPONENT_HOLDER,
                                   g_param_spec_boxed ("linux-md-component-holder",
                                                       NULL,
                                                       NULL,
                                                       DBUS_TYPE_G_OBJECT_PATH,
                                                       G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_MD_COMPONENT_STATE,
                                   g_param_spec_boxed ("linux-md-component-state",
                                                       NULL,
                                                       NULL,
                                                       dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
                                                       G_PARAM_READABLE));

  g_object_class_install_property (object_class, PROP_LINUX_MD_STATE, g_param_spec_string ("linux-md-state",
                                                                                           NULL,
                                                                                           NULL,
                                                                                           NULL,
                                                                                           G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_LINUX_MD_LEVEL, g_param_spec_string ("linux-md-level",
                                                                                           NULL,
                                                                                           NULL,
                                                                                           NULL,
                                                                                           G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_MD_NUM_RAID_DEVICES,
                                   g_param_spec_int ("linux-md-num-raid-devices",
                                                     NULL,
                                                     NULL,
                                                     0,
                                                     G_MAXINT,
                                                     0,
                                                     G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_LINUX_MD_UUID, g_param_spec_string ("linux-md-uuid",
                                                                                          NULL,
                                                                                          NULL,
                                                                                          NULL,
                                                                                          G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_LINUX_MD_HOME_HOST, g_param_spec_string ("linux-md-home-host",
                                                                                               NULL,
                                                                                               NULL,
                                                                                               NULL,
                                                                                               G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_LINUX_MD_NAME, g_param_spec_string ("linux-md-name",
                                                                                          NULL,
                                                                                          NULL,
                                                                                          NULL,
                                                                                          G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_LINUX_MD_VERSION, g_param_spec_string ("linux-md-version",
                                                                                             NULL,
                                                                                             NULL,
                                                                                             NULL,
                                                                                             G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_MD_SLAVES,
                                   g_param_spec_boxed ("linux-md-slaves",
                                                       NULL,
                                                       NULL,
                                                       dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
                                                       G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_MD_IS_DEGRADED,
                                   g_param_spec_boolean ("linux-md-is-degraded", NULL, NULL, FALSE, G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_MD_SYNC_ACTION,
                                   g_param_spec_string ("linux-md-sync-action", NULL, NULL, NULL, G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_MD_SYNC_PERCENTAGE,
                                   g_param_spec_double ("linux-md-sync-percentage",
                                                        NULL,
                                                        NULL,
                                                        0.0,
                                                        100.0,
                                                        0.0,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class, PROP_LINUX_MD_SYNC_SPEED, g_param_spec_uint64 ("linux-md-sync-speed",
                                                                                                NULL,
                                                                                                NULL,
                                                                                                0,
                                                                                                G_MAXUINT64,
                                                                                                0,
                                                                                                G_PARAM_READABLE));

  g_object_class_install_property (object_class,
                                   PROP_LINUX_LVM2_LV_NAME,
                                   g_param_spec_string ("linux-lvm2-lv-name",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_LVM2_LV_UUID,
                                   g_param_spec_string ("linux-lvm2-lv-uuid",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_LVM2_LV_GROUP_NAME,
                                   g_param_spec_string ("linux-lvm2-lv-group-name",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_LVM2_LV_GROUP_UUID,
                                   g_param_spec_string ("linux-lvm2-lv-group-uuid",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));

  g_object_class_install_property (object_class,
                                   PROP_LINUX_LVM2_PV_UUID,
                                   g_param_spec_string ("linux-lvm2-pv-uuid",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_LVM2_PV_NUM_METADATA_AREAS,
                                   g_param_spec_uint ("linux-lvm2-pv-num-metadata-areas",
                                                      NULL,
                                                      NULL,
                                                      0,
                                                      G_MAXUINT,
                                                      0,
                                                      G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_LVM2_PV_GROUP_NAME,
                                   g_param_spec_string ("linux-lvm2-pv-group-name",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_LVM2_PV_GROUP_UUID,
                                   g_param_spec_string ("linux-lvm2-pv-group-uuid",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_LVM2_PV_GROUP_SIZE,
                                   g_param_spec_uint64 ("linux-lvm2-pv-group-size",
                                                        NULL,
                                                        NULL,
                                                        0,
                                                        G_MAXUINT64,
                                                        0,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_LVM2_PV_GROUP_UNALLOCATED_SIZE,
                                   g_param_spec_uint64 ("linux-lvm2-pv-group-unallocated-size",
                                                        NULL,
                                                        NULL,
                                                        0,
                                                        G_MAXUINT64,
                                                        0,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_LVM2_PV_GROUP_SEQUENCE_NUMBER,
                                   g_param_spec_uint64 ("linux-lvm2-pv-group-sequence-number",
                                                        NULL,
                                                        NULL,
                                                        0,
                                                        G_MAXUINT64,
                                                        0,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_LVM2_PV_GROUP_EXTENT_SIZE,
                                   g_param_spec_uint64 ("linux-lvm2-pv-group-extent-size",
                                                        NULL,
                                                        NULL,
                                                        0,
                                                        G_MAXUINT64,
                                                        0,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_LVM2_PV_GROUP_PHYSICAL_VOLUMES,
                                   g_param_spec_boxed ("linux-lvm2-pv-group-physical-volumes",
                                                       NULL,
                                                       NULL,
                                                       dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
                                                       G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_LVM2_PV_GROUP_LOGICAL_VOLUMES,
                                   g_param_spec_boxed ("linux-lvm2-pv-group-logical-volumes",
                                                       NULL,
                                                       NULL,
                                                       dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
                                                       G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_DMMP_COMPONENT_HOLDER,
                                   g_param_spec_boxed ("linux-dmmp-component-holder",
                                                       NULL,
                                                       NULL,
                                                       DBUS_TYPE_G_OBJECT_PATH,
                                                       G_PARAM_READABLE));

  g_object_class_install_property (object_class,
                                   PROP_LINUX_DMMP_NAME,
                                   g_param_spec_string ("linux-dmmp-name",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_DMMP_PARAMETERS,
                                   g_param_spec_string ("linux-dmmp-parameters",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));
  g_object_class_install_property (object_class,
                                   PROP_LINUX_DMMP_SLAVES,
                                   g_param_spec_boxed ("linux-dmmp-slaves",
                                                       NULL,
                                                       NULL,
                                                       dbus_g_type_get_collection ("GPtrArray",
                                                                                   DBUS_TYPE_G_OBJECT_PATH),
                                                       G_PARAM_READABLE));

  g_object_class_install_property (object_class,
                                   PROP_LINUX_LOOP_FILENAME,
                                   g_param_spec_string ("linux-loop-filename",
                                                        NULL,
                                                        NULL,
                                                        NULL,
                                                        G_PARAM_READABLE));
}

Project: udisks
File: device.c

device_constructor (GType type,
                    guint n_construct_properties,
                    GObjectConstructParam *construct_properties)
{
  Device *device;
  DeviceClass *klass;

  klass = DEVICE_CLASS (g_type_class_peek (TYPE_DEVICE));

  device = DEVICE (G_OBJECT_CLASS (device_parent_class)->constructor (type,
                                                                      n_construct_properties,
                                                                      construct_properties));
  return G_OBJECT (device);
}

Project: udisks
File: device.c

device_drive_ata_smart_initiate_selftest (Device *device,
                                          const char *test,
                                          gchar **options,
                                          DBusGMethodInvocation *context)
{
  if (!device->priv->drive_ata_smart_is_available)
    {
      throw_error (context, ERROR_FAILED, "Device does not support ATA SMART");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           "org.freedesktop.udisks.drive-ata-smart-selftest",
                           "DriveAtaSmartInitiateSelftest",
                           TRUE,
                           device_drive_ata_smart_initiate_selftest_authorized_cb,
                           context,
                           2,
                           g_strdup (test),
                           g_free,
                           g_strdupv (options),
                           g_strfreev);

 out:
  return TRUE;
}

Project: udisks

device_drive_ata_smart_initiate_selftest_authorized_cb (Daemon *daemon,
                                                        Device *device,
                                                        DBusGMethodInvocation *context,
                                                        const gchar *action_id,
                                                        guint num_user_data,
                                                        gpointer *user_data_elements)
{
  const gchar *test = user_data_elements[0];
  /* TODO: use options */
  int n;
  char *argv[10];
  GError *error;
  const gchar *job_name;

  if (g_strcmp0 (test, "short") == 0)
    {
      job_name = "DriveAtaSmartSelftestShort";
    }
  else if (g_strcmp0 (test, "extended") == 0)
    {
      job_name = "DriveAtaSmartSelftestExtended";
    }
  else if (g_strcmp0 (test, "conveyance") == 0)
    {
      job_name = "DriveAtaSmartSelftestConveyance";
    }
  else
    {
      throw_error (context, ERROR_FAILED, "Malformed test");
      goto out;
    }

  n = 0;
  argv[n++] = "udisks-helper-ata-smart-selftest";
  argv[n++] = device->priv->device_file;
  argv[n++] = (char *) test;
  argv[n++] = NULL;

  error = NULL;
  if (!job_new (context,
                job_name,
                TRUE,
                device,
                argv,
                NULL,
                drive_ata_smart_initiate_selftest_completed_cb,
                FALSE,
                NULL,
                NULL))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

device_drive_ata_smart_refresh_data (Device *device,
                                     char **options,
                                     DBusGMethodInvocation *context)
{
  const gchar *action_id;

  action_id = NULL;
  if (context != NULL)
    {
      action_id = "org.freedesktop.udisks.drive-ata-smart-refresh";
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           action_id,
                           "DriveAtaSmartRefreshData",
                           TRUE,
                           device_drive_ata_smart_refresh_data_authorized_cb,
                           context,
                           1,
                           g_strdupv (options),
                           g_strfreev);

  return TRUE;
}

Project: udisks
File: device.c

device_drive_ata_smart_refresh_data_authorized_cb (Daemon *daemon,
                                                   Device *device,
                                                   DBusGMethodInvocation *context,
                                                   const gchar *action_id,
                                                   guint num_user_data,
                                                   gpointer *user_data_elements)
{
  char **options = user_data_elements[0];
  int n;
  char *argv[10];
  GError *error;
  const char *simuldata;
  gboolean nowakeup;
  uid_t caller_uid;

  PROFILE ("device_drive_ata_smart_refresh_data_authorized_cb(device=%s) start", device->priv->native_path);
  daemon_local_get_uid (device->priv->daemon, &caller_uid, context);

  simuldata = NULL;
  nowakeup = FALSE;
  for (n = 0; options[n] != NULL; n++)
    {
      if (g_str_has_prefix (options[n], "simulate="))
        {
          if (context != NULL)
            {
              if (caller_uid != 0)
                {
                  throw_error (context, ERROR_FAILED, "Only uid 0 may use the simulate= option");
                  goto out;
                }
            }
          simuldata = (const char *) options[n] + 9;
          device_set_drive_ata_smart_is_available (device, TRUE);
        }
      else if (strcmp (options[n], "nowakeup") == 0)
        {
          nowakeup = TRUE;
        }
    }

  if (!device->priv->drive_ata_smart_is_available)
    {
      throw_error (context, ERROR_FAILED, "Device does not support ATA SMART");
      goto out;
    }

  if (simuldata != NULL)
    {
      n = 0;
      argv[n++] = "base64"; /* provided by coreutils */
      argv[n++] = (char *) simuldata;
      argv[n++] = NULL;
    }
  else
    {
      n = 0;
      argv[n++] = "udisks-helper-ata-smart-collect";
      argv[n++] = device->priv->device_file;
      argv[n++] = nowakeup ? "1" : "0";
      argv[n++] = NULL;
    }

  error = NULL;

  if (!job_new (context, NULL, /* don't run this as a job */
                FALSE, device, argv, NULL, drive_ata_smart_refresh_data_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  ;
  PROFILE ("device_drive_ata_smart_refresh_data_authorized_cb(device=%s) end", device->priv->native_path);
}

Project: udisks
File: device.c

device_drive_benchmark (Device *device,
                        gboolean do_write_benchmark,
                        char **options,
                        DBusGMethodInvocation *context)
{
  if (!device->priv->device_is_drive)
    {
      throw_error (context, ERROR_FAILED, "Device is not a drive");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           "org.freedesktop.udisks.change",
                           "DriveBenchmark",
                           TRUE,
                           device_drive_benchmark_authorized_cb,
                           context,
                           2,
                           GINT_TO_POINTER (do_write_benchmark),
                           NULL,
                           g_strdupv (options),
                           g_strfreev);

 out:
  return TRUE;
}

Project: udisks
File: device.c

device_drive_benchmark_authorized_cb (Daemon *daemon,
                                      Device *device,
                                      DBusGMethodInvocation *context,
                                      const gchar *action_id,
                                      guint num_user_data,
                                      gpointer *user_data_elements)
{
  gboolean do_write_benchmark = GPOINTER_TO_INT (user_data_elements[0]);
  gchar **options = user_data_elements[1];
  gchar *argv[16];
  guint n;

  if (!device->priv->device_is_drive)
    {
      throw_error (context, ERROR_FAILED, "Device is not a drive");
      goto out;
    }

  if (do_write_benchmark)
    {
      if (device->priv->device_is_partition_table)
        {
          throw_error (context, ERROR_FAILED, "A partition table was detected - write benchmarking requires "
                       "the disk to be completely empty");
          goto out;
        }

      if (device->priv->id_usage != NULL)
        {
          throw_error (context, ERROR_FAILED, "The disk seems to have usage `%s' - write benchmarking requires "
                       "the disk to be completely empty", device->priv->id_usage);
          goto out;
        }
    }

  for (n = 0; options[n] != NULL; n++)
    {
      const char *option = options[n];
      throw_error (context, ERROR_INVALID_OPTION, "Unknown option %s", option);
      goto out;
    }

  n = 0;
  argv[n++] = "udisks-helper-drive-benchmark";
  argv[n++] = device->priv->device_file;
  argv[n++] = do_write_benchmark ? "1" : "0";
  argv[n++] = NULL;

  if (!job_new (context, "DriveBenchmark", TRUE, device, argv, NULL, drive_benchmark_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

device_drive_detach (Device *device,
                     char **options,
                     DBusGMethodInvocation *context)
{
  if (!device->priv->device_is_drive)
    {
      throw_error (context, ERROR_FAILED, "Device is not a drive");
      goto out;
    }

  if (!device->priv->drive_can_detach)
    {
      throw_error (context, ERROR_FAILED, "Device is not detachable");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           "org.freedesktop.udisks.drive-detach",
                           "DriveDetach",
                           TRUE,
                           device_drive_detach_authorized_cb,
                           context,
                           1,
                           g_strdupv (options),
                           g_strfreev);

 out:
  return TRUE;
}

Project: udisks
File: device.c

device_drive_detach_authorized_cb (Daemon *daemon,
                                   Device *device,
                                   DBusGMethodInvocation *context,
                                   const gchar *action_id,
                                   guint num_user_data,
                                   gpointer *user_data_elements)
{
  gchar **options = user_data_elements[0];
  int n;
  char *argv[16];
  GError *error;
  char *mount_path;

  error = NULL;
  mount_path = NULL;

  if (!device->priv->device_is_drive)
    {
      throw_error (context, ERROR_FAILED, "Device is not a drive");
      goto out;
    }

  if (!device->priv->drive_can_detach)
    {
      throw_error (context, ERROR_FAILED, "Device is not detachable");
      goto out;
    }

  if (device_local_is_busy (device, TRUE, &error))
    {
      dbus_g_method_return_error (context, error);
      g_error_free (error);
      goto out;
    }

  for (n = 0; options[n] != NULL; n++)
    {
      const char *option = options[n];
      throw_error (context, ERROR_INVALID_OPTION, "Unknown option %s", option);
      goto out;
    }

  n = 0;
  argv[n++] = "udisks-helper-drive-detach";
  argv[n++] = device->priv->device_file;
  argv[n++] = NULL;

  if (!job_new (context, "DriveDetach", FALSE, device, argv, NULL, drive_detach_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

device_drive_eject (Device *device,
                    char **options,
                    DBusGMethodInvocation *context)
{
  if (!device->priv->device_is_drive)
    {
      throw_error (context, ERROR_FAILED, "Device is not a drive");
      goto out;
    }

  if (!device->priv->device_is_media_available)
    {
      throw_error (context, ERROR_FAILED, "No media in drive");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           "org.freedesktop.udisks.drive-eject",
                           "DriveEject",
                           TRUE,
                           device_drive_eject_authorized_cb,
                           context,
                           1,
                           g_strdupv (options),
                           g_strfreev);

 out:
  return TRUE;
}

Project: udisks
File: device.c

device_drive_eject_authorized_cb (Daemon *daemon,
                                  Device *device,
                                  DBusGMethodInvocation *context,
                                  const gchar *action_id,
                                  guint num_user_data,
                                  gpointer *user_data_elements)
{
  gchar **options = user_data_elements[0];
  int n;
  char *argv[16];
  GError *error;
  char *mount_path;

  error = NULL;
  mount_path = NULL;

  if (!device->priv->device_is_drive)
    {
      throw_error (context, ERROR_FAILED, "Device is not a drive");
      goto out;
    }

  if (!device->priv->device_is_media_available)
    {
      throw_error (context, ERROR_FAILED, "No media in drive");
      goto out;
    }

  if (device_local_is_busy (device, TRUE, &error))
    {
      dbus_g_method_return_error (context, error);
      g_error_free (error);
      goto out;
    }

  for (n = 0; options[n] != NULL; n++)
    {
      const char *option = options[n];
      throw_error (context, ERROR_INVALID_OPTION, "Unknown option %s", option);
      goto out;
    }

  n = 0;
  argv[n++] = "eject";
  argv[n++] = device->priv->device_file;
  argv[n++] = NULL;

  if (!job_new (context, "DriveEject", FALSE, device, argv, NULL, drive_eject_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

device_drive_inhibit_polling (Device *device,
                              char **options,
                              DBusGMethodInvocation *context)
{
  if (!device->priv->device_is_drive)
    {
      throw_error (context, ERROR_FAILED, "Device is not a drive");
      goto out;
    }

  if (!device->priv->device_is_media_change_detection_inhibitable)
    {
      throw_error (context, ERROR_FAILED, "Media detection cannot be inhibited");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           "org.freedesktop.udisks.inhibit-polling",
                           "DriveInhibitPolling",
                           TRUE,
                           device_drive_inhibit_polling_authorized_cb,
                           context,
                           1,
                           g_strdupv (options),
                           g_strfreev);

 out:
  return TRUE;
}

Project: udisks
File: device.c

device_drive_inhibit_polling_authorized_cb (Daemon *daemon,
                                            Device *device,
                                            DBusGMethodInvocation *context,
                                            const gchar *action_id,
                                            guint num_user_data,
                                            gpointer *user_data_elements)
{
  gchar **options = user_data_elements[0];
  Inhibitor *inhibitor;
  guint n;

  for (n = 0; options[n] != NULL; n++)
    {
      const char *option = options[n];
      throw_error (context, ERROR_INVALID_OPTION, "Unknown option %s", option);
      goto out;
    }

  inhibitor = inhibitor_new (context);

  device->priv->polling_inhibitors = g_list_prepend (device->priv->polling_inhibitors, inhibitor);
  g_signal_connect (inhibitor, "disconnected", G_CALLBACK (polling_inhibitor_disconnected_cb), device);

  update_info (device);
  drain_pending_changes (device, FALSE);
  daemon_local_update_poller (device->priv->daemon);

  dbus_g_method_return (context, inhibitor_get_cookie (inhibitor));

 out:
  ;
}

Project: udisks
File: device.c

device_drive_poll_media (Device *device,
                         DBusGMethodInvocation *context)
{
  if (!device->priv->device_is_drive)
    {
      throw_error (context, ERROR_FAILED, "Device is not a drive");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           "org.freedesktop.udisks.inhibit-polling",
                           "DrivePollMedia",
                           TRUE,
                           device_drive_poll_media_authorized_cb,
                           context,
                           0);
 out:
  return TRUE;
}

Project: udisks
File: device.c

device_drive_poll_media_authorized_cb (Daemon *daemon,
                                       Device *device,
                                       DBusGMethodInvocation *context,
                                       const gchar *action_id,
                                       guint num_user_data,
                                       gpointer *user_data_elements)
{
  int n;
  char *argv[16];

  n = 0;
  argv[n++] = "udisks-helper-drive-poll";
  argv[n++] = device->priv->device_file;
  argv[n++] = NULL;

  if (!job_new (context, "DrivePollMedia", FALSE, device, argv, NULL, drive_poll_media_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

device_drive_set_spindown_timeout (Device *device,
                                   int timeout_seconds,
                                   char **options,
                                   DBusGMethodInvocation *context)
{
  if (!device->priv->device_is_drive)
    {
      throw_error (context, ERROR_FAILED, "Device is not a drive");
      goto out;
    }

  if (!device->priv->drive_can_spindown)
    {
      throw_error (context, ERROR_FAILED, "Cannot spindown device");
      goto out;
    }

  if (timeout_seconds < 1)
    {
      throw_error (context, ERROR_FAILED, "Timeout seconds must be at least 1");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           "org.freedesktop.udisks.drive-set-spindown",
                           "DriveSetSpindownTimeout",
                           TRUE,
                           device_drive_set_spindown_timeout_authorized_cb,
                           context,
                           2,
                           GINT_TO_POINTER (timeout_seconds),
                           NULL,
                           g_strdupv (options),
                           g_strfreev);

 out:
  return TRUE;
}

Project: udisks
File: device.c

device_drive_set_spindown_timeout_authorized_cb (Daemon *daemon,
                                                 Device *device,
                                                 DBusGMethodInvocation *context,
                                                 const gchar *action_id,
                                                 guint num_user_data,
                                                 gpointer *user_data_elements)
{
  gint timeout_seconds = GPOINTER_TO_INT (user_data_elements[0]);
  gchar **options = user_data_elements[1];
  Inhibitor *inhibitor;
  guint n;

  if (!device->priv->device_is_drive)
    {
      throw_error (context, ERROR_FAILED, "Device is not a drive");
      goto out;
    }

  if (!device->priv->drive_can_spindown)
    {
      throw_error (context, ERROR_FAILED, "Cannot spindown device");
      goto out;
    }

  if (timeout_seconds < 1)
    {
      throw_error (context, ERROR_FAILED, "Timeout seconds must be at least 1");
      goto out;
    }

  for (n = 0; options[n] != NULL; n++)
    {
      const char *option = options[n];
      throw_error (context, ERROR_INVALID_OPTION, "Unknown option %s", option);
      goto out;
    }

  inhibitor = inhibitor_new (context);

  g_object_set_data (G_OBJECT (inhibitor), "spindown-timeout-seconds", GINT_TO_POINTER (timeout_seconds));

  device->priv->spindown_inhibitors = g_list_prepend (device->priv->spindown_inhibitors, inhibitor);
  g_signal_connect (inhibitor, "disconnected", G_CALLBACK (spindown_inhibitor_disconnected_cb), device);

  update_info (device);
  drain_pending_changes (device, FALSE);
  daemon_local_update_spindown (device->priv->daemon);

  dbus_g_method_return (context, inhibitor_get_cookie (inhibitor));

 out:
  ;
}

Project: udisks
File: device.c

device_drive_uninhibit_polling (Device *device,
                                char *cookie,
                                DBusGMethodInvocation *context)
{
  const gchar *sender;
  Inhibitor *inhibitor;
  GList *l;

  sender = dbus_g_method_get_sender (context);

  inhibitor = NULL;
  for (l = device->priv->polling_inhibitors; l != NULL; l = l->next)
    {
      Inhibitor *i = INHIBITOR (l->data);

      if (g_strcmp0 (inhibitor_get_unique_dbus_name (i), sender) == 0 && g_strcmp0 (inhibitor_get_cookie (i), cookie)
          == 0)
        {
          inhibitor = i;
          break;
        }
    }

  if (inhibitor == NULL)
    {
      throw_error (context, ERROR_FAILED, "No such inhibitor");
      goto out;
    }

  device->priv->polling_inhibitors = g_list_remove (device->priv->polling_inhibitors, inhibitor);
  g_object_unref (inhibitor);

  update_info (device);
  drain_pending_changes (device, FALSE);
  daemon_local_update_poller (device->priv->daemon);

  dbus_g_method_return (context);

 out:
  return TRUE;
}

Project: udisks
File: device.c

device_filesystem_check (Device *device,
                         char **options,
                         DBusGMethodInvocation *context)
{
  daemon_local_check_auth (device->priv->daemon,
                           device,
                           device->priv->device_is_system_internal ?
                           "org.freedesktop.udisks.filesystem-check-system-internal" :
                           "org.freedesktop.udisks.filesystem-check",
                           "FilesystemCheck",
                           TRUE,
                           device_filesystem_check_authorized_cb,
                           context,
                           1,
                           g_strdupv (options),
                           g_strfreev);
  return TRUE;
}

Project: udisks

device_filesystem_check_authorized_cb (Daemon *daemon,
                                       Device *device,
                                       DBusGMethodInvocation *context,
                                       const gchar *action_id,
                                       guint num_user_data,
                                       gpointer *user_data_elements)
{
  /* TODO: use options! */
  int n;
  char *argv[16];
  GError *error;

  /* TODO: change when we have a file system that supports online fsck */
  if (device->priv->device_is_mounted)
    {
      throw_error (context, ERROR_BUSY, "Device is mounted and no online capability in fsck tool for file system");
      goto out;
    }

  n = 0;
  argv[n++] = "fsck";
  argv[n++] = "-a";
  argv[n++] = device->priv->device_file;
  argv[n++] = NULL;

  error = NULL;
  if (!job_new (context, "FilesystemCheck", FALSE, device, argv, NULL, filesystem_check_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

device_filesystem_create (Device *device,
                          const char *fstype,
                          char **options,
                          DBusGMethodInvocation *context)
{
  daemon_local_check_auth (device->priv->daemon,
                           device,
                           device->priv->device_is_system_internal ? "org.freedesktop.udisks.change-system-internal"
                           : "org.freedesktop.udisks.change",
                           "FilesystemCreate",
                           TRUE,
                           device_filesystem_create_authorized_cb,
                           context,
                           2,
                           g_strdup (fstype),
                           g_free,
                           g_strdupv (options),
                           g_strfreev);
  return TRUE;
}

Project: udisks
File: device.c

device_filesystem_create_authorized_cb (Daemon *daemon,
                                        Device *device,
                                        DBusGMethodInvocation *context,
                                        const gchar *action_id,
                                        guint num_user_data,
                                        gpointer *user_data_elements)
{
  const gchar *fstype = user_data_elements[0];
  gchar **options = user_data_elements[1];
  device_filesystem_create_internal (device, fstype, options, NULL, NULL, context);
}

Project: udisks
File: device.c

device_filesystem_create_internal (Device *device,
                                   const char *fstype,
                                   char **options,
                                   FilesystemCreateHookFunc hook_func,
                                   gpointer hook_user_data,
                                   DBusGMethodInvocation *context)
{
  int n, m;
  char *argv[128];
  GError *error;
  char *s;
  char *options_for_stdin;
  char *passphrase_stdin;
  MkfsData *mkfs_data;

  options_for_stdin = NULL;
  passphrase_stdin = NULL;
  error = NULL;

  if (device_local_is_busy (device, TRUE, &error))
    {
      dbus_g_method_return_error (context, error);
      g_error_free (error);
      goto out;
    }

  if (strlen (fstype) == 0)
    {
      throw_error (context, ERROR_FAILED, "fstype not specified");
      goto out;
    }

  /* search for luks_encrypt=<passphrase> and do a detour if that's specified */
  for (n = 0; options[n] != NULL; n++)
    {
      if (g_str_has_prefix (options[n], "luks_encrypt="))
        {
          MkfsLuksData *mkfse_data;

          /* So this is a request to create an luks device to put the
           * file system on; save all options for mkfs (except luks_encrypt=) for
           * later invocation once we have a cleartext device.
           */

          mkfse_data = g_new0 (MkfsLuksData, 1);
          mkfse_data->refcount = 1;
          mkfse_data->context = context;
          mkfse_data->device = g_object_ref (device);
          mkfse_data->passphrase = g_strdup (options[n] + sizeof("luks_encrypt=") - 1);
          mkfse_data->mkfs_hook_func = hook_func;
          mkfse_data->mkfs_hook_user_data = hook_user_data;
          mkfse_data->fstype = g_strdup (fstype);
          mkfse_data->options = g_strdupv (options);
          g_free (mkfse_data->options[n]);
          for (m = n; mkfse_data->options[m] != NULL; m++)
            {
              mkfse_data->options[m] = mkfse_data->options[m + 1];
            }

          passphrase_stdin = g_strdup_printf ("%s\n", mkfse_data->passphrase);

          n = 0;
          argv[n++] = "cryptsetup";
          argv[n++] = "-q";
          argv[n++] = "luksFormat";
          argv[n++] = device->priv->device_file;
          argv[n++] = NULL;

          error = NULL;
          if (!job_new (context,
                        "LuksFormat",
                        TRUE,
                        device,
                        argv,
                        passphrase_stdin,
                        filesystem_create_create_luks_device_completed_cb,
                        FALSE,
                        mkfse_data,
                        (GDestroyNotify) mkfse_data_unref))
            {
              goto out;
            }

          goto out;
        }
    }

  mkfs_data = g_new (MkfsData, 1);
  mkfs_data->hook_func = hook_func;
  mkfs_data->hook_user_data = hook_user_data;

  /* pass options on stdin as it may contain secrets */
  s = g_strjoinv ("\n", options);
  options_for_stdin = g_strconcat (s, "\n\n", NULL);
  g_free (s);

  n = 0;
  argv[n++] = "udisks-helper-mkfs";
  argv[n++] = (char *) fstype;
  argv[n++] = device->priv->device_file;
  argv[n++] = device->priv->device_is_partition_table ? "1" : "0";
  argv[n++] = NULL;

  if (!job_new (context,
                "FilesystemCreate",
                TRUE,
                device,
                argv,
                options_for_stdin,
                filesystem_create_completed_cb,
                FALSE,
                mkfs_data,
                (GDestroyNotify) mkfs_data_unref))
    {
      goto out;
    }

 out:
  g_free (options_for_stdin);
  if (passphrase_stdin != NULL)
    {
      memset (passphrase_stdin, '\0', strlen (passphrase_stdin));
      g_free (passphrase_stdin);
    }
  return TRUE;
}

Project: udisks
File: device.c

device_filesystem_list_open_files (Device *device,
                                   DBusGMethodInvocation *context)
{
  if (!device->priv->device_is_mounted || device->priv->device_mount_paths->len == 0)
    {
      throw_error (context, ERROR_FAILED, "Device is not mounted");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           device->priv->device_is_system_internal ? "org.freedesktop.udisks.filesystem-lsof-system-internal"
                           : "org.freedesktop.udisks.filesystem-lsof",
                           "FilesystemListOpenFiles",
                           TRUE,
                           device_filesystem_list_open_files_authorized_cb,
                           context,
                           0);

 out:
  return TRUE;
}

Project: udisks
File: device.c

device_filesystem_list_open_files_authorized_cb (Daemon *daemon,
                                                 Device *device,
                                                 DBusGMethodInvocation *context,
                                                 const gchar *action_id,
                                                 guint num_user_data,
                                                 gpointer *user_data_elements)
{
  int n;
  char *argv[16];
  GError *error;

  if (!device->priv->device_is_mounted || device->priv->device_mount_paths->len == 0)
    {
      throw_error (context, ERROR_FAILED, "Device is not mounted");
      goto out;
    }

  n = 0;
  argv[n++] = "lsof";
  argv[n++] = "-t";
  argv[n++] = ((gchar **) device->priv->device_mount_paths->pdata)[0];
  argv[n++] = NULL;

  error = NULL;
  if (!job_new (context, NULL, /* don't run this as a job */
                FALSE, device, argv, NULL, filesystem_list_open_files_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

device_filesystem_mount (Device *device,
                         const char *filesystem_type,
                         char **given_options,
                         DBusGMethodInvocation *context)
{
  const gchar *action_id;
  gboolean auth_no_user_interaction;
  gchar **options_to_pass;
  guint n;
  guint m;

  if (is_device_in_fstab (device, NULL))
    {
      action_id = NULL;
    }
  else
    {
      if (device->priv->device_is_system_internal)
        action_id = "org.freedesktop.udisks.filesystem-mount-system-internal";
      else
        action_id = "org.freedesktop.udisks.filesystem-mount";
    }

  auth_no_user_interaction = FALSE;
  options_to_pass = g_strdupv (given_options);
  for (n = 0; options_to_pass != NULL && options_to_pass[n] != NULL; n++)
    {
      if (g_strcmp0 (options_to_pass[n], "auth_no_user_interaction") == 0)
        {
          auth_no_user_interaction = TRUE;
          g_free (options_to_pass[n]);
          for (m = n; options_to_pass[m + 1] != NULL; m++)
            options_to_pass[m] = options_to_pass[m + 1];
          options_to_pass[m] = NULL;
          break;
        }
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           action_id,
                           "FilesystemMount",
                           !auth_no_user_interaction,
                           device_filesystem_mount_authorized_cb,
                           context,
                           2,
                           g_strdup (filesystem_type),
                           g_free,
                           options_to_pass,
                           g_strfreev);

  return TRUE;
}

Project: udisks
File: device.c

device_filesystem_mount_authorized_cb (Daemon *daemon,
                                       Device *device,
                                       DBusGMethodInvocation *context,
                                       const gchar *action_id,
                                       guint num_user_data,
                                       gpointer *user_data_elements)
{
  const gchar *filesystem_type = user_data_elements[0];
  gchar **given_options = user_data_elements[1];
  int n;
  GString *s;
  char *argv[10];
  char *mount_point;
  char *fstype;
  char *mount_options;
  GError *error;
  uid_t caller_uid;
  gboolean remove_dir_on_unmount;
  const FSMountOptions *fsmo;
  char **options;
  char uid_buf[32];

  fstype = NULL;
  options = NULL;
  mount_options = NULL;
  mount_point = NULL;
  remove_dir_on_unmount = FALSE;
  error = NULL;

  daemon_local_get_uid (device->priv->daemon, &caller_uid, context);

  if (device->priv->id_usage == NULL || strcmp (device->priv->id_usage, "filesystem") != 0)
    {
      if ((g_strcmp0 (filesystem_type, "auto") == 0 || g_strcmp0 (filesystem_type, "") == 0) && device->priv->id_usage
          == NULL)
        {
          /* if we don't know the usage of the device and 'auto' or '' is passed for fstype
           * then just try that.. this is to make, for example, mounting /dev/fd0 work (we
           * don't probe such devices for filesystems in udev)
           */
        }
      else
        {
          throw_error (context, ERROR_FAILED, "Not a mountable file system");
          goto out;
        }
    }

  if (device_local_is_busy (device, FALSE, &error))
    {
      dbus_g_method_return_error (context, error);
      g_error_free (error);
      goto out;
    }

  /* Check if the device is referenced in /etc/fstab; if so, attempt to
   * mount the device as the user
   */
  if (is_device_in_fstab (device, &mount_point))
    {
      n = 0;
      snprintf (uid_buf, sizeof uid_buf, "%d", caller_uid);
      argv[n++] = "udisks-helper-fstab-mounter";
      argv[n++] = "mount";
      argv[n++] = device->priv->device_file;
      argv[n++] = uid_buf;
      argv[n++] = NULL;
      goto run_job;
    }

  /* set the fstype */
  fstype = NULL;
  if (strlen (filesystem_type) == 0)
    {
      if (device->priv->id_type != NULL && strlen (device->priv->id_type) > 0)
        {
          fstype = g_strdup (device->priv->id_type);
        }
      else
        {
          fstype = g_strdup ("auto");
        }
    }
  else
    {
      fstype = g_strdup (filesystem_type);
    }

  fsmo = find_mount_options_for_fs (fstype);

  /* always prepend some reasonable default mount options; these are
   * chosen here; the user can override them if he wants to
   */
  options = prepend_default_mount_options (fsmo, caller_uid, given_options);

  /* validate mount options and check for authorizations */
  s = g_string_new ("uhelper=udisks,nodev,nosuid");
  for (n = 0; options[n] != NULL; n++)
    {
      const char *option = options[n];

      /* avoid attacks like passing "shortname=lower,uid=0" as a single mount option */
      if (strstr (option, ",") != NULL)
        {
          throw_error (context, ERROR_INVALID_OPTION, "Malformed mount option: ", option);
          g_string_free (s, TRUE);
          goto out;
        }

      /* first check if the mount option is allowed */
      if (!is_mount_option_allowed (fsmo, option, caller_uid))
        {
          throw_error (context, ERROR_INVALID_OPTION, "Mount option %s is not allowed", option);
          g_string_free (s, TRUE);
          goto out;
        }

      g_string_append_c (s, ',');
      g_string_append (s, option);
    }
  mount_options = g_string_free (s, FALSE);

  g_print ("**** USING MOUNT OPTIONS '%s' FOR DEVICE %s\n", mount_options, device->priv->device_file);

  if (device->priv->device_is_mounted)
    {
      throw_error (context, ERROR_FAILED, "Device is already mounted");
      goto out;
    }

  /* Determine the mount point to use.
   *
   * TODO: use characteristics of the drive such as the name, connection etc.
   *       to get better names (/media/disk is kinda lame).
   */
  if (device->priv->id_label != NULL && strlen (device->priv->id_label) > 0)
    {
      GString * s;

      s = g_string_new ("/media/");
      for (n = 0; device->priv->id_label[n] != '\0'; n++)
        {
          gint c = device->priv->id_label[n];
          if (c == '/')
            g_string_append_c (s, '_');
          else
            g_string_append_c (s, c);
        }

      mount_point = g_string_free (s, FALSE);
    }
  else if (device->priv->id_uuid != NULL && strlen (device->priv->id_uuid) > 0)
    {

      GString * s;

      s = g_string_new ("/media/");
      for (n = 0; device->priv->id_uuid[n] != '\0'; n++)
        {
          gint c = device->priv->id_uuid[n];
          if (c == '/')
            g_string_append_c (s, '_');
          else
            g_string_append_c (s, c);
        }

      mount_point = g_string_free (s, FALSE);

    }
  else
    {
      mount_point = g_strdup ("/media/disk");
    }

 try_another_mount_point:
  /* ... then uniqify the mount point and mkdir it */
  if (g_file_test (mount_point, G_FILE_TEST_EXISTS))
    {
      char *s = mount_point;
      /* TODO: append numbers instead of _, __ and so on */
      mount_point = g_strdup_printf ("%s_", mount_point);
      g_free (s);
      goto try_another_mount_point;
    }

  remove_dir_on_unmount = TRUE;

  if (g_mkdir (mount_point, 0700) != 0)
    {
      throw_error (context, ERROR_FAILED, "Error creating moint point: %m");
      goto out;
    }

  /* now that we have a mount point, immediately add it to the
   * /var/lib/udisks/mtab file.
   *
   * If mounting fails we'll clean it up in filesystem_mount_completed_cb. If it
   * hangs we'll clean it up the next time we start up.
   */
  mount_file_add (device->priv->device_file, mount_point, caller_uid, remove_dir_on_unmount);

  n = 0;
  argv[n++] = "mount";
  argv[n++] = "-t";
  argv[n++] = fstype;
  argv[n++] = "-o";
  argv[n++] = mount_options;
  argv[n++] = device->priv->device_file;
  argv[n++] = mount_point;
  argv[n++] = NULL;

 run_job:

  error = NULL;
  if (!job_new (context,
                "FilesystemMount",
                FALSE,
                device,
                argv,
                NULL,
                filesystem_mount_completed_cb,
                FALSE,
                filesystem_mount_data_new (mount_point, remove_dir_on_unmount),
                (GDestroyNotify) filesystem_mount_data_free))
    {
      if (remove_dir_on_unmount)
        {
          mount_file_remove (device->priv->device_file, mount_point);
          if (g_rmdir (mount_point) != 0)
            {
              g_warning ("Error removing dir in early mount error path: %m");
            }
        }
      goto out;
    }

 out:
  g_free (fstype);
  g_free (mount_options);
  g_free (mount_point);
  g_strfreev (options);
}

Project: udisks
File: device.c

device_filesystem_set_label (Device *device,
                             const char *new_label,
                             DBusGMethodInvocation *context)
{
  const Filesystem *fs_details;
  GError *error;

  error = NULL;

  if (device->priv->id_usage == NULL || strcmp (device->priv->id_usage, "filesystem") != 0)
    {
      throw_error (context, ERROR_FAILED, "Not a mountable file system");
      goto out;
    }

  fs_details = daemon_local_get_fs_details (device->priv->daemon, device->priv->id_type);
  if (fs_details == NULL)
    {
      throw_error (context, ERROR_BUSY, "Unknown filesystem");
      goto out;
    }

  if (!fs_details->supports_online_label_rename)
    {
      if (device_local_is_busy (device, FALSE, &error))
        {
          dbus_g_method_return_error (context, error);
          g_error_free (error);
          goto out;
        }
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           device->priv->device_is_system_internal ? "org.freedesktop.udisks.change-system-internal"
                           : "org.freedesktop.udisks.change",
                           "FilesystemSetLabel",
                           TRUE,
                           device_filesystem_set_label_authorized_cb,
                           context,
                           1,
                           g_strdup (new_label),
                           g_free);

 out:
  return TRUE;
}

Project: udisks
File: device.c

device_filesystem_set_label_authorized_cb (Daemon *daemon,
                                           Device *device,
                                           DBusGMethodInvocation *context,
                                           const gchar *action_id,
                                           guint num_user_data,
                                           gpointer *user_data_elements)
{
  const gchar *new_label = user_data_elements[0];
  int n;
  char *argv[10];
  const Filesystem *fs_details;
  GError *error;

  error = NULL;

  if (device->priv->id_usage == NULL || strcmp (device->priv->id_usage, "filesystem") != 0)
    {
      throw_error (context, ERROR_FAILED, "Not a mountable file system");
      goto out;
    }

  fs_details = daemon_local_get_fs_details (device->priv->daemon, device->priv->id_type);
  if (fs_details == NULL)
    {
      throw_error (context, ERROR_BUSY, "Unknown filesystem");
      goto out;
    }

  if (!fs_details->supports_online_label_rename)
    {
      if (device_local_is_busy (device, FALSE, &error))
        {
          dbus_g_method_return_error (context, error);
          g_error_free (error);
          goto out;
        }
    }

  n = 0;
  argv[n++] = "udisks-helper-change-filesystem-label";
  argv[n++] = device->priv->device_file;
  argv[n++] = device->priv->id_type;
  argv[n++] = (char *) new_label;
  argv[n++] = NULL;

  if (!job_new (context,
                "FilesystemSetLabel",
                FALSE,
                device,
                argv,
                NULL,
                filesystem_set_label_completed_cb,
                FALSE,
                g_strdup (new_label),
                g_free))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

device_filesystem_unmount (Device *device,
                           char **options,
                           DBusGMethodInvocation *context)
{
  const gchar *action_id;
  uid_t uid_of_mount;

  if (!device->priv->device_is_mounted || device->priv->device_mount_paths->len == 0)
    {
      throw_error (context, ERROR_FAILED, "Device is not mounted");
      goto out;
    }

  /* if device is in /etc/fstab, then we'll run unmount as the calling user */
  action_id = NULL;
  if (!mount_file_has_device (device->priv->device_file, &uid_of_mount, NULL))
    {
      if (!is_device_in_fstab (device, NULL))
        {
          action_id = "org.freedesktop.udisks.filesystem-unmount-others";
        }
    }
  else
    {
      uid_t uid;
      daemon_local_get_uid (device->priv->daemon, &uid, context);
      if (uid_of_mount != uid)
        {
          action_id = "org.freedesktop.udisks.filesystem-unmount-others";
        }
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           action_id,
                           "FilesystemUnmount",
                           TRUE,
                           device_filesystem_unmount_authorized_cb,
                           context,
                           1,
                           g_strdupv (options),
                           g_strfreev);

 out:
  return TRUE;
}

Project: udisks
File: device.c

device_filesystem_unmount_authorized_cb (Daemon *daemon,
                                         Device *device,
                                         DBusGMethodInvocation *context,
                                         const gchar *action_id,
                                         guint num_user_data,
                                         gpointer *user_data_elements)
{
  gchar **options = user_data_elements[0];
  int n;
  char *argv[16];
  GError *error;
  gboolean force_unmount;
  char *mount_path;
  uid_t uid;
  gchar uid_buf[32];

  mount_path = NULL;

  if (!device->priv->device_is_mounted || device->priv->device_mount_paths->len == 0)
    {
      throw_error (context, ERROR_FAILED, "Device is not mounted");
      goto out;
    }

  force_unmount = FALSE;
  for (n = 0; options[n] != NULL; n++)
    {
      char *option = options[n];
      if (strcmp ("force", option) == 0)
        {
          force_unmount = TRUE;
        }
      else
        {
          throw_error (context, ERROR_INVALID_OPTION, "Unknown option %s", option);
          goto out;
        }
    }

  daemon_local_get_uid (device->priv->daemon, &uid, context);
  g_snprintf (uid_buf, sizeof uid_buf, "%d", uid);

  if (!mount_file_has_device (device->priv->device_file, NULL, NULL))
    {
      if (is_device_in_fstab (device, &mount_path))
        {

          n = 0;
          argv[n++] = "udisks-helper-fstab-mounter";
          if (force_unmount)
            argv[n++] = "force_unmount";
          else
            argv[n++] = "unmount";
          argv[n++] = device->priv->device_file;
          argv[n++] = uid_buf;
          argv[n++] = NULL;
          goto run_job;
        }

      /* otherwise the user will have the .unmount-others authorization per the logic in
       * device_filesystem_unmount()
       */
    }

  mount_path = g_strdup (((gchar **) device->priv->device_mount_paths->pdata)[0]);

  n = 0;
  argv[n++] = "umount";
  if (force_unmount)
    {
      /* on Linux we currently only have lazy unmount to emulate this */
      argv[n++] = "-l";
    }
  argv[n++] = mount_path;
  argv[n++] = NULL;

 run_job:
  error = NULL;
  if (!job_new (context,
                "FilesystemUnmount",
                FALSE,
                device,
                argv,
                NULL,
                filesystem_unmount_completed_cb,
                FALSE,
                g_strdup (mount_path),
                g_free))
    {
      goto out;
    }

 out:
  g_free (mount_path);
}

Project: udisks
File: device.c

device_finalize (GObject *object)
{
  Device *device;
  GList *l;

  g_return_if_fail (object != NULL);
  g_return_if_fail (IS_DEVICE (object));

  device = DEVICE (object);
  g_return_if_fail (device->priv != NULL);

  /* g_debug ("finalizing %s", device->priv->native_path); */

  g_object_unref (device->priv->d);
  g_object_unref (device->priv->daemon);
  g_free (device->priv->object_path);

  g_free (device->priv->native_path);

  for (l = device->priv->polling_inhibitors; l != NULL; l = l->next)
    {
      Inhibitor *inhibitor = INHIBITOR (l->data);
      g_signal_handlers_disconnect_by_func (inhibitor, polling_inhibitor_disconnected_cb, device);
      g_object_unref (inhibitor);
    }
  g_list_free (device->priv->polling_inhibitors);

  for (l = device->priv->spindown_inhibitors; l != NULL; l = l->next)
    {
      Inhibitor *inhibitor = INHIBITOR (l->data);
      g_signal_handlers_disconnect_by_func (inhibitor, spindown_inhibitor_disconnected_cb, device);
      g_object_unref (inhibitor);
    }
  g_list_free (device->priv->spindown_inhibitors);

  if (device->priv->linux_md_poll_timeout_id > 0)
    g_source_remove (device->priv->linux_md_poll_timeout_id);

  if (device->priv->emit_changed_idle_id > 0)
    g_source_remove (device->priv->emit_changed_idle_id);

  /* free properties */
  g_free (device->priv->device_file);
  g_free (device->priv->device_file_presentation);
  g_ptr_array_foreach (device->priv->device_file_by_id, (GFunc) g_free, NULL);
  g_ptr_array_foreach (device->priv->device_file_by_path, (GFunc) g_free, NULL);
  g_ptr_array_free (device->priv->device_file_by_id, TRUE);
  g_ptr_array_free (device->priv->device_file_by_path, TRUE);
  g_ptr_array_free (device->priv->device_mount_paths, TRUE);
  g_free (device->priv->device_presentation_name);
  g_free (device->priv->device_presentation_icon_name);

  g_free (device->priv->id_usage);
  g_free (device->priv->id_type);
  g_free (device->priv->id_version);
  g_free (device->priv->id_uuid);
  g_free (device->priv->id_label);

  g_free (device->priv->partition_slave);
  g_free (device->priv->partition_scheme);
  g_free (device->priv->partition_type);
  g_free (device->priv->partition_label);
  g_free (device->priv->partition_uuid);
  g_ptr_array_foreach (device->priv->partition_flags, (GFunc) g_free, NULL);
  g_ptr_array_free (device->priv->partition_flags, TRUE);

  g_free (device->priv->partition_table_scheme);

  g_free (device->priv->luks_holder);

  g_free (device->priv->luks_cleartext_slave);

  g_free (device->priv->drive_vendor);
  g_free (device->priv->drive_model);
  g_free (device->priv->drive_revision);
  g_free (device->priv->drive_serial);
  g_free (device->priv->drive_wwn);
  g_free (device->priv->drive_connection_interface);
  g_ptr_array_foreach (device->priv->drive_media_compatibility, (GFunc) g_free, NULL);
  g_ptr_array_free (device->priv->drive_media_compatibility, TRUE);
  g_free (device->priv->drive_media);
  g_free (device->priv->drive_write_cache);
  g_free (device->priv->drive_adapter);
  g_ptr_array_foreach (device->priv->drive_ports, (GFunc) g_free, NULL);
  g_ptr_array_free (device->priv->drive_ports, TRUE);
  g_ptr_array_foreach (device->priv->drive_similar_devices, (GFunc) g_free, NULL);
  g_ptr_array_free (device->priv->drive_similar_devices, TRUE);

  g_free (device->priv->linux_md_component_level);
  g_free (device->priv->linux_md_component_uuid);
  g_free (device->priv->linux_md_component_home_host);
  g_free (device->priv->linux_md_component_name);
  g_free (device->priv->linux_md_component_version);
  g_free (device->priv->linux_md_component_holder);
  g_ptr_array_foreach (device->priv->linux_md_component_state, (GFunc) g_free, NULL);
  g_ptr_array_free (device->priv->linux_md_component_state, TRUE);

  g_free (device->priv->linux_md_state);
  g_free (device->priv->linux_md_level);
  g_free (device->priv->linux_md_uuid);
  g_free (device->priv->linux_md_home_host);
  g_free (device->priv->linux_md_name);
  g_free (device->priv->linux_md_version);
  g_ptr_array_foreach (device->priv->linux_md_slaves, (GFunc) g_free, NULL);
  g_ptr_array_free (device->priv->linux_md_slaves, TRUE);

  g_free (device->priv->linux_dmmp_component_holder);

  g_free (device->priv->linux_dmmp_name);
  g_ptr_array_foreach (device->priv->linux_dmmp_slaves, (GFunc) g_free, NULL);
  g_ptr_array_free (device->priv->linux_dmmp_slaves, TRUE);
  g_free (device->priv->linux_dmmp_parameters);

  g_free (device->priv->linux_loop_filename);

  g_free (device->priv->linux_lvm2_lv_name);
  g_free (device->priv->linux_lvm2_lv_uuid);
  g_free (device->priv->linux_lvm2_lv_group_name);
  g_free (device->priv->linux_lvm2_lv_group_uuid);

  g_free (device->priv->linux_lvm2_pv_uuid);
  g_free (device->priv->linux_lvm2_pv_group_name);
  g_free (device->priv->linux_lvm2_pv_group_uuid);
  g_ptr_array_foreach (device->priv->linux_lvm2_pv_group_physical_volumes, (GFunc) g_free, NULL);
  g_ptr_array_free (device->priv->linux_lvm2_pv_group_physical_volumes, TRUE);
  g_ptr_array_foreach (device->priv->linux_lvm2_pv_group_logical_volumes, (GFunc) g_free, NULL);
  g_ptr_array_free (device->priv->linux_lvm2_pv_group_logical_volumes, TRUE);

  g_free (device->priv->drive_ata_smart_blob);

  g_free (device->priv->dm_name);
  g_ptr_array_foreach (device->priv->slaves_objpath, (GFunc) g_free, NULL);
  g_ptr_array_free (device->priv->slaves_objpath, TRUE);
  g_ptr_array_foreach (device->priv->holders_objpath, (GFunc) g_free, NULL);
  g_ptr_array_free (device->priv->holders_objpath, TRUE);

  G_OBJECT_CLASS (device_parent_class)->finalize (object);
}

Project: udisks
File: device.c

device_generate_kernel_change_event (Device *device)
{
  FILE *f;
  char *filename;

  filename = g_build_filename (device->priv->native_path, "uevent", NULL);
  f = fopen (filename, "w");
  if (f == NULL)
    {
      g_warning ("error opening %s for writing: %m", filename);
    }
  else
    {
      if (fputs ("change", f) == EOF)
        {
          g_warning ("error writing 'change' to %s: %m", filename);
        }
      fclose (f);
    }
  g_free (filename);
}

Project: udisks
File: device.c

device_has_logical_partitions (Device *device)
{
  gboolean ret;
  GList *l;
  GList *devices;

  ret = FALSE;

  devices = daemon_local_get_all_devices (device->priv->daemon);
  for (l = devices; l != NULL; l = l->next)
    {
      Device *d = DEVICE (l->data);

      if (d->priv->device_is_partition && d->priv->partition_slave != NULL && g_strcmp0 (d->priv->partition_slave,
                                                                                         device->priv->object_path)
          == 0 && g_strcmp0 (d->priv->partition_scheme, "mbr") == 0 && d->priv->partition_number >= 5)
        {

          ret = TRUE;
        }
    }

  g_list_free (devices);

  return ret;
}

Project: udisks
File: device.c

device_init (Device *device)
{
  device->priv = DEVICE_GET_PRIVATE (device);

  device->priv->device_file_by_id = g_ptr_array_new ();
  device->priv->device_file_by_path = g_ptr_array_new ();
  device->priv->device_mount_paths = g_ptr_array_new ();
  device->priv->partition_flags = g_ptr_array_new ();
  device->priv->drive_media_compatibility = g_ptr_array_new ();
  device->priv->drive_ports = g_ptr_array_new ();
  device->priv->drive_similar_devices = g_ptr_array_new ();
  device->priv->linux_md_component_state = g_ptr_array_new ();
  device->priv->linux_md_slaves = g_ptr_array_new ();
  device->priv->linux_lvm2_pv_group_physical_volumes = g_ptr_array_new ();
  device->priv->linux_lvm2_pv_group_logical_volumes = g_ptr_array_new ();
  device->priv->linux_dmmp_slaves = g_ptr_array_new ();

  device->priv->slaves_objpath = g_ptr_array_new ();
  device->priv->holders_objpath = g_ptr_array_new ();

  device->priv->drive_ata_smart_status = -1;
}

Project: udisks
File: device.c

device_job_cancel (Device *device,
                   DBusGMethodInvocation *context)
{
  uid_t uid;
  const gchar *action_id;

  if (!device->priv->job_in_progress)
    {
      throw_error (context, ERROR_FAILED, "There is no job to cancel");
      goto out;
    }

  if (!device->priv->job_is_cancellable)
    {
      throw_error (context, ERROR_FAILED, "Job cannot be cancelled");
      goto out;
    }

  daemon_local_get_uid (device->priv->daemon, &uid, context);

  action_id = NULL;
  if (device->priv->job_initiated_by_uid != uid)
    {
      action_id = "org.freedesktop.udisks.cancel-job-others";
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           action_id,
                           "JobCancel",
                           TRUE,
                           device_job_cancel_authorized_cb,
                           context,
                           0);

 out:
  return TRUE;
}

Project: udisks
File: device.c

device_job_cancel_authorized_cb (Daemon *daemon,
                                 Device *device,
                                 DBusGMethodInvocation *context,
                                 const gchar *action_id,
                                 guint num_user_data,
                                 gpointer *user_data_elements)
{

  if (!device->priv->job_in_progress)
    {
      throw_error (context, ERROR_FAILED, "There is no job to cancel");
      goto out;
    }

  if (!device->priv->job_is_cancellable)
    {
      throw_error (context, ERROR_FAILED, "Job cannot be cancelled");
      goto out;
    }

  job_cancel (device);

  /* TODO: wait returning once the job is actually cancelled? */
  dbus_g_method_return (context);
 out:
  ;
}

Project: udisks
File: device.c

device_linux_lvm2_lv_stop (Device *device,
                           char **options,
                           DBusGMethodInvocation *context)
{
  daemon_local_check_auth (device->priv->daemon,
                           device,
                           "org.freedesktop.udisks.linux-lvm2",
                           "LinuxLvm2LVStop",
                           TRUE,
                           daemon_linux_lvm2_lv_stop_authorized_cb,
                           context,
                           1,
                           g_strdupv (options),
                           g_strfreev);

  return TRUE;
}

Project: udisks
File: device.c

device_linux_md_add_spare (Device *device,
                           char *component,
                           char **options,
                           DBusGMethodInvocation *context)
{
  if (!device->priv->device_is_linux_md)
    {
      throw_error (context, ERROR_FAILED, "Device is not a Linux md drive");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           "org.freedesktop.udisks.linux-md",
                           "LinuxMdAddSpare",
                           TRUE,
                           device_linux_md_add_spare_authorized_cb,
                           context,
                           2,
                           g_strdup (component),
                           g_free,
                           g_strdupv (options),
                           g_strfreev);
 out:
  return TRUE;
}

Project: udisks

device_linux_md_add_spare_authorized_cb (Daemon *daemon,
                                             Device *device,
                                             DBusGMethodInvocation *context,
                                             const gchar *action_id,
                                             guint num_user_data,
                                             gpointer *user_data_elements)
{
  char *component = user_data_elements[0];
  /* TODO: use options */
  int n;
  char *argv[10];
  GError *error;
  Device *slave;

  error = NULL;

  slave = daemon_local_find_by_object_path (device->priv->daemon, component);
  if (slave == NULL)
    {
      throw_error (context, ERROR_FAILED, "Component doesn't exist");
      goto out;
    }

  /* it's fine if the given device isn't a Linux md component _yet_; think
   * hot adding a new disk if an old one failed
   */

  if (device_local_is_busy (slave, TRUE, &error))
    {
      dbus_g_method_return_error (context, error);
      g_error_free (error);
      goto out;
    }

  /* TODO: check component size is OK */

  n = 0;
  argv[n++] = "mdadm";
  argv[n++] = "--manage";
  argv[n++] = device->priv->device_file;
  argv[n++] = "--add";
  argv[n++] = slave->priv->device_file;
  argv[n++] = "--force";
  argv[n++] = NULL;

  if (!job_new (context,
                "LinuxMdAddSpare",
                TRUE,
                device,
                argv,
                NULL,
                linux_md_add_spare_completed_cb,
                FALSE,
                g_object_ref (slave),
                g_object_unref))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

device_linux_md_check (Device *device,
                       char **options,
                       DBusGMethodInvocation *context)
{
  guint n;
  const gchar *job_name;

  job_name = "LinuxMdCheck";
  for (n = 0; options != NULL && options[n] != NULL; n++)
    if (strcmp (options[n], "repair") == 0)
      job_name = "LinuxMdRepair";

  if (!device->priv->device_is_linux_md)
    {
      throw_error (context, ERROR_FAILED, "Device is not a Linux md drive");
      goto out;
    }

  if (g_strcmp0 (device->priv->linux_md_sync_action, "idle") != 0)
    {
      throw_error (context, ERROR_FAILED, "Array is not idle");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           "org.freedesktop.udisks.linux-md",
                           job_name,
                           TRUE,
                           device_linux_md_check_authorized_cb,
                           context,
                           1,
                           g_strdupv (options),
                           g_strfreev);

 out:
  return TRUE;
}

Project: udisks
File: device.c

device_linux_md_check_authorized_cb (Daemon *daemon,
                                     Device *device,
                                     DBusGMethodInvocation *context,
                                     const gchar *action_id,
                                     guint num_user_data,
                                     gpointer *user_data_elements)
{
  gchar **options = user_data_elements[0];
  gchar *filename;
  int n, m;
  char *argv[128];
  const gchar *job_name;

  filename = NULL;

  if (!device->priv->device_is_linux_md)
    {
      throw_error (context, ERROR_FAILED, "Device is not a Linux md drive");
      goto out;
    }

  if (g_strcmp0 (device->priv->linux_md_sync_action, "idle") != 0)
    {
      throw_error (context, ERROR_FAILED, "Array is not idle");
      goto out;
    }

  n = 0;
  argv[n++] = "udisks-helper-linux-md-check";
  argv[n++] = device->priv->device_file;
  argv[n++] = device->priv->native_path;
  for (m = 0; options[m] != NULL; m++)
    {
      if (n >= (int) sizeof(argv) - 1)
        {
          throw_error (context, ERROR_FAILED, "Too many options");
          goto out;
        }
      /* the helper will validate each option */
      argv[n++] = (char *) options[m];
    }
  argv[n++] = NULL;

  job_name = "LinuxMdCheck";
  for (n = 0; options != NULL && options[n] != NULL; n++)
    if (strcmp (options[n], "repair") == 0)
      job_name = "LinuxMdRepair";

  if (!job_new (context, job_name, TRUE, device, argv, NULL, linux_md_check_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

device_linux_md_expand (Device *device,
                        GPtrArray *components,
                        char **options,
                        DBusGMethodInvocation *context)
{
  gchar **strv;
  guint n;

  if (!device->priv->device_is_linux_md)
    {
      throw_error (context, ERROR_FAILED, "Device is not a Linux md drive");
      goto out;
    }

  strv = (gchar **) g_new0 (gchar*, components->len + 1);
  for (n = 0; n < components->len; n++)
    strv[n] = g_strdup (components->pdata[n]);

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           "org.freedesktop.udisks.linux-md",
                           "LinuxMdExpand",
                           TRUE,
                           device_linux_md_expand_authorized_cb,
                           context,
                           2,
                           strv,
                           g_strfreev,
                           g_strdupv (options),
                           g_strfreev);
 out:
  return TRUE;
}

Project: udisks

device_linux_md_expand_authorized_cb (Daemon *daemon,
                                             Device *device,
                                             DBusGMethodInvocation *context,
                                             const gchar *action_id,
                                             guint num_user_data,
                                             gpointer *user_data_elements)
{
  gchar **components = user_data_elements[0];
  /* TODO: use options */
  guint n;
  GError *error;
  GPtrArray *args;
  gint new_num_raid_devices;
  gchar *backup_filename;
  gchar *md_basename;

  error = NULL;

  args = g_ptr_array_new_with_free_func (g_free);
  g_ptr_array_add (args, g_strdup ("udisks-helper-mdadm-expand"));
  g_ptr_array_add (args, g_strdup (device->priv->device_file));

  new_num_raid_devices = device->priv->linux_md_num_raid_devices + g_strv_length (components);
  g_ptr_array_add (args, g_strdup_printf ("%d", new_num_raid_devices));

  /* TODO: choose a better name and better location */
  md_basename = g_path_get_basename (device->priv->device_file);
  backup_filename = g_strdup_printf ("/root/udisks-mdadm-expand-backup-file-%s-at-%" G_GUINT64_FORMAT,
                                     md_basename,
                                     (guint64) time (NULL));
  g_free (md_basename);
  g_ptr_array_add (args, backup_filename);

  for (n = 0; components != NULL && components[n] != NULL; n++)
    {
      Device *slave;

      slave = daemon_local_find_by_object_path (device->priv->daemon, components[n]);
      if (slave == NULL)
        {
          throw_error (context,
                       ERROR_FAILED,
                       "Component with object path %s doesn't exist",
                       components[n]);
          goto out;
        }

      if (device_local_is_busy (slave, TRUE, &error))
        {
          dbus_g_method_return_error (context, error);
          g_error_free (error);
          goto out;
        }

      g_ptr_array_add (args, g_strdup (slave->priv->device_file));
    }
  g_ptr_array_add (args, NULL);


  if (!job_new (context,
                "LinuxMdExpand",
                TRUE,
                device,
                (char **) args->pdata,
                NULL,
                linux_md_expand_completed_cb,
                FALSE,
                NULL,
                NULL))
    {
      goto out;
    }

 out:
  g_ptr_array_free (args, TRUE);
}

Project: udisks
File: device.c

device_linux_md_remove_component (Device *device,
                                  char *component,
                                  char **options,
                                  DBusGMethodInvocation *context)
{
  if (!device->priv->device_is_linux_md)
    {
      throw_error (context, ERROR_FAILED, "Device is not a Linux md drive");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           "org.freedesktop.udisks.linux-md",
                           "LinuxMdRemoveComponent",
                           TRUE,
                           device_linux_md_remove_component_authorized_cb,
                           context,
                           2,
                           g_strdup (component),
                           g_free,
                           g_strdupv (options),
                           g_strfreev);
 out:
  return TRUE;
}

Project: udisks
File: device.c

device_linux_md_remove_component_authorized_cb (Daemon *daemon,
                                                Device *device,
                                                DBusGMethodInvocation *context,
                                                const gchar *action_id,
                                                guint num_user_data,
                                                gpointer *user_data_elements)
{
  char *component = user_data_elements[0];
  char **options = user_data_elements[1];
  int n, m;
  char *argv[128];
  GError *error;
  Device *slave;

  slave = daemon_local_find_by_object_path (device->priv->daemon, component);
  if (slave == NULL)
    {
      throw_error (context, ERROR_FAILED, "Component doesn't exist");
      goto out;
    }

  /* check that it really is a component of the md device */
  for (n = 0; n < (int) device->priv->linux_md_slaves->len; n++)
    {
      if (strcmp (component, device->priv->linux_md_slaves->pdata[n]) == 0)
        break;
    }
  if (n == (int) device->priv->linux_md_slaves->len)
    {
      throw_error (context, ERROR_FAILED, "Component isn't part of the running array");
      goto out;
    }

  n = 0;
  argv[n++] = "udisks-helper-linux-md-remove-component";
  argv[n++] = device->priv->device_file;
  argv[n++] = slave->priv->device_file;
  for (m = 0; options[m] != NULL; m++)
    {
      if (n >= (int) sizeof(argv) - 1)
        {
          throw_error (context, ERROR_FAILED, "Too many options");
          goto out;
        }
      /* the helper will validate each option */
      argv[n++] = (char *) options[m];
    }
  argv[n++] = NULL;

  error = NULL;
  if (!job_new (context,
                "LinuxMdRemoveComponent",
                TRUE,
                device,
                argv,
                NULL,
                linux_md_remove_component_completed_cb,
                FALSE,
                remove_component_data_new (context, slave, options),
                (GDestroyNotify) remove_component_data_unref))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

device_linux_md_stop (Device *device,
                      char **options,
                      DBusGMethodInvocation *context)
{
  if (!device->priv->device_is_linux_md)
    {
      throw_error (context, ERROR_FAILED, "Device is not a Linux md drive");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           "org.freedesktop.udisks.linux-md",
                           "LinuxMdStop",
                           TRUE,
                           device_linux_md_stop_authorized_cb,
                           context,
                           1,
                           g_strdupv (options),
                           g_strfreev);

 out:
  return TRUE;
}

Project: udisks

device_linux_md_stop_authorized_cb (Daemon *daemon,
                                    Device *device,
                                    DBusGMethodInvocation *context,
                                    const gchar *action_id,
                                    guint num_user_data,
                                    gpointer *user_data_elements)
{
  /* TODO: use options */
  int n;
  char *argv[10];
  GError *error;

  n = 0;
  argv[n++] = "mdadm";
  argv[n++] = "--stop";
  argv[n++] = device->priv->device_file;
  argv[n++] = NULL;

  error = NULL;
  if (!job_new (context, "LinuxMdStop", TRUE, device, argv, NULL, linux_md_stop_completed_cb, FALSE, NULL, NULL))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

device_local_get_dev (Device *device)
{
  return device->priv->dev;
}

Project: udisks
File: device.c

device_local_get_device_file (Device *device)
{
  return device->priv->device_file;
}

Project: udisks
File: device.c

device_local_get_native_path (Device *device)
{
  return device->priv->native_path;
}

Project: udisks
File: device.c

device_local_get_object_path (Device *device)
{
  return device->priv->object_path;
}

Project: udisks
File: device.c

device_local_is_busy (Device *device,
                      gboolean check_partitions,
                      GError **error)
{
  gboolean ret;

  ret = TRUE;

  /* busy if a job is pending */
  if (device->priv->job != NULL)
    {
      g_set_error (error, ERROR, ERROR_BUSY, "A job is pending on %s", device->priv->device_file);
      goto out;
    }

  /* or if we're mounted */
  if (device->priv->device_is_mounted)
    {
      g_set_error (error, ERROR, ERROR_BUSY, "%s is mounted", device->priv->device_file);
      goto out;
    }

  /* or if another block device is using/holding us (e.g. if holders/ is non-empty in sysfs) */
  if (device->priv->holders_objpath->len > 0)
    {
      if (device->priv->device_is_linux_dmmp)
        {
          /* This is OK */
        }
      else
        {
          g_set_error (error,
                       ERROR,
                       ERROR_BUSY,
                       "One or more block devices are holding %s",
                       device->priv->device_file);
          goto out;
        }
    }

  /* If we are an extended partition, we are also busy if one or more logical partitions are busy
   * even if @check_partitions is FALSE... This is because an extended partition only really is
   * a place holder.
   */
  if (g_strcmp0 (device->priv->partition_scheme, "mbr") == 0 && device->priv->partition_type != NULL)
    {
      gint partition_type;
      partition_type = strtol (device->priv->partition_type, NULL, 0);
      if (partition_type == 0x05 || partition_type == 0x0f || partition_type == 0x85)
        {
          Device *drive_device;
          drive_device = daemon_local_find_by_object_path (device->priv->daemon, device->priv->partition_slave);
          if (device_local_logical_partitions_are_busy (drive_device))
            {
              g_set_error (error, ERROR, ERROR_BUSY, "%s is an MS-DOS extended partition and one or more "
                           "logical partitions are busy", device->priv->device_file);
              goto out;
            }
        }
    }

  /* if we are a partition table, we are busy if one of our partitions are busy */
  if (check_partitions && device->priv->device_is_partition_table)
    {
      if (device_local_partitions_are_busy (device))
        {
          g_set_error (error, ERROR, ERROR_BUSY, "One or more partitions are busy on %s", device->priv->device_file);
          goto out;
        }
    }

  ret = FALSE;

 out:
  return ret;
}

Project: udisks
File: device.c

device_local_logical_partitions_are_busy (Device *device)
{
  gboolean ret;
  GList *l;
  GList *devices;

  ret = FALSE;

  devices = daemon_local_get_all_devices (device->priv->daemon);
  for (l = devices; l != NULL; l = l->next)
    {
      Device *d = DEVICE (l->data);

      if (d->priv->device_is_partition && d->priv->partition_slave != NULL && g_strcmp0 (d->priv->partition_slave,
                                                                                         device->priv->object_path)
          == 0 && g_strcmp0 (d->priv->partition_scheme, "mbr") == 0 && d->priv->partition_number >= 5)
        {

          if (device_local_is_busy (d, FALSE, NULL))
            {
              ret = TRUE;
              break;
            }
        }
    }

  g_list_free (devices);

  return ret;
}

Project: udisks
File: device.c

device_local_partitions_are_busy (Device *device)
{
  gboolean ret;
  GList *l;
  GList *devices;

  ret = FALSE;

  devices = daemon_local_get_all_devices (device->priv->daemon);
  for (l = devices; l != NULL; l = l->next)
    {
      Device *d = DEVICE (l->data);

      if (d->priv->device_is_partition && d->priv->partition_slave != NULL && g_strcmp0 (d->priv->partition_slave,
                                                                                         device->priv->object_path)
          == 0)
        {

          if (device_local_is_busy (d, FALSE, NULL))
            {
              ret = TRUE;
              break;
            }
        }
    }

  g_list_free (devices);

  return ret;
}

Project: udisks
File: device.c

device_luks_change_passphrase (Device *device,
                               const char *old_secret,
                               const char *new_secret,
                               DBusGMethodInvocation *context)
{
  /* No need to check for busy; we can actually do this while the device is unlocked as
   * only LUKS metadata is modified.
   */

  if (device->priv->id_usage == NULL || strcmp (device->priv->id_usage, "crypto") != 0)
    {
      throw_error (context, ERROR_FAILED, "Not a LUKS crypto device");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           device->priv->device_is_system_internal ? "org.freedesktop.udisks.change-system-internal"
                           : "org.freedesktop.udisks.change",
                           "LuksChangePassphrase",
                           TRUE,
                           device_luks_change_passphrase_authorized_cb,
                           context,
                           2,
                           g_strdup (old_secret),
                           g_free,
                           g_strdup (new_secret),
                           g_free);

 out:
  return TRUE;
}

Project: udisks
File: device.c

device_luks_change_passphrase_authorized_cb (Daemon *daemon,
                                             Device *device,
                                             DBusGMethodInvocation *context,
                                             const gchar *action_id,
                                             guint num_user_data,
                                             gpointer *user_data_elements)
{
  const char *old_secret = user_data_elements[0];
  const char *new_secret = user_data_elements[1];
  int n;
  char *argv[10];
  GError *error;
  char *secrets_as_stdin;

  secrets_as_stdin = NULL;

  if (device->priv->id_usage == NULL || strcmp (device->priv->id_usage, "crypto") != 0)
    {
      throw_error (context, ERROR_FAILED, "Not a LUKS crypto device");
      goto out;
    }

  secrets_as_stdin = g_strdup_printf ("%s\n%s\n", old_secret, new_secret);

  n = 0;
  argv[n++] = "udisks-helper-change-luks-password";
  argv[n++] = device->priv->device_file;
  argv[n++] = NULL;

  error = NULL;
  if (!job_new (context,
                "LuksChangePassphrase",
                FALSE,
                device,
                argv,
                secrets_as_stdin,
                luks_change_passphrase_completed_cb,
                FALSE,
                NULL,
                NULL))
    {
      goto out;
    }

 out:
  /* scrub the secrets */
  if (secrets_as_stdin != NULL)
    {
      memset (secrets_as_stdin, '\0', strlen (secrets_as_stdin));
    }
  g_free (secrets_as_stdin);
}

Project: udisks
File: device.c

device_luks_lock (Device *device,
                  char **options,
                  DBusGMethodInvocation *context)
{
  uid_t unlocked_by_uid;
  uid_t uid;
  Device *cleartext_device;
  const gchar *action_id;

  daemon_local_get_uid (device->priv->daemon, &uid, context);

  if (device->priv->id_usage == NULL || strcmp (device->priv->id_usage, "crypto") != 0)
    {
      throw_error (context, ERROR_FAILED, "Not a LUKS crypto device");
      goto out;
    }

  cleartext_device = find_cleartext_device (device);
  if (cleartext_device == NULL)
    {
      throw_error (context, ERROR_FAILED, "Cleartext device is not unlocked");
      goto out;
    }

  if (cleartext_device->priv->dm_name == NULL || strlen (cleartext_device->priv->dm_name) == 0)
    {
      throw_error (context, ERROR_FAILED, "Cannot determine device-mapper name");
      goto out;
    }

  /* see if we (e.g. udisks) set up this clear text device */
  if (!luks_get_uid_from_dm_name (cleartext_device->priv->dm_name, &unlocked_by_uid))
    {
      /* nope.. so assume uid 0 set it up.. we still allow locking
       * the device... given enough privilege
       */
      unlocked_by_uid = 0;
    }

  /* require authorization if unlocked by someone else */
  action_id = NULL;
  if (unlocked_by_uid != uid)
    {
      action_id = "org.freedesktop.udisks.luks-lock-others";
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           action_id,
                           "LuksLock",
                           TRUE,
                           device_luks_lock_authorized_cb,
                           context,
                           1,
                           g_strdupv (options),
                           g_strfreev);

 out:
  return TRUE;
}

Project: udisks

device_luks_lock_authorized_cb (Daemon *daemon,
                                Device *device,
                                DBusGMethodInvocation *context,
                                const gchar *action_id,
                                guint num_user_data,
                                gpointer *user_data_elements)
{
  /* TODO: use options */
  Device *cleartext_device;
  int n;
  char *argv[10];
  GError *error;

  if (device->priv->id_usage == NULL || strcmp (device->priv->id_usage, "crypto") != 0)
    {
      throw_error (context, ERROR_FAILED, "Not a LUKS crypto device");
      goto out;
    }

  cleartext_device = find_cleartext_device (device);
  if (cleartext_device == NULL)
    {
      throw_error (context, ERROR_FAILED, "Cleartext device is not unlocked");
      goto out;
    }

  if (cleartext_device->priv->dm_name == NULL || strlen (cleartext_device->priv->dm_name) == 0)
    {
      throw_error (context, ERROR_FAILED, "Cannot determine device-mapper name");
      goto out;
    }

  n = 0;
  argv[n++] = "cryptsetup";
  argv[n++] = "luksClose";
  argv[n++] = cleartext_device->priv->dm_name;
  argv[n++] = NULL;

  error = NULL;
  if (!job_new (context,
                "LuksLock",
                FALSE,
                device,
                argv,
                NULL,
                luks_lock_completed_cb,
                FALSE,
                lock_encryption_data_new (context, device, cleartext_device),
                (GDestroyNotify) lock_encryption_data_unref))
    {
      goto out;
    }

 out:
  ;
}

Project: udisks
File: device.c

device_luks_unlock (Device *device,
                    const char *secret,
                    char **options,
                    DBusGMethodInvocation *context)
{
  if (device->priv->id_usage == NULL || strcmp (device->priv->id_usage, "crypto") != 0)
    {
      throw_error (context, ERROR_FAILED, "Not a LUKS device");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           "org.freedesktop.udisks.luks-unlock",
                           "LuksUnlock",
                           TRUE,
                           device_luks_unlock_authorized_cb,
                           context,
                           2,
                           g_strdup (secret),
                           g_free,
                           g_strdupv (options),
                           g_strfreev);

 out:
  return TRUE;
}

Project: udisks
File: device.c

device_luks_unlock_authorized_cb (Daemon *daemon,
                                  Device *device,
                                  DBusGMethodInvocation *context,
                                  const gchar *action_id,
                                  guint num_user_data,
                                  gpointer *user_data_elements)
{
  const char *secret = user_data_elements[0];
  char **options = user_data_elements[1];
  device_luks_unlock_internal (device, secret, options, NULL, NULL, context);
}

Project: udisks
File: device.c

device_luks_unlock_internal (Device *device,
                             const char *secret,
                             char **options,
                             UnlockEncryptionHookFunc hook_func,
                             gpointer hook_user_data,
                             DBusGMethodInvocation *context)
{
  int n;
  char *argv[10];
  char *luks_name;
  GError *error;
  char *secret_as_stdin;
  uid_t uid;

  luks_name = NULL;
  secret_as_stdin = NULL;
  error = NULL;

  daemon_local_get_uid (device->priv->daemon, &uid, context);

  if (device_local_is_busy (device, FALSE, &error))
    {
      dbus_g_method_return_error (context, error);
      g_error_free (error);
      goto out;
    }

  if (device->priv->id_usage == NULL || strcmp (device->priv->id_usage, "crypto") != 0)
    {
      throw_error (context, ERROR_FAILED, "Not a LUKS device");
      goto out;
    }

  if (find_cleartext_device (device) != NULL)
    {
      throw_error (context, ERROR_FAILED, "Cleartext device is already unlocked");
      goto out;
    }

  luks_name = g_strdup_printf ("udisks-luks-uuid-%s-uid%d", device->priv->id_uuid, uid);
  secret_as_stdin = g_strdup_printf ("%s\n", secret);

  n = 0;
  argv[n++] = "cryptsetup";
  argv[n++] = "-T";
  argv[n++] = "1";
  argv[n++] = "luksOpen";
  argv[n++] = device->priv->device_file;
  argv[n++] = luks_name;
  argv[n++] = NULL;

  /* yay, so it turns out /sbin/cryptsetup returns way too early; what happens is this
   *
   * - invoke /sbin/cryptsetup
   *   - temporary dm node with name temporary-cryptsetup-* appears. We ignore these,
   *     see above
   *   - temporary dm node removed
   * - /sbin/cryptsetup returns with success (brings us here)
   *   - proper dm node appears
   *     - with the name we requested, e.g. udisks-luks-uuid-%s-uid%d
   *   - proper dm node disappears
   *   - proper dm node reappears
   *
   * Obiviously /sbin/cryptsetup shouldn't return before the dm node we are
   * looking for is really there or ready to use. But that's not how things
   * work.
   *
   * This bug has been reported here:
   *
   *  https://bugzilla.redhat.com/show_bug.cgi?id=530721
   *
   * WORKAROUND: wait for the udev queue to settle before returning. Long
   *             term fix is device-mapper/udev integration.
   */
  if (!job_new (context,
                "LuksUnlock",
                FALSE,
                device,
                argv,
                secret_as_stdin,
                luks_unlock_completed_cb,
                TRUE, /* see note above */
                unlock_encryption_data_new (context, device, hook_func, hook_user_data),
                (GDestroyNotify) unlock_encryption_data_unref))
    {
      goto out;
    }

 out:
  /* scrub the secret */
  if (secret_as_stdin != NULL)
    {
      memset (secret_as_stdin, '\0', strlen (secret_as_stdin));
    }
  g_free (secret_as_stdin);
  g_free (luks_name);
  return TRUE;
}

Project: udisks
File: device.c

device_new (Daemon *daemon,
            GUdevDevice *d)
{
  Device *device;
  const char *native_path;

  device = NULL;
  native_path = g_udev_device_get_sysfs_path (d);

  /* ignore ram devices */
  if (g_str_has_prefix (native_path, "/sys/devices/virtual/block/ram"))
    goto out;

  PROFILE ("device_new(native_path=%s): start", native_path);

  device = DEVICE (g_object_new (TYPE_DEVICE, NULL));
  device->priv->d = g_object_ref (d);
  device->priv->daemon = g_object_ref (daemon);
  device->priv->native_path = g_strdup (native_path);

  /* TODO: we might want to get this from udev or the kernel... to get the time when the device
   *       was initially detected... as opposed to this value which is when the device was detected
   *       by our daemon... but this will do for now...
   */
  device->priv->device_detection_time = (guint64) time (NULL);

  PROFILE ("device_new(native_path=%s): update_info", native_path);
  if (!update_info (device))
    {
      g_object_unref (device);
      device = NULL;
      goto out;
    }

  PROFILE ("device_new(native_path=%s): register_disks_device", native_path);
  if (!register_disks_device (DEVICE (device)))
    {
      g_object_unref (device);
      device = NULL;
      goto out;
    }

  /* if just added, update the smart data if applicable */
  if (device->priv->drive_ata_smart_is_available)
    {
      PROFILE ("device_new(native_path=%s): refresh ATA SMART DATA", native_path);
      gchar *ata_smart_refresh_data_options[] = { NULL };
      device_drive_ata_smart_refresh_data (device, ata_smart_refresh_data_options, NULL);
    }

  PROFILE ("device_new(native_path=%s): end", native_path);
 out:
  return device;
}

Project: udisks
File: device.c

device_partition_create (Device *device,
                         guint64 offset,
                         guint64 size,
                         const char *type,
                         const char *label,
                         char **flags,
                         char **options,
                         const char *fstype,
                         char **fsoptions,
                         DBusGMethodInvocation *context)
{
  if (!device->priv->device_is_partition_table)
    {
      throw_error (context, ERROR_FAILED, "Device is not partitioned");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           device->priv->device_is_system_internal ? "org.freedesktop.udisks.change-system-internal"
                           : "org.freedesktop.udisks.change",
                           "PartitionCreate",
                           TRUE,
                           device_partition_create_authorized_cb,
                           context,
                           8,
                           g_memdup (&offset, sizeof(guint64)),
                           g_free,
                           g_memdup (&size, sizeof(guint64)),
                           g_free,
                           g_strdup (type),
                           g_free,
                           g_strdup (label),
                           g_free,
                           g_strdupv (flags),
                           g_strfreev,
                           g_strdupv (options),
                           g_strfreev,
                           g_strdup (fstype),
                           g_free,
                           g_strdupv (fsoptions),
                           g_strfreev);

 out:
  return TRUE;
}

Project: udisks
File: device.c

device_partition_create_authorized_cb (Daemon *daemon,
                                       Device *device,
                                       DBusGMethodInvocation *context,
                                       const gchar *action_id,
                                       guint num_user_data,
                                       gpointer *user_data_elements)
{
  guint64 offset = *((guint64*) user_data_elements[0]);
  guint64 size = *((guint64*) user_data_elements[1]);
  ;
  const char *type = user_data_elements[2];
  const char *label = user_data_elements[3];
  char **flags = user_data_elements[4];
  char **options = user_data_elements[5];
  const char *fstype = user_data_elements[6];
  char **fsoptions = user_data_elements[7];
  int n;
  int m;
  char *argv[128];
  GError *error;
  char *offset_as_string;
  char *size_as_string;
  char *flags_as_string;

  offset_as_string = NULL;
  size_as_string = NULL;
  flags_as_string = NULL;
  error = NULL;

  if (!device->priv->device_is_partition_table)
    {
      throw_error (context, ERROR_FAILED, "Device is not partitioned");
      goto out;
    }

  if (device_local_is_busy (device, FALSE, &error))
    {
      dbus_g_method_return_error (context, error);
      g_error_free (error);
      goto out;
    }

  /* partutil.c / libparted will check there are no partitions in the requested slice */

  offset_as_string = g_strdup_printf ("%" G_GINT64_FORMAT "", offset);
  size_as_string = g_strdup_printf ("%" G_GINT64_FORMAT "", size);
  /* TODO: check that neither of the flags include ',' */
  flags_as_string = g_strjoinv (",", flags);

  n = 0;
  argv[n++] = "udisks-helper-create-partition";
  if (device->priv->device_is_linux_dmmp)
    argv[n++] = (gchar *) get_dmmp_device_node (device);
  else
    argv[n++] = device->priv->device_file;
  argv[n++] = offset_as_string;
  argv[n++] = size_as_string;
  argv[n++] = (char *) type;
  argv[n++] = (char *) label;
  argv[n++] = (char *) flags_as_string;
  for (m = 0; options[m] != NULL; m++)
    {
      if (n >= (int) sizeof(argv) - 1)
        {
          throw_error (context, ERROR_FAILED, "Too many options");
          goto out;
        }
      /* the helper will validate each option */
      argv[n++] = (char *) options[m];
    }
  argv[n++] = NULL;

  if (!job_new (context,
                "PartitionCreate",
                TRUE,
                device,
                argv,
                NULL,
                partition_create_completed_cb,
                FALSE,
                partition_create_data_new (context, device, offset, size, fstype, fsoptions),
                (GDestroyNotify) partition_create_data_unref))
    {
      goto out;
    }

 out:
  g_free (offset_as_string);
  g_free (size_as_string);
  g_free (flags_as_string);
}

Project: udisks
File: device.c

device_partition_delete (Device *device,
                         char **options,
                         DBusGMethodInvocation *context)
{
  daemon_local_check_auth (device->priv->daemon,
                           device,
                           device->priv->device_is_system_internal ? "org.freedesktop.udisks.change-system-internal"
                           : "org.freedesktop.udisks.change",
                           "PartitionDelete",
                           TRUE,
                           device_partition_delete_authorized_cb,
                           context,
                           1,
                           g_strdupv (options),
                           g_strfreev);
  return TRUE;
}

Project: udisks
File: device.c

device_partition_modify (Device *device,
                         const char *type,
                         const char *label,
                         char **flags,
                         DBusGMethodInvocation *context)
{
  if (!device->priv->device_is_partition)
    {
      throw_error (context, ERROR_FAILED, "Device is not a partition");
      goto out;
    }

  daemon_local_check_auth (device->priv->daemon,
                           device,
                           device->priv->device_is_system_internal ? "org.freedesktop.udisks.change-system-internal"
                           : "org.freedesktop.udisks.change",
                           "PartitionModify",
                           TRUE,
                           device_partition_modify_authorized_cb,
                           context,
                           3,
                           g_strdup (type),
                           g_free,
                           g_strdup (label),
                           g_free,
                           g_strdupv (flags),
                           g_strfreev);

 out:
  return TRUE;
}