Пример #1
0
/* called with lock held */
static void
handle_block_uevent_for_block (UDisksLinuxProvider *provider,
                               const gchar         *action,
                               UDisksLinuxDevice   *device)
{
  const gchar *sysfs_path;
  UDisksLinuxBlockObject *object;
  UDisksDaemon *daemon;

  daemon = udisks_provider_get_daemon (UDISKS_PROVIDER (provider));
  sysfs_path = g_udev_device_get_sysfs_path (device->udev_device);

  if (g_strcmp0 (action, "remove") == 0)
    {
      object = g_hash_table_lookup (provider->sysfs_to_block, sysfs_path);
      if (object != NULL)
        {
          g_dbus_object_manager_server_unexport (udisks_daemon_get_object_manager (daemon),
                                                 g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
          g_warn_if_fail (g_hash_table_remove (provider->sysfs_to_block, sysfs_path));
        }
    }
  else
    {
      object = g_hash_table_lookup (provider->sysfs_to_block, sysfs_path);
      if (object != NULL)
        {
          udisks_linux_block_object_uevent (object, action, device);
        }
      else
        {
          object = udisks_linux_block_object_new (daemon, device);
          g_dbus_object_manager_server_export_uniquely (udisks_daemon_get_object_manager (daemon),
                                                        G_DBUS_OBJECT_SKELETON (object));
          g_hash_table_insert (provider->sysfs_to_block, g_strdup (sysfs_path), object);
        }
    }
}
Пример #2
0
/**
 * udisks_linux_drive_object_get_block:
 * @object: A #UDisksLinuxDriveObject.
 * @get_hw: If the drive is multipath, set to %TRUE to get a path device instead of the multipath device.
 *
 * Gets a #UDisksLinuxBlockObject representing a block device associated with @object.
 *
 * Returns: A #UDisksLinuxBlockObject or %NULL. The returned object
 * must be freed with g_object_unref().
 */
UDisksLinuxBlockObject *
udisks_linux_drive_object_get_block (UDisksLinuxDriveObject   *object,
                                     gboolean                  get_hw)
{
  GDBusObjectManagerServer *object_manager;
  UDisksLinuxBlockObject *ret;
  GList *objects;
  GList *l;

  /* TODO: actually look at @get_hw */

  ret = NULL;

  object_manager = udisks_daemon_get_object_manager (object->daemon);
  objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager));
  for (l = objects; l != NULL; l = l->next)
    {
      GDBusObjectSkeleton *iter_object = G_DBUS_OBJECT_SKELETON (l->data);
      UDisksBlock *block;
      UDisksLinuxDevice *device;
      gboolean is_disk;

      if (!UDISKS_IS_LINUX_BLOCK_OBJECT (iter_object))
        continue;

      device = udisks_linux_block_object_get_device (UDISKS_LINUX_BLOCK_OBJECT (iter_object));
      is_disk = (g_strcmp0 (g_udev_device_get_devtype (device->udev_device), "disk") == 0);
      g_object_unref (device);

      if (!is_disk)
        continue;

      block = udisks_object_peek_block (UDISKS_OBJECT (iter_object));
      if (g_strcmp0 (udisks_block_get_drive (block),
                     g_dbus_object_get_object_path (G_DBUS_OBJECT (object))) == 0)
        {
          ret = g_object_ref (iter_object);
          goto out;
        }
    }

 out:
  g_list_foreach (objects, (GFunc) g_object_unref, NULL);
  g_list_free (objects);
  return ret;
}
Пример #3
0
/**
 * udisks_linux_drive_object_get_siblings:
 * @object: A #UDisksLinuxDriveObject.
 *
 * Gets the siblings for @object, if any.
 *
 * Returns: (transfer full) (element-type UDisksLinuxDriveObject): A list of #UDisksLinuxDriveObject
 *   instances. The returned list should be freed with g_list_free() after each element has been
 *   freed with g_object_unref().
 */
