OSDN Git Service

ui: make --help tell where to report bugs
[android-x86/external-parted.git] / parted / parted.c
index 7acfa2f..edf3249 100644 (file)
@@ -1,6 +1,6 @@
 /*
     parted - a frontend to libparted
-    Copyright (C) 1999-2003, 2005-2008 Free Software Foundation, Inc.
+    Copyright (C) 1999-2003, 2005-2010 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
 */
 
 #include <config.h>
+#include <stdbool.h>
 
+#include "argmatch.h"
 #include "closeout.h"
 #include "configmake.h"
 #include "version-etc.h"
 #include "command.h"
 #include "ui.h"
+#include "progname.h"
 #include "table.h"
+#include "version.h"
 
 #define AUTHORS \
-  "<http://parted.alioth.debian.org/cgi-bin/trac.cgi/browser/AUTHORS>"
+  "<http://git.debian.org/?p=parted/parted.git;a=blob_plain;f=AUTHORS>"
 
 /* The official name of this program (e.g., no `g' prefix).  */
 #define PROGRAM_NAME "parted"
@@ -72,19 +76,45 @@ 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;
         time_t  predicted_time_left;
 } TimerContext;
 
-static const struct option const options[] = {
+static struct option const options[] = {
         /* name, has-arg, string-return-val, char-return-val */
         {"help",        0, NULL, 'h'},
         {"list",        0, NULL, 'l'},
         {"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}
 };
@@ -95,16 +125,16 @@ 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}
 };
 
-char *program_name;
-
 int     opt_script_mode = 0;
 int     pretend_input_tty = 0;
 int     opt_machine_mode = 0;
 int     disk_is_modified = 0;
 int     is_toggle_mode = 0;
+int     alignment = ALIGNMENT_OPTIMAL;
 
 static const char* number_msg = N_(
 "NUMBER is the partition number used by Linux.  On MS-DOS disk labels, the "
@@ -113,6 +143,7 @@ static const char* number_msg = N_(
 static const char* label_type_msg_start = N_("LABEL-TYPE is one of: ");
 static const char* flag_msg_start =   N_("FLAG is one of: ");
 static const char* unit_msg_start =   N_("UNIT is one of: ");
+static const char* min_or_opt_msg = N_("desired alignment: minimum or optimal");
 static const char* part_type_msg =    N_("PART-TYPE is one of: primary, logical, "
                                    "extended\n");
 static const char* fs_type_msg_start = N_("FS-TYPE is one of: ");
@@ -148,6 +179,8 @@ static TimerContext timer_context;
 
 static int _print_list ();
 static void _done (PedDevice* dev);
+static bool partition_align_check (PedDisk const *disk,
+                        PedPartition const *part, enum AlignmentType a_type);
 
 static void
 _timer_handler (PedTimer* timer, void* context)
@@ -194,7 +227,7 @@ _partition_warn_busy (PedPartition* part)
                         _("Partition %s is being used. You must unmount it "
                           "before you modify it with Parted."),
                         path);
-                ped_free (path);
+                free (path);
                 return 0;
         }
         return 1;
@@ -223,7 +256,7 @@ _partition_warn_loss ()
                 PED_EXCEPTION_YES_NO,
                 _("The existing file system will be destroyed and "
                   "all data on the partition will be lost. Do "
-                  "you want to continue?"), 
+                  "you want to continue?"),
                 NULL) == PED_EXCEPTION_YES;
 }
 
@@ -235,7 +268,7 @@ _disk_warn_loss (PedDisk* disk)
                 PED_EXCEPTION_YES_NO,
                 _("The existing disk label on %s will be destroyed "
                   "and all data on this disk will be lost. Do you "
-                  "want to continue?"), 
+                  "want to continue?"),
                 disk->dev->path) == PED_EXCEPTION_YES;
 }
 
@@ -264,11 +297,11 @@ enum { /* Don't change these values */
         SECT_END        = -1
 };
 
