diff -up parted-1.9.0/include/parted/disk.h.diskflags parted-1.9.0/include/parted/disk.h --- parted-1.9.0/include/parted/disk.h.diskflags 2009-12-15 11:07:11.000000000 +0100 +++ parted-1.9.0/include/parted/disk.h 2009-12-15 11:08:29.000000000 +0100 @@ -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 { @@ -72,6 +86,7 @@ struct _PedDiskOps; struct _PedDiskType; struct _PedDiskArchOps; +typedef enum _PedDiskFlag PedDiskFlag; typedef enum _PedPartitionType PedPartitionType; typedef enum _PedPartitionFlag PedPartitionFlag; typedef enum _PedDiskTypeFeature PedDiskTypeFeature; @@ -180,6 +195,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 */ @@ -304,6 +329,14 @@ extern const char* ped_partition_flag_ge extern PedPartitionFlag ped_partition_flag_get_by_name (const char* name); extern PedPartitionFlag ped_partition_flag_next (PedPartitionFlag flag); +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 -up parted-1.9.0/libparted/disk.c.diskflags parted-1.9.0/libparted/disk.c --- parted-1.9.0/libparted/disk.c.diskflags 2009-12-15 11:07:11.000000000 +0100 +++ parted-1.9.0/libparted/disk.c 2009-12-15 11:08:29.000000000 +0100 @@ -773,6 +773,130 @@ ped_disk_max_partition_start_sector (con } /** + * 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: diff -up parted-1.9.0/libparted/labels/dos.c.diskflags parted-1.9.0/libparted/labels/dos.c --- parted-1.9.0/libparted/labels/dos.c.diskflags 2009-12-15 11:07:11.000000000 +0100 +++ parted-1.9.0/libparted/labels/dos.c 2009-12-15 11:12:46.000000000 +0100 @@ -140,6 +140,10 @@ typedef struct { } OrigState; typedef struct { + int cylinder_alignment; +} DosDiskData; + +typedef struct { unsigned char system; int boot; int hidden; @@ -243,8 +247,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; } @@ -256,7 +268,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; } @@ -265,7 +280,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 @@ -2029,7 +2083,9 @@ msdos_partition_align (PedPartition* par partition_probe_bios_geometry (part, &bios_geom); - if (ped_disk_align_to_cylinders_on()) + DosDiskData *disk_specific = part->disk->disk_specific; + if (ped_disk_align_to_cylinders_on() && + disk_specific->cylinder_alignment) if (_align (part, &bios_geom, constraint)) return 1; if (_align_no_geom (part, constraint)) @@ -2324,6 +2380,10 @@ static PedDiskOps msdos_disk_ops = { write: NULL, #endif + disk_set_flag: msdos_disk_set_flag, + disk_get_flag: msdos_disk_get_flag, + disk_is_flag_available: msdos_disk_is_flag_available, + partition_new: msdos_partition_new, partition_duplicate: msdos_partition_duplicate, partition_destroy: msdos_partition_destroy, diff -up parted-1.9.0/libparted/labels/sun.c.diskflags parted-1.9.0/libparted/labels/sun.c --- parted-1.9.0/libparted/labels/sun.c.diskflags 2009-12-15 11:07:11.000000000 +0100 +++ parted-1.9.0/libparted/labels/sun.c 2009-12-15 11:13:44.000000000 +0100 @@ -94,6 +94,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; @@ -190,6 +191,7 @@ sun_alloc (const PedDevice* dev) bios_geom->cylinders = dev->length / cyl_size; sun_specific->length = bios_geom->cylinders * cyl_size; + sun_specific->cylinder_alignment = 1; label = &sun_specific->raw_label; memset(label, 0, sizeof(SunRawLabel)); @@ -252,6 +254,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; @@ -738,12 +776,15 @@ sun_partition_align (PedPartition* part, { 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 ( @@ -862,6 +903,10 @@ static PedDiskOps sun_disk_ops = { write: NULL, #endif + disk_set_flag: sun_disk_set_flag, + disk_get_flag: sun_disk_get_flag, + disk_is_flag_available: sun_disk_is_flag_available, + partition_new: sun_partition_new, partition_duplicate: sun_partition_duplicate, partition_destroy: sun_partition_destroy,