[Parted-commits] GNU Parted Official Repository: Changes to 'master'

Jim Meyering meyering at alioth.debian.org
Thu Dec 10 15:45:40 UTC 2009


 NEWS                   |   31 +++++++++++-
 bootstrap.conf         |    1 
 doc/C/parted.8         |   20 +++++++
 doc/parted.texi        |    5 +
 include/parted/disk.h  |   33 +++++++++++++
 libparted/disk.c       |  124 +++++++++++++++++++++++++++++++++++++++++++++++++
 libparted/labels/dos.c |   70 +++++++++++++++++++++++++--
 libparted/labels/sun.c |   57 ++++++++++++++++++++--
 parted/parted.c        |   57 ++++++++++++++++++++--
 po/POTFILES.in         |    1 
 10 files changed, 381 insertions(+), 18 deletions(-)

New commits:
commit f9ca93f2ba43a4cd794b377d59e0a321188bf066
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Dec 10 11:33:58 2009 +0100

    ui: add --align command-line option to specify mkpart alignment
    
    The new --align command-line option can have the following values:
    none:     Use the minimum alignment allowed by the disk type
    cylinder: Align partitions to cylinders (the default)
    minimal: Use minimum alignment as given by the disk topology information
    optimal: Use optimum alignment as given by the disk topology information
    
    Note the "minimal" and "optimal" values will use layout information
    provided by the disk to align the logical partition table addresses
    to actual physical blocks on the disks.  The "minimal" value is the
    minimum aligment needed to align the partition properly to physical
    blocks, which avoids performance degradation.  Whereas the "optimum"
    alignment align's to a multiple of the physical block size in a way
    that guarantees optimal performance.
    
    The "minimal" and "optimal" values are useful only when parted is
    compiled with libblkid >= 2.17 and running on a kernel >= 2.6.31,
    otherwise they are equivalent to --align=none.
    
    * parted/parted.c (ALIGNMENT_ enum values): New enum.
    (options, options_help): Add --align option.
    (align_args, align_types, alignment): New global variables.
    (do_mkpart): Honor aligment variable.
    (_parse_options): handle --align option.
    * bootstrap.conf (gnulib_modules): Add argmatch.
    * NEWS: Mention the new --align option.
    * doc/parted.texi: Document --align option.
    * doc/C/parted.8: Likewise.

diff --git a/NEWS b/NEWS
index 500e060..cd67678 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,21 @@ GNU parted NEWS                                    -*- outline -*-
 
 ** New features
 
+  new --align=<align> commandline option which can have the following values:
+  none:     Use the minimum alignment allowed by the disk type
+  cylinder: Align partitions to cylinders (the default)
+  minimal:  Use minimum alignment as given by the disk topology information
+  optimal:  Use optimum alignment as given by the disk topology information
+  The minimal and optimal  values will use layout information provided by the
+  disk to align the logical partition table addresses to actual physical
+  blocks on the disks. The mininal value uses the minimum aligment needed to
+  align the partition properly to physical blocks, which avoids performance
+  degradation. Where as the optimal value uses a multiple of the physical
+  block size in a way that guarantees optimal performance.
+  The min and opt values will only work when compiled with
+  libblkid >= 2.17 and running on a kernel >= 2.6.31, otherwise they will
+  behave as the none --align value.
+
   libparted: new functions to set per disk (instead of per partition) flags:
   ped_disk_set_flag()
   ped_disk_get_flag()
diff --git a/bootstrap.conf b/bootstrap.conf
index 09870cd..b382bd7 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -26,6 +26,7 @@ avoided_gnulib_modules='
 gnulib_modules="
 	$avoided_gnulib_modules
 	alloca announce-gen assert
+	argmatch
 	calloc config-h configmake
 	canonicalize-lgpl
 	close
diff --git a/doc/C/parted.8 b/doc/C/parted.8
index 9909ba8..2a8992e 100644
--- a/doc/C/parted.8
+++ b/doc/C/parted.8
@@ -30,6 +30,26 @@ never prompts for user intervention
 .TP
 .B -v, --version
 displays the version
