OSDN Git Service

use gnulib's progname module
[android-x86/external-parted.git] / parted / parted.c
index 7e259f2..9f79ea4 100644 (file)
@@ -1,11 +1,10 @@
 /*
     parted - a frontend to libparted
-    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005, 2006
-    Free Software Foundation, Inc.
+    Copyright (C) 1999-2003, 2005-2008 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 2 of the License, or
+    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,
     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, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "../config.h"
+#include <config.h>
+#include <stdbool.h>
+
+#include "closeout.h"
+#include "configmake.h"
+#include "version-etc.h"
 #include "command.h"
 #include "ui.h"
+#include "progname.h"
 #include "table.h"
 
+#define AUTHORS \
+  "<http://parted.alioth.debian.org/cgi-bin/trac.cgi/browser/AUTHORS>"
+
+/* The official name of this program (e.g., no `g' prefix).  */
+#define PROGRAM_NAME "parted"
+
 #define N_(String) String
 #if ENABLE_NLS
 #  include <libintl.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <limits.h>
+#include "xalloc.h"
 
 #ifdef ENABLE_MTRACE
 #include <mcheck.h>
 #endif
 
-#ifdef HAVE_GETOPT_H
 #include <getopt.h>
 
 /* minimum amount of free space to leave, or maximum amount to gobble up */
@@ -56,26 +67,33 @@ static int MEGABYTE_SECTORS (PedDevice* dev)
         return PED_MEGABYTE_SIZE / dev->sector_size;
 }
 
