The strdup/strndup() introduces malloc() to allocate memory,
so we need to free them carefully.
Signed-off-by: Wanlong Gao <gaowanlong(a)cn.fujitsu.com>
---
format/format.c | 88 +++++++++++++++++++++++++++++++++---------------------
1 files changed, 54 insertions(+), 34 deletions(-)
diff --git a/format/format.c b/format/format.c
index b3a47cd..cc7563d 100644
--- a/format/format.c
+++ b/format/format.c
@@ -51,7 +51,7 @@ static const char *vg = NULL, *lv = NULL;
static const char *partition = "DEFAULT";
static int wipe = 0;
-static void parse_vg_lv (const char *lvm);
+static int parse_vg_lv (const char *lvm);
static int do_format (void);
static int do_rescan (char **devices);
@@ -61,7 +61,7 @@ bad_cast (char const *s)
return (char *) s;
}
-static void __attribute__((noreturn))
+static void
usage (int status)
{
char *warning =
@@ -96,7 +96,6 @@ usage (int status)
program_name, warning, program_name, program_name,
warning);
}
- exit (status);
}
int
@@ -156,7 +155,7 @@ main (int argc, char *argv[])
else if (optarg[0] == '-') { /* eg: --filesystem --lvm */
fprintf (stderr, _("%s: no filesystem was specified\n"),
program_name);
- exit (EXIT_FAILURE);
+ goto fail;
} else
filesystem = optarg;
} else if (STREQ (long_options[option_index].name, "lvm")) {
@@ -164,17 +163,19 @@ main (int argc, char *argv[])
fprintf (stderr,
_("%s: --lvm option cannot be given multiple times\n"),
program_name);
- exit (EXIT_FAILURE);
+ goto fail;
}
if (optarg == NULL) {
vg = strdup ("VG");
lv = strdup ("LV");
- if (!vg || !lv) { perror ("strdup"); exit (EXIT_FAILURE); }
+ if (!vg || !lv) { perror ("strdup"); goto fail; }
}
else if (STREQ (optarg, "none"))
vg = lv = NULL;
- else
- parse_vg_lv (optarg);
+ else {
+ if (parse_vg_lv (optarg) == -1)
+ goto fail;
+ }
} else if (STREQ (long_options[option_index].name, "partition")) {
if (optarg == NULL)
partition = "DEFAULT";
@@ -187,7 +188,7 @@ main (int argc, char *argv[])
} else {
fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
program_name, long_options[option_index].name, option_index);
- exit (EXIT_FAILURE);
+ goto fail;
}
break;
@@ -209,9 +210,11 @@ main (int argc, char *argv[])
case HELP_OPTION:
usage (EXIT_SUCCESS);
+ exit (EXIT_SUCCESS);
default:
usage (EXIT_FAILURE);
+ goto fail;
}
}
@@ -224,12 +227,16 @@ main (int argc, char *argv[])
assert (live == 0);
/* Must be no extra arguments on the command line. */
- if (optind != argc)
- usage (EXIT_FAILURE);
+ if (optind != argc) {
+ usage(EXIT_FAILURE);
+ goto fail;
+ }
/* The user didn't specify any drives to format. */
- if (drvs == NULL)
+ if (drvs == NULL) {
usage (EXIT_FAILURE);
+ goto fail;
+ }
/* Because the libguestfs kernel can get stuck rereading the
* partition table after things have been erased, we sometimes need
@@ -240,11 +247,13 @@ main (int argc, char *argv[])
add_drives (drvs, 'a');
if (guestfs_launch (g) == -1)
- exit (EXIT_FAILURE);
+ goto fail;
/* Perform the format. */
retry = do_format ();
- if (!retry)
+ if (retry == -1)
+ goto fail;
+ else if (!retry)
break;
if (retries == 0) {
@@ -266,22 +275,31 @@ main (int argc, char *argv[])
"data which we are unable to remove. If you think this\n"
"is a bug, please file a bug at
http://libguestfs.org/\n"),
program_name);
- exit (EXIT_FAILURE);
+ goto fail;
}
}
+ free ((char *) vg);
+ free ((char *) lv);
/* Free up data structures. */
free_drives (drvs);
guestfs_close (g);
exit (EXIT_SUCCESS);
+
+fail:
+ free ((char *)vg);
+ free ((char *)lv);
+ free_drives (drvs);
+ guestfs_close (g);
+ exit (EXIT_FAILURE);
}
/* Parse lvm string of the form "/dev/VG/LV" or "VG/LV".
* This sets the global variables 'vg' and 'lv', or exits on failure.
*/
-static void
+static int
parse_vg_lv (const char *lvm)
{
size_t i;
@@ -296,20 +314,22 @@ parse_vg_lv (const char *lvm)
if (!vg || !lv) {
perror ("strdup");
- exit (EXIT_FAILURE);
+ return -1;
}
} else {
cannot_parse:
fprintf (stderr, _("%s: cannot parse --lvm option (%s)\n"),
program_name, lvm);
- exit (EXIT_FAILURE);
+ return -1;
}
if (strchr (vg, '/') || strchr (lv, '/'))
goto cannot_parse;
+
+ return 0;
}
-/* Returns 0 on success, 1 if we need to retry. */
+/* Returns 0 on success, 1 if we need to retry. -1 for fail */
static int
do_format (void)
{
@@ -319,7 +339,7 @@ do_format (void)
devices = guestfs_list_devices (g);
if (devices == NULL)
- exit (EXIT_FAILURE);
+ return -1;
/* Erase the disks. */
if (!wipe) {
@@ -328,11 +348,11 @@ do_format (void)
/* No wipe, but get rid of LVM metadata by erasing each partition. */
parts = guestfs_list_partitions (g);
if (parts == NULL)
- exit (EXIT_FAILURE);
+ return -1;
for (i = 0; parts[i] != NULL; ++i) {
if (guestfs_zero (g, parts[i]) == -1)
- exit (EXIT_FAILURE);
+ return -1;
free (parts[i]);
}
free (parts);
@@ -340,13 +360,13 @@ do_format (void)
/* Then erase the partition table on each device. */
for (i = 0; devices[i] != NULL; ++i) {
if (guestfs_zero (g, devices[i]) == -1)
- exit (EXIT_FAILURE);
+ return -1;
}
}
else /* wipe */ {
for (i = 0; devices[i] != NULL; ++i) {
if (guestfs_zero_device (g, devices[i]) == -1)
- exit (EXIT_FAILURE);
+ return -1;
}
}
@@ -368,15 +388,15 @@ do_format (void)
if (STREQ (partition, "DEFAULT")) {
dev_size = guestfs_blockdev_getsize64 (g, devices[i]);
if (dev_size == -1)
- exit (EXIT_FAILURE);
+ return -1;
ptype = dev_size < INT64_C(2)*1024*1024*1024*1024 ? "mbr" :
"gpt";
}
if (guestfs_part_disk (g, devices[i], ptype) == -1)
- exit (EXIT_FAILURE);
+ return -1;
if (asprintf (&dev, "%s1", devices[i]) == -1) {
perror ("asprintf");
- exit (EXIT_FAILURE);
+ return -1;
}
free_dev = 1;
}
@@ -385,29 +405,29 @@ do_format (void)
char *devs[2] = { dev, NULL };
if (guestfs_pvcreate (g, dev) == -1)
- exit (EXIT_FAILURE);
+ return -1;
if (guestfs_vgcreate (g, vg, devs) == -1)
- exit (EXIT_FAILURE);
+ return -1;
if (guestfs_lvcreate (g, lv, vg, 32) == -1) /* 32 MB is smallest LV */
- exit (EXIT_FAILURE);
+ return -1;
if (free_dev)
free (dev);
if (asprintf (&dev, "/dev/%s/%s", vg, lv) == -1) {
perror ("asprintf");
- exit (EXIT_FAILURE);
+ return -1;
}
free_dev = 1;
if (guestfs_lvresize_free (g, dev, 100) == -1)
- exit (EXIT_FAILURE);
+ return -1;
}
if (filesystem) {
if (guestfs_mkfs_opts (g, filesystem, dev, -1) == -1)
- exit (EXIT_FAILURE);
+ return -1;
}
if (free_dev)
@@ -415,7 +435,7 @@ do_format (void)
}
if (guestfs_sync (g) == -1)
- exit (EXIT_FAILURE);
+ return -1;
ret = 0;
--
1.7.9