diff -up parted-1.9.0/doc/C/parted.8.align parted-1.9.0/doc/C/parted.8 --- parted-1.9.0/doc/C/parted.8.align 2009-12-15 18:42:25.000000000 +0100 +++ parted-1.9.0/doc/C/parted.8 2009-12-15 18:42:29.000000000 +0100 @@ -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 -up parted-1.9.0/doc/parted.texi.align parted-1.9.0/doc/parted.texi --- parted-1.9.0/doc/parted.texi.align 2009-12-15 18:42:25.000000000 +0100 +++ parted-1.9.0/doc/parted.texi 2009-12-15 18:42:29.000000000 +0100 @@ -496,6 +496,11 @@ display a help message @itemx --script never prompt the user +@item -a alignment-type +@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 -up parted-1.9.0/lib/argmatch.c.align parted-1.9.0/lib/argmatch.c --- parted-1.9.0/lib/argmatch.c.align 2009-12-15 18:42:25.000000000 +0100 +++ parted-1.9.0/lib/argmatch.c 2009-12-15 18:43:16.000000000 +0100 @@ -0,0 +1,274 @@ +/* argmatch.c -- find a match for a string in an array + + Copyright (C) 1990, 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. + + 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 3 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, see . */ + +/* Written by David MacKenzie + Modified by Akim Demaille */ + +#include + +/* Specification. */ +#include "argmatch.h" + +#include +#include +#include +#include + +#include "gettext.h" +#define _(msgid) gettext (msgid) + +#include "error.h" + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +#endif + +/* When reporting an invalid argument, show nonprinting characters + by using the quoting style ARGMATCH_QUOTING_STYLE. Do not use + literal_quoting_style. */ +#ifndef ARGMATCH_QUOTING_STYLE +# define ARGMATCH_QUOTING_STYLE locale_quoting_style +#endif + +/* Non failing version of argmatch call this function after failing. */ +#ifndef ARGMATCH_DIE +# include "exitfail.h" +# define ARGMATCH_DIE exit (exit_failure) +#endif + +#ifdef ARGMATCH_DIE_DECL +ARGMATCH_DIE_DECL; +#endif + +static void +__argmatch_die (void) +{ + ARGMATCH_DIE; +} + +/* Used by XARGMATCH and XARGCASEMATCH. See description in argmatch.h. + Default to __argmatch_die, but allow caller to change this at run-time. */ +argmatch_exit_fn argmatch_die = __argmatch_die; + + +/* If ARG is an unambiguous match for an element of the + NULL-terminated array ARGLIST, return the index in ARGLIST + of the matched element, else -1 if it does not match any element + or -2 if it is ambiguous (is a prefix of more than one element). + + If VALLIST is none null, use it to resolve ambiguities limited to + synonyms, i.e., for + "yes", "yop" -> 0 + "no", "nope" -> 1 + "y" is a valid argument, for `0', and "n" for `1'. */ + +ptrdiff_t +argmatch (const char *arg, const char *const *arglist, + const char *vallist, size_t valsize) +{ + size_t i; /* Temporary index in ARGLIST. */ + size_t arglen; /* Length of ARG. */ + ptrdiff_t matchind = -1; /* Index of first nonexact match. */ + bool ambiguous = false; /* If true, multiple nonexact match(es). */ + + arglen = strlen (arg); + + /* Test all elements for either exact match or abbreviated matches. */ + for (i = 0; arglist[i]; i++) + { + if (!strncmp (arglist[i], arg, arglen)) + { + if (strlen (arglist[i]) == arglen) + /* Exact match found. */ + return i; + else if (matchind == -1) + /* First nonexact match found. */ + matchind = i; + else + { + /* Second nonexact match found. */ + if (vallist == NULL + || memcmp (vallist + valsize * matchind, + vallist + valsize * i, valsize)) + { + /* There is a real ambiguity, or we could not + disambiguate. */ + ambiguous = true; + } + } + } + } + if (ambiguous) + return -2; + else + return matchind; +} + +/* Error reporting for argmatch. + CONTEXT is a description of the type of entity that was being matched. + VALUE is the invalid value that was given. + PROBLEM is the return value from argmatch. */ + +void +argmatch_invalid (const char *context, const char *value, ptrdiff_t problem) +{ + char const *format = (problem == -1 + ? _("invalid argument %s for %s") + : _("ambiguous argument %s for %s")); + + error (0, 0, format, value, context); +} + +/* List the valid arguments for argmatch. + ARGLIST is the same as in argmatch. + VALLIST is a pointer to an array of values. + VALSIZE is the size of the elements of VALLIST */ +void +argmatch_valid (const char *const *arglist, + const char *vallist, size_t valsize) +{ + size_t i; + const char *last_val = NULL; + + /* We try to put synonyms on the same line. The assumption is that + synonyms follow each other */ + fprintf (stderr, _("Valid arguments are:")); + for (i = 0; arglist[i]; i++) + if ((i == 0) + || memcmp (last_val, vallist + valsize * i, valsize)) + { + fprintf (stderr, "\n - `%s'", arglist[i]); + last_val = vallist + valsize * i; + } + else + { + fprintf (stderr, ", `%s'", arglist[i]); + } + putc ('\n', stderr); +} + +/* Never failing versions of the previous functions. + + CONTEXT is the context for which argmatch is called (e.g., + "--version-control", or "$VERSION_CONTROL" etc.). Upon failure, + calls the (supposed never to return) function EXIT_FN. */ + +ptrdiff_t +__xargmatch_internal (const char *context, + const char *arg, const char *const *arglist, + const char *vallist, size_t valsize, + argmatch_exit_fn exit_fn) +{ + ptrdiff_t res = argmatch (arg, arglist, vallist, valsize); + if (res >= 0) + /* Success. */ + return res; + + /* We failed. Explain why. */ + argmatch_invalid (context, arg, res); + argmatch_valid (arglist, vallist, valsize); + (*exit_fn) (); + + return -1; /* To please the compilers. */ +} + +/* Look for VALUE in VALLIST, an array of objects of size VALSIZE and + return the first corresponding argument in ARGLIST */ +const char * +argmatch_to_argument (const char *value, + const char *const *arglist, + const char *vallist, size_t valsize) +{ + size_t i; + + for (i = 0; arglist[i]; i++) + if (!memcmp (value, vallist + valsize * i, valsize)) + return arglist[i]; + return NULL; +} + +#ifdef TEST +/* + * Based on "getversion.c" by David MacKenzie + */ +char *program_name; + +/* When to make backup files. */ +enum backup_type +{ + /* Never make backups. */ + no_backups, + + /* Make simple backups of every file. */ + simple_backups, + + /* Make numbered backups of files that already have numbered backups, + and simple backups of the others. */ + numbered_existing_backups, + + /* Make numbered backups of every file. */ + numbered_backups +}; + +/* Two tables describing arguments (keys) and their corresponding + values */ +static const char *const backup_args[] = +{ + "no", "none", "off", + "simple", "never", + "existing", "nil", + "numbered", "t", + 0 +}; + +static const enum backup_type backup_vals[] = +{ + no_backups, no_backups, no_backups, + simple_backups, simple_backups, + numbered_existing_backups, numbered_existing_backups, + numbered_backups, numbered_backups +}; + +int +main (int argc, const char *const *argv) +{ + const char *cp; + enum backup_type backup_type = no_backups; + + program_name = (char *) argv[0]; + + if (argc > 2) + { + fprintf (stderr, "Usage: %s [VERSION_CONTROL]\n", program_name); + exit (1); + } + + if ((cp = getenv ("VERSION_CONTROL"))) + backup_type = XARGMATCH ("$VERSION_CONTROL", cp, + backup_args, backup_vals); + + if (argc == 2) + backup_type = XARGMATCH (program_name, argv[1], + backup_args, backup_vals); + + printf ("The version control is `%s'\n", + ARGMATCH_TO_ARGUMENT (backup_type, backup_args, backup_vals)); + + return 0; +} +#endif diff -up parted-1.9.0/lib/argmatch.h.align parted-1.9.0/lib/argmatch.h --- parted-1.9.0/lib/argmatch.h.align 2009-12-15 18:42:25.000000000 +0100 +++ parted-1.9.0/lib/argmatch.h 2009-12-15 18:42:29.000000000 +0100 @@ -0,0 +1,102 @@ +/* argmatch.h -- definitions and prototypes for argmatch.c + + Copyright (C) 1990, 1998, 1999, 2001, 2002, 2004, 2005 Free Software + Foundation, Inc. + + 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 3 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, see . */ + +/* Written by David MacKenzie + Modified by Akim Demaille */ + +#ifndef ARGMATCH_H_ +# define ARGMATCH_H_ 1 + +# include + +# include "verify.h" + +# define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array)) + +/* Assert there are as many real arguments as there are values + (argument list ends with a NULL guard). */ + +# define ARGMATCH_VERIFY(Arglist, Vallist) \ + verify (ARRAY_CARDINALITY (Arglist) == ARRAY_CARDINALITY (Vallist) + 1) + +/* Return the index of the element of ARGLIST (NULL terminated) that + matches with ARG. If VALLIST is not NULL, then use it to resolve + false ambiguities (i.e., different matches of ARG but corresponding + to the same values in VALLIST). */ + +ptrdiff_t argmatch (char const *arg, char const *const *arglist, + char const *vallist, size_t valsize); + +# define ARGMATCH(Arg, Arglist, Vallist) \ + argmatch (Arg, Arglist, (char const *) (Vallist), sizeof *(Vallist)) + +/* xargmatch calls this function when it fails. This function should not + return. By default, this is a function that calls ARGMATCH_DIE which + in turn defaults to `exit (exit_failure)'. */ +typedef void (*argmatch_exit_fn) (void); +extern argmatch_exit_fn argmatch_die; + +/* Report on stderr why argmatch failed. Report correct values. */ + +void argmatch_invalid (char const *context, char const *value, + ptrdiff_t problem); + +/* Left for compatibility with the old name invalid_arg */ + +# define invalid_arg(Context, Value, Problem) \ + argmatch_invalid (Context, Value, Problem) + + + +/* Report on stderr the list of possible arguments. */ + +void argmatch_valid (char const *const *arglist, + char const *vallist, size_t valsize); + +# define ARGMATCH_VALID(Arglist, Vallist) \ + argmatch_valid (Arglist, (char const *) (Vallist), sizeof *(Vallist)) + + + +/* Same as argmatch, but upon failure, reports a explanation on the + failure, and exits using the function EXIT_FN. */ + +ptrdiff_t __xargmatch_internal (char const *context, + char const *arg, char const *const *arglist, + char const *vallist, size_t valsize, + argmatch_exit_fn exit_fn); + +/* Programmer friendly interface to __xargmatch_internal. */ + +# define XARGMATCH(Context, Arg, Arglist, Vallist) \ + ((Vallist) [__xargmatch_internal (Context, Arg, Arglist, \ + (char const *) (Vallist), \ + sizeof *(Vallist), \ + argmatch_die)]) + +/* Convert a value into a corresponding argument. */ + +char const *argmatch_to_argument (char const *value, + char const *const *arglist, + char const *vallist, size_t valsize); + +# define ARGMATCH_TO_ARGUMENT(Value, Arglist, Vallist) \ + argmatch_to_argument (Value, Arglist, \ + (char const *) (Vallist), sizeof *(Vallist)) + +#endif /* ARGMATCH_H_ */ diff -up parted-1.9.0/lib/gnulib.mk.align parted-1.9.0/lib/gnulib.mk --- parted-1.9.0/lib/gnulib.mk.align 2009-12-15 18:42:25.000000000 +0100 +++ parted-1.9.0/lib/gnulib.mk 2009-12-15 18:42:29.000000000 +0100 @@ -72,6 +72,15 @@ EXTRA_DIST += $(top_srcdir)/build-aux/an ## end gnulib module announce-gen +## begin gnulib module argmatch + + +EXTRA_DIST += argmatch.c argmatch.h + +libgnulib_la_SOURCES += argmatch.c + +## end gnulib module argmatch + ## begin gnulib module btowc diff -up parted-1.9.0/parted/parted.c.align parted-1.9.0/parted/parted.c --- parted-1.9.0/parted/parted.c.align 2009-12-15 18:42:25.000000000 +0100 +++ parted-1.9.0/parted/parted.c 2009-12-15 18:42:29.000000000 +0100 @@ -19,6 +19,7 @@ #include #include +#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 [] {"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 " @@ -569,7 +598,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])); @@ -700,6 +729,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 { @@ -752,7 +786,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, @@ -2364,7 +2405,7 @@ int opt, help = 0, list = 0, version while (1) { - opt = getopt_long (*argc_ptr, *argv_ptr, "hlmsv", + opt = getopt_long (*argc_ptr, *argv_ptr, "hlmsva:", options, NULL); if (opt == -1) break; @@ -2375,16 +2416,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] [DEVICE [COMMAND [PARAMETERS]]...]\n"), program_name); return 0; }