+/* For long options that have no equivalent short option, use a
+   non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
+enum
+{
+  PRETEND_INPUT_TTY = CHAR_MAX + 1,
+};
+
 
 typedef struct {
         time_t  last_update;
         time_t  predicted_time_left;
 } TimerContext;
 
-static struct option    options[] = {
+static const 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'},
+        {"-pretend-input-tty", 0, NULL, PRETEND_INPUT_TTY},
         {NULL,          0, NULL, 0}
 };
-#endif
 
-static char*    options_help [][2] = {
+static const char *const options_help [][2] = {
         {"help",        N_("displays this help message")},
-        {"list",        N_("lists partition tables of all detected devices")},
+        {"list",        N_("lists partition layout on all block devices")},
         {"machine",     N_("displays machine parseable output")},
         {"script",      N_("never prompts for user intervention")},
         {"version",     N_("displays the version")},
@@ -83,30 +101,31 @@ static char*    options_help [][2] = {
 };
 
 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;
 
-static char* number_msg = N_(
+static const char* number_msg = N_(
 "NUMBER is the partition number used by Linux.  On MS-DOS disk labels, the "
 "primary partitions number from 1 to 4, logical partitions from 5 onwards.\n");
 
-static char* label_type_msg_start = N_("LABEL-TYPE is one of: ");
-static char* flag_msg_start =   N_("FLAG is one of: ");
-static char* unit_msg_start =   N_("UNIT is one of: ");
-static char* part_type_msg =    N_("PART-TYPE is one of: primary, logical, "
+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* part_type_msg =    N_("PART-TYPE is one of: primary, logical, "
                                    "extended\n");
-static char* fs_type_msg_start = N_("FS-TYPE is one of: ");
-static char* start_end_msg =    N_("START and END are disk locations, such as "
+static const char* fs_type_msg_start = N_("FS-TYPE is one of: ");
+static const char* start_end_msg =    N_("START and END are disk locations, such as "
                 "4GB or 10%.  Negative values count from the end of the disk.  "
                 "For example, -1s specifies exactly the last sector.\n");
-static char* state_msg =        N_("STATE is one of: on, off\n");
-static char* device_msg =       N_("DEVICE is usually /dev/hda or /dev/sda\n");
-static char* name_msg =         N_("NAME is any word you want\n");
-static char* resize_msg_start = N_("The partition must have one of the "
+static const char* state_msg =        N_("STATE is one of: on, off\n");
+static const char* device_msg =       N_("DEVICE is usually /dev/hda or /dev/sda\n");
+static const char* name_msg =         N_("NAME is any word you want\n");
+static const char* resize_msg_start = N_("The partition must have one of the "
                                    "following FS-TYPEs: ");
 
-static char* version_msg = N_("GNU Parted Version information:\n");
-static char* copyright_msg = N_(
+static const char* copyright_msg = N_(
 "Copyright (C) 1998 - 2006 Free Software Foundation, Inc.\n"
 "This program is free software, covered by the GNU General Public License.\n"
 "\n"
@@ -124,10 +143,10 @@ static char* mkpart_fs_type_msg;
 static char* resize_fs_type_msg;
 
 static Command* commands [256] = {NULL};
-static PedTimer* timer;
+static PedTimer* g_timer;
 static TimerContext timer_context;
 
-static int _print_all (int cli);
+static int _print_list ();
 static void _done (PedDevice* dev);
 
 static void
@@ -155,8 +174,8 @@ _timer_handler (PedTimer* timer, void* context)
                         printf ("%s... ", timer->state_name);
                 printf (_("%0.f%%\t(time left %.2d:%.2d)"),
                         100.0 * timer->frac,
-                        tcontext->predicted_time_left / 60,
-                        tcontext->predicted_time_left % 60);
+                        (int) (tcontext->predicted_time_left / 60),
+                        (int) (tcontext->predicted_time_left % 60));
 
                 fflush (stdout);
         }
@@ -175,7 +194,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;
@@ -186,7 +205,9 @@ _disk_warn_busy (PedDisk* disk)
 {
         if (ped_device_is_busy (disk->dev))
                 return ped_exception_throw (
-                        PED_EXCEPTION_WARNING,
+                        (opt_script_mode
+                         ? PED_EXCEPTION_ERROR
+                         : PED_EXCEPTION_WARNING),
                         PED_EXCEPTION_IGNORE_CANCEL,
                         _("Partition(s) on %s are being used."),
                         disk->dev->path) == PED_EXCEPTION_IGNORE;
@@ -430,7 +451,6 @@ do_check (PedDevice** dev)
         PedDisk*        disk;
         PedFileSystem*  fs;
         PedPartition*   part = NULL;
-        int             part_num;
 
         disk = ped_disk_new (*dev);
         if (!disk)
@@ -447,7 +467,7 @@ do_check (PedDevice** dev)
         fs = ped_file_system_open (&part->geom);
         if (!fs)
                 goto error_destroy_disk;
-        if (!ped_file_system_check (fs, timer))
+        if (!ped_file_system_check (fs, g_timer))
                 goto error_close_fs;
         ped_file_system_close (fs);
         ped_disk_destroy (disk);
@@ -466,7 +486,6 @@ do_cp (PedDevice** dev)
 {
         PedDisk*                src_disk;
         PedDisk*                dst_disk;
-        PedDevice*              src_device;
         PedPartition*           src = NULL;
         PedPartition*           dst = NULL;
         PedFileSystem*          src_fs;
@@ -504,7 +523,7 @@ do_cp (PedDevice** dev)
         src_fs = ped_file_system_open (&src->geom);
         if (!src_fs)
                 goto error_destroy_disk;
-        dst_fs = ped_file_system_copy (src_fs, &dst->geom, timer);
+        dst_fs = ped_file_system_copy (src_fs, &dst->geom, g_timer);
         if (!dst_fs)
                 goto error_close_src_fs;
         dst_fs_type = dst_fs->type;     /* may be different to src_fs->type */
@@ -519,6 +538,10 @@ do_cp (PedDevice** dev)
         if (src_disk != dst_disk)
                 ped_disk_destroy (src_disk);
         ped_disk_destroy (dst_disk);
+
+        if ((*dev)->type != PED_DEVICE_FILE)
+                disk_is_modified = 1;
+
         return 1;
 
 error_close_src_fs:
@@ -579,12 +602,12 @@ do_mklabel (PedDevice** dev)
         if (!disk) ped_exception_catch ();
         ped_exception_leave_all ();
 
-       if (!_disk_warn_loss (disk))
-                goto error_destroy_disk;
-
         if (disk) {
                 if (!_disk_warn_busy (disk))
                         goto error_destroy_disk;
+                if (!opt_script_mode && !_disk_warn_loss (disk))
+                        goto error_destroy_disk;
+
                 ped_disk_destroy (disk);
         }
 
@@ -598,6 +621,10 @@ do_mklabel (PedDevice** dev)
         if (!ped_disk_commit (disk))
                 goto error_destroy_disk;
         ped_disk_destroy (disk);
+
+        if ((*dev)->type != PED_DEVICE_FILE)
+                disk_is_modified = 1;
+
         return 1;
 
 error_destroy_disk:
@@ -618,17 +645,17 @@ do_mkfs (PedDevice** dev)
         if (!disk)
                 goto error;
 