-/* Find the prefered way to adjust the sector s inside range.
+/* Find the preferred way to adjust the sector s inside range.
  * If a move isn't allowed or is out of range it can't be selected.
  * what contains SECT_START if the sector to adjust is a start sector
  * or SECT_END if it's an end one.
- * The prefered move is to the nearest allowed boundary of the part
+ * The preferred move is to the nearest allowed boundary of the part
  * partition (if at equal distance: to start if SECT_START or to end
  * if SECT_END).
  * The distance is returned in dist.
@@ -346,7 +379,6 @@ snap_to_boundaries (PedGeometry* new_geom, PedGeometry* old_geom,
         EMoves          start_allow, end_allow, start_want, end_want;
         int             adjacent;
 
-        start_want = end_want = MOVE_NO;
         start_allow = end_allow = MOVE_STILL | MOVE_UP | MOVE_DOWN;
 
         start_part = ped_disk_get_partition_by_sector (disk, start);
@@ -412,7 +444,7 @@ snap_to_boundaries (PedGeometry* new_geom, PedGeometry* old_geom,
 
 /* This functions constructs a constraint from the following information:
  *      start, is_start_exact, end, is_end_exact.
- *      
+ *
  * If is_start_exact == 1, then the constraint requires start be as given in
  * "start".  Otherwise, the constraint does not set any requirements on the
  * start.
@@ -445,9 +477,26 @@ help_on (char* topic)
         command_print_help (cmd);
 }
 
+/* Issue a warning about upcoming removal of FS support.  */
+static void
+issue_fs_op_warning (char const *op)
+{
+  if (getenv ("PARTED_SUPPRESS_FILE_SYSTEM_MANIPULATION_WARNING"))
+    return;
+  fprintf (stderr,
+ _("WARNING: you are attempting to use %s to operate on (%s) a file system.\n"
+   "%s's file system manipulation code is not as robust as what you'll find in\n"
+   "dedicated, file-system-specific packages like e2fsprogs.  We recommend\n"
+   "you use %s only to manipulate partition tables, whenever possible.\n"
+   "Support for performing most operations on most types of file systems\n"
+   "will be removed in an upcoming release.\n"),
+   program_name, op, program_name, program_name);
+}
+
 static int
 do_check (PedDevice** dev)
 {
+        issue_fs_op_warning ("check");
         PedDisk*        disk;
         PedFileSystem*  fs;
         PedPartition*   part = NULL;
@@ -484,6 +533,7 @@ error:
 static int
 do_cp (PedDevice** dev)
 {
+        issue_fs_op_warning ("cp");
         PedDisk*                src_disk;
         PedDisk*                dst_disk;
         PedPartition*           src = NULL;
@@ -569,7 +619,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]));
@@ -595,13 +645,16 @@ static int
 do_mklabel (PedDevice** dev)
 {
         PedDisk*                disk;
-        const PedDiskType*      type = ped_disk_probe (*dev);
+        const PedDiskType*      type = NULL;
 
         ped_exception_fetch_all ();
         disk = ped_disk_new (*dev);
         if (!disk) ped_exception_catch ();
         ped_exception_leave_all ();
 
+        if (!command_line_get_disk_type (_("New disk label type?"), &type))
+                goto error;
+
         if (disk) {
                 if (!_disk_warn_busy (disk))
                         goto error_destroy_disk;
@@ -611,9 +664,6 @@ do_mklabel (PedDevice** dev)
                 ped_disk_destroy (disk);
         }
 
-        if (!command_line_get_disk_type (_("New disk label type?"), &type))
-                goto error;
-
         disk = ped_disk_new_fresh (*dev, type);
         if (!disk)
                 goto error;
@@ -636,6 +686,7 @@ error:
 static int
 do_mkfs (PedDevice** dev)
 {
+        issue_fs_op_warning ("mkfs");
         PedDisk*                disk;
         PedPartition*           part = NULL;
         const PedFileSystemType* type = ped_file_system_type_get ("ext2");
@@ -695,11 +746,16 @@ do_mkpart (PedDevice** dev)
         char*                    part_name = NULL;
         char                     *start_usr = NULL, *end_usr = NULL;
         char                     *start_sol = NULL, *end_sol = NULL;
-        
+
         disk = ped_disk_new (*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 {
@@ -733,14 +789,13 @@ do_mkpart (PedDevice** dev)
                                                &fs_type))
                         goto error_destroy_disk;
         }
-        if (peek_word)
-                ped_free (peek_word);
+        free (peek_word);
 
         if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start))
                 goto error_destroy_disk;
         if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
                 goto error_destroy_disk;
-        
+
         /* processing starts here */
         part = ped_partition_new (disk, part_type, fs_type, start, end);
         if (!part)
@@ -753,34 +808,63 @@ 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,
                         dev_constraint);
+        ped_constraint_destroy (user_constraint);
+        ped_constraint_destroy (dev_constraint);
         if (!final_constraint)
                 goto error_destroy_simple_constraints;
 
         /* subject to partition constraint */
         ped_exception_fetch_all();