+.TP
+.B -a \fIalignment-type\fP, --align \fIalignment-type\fP
+Set alignment for newly created partitions, valid alignment types are:
+.RS
+.IP none
+Use the minimum alignment allowed by the disk type.
+.IP cylinder
+Align partitions to cylinders.
+.IP minimal
+Use minimum alignment as given by the disk topology information. This and
+the opt value will use layout information provided by the disk to align the
+logical partition table addresses to actual physical blocks on the disks.
+The min value is the minimum aligment needed to align the partition properly to
+physical blocks, which avoids performance degradation.
+.IP optimal
+Use optimum alignment as given by the disk topology information. This
+aligns to a multiple of the physical block size in a way that guarantees
+optimal performance.
+.RE
+
 .SH COMMANDS
 .TP
 .B [device]
diff --git a/doc/parted.texi b/doc/parted.texi
index a1d794d..5704520 100644
--- a/doc/parted.texi
+++ b/doc/parted.texi
@@ -496,6 +496,11 @@ display a help message
 @itemx --script
 never prompt the user
 
+ at item -a alignment-type
+ at itemx --align alignment-type
+Set alignment for newly created partitions, valid alignment types are:
+none, cylinder, minimal and optimal.
+
 @item -v
 @itemx --version
 display the version
diff --git a/parted/parted.c b/parted/parted.c
index 099bc94..dba376d 100644
--- a/parted/parted.c
+++ b/parted/parted.c
@@ -19,6 +19,7 @@
 #include <config.h>
 #include <stdbool.h>
 
+#include "argmatch.h"
 #include "closeout.h"
 #include "configmake.h"
 #include "version-etc.h"
@@ -74,6 +75,31 @@ enum
   PRETEND_INPUT_TTY = CHAR_MAX + 1,
 };
 
