bug-parted
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Enhancements to parted's partition table printing


From: Colin Watson
Subject: [PATCH] Enhancements to parted's partition table printing
Date: Tue, 22 Nov 2005 20:46:22 +0000
User-agent: Mutt/1.5.9i

At present, the 'parted' command-line tool is really more useful for
interactive use than anything else. The particular deficiency that's
biting me is that there's no really good way to use it to dump out a
list of all the partitions on the system and their properties in a way
that can be read by scripts such as those in the Debian installer. While
it's certainly possible to write small programs using libparted that do
what we need (and indeed we already have a couple of those), these then
require their own packaging in the installer, live CDs, and suchlike,
and I've been thinking recently that it might be better to take the
small step required to make the parted program usable for this purpose.

The following patch implements a few features that I think would help.
It's a strawman patch in that I'm not very attached to the particular
details of the implementation, as long as the output format is stable so
that we don't have to update scripts all the time (the human-readable
output of parted changed not that long ago, breaking one or two scripts
in d-i that were unwisely trying to parse it). Anyway, this patch adds
the following:

  * A -c/--colons option which causes the 'print' command to output
    information about each partition in an easily-parseable
    colon-separated format rather than the default human-friendly style.

  * A new 'print-all' command, which prints information about all
    devices rather than just the first. This is best used in conjunction
    with ...

  * An -f/--first option which automatically selects the first probed
    device rather than making you provide one (scripts in an installer
    can't hardcode any particular device, and since parted can already
    trivially find out what the first device in the PedDevice chain is
    then it might as well expose that); I found it awkward to make the
    command-line syntax work well for 'print-all' without this.

The result of the above is that instead of this:

  # ./parted -s /dev/hda print
  Disk geometry for /dev/hda: 0kB - 165GB
  Disk label type: msdos
  Number  Start   End     Size    Type      File system  Flags
  1       32kB    214MB   214MB   primary
  2       214MB   5585MB  5371MB  primary   ext3
  3       5585MB  165GB   159GB   extended
  5       5585MB  38GB    32GB    logical                lvm
  6       38GB    70GB    32GB    logical                lvm
  7       70GB    70GB    403MB   logical   linux-swap
  8       70GB    103GB   32GB    logical                lvm
  9       103GB   135GB   32GB    logical                lvm
  10      135GB   165GB   30GB    logical                lvm
  # ./parted -s /dev/hdc print
  Disk geometry for /dev/hdc: 0kB - 40GB
  Disk label type: msdos
  Number  Start   End     Size    Type      File system  Flags
  1       32kB    40GB    40GB    extended
  5       65kB    10GB    10GB    logical                lvm
  6       10GB    20GB    10GB    logical                lvm
  7       20GB    30GB    10GB    logical                lvm
  8       30GB    40GB    10GB    logical                lvm

... I can now do this:

  # ./parted -cfs print-all
  /dev/hda1:32kB:214MB:214MB:primary:::
  /dev/hda2:214MB:5585MB:5371MB:primary:ext3::
  /dev/hda3:5585MB:165GB:159GB:extended:::
  /dev/hda5:5585MB:38GB:32GB:logical:::lvm
  /dev/hda6:38GB:70GB:32GB:logical:::lvm
  /dev/hda7:70GB:70GB:403MB:logical:linux-swap::
  /dev/hda8:70GB:103GB:32GB:logical:::lvm
  /dev/hda9:103GB:135GB:32GB:logical:::lvm
  /dev/hda10:135GB:165GB:30GB:logical:::lvm
  /dev/hdc1:32kB:40GB:40GB:extended:::
  /dev/hdc5:65kB:10GB:10GB:logical:::lvm
  /dev/hdc6:10GB:20GB:10GB:logical:::lvm
  /dev/hdc7:20GB:30GB:10GB:logical:::lvm
  /dev/hdc8:30GB:40GB:10GB:logical:::lvm

... which is much easier to parse and I think provides most of the
information we generally need in the Debian installer (though perhaps we
should invent a machine-parseable way to get the geometry and disk label
type too). What do you think?

--- parted-1.6.25.1.orig/parted/ui.h
+++ parted-1.6.25.1/parted/ui.h
@@ -73,6 +73,7 @@
 extern void print_using_dev (PedDevice* dev);
 
 /* in parted.c */
+extern int     opt_colons;
 extern int     opt_script_mode;
 
 extern void print_options_help ();