-        if (!ped_disk_add_partition (disk, part, final_constraint)) {
+        bool added_ok = ped_disk_add_partition (disk, part, final_constraint);
+        ped_constraint_destroy (final_constraint);
+        if (!added_ok) {
                 ped_exception_leave_all();
-               
-                if (ped_disk_add_partition (disk, part,
-                                        ped_constraint_any (*dev))) {
+
+                PedConstraint *constraint_any = ped_constraint_any (*dev);
+                added_ok = ped_disk_add_partition (disk, part,
+                                                        constraint_any);
+                ped_constraint_destroy (constraint_any);
+
+                if (!added_ok)
+                        goto error_remove_part;
+
+                if (!ped_geometry_test_sector_inside(range_start, part->geom.start) ||
+                    !ped_geometry_test_sector_inside(range_end, part->geom.end)) {
                         start_usr = ped_unit_format (*dev, start);
                         end_usr   = ped_unit_format (*dev, end);
                         start_sol = ped_unit_format (*dev, part->geom.start);
                         end_sol   = ped_unit_format (*dev, part->geom.end);
 
+                        /* In script mode failure to use specified values is fatal.
+                         * However, in interactive mode, it merely elicits a warning
+                         * and a prompt for whether to proceed.  The same appies for
+                         * do_mkpartfs function.
+                         */
                         switch (ped_exception_throw (
-                                PED_EXCEPTION_WARNING,
-                                PED_EXCEPTION_YES_NO,
+                                (opt_script_mode
+                                 ? PED_EXCEPTION_ERROR
+                                 : PED_EXCEPTION_WARNING),
+                                (opt_script_mode
+                                 ? PED_EXCEPTION_CANCEL
+                                 : PED_EXCEPTION_YES_NO),
                                 _("You requested a partition from %s to %s.\n"
                                   "The closest location we can manage is "
-                                  "%s to %s.  "
-                                  "Is this still acceptable to you?"),
-                                start_usr, end_usr, start_sol, end_sol))
+                                  "%s to %s.%s"),
+                                start_usr, end_usr, start_sol, end_sol,
+                                (opt_script_mode ? ""
+                                 : _("\nIs this still acceptable to you?"))))
                         {
                                 case PED_EXCEPTION_YES:
                                         /* all is well in this state */
@@ -791,8 +875,23 @@ do_mkpart (PedDevice** dev)
                                         /* undo partition addition */
                                         goto error_remove_part;
                         }
-                } else {
-                        goto error_remove_part;
+                }
+
+                if ((alignment == ALIGNMENT_OPTIMAL &&
+                     !partition_align_check(disk, part, PA_OPTIMUM)) ||
+                    (alignment == ALIGNMENT_MINIMAL &&
+                     !partition_align_check(disk, part, PA_MINIMUM))) {
+                        if (ped_exception_throw(
+                                PED_EXCEPTION_WARNING,
+                                (opt_script_mode
+                                 ? PED_EXCEPTION_OK
+                                 : PED_EXCEPTION_IGNORE_CANCEL),
+                                _("The resulting partition is not properly "
+                                  "aligned for best performance.")) ==
+                            PED_EXCEPTION_CANCEL) {
+                                /* undo partition addition */
+                                goto error_remove_part;
+                        }
                 }
         } else {
                 ped_exception_leave_all();
@@ -802,34 +901,28 @@ do_mkpart (PedDevice** dev)
         /* set minor attributes */
         if (part_name)
                 PED_ASSERT (ped_partition_set_name (part, part_name), return 0);
+        free (part_name);  /* avoid double-free upon failure */
+        part_name = NULL;
         if (!ped_partition_set_system (part, fs_type))
                 goto error_destroy_disk;
         if (ped_partition_is_flag_available (part, PED_PARTITION_LBA))
                 ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
-        
+
         if (!ped_disk_commit (disk))
                 goto error_destroy_disk;
-        
-        /* clean up */
-        ped_constraint_destroy (final_constraint);
-        ped_constraint_destroy (user_constraint);
-        ped_constraint_destroy (dev_constraint);
 
+        /* clean up */
         ped_disk_destroy (disk);
-        
+
         if (range_start != NULL)
                 ped_geometry_destroy (range_start);
         if (range_end != NULL)
                 ped_geometry_destroy (range_end);
-        
-        if (start_usr != NULL)
-                ped_free (start_usr);
-        if (end_usr != NULL)
-                ped_free (end_usr);
-        if (start_sol != NULL)
-                ped_free (start_sol);
-        if (end_sol != NULL)
-                ped_free (end_sol);
+
+        free (start_usr);
+        free (end_usr);
+        free (start_sol);
+        free (end_sol);
 
         if ((*dev)->type != PED_DEVICE_FILE)
                 disk_is_modified = 1;
@@ -838,12 +931,10 @@ do_mkpart (PedDevice** dev)
 
 error_remove_part:
         ped_disk_remove_partition (disk, part);
-        ped_constraint_destroy (final_constraint);
 error_destroy_simple_constraints:
-        ped_constraint_destroy (user_constraint);
-        ped_constraint_destroy (dev_constraint);
         ped_partition_destroy (part);
 error_destroy_disk:
+        free (part_name);
         ped_disk_destroy (disk);
 error:
         if (range_start != NULL)
@@ -851,14 +942,10 @@ error:
         if (range_end != NULL)
                 ped_geometry_destroy (range_end);
 
-        if (start_usr != NULL)
-                ped_free (start_usr);
-        if (end_usr != NULL)
-                ped_free (end_usr);
-        if (start_sol != NULL)
-                ped_free (start_sol);
-        if (end_sol != NULL)
-                ped_free (end_sol);
+        free (start_usr);
+        free (end_usr);
+        free (start_sol);
+        free (end_sol);
 
         return 0;
 }
