summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2011-08-16 10:50:33 -0400
committerDavid Zeuthen <davidz@redhat.com>2011-08-16 10:50:33 -0400
commitc12cd7a91ae56e937a13746a3a87db73cc300e84 (patch)
tree80b61f1472f254850459a1dc7b201421535819a1
parent157b215bfccf469e729633e67e32a7ebc4590169 (diff)
Factor out drive functionality into three separate types
Signed-off-by: David Zeuthen <davidz@redhat.com>
-rw-r--r--doc/udisks2-docs.xml7
-rw-r--r--doc/udisks2-sections.txt43
-rw-r--r--doc/udisks2.types2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/udisksdaemontypes.h6
-rw-r--r--src/udiskslinuxblock.c8
-rw-r--r--src/udiskslinuxdrive.c1093
-rw-r--r--src/udiskslinuxdrive.h22
-rw-r--r--src/udiskslinuxdriveata.c387
-rw-r--r--src/udiskslinuxdriveata.h43
-rw-r--r--src/udiskslinuxdriveobject.c860
-rw-r--r--src/udiskslinuxdriveobject.h57
-rw-r--r--src/udiskslinuxprovider.c80
13 files changed, 1531 insertions, 1079 deletions
diff --git a/doc/udisks2-docs.xml b/doc/udisks2-docs.xml
index 854f37e..a6a7426 100644
--- a/doc/udisks2-docs.xml
+++ b/doc/udisks2-docs.xml
@@ -191,11 +191,16 @@
<xi:include href="xml/udisksspawnedjob.xml"/>
</chapter>
<chapter id="ref-daemon-linux">
- <title>Linux-specific implementation</title>
+ <title>Linux-specific objects and providers</title>
<xi:include href="xml/udiskslinuxprovider.xml"/>
+ <xi:include href="xml/udiskslinuxdriveobject.xml"/>
+ </chapter>
+ <chapter id="ref-daemon-linux-ifaces">
+ <title>Linux implementation of interfaces</title>
<xi:include href="xml/udiskslinuxmanager.xml"/>
<xi:include href="xml/udiskslinuxblock.xml"/>
<xi:include href="xml/udiskslinuxdrive.xml"/>
+ <xi:include href="xml/udiskslinuxdriveata.xml"/>
<xi:include href="xml/udiskslinuxfilesystem.xml"/>
<xi:include href="xml/udiskslinuxencrypted.xml"/>
<xi:include href="xml/udiskslinuxswapspace.xml"/>
diff --git a/doc/udisks2-sections.txt b/doc/udisks2-sections.txt
index 17cabce..4d5e48c 100644
--- a/doc/udisks2-sections.txt
+++ b/doc/udisks2-sections.txt
@@ -160,21 +160,50 @@ udisks_linux_block_get_type
</SECTION>
<SECTION>
+<FILE>udiskslinuxdriveobject</FILE>
+<TITLE>UDisksLinuxDriveObject</TITLE>
+UDisksLinuxDriveObject
+udisks_linux_drive_object_new
+udisks_linux_drive_object_uevent
+udisks_linux_drive_object_get_daemon
+udisks_linux_drive_object_get_block
+udisks_linux_drive_object_get_device
+udisks_linux_drive_object_get_devices
+udisks_linux_drive_object_housekeeping
+<SUBSECTION Standard>
+UDISKS_TYPE_LINUX_DRIVE_OBJECT
+UDISKS_LINUX_DRIVE_OBJECT
+UDISKS_IS_LINUX_DRIVE_OBJECT
+<SUBSECTION Private>
+udisks_linux_drive_object_get_type
+udisks_linux_drive_object_should_include_device
+</SECTION>
+
+<SECTION>
<FILE>udiskslinuxdrive</FILE>
-<TITLE>UDisksLinuxDrive</TITLE>
UDisksLinuxDrive
udisks_linux_drive_new
-udisks_linux_drive_uevent
-udisks_linux_drive_get_daemon
-udisks_linux_drive_get_devices
-udisks_linux_drive_housekeeping
+udisks_linux_drive_update
<SUBSECTION Standard>
-UDISKS_TYPE_LINUX_DRIVE
UDISKS_LINUX_DRIVE
UDISKS_IS_LINUX_DRIVE
+UDISKS_TYPE_LINUX_DRIVE
<SUBSECTION Private>
udisks_linux_drive_get_type
-udisks_linux_drive_should_include_device
+</SECTION>
+
+<SECTION>
+<FILE>udiskslinuxdriveata</FILE>
+UDisksLinuxDriveAta
+udisks_linux_drive_ata_new
+udisks_linux_drive_ata_update
+udisks_linux_drive_ata_refresh_smart_sync
+<SUBSECTION Standard>
+UDISKS_LINUX_DRIVE_ATA
+UDISKS_IS_LINUX_DRIVE_ATA
+UDISKS_TYPE_LINUX_DRIVE_ATA
+<SUBSECTION Private>
+udisks_linux_drive_ata_get_type
</SECTION>
<SECTION>
diff --git a/doc/udisks2.types b/doc/udisks2.types
index 7b0ceee..c8de422 100644
--- a/doc/udisks2.types
+++ b/doc/udisks2.types
@@ -3,6 +3,8 @@ udisks_client_get_type
udisks_daemon_get_type
udisks_linux_block_get_type
udisks_linux_drive_get_type
+udisks_linux_drive_ata_get_type
+udisks_linux_drive_object_get_type
udisks_base_job_get_type
udisks_spawned_job_get_type
udisks_threaded_job_get_type
diff --git a/src/Makefile.am b/src/Makefile.am
index 962cf12..f628971 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -52,7 +52,9 @@ libudisks_daemon_la_SOURCES = \
udiskslinuxencrypted.h udiskslinuxencrypted.c \
udiskslinuxswapspace.h udiskslinuxswapspace.c \
udiskslinuxloop.h udiskslinuxloop.c \
+ udiskslinuxdriveobject.h udiskslinuxdriveobject.c \
udiskslinuxdrive.h udiskslinuxdrive.c \
+ udiskslinuxdriveata.h udiskslinuxdriveata.c \
udiskslinuxmanager.h udiskslinuxmanager.c \
udisksbasejob.h udisksbasejob.c \
udisksspawnedjob.h udisksspawnedjob.c \
diff --git a/src/udisksdaemontypes.h b/src/udisksdaemontypes.h
index edf97c2..853fbc8 100644
--- a/src/udisksdaemontypes.h
+++ b/src/udisksdaemontypes.h
@@ -37,9 +37,15 @@ typedef struct _UDisksLinuxProvider UDisksLinuxProvider;
struct _UDisksLinuxBlock;
typedef struct _UDisksLinuxBlock UDisksLinuxBlock;
+struct _UDisksLinuxDriveObject;
+typedef struct _UDisksLinuxDriveObject UDisksLinuxDriveObject;
+
struct _UDisksLinuxDrive;
typedef struct _UDisksLinuxDrive UDisksLinuxDrive;
+struct _UDisksLinuxDriveAta;
+typedef struct _UDisksLinuxDriveAta UDisksLinuxDriveAta;
+
struct _UDisksBaseJob;
typedef struct _UDisksBaseJob UDisksBaseJob;
diff --git a/src/udiskslinuxblock.c b/src/udiskslinuxblock.c
index bec388d..b6b13a7 100644
--- a/src/udiskslinuxblock.c
+++ b/src/udiskslinuxblock.c
@@ -40,6 +40,7 @@
#include "udiskslinuxblock.h"
#include "udisksmount.h"
#include "udisksmountmonitor.h"
+#include "udiskslinuxdriveobject.h"
#include "udiskslinuxdrive.h"
#include "udiskslinuxfilesystem.h"
#include "udiskslinuxencrypted.h"
@@ -1252,16 +1253,13 @@ find_drive (GDBusObjectManagerServer *object_manager,
for (l = objects; l != NULL; l = l->next)
{
GDBusObjectSkeleton *object = G_DBUS_OBJECT_SKELETON (l->data);
- UDisksLinuxDrive *drive;
GList *drive_devices;
GList *j;
- if (!UDISKS_IS_LINUX_DRIVE (object))
+ if (!UDISKS_IS_LINUX_DRIVE_OBJECT (object))
continue;
- drive = UDISKS_LINUX_DRIVE (object);
- drive_devices = udisks_linux_drive_get_devices (drive);
-
+ drive_devices = udisks_linux_drive_object_get_devices (UDISKS_LINUX_DRIVE_OBJECT (object));
for (j = drive_devices; j != NULL; j = j->next)
{
GUdevDevice *drive_device = G_UDEV_DEVICE (j->data);
diff --git a/src/udiskslinuxdrive.c b/src/udiskslinuxdrive.c
index df42c98..9a6db9a 100644
--- a/src/udiskslinuxdrive.c
+++ b/src/udiskslinuxdrive.c
@@ -21,25 +21,32 @@
#include "config.h"
#include <glib/gi18n-lib.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <mntent.h>
-#include <atasmart.h>
+#include <glib/gstdio.h>
#include "udiskslogging.h"
-#include "udisksdaemon.h"
-#include "udisksdaemonutil.h"
#include "udiskslinuxprovider.h"
+#include "udiskslinuxdriveobject.h"
#include "udiskslinuxdrive.h"
#include "udiskslinuxblock.h"
+#include "udisksdaemon.h"
+#include "udiskscleanup.h"
+#include "udisksdaemonutil.h"
/**
* SECTION:udiskslinuxdrive
* @title: UDisksLinuxDrive
- * @short_description: Linux drives (ATA, SCSI, Software RAID, etc.)
+ * @short_description: Linux implementation of #UDisksDrive
*
- * Object corresponding to a Drive on Linux.
+ * This type provides an implementation of the #UDisksDrive interface
+ * on Linux.
*/
typedef struct _UDisksLinuxDriveClass UDisksLinuxDriveClass;
@@ -47,409 +54,53 @@ typedef struct _UDisksLinuxDriveClass UDisksLinuxDriveClass;
/**
* UDisksLinuxDrive:
*
- * The #UDisksLinuxDrive structure contains only private data and
- * should only be accessed using the provided API.
+ * The #UDisksLinuxDrive structure contains only private data and should
+ * only be accessed using the provided API.
*/
struct _UDisksLinuxDrive
{
- UDisksObjectSkeleton parent_instance;
-
- UDisksDaemon *daemon;
-
- /* list of GUdevDevice objects for block objects */
- GList *devices;
-
- /* interfaces */
- UDisksDrive *iface_drive;
- UDisksDriveAta *iface_drive_ata;
-
- /* ATA Smart */
- guint64 ata_smart_updated;
- gboolean ata_smart_failing;
- gdouble ata_smart_temperature;
- guint64 ata_smart_power_on_seconds;
-
- guint64 detection_time_at_construction;
+ UDisksDriveSkeleton parent_instance;
};
-G_LOCK_DEFINE_STATIC (drive_lock);
-
struct _UDisksLinuxDriveClass
{
- UDisksObjectSkeletonClass parent_class;
-};
-
-enum
-{
- PROP_0,
- PROP_DAEMON,
- PROP_DEVICE
+ UDisksDriveSkeletonClass parent_class;
};
-G_DEFINE_TYPE (UDisksLinuxDrive, udisks_linux_drive, UDISKS_TYPE_OBJECT_SKELETON);
-
-static void
-udisks_linux_drive_finalize (GObject *object)
-{
- UDisksLinuxDrive *drive = UDISKS_LINUX_DRIVE (object);
-
- /* note: we don't hold a ref to drive->daemon or drive->mount_monitor */
- g_list_foreach (drive->devices, (GFunc) g_object_unref, NULL);
- g_list_free (drive->devices);
-
- if (drive->iface_drive != NULL)
- g_object_unref (drive->iface_drive);
- if (drive->iface_drive_ata != NULL)
- g_object_unref (drive->iface_drive_ata);
-
- if (G_OBJECT_CLASS (udisks_linux_drive_parent_class)->finalize != NULL)
- G_OBJECT_CLASS (udisks_linux_drive_parent_class)->finalize (object);
-}
-
-static void
-udisks_linux_drive_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- UDisksLinuxDrive *drive = UDISKS_LINUX_DRIVE (object);
-
- switch (prop_id)
- {
- case PROP_DAEMON:
- g_value_set_object (value, udisks_linux_drive_get_daemon (drive));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-udisks_linux_drive_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- UDisksLinuxDrive *drive = UDISKS_LINUX_DRIVE (object);
-
- switch (prop_id)
- {
- case PROP_DAEMON:
- g_assert (drive->daemon == NULL);
- /* we don't take a reference to the daemon */
- drive->daemon = g_value_get_object (value);
- break;
+static void drive_iface_init (UDisksDriveIface *iface);
- case PROP_DEVICE:
- g_assert (drive->devices == NULL);
- drive->devices = g_list_prepend (NULL, g_value_dup_object (value));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
+G_DEFINE_TYPE_WITH_CODE (UDisksLinuxDrive, udisks_linux_drive, UDISKS_TYPE_DRIVE_SKELETON,
+ G_IMPLEMENT_INTERFACE (UDISKS_TYPE_DRIVE, drive_iface_init));
+/* ---------------------------------------------------------------------------------------------------- */
static void
udisks_linux_drive_init (UDisksLinuxDrive *drive)
{
-}
-
-static GObjectConstructParam *
-find_construct_property (guint n_construct_properties,
- GObjectConstructParam *construct_properties,
- const gchar *name)
-{
- guint n;
- for (n = 0; n < n_construct_properties; n++)
- if (g_strcmp0 (g_param_spec_get_name (construct_properties[n].pspec), name) == 0)
- return &construct_properties[n];
- return NULL;
-}
-
-/* unless given, compute object path from sysfs path */
-static GObject *
-udisks_linux_drive_constructor (GType type,
- guint n_construct_properties,
- GObjectConstructParam *construct_properties)
-{
- GObjectConstructParam *cp;
- UDisksDaemon *daemon;
- GUdevClient *client;
- GUdevDevice *device;
-
- cp = find_construct_property (n_construct_properties, construct_properties, "daemon");
- g_assert (cp != NULL);
- daemon = UDISKS_DAEMON (g_value_get_object (cp->value));
- g_assert (daemon != NULL);
-
- client = udisks_linux_provider_get_udev_client (udisks_daemon_get_linux_provider (daemon));
-
- cp = find_construct_property (n_construct_properties, construct_properties, "device");
- g_assert (cp != NULL);
- device = G_UDEV_DEVICE (g_value_get_object (cp->value));
- g_assert (device != NULL);
-
- if (!udisks_linux_drive_should_include_device (client, device, NULL))
- {
- return NULL;
- }
- else
- {
- return G_OBJECT_CLASS (udisks_linux_drive_parent_class)->constructor (type,
- n_construct_properties,
- construct_properties);
- }
-}
-
-static void
-strip_and_replace_with_uscore (gchar *s)
-{
- guint n;
-
- if (s == NULL)
- goto out;
-
- g_strstrip (s);
-
- for (n = 0; s != NULL && s[n] != '\0'; n++)
- {
- if (s[n] == ' ' || s[n] == '-')
- s[n] = '_';
- }
-
- out:
- ;
-}
-
-static void
-udisks_linux_drive_constructed (GObject *object)
-{
- UDisksLinuxDrive *drive = UDISKS_LINUX_DRIVE (object);
- gchar *vendor;
- gchar *model;
- gchar *serial;
- GString *str;
-
- /* initial coldplug */
- udisks_linux_drive_uevent (drive, "add", drive->devices->data);
-
- /* compute the object path */
- vendor = g_strdup (udisks_drive_get_vendor (drive->iface_drive));
- model = g_strdup (udisks_drive_get_model (drive->iface_drive));
- serial = g_strdup (udisks_drive_get_serial (drive->iface_drive));
- strip_and_replace_with_uscore (vendor);
- strip_and_replace_with_uscore (model);
- strip_and_replace_with_uscore (serial);
- str = g_string_new ("/org/freedesktop/UDisks2/drives/");
- if (vendor == NULL && model == NULL && serial == NULL)
- {
- g_string_append (str, "drive");
- }
- else
- {
- /* <VENDOR>_<MODEL>_<SERIAL> */
- if (vendor != NULL && strlen (vendor) > 0)
- {
- udisks_safe_append_to_object_path (str, vendor);
- }
- if (model != NULL && strlen (model) > 0)
- {
- if (str->str[str->len - 1] != '/')
- g_string_append_c (str, '_');
- udisks_safe_append_to_object_path (str, model);
- }
- if (serial != NULL && strlen (serial) > 0)
- {
- if (str->str[str->len - 1] != '/')
- g_string_append_c (str, '_');
- udisks_safe_append_to_object_path (str, serial);
- }
- }
- g_free (vendor);
- g_free (model);
- g_free (serial);
- g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (drive), str->str);
- g_string_free (str, TRUE);
-
- if (G_OBJECT_CLASS (udisks_linux_drive_parent_class)->constructed != NULL)
- G_OBJECT_CLASS (udisks_linux_drive_parent_class)->constructed (object);
+ g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (drive),
+ G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
}
static void
udisks_linux_drive_class_init (UDisksLinuxDriveClass *klass)
{
- GObjectClass *gobject_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
- gobject_class->constructor = udisks_linux_drive_constructor;
- gobject_class->finalize = udisks_linux_drive_finalize;
- gobject_class->constructed = udisks_linux_drive_constructed;
- gobject_class->set_property = udisks_linux_drive_set_property;
- gobject_class->get_property = udisks_linux_drive_get_property;
-
- /**
- * UDisksLinuxDrive:daemon:
- *
- * The #UDisksDaemon the object is for.
- */
- g_object_class_install_property (gobject_class,
- PROP_DAEMON,
- g_param_spec_object ("daemon",
- "Daemon",
- "The daemon the object is for",
- UDISKS_TYPE_DAEMON,
- G_PARAM_READABLE |
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
-
- /**
- * UDisksLinuxDrive:device:
- *
- * The #GUdevDevice for the object. Connect to the #GObject::notify
- * signal to get notified whenever this is updated.
- */
- g_object_class_install_property (gobject_class,
- PROP_DEVICE,
- g_param_spec_object ("device",
- "Device",
- "The device for the object",
- G_UDEV_TYPE_DEVICE,
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
-
}
/**
* udisks_linux_drive_new:
- * @daemon: A #UDisksDaemon.
- * @device: The #GUdevDevice for the sysfs block device.
- *
- * Create a new drive object.
- *
- * Returns: A #UDisksLinuxDrive object or %NULL if @device does not represent a drive. Free with g_object_unref().
- */
-UDisksLinuxDrive *
-udisks_linux_drive_new (UDisksDaemon *daemon,
- GUdevDevice *device)
-{
- GObject *object;
-
- g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
- g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
-
- object = g_object_new (UDISKS_TYPE_LINUX_DRIVE,
- "daemon", daemon,
- "device", device,
- NULL);
-
- if (object != NULL)
- return UDISKS_LINUX_DRIVE (object);
- else
- return NULL;
-}
-
-/**
- * udisks_linux_drive_get_daemon:
- * @drive: A #UDisksLinuxDrive.
- *
- * Gets the daemon used by @drive.
*
- * Returns: A #UDisksDaemon. Do not free, the object is owned by @drive.
- */
-UDisksDaemon *
-udisks_linux_drive_get_daemon (UDisksLinuxDrive *drive)
-{
- g_return_val_if_fail (UDISKS_IS_LINUX_DRIVE (drive), NULL);
- return drive->daemon;
-}
-
-/**
- * udisks_linux_drive_get_devices:
- * @drive: A #UDisksLinuxDrive.
- *
- * Gets the current #GUdevDevice objects associated with @drive.
+ * Creates a new #UDisksLinuxDrive instance.
*
- * Returns: A list of #GUdevDevice objects. Free each element with
- * g_object_unref(), then free the list with g_list_free().
+ * Returns: A new #UDisksLinuxDrive. Free with g_object_unref().
*/
-GList *
-udisks_linux_drive_get_devices (UDisksLinuxDrive *drive)
-{
- GList *ret;
- g_return_val_if_fail (UDISKS_IS_LINUX_DRIVE (drive), NULL);
- ret = g_list_copy (drive->devices);
- g_list_foreach (ret, (GFunc) g_object_ref, NULL);
- return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-typedef gboolean (*HasInterfaceFunc) (UDisksLinuxDrive *drive);
-typedef void (*ConnectInterfaceFunc) (UDisksLinuxDrive *drive);
-typedef void (*UpdateInterfaceFunc) (UDisksLinuxDrive *drive,
- const gchar *uevent_action,
- GDBusInterface *interface);
-
-static void
-update_iface (UDisksLinuxDrive *drive,
- const gchar *uevent_action,
- HasInterfaceFunc has_func,
- ConnectInterfaceFunc connect_func,
- UpdateInterfaceFunc update_func,
- GType skeleton_type,
- gpointer _interface_pointer)
+UDisksDrive *
+udisks_linux_drive_new (void)
{
- gboolean has;
- gboolean add;
- GDBusInterface **interface_pointer = _interface_pointer;
-
- g_return_if_fail (drive != NULL);
- g_return_if_fail (has_func != NULL);
- g_return_if_fail (update_func != NULL);
- g_return_if_fail (g_type_is_a (skeleton_type, G_TYPE_OBJECT));
- g_return_if_fail (g_type_is_a (skeleton_type, G_TYPE_DBUS_INTERFACE));
- g_return_if_fail (interface_pointer != NULL);
- g_return_if_fail (*interface_pointer == NULL || G_IS_DBUS_INTERFACE (*interface_pointer));
-
- add = FALSE;
- has = has_func (drive);
- if (*interface_pointer == NULL)
- {
- if (has)
- {
- *interface_pointer = g_object_new (skeleton_type, NULL);
- if (connect_func != NULL)
- connect_func (drive);
- add = TRUE;
- }
- }
- else
- {
- if (!has)
- {
- g_dbus_object_skeleton_remove_interface (G_DBUS_OBJECT_SKELETON (drive), G_DBUS_INTERFACE_SKELETON (*interface_pointer));
- g_object_unref (*interface_pointer);
- *interface_pointer = NULL;
- }
- }
-
- if (*interface_pointer != NULL)
- {
- update_func (drive, uevent_action, G_DBUS_INTERFACE (*interface_pointer));
- if (add)
- g_dbus_object_skeleton_add_interface (G_DBUS_OBJECT_SKELETON (drive), G_DBUS_INTERFACE_SKELETON (*interface_pointer));
- }
+ return UDISKS_DRIVE (g_object_new (UDISKS_TYPE_LINUX_DRIVE,
+ NULL));
}
/* ---------------------------------------------------------------------------------------------------- */
-/* org.freedesktop.UDisks.Drive */
static const struct
{
@@ -539,9 +190,8 @@ ptr_str_array_compare (const gchar **a,
}
static void
-drive_set_media (UDisksLinuxDrive *drive,
- UDisksDrive *iface,
- GUdevDevice *device)
+set_media (UDisksDrive *iface,
+ GUdevDevice *device)
{
guint n;
GPtrArray *media_compat_array;
@@ -581,9 +231,8 @@ drive_set_media (UDisksLinuxDrive *drive,
}
static void
-drive_set_rotation_rate (UDisksLinuxDrive *drive,
- UDisksDrive *iface,
- GUdevDevice *device)
+set_rotation_rate (UDisksDrive *iface,
+ GUdevDevice *device)
{
gint rate;
@@ -600,144 +249,9 @@ drive_set_rotation_rate (UDisksLinuxDrive *drive,
udisks_drive_set_rotation_rate (iface, rate);
}
-static gboolean
-drive_check (UDisksLinuxDrive *drive)
-{
- return TRUE;
-}
-
-/* TODO: ensure that returned object is for a physical device e.g. not multipath */
-static UDisksObject *
-find_block_object (UDisksLinuxDrive *drive)
-{
- GDBusObjectManagerServer *object_manager;
- UDisksObject *ret;
- GList *objects;
- GList *l;
-
- ret = NULL;
-
- object_manager = udisks_daemon_get_object_manager (udisks_linux_drive_get_daemon (drive));
- objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (object_manager));
- for (l = objects; l != NULL; l = l->next)
- {
- GDBusObjectSkeleton *object = G_DBUS_OBJECT_SKELETON (l->data);
- UDisksBlockDevice *block;
- GUdevDevice *device;
- gboolean is_disk;
-
- if (!UDISKS_IS_LINUX_BLOCK (object))
- continue;
-
- device = udisks_linux_block_get_device (UDISKS_LINUX_BLOCK (object));
- is_disk = (g_strcmp0 (g_udev_device_get_devtype (device), "disk") == 0);
- g_object_unref (device);
-
- if (!is_disk)
- continue;
-
- block = udisks_object_peek_block_device (UDISKS_OBJECT (object));
-
- if (g_strcmp0 (udisks_block_device_get_drive (block),
- g_dbus_object_get_object_path (G_DBUS_OBJECT (drive))) == 0)
- {
- ret = g_object_ref (object);
- goto out;
- }
- }
-
- out:
- g_list_foreach (objects, (GFunc) g_object_unref, NULL);
- g_list_free (objects);
- return ret;
-}
-
-static gboolean
-on_eject (UDisksDrive *drive_iface,
- GDBusMethodInvocation *invocation,
- GVariant *options,
- gpointer user_data)
-{
- UDisksLinuxDrive *drive = UDISKS_LINUX_DRIVE (user_data);
- UDisksObject *block_object;
- UDisksBlockDevice *block;
- UDisksDaemon *daemon;
- const gchar *action_id;
- gchar *error_message;
-
- daemon = NULL;
- block = NULL;
- error_message = NULL;
-
- daemon = udisks_linux_drive_get_daemon (drive);
- block_object = find_block_object (drive);
- if (block_object == NULL)
- {
- g_dbus_method_invocation_return_error (invocation,
- UDISKS_ERROR,
- UDISKS_ERROR_FAILED,
- "Unable to find physical block device for drive");
- goto out;
- }
- block = udisks_object_peek_block_device (block_object);
-
- /* TODO: is it a good idea to overload modify-device? */
- action_id = "org.freedesktop.udisks2.modify-device";
- if (udisks_block_device_get_hint_system (block))
- action_id = "org.freedesktop.udisks2.modify-device-system";
-
- /* Check that the user is actually authorized */
- if (!udisks_daemon_util_check_authorization_sync (daemon,
- block_object,
- action_id,
- options,
- N_("Authentication is required to eject $(udisks2.device)"),
- invocation))
- goto out;
-
- if (!udisks_daemon_launch_spawned_job_sync (daemon,
- NULL, /* GCancellable */
- 0, /* uid_t run_as_uid */
- 0, /* uid_t run_as_euid */
- NULL, /* gint *out_status */
- &error_message,
- NULL, /* input_string */
- "eject \"%s\"",
- udisks_block_device_get_device (block)))
- {
- g_dbus_method_invocation_return_error (invocation,
- UDISKS_ERROR,
- UDISKS_ERROR_FAILED,
- "Error eject %s: %s",
- udisks_block_device_get_device (block),
- error_message);
- goto out;
- }
-
- udisks_drive_complete_eject (drive_iface, invocation);
-
- out:
- if (block_object != NULL)
- g_object_unref (block_object);
- g_free (error_message);
- return TRUE; /* returning TRUE means that we handled the method invocation */
-}
-
-static void
-drive_connect (UDisksLinuxDrive *drive)
-{
- g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (drive->iface_drive),
- G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
- g_signal_connect (drive->iface_drive,
- "handle-eject",
- G_CALLBACK (on_eject),
- drive);
-}
-
static void
-drive_set_connection_bus (UDisksLinuxDrive *drive,
- UDisksDrive *iface,
- GUdevDevice *device)
+set_connection_bus (UDisksDrive *iface,
+ GUdevDevice *device)
{
GUdevDevice *parent;
@@ -767,20 +281,25 @@ drive_set_connection_bus (UDisksLinuxDrive *drive,
}
-static void
-drive_update (UDisksLinuxDrive *drive,
- const gchar *uevent_action,
- GDBusInterface *_iface)
+/**
+ * udisks_linux_drive_update:
+ * @drive: A #UDisksLinuxDrive.
+ * @object: The enclosing #UDisksLinuxDriveObject instance.
+ *
+ * Updates the interface.
+ */
+void
+udisks_linux_drive_update (UDisksLinuxDrive *drive,
+ UDisksLinuxDriveObject *object)
{
- UDisksDrive *iface = UDISKS_DRIVE (_iface);
+ UDisksDrive *iface = UDISKS_DRIVE (drive);
GUdevDevice *device;
gchar *sort_key;
- if (drive->devices == NULL)
+ device = udisks_linux_drive_object_get_device (object, TRUE /* get_hw */);
+ if (device == NULL)
goto out;
- device = G_UDEV_DEVICE (drive->devices->data);
-
/* this is the _almost_ the same for both ATA and SCSI devices (cf. udev's ata_id and scsi_id)
* but we special case since there are subtle differences...
*/
@@ -916,9 +435,9 @@ drive_update (UDisksLinuxDrive *drive,
/* common bits go here */
udisks_drive_set_media_removable (iface, g_udev_device_get_sysfs_attr_as_boolean (device, "removable"));
udisks_drive_set_size (iface, udisks_daemon_util_block_get_size (device));
- drive_set_media (drive, iface, device);
- drive_set_rotation_rate (drive, iface, device);
- drive_set_connection_bus (drive, iface, device);
+ set_media (iface, device);
+ set_rotation_rate (iface, device);
+ set_connection_bus (iface, device);
#if 0
/* This ensures that devices are shown in the order they are detected */
@@ -931,129 +450,43 @@ drive_update (UDisksLinuxDrive *drive,
{
GUdevClient *client;
GUdevDevice *ns_device;
- client = udisks_linux_provider_get_udev_client (udisks_daemon_get_linux_provider (drive->daemon));
+ client = g_udev_client_new (NULL);
ns_device = g_udev_client_query_by_sysfs_path (client, g_udev_device_get_sysfs_path (device));
sort_key = g_strdup_printf ("%" G_GUINT64_FORMAT,
time (NULL) * G_USEC_PER_SEC - g_udev_device_get_usec_since_initialized (ns_device));
g_object_unref (ns_device);
+ g_object_unref (client);
}
#endif
udisks_drive_set_sort_key (iface, sort_key);
g_free (sort_key);
out:
- ;
+ if (device != NULL)
+ g_object_unref (device);
}
/* ---------------------------------------------------------------------------------------------------- */
-static void drive_ata_smart_update (UDisksLinuxDrive *drive);
-
-static gboolean
-update_smart (UDisksLinuxDrive *drive,
- gboolean nowakeup,
- GError **error)
-{
- gboolean ret;
- SkDisk *d;
- SkBool awake;
- SkBool good;
- uint64_t temp_mkelvin;
- uint64_t power_on_msec;
- GUdevDevice *device;
-
- d = NULL;
- ret = FALSE;
-
- device = G_UDEV_DEVICE (drive->devices->data);
-
- if (sk_disk_open (g_udev_device_get_device_file (device), &d) != 0)
- {
- g_set_error (error,
- UDISKS_ERROR,
- UDISKS_ERROR_FAILED,
- "sk_disk_open: %m");
- goto out;
- }
-
- if (sk_disk_check_sleep_mode (d, &awake) != 0)
- {
- g_set_error (error,
- UDISKS_ERROR,
- UDISKS_ERROR_FAILED,
- "sk_disk_check_sleep_mode: %m");
- goto out;
- }
-
- /* don't wake up disk unless specically asked to */
- if (nowakeup && !awake)
- {
- g_set_error (error,
- UDISKS_ERROR,
- UDISKS_ERROR_WOULD_WAKEUP,
- "Disk is in sleep mode and the nowakeup option was passed");
- goto out;
- }
-
- if (sk_disk_smart_read_data (d) != 0)
- {
- g_set_error (error,
- UDISKS_ERROR,
- UDISKS_ERROR_FAILED,
- "sk_disk_smart_read_data: %m");
- goto out;
- }
-
- if (sk_disk_smart_status (d, &good) != 0)
- {
- g_set_error (error,
- UDISKS_ERROR,
- UDISKS_ERROR_FAILED,
- "sk_disk_smart_status: %m");
- goto out;
- }
-
- /* don't care if these are failing or not */
- temp_mkelvin = 0;
- sk_disk_smart_get_temperature (d, &temp_mkelvin);
- power_on_msec = 0;
- sk_disk_smart_get_power_on (d, &power_on_msec);
-
- G_LOCK (drive_lock);
- drive->ata_smart_updated = time (NULL);
- drive->ata_smart_failing = !good;
- drive->ata_smart_temperature = temp_mkelvin / 1000.0;
- drive->ata_smart_power_on_seconds = power_on_msec / 1000.0;
- G_UNLOCK (drive_lock);
-
- drive_ata_smart_update (drive);
-
- ret = TRUE;
-
- out:
- if (d != NULL)
- sk_disk_free (d);
- return ret;
-}
-
static gboolean
-on_smart_update (UDisksDriveAta *drive_ata_iface,
- GDBusMethodInvocation *invocation,
- GVariant *options,
- gpointer user_data)
+handle_eject (UDisksDrive *_drive,
+ GDBusMethodInvocation *invocation,
+ GVariant *options)
{
- UDisksLinuxDrive *drive = UDISKS_LINUX_DRIVE (user_data);
- UDisksObject *block_object;
+ UDisksLinuxDrive *drive = UDISKS_LINUX_DRIVE (_drive);
+ UDisksLinuxDriveObject *object;
+ UDisksLinuxBlock *block_object;
UDisksBlockDevice *block;
UDisksDaemon *daemon;
const gchar *action_id;
- gboolean nowakeup;
- GError *error;
+ gchar *error_message;
daemon = NULL;
block = NULL;
+ error_message = NULL;
- daemon = udisks_linux_drive_get_daemon (drive);
- block_object = find_block_object (drive);
+ object = UDISKS_LINUX_DRIVE_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (drive)));
+ daemon = udisks_linux_drive_object_get_daemon (object);
+ block_object = udisks_linux_drive_object_get_block (object, TRUE);
if (block_object == NULL)
{
g_dbus_method_invocation_return_error (invocation,
@@ -1062,12 +495,7 @@ on_smart_update (UDisksDriveAta *drive_ata_iface,
"Unable to find physical block device for drive");
goto out;
}
- block = udisks_object_peek_block_device (block_object);
-
- g_variant_lookup (options,
- "nowakeup",
- "b",
- &nowakeup);
+ block = udisks_object_peek_block_device (UDISKS_OBJECT (block_object));
/* TODO: is it a good idea to overload modify-device? */
action_id = "org.freedesktop.udisks2.modify-device";
@@ -1076,396 +504,45 @@ on_smart_update (UDisksDriveAta *drive_ata_iface,
/* Check that the user is actually authorized */
if (!udisks_daemon_util_check_authorization_sync (daemon,
- block_object,
+ UDISKS_OBJECT (block_object),
action_id,
options,
- N_("Authentication is required to update SMART from $(udisks2.device)"),
+ N_("Authentication is required to eject $(udisks2.device)"),
invocation))
goto out;
- if (!udisks_drive_ata_get_smart_supported (drive_ata_iface))
- {
- g_dbus_method_invocation_return_error (invocation,
- UDISKS_ERROR,
- UDISKS_ERROR_FAILED,
- "SMART is not supported");
- goto out;
- }
-
- if (!udisks_drive_ata_get_smart_enabled (drive_ata_iface))
+ if (!udisks_daemon_launch_spawned_job_sync (daemon,
+ NULL, /* GCancellable */
+ 0, /* uid_t run_as_uid */
+ 0, /* uid_t run_as_euid */
+ NULL, /* gint *out_status */
+ &error_message,
+ NULL, /* input_string */
+ "eject \"%s\"",
+ udisks_block_device_get_device (block)))
{
g_dbus_method_invocation_return_error (invocation,
UDISKS_ERROR,
UDISKS_ERROR_FAILED,
- "SMART is not enabled");
- goto out;
- }
-
- error = NULL;
- if (!update_smart (drive, nowakeup, &error))
- {
- udisks_warning ("Error updating ATA smart for %s: %s (%s, %d)",
- g_dbus_object_get_object_path (G_DBUS_OBJECT (drive)),
- error->message, g_quark_to_string (error->domain), error->code);
- g_dbus_method_invocation_take_error (invocation, error);
+ "Error eject %s: %s",
+ udisks_block_device_get_device (block),
+ error_message);
goto out;
}
- udisks_drive_ata_complete_smart_update (drive_ata_iface, invocation);
+ udisks_drive_complete_eject (UDISKS_DRIVE (drive), invocation);
out:
if (block_object != NULL)
g_object_unref (block_object);
+ g_free (error_message);
return TRUE; /* returning TRUE means that we handled the method invocation */
}
-static gboolean
-drive_ata_check (UDisksLinuxDrive *drive)
-{
- gboolean ret;
- GUdevDevice *device;
-
- ret = FALSE;
- if (drive->devices == NULL)
- goto out;
-
- device = G_UDEV_DEVICE (drive->devices->data);
- if (!g_udev_device_get_property_as_boolean (device, "ID_ATA"))
- goto out;
-
- ret = TRUE;
-
- out:
- return ret;
-}
-
-static void
-drive_ata_connect (UDisksLinuxDrive *drive)
-{
- g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (drive->iface_drive_ata),
- G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
- g_signal_connect (drive->iface_drive_ata,
- "handle-smart-update",
- G_CALLBACK (on_smart_update),
- drive);
-}
-
-/* also called from *any* thread when the SMART data has been updated */
-static void
-drive_ata_smart_update (UDisksLinuxDrive *drive)
-{
- GUdevDevice *device;
- gboolean supported;
- gboolean enabled;
- guint64 updated;
- gboolean failing;
- gdouble temperature;
- guint64 power_on_seconds;
-
- device = G_UDEV_DEVICE (drive->devices->data);
-
- supported = g_udev_device_get_property_as_boolean (device, "ID_ATA_FEATURE_SET_SMART");
- enabled = g_udev_device_get_property_as_boolean (device, "ID_ATA_FEATURE_SET_SMART_ENABLED");
- updated = 0;
- failing = FALSE;
- temperature = 0.0;
- power_on_seconds = 0;
-
- G_LOCK (drive_lock);
- if (drive->ata_smart_updated > 0)
- {
- updated = drive->ata_smart_updated;
- failing = drive->ata_smart_failing;
- temperature = drive->ata_smart_temperature;
- power_on_seconds = drive->ata_smart_power_on_seconds;
- }
- G_UNLOCK (drive_lock);
-
- g_object_freeze_notify (G_OBJECT (drive->iface_drive_ata));
- udisks_drive_ata_set_smart_supported (drive->iface_drive_ata, supported);
- udisks_drive_ata_set_smart_enabled (drive->iface_drive_ata, enabled);
- udisks_drive_ata_set_smart_updated (drive->iface_drive_ata, updated);
- udisks_drive_ata_set_smart_failing (drive->iface_drive_ata, failing);
- udisks_drive_ata_set_smart_temperature (drive->iface_drive_ata, temperature);
- udisks_drive_ata_set_smart_power_on_seconds (drive->iface_drive_ata, power_on_seconds);
- g_object_thaw_notify (G_OBJECT (drive->iface_drive_ata));
-}
-
-static void
-drive_ata_update (UDisksLinuxDrive *drive,
- const gchar *uevent_action,
- GDBusInterface *_iface)
-{
- drive_ata_smart_update (drive);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static GList *
-find_link_for_sysfs_path (UDisksLinuxDrive *drive,
- const gchar *sysfs_path)
-{
- GList *l;
- GList *ret;
- ret = NULL;
- for (l = drive->devices; l != NULL; l = l->next)
- {
- GUdevDevice *device = G_UDEV_DEVICE (l->data);
- if (g_strcmp0 (g_udev_device_get_sysfs_path (device), sysfs_path) == 0)
- {
- ret = l;
- goto out;
- }
- }
- out:
- return ret;
-}
-
-/**
- * udisks_linux_drive_uevent:
- * @drive: A #UDisksLinuxDrive.
- * @action: Uevent action or %NULL
- * @device: A new #GUdevDevice device object or %NULL if the device hasn't changed.
- *
- * Updates all information on interfaces on @drive.
- */
-void
-udisks_linux_drive_uevent (UDisksLinuxDrive *drive,
- const gchar *action,
- GUdevDevice *device)
-{
- GList *link;
-
- g_return_if_fail (UDISKS_IS_LINUX_DRIVE (drive));
- g_return_if_fail (G_UDEV_IS_DEVICE (device));
-
- link = find_link_for_sysfs_path (drive, g_udev_device_get_sysfs_path (device));
- if (g_strcmp0 (action, "remove") == 0)
- {
- if (link != NULL)
- {
- g_object_unref (G_UDEV_DEVICE (link->data));
- drive->devices = g_list_delete_link (drive->devices, link);
- }
- else
- {
- udisks_warning ("Drive doesn't have device with sysfs path %s on remove event",
- g_udev_device_get_sysfs_path (device));
- }
- }
- else
- {
- if (link != NULL)
- {
- g_object_unref (G_UDEV_DEVICE (link->data));
- link->data = g_object_ref (device);
- }
- else
- {
- drive->devices = g_list_append (drive->devices, g_object_ref (device));
- }
- }
-
- update_iface (drive, action, drive_check, drive_connect, drive_update,
- UDISKS_TYPE_DRIVE_SKELETON, &drive->iface_drive);
- update_iface (drive, action, drive_ata_check, drive_ata_connect, drive_ata_update,
- UDISKS_TYPE_DRIVE_ATA_SKELETON, &drive->iface_drive_ata);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static gchar *
-check_for_vpd (GUdevDevice *device)
-{
- gchar *ret;
- const gchar *serial;
- const gchar *wwn;
-
- g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE);
-
- ret = NULL;
-
- /* prefer WWN to serial */
- serial = g_udev_device_get_property (device, "ID_SERIAL");
- wwn = g_udev_device_get_property (device, "ID_WWN_WITH_EXTENSION");
- if (wwn != NULL && strlen (wwn) > 0)
- {
- ret = g_strdup (wwn);
- }
- else if (serial != NULL && strlen (serial) > 0)
- {
- ret = g_strdup (serial);
- }
- return ret;
-}
-
-/* <internal>
- * udisks_linux_drive_should_include_device:
- * @client: A #GUdevClient.
- * @device: A #GUdevDevice.
- * @out_vpd: Return location for unique ID or %NULL.
- *
- * Checks if we should even construct a #UDisksLinuxDrive for @device.
- *
- * Returns: %TRUE if we should construct an object, %FALSE otherwise.
- */
-gboolean
-udisks_linux_drive_should_include_device (GUdevClient *client,
- GUdevDevice *device,
- gchar **out_vpd)
-{
- gboolean ret;
- gchar *vpd;
-
- ret = FALSE;
- vpd = NULL;
-
- /* The 'block' subsystem encompasses several objects with varying
- * DEVTYPE including
- *
- * - disk
- * - partition
- *
- * and we are only interested in the first.
- */
- if (g_strcmp0 (g_udev_device_get_devtype (device), "disk") != 0)
- goto out;
-
- vpd = check_for_vpd (device);
-
- if (vpd == NULL)
- {
- const gchar *name;
- GUdevDevice *parent;
-
- name = g_udev_device_get_name (device);
-
- /* workaround for missing serial/wwn on virtio-blk */
- if (g_str_has_prefix (name, "vd"))
- {
- vpd = g_strdup (name);
- goto found;
- }
-
- /* workaround for missing serial/wwn on firewire devices */
- parent = g_udev_device_get_parent_with_subsystem (device, "firewire", NULL);
- if (parent != NULL)
- {
- vpd = g_strdup (name);
- g_object_unref (parent);
- goto found;
- }
-
- /* dm-multipath */
- const gchar *dm_name;
- dm_name = g_udev_device_get_sysfs_attr (device, "dm/name");
- if (dm_name != NULL && g_str_has_prefix (dm_name, "mpath"))
- {
- gchar **slaves;
- guint n;
- slaves = udisks_daemon_util_resolve_links (g_udev_device_get_sysfs_path (device), "slaves");
- for (n = 0; slaves[n] != NULL; n++)
- {
- GUdevDevice *slave;
- slave = g_udev_client_query_by_sysfs_path (client, slaves[n]);
- if (slave != NULL)
- {
- vpd = check_for_vpd (slave);
- if (vpd != NULL)
- {
- g_object_unref (slave);
- g_strfreev (slaves);
- goto found;
- }
- g_object_unref (slave);
- }
- }
- g_strfreev (slaves);
- }
- }
-
- found:
- if (vpd != NULL)
- {
- if (out_vpd != NULL)
- {
- *out_vpd = vpd;
- vpd = NULL;
- }
- ret = TRUE;
- }
-
- out:
- g_free (vpd);
- return ret;
-}
-
/* ---------------------------------------------------------------------------------------------------- */
-/**
- * udisks_linux_drive_housekeeping:
- * @drive: A #UDisksLinuxDrive.
- * @secs_since_last: Number of seconds sincex the last housekeeping or 0 if the first housekeeping ever.
- * @cancellable: A %GCancellable or %NULL.
- * @error: Return location for error or %NULL.
- *
- * Called periodically (every ten minutes or so) to perform
- * housekeeping tasks such as refreshing ATA SMART data.
- *
- * The function runs in a dedicated thread and is allowed to perform
- * blocking I/O.
- *
- * Long-running tasks should periodically check @cancellable to see if
- * they have been cancelled.
- *
- * Returns: %TRUE if the operation succeeded, %FALSE if @error is set.
- */
-gboolean
-udisks_linux_drive_housekeeping (UDisksLinuxDrive *drive,
- guint secs_since_last,
- GCancellable *cancellable,
- GError **error)
+static void
+drive_iface_init (UDisksDriveIface *iface)
{
- gboolean ret;
-
- ret = FALSE;
-
- if (drive->iface_drive_ata != NULL &&
- udisks_drive_ata_get_smart_supported (drive->iface_drive_ata) &&
- udisks_drive_ata_get_smart_enabled (drive->iface_drive_ata))
- {
- GError *local_error;
- gboolean nowakeup;
-
- /* Wake-up only on start-up */
- nowakeup = TRUE;
- if (secs_since_last == 0)
- nowakeup = FALSE;
-
- udisks_info ("Refreshing SMART data on %s (nowakeup=%d)",
- g_dbus_object_get_object_path (G_DBUS_OBJECT (drive)),
- nowakeup);
-
- local_error = NULL;
- if (!update_smart (drive, nowakeup, &local_error))
- {
- if (nowakeup && (local_error->domain == UDISKS_ERROR &&
- local_error->code == UDISKS_ERROR_WOULD_WAKEUP))
- {
- udisks_info ("Drive %s is in a sleep state",
- g_dbus_object_get_object_path (G_DBUS_OBJECT (drive)));
- g_error_free (local_error);
- }
- else
- {
- g_propagate_prefixed_error (error, local_error, "Error updating SMART data: ");
- goto out;
- }
- }
- }
-
- ret = TRUE;
-
- out:
- return ret;
+ iface->handle_eject = handle_eject;
}
diff --git a/src/udiskslinuxdrive.h b/src/udiskslinuxdrive.h
index e287ebb..084a68d 100644
--- a/src/udiskslinuxdrive.h
+++ b/src/udiskslinuxdrive.h
@@ -22,7 +22,6 @@
#define __UDISKS_LINUX_DRIVE_H__
#include "udisksdaemontypes.h"
-#include <gudev/gudev.h>
G_BEGIN_DECLS
@@ -30,23 +29,10 @@ G_BEGIN_DECLS
#define UDISKS_LINUX_DRIVE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UDISKS_TYPE_LINUX_DRIVE, UDisksLinuxDrive))
#define UDISKS_IS_LINUX_DRIVE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UDISKS_TYPE_LINUX_DRIVE))
-GType udisks_linux_drive_get_type (void) G_GNUC_CONST;
-UDisksLinuxDrive *udisks_linux_drive_new (UDisksDaemon *daemon,
- GUdevDevice *device);
-void udisks_linux_drive_uevent (UDisksLinuxDrive *drive,
- const gchar *action,
- GUdevDevice *device);
-UDisksDaemon *udisks_linux_drive_get_daemon (UDisksLinuxDrive *drive);
-GList *udisks_linux_drive_get_devices (UDisksLinuxDrive *drive);
-
-gboolean udisks_linux_drive_housekeeping (UDisksLinuxDrive *drive,
- guint secs_since_last,
- GCancellable *cancellable,
- GError **error);
-
-gboolean udisks_linux_drive_should_include_device (GUdevClient *client,
- GUdevDevice *device,
- gchar **out_vpd);
+GType udisks_linux_drive_get_type (void) G_GNUC_CONST;
+UDisksDrive *udisks_linux_drive_new (void);
+void udisks_linux_drive_update (UDisksLinuxDrive *drive,
+ UDisksLinuxDriveObject *object);
G_END_DECLS
diff --git a/src/udiskslinuxdriveata.c b/src/udiskslinuxdriveata.c
new file mode 100644
index 0000000..00104f3
--- /dev/null
+++ b/src/udiskslinuxdriveata.c
@@ -0,0 +1,387 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2007-2010 David Zeuthen <zeuthen@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <mntent.h>
+
+#include <glib/gstdio.h>
+
+#include <atasmart.h>
+
+#include "udiskslogging.h"
+#include "udiskslinuxprovider.h"
+#include "udiskslinuxdriveobject.h"
+#include "udiskslinuxdriveata.h"
+#include "udiskslinuxblock.h"
+#include "udisksdaemon.h"
+#include "udiskscleanup.h"
+#include "udisksdaemonutil.h"
+
+/**
+ * SECTION:udiskslinuxdriveata
+ * @title: UDisksLinuxDriveAta
+ * @short_description: Linux implementation of #UDisksDriveAta
+ *
+ * This type provides an implementation of the #UDisksDriveAta
+ * interface on Linux.
+ */
+
+typedef struct _UDisksLinuxDriveAtaClass UDisksLinuxDriveAtaClass;
+
+/**
+ * UDisksLinuxDriveAta:
+ *
+ * The #UDisksLinuxDriveAta structure contains only private data and should
+ * only be accessed using the provided API.
+ */
+struct _UDisksLinuxDriveAta
+{
+ UDisksDriveAtaSkeleton parent_instance;
+
+ guint64 smart_updated;
+ gboolean smart_failing;
+ gdouble smart_temperature;
+ guint64 smart_power_on_seconds;
+};
+
+struct _UDisksLinuxDriveAtaClass
+{
+ UDisksDriveAtaSkeletonClass parent_class;
+};
+
+static void drive_ata_iface_init (UDisksDriveAtaIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (UDisksLinuxDriveAta, udisks_linux_drive_ata, UDISKS_TYPE_DRIVE_ATA_SKELETON,
+ G_IMPLEMENT_INTERFACE (UDISKS_TYPE_DRIVE_ATA, drive_ata_iface_init));
+
+G_LOCK_DEFINE_STATIC (object_lock);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+udisks_linux_drive_ata_init (UDisksLinuxDriveAta *drive_ata)
+{
+ g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (drive_ata),
+ G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
+}
+
+static void
+udisks_linux_drive_ata_class_init (UDisksLinuxDriveAtaClass *klass)
+{
+}
+
+/**
+ * udisks_linux_drive_ata_new:
+ *
+ * Creates a new #UDisksLinuxDriveAta instance.
+ *
+ * Returns: A new #UDisksLinuxDriveAta. Free with g_object_unref().
+ */
+UDisksDriveAta *
+udisks_linux_drive_ata_new (void)
+{
+ return UDISKS_DRIVE_ATA (g_object_new (UDISKS_TYPE_LINUX_DRIVE_ATA,
+ NULL));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* may be called from *any* thread when the SMART data has been updated */
+static void
+update_smart (UDisksLinuxDriveAta *drive,
+ GUdevDevice *device)
+{
+ gboolean supported;
+ gboolean enabled;
+ guint64 updated;
+ gboolean failing;
+ gdouble temperature;
+ guint64 power_on_seconds;
+
+ supported = g_udev_device_get_property_as_boolean (device, "ID_ATA_FEATURE_SET_SMART");
+ enabled = g_udev_device_get_property_as_boolean (device, "ID_ATA_FEATURE_SET_SMART_ENABLED");
+ updated = 0;
+ failing = FALSE;
+ temperature = 0.0;
+ power_on_seconds = 0;
+
+ G_LOCK (object_lock);
+ if (drive->smart_updated > 0)
+ {
+ updated = drive->smart_updated;
+ failing = drive->smart_failing;
+ temperature = drive->smart_temperature;
+ power_on_seconds = drive->smart_power_on_seconds;
+ }
+ G_UNLOCK (object_lock);
+
+ g_object_freeze_notify (G_OBJECT (drive));
+ udisks_drive_ata_set_smart_supported (UDISKS_DRIVE_ATA (drive), supported);
+ udisks_drive_ata_set_smart_enabled (UDISKS_DRIVE_ATA (drive), enabled);
+ udisks_drive_ata_set_smart_updated (UDISKS_DRIVE_ATA (drive), updated);
+ udisks_drive_ata_set_smart_failing (UDISKS_DRIVE_ATA (drive), failing);
+ udisks_drive_ata_set_smart_temperature (UDISKS_DRIVE_ATA (drive), temperature);
+ udisks_drive_ata_set_smart_power_on_seconds (UDISKS_DRIVE_ATA (drive), power_on_seconds);
+ g_object_thaw_notify (G_OBJECT (drive));
+}
+
+/**
+ * udisks_linux_drive_ata_update:
+ * @drive: A #UDisksLinuxDriveAta.
+ * @object: The enclosing #UDisksLinuxDriveObject instance.
+ *
+ * Updates the interface.
+ */
+void
+udisks_linux_drive_ata_update (UDisksLinuxDriveAta *drive,
+ UDisksLinuxDriveObject *object)
+{
+ GUdevDevice *device;
+ device = udisks_linux_drive_object_get_device (object, TRUE /* get_hw */);
+ if (device == NULL)
+ goto out;
+ update_smart (drive, device);
+ out:
+ if (device != NULL)
+ g_object_unref (device);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * udisks_linux_drive_ata_refresh_smart_sync:
+ * @drive: The #UDisksLinuxDriveAta to refresh.
+ * @nowakeup: If %TRUE, will not wake up the disk if asleep.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error.
+ *
+ * Synchronously refreshes ATA S.M.A.R.T. data on @drive using one of
+ * the physical drives associated with it. The calling thread is
+ * blocked until the data has been obtained.
+ *
+ * If @nowake is %TRUE and the disk is in a sleep state this fails
+ * with %UDISKS_ERROR_WOULD_WAKEUP.
+ *
+ * This may only be called if @drive has been associated with a
+ * #UDisksLinuxDriveObject instance.
+ *
+ * This method may be called from any thread.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if @error is set.
+ */
+gboolean
+udisks_linux_drive_ata_refresh_smart_sync (UDisksLinuxDriveAta *drive,
+ gboolean nowakeup,
+ GCancellable *cancellable,
+ GError **error)
+{
+ UDisksLinuxDriveObject *object;
+ GUdevDevice *device;
+ gboolean ret;
+ SkDisk *d;
+ SkBool awake;
+ SkBool good;
+ uint64_t temp_mkelvin;
+ uint64_t power_on_msec;
+
+ object = UDISKS_LINUX_DRIVE_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (drive)));
+ device = udisks_linux_drive_object_get_device (object, TRUE /* get_hw */);
+ g_assert (device != NULL);
+
+ /* TODO: use cancellable */
+
+ d = NULL;
+ ret = FALSE;
+
+ if (sk_disk_open (g_udev_device_get_device_file (device), &d) != 0)
+ {
+ g_set_error (error,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "sk_disk_open: %m");
+ goto out;
+ }
+
+ if (sk_disk_check_sleep_mode (d, &awake) != 0)
+ {
+ g_set_error (error,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "sk_disk_check_sleep_mode: %m");
+ goto out;
+ }
+
+ /* don't wake up disk unless specically asked to */
+ if (nowakeup && !awake)
+ {
+ g_set_error (error,
+ UDISKS_ERROR,
+ UDISKS_ERROR_WOULD_WAKEUP,
+ "Disk is in sleep mode and the nowakeup option was passed");
+ goto out;
+ }
+
+ if (sk_disk_smart_read_data (d) != 0)
+ {
+ g_set_error (error,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "sk_disk_smart_read_data: %m");
+ goto out;
+ }
+
+ if (sk_disk_smart_status (d, &good) != 0)
+ {
+ g_set_error (error,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "sk_disk_smart_status: %m");
+ goto out;
+ }
+
+ /* don't care if these are failing or not */
+ temp_mkelvin = 0;
+ sk_disk_smart_get_temperature (d, &temp_mkelvin);
+ power_on_msec = 0;
+ sk_disk_smart_get_power_on (d, &power_on_msec);
+
+ G_LOCK (object_lock);
+ drive->smart_updated = time (NULL);
+ drive->smart_failing = !good;
+ drive->smart_temperature = temp_mkelvin / 1000.0;
+ drive->smart_power_on_seconds = power_on_msec / 1000.0;
+ G_UNLOCK (object_lock);
+
+ update_smart (drive, device);
+
+ ret = TRUE;
+
+ out:
+ g_object_unref (device);
+ if (d != NULL)
+ sk_disk_free (d);
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+handle_smart_update (UDisksDriveAta *_drive,
+ GDBusMethodInvocation *invocation,
+ GVariant *options)
+{
+ UDisksLinuxDriveAta *drive = UDISKS_LINUX_DRIVE_ATA (_drive);
+ UDisksLinuxDriveObject *object;
+ UDisksLinuxBlock *block_object;
+ UDisksBlockDevice *block;
+ UDisksDaemon *daemon;
+ const gchar *action_id;
+ gboolean nowakeup;
+ GError *error;
+
+ daemon = NULL;
+ block = NULL;
+
+ object = UDISKS_LINUX_DRIVE_OBJECT (g_dbus_interface_get_object (G_DBUS_INTERFACE (drive)));
+ daemon = udisks_linux_drive_object_get_daemon (object);
+ block_object = udisks_linux_drive_object_get_block (object, TRUE);
+ if (block_object == NULL)
+ {
+ g_dbus_method_invocation_return_error (invocation,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "Unable to find physical block device for drive");
+ goto out;
+ }
+ block = udisks_object_peek_block_device (UDISKS_OBJECT (block_object));
+
+ g_variant_lookup (options,
+ "nowakeup",
+ "b",
+ &nowakeup);
+
+ /* TODO: is it a good idea to overload modify-device? */
+ action_id = "org.freedesktop.udisks2.modify-device";
+ if (udisks_block_device_get_hint_system (block))
+ action_id = "org.freedesktop.udisks2.modify-device-system";
+
+ /* Check that the user is actually authorized */
+ if (!udisks_daemon_util_check_authorization_sync (daemon,
+ UDISKS_OBJECT (block_object),
+ action_id,
+ options,
+ N_("Authentication is required to update S.M.A.R.T. data from $(udisks2.device)"),
+ invocation))
+ goto out;
+
+ if (!udisks_drive_ata_get_smart_supported (UDISKS_DRIVE_ATA (drive)))
+ {
+ g_dbus_method_invocation_return_error (invocation,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "SMART is not supported");
+ goto out;
+ }
+
+ if (!udisks_drive_ata_get_smart_enabled (UDISKS_DRIVE_ATA (drive)))
+ {
+ g_dbus_method_invocation_return_error (invocation,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "SMART is not enabled");
+ goto out;
+ }
+
+ error = NULL;
+ if (!udisks_linux_drive_ata_refresh_smart_sync (drive,
+ nowakeup,
+ NULL /* cancellable */,
+ &error))
+ {
+ udisks_warning ("Error updating ATA smart for %s: %s (%s, %d)",
+ g_dbus_object_get_object_path (G_DBUS_OBJECT (drive)),
+ error->message, g_quark_to_string (error->domain), error->code);
+ g_dbus_method_invocation_take_error (invocation, error);
+ goto out;
+ }
+
+ udisks_drive_ata_complete_smart_update (UDISKS_DRIVE_ATA (drive), invocation);
+
+ out:
+ if (block_object != NULL)
+ g_object_unref (block_object);
+ return TRUE; /* returning TRUE means that we handled the method invocation */
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+drive_ata_iface_init (UDisksDriveAtaIface *iface)
+{
+ iface->handle_smart_update = handle_smart_update;
+}
diff --git a/src/udiskslinuxdriveata.h b/src/udiskslinuxdriveata.h
new file mode 100644
index 0000000..31d5676
--- /dev/null
+++ b/src/udiskslinuxdriveata.h
@@ -0,0 +1,43 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2007-2010 David Zeuthen <zeuthen@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __UDISKS_LINUX_DRIVE_ATA_H__
+#define __UDISKS_LINUX_DRIVE_ATA_H__
+
+#include "udisksdaemontypes.h"
+
+G_BEGIN_DECLS
+
+#define UDISKS_TYPE_LINUX_DRIVE_ATA (udisks_linux_drive_ata_get_type ())
+#define UDISKS_LINUX_DRIVE_ATA(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UDISKS_TYPE_LINUX_DRIVE_ATA, UDisksLinuxDriveAta))
+#define UDISKS_IS_LINUX_DRIVE_ATA(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UDISKS_TYPE_LINUX_DRIVE_ATA))
+
+GType udisks_linux_drive_ata_get_type (void) G_GNUC_CONST;
+UDisksDriveAta *udisks_linux_drive_ata_new (void);
+void udisks_linux_drive_ata_update (UDisksLinuxDriveAta *drive,
+ UDisksLinuxDriveObject *object);
+gboolean udisks_linux_drive_ata_refresh_smart_sync (UDisksLinuxDriveAta *drive,
+ gboolean nowakeup,
+ GCancellable *cancellable,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __UDISKS_LINUX_DRIVE_ATA_H__ */
diff --git a/src/udiskslinuxdriveobject.c b/src/udiskslinuxdriveobject.c
new file mode 100644
index 0000000..0956419
--- /dev/null
+++ b/src/udiskslinuxdriveobject.c
@@ -0,0 +1,860 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2007-2010 David Zeuthen <zeuthen@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "udiskslogging.h"
+#include "udisksdaemon.h"
+#include "udisksdaemonutil.h"
+#include "udiskslinuxprovider.h"
+#include "udiskslinuxdriveobject.h"
+#include "udiskslinuxdrive.h"
+#include "udiskslinuxdriveata.h"
+#include "udiskslinuxblock.h"
+
+/**
+ * SECTION:udiskslinuxdriveobject
+ * @title: UDisksLinuxDriveObject
+ * @short_description: Object representing a drive on Linux
+ *
+ * Object corresponding to a drive on Linux.
+ */
+
+typedef struct _UDisksLinuxDriveObjectClass UDisksLinuxDriveObjectClass;
+
+/**
+ * UDisksLinuxDriveObject:
+ *
+ * The #UDisksLinuxDriveObject structure contains only private data and
+ * should only be accessed using the provided API.
+ */
+struct _UDisksLinuxDriveObject
+{
+ UDisksObjectSkeleton parent_instance;
+
+ UDisksDaemon *daemon;
+
+ /* list of GUdevDevice objects for block objects */
+ GList *devices;
+
+ /* interfaces */
+ UDisksDrive *iface_drive;
+ UDisksDriveAta *iface_drive_ata;
+};
+
+// G_LOCK_DEFINE_STATIC (drive_object_lock);
+
+struct _UDisksLinuxDriveObjectClass
+{
+ UDisksObjectSkeletonClass parent_class;
+};
+
+enum
+{
+ PROP_0,
+ PROP_DAEMON,
+ PROP_DEVICE
+};
+
+G_DEFINE_TYPE (UDisksLinuxDriveObject, udisks_linux_drive_object, UDISKS_TYPE_OBJECT_SKELETON);
+
+static void
+udisks_linux_drive_object_finalize (GObject *_object)
+{
+ UDisksLinuxDriveObject *object = UDISKS_LINUX_DRIVE_OBJECT (_object);
+
+ /* note: we don't hold a ref to drive_object->daemon or drive_object->mount_monitor */
+ g_list_foreach (object->devices, (GFunc) g_object_unref, NULL);
+ g_list_free (object->devices);
+
+ if (object->iface_drive != NULL)
+ g_object_unref (object->iface_drive);
+ if (object->iface_drive_ata != NULL)
+ g_object_unref (object->iface_drive_ata);
+
+ if (G_OBJECT_CLASS (udisks_linux_drive_object_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (udisks_linux_drive_object_parent_class)->finalize (_object);
+}
+
+static void
+udisks_linux_drive_object_get_property (GObject *_object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ UDisksLinuxDriveObject *object = UDISKS_LINUX_DRIVE_OBJECT (_object);
+
+ switch (prop_id)
+ {
+ case PROP_DAEMON:
+ g_value_set_object (value, udisks_linux_drive_object_get_daemon (object));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (_object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+udisks_linux_drive_object_set_property (GObject *_object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ UDisksLinuxDriveObject *object = UDISKS_LINUX_DRIVE_OBJECT (_object);
+
+ switch (prop_id)
+ {
+ case PROP_DAEMON:
+ g_assert (object->daemon == NULL);
+ /* we don't take a reference to the daemon */
+ object->daemon = g_value_get_object (value);
+ break;
+
+ case PROP_DEVICE:
+ g_assert (object->devices == NULL);
+ object->devices = g_list_prepend (NULL, g_value_dup_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (_object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+udisks_linux_drive_object_init (UDisksLinuxDriveObject *object)
+{
+}
+
+static GObjectConstructParam *
+find_construct_property (guint n_construct_properties,
+ GObjectConstructParam *construct_properties,
+ const gchar *name)
+{
+ guint n;
+ for (n = 0; n < n_construct_properties; n++)
+ if (g_strcmp0 (g_param_spec_get_name (construct_properties[n].pspec), name) == 0)
+ return &construct_properties[n];
+ return NULL;
+}
+
+/* unless given, compute object path from sysfs path */
+static GObject *
+udisks_linux_drive_object_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObjectConstructParam *cp;
+ UDisksDaemon *daemon;
+ GUdevClient *client;
+ GUdevDevice *device;
+
+ cp = find_construct_property (n_construct_properties, construct_properties, "daemon");
+ g_assert (cp != NULL);
+ daemon = UDISKS_DAEMON (g_value_get_object (cp->value));
+ g_assert (daemon != NULL);
+
+ client = udisks_linux_provider_get_udev_client (udisks_daemon_get_linux_provider (daemon));
+
+ cp = find_construct_property (n_construct_properties, construct_properties, "device");
+ g_assert (cp != NULL);
+ device = G_UDEV_DEVICE (g_value_get_object (cp->value));
+ g_assert (device != NULL);
+
+ if (!udisks_linux_drive_object_should_include_device (client, device, NULL))
+ {
+ return NULL;
+ }
+ else
+ {
+ return G_OBJECT_CLASS (udisks_linux_drive_object_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties);
+ }
+}
+
+static void
+strip_and_replace_with_uscore (gchar *s)
+{
+ guint n;
+
+ if (s == NULL)
+ goto out;
+
+ g_strstrip (s);
+
+ for (n = 0; s != NULL && s[n] != '\0'; n++)
+ {
+ if (s[n] == ' ' || s[n] == '-')
+ s[n] = '_';
+ }
+
+ out:
+ ;
+}
+
+static void
+udisks_linux_drive_object_constructed (GObject *_object)
+{
+ UDisksLinuxDriveObject *object = UDISKS_LINUX_DRIVE_OBJECT (_object);
+ gchar *vendor;
+ gchar *model;
+ gchar *serial;
+ GString *str;
+
+ /* initial coldplug */
+ udisks_linux_drive_object_uevent (object, "add", object->devices->data);
+
+ /* compute the object path */
+ vendor = g_strdup (udisks_drive_get_vendor (object->iface_drive));
+ model = g_strdup (udisks_drive_get_model (object->iface_drive));
+ serial = g_strdup (udisks_drive_get_serial (object->iface_drive));
+ strip_and_replace_with_uscore (vendor);
+ strip_and_replace_with_uscore (model);
+ strip_and_replace_with_uscore (serial);
+ str = g_string_new ("/org/freedesktop/UDisks2/drives/");
+ if (vendor == NULL && model == NULL && serial == NULL)
+ {
+ g_string_append (str, "drive");
+ }
+ else
+ {
+ /* <VENDOR>_<MODEL>_<SERIAL> */
+ if (vendor != NULL && strlen (vendor) > 0)
+ {
+ udisks_safe_append_to_object_path (str, vendor);
+ }
+ if (model != NULL && strlen (model) > 0)
+ {
+ if (str->str[str->len - 1] != '/')
+ g_string_append_c (str, '_');
+ udisks_safe_append_to_object_path (str, model);
+ }
+ if (serial != NULL && strlen (serial) > 0)
+ {
+ if (str->str[str->len - 1] != '/')
+ g_string_append_c (str, '_');
+ udisks_safe_append_to_object_path (str, serial);
+ }
+ }
+ g_free (vendor);
+ g_free (model);
+ g_free (serial);
+ g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object), str->str);
+ g_string_free (str, TRUE);
+
+ if (G_OBJECT_CLASS (udisks_linux_drive_object_parent_class)->constructed != NULL)
+ G_OBJECT_CLASS (udisks_linux_drive_object_parent_class)->constructed (_object);
+}
+
+static void
+udisks_linux_drive_object_class_init (UDisksLinuxDriveObjectClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->constructor = udisks_linux_drive_object_constructor;
+ gobject_class->finalize = udisks_linux_drive_object_finalize;
+ gobject_class->constructed = udisks_linux_drive_object_constructed;
+ gobject_class->set_property = udisks_linux_drive_object_set_property;
+ gobject_class->get_property = udisks_linux_drive_object_get_property;
+
+ /**
+ * UDisksLinuxDriveObject:daemon:
+ *
+ * The #UDisksDaemon the object is for.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_DAEMON,
+ g_param_spec_object ("daemon",
+ "Daemon",
+ "The daemon the object is for",
+ UDISKS_TYPE_DAEMON,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * UDisksLinuxDriveObject:device:
+ *
+ * The #GUdevDevice for the object. Connect to the #GObject::notify
+ * signal to get notified whenever this is updated.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_DEVICE,
+ g_param_spec_object ("device",
+ "Device",
+ "The device for the object",
+ G_UDEV_TYPE_DEVICE,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+}
+
+/**
+ * udisks_linux_drive_object_new:
+ * @daemon: A #UDisksDaemon.
+ * @device: The #GUdevDevice for the sysfs block device.
+ *
+ * Create a new drive object.
+ *
+ * Returns: A #UDisksLinuxDriveObject object or %NULL if @device does not represent a drive. Free with g_object_unref().
+ */
+UDisksLinuxDriveObject *
+udisks_linux_drive_object_new (UDisksDaemon *daemon,
+ GUdevDevice *device)
+{
+ GObject *object;
+
+ g_return_val_if_fail (UDISKS_IS_DAEMON (daemon), NULL);
+ g_return_val_if_fail (G_UDEV_IS_DEVICE (device), NULL);
+
+ object = g_object_new (UDISKS_TYPE_LINUX_DRIVE_OBJECT,
+ "daemon", daemon,
+ "device", device,
+ NULL);
+
+ if (object != NULL)
+ return UDISKS_LINUX_DRIVE_OBJECT (object);
+ else
+ return NULL;
+}
+
+/**
+ * udisks_linux_drive_object_get_daemon:
+ * @object: A #UDisksLinuxDriveObject.
+ *
+ * Gets the daemon used by @object.
+ *
+ * Returns: A #UDisksDaemon. Do not free, the object is owned by @object.
+ */
+UDisksDaemon *
+udisks_linux_drive_object_get_daemon (UDisksLinuxDriveObject *object)
+{
+ g_return_val_if_fail (UDISKS_IS_LINUX_DRIVE_OBJECT (object), NULL);
+ return object->daemon;
+}
+
+/**
+ * udisks_linux_drive_object_get_devices:
+ * @object: A #UDisksLinuxDriveObject.
+ *
+ * Gets the current #GUdevDevice objects associated with @object.
+ *
+ * Returns: A list of #GUdevDevice objects. Free each element with
+ * g_object_unref(), then free the list with g_list_free().
+ */
+GList *
+udisks_linux_drive_object_get_devices (UDisksLinuxDriveObject *object)
+{
+ GList *ret;
+ g_return_val_if_fail (UDISKS_IS_LINUX_DRIVE_OBJECT (object), NULL);
+ ret = g_list_copy (object->devices);
+ g_list_foreach (ret, (GFunc) g_object_ref, NULL);
+ return ret;
+}
+
+/**
+ * udisks_linux_drive_object_get_device:
+ * @object: A #UDisksLinuxDriveObject.
+ * @get_hw: If the drive is multipath, set to %TRUE to get a path device instead of the multipath device.
+ *
+ * Gets one of the #GUdevDevice object associated with @object.
+ *
+ * If @get_hw is %TRUE and @object represents a multipath device then
+ * one of the paths is returned rather than the multipath device. This
+ * is useful if you e.g. need to configure the physical hardware.
+ *
+ * Returns: A #GUdevDevice or %NULL. The returned object must be freed
+ * with g_object_unref().
+ */
+GUdevDevice *
+udisks_linux_drive_object_get_device (UDisksLinuxDriveObject *object,
+ gboolean get_hw)
+{
+ GUdevDevice *ret;
+ /* TODO: actually look at @get_hw */
+ ret = object->devices->data;
+ if (ret != NULL)
+ g_object_ref (ret);
+ return ret;
+}
+
+/**
+ * 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().
+ */
+UDisksLinuxBlock *
+udisks_linux_drive_object_get_block (UDisksLinuxDriveObject *object,
+ gboolean get_hw)
+{
+ GDBusObjectManagerServer *object_manager;
+ UDisksLinuxBlock *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);
+ UDisksBlockDevice *block;
+ GUdevDevice *device;
+ gboolean is_disk;
+
+ if (!UDISKS_IS_LINUX_BLOCK (iter_object))
+ continue;
+
+ device = udisks_linux_block_get_device (UDISKS_LINUX_BLOCK (iter_object));
+ is_disk = (g_strcmp0 (g_udev_device_get_devtype (device), "disk") == 0);
+ g_object_unref (device);
+
+ if (!is_disk)
+ continue;
+
+ block = udisks_object_peek_block_device (UDISKS_OBJECT (iter_object));
+ if (g_strcmp0 (udisks_block_device_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;
+
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef gboolean (*HasInterfaceFunc) (UDisksLinuxDriveObject *object);
+typedef void (*ConnectInterfaceFunc) (UDisksLinuxDriveObject *object);
+typedef void (*UpdateInterfaceFunc) (UDisksLinuxDriveObject *object,
+ const gchar *uevent_action,
+ GDBusInterface *interface);
+
+static void
+update_iface (UDisksLinuxDriveObject *object,
+ const gchar *uevent_action,
+ HasInterfaceFunc has_func,
+ ConnectInterfaceFunc connect_func,
+ UpdateInterfaceFunc update_func,
+ GType skeleton_type,
+ gpointer _interface_pointer)
+{
+ gboolean has;
+ gboolean add;
+ GDBusInterface **interface_pointer = _interface_pointer;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (has_func != NULL);
+ g_return_if_fail (update_func != NULL);
+ g_return_if_fail (g_type_is_a (skeleton_type, G_TYPE_OBJECT));
+ g_return_if_fail (g_type_is_a (skeleton_type, G_TYPE_DBUS_INTERFACE));
+ g_return_if_fail (interface_pointer != NULL);
+ g_return_if_fail (*interface_pointer == NULL || G_IS_DBUS_INTERFACE (*interface_pointer));
+
+ add = FALSE;
+ has = has_func (object);
+ if (*interface_pointer == NULL)
+ {
+ if (has)
+ {
+ *interface_pointer = g_object_new (skeleton_type, NULL);
+ if (connect_func != NULL)
+ connect_func (object);
+ add = TRUE;
+ }
+ }
+ else
+ {
+ if (!has)
+ {
+ g_dbus_object_skeleton_remove_interface (G_DBUS_OBJECT_SKELETON (object),
+ G_DBUS_INTERFACE_SKELETON (*interface_pointer));
+ g_object_unref (*interface_pointer);
+ *interface_pointer = NULL;
+ }
+ }
+
+ if (*interface_pointer != NULL)
+ {
+ update_func (object, uevent_action, G_DBUS_INTERFACE (*interface_pointer));
+ if (add)
+ g_dbus_object_skeleton_add_interface (G_DBUS_OBJECT_SKELETON (object),
+ G_DBUS_INTERFACE_SKELETON (*interface_pointer));
+ }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+drive_check (UDisksLinuxDriveObject *object)
+{
+ return TRUE;
+}
+
+static void
+drive_connect (UDisksLinuxDriveObject *object)
+{
+}
+
+static void
+drive_update (UDisksLinuxDriveObject *object,
+ const gchar *uevent_action,
+ GDBusInterface *_iface)
+{
+ udisks_linux_drive_update (UDISKS_LINUX_DRIVE (object->iface_drive), object);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+drive_ata_check (UDisksLinuxDriveObject *object)
+{
+ gboolean ret;
+ GUdevDevice *device;
+
+ ret = FALSE;
+ if (object->devices == NULL)
+ goto out;
+
+ device = G_UDEV_DEVICE (object->devices->data);
+ if (!g_udev_device_get_property_as_boolean (device, "ID_ATA"))
+ goto out;
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+static void
+drive_ata_connect (UDisksLinuxDriveObject *object)
+{
+
+}
+
+static void
+drive_ata_update (UDisksLinuxDriveObject *object,
+ const gchar *uevent_action,
+ GDBusInterface *_iface)
+{
+ udisks_linux_drive_ata_update (UDISKS_LINUX_DRIVE_ATA (object->iface_drive_ata), object);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static GList *
+find_link_for_sysfs_path (UDisksLinuxDriveObject *object,
+ const gchar *sysfs_path)
+{
+ GList *l;
+ GList *ret;
+ ret = NULL;
+ for (l = object->devices; l != NULL; l = l->next)
+ {
+ GUdevDevice *device = G_UDEV_DEVICE (l->data);
+ if (g_strcmp0 (g_udev_device_get_sysfs_path (device), sysfs_path) == 0)
+ {
+ ret = l;
+ goto out;
+ }
+ }
+ out:
+ return ret;
+}
+
+/**
+ * udisks_linux_drive_object_uevent:
+ * @object: A #UDisksLinuxDriveObject.
+ * @action: Uevent action or %NULL
+ * @device: A #GUdevDevice device object or %NULL if the device hasn't changed.
+ *
+ * Updates all information on interfaces on @drive.
+ */
+void
+udisks_linux_drive_object_uevent (UDisksLinuxDriveObject *object,
+ const gchar *action,
+ GUdevDevice *device)
+{
+ GList *link;
+
+ g_return_if_fail (UDISKS_IS_LINUX_DRIVE_OBJECT (object));
+ g_return_if_fail (device == NULL || G_UDEV_IS_DEVICE (device));
+
+ link = NULL;
+ if (device != NULL)
+ link = find_link_for_sysfs_path (object, g_udev_device_get_sysfs_path (device));
+ if (g_strcmp0 (action, "remove") == 0)
+ {
+ if (link != NULL)
+ {
+ g_object_unref (G_UDEV_DEVICE (link->data));
+ object->devices = g_list_delete_link (object->devices, link);
+ }
+ else
+ {
+ udisks_warning ("Drive doesn't have device with sysfs path %s on remove event",
+ g_udev_device_get_sysfs_path (device));
+ }
+ }
+ else
+ {
+ if (link != NULL)
+ {
+ g_object_unref (G_UDEV_DEVICE (link->data));
+ link->data = g_object_ref (device);
+ }
+ else
+ {
+ object->devices = g_list_append (object->devices, g_object_ref (device));
+ }
+ }
+
+ update_iface (object, action, drive_check, drive_connect, drive_update,
+ UDISKS_TYPE_LINUX_DRIVE, &object->iface_drive);
+ update_iface (object, action, drive_ata_check, drive_ata_connect, drive_ata_update,
+ UDISKS_TYPE_LINUX_DRIVE_ATA, &object->iface_drive_ata);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gchar *
+check_for_vpd (GUdevDevice *device)
+{
+ gchar *ret;
+ const gchar *serial;
+ const gchar *wwn;
+
+ g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE);
+
+ ret = NULL;
+
+ /* prefer WWN to serial */
+ serial = g_udev_device_get_property (device, "ID_SERIAL");
+ wwn = g_udev_device_get_property (device, "ID_WWN_WITH_EXTENSION");
+ if (wwn != NULL && strlen (wwn) > 0)
+ {
+ ret = g_strdup (wwn);
+ }
+ else if (serial != NULL && strlen (serial) > 0)
+ {
+ ret = g_strdup (serial);
+ }
+ return ret;
+}
+
+/* <internal>
+ * udisks_linux_drive_object_should_include_device:
+ * @client: A #GUdevClient.
+ * @device: A #GUdevDevice.
+ * @out_vpd: Return location for unique ID or %NULL.
+ *
+ * Checks if we should even construct a #UDisksLinuxDriveObject for @device.
+ *
+ * Returns: %TRUE if we should construct an object, %FALSE otherwise.
+ */
+gboolean
+udisks_linux_drive_object_should_include_device (GUdevClient *client,
+ GUdevDevice *device,
+ gchar **out_vpd)
+{
+ gboolean ret;
+ gchar *vpd;
+
+ ret = FALSE;
+ vpd = NULL;
+
+ /* The 'block' subsystem encompasses several objects with varying
+ * DEVTYPE including
+ *
+ * - disk
+ * - partition
+ *
+ * and we are only interested in the first.
+ */
+ if (g_strcmp0 (g_udev_device_get_devtype (device), "disk") != 0)
+ goto out;
+
+ vpd = check_for_vpd (device);
+
+ if (vpd == NULL)
+ {
+ const gchar *name;
+ GUdevDevice *parent;
+
+ name = g_udev_device_get_name (device);
+
+ /* workaround for missing serial/wwn on virtio-blk */
+ if (g_str_has_prefix (name, "vd"))
+ {
+ vpd = g_strdup (name);
+ goto found;
+ }
+
+ /* workaround for missing serial/wwn on firewire devices */
+ parent = g_udev_device_get_parent_with_subsystem (device, "firewire", NULL);
+ if (parent != NULL)
+ {
+ vpd = g_strdup (name);
+ g_object_unref (parent);
+ goto found;
+ }
+
+ /* dm-multipath */
+ const gchar *dm_name;
+ dm_name = g_udev_device_get_sysfs_attr (device, "dm/name");
+ if (dm_name != NULL && g_str_has_prefix (dm_name, "mpath"))
+ {
+ gchar **slaves;
+ guint n;
+ slaves = udisks_daemon_util_resolve_links (g_udev_device_get_sysfs_path (device), "slaves");
+ for (n = 0; slaves[n] != NULL; n++)
+ {
+ GUdevDevice *slave;
+ slave = g_udev_client_query_by_sysfs_path (client, slaves[n]);
+ if (slave != NULL)
+ {
+ vpd = check_for_vpd (slave);
+ if (vpd != NULL)
+ {
+ g_object_unref (slave);
+ g_strfreev (slaves);
+ goto found;
+ }
+ g_object_unref (slave);
+ }
+ }
+ g_strfreev (slaves);
+ }
+ }
+
+ found:
+ if (vpd != NULL)
+ {
+ if (out_vpd != NULL)
+ {
+ *out_vpd = vpd;
+ vpd = NULL;
+ }
+ ret = TRUE;
+ }
+
+ out:
+ g_free (vpd);
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * udisks_linux_drive_object_housekeeping:
+ * @object: A #UDisksLinuxDriveObject.
+ * @secs_since_last: Number of seconds sincex the last housekeeping or 0 if the first housekeeping ever.
+ * @cancellable: A %GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Called periodically (every ten minutes or so) to perform
+ * housekeeping tasks such as refreshing ATA SMART data.
+ *
+ * The function runs in a dedicated thread and is allowed to perform
+ * blocking I/O.
+ *
+ * Long-running tasks should periodically check @cancellable to see if
+ * they have been cancelled.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if @error is set.
+ */
+gboolean
+udisks_linux_drive_object_housekeeping (UDisksLinuxDriveObject *object,
+ guint secs_since_last,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret;
+
+ ret = FALSE;
+
+ if (object->iface_drive_ata != NULL &&
+ udisks_drive_ata_get_smart_supported (object->iface_drive_ata) &&
+ udisks_drive_ata_get_smart_enabled (object->iface_drive_ata))
+ {
+ GError *local_error;
+ gboolean nowakeup;
+
+ /* Wake-up only on start-up */
+ nowakeup = TRUE;
+ if (secs_since_last == 0)
+ nowakeup = FALSE;
+
+ udisks_info ("Refreshing SMART data on %s (nowakeup=%d)",
+ g_dbus_object_get_object_path (G_DBUS_OBJECT (object)),
+ nowakeup);
+
+ local_error = NULL;
+ if (!udisks_linux_drive_ata_refresh_smart_sync (UDISKS_LINUX_DRIVE_ATA (object->iface_drive_ata),
+ nowakeup,
+ cancellable,
+ &local_error))
+ {
+ if (nowakeup && (local_error->domain == UDISKS_ERROR &&
+ local_error->code == UDISKS_ERROR_WOULD_WAKEUP))
+ {
+ udisks_info ("Drive %s is in a sleep state",
+ g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
+ g_error_free (local_error);
+ }
+ else
+ {
+ g_propagate_prefixed_error (error, local_error, "Error updating SMART data: ");
+ goto out;
+ }
+ }
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
diff --git a/src/udiskslinuxdriveobject.h b/src/udiskslinuxdriveobject.h
new file mode 100644
index 0000000..289bffc
--- /dev/null
+++ b/src/udiskslinuxdriveobject.h
@@ -0,0 +1,57 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2007-2010 David Zeuthen <zeuthen@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __UDISKS_LINUX_DRIVE_OBJECT_H__
+#define __UDISKS_LINUX_DRIVE_OBJECT_H__
+
+#include "udisksdaemontypes.h"
+#include <gudev/gudev.h>
+
+G_BEGIN_DECLS
+
+#define UDISKS_TYPE_LINUX_DRIVE_OBJECT (udisks_linux_drive_object_get_type ())
+#define UDISKS_LINUX_DRIVE_OBJECT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UDISKS_TYPE_LINUX_DRIVE_OBJECT, UDisksLinuxDriveObject))
+#define UDISKS_IS_LINUX_DRIVE_OBJECT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UDISKS_TYPE_LINUX_DRIVE_OBJECT))
+
+GType udisks_linux_drive_object_get_type (void) G_GNUC_CONST;
+UDisksLinuxDriveObject *udisks_linux_drive_object_new (UDisksDaemon *daemon,
+ GUdevDevice *device);
+void udisks_linux_drive_object_uevent (UDisksLinuxDriveObject *object,
+ const gchar *action,
+ GUdevDevice *device);
+UDisksDaemon *udisks_linux_drive_object_get_daemon (UDisksLinuxDriveObject *object);
+GList *udisks_linux_drive_object_get_devices (UDisksLinuxDriveObject *object);
+GUdevDevice *udisks_linux_drive_object_get_device (UDisksLinuxDriveObject *object,
+ gboolean get_hw);
+UDisksLinuxBlock *udisks_linux_drive_object_get_block (UDisksLinuxDriveObject *object,
+ gboolean get_hw);
+
+gboolean udisks_linux_drive_object_housekeeping (UDisksLinuxDriveObject *object,
+ guint secs_since_last,
+ GCancellable *cancellable,
+ GError **error);
+
+gboolean udisks_linux_drive_object_should_include_device (GUdevClient *client,
+ GUdevDevice *device,
+ gchar **out_vpd);
+
+G_END_DECLS
+
+#endif /* __UDISKS_LINUX_DRIVE_OBJECT_H__ */
diff --git a/src/udiskslinuxprovider.c b/src/udiskslinuxprovider.c
index 39d599d..9a0fbca 100644
--- a/src/udiskslinuxprovider.c
+++ b/src/udiskslinuxprovider.c
@@ -28,7 +28,7 @@
#include "udisksprovider.h"
#include "udiskslinuxprovider.h"
#include "udiskslinuxblock.h"
-#include "udiskslinuxdrive.h"
+#include "udiskslinuxdriveobject.h"
#include "udiskslinuxmanager.h"
#include "udiskscleanup.h"
@@ -38,7 +38,7 @@
* @short_description: Provider of Linux-specific objects
*
* This object is used to add/remove Linux specific objects. Right now
- * it handles #UDisksLinuxBlock and #UDisksLinuxDrive objects.
+ * it handles #UDisksLinuxBlock and #UDisksLinuxDriveObject instances.
*/
typedef struct _UDisksLinuxProviderClass UDisksLinuxProviderClass;
@@ -60,7 +60,7 @@ struct _UDisksLinuxProvider
/* maps from sysfs path to UDisksLinuxBlock objects */
GHashTable *sysfs_to_block;
- /* maps from VPD (serial, wwn) and sysfs_path to UDisksLinuxDrive objects */
+ /* maps from VPD (serial, wwn) and sysfs_path to UDisksLinuxDriveObject instances */
GHashTable *vpd_to_drive;
GHashTable *sysfs_path_to_drive;
@@ -287,16 +287,16 @@ perform_initial_housekeeping_for_drive (GIOSchedulerJob *job,
GCancellable *cancellable,
gpointer user_data)
{
- UDisksLinuxDrive *drive = UDISKS_LINUX_DRIVE (user_data);
+ UDisksLinuxDriveObject *object = UDISKS_LINUX_DRIVE_OBJECT (user_data);
GError *error;
error = NULL;
- if (!udisks_linux_drive_housekeeping (drive, 0,
- NULL, /* TODO: cancellable */
- &error))
+ if (!udisks_linux_drive_object_housekeeping (object, 0,
+ NULL, /* TODO: cancellable */
+ &error))
{
udisks_warning ("Error performing initial housekeeping for drive %s: %s (%s, %d)",
- g_dbus_object_get_object_path (G_DBUS_OBJECT (drive)),
+ g_dbus_object_get_object_path (G_DBUS_OBJECT (object)),
error->message, g_quark_to_string (error->domain), error->code);
g_error_free (error);
}
@@ -309,7 +309,7 @@ handle_block_uevent_for_drive (UDisksLinuxProvider *provider,
const gchar *action,
GUdevDevice *device)
{
- UDisksLinuxDrive *drive;
+ UDisksLinuxDriveObject *object;
UDisksDaemon *daemon;
const gchar *sysfs_path;
gchar *vpd;
@@ -320,22 +320,22 @@ handle_block_uevent_for_drive (UDisksLinuxProvider *provider,
if (g_strcmp0 (action, "remove") == 0)
{
- drive = g_hash_table_lookup (provider->sysfs_path_to_drive, sysfs_path);
- if (drive != NULL)
+ object = g_hash_table_lookup (provider->sysfs_path_to_drive, sysfs_path);
+ if (object != NULL)
{
GList *devices;
- udisks_linux_drive_uevent (drive, action, device);
+ 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_get_devices (drive);
+ devices = udisks_linux_drive_object_get_devices (object);
if (devices == NULL)
{
const gchar *vpd;
- vpd = g_object_get_data (G_OBJECT (drive), "x-vpd");
+ 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 (drive)));
+ g_dbus_object_get_object_path (G_DBUS_OBJECT (object)));
g_warn_if_fail (g_hash_table_remove (provider->vpd_to_drive, vpd));
}
g_list_foreach (devices, (GFunc) g_object_unref, NULL);
@@ -344,7 +344,7 @@ handle_block_uevent_for_drive (UDisksLinuxProvider *provider,
}
else
{
- if (!udisks_linux_drive_should_include_device (provider->gudev_client, device, &vpd))
+ if (!udisks_linux_drive_object_should_include_device (provider->gudev_client, device, &vpd))
goto out;
if (vpd == NULL)
@@ -353,29 +353,29 @@ handle_block_uevent_for_drive (UDisksLinuxProvider *provider,
g_udev_device_get_sysfs_path (device));
goto out;
}
- drive = g_hash_table_lookup (provider->vpd_to_drive, vpd);
- if (drive != NULL)
+ 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), drive);
- udisks_linux_drive_uevent (drive, action, device);
+ g_hash_table_insert (provider->sysfs_path_to_drive, g_strdup (sysfs_path), object);
+ udisks_linux_drive_object_uevent (object, action, device);
}
else
{
- drive = udisks_linux_drive_new (daemon, device);
- if (drive != NULL)
+ object = udisks_linux_drive_object_new (daemon, device);
+ if (object != NULL)
{
- g_object_set_data_full (G_OBJECT (drive), "x-vpd", g_strdup (vpd), g_free);
+ 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 (drive));
- g_hash_table_insert (provider->vpd_to_drive, g_strdup (vpd), drive);
- g_hash_table_insert (provider->sysfs_path_to_drive, g_strdup (sysfs_path), drive);
+ 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 (drive),
+ g_object_ref (object),
(GDestroyNotify) g_object_unref,
G_PRIORITY_DEFAULT,
NULL);
@@ -434,7 +434,7 @@ handle_block_uevent (UDisksLinuxProvider *provider,
const gchar *action,
GUdevDevice *device)
{
- /* We use the sysfs block device for both Drive and BlockDevice
+ /* We use the sysfs block device for both UDisksLinuxDriveObject and BlockDevice
* objects. Ensure that drive are added before and removed after
* BlockDevice
*/
@@ -486,34 +486,34 @@ static void
housekeeping_all_drives (UDisksLinuxProvider *provider,
guint secs_since_last)
{
- GList *drives;
+ GList *objects;
GList *l;
G_LOCK (provider_lock);
- drives = g_hash_table_get_values (provider->vpd_to_drive);
- g_list_foreach (drives, (GFunc) g_object_ref, NULL);
+ objects = g_hash_table_get_values (provider->vpd_to_drive);
+ g_list_foreach (objects, (GFunc) g_object_ref, NULL);
G_UNLOCK (provider_lock);
- for (l = drives; l != NULL; l = l->next)
+ for (l = objects; l != NULL; l = l->next)
{
- UDisksLinuxDrive *drive = UDISKS_LINUX_DRIVE (l->data);
+ UDisksLinuxDriveObject *object = UDISKS_LINUX_DRIVE_OBJECT (l->data);
GError *error;
error = NULL;
- if (!udisks_linux_drive_housekeeping (drive,
- secs_since_last,
- NULL, /* TODO: cancellable */
- &error))
+ if (!udisks_linux_drive_object_housekeeping (object,
+ secs_since_last,
+ NULL, /* TODO: cancellable */
+ &error))
{
udisks_warning ("Error performing housekeeping for drive %s: %s (%s, %d)",
- g_dbus_object_get_object_path (G_DBUS_OBJECT (drive)),
+ g_dbus_object_get_object_path (G_DBUS_OBJECT (object)),
error->message, g_quark_to_string (error->domain), error->code);
g_error_free (error);
}
}
- g_list_foreach (drives, (GFunc) g_object_unref, NULL);
- g_list_free (drives);
+ g_list_foreach (objects, (GFunc) g_object_unref, NULL);
+ g_list_free (objects);
}
/* ---------------------------------------------------------------------------------------------------- */