-        if  (!_partition_warn_loss())
+        if  (!opt_script_mode && !_partition_warn_loss())
                 goto error_destroy_disk;
 
         if (!command_line_get_partition (_("Partition number?"), disk, &part))
                 goto error_destroy_disk;
         if (!_partition_warn_busy (part))
                 goto error_destroy_disk;
-        if (!command_line_get_fs_type (_("File system?"), &type))
+        if (!command_line_get_fs_type (_("File system type?"), &type))
                 goto error_destroy_disk;
 
-        fs = ped_file_system_create (&part->geom, type, timer);
+        fs = ped_file_system_create (&part->geom, type, g_timer);
         if (!fs)
                 goto error_destroy_disk;
         ped_file_system_close (fs);
@@ -640,6 +667,10 @@ do_mkfs (PedDevice** dev)
         if (!ped_disk_commit (disk))
                 goto error_destroy_disk;
         ped_disk_destroy (disk);
+
+        if ((*dev)->type != PED_DEVICE_FILE)
+                disk_is_modified = 1;
+
         return 1;
 
 error_destroy_disk:
@@ -677,11 +708,22 @@ do_mkpart (PedDevice** dev)
                         goto error_destroy_disk;
         }
 
+        /* The undocumented feature that mkpart sometimes takes a
+           partition name is next to useless, at least with a dvh
+           partition table, since it makes the "mkpart" command
+           fail unconditionally for a primary partition.  E.g.,
+           mkpart primary any-name xfs 4096s 5000s
+           requires the name, yet always fails, saying that only
+           logical partitions may have names.
+           If you want a name, use parted's separate "name" command.  */
+
         if (ped_disk_type_check_feature (disk->type,
-                                         PED_DISK_TYPE_PARTITION_NAME)) 
+                                         PED_DISK_TYPE_PARTITION_NAME)
+            && ! (strcmp (disk->type->name, "dvh") == 0
+                  && part_type != PED_PARTITION_LOGICAL))
                 part_name = command_line_get_word (_("Partition name?"),
-                                                   "", NULL, 1); 
-                
+                                                   "", NULL, 1);
+
         peek_word = command_line_peek_word ();
         if (part_type == PED_PARTITION_EXTENDED
             || (peek_word && isdigit (peek_word[0]))) {
@@ -691,8 +733,7 @@ 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;
@@ -716,12 +757,16 @@ do_mkpart (PedDevice** dev)
 
         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,
@@ -752,6 +797,8 @@ do_mkpart (PedDevice** dev)
                 } else {
                         goto error_remove_part;
                 }
+        } else {
+                ped_exception_leave_all();
         }
         ped_exception_catch();
 
@@ -767,10 +814,6 @@ do_mkpart (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);
         
         if (range_start != NULL)
@@ -778,25 +821,19 @@ do_mkpart (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;
 
         return 1;
 
 error_remove_part:
         ped_disk_remove_partition (disk, part);
-error_destroy_all_constraints:
-        ped_constraint_destroy (final_constraint);
 error_destroy_simple_constraints:
-        ped_constraint_destroy (user_constraint);
-        ped_constraint_destroy (dev_constraint);
-error_destroy_part:
         ped_partition_destroy (part);
 error_destroy_disk:
         ped_disk_destroy (disk);
@@ -806,14 +843,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;
 }
@@ -884,12 +917,16 @@ do_mkpartfs (PedDevice** dev)
 
         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,
@@ -919,6 +956,8 @@ do_mkpartfs (PedDevice** dev)
                 } else {
                         goto error_remove_part;
                 }
+        } else {
+                ped_exception_leave_all();
         }
         ped_exception_catch();
 
@@ -927,7 +966,7 @@ do_mkpartfs (PedDevice** dev)
                 ped_partition_set_flag (part, PED_PARTITION_LBA, 1);
 
         /* fs creation */
-        fs = ped_file_system_create (&part->geom, fs_type, timer);
+        fs = ped_file_system_create (&part->geom, fs_type, g_timer);
         if (!fs) 
                 goto error_destroy_disk;
         ped_file_system_close (fs);
@@ -939,9 +978,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);
 
@@ -950,25 +986,19 @@ 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;
 
         return 1;
 
 error_remove_part:
         ped_disk_remove_partition (disk, part);
-error_destroy_all_constraints:
-        ped_constraint_destroy (final_constraint);
 error_destroy_simple_constraints:
-        ped_constraint_destroy (user_constraint);
-        ped_constraint_destroy (dev_constraint);
-error_destroy_part:
         ped_partition_destroy (part);
 error_destroy_disk:
         ped_disk_destroy (disk);