@@ -866,6 +953,7 @@ error:
 static int
 do_mkpartfs (PedDevice** dev)
 {
+        issue_fs_op_warning ("mkpartfs");
         PedDisk*            disk;
         PedPartition*       part;
         PedPartitionType    part_type;
@@ -884,6 +972,11 @@ do_mkpartfs (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 {
@@ -893,9 +986,9 @@ do_mkpartfs (PedDevice** dev)
         }
 
         if (ped_disk_type_check_feature (disk->type,
-                                         PED_DISK_TYPE_PARTITION_NAME)) 
+                                         PED_DISK_TYPE_PARTITION_NAME))
                 part_name = command_line_get_word (_("Partition name?"),
-                                                   "", NULL, 1); 
+                                                   "", NULL, 1);
 
         if (part_type == PED_PARTITION_EXTENDED) {
                 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
@@ -924,34 +1017,59 @@ do_mkpartfs (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,
                                                      dev_constraint);
+        ped_constraint_destroy (user_constraint);
+        ped_constraint_destroy (dev_constraint);
         if (!final_constraint)
                 goto error_destroy_simple_constraints;
 
         /* subject to partition constraint */
         ped_exception_fetch_all();
-        if (!ped_disk_add_partition (disk, part, final_constraint)) {
+       bool added_ok = ped_disk_add_partition (disk, part, final_constraint);
+        ped_constraint_destroy (final_constraint);
+        if (!added_ok) {
                 ped_exception_leave_all();
-               
-                if (ped_disk_add_partition (disk, part,
-                                        ped_constraint_any (*dev))) {
+
+                PedConstraint *constraint_any = ped_constraint_any (*dev);
+                bool added_ok = ped_disk_add_partition (disk, part,
+                                                        constraint_any);
+                ped_constraint_destroy (constraint_any);
+
+                if (!added_ok)
+                        goto error_remove_part;
+
+                if (!ped_geometry_test_sector_inside(range_start, part->geom.start) ||
+                    !ped_geometry_test_sector_inside(range_end, part->geom.end)) {
                         start_usr = ped_unit_format (*dev, start);
                         end_usr   = ped_unit_format (*dev, end);
                         start_sol = ped_unit_format (*dev, part->geom.start);
                         end_sol   = ped_unit_format (*dev, part->geom.end);
 
                         switch (ped_exception_throw (
-                                PED_EXCEPTION_WARNING,
-                                PED_EXCEPTION_YES_NO,
+                                (opt_script_mode
+                                 ? PED_EXCEPTION_ERROR
+                                 : PED_EXCEPTION_WARNING),
+                                (opt_script_mode
+                                 ? PED_EXCEPTION_CANCEL
+                                 : PED_EXCEPTION_YES_NO),
                                 _("You requested a partition from %s to %s.\n"
                                   "The closest location we can manage is "
-                                  "%s to %s.  "
-                                  "Is this still acceptable to you?"),
-                                start_usr, end_usr, start_sol, end_sol)) {
+                                  "%s to %s.%s"),
+                                start_usr, end_usr, start_sol, end_sol,
+                                (opt_script_mode ? ""
+                                 : _("\nIs this still acceptable to you?"))))
+                        {
                                 case PED_EXCEPTION_YES:
                                         /* all is well in this state */
                                         break;
@@ -961,8 +1079,23 @@ do_mkpartfs (PedDevice** dev)
                                         /* undo partition addition */
                                         goto error_remove_part;
                         }
-                } else {
-                        goto error_remove_part;
+                }
+
+                if ((alignment == ALIGNMENT_OPTIMAL &&
+                     !partition_align_check(disk, part, PA_OPTIMUM)) ||
+                    (alignment == ALIGNMENT_MINIMAL &&
+                     !partition_align_check(disk, part, PA_MINIMUM))) {
+                        if (ped_exception_throw(
+                                PED_EXCEPTION_WARNING,
+                                (opt_script_mode
+                                 ? PED_EXCEPTION_OK
+                                 : PED_EXCEPTION_IGNORE_CANCEL),
+                                _("The resulting partition is not properly "
+                                  "aligned for best performance.")) ==
+                            PED_EXCEPTION_CANCEL) {
+                                /* undo partition addition */
+                                goto error_remove_part;
+                        }
                 }
         } else {
                 ped_exception_leave_all();
@@ -975,10 +1108,12 @@ do_mkpartfs (PedDevice** dev)
 
         /* fs creation */
         fs = ped_file_system_create (&part->geom, fs_type, g_timer);
-        if (!fs) 
+        if (!fs)
                 goto error_destroy_disk;
         ped_file_system_close (fs);
 
+        if (part_name)
+                PED_ASSERT (ped_partition_set_name (part, part_name), return 0);
         if (!ped_partition_set_system (part, fs_type))
                 goto error_destroy_disk;
 
@@ -986,9 +1121,6 @@ do_mkpartfs (PedDevice** dev)
                 goto error_destroy_disk;
 
         /* clean up */
-        ped_constraint_destroy (final_constraint);
-        ped_constraint_destroy (user_constraint);
-        ped_constraint_destroy (dev_constraint);
 
         ped_disk_destroy (disk);
 
@@ -997,14 +1129,10 @@ do_mkpartfs (PedDevice** dev)
         if (range_end != NULL)
                 ped_geometry_destroy (range_end);
 
-        if (start_usr != NULL)
-                ped_free (start_usr);
-        if (end_usr != NULL)
-                ped_free (end_usr);
-        if (start_sol != NULL)
-                ped_free (start_sol);
-        if (end_sol != NULL)
-                ped_free (end_sol);
+        free (start_usr);
+        free (end_usr);
+        free (start_sol);
+        free (end_sol);
 
         if ((*dev)->type != PED_DEVICE_FILE)
                 disk_is_modified = 1;
@@ -1013,10 +1141,7 @@ do_mkpartfs (PedDevice** dev)
 
 error_remove_part:
         ped_disk_remove_partition (disk, part);
-        ped_constraint_destroy (final_constraint);
 error_destroy_simple_constraints:
-        ped_constraint_destroy (user_constraint);
-        ped_constraint_destroy (dev_constraint);
         ped_partition_destroy (part);
 error_destroy_disk:
         ped_disk_destroy (disk);
@@ -1026,14 +1151,10 @@ error:
         if (range_end != NULL)
                 ped_geometry_destroy (range_end);
 
-        if (start_usr != NULL)
-                ped_free (start_usr);
-        if (end_usr != NULL)
-                ped_free (end_usr);
-        if (start_sol != NULL)
-                ped_free (start_sol);
-        if (end_sol != NULL)
-                ped_free (end_sol);
+        free (start_usr);
+        free (end_usr);
+        free (start_sol);
+        free (end_sol);
 
         return 0;
 }
@@ -1041,6 +1162,7 @@ error:
 static int
 do_move (PedDevice** dev)
 {
+        issue_fs_op_warning ("move");
         PedDisk*        disk;
         PedPartition*   part = NULL;
         PedFileSystem*  fs;
@@ -1168,7 +1290,7 @@ partition_print_flags (PedPartition* part)
         PedPartitionFlag        flag;
         int                     first_flag;
         const char*             name;
-        char*                   res = ped_malloc(1); 
+        char*                   res = ped_malloc(1);
         void*                   _res = res;
 
         *res = '\0';
@@ -1181,18 +1303,16 @@ partition_print_flags (PedPartition* part)
                                 first_flag = 0;
                         else {
                                 _res = res;
-                                ped_realloc (&_res, strlen (res)
-                                                           + 1 + 2);
+                                ped_realloc (&_res, strlen (res) + 1 + 2);
                                 res = _res;
                                 strncat (res, ", ", 2);
                         }
 
                         name = _(ped_partition_flag_get_name (flag));
                         _res = res;
-                        ped_realloc (&_res, strlen (res) + 1
-                                                   + strlen (name));
+                        ped_realloc (&_res, strlen (res) + 1 + strlen (name));
                         res = _res;
-                        strncat (res, name, 21);
+                        strcat(res, name);
                 }
         }
 
