UNIX special device file for device. Example: <doc:tt>/dev/sda</doc:tt>.
</doc:para></doc:description></doc:doc>
</property>
+ <property name="DeviceFilePresentation" type="s" access="read">
+ <doc:doc><doc:description><doc:para>
+ If not blank, the preferred device file (typically a symlink to the value of the <doc:ref type="property" to="Device:DeviceFile">DeviceFile</doc:ref> property) to present in user interface.
+ Example: <doc:tt>/dev/mapper/mpathb</doc:tt> or
+ <doc:tt>/dev/vg_phobos/lv_root</doc:tt>.
+ </doc:para></doc:description></doc:doc>
+ </property>
<property name="DeviceFileById" type="as" access="read">
<doc:doc><doc:description><doc:para>
Symlinks to UNIX special device file that are stable and uniquely identifies the device.
TRUE if the device is a Linux LVM2 physical. See LinuxLvm2PV properties for details.
</doc:para></doc:description></doc:doc>
</property>
+ <property name="DeviceIsLinuxDmmpComponent" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ TRUE if the device is a component (e.g. active path) of a Linux dm-multipath device.
+ </doc:para></doc:description></doc:doc>
+ </property>
+ <property name="DeviceIsLinuxDmmp" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ TRUE if the device is a Linux dm-multipath device.
+ </doc:para></doc:description></doc:doc>
+ </property>
<property name="DeviceSize" type="t" access="read">
<doc:doc><doc:description><doc:para>
The size of the device in bytes.
</doc:para></doc:description></doc:doc>
</property>
+ <!-- ******************** -->
+ <!-- Multi-path Component -->
+ <!-- ******************** -->
+
+ <property name="LinuxDmmpComponentHolder" type="o" access="read">
+ <doc:doc><doc:description><doc:para>
+ The object path of the multi-path device the component is currently part of.
+ This property is only valid if
+ <doc:ref type="property" to="Device:DeviceIsLinuxDmmpComponent">DeviceIsLinuxDmmpComponent</doc:ref>
+ is TRUE.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <!-- ***************** -->
+ <!-- Multi-path Device -->
+ <!-- ***************** -->
+
+ <property name="LinuxDmmpName" type="s" access="read">
+ <doc:doc><doc:description><doc:para>
+ The symbolic name for the multipath device, e.g. <doc:tt>mpathb</doc:tt>.
+ This property is only valid if
+ <doc:ref type="property" to="Device:DeviceIsLinuxDmmp">DeviceIsLinuxDmmp</doc:ref>
+ is TRUE.
+ </doc:para></doc:description></doc:doc>
+ </property>
+ <property name="LinuxDmmpSlaves" type="ao" access="read">
+ <doc:doc><doc:description><doc:para>
+ The object paths of currently active component devices, e.g. paths.
+ This property is only valid if
+ <doc:ref type="property" to="Device:DeviceIsLinuxDmmp">DeviceIsLinuxDmmp</doc:ref>
+ is TRUE.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
</interface>
</node>
}
void
+device_set_device_file_presentation (Device *device,
+ const gchar *value)
+{
+ if (G_UNLIKELY (g_strcmp0 (device->priv->device_file_presentation, value) != 0))
+ {
+ g_free (device->priv->device_file_presentation);
+ device->priv->device_file_presentation = g_strdup (value);
+ emit_changed (device, "device_file_presentation");
+ }
+}
+
+void
device_set_device_file_by_id (Device *device,
GStrv value)
{
}
void
+device_set_device_is_linux_dmmp (Device *device, gboolean value)
+{
+ if (G_UNLIKELY (device->priv->device_is_linux_dmmp != value))
+ {
+ device->priv->device_is_linux_dmmp = value;
+ emit_changed (device, "device_is_linux_dmmp");
+ }
+}
+
+void
+device_set_device_is_linux_dmmp_component (Device *device, gboolean value)
+{
+ if (G_UNLIKELY (device->priv->device_is_linux_dmmp_component != value))
+ {
+ device->priv->device_is_linux_dmmp_component = value;
+ emit_changed (device, "device_is_linux_dmmp_component");
+ }
+}
+
+void
device_set_device_size (Device *device,
guint64 value)
{
emit_changed (device, "linux_lvm2_pv_group_logical_volumes");
}
}
+
+
+void
+device_set_linux_dmmp_component_holder (Device *device,
+ const gchar *value)
+{
+ if (G_UNLIKELY (g_strcmp0 (device->priv->linux_dmmp_component_holder, value) != 0))
+ {
+ g_free (device->priv->linux_dmmp_component_holder);
+ device->priv->linux_dmmp_component_holder = g_strdup (value);
+ emit_changed (device, "linux_dmmp_component_holder");
+ }
+}
+
+void
+device_set_linux_dmmp_name (Device *device,
+ const gchar *value)
+{
+ if (G_UNLIKELY (g_strcmp0 (device->priv->linux_dmmp_name, value) != 0))
+ {
+ g_free (device->priv->linux_dmmp_name);
+ device->priv->linux_dmmp_name = g_strdup (value);
+ emit_changed (device, "linux_dmmp_name");
+ }
+}
+
+void
+device_set_linux_dmmp_slaves (Device *device,
+ GStrv value)
+{
+ if (G_UNLIKELY (!ptr_str_array_equals_strv (device->priv->linux_dmmp_slaves, value)))
+ {
+ ptr_str_array_free (device->priv->linux_dmmp_slaves);
+ device->priv->linux_dmmp_slaves = ptr_str_array_from_strv (value);
+ emit_changed (device, "linux_dmmp_slaves");
+ }
+}
/**************/
char *device_file;
+ char *device_file_presentation;
dev_t dev;
GPtrArray *device_file_by_id;
GPtrArray *device_file_by_path;
gboolean device_is_linux_md;
gboolean device_is_linux_lvm2_lv;
gboolean device_is_linux_lvm2_pv;
+ gboolean device_is_linux_dmmp;
+ gboolean device_is_linux_dmmp_component;
guint64 device_size;
guint64 device_block_size;
gboolean device_is_mounted;
void *drive_ata_smart_blob;
gsize drive_ata_smart_blob_size;
+ gchar *linux_dmmp_component_holder;
+
+ gchar *linux_dmmp_name;
+ GPtrArray *linux_dmmp_slaves;
+
/* the following properties are not (yet) exported */
char *dm_name;
GPtrArray *slaves_objpath;
void device_set_device_detection_time (Device *device, guint64 value);
void device_set_device_media_detection_time (Device *device, guint64 value);
void device_set_device_file (Device *device, const gchar *value);
+void device_set_device_file_presentation (Device *device, const gchar *value);
void device_set_device_file_by_id (Device *device, GStrv value);
void device_set_device_file_by_path (Device *device, GStrv value);
void device_set_device_is_system_internal (Device *device, gboolean value);
void device_set_device_is_linux_md (Device *device, gboolean value);
void device_set_device_is_linux_lvm2_lv (Device *device, gboolean value);
void device_set_device_is_linux_lvm2_pv (Device *device, gboolean value);
+void device_set_device_is_linux_dmmp (Device *device, gboolean value);
+void device_set_device_is_linux_dmmp_component (Device *device, gboolean value);
void device_set_device_size (Device *device, guint64 value);
void device_set_device_block_size (Device *device, guint64 value);
void device_set_device_is_mounted (Device *device, gboolean value);
void device_set_linux_lvm2_pv_group_physical_volumes (Device *device, GStrv value);
void device_set_linux_lvm2_pv_group_logical_volumes (Device *device, GStrv value);
+void device_set_linux_dmmp_component_holder (Device *device, const gchar *value);
+
+void device_set_linux_dmmp_name (Device *device, const gchar *value);
+void device_set_linux_dmmp_slaves (Device *device, GStrv value);
+
void device_set_dm_name (Device *device, const gchar *value);
void device_set_slaves_objpath (Device *device, GStrv value);
void device_set_holders_objpath (Device *device, GStrv value);
ForceRemovalCompleteFunc callback,
gpointer user_data);
+/* TODO: this is kinda a hack */
+static const gchar *
+get_dmmp_device_node (Device *device)
+{
+ static gchar buf[1024];
+
+ g_assert (device->priv->device_is_linux_dmmp);
+ g_snprintf (buf, sizeof (buf), "/dev/mapper/%s", device->priv->linux_dmmp_name);
+ return buf;
+}
+
enum
{
PROP_0,
PROP_DEVICE_MAJOR,
PROP_DEVICE_MINOR,
PROP_DEVICE_FILE,
+ PROP_DEVICE_FILE_PRESENTATION,
PROP_DEVICE_FILE_BY_ID,
PROP_DEVICE_FILE_BY_PATH,
PROP_DEVICE_IS_SYSTEM_INTERNAL,
PROP_DEVICE_IS_LINUX_MD,
PROP_DEVICE_IS_LINUX_LVM2_LV,
PROP_DEVICE_IS_LINUX_LVM2_PV,
+ PROP_DEVICE_IS_LINUX_DMMP,
+ PROP_DEVICE_IS_LINUX_DMMP_COMPONENT,
PROP_DEVICE_SIZE,
PROP_DEVICE_BLOCK_SIZE,
PROP_DEVICE_IS_MOUNTED,
PROP_LINUX_LVM2_PV_GROUP_EXTENT_SIZE,
PROP_LINUX_LVM2_PV_GROUP_PHYSICAL_VOLUMES,
PROP_LINUX_LVM2_PV_GROUP_LOGICAL_VOLUMES,
+
+ PROP_LINUX_DMMP_COMPONENT_HOLDER,
+
+ PROP_LINUX_DMMP_NAME,
+ PROP_LINUX_DMMP_SLAVES,
};
enum
case PROP_DEVICE_FILE:
g_value_set_string (value, device->priv->device_file);
break;
+ case PROP_DEVICE_FILE_PRESENTATION:
+ g_value_set_string (value, device->priv->device_file_presentation);
+ break;
case PROP_DEVICE_FILE_BY_ID:
g_value_set_boxed (value, device->priv->device_file_by_id);
break;
case PROP_DEVICE_IS_LINUX_LVM2_PV:
g_value_set_boolean (value, device->priv->device_is_linux_lvm2_pv);
break;
+ case PROP_DEVICE_IS_LINUX_DMMP:
+ g_value_set_boolean (value, device->priv->device_is_linux_dmmp);
+ break;
+ case PROP_DEVICE_IS_LINUX_DMMP_COMPONENT:
+ g_value_set_boolean (value, device->priv->device_is_linux_dmmp_component);
+ break;
case PROP_DEVICE_SIZE:
g_value_set_uint64 (value, device->priv->device_size);
break;
g_value_set_boxed (value, device->priv->linux_lvm2_pv_group_logical_volumes);
break;
+ case PROP_LINUX_DMMP_COMPONENT_HOLDER:
+ if (device->priv->linux_dmmp_component_holder != NULL)
+ g_value_set_boxed (value, device->priv->linux_dmmp_component_holder);
+ else
+ g_value_set_boxed (value, "/");
+ break;
+
+ case PROP_LINUX_DMMP_NAME:
+ g_value_set_string (value, device->priv->linux_dmmp_name);
+ break;
+
+ case PROP_LINUX_DMMP_SLAVES:
+ g_value_set_boxed (value, device->priv->linux_dmmp_slaves);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
G_MAXINT64,
0,
G_PARAM_READABLE));
- g_object_class_install_property (object_class, PROP_DEVICE_FILE, g_param_spec_string ("device-file",
- NULL,
- NULL,
- NULL,
- G_PARAM_READABLE));
+ g_object_class_install_property (object_class,
+ PROP_DEVICE_FILE,
+ g_param_spec_string ("device-file",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READABLE));
+ g_object_class_install_property (object_class,
+ PROP_DEVICE_FILE_PRESENTATION,
+ g_param_spec_string ("device-file-presentation",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_DEVICE_FILE_BY_ID,
g_param_spec_boxed ("device-file-by-id",
NULL,
FALSE,
G_PARAM_READABLE));
+ g_object_class_install_property (object_class,
+ PROP_DEVICE_IS_LINUX_DMMP,
+ g_param_spec_boolean ("device-is-linux-dmmp",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READABLE));
+ g_object_class_install_property (object_class,
+ PROP_DEVICE_IS_LINUX_DMMP_COMPONENT,
+ g_param_spec_boolean ("device-is-linux-dmmp-component",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READABLE));
g_object_class_install_property (object_class, PROP_DEVICE_SIZE, g_param_spec_uint64 ("device-size",
NULL,
NULL,
dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
G_PARAM_READABLE));
+ g_object_class_install_property (object_class,
+ PROP_LINUX_DMMP_COMPONENT_HOLDER,
+ g_param_spec_boxed ("linux-dmmp-component-holder",
+ NULL,
+ NULL,
+ DBUS_TYPE_G_OBJECT_PATH,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class,
+ PROP_LINUX_DMMP_NAME,
+ g_param_spec_string ("linux-dmmp-name",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READABLE));
+ g_object_class_install_property (object_class,
+ PROP_LINUX_DMMP_SLAVES,
+ g_param_spec_boxed ("linux-dmmp-slaves",
+ NULL,
+ NULL,
+ dbus_g_type_get_collection ("GPtrArray",
+ DBUS_TYPE_G_OBJECT_PATH),
+ G_PARAM_READABLE));
}
static void
device->priv->linux_md_slaves = g_ptr_array_new ();
device->priv->linux_lvm2_pv_group_physical_volumes = g_ptr_array_new ();
device->priv->linux_lvm2_pv_group_logical_volumes = g_ptr_array_new ();
+ device->priv->linux_dmmp_slaves = g_ptr_array_new ();
device->priv->slaves_objpath = g_ptr_array_new ();
device->priv->holders_objpath = g_ptr_array_new ();
/* free properties */
g_free (device->priv->device_file);
+ g_free (device->priv->device_file_presentation);
g_ptr_array_foreach (device->priv->device_file_by_id, (GFunc) g_free, NULL);
g_ptr_array_foreach (device->priv->device_file_by_path, (GFunc) g_free, NULL);
g_ptr_array_free (device->priv->device_file_by_id, TRUE);
g_ptr_array_foreach (device->priv->linux_md_slaves, (GFunc) g_free, NULL);
g_ptr_array_free (device->priv->linux_md_slaves, TRUE);
+ g_free (device->priv->linux_dmmp_component_holder);
+
+ g_free (device->priv->linux_dmmp_name);
+ g_ptr_array_foreach (device->priv->linux_dmmp_slaves, (GFunc) g_free, NULL);
+ g_ptr_array_free (device->priv->linux_dmmp_slaves, TRUE);
+
g_free (device->priv->linux_lvm2_lv_name);
g_free (device->priv->linux_lvm2_lv_uuid);
g_free (device->priv->linux_lvm2_lv_group_name);
device_set_drive_serial (device, g_udev_device_get_property (device->priv->d, "ID_SERIAL_SHORT"));
}
- if (g_udev_device_has_property (device->priv->d, "ID_WWN"))
+ if (g_udev_device_has_property (device->priv->d, "ID_WWN_WITH_EXTENSION"))
+ device_set_drive_wwn (device, g_udev_device_get_property (device->priv->d, "ID_WWN_WITH_EXTENSION") + 2);
+ else if (g_udev_device_has_property (device->priv->d, "ID_WWN"))
device_set_drive_wwn (device, g_udev_device_get_property (device->priv->d, "ID_WWN") + 2);
/* pick up some things (vendor, model, connection_interface, connection_speed)
ret = FALSE;
- dkd_dm_name = g_udev_device_get_property (device->priv->d, "UDISKS_DM_NAME");
- dkd_dm_target_types = g_udev_device_get_property (device->priv->d, "UDISKS_DM_TARGET_TYPES");
+ dkd_dm_name = g_udev_device_get_property (device->priv->d, "DM_NAME");
+ dkd_dm_target_types = g_udev_device_get_property (device->priv->d, "UDISKS_DM_TARGETS_TYPE");
if (dkd_dm_name != NULL && g_strcmp0 (dkd_dm_target_types, "crypt") == 0 && device->priv->slaves_objpath->len == 1)
{
/* ---------------------------------------------------------------------------------------------------- */
+/* update device_is_linux_dmmp and linux_dmmp_* properties */
+static gboolean
+update_info_linux_dmmp (Device *device)
+{
+ const gchar *dm_name;
+ const gchar* const *target_types;
+ gboolean is_dmmp;
+ guint n;
+ GPtrArray *p;
+ Device *component;
+ gchar *s;
+
+ is_dmmp = FALSE;
+ p = NULL;
+
+ dm_name = g_udev_device_get_property (device->priv->d, "DM_NAME");
+ if (dm_name == NULL)
+ goto out;
+
+ target_types = g_udev_device_get_property_as_strv (device->priv->d, "UDISKS_DM_TARGETS_TYPE");
+ if (target_types == NULL || g_strcmp0 (target_types[0], "multipath") != 0)
+ goto out;
+
+ if (device->priv->slaves_objpath->len == 0)
+ goto out;
+
+ device_set_linux_dmmp_name (device, dm_name);
+
+ p = g_ptr_array_new ();
+ for (n = 0; n < device->priv->slaves_objpath->len; n++)
+ {
+ const gchar *component_objpath = device->priv->slaves_objpath->pdata[n];
+ if (component == NULL)
+ {
+ component = daemon_local_find_by_object_path (device->priv->daemon, component_objpath);
+ }
+ g_ptr_array_add (p, (gpointer) component_objpath);
+ }
+ g_ptr_array_add (p, NULL);
+ device_set_linux_dmmp_slaves (device, (GStrv) p->pdata);
+
+ if (component == NULL)
+ goto out;
+
+ /* copy some of the Drive* properties from the (first) components - we could check here whether
+ * it matches the other components and warn if it doesn't (it should)
+ *
+ * TODO: what about DriveAdapter and DrivePorts? Set them to NULL for now
+ */
+ device_set_drive_vendor (device, component->priv->drive_vendor);
+ device_set_drive_model (device, component->priv->drive_model);
+ device_set_drive_revision (device, component->priv->drive_revision);
+ device_set_drive_serial (device, component->priv->drive_serial);
+ device_set_drive_wwn (device, component->priv->drive_wwn);
+ device_set_drive_connection_interface (device, "virtual_multipath");
+ device_set_drive_connection_speed (device, 0);
+ /* GStrv vs GPtrArray.. device_set_drive_media_compatibility (device, component->priv->drive_media_compatibility); */
+ device_set_drive_media (device, component->priv->drive_media);
+ device_set_drive_is_media_ejectable (device, component->priv->drive_is_media_ejectable);
+ device_set_drive_can_detach (device, component->priv->drive_can_detach);
+ device_set_drive_can_spindown (device, component->priv->drive_can_spindown);
+ device_set_drive_is_rotational (device, component->priv->drive_is_rotational);
+ device_set_drive_rotation_rate (device, component->priv->drive_rotation_rate);
+ device_set_drive_write_cache (device, component->priv->drive_write_cache);
+
+ s = g_strdup_printf ("/dev/mapper/%s", dm_name);
+ device_set_device_file_presentation (device, s);
+ g_free (s);
+
+ is_dmmp = TRUE;
+
+ out:
+ if (p != NULL)
+ g_ptr_array_free (p, TRUE);
+ device_set_device_is_linux_dmmp (device, is_dmmp);
+ return TRUE;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* updates device_is_partition and partition_* properties for dm-0 "partitions" on a multi-path device */
+static gboolean
+update_info_partition_on_linux_dmmp (Device *device)
+{
+ const gchar *dm_name;
+ const gchar* const *targets_type;
+ const gchar* const *targets_params;
+ gchar *params;
+ gint partition_slave_major;
+ gint partition_slave_minor;
+ guint64 offset_sectors;
+ guint64 offset;
+ guint partition_number;
+ Device *partition_slave;
+ gchar *s;
+
+ params = NULL;
+
+ dm_name = g_udev_device_get_property (device->priv->d, "DM_NAME");
+ if (dm_name == NULL)
+ goto out;
+
+ targets_type = g_udev_device_get_property_as_strv (device->priv->d, "UDISKS_DM_TARGETS_TYPE");
+ if (targets_type == NULL || g_strcmp0 (targets_type[0], "linear") != 0)
+ goto out;
+
+ targets_params = g_udev_device_get_property_as_strv (device->priv->d, "UDISKS_DM_TARGETS_PARAMS");
+ if (targets_params == NULL)
+ goto out;
+ params = decode_udev_encoded_string (targets_params[0]);
+
+ if (sscanf (params,
+ "%d:%d %" G_GUINT64_FORMAT,
+ &partition_slave_major,
+ &partition_slave_minor,
+ &offset_sectors) != 3)
+ goto out;
+
+ partition_slave = daemon_local_find_by_dev (device->priv->daemon,
+ makedev (partition_slave_major, partition_slave_minor));
+ if (partition_slave == NULL)
+ goto out;
+
+ offset = offset_sectors * 512;
+
+ device_set_partition_slave (device, partition_slave->priv->object_path);
+ device_set_partition_offset (device, offset);
+ device_set_partition_size (device, device->priv->device_size);
+ partition_number = g_udev_device_get_property_as_int (device->priv->d, "UDISKS_PARTITION_NUMBER");
+ if (partition_number > 0)
+ device_set_partition_number (device, partition_number);
+
+ /* all the other Partition* has been set as part of update_info_partition() by reading
+ * UDISKS_PARTITION_* properties
+ */
+
+ device_set_device_is_partition (device, TRUE);
+ device_set_device_is_drive (device, FALSE);
+
+ s = g_strdup_printf ("/dev/mapper/%s", dm_name);
+ device_set_device_file_presentation (device, s);
+ g_free (s);
+
+ out:
+ g_free (params);
+ return TRUE;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* update device_is_linux_dmmp_component and linux_dmmp_component_* properties */
+static gboolean
+update_info_linux_dmmp_component (Device *device)
+{
+ gboolean is_dmmp_component;
+
+ is_dmmp_component = FALSE;
+
+ if (device->priv->holders_objpath->len == 1)
+ {
+ Device *holder;
+
+ holder = daemon_local_find_by_object_path (device->priv->daemon, device->priv->holders_objpath->pdata[0]);
+ if (holder != NULL && holder->priv->device_is_linux_dmmp)
+ {
+ is_dmmp_component = TRUE;
+ device_set_linux_dmmp_component_holder (device, holder->priv->object_path);
+ }
+ }
+
+ device_set_device_is_linux_dmmp_component (device, is_dmmp_component);
+ return TRUE;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
/* update device_is_linux_lvm2_pv and linux_lvm2_pv_* properties */
static gboolean
update_info_linux_lvm2_pv (Device *device)
goto out;
}
- /* ignore dm devices that are not active */
- if (g_str_has_prefix (g_udev_device_get_name (device->priv->d), "dm-")
- && g_udev_device_get_property (device->priv->d, "UDISKS_DM_STATE") == NULL)
+ /* ignore dm devices that are suspended */
+ if (g_str_has_prefix (g_udev_device_get_name (device->priv->d), "dm-") &&
+ g_strcmp0 (g_udev_device_get_property (device->priv->d, "DM_SUSPENDED"), "0") != 0)
goto out;
major = g_udev_device_get_property_as_int (device->priv->d, "MAJOR");
if (!update_info_linux_lvm2_pv (device))
goto out;
+ /* device_is_linux_dmmp and linux_dmmp_* properties */
+ if (!update_info_linux_dmmp (device))
+ goto out;
+
+ /* device_is_partition and partition_* properties for dm-0 "partitions" on a multi-path device */
+ if (!update_info_partition_on_linux_dmmp (device))
+ goto out;
+
+ /* device_is_linux_dmmp_component and linux_dmmp_component_* properties */
+ if (!update_info_linux_dmmp_component (device))
+ goto out;
+
/* device_is_linux_md_component and linux_md_component_* properties */
if (!update_info_linux_md_component (device))
goto out;
/* or if another block device is using/holding us (e.g. if holders/ is non-empty in sysfs) */
if (device->priv->holders_objpath->len > 0)
{
- g_set_error (error, ERROR, ERROR_BUSY, "One or more block devices are holding %s", device->priv->device_file);
- goto out;
+ if (device->priv->device_is_linux_dmmp)
+ {
+ /* This is OK */
+ }
+ else
+ {
+ g_set_error (error,
+ ERROR,
+ ERROR_BUSY,
+ "One or more block devices are holding %s",
+ device->priv->device_file);
+ goto out;
+ }
}
/* If we are an extended partition, we are also busy if one or more logical partitions are busy
n = 0;
argv[n++] = PACKAGE_LIBEXEC_DIR "/udisks-helper-delete-partition";
- argv[n++] = enclosing_device->priv->device_file;
+ if (enclosing_device->priv->device_is_linux_dmmp)
+ argv[n++] = (gchar *) get_dmmp_device_node (enclosing_device);
+ else
+ argv[n++] = enclosing_device->priv->device_file;
argv[n++] = device->priv->device_file;
argv[n++] = offset_as_string;
argv[n++] = size_as_string;
n = 0;
argv[n++] = PACKAGE_LIBEXEC_DIR "/udisks-helper-create-partition";
- argv[n++] = device->priv->device_file;
- ;
+ if (device->priv->device_is_linux_dmmp)
+ argv[n++] = (gchar *) get_dmmp_device_node (device);
+ else
+ argv[n++] = device->priv->device_file;
argv[n++] = offset_as_string;
argv[n++] = size_as_string;
argv[n++] = (char *) type;
n = 0;
argv[n++] = PACKAGE_LIBEXEC_DIR "/udisks-helper-create-partition-table";
- argv[n++] = device->priv->device_file;
+ if (device->priv->device_is_linux_dmmp)
+ argv[n++] = (gchar *) get_dmmp_device_node (device);
+ else
+ argv[n++] = device->priv->device_file;
argv[n++] = (char *) scheme;
for (m = 0; options[m] != NULL; m++)
{
ret = 0;
}
- /* reread partition table */
- if (!reread_partition_table (device))
+ /* tell kernel reread partition table (but only if we are a kernel partition) */
+ if (!g_str_has_prefix (device, "/dev/mapper/mpath"))
{
- ret = 1;
- goto out;
+ if (!reread_partition_table (device))
+ {
+ ret = 1;
+ goto out;
+ }
}
out:
}
}
- /* OK, now tell the kernel about the newly added partition */
- fd = open (device, O_RDONLY);
- if (fd < 0)
+ /* OK, now tell the kernel about the newly added partition (but only if we are a kernel partition) */
+ if (!g_str_has_prefix (device, "/dev/mapper/mpath"))
{
- g_printerr ("Cannot open %s: %m\n", device);
- goto out;
- }
- memset (&a, '\0', sizeof(struct blkpg_ioctl_arg));
- memset (&p, '\0', sizeof(struct blkpg_partition));
- p.pno = out_num;
- p.start = out_start;
- p.length = out_size;
- a.op = BLKPG_ADD_PARTITION;
- a.datalen = sizeof(p);
- a.data = &p;
- if (ioctl (fd, BLKPG, &a) == -1)
- {
- g_printerr ("Error doing BLKPG ioctl with BLKPG_ADD_PARTITION for partition %d "
- "of size %" G_GUINT64_FORMAT " at offset %" G_GUINT64_FORMAT " on %s: %m\n",
- out_num,
- out_start,
- out_size,
- device);
+ fd = open (device, O_RDONLY);
+ if (fd < 0)
+ {
+ g_printerr ("Cannot open %s: %m\n", device);
+ goto out;
+ }
+ memset (&a, '\0', sizeof(struct blkpg_ioctl_arg));
+ memset (&p, '\0', sizeof(struct blkpg_partition));
+ p.pno = out_num;
+ p.start = out_start;
+ p.length = out_size;
+ a.op = BLKPG_ADD_PARTITION;
+ a.datalen = sizeof(p);
+ a.data = &p;
+ if (ioctl (fd, BLKPG, &a) == -1)
+ {
+ g_printerr ("Error doing BLKPG ioctl with BLKPG_ADD_PARTITION for partition %d "
+ "of size %" G_GUINT64_FORMAT " at offset %" G_GUINT64_FORMAT " on %s: %m\n",
+ out_num,
+ out_start,
+ out_size,
+ device);
+ close (fd);
+ goto out;
+ }
close (fd);
- goto out;
}
- close (fd);
/* send the start and size back to the daemon - it needs to know, to
* wait for the created partition, because the partition may not have
goto out;
}
- /* don't ask libparted to poke the kernel - it won't work if other partitions are mounted/busy */
- if (part_del_partition ((char *) device, offset, FALSE))
- {
- gint fd;
- struct blkpg_ioctl_arg a;
- struct blkpg_partition p;
+ gboolean is_kernel_partition;
+ is_kernel_partition = !g_str_has_prefix (device, "/dev/mapper/mpath");
- /* now, ask the kernel to delete the partition */
- fd = open (device, O_RDONLY);
- if (fd < 0)
- {
- g_printerr ("Cannot open %s: %m\n", device);
- goto out;
- }
- memset (&a, '\0', sizeof(struct blkpg_ioctl_arg));
- memset (&p, '\0', sizeof(struct blkpg_partition));
- p.pno = part_number;
- a.op = BLKPG_DEL_PARTITION;
- a.datalen = sizeof(p);
- a.data = &p;
- if (ioctl (fd, BLKPG, &a) == -1)
+ /* don't ask libparted to poke the kernel - it won't work if other
+ * partitions are mounted/busy (unless it's not a kernel partition)
+ */
+ if (part_del_partition ((char *) device,
+ offset,
+ is_kernel_partition ? FALSE : TRUE))
+ {
+ /* now, ask the kernel to delete the partition (but only if we are a kernel partition) */
+ if (is_kernel_partition)
{
- g_printerr ("Error doing BLKPG ioctl with BLKPG_DEL_PARTITION for partition %d on %s: %m\n",
- part_number,
- device);
+ gint fd;
+ struct blkpg_ioctl_arg a;
+ struct blkpg_partition p;
+
+ fd = open (device, O_RDONLY);
+ if (fd < 0)
+ {
+ g_printerr ("Cannot open %s: %m\n", device);
+ goto out;
+ }
+ memset (&a, '\0', sizeof(struct blkpg_ioctl_arg));
+ memset (&p, '\0', sizeof(struct blkpg_partition));
+ p.pno = part_number;
+ a.op = BLKPG_DEL_PARTITION;
+ a.datalen = sizeof(p);
+ a.data = &p;
+ if (ioctl (fd, BLKPG, &a) == -1)
+ {
+ g_printerr ("Error doing BLKPG ioctl with BLKPG_DEL_PARTITION for partition %d on %s: %m\n",
+ part_number,
+ device);
+ close (fd);
+ goto out;
+ }
close (fd);
- goto out;
}
- close (fd);
/* zero the contents of what was the _partition_
*
/* scrub signatures */
if (!scrub_signatures (device, offset, size))
{
- g_printerr ("Cannot scrub filesystem signatures at "
- "offset=%" G_GINT64_FORMAT " and size=%" G_GINT64_FORMAT "\n",
- offset, size);
+ g_printerr ("Cannot scrub filesystem signatures at "
+ "offset=%" G_GINT64_FORMAT " and size=%" G_GINT64_FORMAT "\n",
+ offset, size);
}
else
{
exit (1);
}
+static gchar *
+decode_udev_encoded_string (const gchar *str)
+{
+ GString *s;
+ gchar *ret;
+ const gchar *end_valid;
+ guint n;
+
+ s = g_string_new (NULL);
+ for (n = 0; str[n] != '\0'; n++)
+ {
+ if (str[n] == '\\')
+ {
+ gint val;
+
+ if (str[n + 1] != 'x' || str[n + 2] == '\0' || str[n + 3] == '\0')
+ {
+ g_print ("**** NOTE: malformed encoded string '%s'\n", str);
+ break;
+ }
+
+ val = (g_ascii_xdigit_value (str[n + 2]) << 4) | g_ascii_xdigit_value (str[n + 3]);
+
+ g_string_append_c (s, val);
+
+ n += 3;
+ }
+ else
+ {
+ g_string_append_c (s, str[n]);
+ }
+ }
+
+ if (!g_utf8_validate (s->str, -1, &end_valid))
+ {
+ g_print ("**** NOTE: The string '%s' is not valid UTF-8. Invalid characters begins at '%s'\n", s->str, end_valid);
+ ret = g_strndup (s->str, end_valid - s->str);
+ g_string_free (s, TRUE);
+ }
+ else
+ {
+ ret = g_string_free (s, FALSE);
+ }
+
+ return ret;
+}
+
static int
sysfs_get_int (const char *dir,
const char *attribute)
return result;
}
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gchar *
+get_syspath (struct udev *udev,
+ const gchar *device_file)
+{
+ struct udev_device *device;
+ struct stat statbuf;
+ gchar *ret;
+
+ ret = NULL;
+
+ if (stat (device_file, &statbuf) != 0)
+ {
+ g_printerr ("Error statting %s: %m\n", device_file);
+ goto out;
+ }
+
+ device = udev_device_new_from_devnum (udev, 'b', statbuf.st_rdev);
+ if (device == NULL)
+ {
+ g_printerr ("Error getting udev device for %s: %m\n", device_file);
+ goto out;
+ }
+ ret = g_strdup (udev_device_get_syspath (device));
+ udev_device_unref (device);
+
+ out:
+ return ret;
+}
+
+/**
+ * get_part_table_device_file:
+ * @udev: An udev context.
+ * @given_device_file: The device file given on the command line.
+ * @out_offset: Return location for offset or %NULL.
+ * @out_partition_number: Return location for partition number or %NULL.
+ *
+ * If @given_device_file is not a partition, returns a copy of it and
+ * sets @out_offset and @out_partition_number to 0.
+ *
+ * Otherwise, returns the device file for the block device for which
+ * @given_device_file is a partition of and returns the offset of the
+ * partition in @out_offset and the partition number in
+ * @out_partition_number.
+ *
+ * If something goes wrong, %NULL is returned.
+ */
+static gchar *
+get_part_table_device_file (struct udev *udev,
+ const gchar *given_device_file,
+ guint64 *out_offset,
+ guint *out_partition_number)
+{
+ gchar *ret;
+ guint64 offset;
+ guint partition_number;
+ gchar *devpath;
+
+ devpath = NULL;
+ offset = 0;
+ ret = NULL;
+
+ devpath = get_syspath (udev, given_device_file);
+ if (devpath == NULL)
+ goto out;
+
+ partition_number = sysfs_get_int (devpath, "partition");
+
+ /* find device file for partition table device */
+ if (partition_number > 0)
+ {
+ struct udev_device *device;
+ gchar *partition_table_devpath;
+ guint n;
+
+ /* partition */
+ partition_table_devpath = g_strdup (devpath);
+ for (n = strlen (partition_table_devpath) - 1; partition_table_devpath[n] != '/'; n--)
+ partition_table_devpath[n] = '\0';
+ partition_table_devpath[n] = '\0';
+
+ device = udev_device_new_from_syspath (udev, partition_table_devpath);
+ if (device == NULL)
+ {
+ g_printerr ("Error getting udev device for syspath %s: %m\n", partition_table_devpath);
+ goto out;
+ }
+ ret = g_strdup (udev_device_get_devnode (device));
+ udev_device_unref (device);
+ if (ret == NULL)
+ {
+ /* This Should Not Happen™, but was reported in a distribution upgrade
+ scenario, so handle it gracefully */
+ g_printerr ("Error getting devnode from udev device path %s: %m\n", partition_table_devpath);
+ goto out;
+ }
+ g_free (partition_table_devpath);
+
+ offset = sysfs_get_uint64 (devpath, "start") * 512;
+ }
+ else
+ {
+ struct udev_device *device;
+ const char *targets_type;
+ const char *encoded_targets_params;
+
+ device = udev_device_new_from_syspath (udev, devpath);
+ if (device == NULL)
+ {
+ g_printerr ("Error getting udev device for syspath %s: %m\n", devpath);
+ goto out;
+ }
+
+ targets_type = udev_device_get_property_value (device, "UDISKS_DM_TARGETS_TYPE");
+ encoded_targets_params = udev_device_get_property_value (device, "UDISKS_DM_TARGETS_PARAMS");
+ if (g_strcmp0 (targets_type, "linear") == 0)
+ {
+ gint partition_slave_major;
+ gint partition_slave_minor;
+ guint64 offset_sectors;
+ gchar *targets_params;
+
+ targets_params = decode_udev_encoded_string (encoded_targets_params);
+ if (sscanf (targets_params,
+ "%d:%d\x20%" G_GUINT64_FORMAT,
+ &partition_slave_major,
+ &partition_slave_minor,
+ &offset_sectors) == 3)
+ {
+ struct udev_device *mp_device;
+
+ mp_device = udev_device_new_from_devnum (udev, 'b', makedev (partition_slave_major,
+ partition_slave_minor));
+ if (mp_device != NULL)
+ {
+ const char *dm_uuid;
+
+ ret = g_strdup (udev_device_get_devnode (mp_device));
+ offset = offset_sectors * 512;
+
+ /* now figure out partition_number
+ *
+ * this is kind of a hack.. but works since UUID is of the
+ * form part2-mpath-3600508b400105df70000e00000d80000
+ */
+ partition_number = 0;
+ dm_uuid = udev_device_get_property_value (device, "DM_UUID");
+ if (dm_uuid != NULL && g_str_has_prefix (dm_uuid, "part"))
+ partition_number = atoi (dm_uuid + 4);
+
+ udev_device_unref (mp_device);
+ g_free (targets_params);
+ udev_device_unref (device);
+ goto out;
+ }
+ }
+ g_free (targets_params);
+ }
+ udev_device_unref (device);
+
+ /* not a kernel partition */
+ ret = g_strdup (given_device_file);
+ partition_number = 0;
+ }
+
+ out:
+ if (out_offset != NULL)
+ *out_offset = offset;
+ if (out_partition_number != NULL)
+ *out_partition_number = partition_number;
+
+ g_free (devpath);
+
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static guint
+count_entries (PartitionTable *pt)
+{
+ guint ret;
+ guint num_top_level;
+ guint n;
+
+ ret = 0;
+
+ num_top_level = part_table_get_num_entries (pt);
+ for (n = 0; n < num_top_level; n++)
+ {
+ PartitionTable *nested;
+
+ if (part_table_entry_is_in_use (pt, n))
+ ret++;
+
+ nested = part_table_entry_get_nested (pt, n);
+ if (nested != NULL)
+ {
+ ret += part_table_get_num_entries (nested);
+ }
+ }
+
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
int
main (int argc,
char *argv[])
{
guint n;
gint fd;
- gint partition_number;
gchar *devpath;
const gchar *device_file;
gchar *partition_table_device_file;
goto out;
}
- devpath = getenv ("DEVPATH");
- if (devpath != NULL)
- {
- devpath = g_build_filename ("/sys", devpath, NULL);
- }
- else
- {
- struct udev_device *device;
- struct stat statbuf;
-
- if (stat (device_file, &statbuf) != 0)
- {
- g_printerr ("Error statting %s: %m\n", device_file);
- goto out;
- }
-
- device = udev_device_new_from_devnum (udev, 'b', statbuf.st_rdev);
- if (device == NULL)
- {
- g_printerr ("Error getting udev device for %s: %m\n", device_file);
- goto out;
- }
- devpath = g_strdup (udev_device_get_syspath (device));
- udev_device_unref (device);
- }
-
- partition_number = sysfs_get_int (devpath, "partition");
-
- /* find device file for partition table device */
- if (partition_number > 0)
- {
- struct udev_device *device;
- gchar *partition_table_devpath;
-
- /* partition */
- partition_table_devpath = g_strdup (devpath);
- for (n = strlen (partition_table_devpath) - 1; partition_table_devpath[n] != '/'; n--)
- partition_table_devpath[n] = '\0';
- partition_table_devpath[n] = '\0';
+ guint64 partition_offset;
+ guint partition_number;
- device = udev_device_new_from_syspath (udev, partition_table_devpath);
- if (device == NULL)
- {
- g_printerr ("Error getting udev device for syspath %s: %m\n", partition_table_devpath);
- goto out;
- }
- partition_table_device_file = g_strdup (udev_device_get_devnode (device));
- udev_device_unref (device);
- if (partition_table_device_file == NULL)
- {
- /* This Should Not Happen™, but was reported in a distribution upgrade
- scenario, so handle it gracefully */
- g_printerr ("Error getting devnode from udev device path %s: %m\n", partition_table_devpath);
- goto out;
- }
- g_free (partition_table_devpath);
- }
- else
- {
- /* not partition */
- partition_table_device_file = g_strdup (device_file);
- }
+ partition_table_device_file = get_part_table_device_file (udev,
+ device_file,
+ &partition_offset,
+ &partition_number);
+ g_printerr ("got `%s' and %" G_GUINT64_FORMAT "\n", partition_table_device_file, partition_offset);
fd = open (partition_table_device_file, O_RDONLY);
/* TODO: right now we also use part_id to determine if media is available or not. This
* should probably be done elsewhere
*/
- if (partition_number == 0)
+ if (partition_offset == 0)
{
if (fd < 0)
{
}
close (fd);
- if (partition_number > 0)
+ if (partition_offset > 0)
{
- guint64 partition_offset;
PartitionTable *partition_table_for_entry;
gint entry_num;
gchar *type;
guint64 size;
/* partition */
- partition_offset = sysfs_get_uint64 (devpath, "start") * 512;
part_table_find (partition_table, partition_offset, &partition_table_for_entry, &entry_num);
if (entry_num == -1)
{
{
g_print ("UDISKS_PARTITION_TABLE=1\n");
g_print ("UDISKS_PARTITION_TABLE_SCHEME=%s\n", part_get_scheme_name (part_table_get_scheme (partition_table)));
+ g_print ("UDISKS_PARTITION_TABLE_COUNT=%d\n", count_entries (partition_table));
}
out:
/* ---------------------------------------------------------------------------------------------------- */
+
+/* This code is from udev - will become public libudev API at some point */
+
+/* count of characters used to encode one unicode char */
+static int utf8_encoded_expected_len(const char *str)
+{
+ unsigned char c = (unsigned char)str[0];
+
+ if (c < 0x80)
+ return 1;
+ if ((c & 0xe0) == 0xc0)
+ return 2;
+ if ((c & 0xf0) == 0xe0)
+ return 3;
+ if ((c & 0xf8) == 0xf0)
+ return 4;
+ if ((c & 0xfc) == 0xf8)
+ return 5;
+ if ((c & 0xfe) == 0xfc)
+ return 6;
+ return 0;
+}
+
+/* decode one unicode char */
+static int utf8_encoded_to_unichar(const char *str)
+{
+ int unichar;
+ int len;
+ int i;
+
+ len = utf8_encoded_expected_len(str);
+ switch (len) {
+ case 1:
+ return (int)str[0];
+ case 2:
+ unichar = str[0] & 0x1f;
+ break;
+ case 3:
+ unichar = (int)str[0] & 0x0f;
+ break;
+ case 4:
+ unichar = (int)str[0] & 0x07;
+ break;
+ case 5:
+ unichar = (int)str[0] & 0x03;
+ break;
+ case 6:
+ unichar = (int)str[0] & 0x01;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i = 1; i < len; i++) {
+ if (((int)str[i] & 0xc0) != 0x80)
+ return -1;
+ unichar <<= 6;
+ unichar |= (int)str[i] & 0x3f;
+ }
+
+ return unichar;
+}
+
+/* expected size used to encode one unicode char */
+static int utf8_unichar_to_encoded_len(int unichar)
+{
+ if (unichar < 0x80)
+ return 1;
+ if (unichar < 0x800)
+ return 2;
+ if (unichar < 0x10000)
+ return 3;
+ if (unichar < 0x200000)
+ return 4;
+ if (unichar < 0x4000000)
+ return 5;
+ return 6;
+}
+
+/* check if unicode char has a valid numeric range */
+static int utf8_unichar_valid_range(int unichar)
+{
+ if (unichar > 0x10ffff)
+ return 0;
+ if ((unichar & 0xfffff800) == 0xd800)
+ return 0;
+ if ((unichar > 0xfdcf) && (unichar < 0xfdf0))
+ return 0;
+ if ((unichar & 0xffff) == 0xffff)
+ return 0;
+ return 1;
+}
+
+/* validate one encoded unicode char and return its length */
+static int utf8_encoded_valid_unichar(const char *str)
+{
+ int len;
+ int unichar;
+ int i;
+
+ len = utf8_encoded_expected_len(str);
+ if (len == 0)
+ return -1;
+
+ /* ascii is valid */
+ if (len == 1)
+ return 1;
+
+ /* check if expected encoded chars are available */
+ for (i = 0; i < len; i++)
+ if ((str[i] & 0x80) != 0x80)
+ return -1;
+
+ unichar = utf8_encoded_to_unichar(str);
+
+ /* check if encoded length matches encoded value */
+ if (utf8_unichar_to_encoded_len(unichar) != len)
+ return -1;
+
+ /* check if value has valid range */
+ if (!utf8_unichar_valid_range(unichar))
+ return -1;
+
+ return len;
+}
+
+static int is_whitelisted(char c, const char *white)
+{
+ if ((c >= '0' && c <= '9') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') ||
+ strchr("#+-.:=@_", c) != NULL ||
+ (white != NULL && strchr(white, c) != NULL))
+ return 1;
+ return 0;
+}
+
+/**
+ * _udev_util_encode_string:
+ * @str: input string to be encoded
+ * @str_enc: output string to store the encoded input string
+ * @len: maximum size of the output string, which may be
+ * four times as long as the input string
+ *
+ * Encode all potentially unsafe characters of a string to the
+ * corresponding hex value prefixed by '\x'.
+ *
+ * Returns: 0 if the entire string was copied, non-zero otherwise.
+ */
+static int
+_udev_util_encode_string(const char *str, char *str_enc, size_t len)
+{
+ size_t i, j;
+
+ if (str == NULL || str_enc == NULL)
+ return -1;
+
+ for (i = 0, j = 0; str[i] != '\0'; i++) {
+ int seqlen;
+
+ seqlen = utf8_encoded_valid_unichar(&str[i]);
+ if (seqlen > 1) {
+ if (len-j < (size_t)seqlen)
+ goto err;
+ memcpy(&str_enc[j], &str[i], seqlen);
+ j += seqlen;
+ i += (seqlen-1);
+ } else if (str[i] == '\\' || !is_whitelisted(str[i], NULL)) {
+ if (len-j < 4)
+ goto err;
+ sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]);
+ j += 4;
+ } else {
+ if (len-j < 1)
+ goto err;
+ str_enc[j] = str[i];
+ j++;
+ }
+ }
+ if (len-j < 1)
+ goto err;
+ str_enc[j] = '\0';
+ return 0;
+err:
+ return -1;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
/* based on the export patch in https://bugzilla.redhat.com/show_bug.cgi?id=438604 */
static int
char *target_type;
char *params;
const char *name;
- const char *uuid;
struct dm_info info;
+ GString *target_types_str;
+ GString *start_str;
+ GString *length_str;
+ GString *params_str;
+ gchar buf[4096];
ret = FALSE;
dmt = NULL;
- dmt = dm_task_create (DM_DEVICE_STATUS);
+ dmt = dm_task_create (DM_DEVICE_TABLE);
if (dmt == NULL)
{
perror ("dm_task_create");
perror ("dm_task_get_name");
goto out;
}
- g_print ("UDISKS_DM_NAME=%s\n", name);
-
- uuid = dm_task_get_uuid (dmt);
- if (uuid != NULL)
- {
- g_print ("UDISKS_DM_UUID=%s\n", uuid);
- }
if (!info.exists)
{
- g_print ("UDISKS_DM_STATE=NOTPRESENT\n");
goto out;
}
- g_print ("UDISKS_DM_STATE=%s\n",
- info.suspended ? "SUSPENDED" :
- (info.read_only ? " READONLY" : "ACTIVE"));
-
- if (!info.live_table && !info.inactive_table)
- {
- g_print ("UDISKS_DM_TABLE_STATE=NONE\n");
- }
- else
- {
- g_print ("UDISKS_DM_TABLE_STATE=%s%s%s\n",
- info.live_table ? "LIVE" : "",
- info.live_table && info.inactive_table ? "/" : "",
- info.inactive_table ? "INACTIVE" : "");
- }
-
- if (info.open_count != -1)
- {
- g_print ("UDISKS_DM_OPENCOUNT=%d\n", info.open_count);
- }
-
- g_print ("UDISKS_DM_LAST_EVENT_NR=%" G_GUINT32_FORMAT "\n", (guint32) info.event_nr);
-
- g_print ("UDISKS_DM_MAJOR=%d\n", info.major);
- g_print ("UDISKS_DM_MINOR=%d\n", info.minor);
-
if (info.target_count != -1)
- g_print ("UDISKS_DM_TARGET_COUNT=%d\n", info.target_count);
+ g_print ("UDISKS_DM_TARGETS_COUNT=%d\n", info.target_count);
+
+ target_types_str = g_string_new (NULL);
+ start_str = g_string_new (NULL);
+ length_str = g_string_new (NULL);
+ params_str = g_string_new (NULL);
- /* export all table types */
+ /* export all tables */
next = NULL;
- next = dm_get_next_target (dmt, next, &start, &length, &target_type, ¶ms);
- if (target_type != NULL)
+ do
{
- g_print ("UDISKS_DM_TARGET_TYPES=%s", target_type);
- while (next != NULL)
+ next = dm_get_next_target (dmt, next, &start, &length, &target_type, ¶ms);
+ if (target_type != NULL)
+ {
+ g_string_append (target_types_str, target_type);
+ g_string_append_printf (start_str, "%" G_GUINT64_FORMAT, start);
+ g_string_append_printf (length_str, "%" G_GUINT64_FORMAT, length);
+ if (params != NULL && strlen (params) > 0)
+ {
+ _udev_util_encode_string (params, buf, sizeof (buf));
+ g_string_append (params_str, buf);
+ }
+ }
+
+ if (next != NULL)
{
- next = dm_get_next_target (dmt, next, &start, &length, &target_type, ¶ms);
- if (target_type)
- g_print (",%s", target_type);
+ g_string_append_c (target_types_str, ' ');
+ g_string_append_c (start_str, ' ');
+ g_string_append_c (length_str, ' ');
+ g_string_append_c (params_str, ' ');
}
- g_print ("\n");
}
+ while (next != NULL);
+
+ if (target_types_str->len > 0)
+ g_print ("UDISKS_DM_TARGETS_TYPE=%s\n", target_types_str->str);
+ if (start_str->len > 0)
+ g_print ("UDISKS_DM_TARGETS_START=%s\n", start_str->str);
+ if (length_str->len > 0)
+ g_print ("UDISKS_DM_TARGETS_LENGTH=%s\n", length_str->str);
+ if (params_str->len > 0)
+ g_print ("UDISKS_DM_TARGETS_PARAMS=%s\n", params_str->str);
+
+ g_string_free (target_types_str, TRUE);
+ g_string_free (start_str, TRUE);
+ g_string_free (length_str, TRUE);
+ g_string_free (params_str, TRUE);
ret = TRUE;
gint64 device_major;
gint64 device_minor;
char *device_file;
+ char *device_file_presentation;
char **device_file_by_id;
char **device_file_by_path;
gboolean device_is_system_internal;
gboolean device_is_linux_md;
gboolean device_is_linux_lvm2_lv;
gboolean device_is_linux_lvm2_pv;
+ gboolean device_is_linux_dmmp;
+ gboolean device_is_linux_dmmp_component;
char **device_mount_paths;
uid_t device_mounted_by_uid;
gboolean device_presentation_hide;
guint64 linux_lvm2_pv_group_extent_size;
char **linux_lvm2_pv_group_physical_volumes;
char **linux_lvm2_pv_group_logical_volumes;
+
+ gchar *linux_dmmp_component_holder;
+
+ gchar *linux_dmmp_name;
+ gchar **linux_dmmp_slaves;
+
} DeviceProperties;
static void
props->device_minor = g_value_get_int64 (value);
else if (strcmp (key, "DeviceFile") == 0)
props->device_file = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "DeviceFilePresentation") == 0)
+ props->device_file_presentation = g_strdup (g_value_get_string (value));
else if (strcmp (key, "DeviceFileById") == 0)
props->device_file_by_id = g_strdupv (g_value_get_boxed (value));
else if (strcmp (key, "DeviceFileByPath") == 0)
props->device_is_linux_lvm2_lv = g_value_get_boolean (value);
else if (strcmp (key, "DeviceIsLinuxLvm2PV") == 0)
props->device_is_linux_lvm2_pv = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsLinuxDmmp") == 0)
+ props->device_is_linux_dmmp = g_value_get_boolean (value);
+ else if (strcmp (key, "DeviceIsLinuxDmmpComponent") == 0)
+ props->device_is_linux_dmmp_component = g_value_get_boolean (value);
else if (strcmp (key, "DeviceIsMounted") == 0)
props->device_is_mounted = g_value_get_boolean (value);
else if (strcmp (key, "DeviceMountPaths") == 0)
else if (strcmp (key, "LinuxLvm2PVGroupLogicalVolumes") == 0)
props->linux_lvm2_pv_group_logical_volumes = g_strdupv (g_value_get_boxed (value));
+ else if (strcmp (key, "LinuxDmmpComponentHolder") == 0)
+ props->linux_dmmp_component_holder = g_strdup (g_value_get_boxed (value));
+
+ else if (strcmp (key, "LinuxDmmpName") == 0)
+ props->linux_dmmp_name = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "LinuxDmmpSlaves") == 0)
+ {
+ guint n;
+ GPtrArray *object_paths;
+
+ object_paths = g_value_get_boxed (value);
+
+ props->linux_dmmp_slaves = g_new0 (char *, object_paths->len + 1);
+ for (n = 0; n < object_paths->len; n++)
+ props->linux_dmmp_slaves[n] = g_strdup (object_paths->pdata[n]);
+ props->linux_dmmp_slaves[n] = NULL;
+ }
+
else
handled = FALSE;
{
g_free (props->native_path);
g_free (props->device_file);
+ g_free (props->device_file_presentation);
g_strfreev (props->device_file_by_id);
g_strfreev (props->device_file_by_path);
g_strfreev (props->device_mount_paths);
g_strfreev (props->linux_lvm2_pv_group_physical_volumes);
g_strfreev (props->linux_lvm2_pv_group_logical_volumes);
+ g_free (props->linux_dmmp_component_holder);
+
+ g_free (props->linux_dmmp_name);
+ g_strfreev (props->linux_dmmp_slaves);
+
g_free (props);
}
props->device_major,
props->device_minor);
g_print (" device-file: %s\n", props->device_file);
+ g_print (" presentation: %s\n",
+ (props->device_file_presentation != NULL && strlen (props->device_file_presentation) > 0) ?
+ props->device_file_presentation : "(not set)");
for (n = 0; props->device_file_by_id[n] != NULL; n++)
g_print (" by-id: %s\n", (char *) props->device_file_by_id[n]);
for (n = 0; props->device_file_by_path[n] != NULL; n++)
for (n = 0; props->linux_lvm2_pv_group_logical_volumes[n] != NULL; n++)
g_print (" %s\n", props->linux_lvm2_pv_group_logical_volumes[n]);
}
+ if (props->device_is_linux_dmmp)
+ {
+ g_print (" dm-multipath:\n");
+ g_print (" name: %s\n", props->linux_dmmp_name);
+ g_print (" components:\n");
+ for (n = 0; props->linux_dmmp_slaves[n] != NULL; n++)
+ g_print (" %s\n", props->linux_dmmp_slaves[n]);
+ }
+ if (props->device_is_linux_dmmp_component)
+ {
+ g_print (" dm-multipath component:\n");
+ g_print (" multipath device: %s\n", props->linux_dmmp_component_holder);
+ }
if (props->device_is_luks)
{