From: David Zeuthen Date: Tue, 31 Mar 2009 19:32:48 +0000 (-0400) Subject: rework partition table handling X-Git-Tag: upstream/2.1.2~894 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dab89114484d1190e8b7e110871ffe470a8c2afb;p=platform%2Fupstream%2Fudisks2.git rework partition table handling --- diff --git a/configure.ac b/configure.ac index 6da4ed6..14d178f 100644 --- a/configure.ac +++ b/configure.ac @@ -143,6 +143,10 @@ PKG_CHECK_MODULES(LIBATASMART, [libatasmart >= 0.2]) AC_SUBST(LIBATASMART_CFLAGS) AC_SUBST(LIBATASMART_LIBS) +PKG_CHECK_MODULES(LIBUDEV, [libudev >= 139]) +AC_SUBST(LIBUDEV_CFLAGS) +AC_SUBST(LIBUDEV_LIBS) + if test "x$GCC" = "xyes"; then LDFLAGS="-Wl,--as-needed $LDFLAGS" fi diff --git a/src/95-devkit-disks.rules b/src/95-devkit-disks.rules index 9e4b585..8327377 100644 --- a/src/95-devkit-disks.rules +++ b/src/95-devkit-disks.rules @@ -17,20 +17,10 @@ KERNEL=="sr*", ENV{ID_CDROM_MEDIA_TRACK_COUNT}!="?*", GOTO="probe_parttable_end" # scan for partition table only if we're not a partition # -ATTR{range}=="[0-9]*", IMPORT{program}="devkit-disks-part-id $tempnode" - -# for partitions, import parent information -# -#ATTR{start}=="[0-9]*", IMPORT{parent}="DKD_PART_*" - -# However.. right now we're not getting change events on media changes -# *until* all the partitions are added.. so importing parent information -# won't work; therefore, probe the partition table for each partition. -# -ATTR{start}=="[0-9]*", IMPORT{program}="devkit-disks-part-id $tempnode" +IMPORT{program}="devkit-disks-part-id $tempnode" # clear all ID_FS_USAGE, TYPE if we're a partition table -ATTR{range}=="[0-9]*", ENV{PART_P1_TYPE}!="", ENV{ID_FS_USAGE}="", ENV{ID_FS_TYPE}="" +ENV{DKD_PART_ID_PARTITION_TABLE_SCHEME}!="", ENV{ID_FS_USAGE}="", ENV{ID_FS_TYPE}="" LABEL="probe_parttable_end" diff --git a/src/Makefile.am b/src/Makefile.am index 834c01a..81e2901 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -137,8 +137,8 @@ udevhelperdir = $(slashlibdir)/udev udevhelper_PROGRAMS = devkit-disks-part-id devkit-disks-dm-export devkit-disks-probe-ata-smart devkit_disks_part_id_SOURCES = part-id.c -devkit_disks_part_id_CPPFLAGS = $(AM_CPPFLAGS) -devkit_disks_part_id_LDADD = $(GLIB_LIBS) libpartutil.la +devkit_disks_part_id_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUDEV_CFLAGS) +devkit_disks_part_id_LDADD = $(GLIB_LIBS) $(LIBUDEV_LIBS) libpartutil.la devkit_disks_dm_export_SOURCES = devkit-disks-dm-export.c devkit_disks_dm_export_CPPFLAGS = $(AM_CPPFLAGS) $(DEVMAPPER_CFLAGS) diff --git a/src/devkit-disks-device-private.c b/src/devkit-disks-device-private.c index 14735dc..9752523 100644 --- a/src/devkit-disks-device-private.c +++ b/src/devkit-disks-device-private.c @@ -103,34 +103,6 @@ ptr_str_array_from_strv (GStrv s) return ret; } - -static gboolean -array_equals (GArray * a, GArray * b, guint elem_size) -{ - if (a == NULL && b == NULL) - return TRUE; - if (a == NULL || b == NULL) - return FALSE; - if (a->len != b->len) - return FALSE; - if (a->len == 0) - return TRUE; - if (memcmp (a->data, b->data, a->len * elem_size) == 0) - return TRUE; - return FALSE; -} - -static GArray * -array_dup (GArray * a, guint elem_size) -{ - GArray *ret; - - ret = g_array_sized_new (FALSE, FALSE, elem_size, a->len); - g_array_append_vals (ret, a->data, a->len); - - return ret; -} - void devkit_disks_device_set_job_in_progress (DevkitDisksDevice *device, gboolean value) { @@ -652,38 +624,6 @@ devkit_disks_device_set_partition_table_count (DevkitDisksDevice *device, gint v } void -devkit_disks_device_set_partition_table_max_number (DevkitDisksDevice *device, gint value) -{ - if (G_UNLIKELY (device->priv->partition_table_max_number != value)) - { - device->priv->partition_table_max_number = value; - emit_changed (device, "partition_table_max_number"); - } -} - -void -devkit_disks_device_set_partition_table_offsets (DevkitDisksDevice *device, GArray * value) -{ - if (G_UNLIKELY (!array_equals (device->priv->partition_table_offsets, value, sizeof (guint64)))) - { - g_array_free (device->priv->partition_table_offsets, TRUE); - device->priv->partition_table_offsets = array_dup (value, sizeof (guint64)); - emit_changed (device, "partition_table_offsets"); - } -} - -void -devkit_disks_device_set_partition_table_sizes (DevkitDisksDevice *device, GArray * value) -{ - if (G_UNLIKELY (!array_equals (device->priv->partition_table_sizes, value, sizeof (guint64)))) - { - g_array_free (device->priv->partition_table_sizes, TRUE); - device->priv->partition_table_sizes = array_dup (value, sizeof (guint64)); - emit_changed (device, "partition_table_sizes"); - } -} - -void devkit_disks_device_set_drive_vendor (DevkitDisksDevice *device, const gchar *value) { if (G_UNLIKELY (g_strcmp0 (device->priv->drive_vendor, value) != 0)) diff --git a/src/devkit-disks-device-private.h b/src/devkit-disks-device-private.h index 6774ad5..9bd3f10 100644 --- a/src/devkit-disks-device-private.h +++ b/src/devkit-disks-device-private.h @@ -144,9 +144,6 @@ struct DevkitDisksDevicePrivate char *partition_table_scheme; int partition_table_count; - int partition_table_max_number; - GArray *partition_table_offsets; - GArray *partition_table_sizes; char *drive_vendor; char *drive_model; @@ -277,9 +274,6 @@ void devkit_disks_device_set_partition_size (DevkitDisksDevice *device, guint64 void devkit_disks_device_set_partition_table_scheme (DevkitDisksDevice *device, const gchar *value); void devkit_disks_device_set_partition_table_count (DevkitDisksDevice *device, gint value); -void devkit_disks_device_set_partition_table_max_number (DevkitDisksDevice *device, gint value); -void devkit_disks_device_set_partition_table_offsets (DevkitDisksDevice *device, GArray * value); -void devkit_disks_device_set_partition_table_sizes (DevkitDisksDevice *device, GArray * value); void devkit_disks_device_set_drive_vendor (DevkitDisksDevice *device, const gchar *value); void devkit_disks_device_set_drive_model (DevkitDisksDevice *device, const gchar *value); diff --git a/src/devkit-disks-device.c b/src/devkit-disks-device.c index d2200b3..fb7cd49 100644 --- a/src/devkit-disks-device.c +++ b/src/devkit-disks-device.c @@ -186,9 +186,6 @@ enum PROP_PARTITION_TABLE_SCHEME, PROP_PARTITION_TABLE_COUNT, - PROP_PARTITION_TABLE_MAX_NUMBER, - PROP_PARTITION_TABLE_OFFSETS, - PROP_PARTITION_TABLE_SIZES, PROP_LUKS_HOLDER, @@ -461,15 +458,6 @@ get_property (GObject *object, case PROP_PARTITION_TABLE_COUNT: g_value_set_int (value, device->priv->partition_table_count); break; - case PROP_PARTITION_TABLE_MAX_NUMBER: - g_value_set_int (value, device->priv->partition_table_max_number); - break; - case PROP_PARTITION_TABLE_OFFSETS: - g_value_set_boxed (value, device->priv->partition_table_offsets); - break; - case PROP_PARTITION_TABLE_SIZES: - g_value_set_boxed (value, device->priv->partition_table_sizes); - break; case PROP_LUKS_HOLDER: if (device->priv->luks_holder != NULL) @@ -928,22 +916,6 @@ devkit_disks_device_class_init (DevkitDisksDeviceClass *klass) object_class, PROP_PARTITION_TABLE_COUNT, g_param_spec_int ("partition-table-count", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READABLE)); - g_object_class_install_property ( - object_class, - PROP_PARTITION_TABLE_MAX_NUMBER, - g_param_spec_int ("partition-table-max-number", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READABLE)); - g_object_class_install_property ( - object_class, - PROP_PARTITION_TABLE_OFFSETS, - g_param_spec_boxed ("partition-table-offsets", NULL, NULL, - dbus_g_type_get_collection ("GArray", G_TYPE_UINT64), - G_PARAM_READABLE)); - g_object_class_install_property ( - object_class, - PROP_PARTITION_TABLE_SIZES, - g_param_spec_boxed ("partition-table-sizes", NULL, NULL, - dbus_g_type_get_collection ("GArray", G_TYPE_UINT64), - G_PARAM_READABLE)); g_object_class_install_property ( object_class, @@ -1206,8 +1178,6 @@ devkit_disks_device_init (DevkitDisksDevice *device) device->priv->device_file_by_id = g_ptr_array_new (); device->priv->device_file_by_path = g_ptr_array_new (); device->priv->partition_flags = g_ptr_array_new (); - device->priv->partition_table_offsets = g_array_new (FALSE, TRUE, sizeof (guint64)); - device->priv->partition_table_sizes = g_array_new (FALSE, TRUE, sizeof (guint64)); device->priv->drive_media_compatibility = g_ptr_array_new (); device->priv->linux_md_component_state = g_ptr_array_new (); device->priv->linux_md_slaves = g_ptr_array_new (); @@ -1274,8 +1244,6 @@ devkit_disks_device_finalize (GObject *object) g_free (device->priv->partition_uuid); g_ptr_array_foreach (device->priv->partition_flags, (GFunc) g_free, NULL); g_ptr_array_free (device->priv->partition_flags, TRUE); - g_array_free (device->priv->partition_table_offsets, TRUE); - g_array_free (device->priv->partition_table_sizes, TRUE); g_free (device->priv->partition_table_scheme); @@ -1450,12 +1418,11 @@ sysfs_get_uint64 (const char *dir, const char *attribute) result = 0; filename = g_build_filename (dir, attribute, NULL); if (g_file_get_contents (filename, &contents, NULL, NULL)) { - result = atoll (contents); + result = strtoll (contents, NULL, 0); g_free (contents); } g_free (filename); - return result; } @@ -1707,63 +1674,17 @@ update_info_id (DevkitDisksDevice *device) /* ---------------------------------------------------------------------------------------------------- */ -/* update device_is_partition_table and partition_table_* properties */ +/* update partition_table_* properties */ static gboolean update_info_partition_table (DevkitDisksDevice *device) { - guint n; - - if (!device->priv->device_is_partition && devkit_device_has_property (device->priv->d, "DKD_PART_SCHEME")) { - GArray *offsets; - GArray *sizes; + if (!device->priv->device_is_partition && + devkit_device_has_property (device->priv->d, "DKD_PARTITION_TABLE")) { devkit_disks_device_set_device_is_partition_table (device, TRUE); - devkit_disks_device_set_partition_table_scheme (device, devkit_device_get_property (device->priv->d, "DKD_PART_SCHEME")); - devkit_disks_device_set_partition_table_count (device, devkit_device_get_property_as_int (device->priv->d, "DKD_PART_COUNT")); - devkit_disks_device_set_partition_table_max_number (device, devkit_device_get_property_as_int (device->priv->d, "DKD_PART_MAX_NUMBER")); - - offsets = g_array_sized_new (FALSE, TRUE, sizeof (guint64), device->priv->partition_table_max_number); - sizes = g_array_sized_new (FALSE, TRUE, sizeof (guint64), device->priv->partition_table_max_number); - g_array_set_size (offsets, device->priv->partition_table_max_number); - g_array_set_size (sizes, device->priv->partition_table_max_number); - - for (n = 0; n < (guint) device->priv->partition_table_max_number; n++) { - gchar *part_key; - guint64 offset; - guint64 size; - - part_key = g_strdup_printf ("DKD_PART_P%d_OFFSET", n + 1); - if (devkit_device_has_property (device->priv->d, part_key)) - offset = devkit_device_get_property_as_uint64 (device->priv->d, part_key); - else - offset = 0; - g_free (part_key); - - part_key = g_strdup_printf ("DKD_PART_P%d_SIZE", n + 1); - if (devkit_device_has_property (device->priv->d, part_key)) - size = devkit_device_get_property_as_uint64 (device->priv->d, part_key); - else - size = 0; - g_free (part_key); - - g_array_index (offsets, guint64, n) = offset; - g_array_index (sizes, guint64, n) = size; - } - - devkit_disks_device_set_partition_table_offsets (device, offsets); - devkit_disks_device_set_partition_table_sizes (device, sizes); - g_array_free (offsets, TRUE); - g_array_free (sizes, TRUE); + devkit_disks_device_set_partition_table_scheme (device, devkit_device_get_property (device->priv->d, "DKD_PARTITION_TABLE_SCHEME")); } else { - GArray *empty_array; - devkit_disks_device_set_device_is_partition_table (device, FALSE); - empty_array = g_array_new (FALSE, TRUE, sizeof (guint64)); devkit_disks_device_set_partition_table_scheme (device, NULL); - devkit_disks_device_set_partition_table_count (device, 0); - devkit_disks_device_set_partition_table_max_number (device, 0); - devkit_disks_device_set_partition_table_offsets (device, empty_array); - devkit_disks_device_set_partition_table_sizes (device, empty_array); - g_array_free (empty_array, TRUE); } return TRUE; @@ -1775,51 +1696,28 @@ update_info_partition_table (DevkitDisksDevice *device) static gboolean update_info_partition (DevkitDisksDevice *device) { - if (device->priv->device_is_partition) { - gchar *part_key; - guint64 offset; + guint64 offset; + + offset = sysfs_get_uint64 (device->priv->native_path, "start") * device->priv->device_block_size; + devkit_disks_device_set_partition_offset (device, offset); + + if (device->priv->device_is_partition && + devkit_device_has_property (device->priv->d, "DKD_PARTITION")) { guint64 size; + const gchar *scheme; const gchar *type; const gchar *label; const gchar *uuid; gchar **flags; - devkit_disks_device_set_partition_scheme (device, devkit_device_get_property (device->priv->d, "DKD_PART_SCHEME")); - - part_key = g_strdup_printf ("DKD_PART_P%d_OFFSET", device->priv->partition_number); - if (devkit_device_has_property (device->priv->d, part_key)) - offset = devkit_device_get_property_as_uint64 (device->priv->d, part_key); - else - offset = 0; - g_free (part_key); - - part_key = g_strdup_printf ("DKD_PART_P%d_SIZE", device->priv->partition_number); - if (devkit_device_has_property (device->priv->d, part_key)) - size = devkit_device_get_property_as_uint64 (device->priv->d, part_key); - else - size = 0; - g_free (part_key); - - part_key = g_strdup_printf ("DKD_PART_P%d_TYPE", device->priv->partition_number); - type = devkit_device_get_property (device->priv->d, part_key); - g_free (part_key); - - part_key = g_strdup_printf ("DKD_PART_P%d_LABEL", device->priv->partition_number); - label = devkit_device_get_property (device->priv->d, part_key); - g_free (part_key); - - part_key = g_strdup_printf ("DKD_PART_P%d_UUID", device->priv->partition_number); - uuid = devkit_device_get_property (device->priv->d, part_key); - g_free (part_key); - - part_key = g_strdup_printf ("DKD_PART_P%d_FLAGS", device->priv->partition_number); - if (devkit_device_has_property (device->priv->d, part_key)) - flags = devkit_device_dup_property_as_strv (device->priv->d, part_key); - else - flags = NULL; - g_free (part_key); + scheme = devkit_device_get_property (device->priv->d, "DKD_PARTITION_SCHEME"); + size = devkit_device_get_property_as_uint64 (device->priv->d, "DKD_PARTITION_SIZE"); + type = devkit_device_get_property (device->priv->d, "DKD_PARTITION_TYPE"); + label = devkit_device_get_property (device->priv->d, "DKD_PARTITION_LABEL"); + uuid = devkit_device_get_property (device->priv->d, "DKD_PARTITION_UUID"); + flags = devkit_device_dup_property_as_strv (device->priv->d, "DKD_PARTITION_FLAGS"); - devkit_disks_device_set_partition_offset (device, offset); + devkit_disks_device_set_partition_scheme (device, scheme); devkit_disks_device_set_partition_size (device, size); devkit_disks_device_set_partition_type (device, type); devkit_disks_device_set_partition_label (device, label); @@ -1828,8 +1726,9 @@ update_info_partition (DevkitDisksDevice *device) g_strfreev (flags); } else { - devkit_disks_device_set_partition_offset (device, 0); - devkit_disks_device_set_partition_size (device, 0); + /* if we don't have info from part_id, set the partition size to the same as the block device */ + devkit_disks_device_set_partition_scheme (device, NULL); + devkit_disks_device_set_partition_size (device, device->priv->device_size); devkit_disks_device_set_partition_type (device, NULL); devkit_disks_device_set_partition_label (device, NULL); devkit_disks_device_set_partition_uuid (device, NULL); @@ -3023,15 +2922,35 @@ update_info (DevkitDisksDevice *device) devkit_disks_device_set_partition_slave (device, compute_object_path_from_basename (p)); g_free (p); g_free (s); - - /* since the env from the parent is imported, we'll - * add partition table information from enclosing - * device by matching on partition number - */ } else { /* TODO: handle partitions created by kpartx / dm-linear */ } + /* Figure out if we are a partition table - we don't want to rely on devkit-disks-part-id + * for this; it might not detect all partition table formats that the kernel supports. + * + * The kernel guarantees that all childs are created before the uevent for the parent + * is created. So if we have childs, we must be a partition table. + * + * To detect a child we check for the existance of a subdir that has the parents + * name as a prefix (e.g. for parent sda then sda1, sda2, sdap1 etc. will work). + */ + s = g_path_get_basename (device->priv->native_path); + if ((dir = g_dir_open (device->priv->native_path, 0, NULL)) != NULL) { + guint partition_count; + partition_count = 0; + while ((name = g_dir_read_name (dir)) != NULL) { + if (g_str_has_prefix (name, s)) { + partition_count++; + } + } + g_dir_close (dir); + devkit_disks_device_set_partition_table_count (device, partition_count); + devkit_disks_device_set_device_is_partition_table (device, (partition_count > 0)); + } + g_free (s); + + /* Maintain (non-exported) properties holders and slaves for the holders resp. slaves * directories in sysfs. The entries in these arrays are object paths - we ignore * an entry unless it corresponds to an device in our local database. @@ -3103,6 +3022,7 @@ update_info (DevkitDisksDevice *device) * - device_is_drive * - device_is_media_available * - device_is_partition + * - device_is_partition_table * - slaves_objpath * - holders_objpath * @@ -3119,7 +3039,7 @@ update_info (DevkitDisksDevice *device) if (!update_info_id (device)) goto out; - /* device_is_partition_table and partition_table_* properties */ + /* partition_table_* properties */ if (!update_info_partition_table (device)) goto out; @@ -6085,12 +6005,10 @@ devkit_disks_device_partition_create (DevkitDisksDevice *device, PolKitCaller *pk_caller; char *offset_as_string; char *size_as_string; - char *max_number_as_string; char *flags_as_string; offset_as_string = NULL; size_as_string = NULL; - max_number_as_string = NULL; flags_as_string = NULL; if ((pk_caller = devkit_disks_damon_local_get_caller_for_context (device->priv->daemon, context)) == NULL) @@ -6119,16 +6037,8 @@ devkit_disks_device_partition_create (DevkitDisksDevice *device, context)) goto out; - if (strlen (type) == 0) { - throw_error (context, - DEVKIT_DISKS_ERROR_FAILED, - "type not specified"); - goto out; - } - offset_as_string = g_strdup_printf ("%" G_GINT64_FORMAT "", offset); size_as_string = g_strdup_printf ("%" G_GINT64_FORMAT "", size); - max_number_as_string = g_strdup_printf ("%d", device->priv->partition_table_max_number); /* TODO: check that neither of the flags include ',' */ flags_as_string = g_strjoinv (",", flags); @@ -6137,7 +6047,6 @@ devkit_disks_device_partition_create (DevkitDisksDevice *device, argv[n++] = device->priv->device_file;; argv[n++] = offset_as_string; argv[n++] = size_as_string; - argv[n++] = max_number_as_string; argv[n++] = (char *) type; argv[n++] = (char *) label; argv[n++] = (char *) flags_as_string; @@ -6170,7 +6079,6 @@ devkit_disks_device_partition_create (DevkitDisksDevice *device, out: g_free (offset_as_string); g_free (size_as_string); - g_free (max_number_as_string); g_free (flags_as_string); if (pk_caller != NULL) polkit_caller_unref (pk_caller); diff --git a/src/job-create-partition.c b/src/job-create-partition.c index f955e56..7b7d017 100644 --- a/src/job-create-partition.c +++ b/src/job-create-partition.c @@ -56,12 +56,11 @@ main (int argc, char **argv) guint64 out_start; guint64 out_size; char *endp; - int max_number; ret = 1; flags = NULL; - if (argc < 8) { + if (argc < 7) { g_printerr ("wrong usage\n"); goto out; } @@ -76,15 +75,10 @@ main (int argc, char **argv) g_printerr ("malformed size '%s'\n", argv[3]); goto out; } - max_number = strtol (argv[4], &endp, 10); - if (*endp != '\0') { - g_printerr ("malformed max number '%s'\n", argv[4]); - goto out; - } - type = argv[5]; - label = argv[6]; - flags_as_string = argv[7]; - options = argv + 8; + type = argv[4]; + label = argv[5]; + flags_as_string = argv[6]; + options = argv + 7; flags = g_strsplit (flags_as_string, ",", 0); diff --git a/src/org.freedesktop.DeviceKit.Disks.Device.xml b/src/org.freedesktop.DeviceKit.Disks.Device.xml index 842e662..3a87285 100644 --- a/src/org.freedesktop.DeviceKit.Disks.Device.xml +++ b/src/org.freedesktop.DeviceKit.Disks.Device.xml @@ -1747,42 +1747,6 @@ is TRUE. - - - The maximum value for - partition-number - of the enclosed partitions (partitions may not be sequentially numbered). - This property is only valid if - device-is-partition-table - is TRUE. - - - - - An array of size - partition-table-max-number - that contains the offsets (in bytes) of each partition. - The property - partition-number - on enclosed partitions can be used as an index in this array. - This property is only valid if - device-is-partition-table - is TRUE. - - - - - An array of size - partition-table-max-number - that contains the size (in bytes) of each partition. - The property - partition-number - on enclosed partitions can be used as an index in this array. - This property is only valid if - device-is-partition-table - is TRUE. - - diff --git a/src/part-id.c b/src/part-id.c index 3708d98..b37d48e 100644 --- a/src/part-id.c +++ b/src/part-id.c @@ -1,3 +1,22 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2009 David Zeuthen + * + * 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 #include @@ -8,16 +27,20 @@ #include #include +#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE +#include + #include "partutil.h" static void usage (int argc, char *argv[]) { execlp ("man", "man", "part_id", NULL); - fprintf (stderr, "Cannot show man page: %m\n"); + g_printerr ("Cannot show man page: %m\n"); exit (1); } +#if 0 static void print_entry (PartitionTable *p, int entry, int print_number) { @@ -52,11 +75,106 @@ print_entry (PartitionTable *p, int entry, int print_number) g_free (flags_combined); } +static GString *e_types; +static GString *e_offsets; +static GString *e_sizes; +static GString *e_labels; +static GString *e_uuids; +static GString *e_flags; + +static void +entries_begin (void) +{ + e_types = g_string_new (NULL); + e_offsets = g_string_new (NULL); + e_sizes = g_string_new (NULL); + e_labels = g_string_new (NULL); + e_uuids = g_string_new (NULL); + e_flags = g_string_new (NULL); +} + +static void +entries_add (PartitionTable *p, int entry, int print_number) +{ + char *type; + char *label; + char *uuid; + char **flags; + char *flags_combined; + guint64 offset; + guint64 size; + + type = part_table_entry_get_type (p, entry); + label = part_table_entry_get_label (p, entry); + uuid = part_table_entry_get_uuid (p, entry); + flags = part_table_entry_get_flags (p, entry); + offset = part_table_entry_get_offset (p, entry); + size = part_table_entry_get_size (p, entry); + + flags_combined = g_strjoinv (" ", flags); + + if (e_types->len != 0) + g_string_append_c (e_types, ' '); + if (e_offsets->len != 0) + g_string_append_c (e_offsets, ' '); + if (e_sizes->len != 0) + g_string_append_c (e_sizes, ' '); + if (e_labels->len != 0) + g_string_append_c (e_labels, ' '); + if (e_uuids->len != 0) + g_string_append_c (e_uuids, ' '); + if (e_flags->len != 0) + g_string_append_c (e_flags, ' '); + + /* TODO: escape label */ + + g_string_append_printf (e_types, "%s", type != NULL ? type : ""); + g_string_append_printf (e_offsets, "%" G_GINT64_FORMAT, offset); + g_string_append_printf (e_sizes, "%" G_GINT64_FORMAT, size); + g_string_append_printf (e_labels, "%s", label != NULL ? label : ""); + g_string_append_printf (e_uuids, "%s", uuid != NULL ? uuid : ""); + g_string_append_printf (e_flags, "%s", flags_combined); + + g_free (type); + g_free (label); + g_free (uuid); + g_strfreev (flags); + g_free (flags_combined); +} + +static void +entries_print (void) +{ + printf ("DKD_PART_TYPES=%s\n", e_types->str); + printf ("DKD_PART_OFFSETS=%s\n", e_offsets->str); + printf ("DKD_PART_SIZES=%s\n", e_sizes->str); + printf ("DKD_PART_LABELS=%s\n", e_labels->str); + printf ("DKD_PART_UUIDS=%s\n", e_uuids->str); + printf ("DKD_PART_FLAGS=%s\n", e_flags->str); +} + +static void +entries_end (void) +{ + g_string_free (e_types, TRUE); + g_string_free (e_offsets, TRUE); + g_string_free (e_sizes, TRUE); + g_string_free (e_labels, TRUE); + g_string_free (e_uuids, TRUE); + g_string_free (e_flags, TRUE); + e_types = NULL; + e_offsets = NULL; + e_sizes = NULL; + e_labels = NULL; + e_uuids = NULL; + e_flags = NULL; +} + static void do_table (int fd) { - int n; - guint max_number; + gint n; + gint max_number; PartitionTable *table; PartitionTable *nested_table; int num_entries; @@ -99,21 +217,28 @@ do_table (int fd) printf ("DKD_PART_SCHEME=%s\n", part_get_scheme_name (part_table_get_scheme (table))); printf ("DKD_PART_COUNT=%d\n", num_used_entries + num_nested_entries); + entries_begin (); + max_number = 0; for (n = 0; n < num_entries; n++) { if (!part_table_entry_is_in_use (table, n)) continue; print_entry (table, n, n + 1); + entries_add (table, n, n + 1); if (n + 1 >= max_number) max_number = n + 1; } for (n = 0; n < num_nested_entries; n++) { print_entry (nested_table, n, n + 5); + entries_add (table, n, n + 1); if (n + 5 >= max_number) max_number = n + 5; } + //entries_print (); + entries_end (); + printf ("DKD_PART_MAX_NUMBER=%d\n", max_number); out: if (table != NULL) @@ -167,17 +292,17 @@ get_devpath (const char *device) /* ok, so this means we're not invoked from udev; do * some lipservice, because we're such nice and - * gullibe guys.. we run udevinfo to determine the + * gullibe guys.. we run udevadm to determine the * devpath */ error = NULL; - command_line = g_strdup_printf ("udevinfo -q path --name %s",device); + command_line = g_strdup_printf ("udevadm info -q path --name %s", device); if (!g_spawn_command_line_sync (command_line, &standard_output, NULL, &exit_status, &error)) { - fprintf (stderr, "couldn't run udevinfo to determine node: %s", error->message); + fprintf (stderr, "error running udevadm to determine node: %s", error->message); g_error_free (error); g_free (command_line); goto out; @@ -284,17 +409,70 @@ not_part: } return fd; } +#endif + +static int +sysfs_get_int (const char *dir, const char *attribute) +{ + int result; + char *contents; + char *filename; + + result = 0; + filename = g_build_filename (dir, attribute, NULL); + if (g_file_get_contents (filename, &contents, NULL, NULL)) { + result = strtol (contents, NULL, 0); + g_free (contents); + } + g_free (filename); + + + return result; +} + +static guint64 +sysfs_get_uint64 (const char *dir, const char *attribute) +{ + guint64 result; + char *contents; + char *filename; + + result = 0; + filename = g_build_filename (dir, attribute, NULL); + if (g_file_get_contents (filename, &contents, NULL, NULL)) { + result = strtoll (contents, NULL, 0); + g_free (contents); + } + g_free (filename); + + return result; +} int main (int argc, char *argv[]) { - int n; - int fd; - char *device_file; - gboolean is_part; + guint n; + gint fd; + gint partition_number; + gchar *devpath; + const gchar *device_file; + gchar *partition_table_device_file; + struct udev *udev; + PartitionTable *partition_table; + + udev = NULL; + devpath = NULL; + partition_table_device_file = NULL; + partition_table = NULL; + + udev = udev_new (); + if (udev == NULL) { + g_printerr ("Error initializing libudev: %m\n"); + goto out; + } device_file = NULL; - for (n = 1; n < argc; n++) { + for (n = 1; n < (guint) argc; n++) { if (strcmp (argv[n], "--help") == 0) { usage (argc, argv); return 0; @@ -306,30 +484,144 @@ main (int argc, char *argv[]) } if (device_file == NULL) { - fprintf (stderr, "no device\n"); + g_printerr ("no device\n"); goto out; } - fd = open_device (device_file, &is_part); - if (fd >= 0) { - char *usage; - - if (!is_part) { - /* we currently errornously detect a vfat fs on the whole disk as a partition table. - * Avoid doing that. - */ - usage = getenv ("ID_FS_USAGE"); - if (usage != NULL && strcmp (usage, "filesystem") == 0) { - close (fd); - 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'; + + 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); + g_free (partition_table_devpath); + } else { + /* not partition */ + partition_table_device_file = g_strdup (device_file); + } + + 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 (fd < 0) { + g_print ("DKD_MEDIA_AVAILABLE=0\n"); + } else { + g_print ("DKD_MEDIA_AVAILABLE=1\n"); } + } - do_table (fd); - close (fd); + if (fd < 0) { + g_printerr ("Error opening %s: %m\n", partition_table_device_file); + goto out; + } + partition_table = part_table_load_from_disk (fd); + if (partition_table == NULL) { + g_printerr ("No partition table found on %s: %m\n", partition_table_device_file); + goto out; + } + close (fd); + + if (partition_number > 0) { + guint64 partition_offset; + PartitionTable *partition_table_for_entry; + gint entry_num; + gchar *type; + gchar *label; + gchar *uuid; + gchar **flags; + gchar *flags_combined; + guint64 offset; + 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_printerr ("Error finding partition at offset %" G_GUINT64_FORMAT " on %s\n", + partition_offset, + partition_table_device_file); + goto out; + } + + type = part_table_entry_get_type (partition_table_for_entry, entry_num); + label = part_table_entry_get_label (partition_table_for_entry, entry_num); + uuid = part_table_entry_get_uuid (partition_table_for_entry, entry_num); + flags = part_table_entry_get_flags (partition_table_for_entry, entry_num); + offset = part_table_entry_get_offset (partition_table_for_entry, entry_num); + size = part_table_entry_get_size (partition_table_for_entry, entry_num); + + flags_combined = g_strjoinv (" ", flags); + + g_print ("DKD_PARTITION=1\n"); + g_print ("DKD_PARTITION_SCHEME=%s\n", + part_get_scheme_name (part_table_get_scheme (partition_table_for_entry))); + g_print ("DKD_PARTITION_NUMBER=%d\n", partition_number); + g_print ("DKD_PARTITION_TYPE=%s\n", type != NULL ? type : ""); + g_print ("DKD_PARTITION_SIZE=%" G_GINT64_FORMAT "\n", size); + g_print ("DKD_PARTITION_LABEL=%s\n", label != NULL ? label : ""); + g_print ("DKD_PARTITION_UUID=%s\n", uuid != NULL ? uuid : ""); + g_print ("DKD_PARTITION_FLAGS=%s\n", flags_combined); + + g_free (type); + g_free (label); + g_free (uuid); + g_strfreev (flags); + g_free (flags_combined); + } else { + g_print ("DKD_PARTITION_TABLE=1\n"); + g_print ("DKD_PARTITION_TABLE_SCHEME=%s\n", + part_get_scheme_name (part_table_get_scheme (partition_table))); } out: + g_free (devpath); + g_free (partition_table_device_file); + if (partition_table != NULL) + part_table_free (partition_table); + if (udev != NULL) + udev_unref (udev); + return 0; } diff --git a/src/partutil.c b/src/partutil.c index 795b896..8b5663c 100644 --- a/src/partutil.c +++ b/src/partutil.c @@ -1,3 +1,5 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + /*************************************************************************** * * part.c : library for reading and writing partition tables - uses @@ -1278,9 +1280,6 @@ part_add_change_partition (char *device_file, guint64 end_sector; guint64 new_start_sector; guint64 new_end_sector; - PartitionTable *p; - PartitionTable *container_p; - int container_entry; PartitionScheme scheme; guint8 mbr_flags = 0; guint8 mbr_part_type = 0; @@ -1301,51 +1300,63 @@ part_add_change_partition (char *device_file, DEBUG ("In part_add_partition: device_file=%s, start=%lld, size=%lld, type=%s", device_file, start, size, type); } - /* first, find the kind of (embedded) partition table the new partition is going to be part of */ - p = part_table_load_from_disk_from_file (device_file); - if (p == NULL) { - DEBUG ("Cannot load partition table from %s", device_file); - goto out; - } + scheme = -1; + if (is_change) { + PartitionTable *p; + PartitionTable *container_p; + int container_entry; - part_table_find (p, start + 512, &container_p, &container_entry); - scheme = part_table_get_scheme (container_p); + /* if changing something, make sure the partition to change actually exists */ + + p = part_table_load_from_disk_from_file (device_file); + if (p == NULL) { + DEBUG ("Cannot load partition table from %s", device_file); + goto out; + } + part_table_find (p, start + 512, &container_p, &container_entry); + scheme = part_table_get_scheme (container_p); + DEBUG ("containing partition table scheme = %d", scheme); + part_table_free (p); - if (is_change) { - /* if changing, make sure there is a partition to change */ if (container_entry < 0) { DEBUG ("Couldn't find partition to change"); goto out; } } else { - /* if adding, make sure there is no partition in the way... */ - if (container_entry >= 0) { - char *part_type; - - /* this might be Apple_Free if we're on PART_TYPE_APPLE */ - part_type = part_table_entry_get_type (p, container_entry); - if (! (p->scheme == PART_TYPE_APPLE && part_type != NULL && (strcmp (part_type, "Apple_Free") == 0))) { - part_table_free (p); - DEBUG ("There is a partition in the way on %s", device_file); - goto out; - } - } - } + PartitionTable *p; + PartitionTable *container_p; + int container_entry; + + /* if adding, try to find the scheme of the partition table.. don't error out if we can't find it */ + p = part_table_load_from_disk_from_file (device_file); + if (p != NULL) { + part_table_find (p, start + 512, &container_p, &container_entry); + scheme = part_table_get_scheme (container_p); + DEBUG ("containing partition table scheme = %d", scheme); + part_table_free (p); + } + } - DEBUG ("containing partition table scheme = %d", scheme); + /* now that we know the partitoning scheme, sanity check type and flags */ + switch (scheme) { + case -1: + /* unknown partition table format; error out if any type, label or flags are given */ + if ((flags != NULL && flags[0] != NULL)) { + DEBUG ("unknown partition table format and flags is not empty"); + goto out; + } - part_table_free (p); - p = NULL; + if (type != NULL && strlen (type) > 0) { + DEBUG ("unknown partition table format and type is not empty"); + goto out; + } - if (!is_change) { - if (type == NULL) { - DEBUG ("No type specified"); - goto out; - } - } + if (label != NULL && strlen (label) > 0) { + DEBUG ("unknown partition table format and label is not empty"); + goto out; + } + break; - /* now that we know the partitoning scheme, sanity check type and flags */ - switch (scheme) { case PART_TYPE_MSDOS: case PART_TYPE_MSDOS_EXTENDED: mbr_flags = 0; @@ -1730,7 +1741,7 @@ part_del_partition (char *device_file, guint64 offset, gboolean poke_kernel) PedDevice *device; PedDisk *disk; PedPartition *part; - PartitionTable *p; + PartitionTable *p; gboolean is_extended; int n; @@ -1749,21 +1760,19 @@ part_del_partition (char *device_file, guint64 offset, gboolean poke_kernel) */ is_extended = FALSE; p = part_table_load_from_disk_from_file (device_file); - if (p == NULL) { - DEBUG ("Cannot load partition table from %s", device_file); - goto out; - } - for (n = 0; n < part_table_get_num_entries (p); n++) { - PartitionTable *nested; - nested = part_table_entry_get_nested (p, n); - if (nested != NULL) { - if (part_table_get_offset (nested) == offset) { - DEBUG ("partition to delete is an extended partition"); - is_extended = TRUE; - } - } - } - part_table_free (p); + if (p != NULL) { + for (n = 0; n < part_table_get_num_entries (p); n++) { + PartitionTable *nested; + nested = part_table_entry_get_nested (p, n); + if (nested != NULL) { + if (part_table_get_offset (nested) == offset) { + DEBUG ("partition to delete is an extended partition"); + is_extended = TRUE; + } + } + } + part_table_free (p); + } device = ped_device_get (device_file); if (device == NULL) { @@ -1791,13 +1800,21 @@ part_del_partition (char *device_file, guint64 offset, gboolean poke_kernel) } DEBUG ("got partition - part->type=%d", part->type); - /* allow only to delete primary, logical and extended partitions */ - if (! ((part->type == PED_PARTITION_NORMAL) || - (part->type == PED_PARTITION_LOGICAL) || - (part->type == PED_PARTITION_EXTENDED))) { - DEBUG ("no data partition at given offset %lld for device %s", offset, device_file); - goto out_ped_disk; - } + + if (part->type & PED_PARTITION_METADATA) { + DEBUG ("refusing to delete a metadata partition"); + goto out_ped_disk; + } + + if (part->type & PED_PARTITION_PROTECTED) { + DEBUG ("refusing to delete a protected partition"); + goto out_ped_disk; + } + + if (part->type & PED_PARTITION_FREESPACE) { + DEBUG ("refusing to delete a protected partition"); + goto out_ped_disk; + } if (ped_disk_delete_partition (disk, part) == 0) { DEBUG ("ped_disk_delete_partition() failed"); diff --git a/tools/devkit-disks.c b/tools/devkit-disks.c index c0508bd..47ebe9f 100644 --- a/tools/devkit-disks.c +++ b/tools/devkit-disks.c @@ -302,18 +302,18 @@ device_removed_signal_handler (DBusGProxy *proxy, const char *object_path, gpoin g_print ("removed: %s\n", object_path); } -#define ATA_SMART_DATA_ATTRIBUTE_STRUCT_TYPE (dbus_g_type_get_struct ("GValueArray", \ - G_TYPE_UINT, \ - G_TYPE_STRING, \ - G_TYPE_UINT, \ - G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, \ - G_TYPE_UCHAR, G_TYPE_BOOLEAN, \ - G_TYPE_UCHAR, G_TYPE_BOOLEAN, \ - G_TYPE_UCHAR, G_TYPE_BOOLEAN, \ - G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, \ - G_TYPE_UINT, G_TYPE_UINT64, \ - dbus_g_type_get_collection ("GArray", G_TYPE_UCHAR), \ - G_TYPE_INVALID)) +#define ATA_SMART_ATTRIBUTE_STRUCT_TYPE (dbus_g_type_get_struct ("GValueArray", \ + G_TYPE_UINT, \ + G_TYPE_STRING, \ + G_TYPE_UINT, \ + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, \ + G_TYPE_UCHAR, G_TYPE_BOOLEAN, \ + G_TYPE_UCHAR, G_TYPE_BOOLEAN, \ + G_TYPE_UCHAR, G_TYPE_BOOLEAN, \ + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, \ + G_TYPE_UINT, G_TYPE_UINT64, \ + dbus_g_type_get_collection ("GArray", G_TYPE_UCHAR), \ + G_TYPE_INVALID)) #define ATA_SMART_HISTORICAL_SMART_DATA_STRUCT_TYPE (dbus_g_type_get_struct ("GValueArray", \ G_TYPE_UINT64, \ @@ -400,9 +400,6 @@ typedef struct char *partition_table_scheme; int partition_table_count; - int partition_table_max_number; - GArray *partition_table_offsets; - GArray *partition_table_sizes; char *luks_holder; @@ -585,19 +582,6 @@ collect_props (const char *key, const GValue *value, DeviceProperties *props) props->partition_table_scheme = g_strdup (g_value_get_string (value)); else if (strcmp (key, "partition-table-count") == 0) props->partition_table_count = g_value_get_int (value); - else if (strcmp (key, "partition-table-max-number") == 0) - props->partition_table_max_number = g_value_get_int (value); - else if (strcmp (key, "partition-table-offsets") == 0) { - GValue dest_value = {0,}; - g_value_init (&dest_value, dbus_g_type_get_collection ("GArray", G_TYPE_UINT64)); - g_value_copy (value, &dest_value); - props->partition_table_offsets = g_value_get_boxed (&dest_value); - } else if (strcmp (key, "partition-table-sizes") == 0) { - GValue dest_value = {0,}; - g_value_init (&dest_value, dbus_g_type_get_collection ("GArray", G_TYPE_UINT64)); - g_value_copy (value, &dest_value); - props->partition_table_sizes = g_value_get_boxed (&dest_value); - } else if (strcmp (key, "luks-holder") == 0) props->luks_holder = g_strdup (g_value_get_boxed (value)); @@ -764,10 +748,6 @@ device_properties_free (DeviceProperties *props) g_free (props->partition_uuid); g_strfreev (props->partition_flags); g_free (props->partition_table_scheme); - if (props->partition_table_offsets != NULL) - g_array_free (props->partition_table_offsets, TRUE); - if (props->partition_table_sizes != NULL) - g_array_free (props->partition_table_sizes, TRUE); g_free (props->luks_holder); g_free (props->luks_cleartext_slave); g_free (props->drive_model); @@ -811,7 +791,7 @@ device_properties_get (DBusGConnection *bus, props = g_new0 (DeviceProperties, 1); g_value_init (&(props->drive_ata_smart_attributes), - dbus_g_type_get_collection ("GPtrArray", ATA_SMART_DATA_ATTRIBUTE_STRUCT_TYPE)); + dbus_g_type_get_collection ("GPtrArray", ATA_SMART_ATTRIBUTE_STRUCT_TYPE)); prop_proxy = dbus_g_proxy_new_for_name (bus, "org.freedesktop.DeviceKit.Disks", @@ -1089,7 +1069,6 @@ do_show_info (const char *object_path) g_print (" partition table:\n"); g_print (" scheme: %s\n", props->partition_table_scheme); g_print (" count: %d\n", props->partition_table_count); - g_print (" max number: %d\n", props->partition_table_max_number); } if (props->device_is_partition) { g_print (" partition:\n"); @@ -1251,7 +1230,7 @@ do_show_info (const char *object_path) gboolean do_highlight; GArray *raw_data; - g_value_init (&elem, ATA_SMART_DATA_ATTRIBUTE_STRUCT_TYPE); + g_value_init (&elem, ATA_SMART_ATTRIBUTE_STRUCT_TYPE); g_value_set_static_boxed (&elem, p->pdata[m]); dbus_g_type_struct_get (&elem,