@@ -1218,8 +1338,8 @@ print_sector_compact_and_percent (PedSector sector, PedDevice* dev)
 
         printf ("%s (%s)\n", compact, percent);
 
-        ped_free (compact);
-        ped_free (percent);
+        free (compact);
+        free (percent);
 }
 
 static int
@@ -1256,7 +1376,7 @@ partition_print (PedPartition* part)
 
         putchar ('\n');
 
-        ped_free (flags);
+        free (flags);
         ped_file_system_close (fs);
 
         return 1;
@@ -1274,42 +1394,50 @@ do_print (PedDevice** dev)
         int             has_free_arg = 0;
         int             has_list_arg = 0;
         int             has_num_arg = 0;
-        const char *const transport[14] = {"unknown", "scsi", "ide", "dac960",
-                                          "cpqarray", "file", "ataraid", "i2o",
-                                          "ubd", "dasd", "viodasd", "sx8", "dm",
-                                          "xvd"};
+        const char *const transport[] = {"unknown", "scsi", "ide", "dac960",
+                                         "cpqarray", "file", "ataraid", "i2o",
+                                         "ubd", "dasd", "viodasd", "sx8", "dm",
+                                         "xvd", "sd/mmc", "virtblk", "aoe",
+                                         "md"};
         char*           peek_word;
         char*           start;
         char*           end;
         char*           size;
         const char*     name;
         char*           tmp;
-        char*           flags;
         wchar_t*        table_rendered;
 
         disk = ped_disk_new (*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;
+
         peek_word = command_line_peek_word ();
         if (peek_word) {
                 if (strncmp (peek_word, "devices", 7) == 0) {
-                        command_line_pop_word();
+                        char *w = command_line_pop_word();
+                        free (w);
                         has_devices_arg = 1;
                 }
                 else if (strncmp (peek_word, "free", 4) == 0) {
-                        command_line_pop_word ();
+                        char *w = command_line_pop_word ();
+                        free (w);
                         has_free_arg = 1;
-                } 
+                }
                 else if (strncmp (peek_word, "list", 4) == 0 ||
                          strncmp (peek_word, "all", 3) == 0) {
-                        command_line_pop_word();
+                        char *w = command_line_pop_word();
+                        free (w);
                         has_list_arg = 1;
                 }
                 else
                         has_num_arg = isdigit(peek_word[0]);
 
-                ped_free (peek_word);
+                free (peek_word);
         }
 
         if (has_devices_arg) {
@@ -1323,8 +1451,8 @@ do_print (PedDevice** dev)
                                              current_dev->length
                                              * current_dev->sector_size);
                         printf ("%s (%s)\n", current_dev->path, end);