--- parted-1.6.25.1.orig/parted/parted.c
+++ parted-1.6.25.1/parted/parted.c
@@ -62,6 +62,8 @@
 
 static struct option   options[] = {
        /* name, has-arg, string-return-val, char-return-val */
+       {"colons",      0, NULL, 'c'},
+       {"first",       0, NULL, 'f'},
        {"help",        0, NULL, 'h'},
        {"interactive", 0, NULL, 'i'},
        {"script",      0, NULL, 's'},
@@ -71,6 +73,8 @@
 #endif
 
 static char*   options_help [][2] = {
+       {"colons",      N_("use colon-separated print output style")},
+       {"first",       N_("automatically select first probed device")},
        {"help",        N_("displays this help message")},
        {"interactive", N_("where necessary, prompts for user intervention")},
        {"script",      N_("never prompts for user intervention")},
@@ -78,6 +82,8 @@
        {NULL,          NULL}
 };
 
+int    opt_colons = 0;
+int    opt_first_device = 0;
 int    opt_script_mode;
 
 static char* number_msg = N_(
@@ -883,6 +889,8 @@
                if (ped_partition_get_flag (part, flag)) {
                        if (first_flag)
                                first_flag = 0;
+                       else if (opt_colons)
+                               printf (" ");
                        else
                                printf (", ");
                        printf (_(ped_partition_flag_get_name (flag)));
@@ -956,6 +964,8 @@
        char*           start;
        char*           end;
        char*           size;
+       const char*     partition_type;
+       const char*     fs_type;
 
        disk = ped_disk_new (*dev);
        if (!disk)
@@ -978,45 +988,51 @@
                return status;
        }
 
-       start = ped_unit_format (*dev,0 );
-       end = ped_unit_format (*dev, (*dev)->length - 1);
-       printf (_("Disk geometry for %s: %s - %s\n"), (*dev)->path, start, end);
-       ped_free (start);
-       ped_free (end);
-
-       if (ped_unit_get_default () == PED_UNIT_CHS
-           || ped_unit_get_default () == PED_UNIT_CYLINDER) {
-               PedCHSGeometry* chs = &(*dev)->bios_geom;
-               char* cyl_size = ped_unit_format_custom (*dev,
-                                       chs->heads * chs->sectors,
-                                       PED_UNIT_KILOBYTE);
-               printf (_("BIOS cylinder,head,sector geometry: %d,%d,%d.  "
-                         "Each cylinder is %s.\n"),
-                       chs->cylinders, chs->heads, chs->sectors, cyl_size);
-               ped_free (cyl_size);
-       }
+       if (!opt_colons) {
+               start = ped_unit_format (*dev,0 );
+               end = ped_unit_format (*dev, (*dev)->length - 1);
+               printf (_("Disk geometry for %s: %s - %s\n"),
+                       (*dev)->path, start, end);
+               ped_free (start);
+               ped_free (end);
+
+               if (ped_unit_get_default () == PED_UNIT_CHS
+                   || ped_unit_get_default () == PED_UNIT_CYLINDER) {
+                       PedCHSGeometry* chs = &(*dev)->bios_geom;
+                       char* cyl_size = ped_unit_format_custom (*dev,
+                                               chs->heads * chs->sectors,
+                                               PED_UNIT_KILOBYTE);
+                       printf (_("BIOS cylinder,head,sector geometry: 
%d,%d,%d.  "
+                                 "Each cylinder is %s.\n"),
+                               chs->cylinders, chs->heads, chs->sectors,
+                               cyl_size);
+                       ped_free (cyl_size);
+               }
 
-       printf (_("Disk label type: %s\n"), disk->type->name);
+               printf (_("Disk label type: %s\n"), disk->type->name);
+       }
 
        has_extended = ped_disk_type_check_feature (disk->type,
                                         PED_DISK_TYPE_EXTENDED);
        has_name = ped_disk_type_check_feature (disk->type,
                                         PED_DISK_TYPE_PARTITION_NAME);
 
-       if (ped_unit_get_default() == PED_UNIT_CHS) {
-               printf ("%-7s %-11s %-11s ", _("Number"), _("Start"),
-                       _("End"));
-       } else  {
-               printf ("%-7s %-7s %-7s %-7s ", _("Number"), _("Start"),
-                       _("End"), _("Size"));
-       }
-       if (has_extended)
-               printf ("%-9s ", _("Type"));
-       printf ("%-12s ", _("File system"));
-       if (has_name)
-               printf ("%-21s ", _("Name"));
-       printf (_("Flags"));
-       printf ("\n");
+       if (!opt_colons) {
+               if (ped_unit_get_default() == PED_UNIT_CHS) {
+                       printf ("%-7s %-11s %-11s ", _("Number"), _("Start"),
+                               _("End"));
+               } else  {
+                       printf ("%-7s %-7s %-7s %-7s ", _("Number"), _("Start"),
+                               _("End"), _("Size"));
+               }
+               if (has_extended)
+                       printf ("%-9s ", _("Type"));
+               printf ("%-12s ", _("File system"));
+               if (has_name)
+                       printf ("%-21s ", _("Name"));
+               printf (_("Flags"));
+               printf ("\n");
+       }
 
        for (part = ped_disk_next_partition (disk, NULL); part;
             part = ped_disk_next_partition (disk, part)) {
@@ -1024,27 +1040,61 @@
                if (!ped_partition_is_active (part))
                        continue;
 
-               printf ("%-7d ", part->num);
+               /* The --colons output is parsed by scripts. Please make
+                * sure only ever to extend the format by adding new fields
+                * to the end of each line; don't insert fields in the
+                * middle!
+                */
+               if (opt_colons)
+                       /* Print the path rather than the number, since we
+                        * don't print the header with the disk path in
+                        * --colons mode.
+                        */
+                       printf ("%s:", ped_partition_get_path (part));
+               else
+                       printf ("%-7d ", part->num);
 
                start = ped_unit_format (*dev, part->geom.start);
                end = ped_unit_format (*dev, part->geom.end);
                size = ped_unit_format (*dev, part->geom.length);
-               if (ped_unit_get_default() == PED_UNIT_CHS)
-                       printf ("%-11s %-11s ", start, end);
-               else
-                       printf ("%-7s %-7s %-7s ", start, end, size);
+               if (ped_unit_get_default() == PED_UNIT_CHS) {
+                       if (opt_colons)
+                               printf ("%s:%s::", start, end);
+                       else
+                               printf ("%-11s %-11s ", start, end);
+               } else {
+                       if (opt_colons)
+                               printf ("%s:%s:%s:", start, end, size);
+                       else
+                               printf ("%-7s %-7s %-7s ", start, end, size);
+               }
                ped_free (start);
                ped_free (end);
                ped_free (size);
 
-               if (has_extended)
-                       printf ("%-9s ",
-                               _(ped_partition_type_get_name (part->type)));
-
-               printf ("%-12s ", part->fs_type ? part->fs_type->name : "");
+               if (has_extended) {
+                       partition_type =
+                               _(ped_partition_type_get_name (part->type));
+                       if (opt_colons)
+                               printf ("%s:", partition_type);
+                       else
+                               printf ("%-9s ", partition_type);
+               } else if (opt_colons)
+                       printf (":");
+
+               fs_type = part->fs_type ? part->fs_type->name : "";
+               if (opt_colons)
+                       printf ("%s:", fs_type);
+               else
+                       printf ("%-12s ", fs_type);
 
-               if (has_name)
-                       printf ("%-21s ", ped_partition_get_name (part));
+               if (has_name) {
+                       if (opt_colons)
+                               printf ("%s:", ped_partition_get_name (part));
+                       else
+                               printf ("%-21s ", ped_partition_get_name 
(part));
+               } else if (opt_colons)
+                       printf (":");
 
                partition_print_flags (part);
                printf ("\n");
@@ -1060,6 +1110,27 @@
 }
 
 static int
+do_print_all (PedDevice** dev)
+{
+       int             first_device;
+       PedDevice       *walk_dev;
+
+       first_device = 0;
+       walk_dev = *dev;
+       while (walk_dev) {
+               if (do_print (&walk_dev))
+                       return 1;
+               if (first_device)
+                       first_device = 0;
+               else if (!opt_colons)
+                       printf ("\n");
+               walk_dev = ped_device_get_next (walk_dev);
+       }
+
+       return 0;
+}
+
+static int
 do_quit (PedDevice** dev)
 {
        _done (*dev);
@@ -1643,6 +1714,17 @@
 NULL)));
        
        command_register (commands, command_create (
+               str_list_create_unique ("print-all", _("print-all"), NULL),
+               do_print_all,
+               str_list_create (
+_("print-all                     display partition tables of all devices"),
+NULL),
+               str_list_create (
+_("print-all displays the entire partition tables of all devices, in the\n"
+  "same format used by print.\n"),
+NULL)));
+
+       command_register (commands, command_create (
                str_list_create_unique ("quit", _("quit"), NULL),
                do_quit,
                str_list_create (
@@ -1738,15 +1820,17 @@
        while (1)
        {
 #ifdef HAVE_GETOPT_H
-               opt = getopt_long (*argc_ptr, *argv_ptr, "hisv",
+               opt = getopt_long (*argc_ptr, *argv_ptr, "cfhisv",
                                   options, NULL);
 #else
-               opt = getopt (*argc_ptr, *argv_ptr, "hisv");
+               opt = getopt (*argc_ptr, *argv_ptr, "cfhisv");
 #endif
                if (opt == -1)
                        break;
 
                switch (opt) {
+                       case 'c': opt_colons = 1; break;
+                       case 'f': opt_first_device = 1; break;
                        case 'h': help_msg (); break;
                        case 'i': opt_script_mode = 0; break;
                        case 's': opt_script_mode = 1; break;
@@ -1768,7 +1852,7 @@
        PedDevice*      dev;
 
        /* specified on comand line? */
-       if (*argc_ptr) {
+       if (*argc_ptr && !opt_first_device) {
                dev = ped_device_get ((*argv_ptr) [0]);
                if (!dev)
                        return NULL;
--- parted-1.6.25.1.orig/parted/ui.c
+++ parted-1.6.25.1/parted/ui.c
@@ -75,6 +75,7 @@
 
 static char* usage_msg = N_(
 "Usage: parted [OPTION]... [DEVICE [COMMAND [PARAMETERS]...]...]\n"
+"       parted -f [OPTION]... [COMMAND [PARAMETERS]...]\n"
 "Apply COMMANDs with PARAMETERS to DEVICE.  If no COMMAND(s) are given, runs 
in\n"
 "interactive mode.\n");
 

Thanks,

-- 
Colin Watson                                       address@hidden

Attachment: signature.asc
Description: Digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]