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
# 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"
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)
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)
{
}
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))
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;
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);
PROP_PARTITION_TABLE_SCHEME,
PROP_PARTITION_TABLE_COUNT,
- PROP_PARTITION_TABLE_MAX_NUMBER,
- PROP_PARTITION_TABLE_OFFSETS,
- PROP_PARTITION_TABLE_SIZES,
PROP_LUKS_HOLDER,
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)
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,
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 ();
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);
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;
}
/* ---------------------------------------------------------------------------------------------------- */
-/* 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;
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);
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);
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.
* - device_is_drive
* - device_is_media_available
* - device_is_partition
+ * - device_is_partition_table
* - slaves_objpath
* - holders_objpath
*
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;
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)
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);
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;
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);
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;
}
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);
is TRUE.
</doc:para></doc:description></doc:doc>
</property>
- <property name="partition-table-max-number" type="i" access="read">
- <doc:doc><doc:description><doc:para>
- The maximum value for
- <doc:ref type="property" to="Device:partition-number">partition-number</doc:ref>
- of the enclosed partitions (partitions may not be sequentially numbered).
- This property is only valid if
- <doc:ref type="property" to="Device:device-is-partition-table">device-is-partition-table</doc:ref>
- is TRUE.
- </doc:para></doc:description></doc:doc>
- </property>
- <property name="partition-table-offsets" type="at" access="read">
- <doc:doc><doc:description><doc:para>
- An array of size
- <doc:ref type="property" to="Device:partition-table-max-number">partition-table-max-number</doc:ref>
- that contains the offsets (in bytes) of each partition.
- The property
- <doc:ref type="property" to="Device:partition-number">partition-number</doc:ref>
- on enclosed partitions can be used as an index in this array.
- This property is only valid if
- <doc:ref type="property" to="Device:device-is-partition-table">device-is-partition-table</doc:ref>
- is TRUE.
- </doc:para></doc:description></doc:doc>
- </property>
- <property name="partition-table-sizes" type="at" access="read">
- <doc:doc><doc:description><doc:para>
- An array of size
- <doc:ref type="property" to="Device:partition-table-max-number">partition-table-max-number</doc:ref>
- that contains the size (in bytes) of each partition.
- The property
- <doc:ref type="property" to="Device:partition-number">partition-number</doc:ref>
- on enclosed partitions can be used as an index in this array.
- This property is only valid if
- <doc:ref type="property" to="Device:device-is-partition-table">device-is-partition-table</doc:ref>
- is TRUE.
- </doc:para></doc:description></doc:doc>
- </property>
<property name="drive-vendor" type="s" access="read">
<doc:doc><doc:description><doc:para>
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 David Zeuthen <david@fubar.dk>
+ *
+ * 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 <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
+#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
+#include <libudev.h>
+
#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)
{
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;
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)
/* 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;
}
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;
}
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;
}
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
/***************************************************************************
*
* part.c : library for reading and writing partition tables - uses
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;
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;
PedDevice *device;
PedDisk *disk;
PedPartition *part;
- PartitionTable *p;
+ PartitionTable *p;
gboolean is_extended;
int n;
*/
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) {
}
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");
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, \
char *partition_table_scheme;
int partition_table_count;
- int partition_table_max_number;
- GArray *partition_table_offsets;
- GArray *partition_table_sizes;
char *luks_holder;
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));
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);
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",
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");
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,