-                        ped_free (end);
-                }    
+                        free (end);
+                }
 
                 dev_name = xstrdup ((*dev)->path);
                 ped_device_free_all ();
@@ -1335,12 +1463,12 @@ do_print (PedDevice** dev)
                 if (!ped_device_open (*dev))
                         return 0;
 
-                ped_free (dev_name);
+                free (dev_name);
 
                 return 1;
         }
 
-        else if (has_list_arg) 
+        else if (has_list_arg)
                 return _print_list ();
 
         else if (has_num_arg) {
@@ -1373,15 +1501,15 @@ do_print (PedDevice** dev)
                     (*dev)->sector_size, (*dev)->phys_sector_size,
                     disk->type->name, (*dev)->model);
         } else {
-            printf (_("Model: %s (%s)\n"), 
+            printf (_("Model: %s (%s)\n"),
                     (*dev)->model, transport[(*dev)->type]);
             printf (_("Disk %s: %s\n"), (*dev)->path, end);
             printf (_("Sector size (logical/physical): %lldB/%lldB\n"),
                     (*dev)->sector_size, (*dev)->phys_sector_size);
         }
 
-        ped_free (start);
-        ped_free (end);
+        free (start);
+        free (end);
 
         if (ped_unit_get_default () == PED_UNIT_CHS
             || ped_unit_get_default () == PED_UNIT_CYLINDER) {
@@ -1389,7 +1517,7 @@ do_print (PedDevice** dev)
                 char* cyl_size = ped_unit_format_custom (*dev,
                                         chs->heads * chs->sectors,
                                         PED_UNIT_KILOBYTE);
-                
+
                 if (opt_machine_mode) {
                     printf ("%d:%d:%d:%s;\n",
                             chs->cylinders, chs->heads, chs->sectors, cyl_size);
@@ -1399,20 +1527,20 @@ do_print (PedDevice** dev)
                             chs->cylinders, chs->heads, chs->sectors, cyl_size);
                 }
 
-                ped_free (cyl_size);
+                free (cyl_size);
         }
 
         if (!opt_machine_mode) {
             printf (_("Partition Table: %s\n"), disk->type->name);
             putchar ('\n');
         }
-        
+
         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);
 
-        
+
         PedPartition* part;
         if (!opt_machine_mode) {
             StrList *row1;
@@ -1484,9 +1612,9 @@ do_print (PedDevice** dev)
                                     str_list_append (row, name);
                             }
 
-                            flags = partition_print_flags (part);
+                            char *flags = partition_print_flags (part);
                             str_list_append (row, flags);
-                            ped_free (flags);
+                            free (flags);
                     } else {
                             if (has_extended)
                                     str_list_append (row, "");
@@ -1499,46 +1627,51 @@ do_print (PedDevice** dev)
                     //PED_ASSERT (row.cols == caption.cols)
                     table_add_row_from_strlist (table, row);
                     str_list_destroy (row);
-                    ped_free (tmp);
-                    ped_free (start);
-                    ped_free (end);
-                    ped_free (size);
+                    free (tmp);
+                    free (start);
+                    free (end);
+                    free (size);
             }
 
-            table_rendered = table_render (table); 
+            table_rendered = table_render (table);
 #ifdef ENABLE_NLS
             printf("%ls\n", table_rendered);
 #else
             printf("%s\n", table_rendered);
 #endif
-            ped_free (table_rendered);
+            free (table_rendered);
             table_destroy (table);
             str_list_destroy (row1);
 
         } else {
-    
+
             for (part = ped_disk_next_partition (disk, NULL); part;
                  part = ped_disk_next_partition (disk, part)) {
 
                 if ((!has_free_arg && !ped_partition_is_active(part)) ||
                         part->type & PED_PARTITION_METADATA)
-                            continue; 
-                
+                            continue;
+
                 if (part->num >= 0)
                     printf ("%d:", part->num);
                 else
                     fputs ("1:", stdout);
 
-                printf ("%s:", ped_unit_format (*dev, part->geom.start));
-                printf ("%s:", ped_unit_format_byte (
-                                *dev,
-                                (part->geom.end + 1) * 
-                                (*dev)->sector_size - 1));
+                char *s = ped_unit_format (*dev, part->geom.start);
+                printf ("%s:", s);
+                free (s);
+                s = ped_unit_format_byte (*dev,
+                                          (part->geom.end + 1) *
+                                          (*dev)->sector_size - 1);
+                printf ("%s:", s);
+                free (s);
+
+                if (ped_unit_get_default() != PED_UNIT_CHS) {
+                    s = ped_unit_format (*dev, part->geom.length);
+                    printf ("%s:", s);
+                    free (s);
+                }
 
-                if (ped_unit_get_default() != PED_UNIT_CHS)
-                    printf ("%s:", ped_unit_format (*dev,
-                                                    part->geom.length));
-                    
                 if (!(part->type & PED_PARTITION_FREESPACE)) {
 
                     if (part->fs_type)
@@ -1546,12 +1679,14 @@ do_print (PedDevice** dev)
                     else
                         putchar (':');
 
-                    if (has_name) 
+                    if (has_name)
                         printf ("%s:", _(ped_partition_get_name (part)));
                     else
                         putchar (':');
 
-                    printf ("%s;\n", partition_print_flags (part));
+                    char *flags = partition_print_flags (part);
+                    printf ("%s;\n", flags);
+                    free (flags);
 
                 } else {
                     puts ("free;");
@@ -1563,6 +1698,7 @@ do_print (PedDevice** dev)
 
         return 1;
 
+error_destroy_disk:
         ped_disk_destroy (disk);
 error:
         return 0;
@@ -1578,7 +1714,7 @@ _print_list ()
         while ((current_dev = ped_device_get_next(current_dev))) {
                 do_print (&current_dev);
                 putchar ('\n');
-        }    
+        }
 
         return 1;
 }
@@ -1587,7 +1723,7 @@ static int
 do_quit (PedDevice** dev)
 {
         _done (*dev);
-        exit (0);
+        exit (EXIT_SUCCESS);
 }
 
 static PedPartitionType
@@ -1648,8 +1784,8 @@ _rescue_add_partition (PedPartition* part)
                 fs_type->name, ped_partition_type_get_name (part->type),
                 found_start, found_end);
         ped_geometry_destroy (probed);