@@ -978,14 +1008,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;
 }
@@ -1047,7 +1073,7 @@ do_move (PedDevice** dev)
         }
 
         /* do the move */
-        fs_copy = ped_file_system_copy (fs, &part->geom, timer);
+        fs_copy = ped_file_system_copy (fs, &part->geom, g_timer);
         if (!fs_copy)
                 goto error_close_fs;
         ped_file_system_close (fs_copy);
@@ -1059,6 +1085,10 @@ do_move (PedDevice** dev)
                 ped_geometry_destroy (range_start);
         if (range_end != NULL)
                 ped_geometry_destroy (range_end);
+
+        if ((*dev)->type != PED_DEVICE_FILE)
+                disk_is_modified = 1;
+
         return 1;
 
 error_destroy_constraint:
@@ -1166,8 +1196,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
@@ -1181,30 +1211,30 @@ partition_print (PedPartition* part)
         if (!fs)
                 return 1;
 
-        printf ("\n");
+        putchar ('\n');
 
         flags = partition_print_flags (part);
-     
+
         printf (_("Minor: %d\n"), part->num);
         printf (_("Flags: %s\n"), flags);
         printf (_("File System: %s\n"), fs->type->name);
-        printf (_("Size:         "));
+        fputs (_("Size:         "), stdout);
         print_sector_compact_and_percent (part->geom.length, part->geom.dev);
 
         resize_constraint = ped_file_system_get_resize_constraint (fs);
         if (resize_constraint) {
-                printf (_("Minimum size: "));
+                fputs (_("Minimum size: "), stdout);
                 print_sector_compact_and_percent (resize_constraint->min_size,
                         part->geom.dev);
-                printf (_("Maximum size: "));
+                fputs (_("Maximum size: "), stdout);
                 print_sector_compact_and_percent (resize_constraint->max_size,
                         part->geom.dev);
                 ped_constraint_destroy (resize_constraint);
         }
 
-        printf ("\n");
+        putchar ('\n');
 
-        ped_free (flags);
+        free (flags);
         ped_file_system_close (fs);
 
         return 1;
@@ -1213,25 +1243,26 @@ partition_print (PedPartition* part)
 static int
 do_print (PedDevice** dev)
 {
+        PedUnit         default_unit;
         PedDisk*        disk;
-        PedPartition*   part;
         Table*          table;
-        StrList*        row;
         int             has_extended;
         int             has_name;
-        int             has_all_arg = 0;
         int             has_devices_arg = 0;
         int             has_free_arg = 0;
+        int             has_list_arg = 0;
         int             has_num_arg = 0;
-        char*           transport[13] = {"unknown", "scsi", "ide", "dac960",
-                                         "cpqarray", "file", "ataraid", "i2o",
-                                         "ubd", "dasd", "viodasd", "sx8", "dm"};
+        const char *const transport[14] = {"unknown", "scsi", "ide", "dac960",
+                                          "cpqarray", "file", "ataraid", "i2o",
+                                          "ubd", "dasd", "viodasd", "sx8", "dm",
+                                          "xvd"};
         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);
