PROP_DEVICE_SIZE,
PROP_DEVICE_BLOCK_SIZE,
PROP_DEVICE_IS_MOUNTED,
+ PROP_DEVICE_IS_BUSY,
PROP_DEVICE_MOUNT_PATH,
PROP_JOB_IN_PROGRESS,
case PROP_DEVICE_IS_MOUNTED:
g_value_set_boolean (value, device->priv->info.device_is_mounted);
break;
+ case PROP_DEVICE_IS_BUSY:
+ /* this property is special; it's value is computed on demand */
+ g_value_set_boolean (value, devkit_disks_device_local_is_busy (device));
+ break;
case PROP_DEVICE_MOUNT_PATH:
g_value_set_string (value, device->priv->info.device_mount_path);
break;
g_param_spec_boolean ("device-is-mounted", NULL, NULL, FALSE, G_PARAM_READABLE));
g_object_class_install_property (
object_class,
+ PROP_DEVICE_IS_BUSY,
+ g_param_spec_boolean ("device-is-busy", NULL, NULL, FALSE, G_PARAM_READABLE));
+ g_object_class_install_property (
+ object_class,
PROP_DEVICE_MOUNT_PATH,
g_param_spec_string ("device-mount-path", NULL, NULL, NULL, G_PARAM_READABLE));
g_free (device->priv->info.drive_serial);
g_free (device->priv->info.dm_name);
+ g_ptr_array_foreach (device->priv->info.slaves_objpath, (GFunc) g_free, NULL);
+ g_ptr_array_free (device->priv->info.slaves_objpath, TRUE);
+ g_ptr_array_foreach (device->priv->info.holders_objpath, (GFunc) g_free, NULL);
+ g_ptr_array_free (device->priv->info.holders_objpath, TRUE);
}
static void
device->priv->info.partition_flags = g_ptr_array_new ();
device->priv->info.partition_table_offsets = g_array_new (FALSE, TRUE, sizeof (guint64));
device->priv->info.partition_table_sizes = g_array_new (FALSE, TRUE, sizeof (guint64));
+ device->priv->info.slaves_objpath = g_ptr_array_new ();
+ device->priv->info.holders_objpath = g_ptr_array_new ();
}
} else if (strcmp (key, "DM_TARGET_TYPES") == 0) {
if (strcmp (devkit_info_property_get_string (info, key), "crypt") == 0) {
- char *slaves_path;
- GDir *slaves_dir;
- const char *slave_name;
-
- /* we're a dm-crypt target, find our slave */
- slaves_path = g_build_filename (device->priv->native_path, "slaves", NULL);
- if((slaves_dir = g_dir_open (slaves_path, 0, NULL)) != NULL) {
- while ((slave_name = g_dir_read_name (slaves_dir)) != NULL) {
- device->priv->info.device_is_crypto_cleartext = TRUE;
- device->priv->info.crypto_cleartext_slave =
- compute_object_path_from_basename (slave_name);
- }
- g_dir_close (slaves_dir);
+ /* we're a dm-crypt target and can, by design, then only have one slave */
+ if (device->priv->info.slaves_objpath->len == 1) {
+ device->priv->info.device_is_crypto_cleartext = TRUE;
+ device->priv->info.crypto_cleartext_slave =
+ g_strdup (g_ptr_array_index (device->priv->info.slaves_objpath, 0));
}
- g_free (slaves_path);
-
}
} else if (strcmp (key, "MEDIA_AVAILABLE") == 0) {
static gboolean
update_info (DevkitDisksDevice *device)
{
+ guint64 start, size;
+ char *s;
+ char *p;
+ int n;
gboolean ret;
int fd;
int block_size;
DevKitInfo *info;
+ char *path;
+ GDir *dir;
+ const char *name;
ret = FALSE;
info = NULL;
/* figure out if we're a partition and, if so, who our slave is */
if (sysfs_file_exists (device->priv->native_path, "start")) {
- guint64 start, size;
- char *s;
- char *p;
- int n;
/* we're partitioned by the kernel */
device->priv->info.device_is_partition = TRUE;
/* TODO: handle partitions created by kpartx / dm-linear */
}
+ /* Maintain (non-exported) properties holders and slaves for the holders resp. slaves
+ * directories in sysfs. The entries in these arrays are object paths (that may not
+ * exist; we just compute the name).
+ */
+ path = g_build_filename (device->priv->native_path, "slaves", NULL);
+ if((dir = g_dir_open (path, 0, NULL)) != NULL) {
+ while ((name = g_dir_read_name (dir)) != NULL) {
+ s = compute_object_path_from_basename (name);
+ g_ptr_array_add (device->priv->info.slaves_objpath, s);
+ g_warning ("slave='%s'", s);
+ }
+ g_dir_close (dir);
+ }
+ g_free (path);
+
+ path = g_build_filename (device->priv->native_path, "holders", NULL);
+ if((dir = g_dir_open (path, 0, NULL)) != NULL) {
+ while ((name = g_dir_read_name (dir)) != NULL) {
+ s = compute_object_path_from_basename (name);
+ g_ptr_array_add (device->priv->info.holders_objpath, s);
+ g_warning ("holder='%s'", s);
+ }
+ g_dir_close (dir);
+ }
+ g_free (path);
+
+
if (devkit_info_property_foreach (info, update_info_properties_cb, device)) {
goto out;
}
return ret;
}
+gboolean
+devkit_disks_device_local_is_busy (DevkitDisksDevice *device)
+{
+ gboolean ret;
+
+ ret = TRUE;
+
+ /* busy if a job is pending */
+ if (device->priv->job != NULL)
+ goto out;
+
+ /* or if we're mounted */
+ if (device->priv->info.device_is_mounted)
+ goto out;
+
+ /* or if another block device is using/holding us (e.g. if holders/ is non-empty in sysfs) */
+ if (device->priv->info.holders_objpath->len > 0)
+ goto out;
+
+ ret = FALSE;
+
+out:
+ return ret;
+}
+
DevkitDisksDevice *
devkit_disks_device_new (DevkitDisksDaemon *daemon, const char *native_path)
{
"/" to mean "not set" for object paths. -->
<!-- The 'native-path' property is the OS native path for the
- device; on Linux this is the sysfs path. -->
+ device; on Linux this is the sysfs path.
+
+ The 'device-is-busy' property is set if the device is
+ in use; this can hapen if it's mounted, if another
+ block device is claiming it or if a job initiated from
+ DeviceKit-disks is pending.
+ -->
<property name="native-path" type="s" access="read"/>
<property name="device-file" type="s" access="read"/>
<property name="device-file-by-id" type="as" access="read"/>
<property name="device-is-drive" type="b" access="read"/>
<property name="device-is-mounted" type="b" access="read"/>
<property name="device-is-crypto-cleartext" type="b" access="read"/>
+ <property name="device-is-busy" type="b" access="read"/>
<property name="device-mount-path" type="s" access="read"/>
<property name="device-size" type="t" access="read"/>
<property name="device-block-size" type="t" access="read"/>
e.g. 'Erase', 'CreateFilesystem' and so on.
Note that the 'job-cur-task' percentage starts at 0. The
- percentage is a number between -1 and 100. If set to -1 it
- means the progress of the current is unknown. The task id is
+ percentage is normally a number between 0 and 100. If set to -1
+ it means the progress of the current is unknown. The task id is
a well-defined name defining the current subtask of the job;
known tasks id's are
gboolean device_is_drive;
gboolean device_is_crypto_cleartext;
gboolean device_is_mounted;
+ gboolean device_is_busy;
char *device_mount_path;
guint64 device_size;
guint64 device_block_size;
props->device_is_crypto_cleartext = g_value_get_boolean (value);
else if (strcmp (key, "device-is-mounted") == 0)
props->device_is_mounted = g_value_get_boolean (value);
+ else if (strcmp (key, "device-is-busy") == 0)
+ props->device_is_busy = g_value_get_boolean (value);
else if (strcmp (key, "device-mount-path") == 0)
props->device_mount_path = g_strdup (g_value_get_string (value));
else if (strcmp (key, "device-size") == 0)
g_print (" removable: %d\n", props->device_is_removable);
g_print (" has media: %d\n", props->device_is_media_available);
g_print (" is mounted: %d\n", props->device_is_mounted);
+ g_print (" is busy: %d\n", props->device_is_busy);
g_print (" mount path: %s\n", props->device_mount_path);
g_print (" size: %lld\n", props->device_size);
g_print (" block size: %lld\n", props->device_block_size);