-        ped_free (found_start);
-        ped_free (found_end);
+        free (found_start);
+        free (found_end);
 
         switch (ex_opt) {
                 case PED_EXCEPTION_CANCEL: return -1;
@@ -1778,6 +1914,7 @@ error:
 static int
 do_resize (PedDevice** dev)
 {
+        issue_fs_op_warning ("resize");
         PedDisk                 *disk;
         PedPartition            *part = NULL;
         PedFileSystem           *fs;
@@ -1790,6 +1927,11 @@ do_resize (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 (!command_line_get_partition (_("Partition number?"), disk, &part))
                 goto error_destroy_disk;
         if (part->type != PED_PARTITION_EXTENDED) {
@@ -1907,6 +2049,49 @@ do_select (PedDevice** dev)
         return 1;
 }
 
+/* Return true if partition PART is consistent with DISK's selected
+   offset and alignment requirements.  Also return true if there is
+   insufficient kernel support to determine DISK's alignment requirements.
+   Otherwise, return false.  A_TYPE selects whether to check for minimal
+   or optimal alignment requirements.  */
+static bool
+partition_align_check (PedDisk const *disk, PedPartition const *part,
+                      enum AlignmentType a_type)
+{
+  PED_ASSERT (part->disk == disk, return false);
+  PedDevice const *dev = disk->dev;
+
+  PedAlignment *pa = (a_type == PA_MINIMUM
+                     ? ped_device_get_minimum_alignment (dev)
+                     : ped_device_get_optimum_alignment (dev));
+  if (pa == NULL)
+    return true;
+
+  PED_ASSERT (pa->grain_size != 0, return false);
+  bool ok = (part->geom.start % pa->grain_size == pa->offset);
+  free (pa);
+  return ok;
+}
+
+static int
+do_align_check (PedDevice **dev)
+{
+  PedDisk *disk = ped_disk_new (*dev);
+  if (!disk)
+    return 0;
+
+  enum AlignmentType align_type;
+  PedPartition *part = NULL;
+  bool aligned =
+    (command_line_get_align_type (_("alignment type(min/opt)"), &align_type)
+     && command_line_get_partition (_("Partition number?"), disk, &part)
+     && partition_align_check (disk, part, align_type));
+
+  ped_disk_destroy (disk);
+
+  return aligned ? 1 : 0;
+}
+
 static int
 do_set (PedDevice** dev)
 {
@@ -1914,22 +2099,22 @@ do_set (PedDevice** dev)
         PedPartition*           part = NULL;
         PedPartitionFlag        flag;
         int                     state;
-        
+
         disk = ped_disk_new (*dev);
         if (!disk)
                 goto error;
-        
+
         if (!command_line_get_partition (_("Partition number?"), disk, &part))
                 goto error_destroy_disk;
         if (!command_line_get_part_flag (_("Flag to Invert?"), part, &flag))
                 goto error_destroy_disk;
-        state = (ped_partition_get_flag (part, flag) == 0 ? 1 : 0);      
-        
+        state = (ped_partition_get_flag (part, flag) == 0 ? 1 : 0);
+
         if (!is_toggle_mode) {
                 if (!command_line_get_state (_("New state?"), &state))
                            goto error_destroy_disk;
         }
-    
+
         if (!ped_partition_set_flag (part, flag, state))
                        goto error_destroy_disk;
        if (!ped_disk_commit (disk))
@@ -1951,7 +2136,7 @@ static int
 do_toggle (PedDevice **dev)
 {
         int result;
-        
+
         is_toggle_mode = 1;
         result = do_set (dev);
         is_toggle_mode = 0;
@@ -1984,6 +2169,7 @@ _init_messages ()
         StrList*                list;
         int                     first;
         PedFileSystemType*      fs_type;
+        PedFileSystemAlias*     fs_alias;
         PedDiskType*            disk_type;
         PedPartitionFlag        part_flag;
         PedUnit                 unit;
@@ -2040,7 +2226,7 @@ _init_messages ()
         label_type_msg = str_list_convert (list);
         str_list_destroy (list);
 
-/* mkfs - file system types */
+/* mkfs - file system types and aliases */
         list = str_list_create (_(fs_type_msg_start), NULL);
 
         first = 1;
@@ -2055,12 +2241,23 @@ _init_messages ()
                         str_list_append (list, ", ");
                 str_list_append (list, fs_type->name);
         }
+        for (fs_alias = ped_file_system_alias_get_next (NULL);
+             fs_alias; fs_alias = ped_file_system_alias_get_next (fs_alias)) {
+                if (fs_alias->fs_type->ops->create == NULL)
+                        continue;
+
+                if (first)
+                        first = 0;
+                else
+                        str_list_append (list, ", ");
+                str_list_append (list, fs_alias->alias);
+        }
         str_list_append (list, "\n");
 
         mkfs_fs_type_msg = str_list_convert (list);
         str_list_destroy (list);
 
-/* mkpart - file system types */
+/* mkpart - file system types and aliases */
         list = str_list_create (_(fs_type_msg_start), NULL);
 
         first = 1;
@@ -2072,12 +2269,20 @@ _init_messages ()
                         str_list_append (list, ", ");
                 str_list_append (list, fs_type->name);
         }
+        for (fs_alias = ped_file_system_alias_get_next (NULL);
+             fs_alias; fs_alias = ped_file_system_alias_get_next (fs_alias)) {
+                if (first)
+                        first = 0;
+                else
+                        str_list_append (list, ", ");
+                str_list_append (list, fs_alias->alias);
+        }
         str_list_append (list, "\n");
 
         mkpart_fs_type_msg = str_list_convert (list);
         str_list_destroy (list);
 
-/* resize - file system types */
+/* resize - file system types and aliases */
         list = str_list_create (_(resize_msg_start), NULL);
 
         first = 1;
@@ -2092,6 +2297,17 @@ _init_messages ()
                         str_list_append (list, ", ");
                 str_list_append (list, fs_type->name);
         }
+        for (fs_alias = ped_file_system_alias_get_next (NULL);
+             fs_alias; fs_alias = ped_file_system_alias_get_next (fs_alias)) {
+                if (fs_alias->fs_type->ops->resize == NULL)
+                        continue;
+
+                if (first)
+                        first = 0;
+                else
+                        str_list_append (list, ", ");
+                str_list_append (list, fs_alias->alias);
+        }
         str_list_append (list, "\n");
 
         resize_fs_type_msg = str_list_convert (list);
@@ -2111,6 +2327,18 @@ _done_messages ()
 static void
 _init_commands ()
 {
+  command_register (commands,
+    command_create ( str_list_create_unique ("align-check",
+                                            _("align-check"), NULL),
+                    do_align_check,
+                    str_list_create (
+                                     _("align-check TYPE N"
+                                       "                        "
+                                       "check partition N for"
+                                       " TYPE(min|opt) alignment"), NULL),
+
+                    str_list_create (_(number_msg), _(min_or_opt_msg),
+                                     NULL), 1));
         command_register (commands, command_create (
                 str_list_create_unique ("check", _("check"), NULL),
                 do_check,
@@ -2152,7 +2380,7 @@ NULL),
                 do_mkfs,
                 str_list_create (
 _("mkfs NUMBER FS-TYPE                      make a FS-TYPE file "
-  "system on partititon NUMBER"),
+  "system on partition NUMBER"),
 NULL),
                 str_list_create (_(number_msg), _(mkfs_fs_type_msg), NULL), 1));
 
@@ -2323,7 +2551,7 @@ textdomain(PACKAGE);
 void
 _version ()
 {
-  version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, VERSION, AUTHORS,
+  version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, Version, AUTHORS,
                (char *) NULL);
 }
 