@@ -1240,32 +1271,28 @@ do_print (PedDevice** dev)
 
         peek_word = command_line_peek_word ();
         if (peek_word) {
-                has_num_arg = isdigit (peek_word[0]);
-
-                if (strncmp (peek_word, "all", 3) == 0) {
-                        command_line_pop_word();
-                        has_all_arg = 1;
-                }
-
-                else if (strncmp (peek_word, "devices", 7) == 0) {
+                if (strncmp (peek_word, "devices", 7) == 0) {
                         command_line_pop_word();
                         has_devices_arg = 1;
                 }
-
                 else if (strncmp (peek_word, "free", 4) == 0) {
                         command_line_pop_word ();
                         has_free_arg = 1;
                 } 
+                else if (strncmp (peek_word, "list", 4) == 0 ||
+                         strncmp (peek_word, "all", 3) == 0) {
+                        command_line_pop_word();
+                        has_list_arg = 1;
+                }
+                else
+                        has_num_arg = isdigit(peek_word[0]);
 
-                ped_free (peek_word);
-
+                free (peek_word);
         }
 
-        if (has_all_arg) 
-                return _print_all (0);
-
-        else if (has_devices_arg) {
-                PedDevice *current_dev = NULL;
+        if (has_devices_arg) {
+                char*           dev_name;
+                PedDevice*      current_dev = NULL;
 
                 ped_device_probe_all();
 
@@ -1274,12 +1301,26 @@ 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 ();
+
+                *dev = ped_device_get (dev_name);
+                if (!*dev)
+                       return 0;
+                if (!ped_device_open (*dev))
+                        return 0;
+
+                free (dev_name);
+
                 return 1;
         }
 
+        else if (has_list_arg) 
+                return _print_list ();
+
         else if (has_num_arg) {
                 PedPartition*   part = NULL;
                 int             status = 0;
@@ -1290,16 +1331,18 @@ do_print (PedDevice** dev)
         }
 
         start = ped_unit_format (*dev, 0);
+        default_unit = ped_unit_get_default ();
         end = ped_unit_format_byte (*dev, (*dev)->length * (*dev)->sector_size
-                                          - 1 );
-        
+                                    - (default_unit == PED_UNIT_CHS ||
+                                       default_unit == PED_UNIT_CYLINDER));
+
         if (opt_machine_mode) {
-            switch (ped_unit_get_default ()) {
-                case PED_UNIT_CHS:      printf ("CHS;\n");
+            switch (default_unit) {
+                case PED_UNIT_CHS:      puts ("CHS;");
                                         break;
-                case PED_UNIT_CYLINDER: printf ("CYL;\n");
+                case PED_UNIT_CYLINDER: puts ("CYL;");
                                         break;
-                default:                printf ("BYT;\n");
+                default:                puts ("BYT;");
                                         break;
 
             }
@@ -1308,7 +1351,6 @@ do_print (PedDevice** dev)
                     (*dev)->sector_size, (*dev)->phys_sector_size,
                     disk->type->name, (*dev)->model);
         } else {
-            printf ("\n");
             printf (_("Model: %s (%s)\n"), 
                     (*dev)->model, transport[(*dev)->type]);
             printf (_("Disk %s: %s\n"), (*dev)->path, end);
@@ -1316,8 +1358,8 @@ do_print (PedDevice** dev)
                     (*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) {
@@ -1335,12 +1377,12 @@ 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);
-            printf ("\n");
+            putchar ('\n');
         }
         
         has_extended = ped_disk_type_check_feature (disk->type,
@@ -1349,31 +1391,32 @@ do_print (PedDevice** dev)
                                          PED_DISK_TYPE_PARTITION_NAME);
 
         
+        PedPartition* part;
         if (!opt_machine_mode) {
+            StrList *row1;
 
             if (ped_unit_get_default() == PED_UNIT_CHS) {
-                    row = str_list_create (_("Number"), _("Start"),
+                    row1 = str_list_create (_("Number"), _("Start"),
                                                _("End"), NULL);
             } else {
-                    row = str_list_create (_("Number"), _("Start"),
+                    row1 = str_list_create (_("Number"), _("Start"),
                                                _("End"), _("Size"), NULL);
             }
 
             if (has_extended)
-                    str_list_append (row, _("Type"));
+                    str_list_append (row1, _("Type"));
 
-            str_list_append (row, _("File system"));
+            str_list_append (row1, _("File system"));
 
             if (has_name)
-                    str_list_append (row, _("Name"));
-
-            str_list_append (row, _("Flags"));
+                    str_list_append (row1, _("Name"));
 
+            str_list_append (row1, _("Flags"));
 
-            table = table_new (str_list_length(row));
 
-            table_add_row_from_strlist (table, row);
+            table = table_new (str_list_length(row1));
 
+            table_add_row_from_strlist (table, row1);
 
             for (part = ped_disk_next_partition (disk, NULL); part;
                  part = ped_disk_next_partition (disk, part)) {
@@ -1389,7 +1432,7 @@ do_print (PedDevice** dev)
                     else
                             sprintf (tmp, "%2s ", "");
 
-                    row = str_list_create (tmp, NULL);
+                    StrList *row = str_list_create (tmp, NULL);
 
                     start = ped_unit_format (*dev, part->geom.start);
                     end = ped_unit_format_byte (
@@ -1407,8 +1450,7 @@ do_print (PedDevice** dev)
 
                     if (!(part->type & PED_PARTITION_FREESPACE)) {
                             if (has_extended) {
-                                name = 
-                                    _(ped_partition_type_get_name (part->type));
+                                name = ped_partition_type_get_name (part->type);
                                 str_list_append (row, name);
                             }
 
@@ -1416,11 +1458,13 @@ do_print (PedDevice** dev)
                                              part->fs_type->name : "");
 
                             if (has_name) {
-                                    name = _(ped_partition_get_name (part));
+                                    name = ped_partition_get_name (part);
                                     str_list_append (row, name);
                             }
 
-                            str_list_append (row, partition_print_flags (part));
+                            flags = partition_print_flags (part);
+                            str_list_append (row, flags);
+                            free (flags);
                     } else {
                             if (has_extended)
                                     str_list_append (row, "");
@@ -1432,6 +1476,11 @@ do_print (PedDevice** dev)
 
                     //PED_ASSERT (row.cols == caption.cols)
                     table_add_row_from_strlist (table, row);
+                    str_list_destroy (row);
+                    free (tmp);
+                    free (start);
+                    free (end);
+                    free (size);
             }
 
             table_rendered = table_render (table); 
@@ -1440,8 +1489,9 @@ do_print (PedDevice** dev)
 #else
             printf("%s\n", table_rendered);
 #endif
-            ped_free (table_rendered);
+            free (table_rendered);
             table_destroy (table);
+            str_list_destroy (row1);
 
         } else {
     
@@ -1455,34 +1505,39 @@ do_print (PedDevice** dev)
                 if (part->num >= 0)
                     printf ("%d:", part->num);
                 else
-                    printf ("1:");
-
-                printf ("%s:", ped_unit_format (*dev, part->geom.start));
-                printf ("%s:", ped_unit_format_byte (
-                                *dev,
-                                (part->geom.end + 1) * 
-                                (*dev)->sector_size - 1));
-
-                if (ped_unit_get_default() != PED_UNIT_CHS)
-                    printf ("%s:", ped_unit_format (*dev,
-                                                    part->geom.length));
+                    fputs ("1:", stdout);
+
+                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 (!(part->type & PED_PARTITION_FREESPACE)) {
 
                     if (part->fs_type)
                         printf ("%s:", part->fs_type->name);
                     else
-                        printf (":");
+                        putchar (':');
 
                     if (has_name) 
                         printf ("%s:", _(ped_partition_get_name (part)));
                     else
-                        printf (":");
+                        putchar (':');
 
                     printf ("%s;\n", partition_print_flags (part));
 
                 } else {
-                    printf ("free;\n");
+                    puts ("free;");
                 }
             }
         }
@@ -1491,14 +1546,13 @@ do_print (PedDevice** dev)
 
         return 1;
 
-error_destroy_disk:
         ped_disk_destroy (disk);
 error:
         return 0;
 }
 
 static int
-_print_all (int cli)
+_print_list ()
 {
         PedDevice *current_dev = NULL;
 
@@ -1506,12 +1560,9 @@ _print_all (int cli)
 
         while ((current_dev = ped_device_get_next(current_dev))) {
                 do_print (&current_dev);
-                printf ("\n");
+                putchar ('\n');
         }    
 
-        if(cli)
-                exit(0);
-
         return 1;
 }
 
@@ -1580,12 +1631,13 @@ _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;
                 case PED_EXCEPTION_NO: return 0;
+                default: break;
         }
 
         ped_partition_set_system (part, fs_type);
@@ -1612,10 +1664,10 @@ _rescue_pass (PedDisk* disk, PedGeometry* start_range, PedGeometry* end_range)
 
         ped_geometry_init (&entire_dev, disk->dev, 0, disk->dev->length);
 
-        ped_timer_reset (timer);
-        ped_timer_set_state_name (timer, _("searching for file systems"));
+        ped_timer_reset (g_timer);
+        ped_timer_set_state_name (g_timer, _("searching for file systems"));
         for (start = start_range->start; start <= start_range->end; start++) {
-                ped_timer_update (timer, 1.0 * (start - start_range->start)
+                ped_timer_update (g_timer, 1.0 * (start - start_range->start)
                                          / start_range->length);
 
                 ped_geometry_init (&start_geom_exact, disk->dev, start, 1);
@@ -1651,17 +1703,14 @@ _rescue_pass (PedDisk* disk, PedGeometry* start_range, PedGeometry* end_range)
                 ped_partition_destroy (part);
                 ped_constraint_done (&constraint);
         }
-        ped_timer_update (timer, 1.0);
+        ped_timer_update (g_timer, 1.0);
 
         return 1;
 
 error_remove_partition:
         ped_disk_remove_partition (disk, part);
-error_partition_destroy:
         ped_partition_destroy (part);
-error_constraint_done:
         ped_constraint_done (&constraint);
-error:
         return 0;
 }
 
@@ -1697,6 +1746,10 @@ do_rescue (PedDevice** dev)
                 goto error_destroy_disk;
 
         ped_disk_destroy (disk);
+
+        if ((*dev)->type != PED_DEVICE_FILE)
+                disk_is_modified = 1;
+
         return 1;
 
 error_destroy_disk:
@@ -1757,7 +1810,7 @@ do_resize (PedDevice** dev)
                 if (!ped_disk_set_partition_geom (disk, part, constraint,
                                                   new_geom.start, new_geom.end))
                         goto error_close_fs;
-                if (!ped_file_system_resize (fs, &part->geom, timer))
+                if (!ped_file_system_resize (fs, &part->geom, g_timer))
                         goto error_close_fs;
                 /* may have changed... eg fat16 -> fat32 */
                 ped_partition_set_system (part, fs->type);
@@ -1771,6 +1824,10 @@ do_resize (PedDevice** dev)
                 ped_geometry_destroy (range_start);
         if (range_end != NULL)
                 ped_geometry_destroy (range_end);
+
+        if ((*dev)->type != PED_DEVICE_FILE)
+                disk_is_modified = 1;
+
         return 1;
 
 error_close_fs:
@@ -1805,6 +1862,10 @@ do_rm (PedDevice** dev)
         ped_disk_delete_partition (disk, part);
         ped_disk_commit (disk);
         ped_disk_destroy (disk);
+
+        if ((*dev)->type != PED_DEVICE_FILE)
+                disk_is_modified = 1;
+
         return 1;
 
 error_destroy_disk:
@@ -1857,6 +1918,10 @@ do_set (PedDevice** dev)
        if (!ped_disk_commit (disk))
                        goto error_destroy_disk;
        ped_disk_destroy (disk);
+
+        if ((*dev)->type != PED_DEVICE_FILE)
+                disk_is_modified = 1;
+
            return 1;
 
 error_destroy_disk:
@@ -2051,7 +2116,7 @@ NULL),
                 str_list_create_unique ("help", _("help"), NULL),
                 do_help,
                 str_list_create (
-_("help [COMMAND]                           prints general help, or help "
+_("help [COMMAND]                           print general help, or help "
   "on COMMAND"),
 NULL),
                 NULL, 1));