+enum
+{
+        ALIGNMENT_NONE = 2,
+        ALIGNMENT_CYLINDER,
+        ALIGNMENT_MINIMAL,
+        ALIGNMENT_OPTIMAL
+};
+
+static char const *const align_args[] =
+{
+  "none",
+  "cylinder",
+  "minimal",
+  "optimal",
+  NULL
+};
+
+static int const align_types[] =
+{
+  ALIGNMENT_NONE,
+  ALIGNMENT_CYLINDER,
+  ALIGNMENT_MINIMAL,
+  ALIGNMENT_OPTIMAL
+};
+ARGMATCH_VERIFY (align_args, align_types);
 
 typedef struct {
         time_t  last_update;
@@ -87,6 +113,7 @@ static struct option const options[] = {
         {"machine",     0, NULL, 'm'},
         {"script",      0, NULL, 's'},
         {"version",     0, NULL, 'v'},
+        {"align",       required_argument, NULL, 'a'},
         {"-pretend-input-tty", 0, NULL, PRETEND_INPUT_TTY},
         {NULL,          0, NULL, 0}
 };
@@ -97,6 +124,7 @@ static const char *const options_help [][2] = {
         {"machine",     N_("displays machine parseable output")},
         {"script",      N_("never prompts for user intervention")},
         {"version",     N_("displays the version")},
+        {"align=[none|cyl|min|opt]", N_("alignment for new partitions")},
         {NULL,          NULL}
 };
 
@@ -105,6 +133,7 @@ int     pretend_input_tty = 0;
 int     opt_machine_mode = 0;
 int     disk_is_modified = 0;
 int     is_toggle_mode = 0;
+int     alignment = ALIGNMENT_CYLINDER;
 
 static const char* number_msg = N_(
 "NUMBER is the partition number used by Linux.  On MS-DOS disk labels, the "
@@ -587,7 +616,7 @@ print_options_help ()
         int             i;
 
         for (i=0; options_help [i][0]; i++) {
-                printf ("  -%c, --%-23.23s %s\n",
+                printf ("  -%c, --%-25.25s %s\n",
                         options_help [i][0][0],
                         options_help [i][0],
                         _(options_help [i][1]));
@@ -719,6 +748,11 @@ do_mkpart (PedDevice** dev)
         if (!disk)
                 goto error;
 
+        if (ped_disk_is_flag_available(disk, PED_DISK_CYLINDER_ALIGNMENT))
+                if (!ped_disk_set_flag(disk, PED_DISK_CYLINDER_ALIGNMENT,
+                                       alignment == ALIGNMENT_CYLINDER))
+                        goto error_destroy_disk;
+
         if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) {
                 part_type = PED_PARTITION_NORMAL;
         } else {
@@ -771,7 +805,14 @@ do_mkpart (PedDevice** dev)
                         range_end);
         PED_ASSERT (user_constraint != NULL, return 0);
 
-        dev_constraint = ped_device_get_constraint (*dev);
+        if (alignment == ALIGNMENT_OPTIMAL)
+                dev_constraint =
+                        ped_device_get_optimal_aligned_constraint(*dev);
+        else if (alignment == ALIGNMENT_MINIMAL)
+                dev_constraint =
+                        ped_device_get_minimal_aligned_constraint(*dev);
+        else
+                dev_constraint = ped_device_get_constraint(*dev);
         PED_ASSERT (dev_constraint != NULL, return 0);
 
         final_constraint = ped_constraint_intersect (user_constraint,
@@ -2451,7 +2492,7 @@ int     opt, help = 0, list = 0, version = 0, wrong = 0;
 
 while (1)
 {
-        opt = getopt_long (*argc_ptr, *argv_ptr, "hlmsv",
+        opt = getopt_long (*argc_ptr, *argv_ptr, "hlmsva:",
                            options, NULL);
         if (opt == -1)
                 break;
@@ -2462,16 +2503,22 @@ while (1)
                 case 'm': opt_machine_mode = 1; break;
                 case 's': opt_script_mode = 1; break;
                 case 'v': version = 1; break;
+                case 'a':
+                  alignment = XARGMATCH ("--align", optarg,
+                                         align_args, align_types);
+                  break;
                 case PRETEND_INPUT_TTY:
                   pretend_input_tty = 1;
                   break;
-                default:  wrong = 1; break;
+                default:
+                  wrong = 1;
+                  break;
         }
 }
 
 if (wrong == 1) {
         fprintf (stderr,
-                 _("Usage: %s [-hlmsv] [DEVICE [COMMAND [PARAMETERS]]...]\n"),
+                 _("Usage: %s [-hlmsv] [-a<align>] [DEVICE [COMMAND [PARAMETERS]]...]\n"),
                  program_name);
         return 0;
 }
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 203252e..d1fcbdd 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -5,6 +5,7 @@
 # list of files containing translatable strings
 
 # lib
+lib/argmatch.c
 lib/closeout.c
 lib/error.c
 lib/getopt.c

commit 787759a3109c600199a34e167f10035d78f4c981
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Dec 10 11:34:00 2009 +0100

    NEWS: update with libblkid and kernel requirements for alignment funcs
    
    * NEWS: Change the note for the align-check command to also reference
    libblkid, add a note to the libparted alignment functions NEWS entry
    about libblkid and kernel requirements.

diff --git a/NEWS b/NEWS
index c0b29cc..500e060 100644
--- a/NEWS
+++ b/NEWS
@@ -26,8 +26,7 @@ GNU parted NEWS                                    -*- outline -*-
   of partition N is TYPE(minimal|optimal)-aligned for the disk.  E.g.,
       parted -s /dev/sda align-check min 1 && echo partition 1 is min-aligned
       parted -s /dev/sda align-check opt 2 && echo partition 2 is opt-aligned
-  This is useful only on kernels for which Parted is able to determine
-  a disk's alignment characteristics.
+  The same libblkid and kernel version requirements apply as for --align
 
   Add functions to libparted to get minimal and optimal alignment
   information from devices:
@@ -35,6 +34,7 @@ GNU parted NEWS                                    -*- outline -*-
   ped_device_get_optimal_aligned_constraint()
   ped_device_get_minimum_alignment()
   ped_device_get_optimum_alignment()
+  The same libblkid and kernel version requirements apply as for --align
 
   Add ped_disk_get_partition_alignment() function to libparted to get
   information about alignment enforced by the disk type.

commit d566cac545f5d98c2ba8f5c29680f57e4b2abcd5
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Dec 10 11:33:57 2009 +0100

    NEWS: Add new disk flag functions to NEWS
    
    * NEWS: Add new disk flag functions.

diff --git a/NEWS b/NEWS
index 9a0ac2c..c0b29cc 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,18 @@ GNU parted NEWS                                    -*- outline -*-
 
 ** New features
 
+  libparted: new functions to set per disk (instead of per partition) flags:
+  ped_disk_set_flag()
+  ped_disk_get_flag()
+  ped_disk_is_flag_available()
+  ped_disk_flag_get_name()
+  ped_disk_flag_get_by_name()
+  ped_disk_flag_next()
+
+  libparted: new per disk flag: PED_DISK_CYLINDER_ALIGNMENT. This flag
+  (which defaults to true) controls if disk types for which cylinder alignment
+  is optional do cylinder alignment when a new partition gets added.
+
   libparted: new functions to return per-partition-table-type limits:
     - ped_disk_max_partition_start_sector: Return the largest representable
     start sector number for a given "disk".

commit 723ea23c5df68cbe67d1f518ef484f4c77f516fa
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Dec 9 15:38:01 2009 +0100

    msdos, sun: implement disk flag operations
    
    * libparted/labels/dos.c (DosDiskData): New struct.
    * libparted/labels/dos.c (msdos_alloc, msdos_duplicate, msdos_free):
    Handle per disk DosDiskData.
    * libparted/labels/dos.c (msdos_disk_set_flag, msdos_disk_get_flag,
    msdos_disk_is_flag_available): New functions.
    * libparted/labels/sun.c (sun_disk_set_flag, sun_disk_get_flag,
    sun_disk_is_flag_available): New functions.

diff --git a/libparted/labels/dos.c b/libparted/labels/dos.c
index f1ccb0a..ea8fc0b 100644
--- a/libparted/labels/dos.c
+++ b/libparted/labels/dos.c
@@ -143,6 +143,10 @@ typedef struct {
 } OrigState;
 
 typedef struct {
+        int             cylinder_alignment;
+} DosDiskData;
+
+typedef struct {
 	unsigned char	system;
 	int		boot;
 	int		hidden;
@@ -227,8 +231,16 @@ msdos_alloc (const PedDevice* dev)
 	PED_ASSERT (dev != NULL, return NULL);
 
 	disk = _ped_disk_alloc ((PedDevice*)dev, &msdos_disk_type);
-	if (disk)
-		disk->disk_specific = NULL;
+        if (disk) {
+		DosDiskData *disk_specific = ped_malloc(sizeof *disk_specific);
+                if (!disk_specific) {
+                        free (disk);
+                        return NULL;
+                }
+                disk_specific->cylinder_alignment = 1;
+                disk->disk_specific = disk_specific;
+        }
+
 	return disk;
 }
 
@@ -240,7 +252,10 @@ msdos_duplicate (const PedDisk* disk)
 	new_disk = ped_disk_new_fresh (disk->dev, &msdos_disk_type);
 	if (!new_disk)
 		return NULL;
-	new_disk->disk_specific = NULL;
+
+        memcpy(new_disk->disk_specific, disk->disk_specific,
+               sizeof(DosDiskData));
+
 	return new_disk;
 }
 
@@ -249,7 +264,45 @@ msdos_free (PedDisk* disk)
 {
 	PED_ASSERT (disk != NULL, return);
 
+	DosDiskData *disk_specific = disk->disk_specific;
 	_ped_disk_free (disk);
+	free(disk_specific);
+}
+
+static int
+msdos_disk_set_flag (PedDisk *disk, PedDiskFlag flag, int state)
+{
+        DosDiskData *disk_specific = disk->disk_specific;
+        switch (flag) {
+        case PED_DISK_CYLINDER_ALIGNMENT:
+                disk_specific->cylinder_alignment = !!state;
+                return 1;
+        default:
+                return 0;
+        }
+}
+
+static int
+msdos_disk_get_flag (const PedDisk *disk, PedDiskFlag flag)
+{
+        DosDiskData *disk_specific = disk->disk_specific;
+        switch (flag) {
+        case PED_DISK_CYLINDER_ALIGNMENT:
+                return disk_specific->cylinder_alignment;
+        default:
+                return 0;
+        }
+}
+
+static int
+msdos_disk_is_flag_available (const PedDisk *disk, PedDiskFlag flag)
+{
+        switch (flag) {
+        case PED_DISK_CYLINDER_ALIGNMENT:
+               return 1;
+        default:
+               return 0;
+        }
 }
 
 #ifndef DISCOVER_ONLY
@@ -1974,10 +2027,11 @@ msdos_partition_align (PedPartition* part, const PedConstraint* constraint)
 	PedCHSGeometry	bios_geom;
 	DosPartitionData* dos_data;
 
- 	PED_ASSERT (part != NULL, return 0);
+	PED_ASSERT (part != NULL, return 0);
 	PED_ASSERT (part->disk_specific != NULL, return 0);
 
 	dos_data = part->disk_specific;
+
 	if (dos_data->system == PARTITION_LDM && dos_data->orig) {
 		PedGeometry *orig_geom = &dos_data->orig->geom;
 
@@ -1997,7 +2051,9 @@ msdos_partition_align (PedPartition* part, const PedConstraint* constraint)
 
 	partition_probe_bios_geometry (part, &bios_geom);
 
-	if (_align (part, &bios_geom, constraint))
+	DosDiskData *disk_specific = part->disk->disk_specific;
+	if (disk_specific->cylinder_alignment
+	    && _align(part, &bios_geom, constraint))
 		return 1;
 	if (_align_no_geom (part, constraint))
 		return 1;
@@ -2281,6 +2337,10 @@ static PedDiskOps msdos_disk_ops = {
 	clobber:		NULL_IF_DISCOVER_ONLY (msdos_clobber),
 	write:			NULL_IF_DISCOVER_ONLY (msdos_write),
 
+	disk_set_flag:          msdos_disk_set_flag,
+	disk_get_flag:          msdos_disk_get_flag,
+	disk_is_flag_available: msdos_disk_is_flag_available,
+
 	partition_set_name:	NULL,
 	partition_get_name:	NULL,
 
diff --git a/libparted/labels/sun.c b/libparted/labels/sun.c
index 1909cc7..1622433 100644
--- a/libparted/labels/sun.c
+++ b/libparted/labels/sun.c
@@ -96,6 +96,7 @@ struct _SunPartitionData {
 struct _SunDiskData {
 	PedSector		length; /* This is based on cyl - alt-cyl */
 	SunRawLabel		raw_label;
+	int                     cylinder_alignment;
 };
 
 static PedDiskType sun_disk_type;
@@ -196,6 +197,7 @@ sun_alloc (const PedDevice* dev)
 	PED_ASSERT (bios_geom->cylinders == (PedSector) (dev->length / cyl_size),
                     return NULL);
 	sun_specific->length = ped_round_down_to (dev->length, cyl_size);
+        sun_specific->cylinder_alignment = 1;
 
 	label = &sun_specific->raw_label;
 	memset(label, 0, sizeof(SunRawLabel));
@@ -258,6 +260,42 @@ sun_free (PedDisk *disk)
 }
 
 static int
+sun_disk_set_flag (PedDisk *disk, PedDiskFlag flag, int state)
+{
+        SunDiskData *disk_specific = disk->disk_specific;
+        switch (flag) {
+        case PED_DISK_CYLINDER_ALIGNMENT:
+                disk_specific->cylinder_alignment = !!state;
+                return 1;
+        default:
+                return 0;
+        }
+}
+
+static int
+sun_disk_get_flag (const PedDisk *disk, PedDiskFlag flag)
+{
+        SunDiskData *disk_specific = disk->disk_specific;
+        switch (flag) {
+        case PED_DISK_CYLINDER_ALIGNMENT:
+                return disk_specific->cylinder_alignment;
+        default:
+                return 0;
+        }
+}
+
+static int
+sun_disk_is_flag_available (const PedDisk *disk, PedDiskFlag flag)
+{
+        switch (flag) {
+        case PED_DISK_CYLINDER_ALIGNMENT:
+               return 1;
+        default:
+               return 0;
+        }
+}
+
+static int
 _check_geometry_sanity (PedDisk* disk, SunRawLabel* label)
 {
 	PedDevice*	dev = disk->dev;
@@ -768,12 +806,15 @@ sun_partition_align (PedPartition* part, const PedConstraint* constraint)
 {
         PED_ASSERT (part != NULL, return 0);
 
-	if (_ped_partition_attempt_align (part, constraint,
-					  _get_strict_constraint (part->disk)))
-	       	return 1;
-	if (_ped_partition_attempt_align (part, constraint,
-					  _get_lax_constraint (part->disk)))
-	       	return 1;
+        SunDiskData *disk_specific = part->disk->disk_specific;
+
+        if (disk_specific->cylinder_alignment &&
+            _ped_partition_attempt_align (part, constraint,
+                                          _get_strict_constraint (part->disk)))
+                return 1;
+        if (_ped_partition_attempt_align (part, constraint,
+                                          _get_lax_constraint (part->disk)))
+                return 1;
 
 #ifndef DISCOVER_ONLY
 	ped_exception_throw (
@@ -882,6 +923,10 @@ static PedDiskOps sun_disk_ops = {
 	clobber:		NULL_IF_DISCOVER_ONLY (sun_clobber),
 	write:			NULL_IF_DISCOVER_ONLY (sun_write),
 
+	disk_set_flag:          sun_disk_set_flag,
+	disk_get_flag:          sun_disk_get_flag,
+	disk_is_flag_available: sun_disk_is_flag_available,
+
 	get_partition_alignment: sun_get_partition_alignment,
 
 	partition_set_name:		NULL,

commit 60e36b587b3f16ea09242aaf7235866493cb4e96
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Dec 9 15:38:00 2009 +0100

    libparted: add disk flag functions and PED_DISK_CYLINDER_ALIGNMENT flag
    
    Sometimes we want to be able to set flags at the disk level rather then
    at the parition level, to influence how new partitions will be created
    for example.  This patch adds functions to do this (modelled after the
    partition flag functions), and adds a PED_DISK_CYLINDER_ALIGNMENT flag.
    
    This flag (which defaults to true) controls if disk types for which
    cylinder alignment is optional do cylinder alignment when a new
    partition gets added. This flag is available for msdos and sun
    disklabels (for sun labels it only controls the aligning of the end of
    the partition).
    * include/parted/disk.h (PedDiskFlag): New type
    * include/parted/disk.h (ped_disk_set_flag, ped_disk_get_flag,
    ped_disk_is_flag_available): new functions and PedDiskOps members
    * include/parted/disk.h (ped_disk_flag_get_name,
    ped_disk_flag_get_by_name, ped_disk_flag_next): new functions
    * libparted/disk.c (ped_disk_set_flag, ped_disk_get_flag,
    ped_disk_is_flag_available, ped_disk_flag_get_name,
    ped_disk_flag_get_by_name, ped_disk_flag_next): new functions

diff --git a/include/parted/disk.h b/include/parted/disk.h
index cb5d179..eb8e37b 100644
--- a/include/parted/disk.h
+++ b/include/parted/disk.h
@@ -27,6 +27,20 @@
 #define PED_DISK_H_INCLUDED
 
 /**
+ * Disk flags
+ */
+enum _PedDiskFlag {
+        /* This flag (which defaults to true) controls if disk types for
+           which cylinder alignment is optional do cylinder alignment when a
+           new partition gets added.
+           This flag is available for msdos and sun disklabels (for sun labels
+           it only controls the aligning of the end of the partition) */
+        PED_DISK_CYLINDER_ALIGNMENT=1,
+};
+#define PED_DISK_FIRST_FLAG             PED_DISK_CYLINDER_ALIGNMENT
+#define PED_DISK_LAST_FLAG              PED_DISK_CYLINDER_ALIGNMENT
+
+/**
  * Partition types
  */
 enum _PedPartitionType {
@@ -71,6 +85,7 @@ struct _PedDiskOps;
 struct _PedDiskType;
 struct _PedDiskArchOps;
 
+typedef enum _PedDiskFlag               PedDiskFlag;
 typedef enum _PedPartitionType          PedPartitionType;
 typedef enum _PedPartitionFlag          PedPartitionFlag;
 typedef enum _PedDiskTypeFeature        PedDiskTypeFeature;
@@ -179,6 +194,16 @@ struct _PedDiskOps {
         void (*free) (PedDisk* disk);
         int (*read) (PedDisk* disk);
         int (*write) (const PedDisk* disk);
+        int (*disk_set_flag) (
+                PedDisk *disk,
+                PedDiskFlag flag,
+                int state);
+        int (*disk_get_flag) (
+                const PedDisk *disk,
+                PedDiskFlag flag);
+        int (*disk_is_flag_available) (
+                const PedDisk *disk,
+                PedDiskFlag flag);
         /** \todo add label guessing op here */
 
         /* partition operations */
@@ -266,6 +291,14 @@ extern bool ped_disk_get_max_supported_partition_count(const PedDisk* disk,
                                                        int* supported);
 extern PedAlignment *ped_disk_get_partition_alignment(const PedDisk *disk);
 
+extern int ped_disk_set_flag(PedDisk *disk, PedDiskFlag flag, int state);
+extern int ped_disk_get_flag(const PedDisk *disk, PedDiskFlag flag);
+extern int ped_disk_is_flag_available(const PedDisk *disk, PedDiskFlag flag);
+
+extern const char *ped_disk_flag_get_name(PedDiskFlag flag);
+extern PedDiskFlag ped_disk_flag_get_by_name(const char *name);
+extern PedDiskFlag ped_disk_flag_next(PedDiskFlag flag);
+
 /** @} */
 
 /**
diff --git a/libparted/disk.c b/libparted/disk.c
index a615d36..e8014d1 100644
--- a/libparted/disk.c
+++ b/libparted/disk.c
@@ -738,6 +738,130 @@ ped_disk_get_max_primary_partition_count (const PedDisk* disk)
 }
 
 /**
+ * Set the state (\c 1 or \c 0) of a flag on a disk.
+ *
+ * \note It is an error to call this on an unavailable flag -- use
+ * ped_disk_is_flag_available() to determine which flags are available
+ * for a given disk label.
+ *
+ * \throws PED_EXCEPTION_ERROR if the requested flag is not available for this
+ *      label.
+ */
+int
+ped_disk_set_flag(PedDisk *disk, PedDiskFlag flag, int state)
+{
+        PED_ASSERT (disk != NULL, return 0);
+
+        PedDiskOps *ops = disk->type->ops;
+
+        if (!ped_disk_is_flag_available(disk, flag)) {
+                ped_exception_throw (
+                        PED_EXCEPTION_ERROR,
+                        PED_EXCEPTION_CANCEL,
+                        "The flag '%s' is not available for %s disk labels.",
+                        ped_disk_flag_get_name(flag),
+                        disk->type->name);
+                return 0;
+        }
+
+        return ops->disk_set_flag(disk, flag, state);
+}
+
+/**
+ * Get the state (\c 1 or \c 0) of a flag on a disk.
+ */
+int
+ped_disk_get_flag(const PedDisk *disk, PedDiskFlag flag)
+{
+        PED_ASSERT (disk != NULL, return 0);
+
+        PedDiskOps *ops = disk->type->ops;
+
+        if (!ped_disk_is_flag_available(disk, flag))
+                return 0;
+
+        return ops->disk_get_flag(disk, flag);
+}
+
+/**
+ * Check whether a given flag is available on a disk.
+ *
+ * \return \c 1 if the flag is available.
+ */
+int
+ped_disk_is_flag_available(const PedDisk *disk, PedDiskFlag flag)
+{
+        PED_ASSERT (disk != NULL, return 0);
+
+        PedDiskOps *ops = disk->type->ops;
+
+        if (!ops->disk_is_flag_available)
+                return 0;
+
+        return ops->disk_is_flag_available(disk, flag);
+}
+
+/**
+ * Returns a name for a \p flag, e.g. PED_DISK_CYLINDER_ALIGNMENT will return
+ * "cylinder_alignment".
+ *
+ * \note The returned string will be in English.  However,
+ * translations are provided, so the caller can call
+ * dgettext("parted", RESULT) on the result.
+ */
+const char *
+ped_disk_flag_get_name(PedDiskFlag flag)
+{
+        switch (flag) {
+        case PED_DISK_CYLINDER_ALIGNMENT:
+                return N_("cylinder_alignment");
+
+        default:
+                ped_exception_throw (
+                        PED_EXCEPTION_BUG,
+                        PED_EXCEPTION_CANCEL,
+                        _("Unknown disk flag, %d."),
+                        flag);
+                return NULL;
+        }
+}
+
+/**
+ * Returns the flag associated with \p name.
+ *
+ * \p name can be the English
+ * string, or the translation for the native language.
+ */
+PedDiskFlag
+ped_disk_flag_get_by_name(const char *name)
+{
+        PedDiskFlag flag;
+
+        for (flag = ped_disk_flag_next(0); flag;
+             flag = ped_disk_flag_next(flag)) {
+                const char *flag_name = ped_disk_flag_get_name(flag);
+                if (strcasecmp(name, flag_name) == 0
+                    || strcasecmp(name, _(flag_name)) == 0)
+                        return flag;
+        }
+
+        return 0;
+}
+
+/**
+ * Iterates through all disk flags.
+ *
+ * ped_disk_flag_next(0) returns the first flag
+ *
+ * \return the next flag, or 0 if there are no more flags
+ */
+PedDiskFlag
+ped_disk_flag_next(PedDiskFlag flag)
+{
+        return (flag + 1) % (PED_DISK_LAST_FLAG + 1);
+}
+
+/**
  * \internal We turned a really nasty bureaucracy problem into an elegant maths
  * problem :-)  Basically, there are some constraints to a partition's
  * geometry:



More information about the Parted-commits mailing list