GList *
udisks_linux_drive_object_get_siblings (UDisksLinuxDriveObject *object)
{
  GDBusObjectManagerServer *object_manager;
  GList *ret = NULL;
  GList *objects = NULL;
  GList *l;
  gchar *sibling_id = NULL;

  if (object->iface_drive == NULL)
    goto out;

  sibling_id = udisks_drive_dup_sibling_id (object->iface_drive);
  if (sibling_id == NULL || strlen (sibling_id) == 0)
    goto out;

  object_manager = udisks_daemon_get_object_manager (object->daemon);
  objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager));
  for (l = objects; l != NULL; l = l->next)
    {
      GDBusObjectSkeleton *iter_object = G_DBUS_OBJECT_SKELETON (l->data);
      UDisksLinuxDriveObject *iter_linux_drive_object;

      if (!UDISKS_IS_LINUX_DRIVE_OBJECT (iter_object))
        continue;

      iter_linux_drive_object = UDISKS_LINUX_DRIVE_OBJECT (iter_object);
      if (iter_linux_drive_object->iface_drive != NULL &&
          g_strcmp0 (udisks_drive_get_sibling_id (iter_linux_drive_object->iface_drive), sibling_id) == 0)
        {
          ret = g_list_prepend (ret, g_object_ref (iter_object));
        }
    }

 out:
  ret = g_list_reverse (ret);
  g_list_foreach (objects, (GFunc) g_object_unref, NULL);
  g_list_free (objects);
  g_free (sibling_id);
  return ret;
}
Пример #4
0
static void
maybe_remove_mdraid_object (UDisksLinuxProvider     *provider,
                            UDisksLinuxMDRaidObject *object)
{
  gchar *object_uuid = NULL;
  UDisksDaemon *daemon = NULL;

  /* remove the object only if there are no devices left */
  if (udisks_linux_mdraid_object_have_devices (object))
    goto out;

  daemon = udisks_provider_get_daemon (UDISKS_PROVIDER (provider));

  object_uuid = g_strdup (udisks_linux_mdraid_object_get_uuid (object));
  g_dbus_object_manager_server_unexport (udisks_daemon_get_object_manager (daemon),
                                         g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
  g_warn_if_fail (g_hash_table_remove (provider->uuid_to_mdraid, object_uuid));

 out:
  g_free (object_uuid);
}
Пример #5
0
/**
 * udisks_linux_drive_object_is_not_in_use:
 * @object: A #UDisksLinuxDriveObject.
 * @cancellable: (allow-none): A #GCancellable or %NULL.
 * @error: A #GError or %NULL.
 *
 * Checks if the drive represented by @object is in use and sets
 * @error if so.
 *
 * Returns: %TRUE if @object is not is use, %FALSE if @error is set.
 */
gboolean
udisks_linux_drive_object_is_not_in_use (UDisksLinuxDriveObject   *object,
                                         GCancellable             *cancellable,
                                         GError                  **error)
{
  GDBusObjectManagerServer *object_manager;
  const gchar *drive_object_path;
  gboolean ret = TRUE;
  GList *objects = NULL;
  GList *l;

  g_return_val_if_fail (UDISKS_IS_LINUX_DRIVE_OBJECT (object), FALSE);
  g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

  drive_object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object));

  object_manager = udisks_daemon_get_object_manager (object->daemon);
  objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager));

  /* Visit all block devices related to the drive... */
  for (l = objects; l != NULL; l = l->next)
    {
      GDBusObjectSkeleton *iter_object = G_DBUS_OBJECT_SKELETON (l->data);
      UDisksBlock *block;
      UDisksFilesystem *filesystem;

      if (!UDISKS_IS_LINUX_BLOCK_OBJECT (iter_object))
        continue;

      block = udisks_object_peek_block (UDISKS_OBJECT (iter_object));
      filesystem = udisks_object_peek_filesystem (UDISKS_OBJECT (iter_object));

      if (g_strcmp0 (udisks_block_get_drive (block), drive_object_path) != 0)
        continue;

      /* bail if block device is mounted */
      if (filesystem != NULL)
        {
          if (g_strv_length ((gchar **) udisks_filesystem_get_mount_points (filesystem)) > 0)
            {
              g_set_error (error,
                           UDISKS_ERROR,
                           UDISKS_ERROR_DEVICE_BUSY,
                           "Device %s is mounted",
                           udisks_block_get_preferred_device (block));
              ret = FALSE;
              goto out;
            }
        }

      /* bail if block device is unlocked (LUKS) */
      if (is_block_unlocked (objects, g_dbus_object_get_object_path (G_DBUS_OBJECT (iter_object))))
        {
          g_set_error (error,
                       UDISKS_ERROR,
                       UDISKS_ERROR_DEVICE_BUSY,
                       "Encrypted device %s is unlocked",
                       udisks_block_get_preferred_device (block));
          ret = FALSE;
          goto out;
        }
    }

 out:
  g_list_free_full (objects, g_object_unref);
  return ret;
}
Пример #6
0
/* called with lock held */
static void
handle_block_uevent_for_drive (UDisksLinuxProvider *provider,
                               const gchar         *action,
                               UDisksLinuxDevice   *device)
{
  UDisksLinuxDriveObject *object;
  UDisksDaemon *daemon;
  const gchar *sysfs_path;
  gchar *vpd;

  vpd = NULL;
  daemon = udisks_provider_get_daemon (UDISKS_PROVIDER (provider));
  sysfs_path = g_udev_device_get_sysfs_path (device->udev_device);

  if (g_strcmp0 (action, "remove") == 0)
    {
      object = g_hash_table_lookup (provider->sysfs_path_to_drive, sysfs_path);
      if (object != NULL)
        {
          GList *devices;

          udisks_linux_drive_object_uevent (object, action, device);

          g_warn_if_fail (g_hash_table_remove (provider->sysfs_path_to_drive, sysfs_path));

          devices = udisks_linux_drive_object_get_devices (object);
          if (devices == NULL)
            {
              const gchar *existing_vpd;
              existing_vpd = g_object_get_data (G_OBJECT (object), "x-vpd");
              g_dbus_object_manager_server_unexport (udisks_daemon_get_object_manager (daemon),
                                                     g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
              g_warn_if_fail (g_hash_table_remove (provider->vpd_to_drive, existing_vpd));
            }
          g_list_foreach (devices, (GFunc) g_object_unref, NULL);
          g_list_free (devices);
        }
    }
  else
    {
      if (!udisks_linux_drive_object_should_include_device (provider->gudev_client, device, &vpd))
        goto out;

      if (vpd == NULL)
        {
          udisks_debug ("Ignoring block device %s with no serial or WWN",
                        g_udev_device_get_sysfs_path (device->udev_device));
          goto out;
        }
      object = g_hash_table_lookup (provider->vpd_to_drive, vpd);
      if (object != NULL)
        {
          if (g_hash_table_lookup (provider->sysfs_path_to_drive, sysfs_path) == NULL)
            g_hash_table_insert (provider->sysfs_path_to_drive, g_strdup (sysfs_path), object);
          udisks_linux_drive_object_uevent (object, action, device);
        }
      else
        {
          object = udisks_linux_drive_object_new (daemon, device);
          if (object != NULL)
            {
              g_object_set_data_full (G_OBJECT (object), "x-vpd", g_strdup (vpd), g_free);
              g_dbus_object_manager_server_export_uniquely (udisks_daemon_get_object_manager (daemon),
                                                            G_DBUS_OBJECT_SKELETON (object));
              g_hash_table_insert (provider->vpd_to_drive, g_strdup (vpd), object);
              g_hash_table_insert (provider->sysfs_path_to_drive, g_strdup (sysfs_path), object);

              /* schedule initial housekeeping for the drive unless coldplugging */
              if (!provider->coldplug)
                {
                  g_io_scheduler_push_job (perform_initial_housekeeping_for_drive,
                                           g_object_ref (object),
                                           (GDestroyNotify) g_object_unref,
                                           G_PRIORITY_DEFAULT,
                                           NULL);
                }
            }
        }
    }

 out:
  g_free (vpd);
}
Пример #7
0
static void
handle_block_uevent_for_mdraid_with_uuid (UDisksLinuxProvider *provider,
                                          const gchar         *action,
                                          UDisksLinuxDevice   *device,
                                          const gchar         *uuid,
                                          gboolean             is_member)
{
  UDisksLinuxMDRaidObject *object;
  UDisksDaemon *daemon;
  const gchar *sysfs_path;

  daemon = udisks_provider_get_daemon (UDISKS_PROVIDER (provider));
  sysfs_path = g_udev_device_get_sysfs_path (device->udev_device);

  /* if uuid is NULL or bogus, consider it a remove event */
  if (uuid == NULL || g_strcmp0 (uuid, "00000000:00000000:00000000:00000000") == 0)
    action = "remove";

  if (g_strcmp0 (action, "remove") == 0)
    {
      /* first check if this device was a member */
      object = g_hash_table_lookup (provider->sysfs_path_to_mdraid_members, sysfs_path);
      if (object != NULL)
        {
          udisks_linux_mdraid_object_uevent (object, action, device, TRUE /* is_member */);
          g_warn_if_fail (g_hash_table_remove (provider->sysfs_path_to_mdraid_members, sysfs_path));
          maybe_remove_mdraid_object (provider, object);
        }

      /* then check if the device was the raid device */
      object = g_hash_table_lookup (provider->sysfs_path_to_mdraid, sysfs_path);
      if (object != NULL)
        {
          udisks_linux_mdraid_object_uevent (object, action, device, FALSE /* is_member */);
          g_warn_if_fail (g_hash_table_remove (provider->sysfs_path_to_mdraid, sysfs_path));
          maybe_remove_mdraid_object (provider, object);
        }
    }
  else
    {
      if (uuid == NULL)
        goto out;

      object = g_hash_table_lookup (provider->uuid_to_mdraid, uuid);
      if (object != NULL)
        {
          if (is_member)
            {
              if (g_hash_table_lookup (provider->sysfs_path_to_mdraid_members, sysfs_path) == NULL)
                g_hash_table_insert (provider->sysfs_path_to_mdraid_members, g_strdup (sysfs_path), object);
            }
          else
            {
              if (g_hash_table_lookup (provider->sysfs_path_to_mdraid, sysfs_path) == NULL)
                g_hash_table_insert (provider->sysfs_path_to_mdraid, g_strdup (sysfs_path), object);
            }
          udisks_linux_mdraid_object_uevent (object, action, device, is_member);
        }
      else
        {
          object = udisks_linux_mdraid_object_new (daemon, uuid);
          udisks_linux_mdraid_object_uevent (object, action, device, is_member);
          g_dbus_object_manager_server_export_uniquely (udisks_daemon_get_object_manager (daemon),
                                                        G_DBUS_OBJECT_SKELETON (object));
          g_hash_table_insert (provider->uuid_to_mdraid, g_strdup (uuid), object);
          if (is_member)
            g_hash_table_insert (provider->sysfs_path_to_mdraid_members, g_strdup (sysfs_path), object);
          else
            g_hash_table_insert (provider->sysfs_path_to_mdraid, g_strdup (sysfs_path), object);
        }
    }

 out:
  ;
}
Пример #8
0
static void
udisks_linux_provider_start (UDisksProvider *_provider)
{
  UDisksLinuxProvider *provider = UDISKS_LINUX_PROVIDER (_provider);
  UDisksDaemon *daemon;
  UDisksManager *manager;
  GList *devices;
  GList *udisks_devices;
  GList *l;
  guint n;

  provider->coldplug = TRUE;

  if (UDISKS_PROVIDER_CLASS (udisks_linux_provider_parent_class)->start != NULL)
    UDISKS_PROVIDER_CLASS (udisks_linux_provider_parent_class)->start (_provider);

  daemon = udisks_provider_get_daemon (UDISKS_PROVIDER (provider));

  provider->manager_object = udisks_object_skeleton_new ("/org/freedesktop/UDisks2/Manager");
  manager = udisks_linux_manager_new (daemon);
  udisks_object_skeleton_set_manager (provider->manager_object, manager);
  g_object_unref (manager);

  g_dbus_object_manager_server_export (udisks_daemon_get_object_manager (daemon),
                                       G_DBUS_OBJECT_SKELETON (provider->manager_object));

  provider->sysfs_to_block = g_hash_table_new_full (g_str_hash,
                                                    g_str_equal,
                                                    g_free,
                                                    (GDestroyNotify) g_object_unref);
  provider->vpd_to_drive = g_hash_table_new_full (g_str_hash,
                                                  g_str_equal,
                                                  g_free,
                                                  (GDestroyNotify) g_object_unref);
  provider->sysfs_path_to_drive = g_hash_table_new_full (g_str_hash,
                                                         g_str_equal,
                                                         g_free,
                                                         NULL);
  provider->uuid_to_mdraid = g_hash_table_new_full (g_str_hash,
                                                    g_str_equal,
                                                    g_free,
                                                    (GDestroyNotify) g_object_unref);
  provider->sysfs_path_to_mdraid = g_hash_table_new_full (g_str_hash,
                                                          g_str_equal,
                                                          g_free,
                                                          NULL);
  provider->sysfs_path_to_mdraid_members = g_hash_table_new_full (g_str_hash,
                                                                  g_str_equal,
                                                                  g_free,
                                                                  NULL);

  devices = g_udev_client_query_by_subsystem (provider->gudev_client, "block");

  /* make sure we process sda before sdz and sdz before sdaa */
  devices = g_list_sort (devices, (GCompareFunc) udev_device_name_cmp);

  /* probe for extra data we don't get from udev */
  udisks_info ("Initialization (device probing)");
  udisks_devices = NULL;
  for (l = devices; l != NULL; l = l->next)
    {
      GUdevDevice *device = G_UDEV_DEVICE (l->data);
      udisks_devices = g_list_prepend (udisks_devices, udisks_linux_device_new_sync (device));
    }
  udisks_devices = g_list_reverse (udisks_devices);

  /* do two coldplug runs to handle dependencies between devices */
  for (n = 0; n < 2; n++)
    {
      udisks_info ("Initialization (coldplug %d/2)", n + 1);
      for (l = udisks_devices; l != NULL; l = l->next)
        {
          UDisksLinuxDevice *device = l->data;
          udisks_linux_provider_handle_uevent (provider, "add", device);
        }
    }
  g_list_free_full (devices, g_object_unref);
  g_list_free_full (udisks_devices, g_object_unref);
  udisks_info ("Initialization complete");

  /* schedule housekeeping for every 10 minutes */
  provider->housekeeping_timeout = g_timeout_add_seconds (10*60,
                                                          on_housekeeping_timeout,
                                                          provider);
  /* ... and also do an initial run */
  on_housekeeping_timeout (provider);

  provider->coldplug = FALSE;

  /* update Block:Configuration whenever fstab or crypttab entries are added or removed */
  g_signal_connect (udisks_daemon_get_fstab_monitor (daemon),
                    "entry-added",
                    G_CALLBACK (fstab_monitor_on_entry_added),
                    provider);
  g_signal_connect (udisks_daemon_get_fstab_monitor (daemon),
                    "entry-removed",
                    G_CALLBACK (fstab_monitor_on_entry_removed),
                    provider);
  g_signal_connect (udisks_daemon_get_crypttab_monitor (daemon),
                    "entry-added",
                    G_CALLBACK (crypttab_monitor_on_entry_added),
                    provider);
  g_signal_connect (udisks_daemon_get_crypttab_monitor (daemon),
                    "entry-removed",
                    G_CALLBACK (crypttab_monitor_on_entry_removed),
                    provider);
}
Пример #9
0
static void
lvm_update_vgs (GObject      *source_obj,
                GAsyncResult *result,
                gpointer      user_data)
{
  UDisksLVM2State *state;
  UDisksDaemon *daemon = UDISKS_DAEMON (source_obj);
  GDBusObjectManagerServer *manager;

  GTask *task = G_TASK (result);
  GError *error = NULL;
  VGsPVsData *data = g_task_propagate_pointer (task, &error);
  BDLVMVGdata **vgs = NULL;
  BDLVMPVdata **pvs = NULL;

  GHashTableIter vg_name_iter;
  gpointer key, value;
  const gchar *vg_name;

  if (!data)
    {
      if (error)
        udisks_warning ("LVM2 plugin: %s", error->message);
      else
        /* this should never happen */
        udisks_warning ("LVM2 plugin: failure but no error when getting VGs!");

      return;
    }
  vgs = data->vgs;
  pvs = data->pvs;

  /* free the data container (but not 'vgs' and 'pvs') */
  g_free (data);

  manager = udisks_daemon_get_object_manager (daemon);
  state = get_module_state (daemon);

  /* Remove obsolete groups */
  g_hash_table_iter_init (&vg_name_iter,
                          udisks_lvm2_state_get_name_to_volume_group (state));
  while (g_hash_table_iter_next (&vg_name_iter, &key, &value))
    {
      UDisksLinuxVolumeGroupObject *group;
      gboolean found = FALSE;

      vg_name = key;
      group = value;

      for (BDLVMVGdata **vgs_p=vgs; !found && (*vgs_p); vgs_p++)
          found = g_strcmp0 ((*vgs_p)->name, vg_name) == 0;

      if (!found)
        {
          udisks_linux_volume_group_object_destroy (group);
          g_dbus_object_manager_server_unexport (manager,
                                                 g_dbus_object_get_object_path (G_DBUS_OBJECT (group)));
          g_hash_table_iter_remove (&vg_name_iter);
        }
    }

  /* Add new groups and update existing groups */
  for (BDLVMVGdata **vgs_p=vgs; *vgs_p; vgs_p++)
    {
      UDisksLinuxVolumeGroupObject *group;
      GSList *vg_pvs = NULL;
      vg_name = (*vgs_p)->name;
      group = g_hash_table_lookup (udisks_lvm2_state_get_name_to_volume_group (state),
                                   vg_name);

      if (group == NULL)
        {
          group = udisks_linux_volume_group_object_new (daemon, vg_name);
          g_hash_table_insert (udisks_lvm2_state_get_name_to_volume_group (state),
                               g_strdup (vg_name), group);
        }

      for (BDLVMPVdata **pvs_p=pvs; *pvs_p; pvs_p++)
        if (g_strcmp0 ((*pvs_p)->vg_name, vg_name) == 0)
            vg_pvs = g_slist_prepend (vg_pvs, *pvs_p);

      udisks_linux_volume_group_object_update (group, *vgs_p, vg_pvs);
    }

  /* this is safe to do -- all BDLVMPVdata objects are still existing because
     the function that frees them is scheduled in main loop by the
     udisks_linux_volume_group_object_update() call above */
  for (BDLVMPVdata **pvs_p=pvs; *pvs_p; pvs_p++)
    if ((*pvs_p)->vg_name == NULL)
      bd_lvm_pvdata_free (*pvs_p);

  /* only free the containers, the contents were passed further */
  g_free (vgs);
  g_free (pvs);
}