@@ -2084,7 +2149,7 @@ NULL),
                                  _(mkpart_fs_type_msg),
                                  _(start_end_msg),
                                  "\n",
-_("mkpart makes a partition without creating a new file system on the "
+_("'mkpart' makes a partition without creating a new file system on the "
   "partition.  FS-TYPE may be specified to set an appropriate partition ID.\n"),
 NULL), 1));
 
@@ -2093,7 +2158,7 @@ NULL), 1));
                 do_mkpartfs,
                 str_list_create (
 _("mkpartfs PART-TYPE FS-TYPE START END     make a partition with a "
-"file system"),
+  "file system"),
 NULL),
         str_list_create (_(part_type_msg), _(start_end_msg), NULL), 1));
 
@@ -2117,16 +2182,20 @@ command_register (commands, command_create (
         str_list_create_unique ("print", _("print"), NULL),
         do_print,
         str_list_create (
-_("print [NUMBER|all|devices|free]          display the partition table, "
-  "a partition, or all devices"),
+_("print [devices|free|list,all|NUMBER]     display the partition table, "
+  "available devices, free space, all found partitions, or a particular "
+  "partition"),
 NULL),
         str_list_create (
-_("Without arguments, print displays the entire partition table. With 'devices',\n"
-"all the active block devices are listed, while with the argument 'free'\n"
-"information about free space will be displayed. If a partition number is given,\n"
-"then more detailed information is displayed about that partition. If the 'all'\n"
-"argument is passed instead, partition information for all devices will be\n"
-"displayed.\n"), NULL), 1));
+_("Without arguments, 'print' displays the entire partition table. However "
+  "with the following arguments it performs various other actions.\n"),
+_("  devices   : display all active block devices\n"),
+_("  free      : display information about free unpartitioned space on the "
+  "current block device\n"),
+_("  list, all : display the partition tables of all active block devices\n"),
+_("  NUMBER    : display more detailed information about this particular "
+  "partition\n"),
+NULL), 1));
 
 command_register (commands, command_create (
         str_list_create_unique ("quit", _("quit"), NULL),
@@ -2202,11 +2271,11 @@ command_register (commands, command_create (
         str_list_create_unique ("version", _("version"), NULL),
         do_version,
         str_list_create (
-_("version                                  displays the current version "
-"of GNU Parted and copyright information"),
+_("version                                  display the version number "
+"and copyright information of GNU Parted"),
 NULL),
         str_list_create (
-_("version displays copyright and version information corressponding to this "
+_("'version' displays copyright and version information corresponding to this "
 "copy of GNU Parted\n"),
 NULL), 1));
 
@@ -2237,41 +2306,60 @@ textdomain(PACKAGE);
 void
 _version ()
 {
-printf (prog_name);
-exit (0);
+  version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, VERSION, AUTHORS,
+               (char *) NULL);
 }
 
 static int
 _parse_options (int* argc_ptr, char*** argv_ptr)
 {
-int     opt;
+int     opt, help = 0, list = 0, version = 0, wrong = 0;
 
 while (1)
 {
-#ifdef HAVE_GETOPT_H
         opt = getopt_long (*argc_ptr, *argv_ptr, "hilmsv",
                            options, NULL);
-#else
-        opt = getopt (*argc_ptr, *argv_ptr, "hilmsv");
-#endif
         if (opt == -1)
                 break;
 
         switch (opt) {
-                case 'h': help_msg (); break;
-                case 'l': _print_all(1); break;
+                case 'h': help = 1; break;
+                case 'l': list = 1; break;
                 case 'm': opt_machine_mode = 1; break;
                 case 's': opt_script_mode = 1; break;
-                case 'v': _version (); break;
+                case 'v': version = 1; break;
+                case PRETEND_INPUT_TTY:
+                  pretend_input_tty = 1;
+                  break;
+                default:  wrong = 1; break;
         }
 }
 
+if (wrong == 1) {
+        fprintf (stderr,
+                 _("Usage: %s [-hlmsv] [DEVICE [COMMAND [PARAMETERS]]...]\n"),
+                 program_name);
+        return 0;
+}
+
+if (version == 1) {
+        _version ();
+        exit (EXIT_SUCCESS);
+}
+
+if (help == 1) {
+        help_msg ();
+        exit (EXIT_SUCCESS);
+}
+
+if (list == 1) {
+        _print_list ();
+        exit (EXIT_SUCCESS);
+}
+
 *argc_ptr -= optind;
 *argv_ptr += optind;
 return 1;
-
-error:
-return 0;
 }
 
 static PedDevice*
@@ -2325,9 +2413,9 @@ if (!_parse_options (argc_ptr, argv_ptr))
         goto error_done_commands;
 
 #ifdef HAVE_GETUID
-        if (getuid() != 0) {
-            printf(_("WARNING: You are not superuser.  Watch out for "
-                     "permissions.\n"));
+        if (getuid() != 0 && !opt_script_mode) {
+            puts (_("WARNING: You are not superuser.  Watch out for "
+                    "permissions."));
         }
 #endif
 
@@ -2335,8 +2423,8 @@ dev = _choose_device (argc_ptr, argv_ptr);
 if (!dev)
         goto error_done_commands;
 
-timer = ped_timer_new (_timer_handler, &timer_context);
-if (!timer)
+g_timer = ped_timer_new (_timer_handler, &timer_context);
+if (!g_timer)
         goto error_done_commands;
 timer_context.last_update = 0;
 
@@ -2345,7 +2433,6 @@ return dev;
 error_done_commands:
 _done_commands ();
 _done_messages ();
-error_done_ui:
 done_ui ();
 error:
 return NULL;
@@ -2362,16 +2449,15 @@ if (dev->boot_dirty && dev->type != PED_DEVICE_FILE) {
           "rebooting.  Read section 4 of the Parted User "
           "documentation for more information."));
 }
-if (dev->type != PED_DEVICE_FILE && !opt_script_mode && !opt_machine_mode) {
+if (!opt_script_mode && !opt_machine_mode && disk_is_modified) {
         ped_exception_throw (
                 PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK,
-                _("Don't forget to update /etc/fstab, if "
-                  "necessary.\n"));
+                _("You may need to update /etc/fstab.\n"));
 }
 
 ped_device_close (dev);
 
-ped_timer_destroy (timer);
+ped_timer_destroy (g_timer);
 _done_commands ();
 _done_messages ();
 done_ui();
@@ -2383,6 +2469,9 @@ main (int argc, char** argv)
         PedDevice*      dev;
         int             status;
 
+        set_program_name (argv[0]);
+        atexit (close_stdout);
+
         dev = _init (&argc, &argv);
         if (!dev)
                 return 1;