@@ -2334,7 +2562,7 @@ int     opt, help = 0, list = 0, version = 0, wrong = 0;
 
 while (1)
 {
-        opt = getopt_long (*argc_ptr, *argv_ptr, "hilmsv",
+        opt = getopt_long (*argc_ptr, *argv_ptr, "hlmsva:",
                            options, NULL);
         if (opt == -1)
                 break;
@@ -2345,16 +2573,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;
 }
@@ -2408,7 +2642,7 @@ retry:
 
 if (!ped_device_open (dev))
         return NULL;
-return dev;     
+return dev;
 }
 
 static PedDevice*
@@ -2429,6 +2663,10 @@ _init_commands ();
 if (!_parse_options (argc_ptr, argv_ptr))
         goto error_done_commands;
 
+if (!opt_script_mode)
+        if (init_readline ())
+                goto error_done_commands;
+
 #ifdef HAVE_GETUID
         if (getuid() != 0 && !opt_script_mode) {
             puts (_("WARNING: You are not superuser.  Watch out for "
@@ -2486,7 +2724,7 @@ main (int argc, char** argv)
         PedDevice*      dev;
         int             status;
 
-        program_name = argv[0];
+        set_program_name (argv[0]);
         atexit (close_stdout);
 
         dev = _init (&argc, &argv);