/* libguestfs - guestfish and guestmount shared option parsing
- * Copyright (C) 2010 Red Hat Inc.
+ * Copyright (C) 2010-2011 Red Hat 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 <stdio.h>
#include <stdlib.h>
+#include "c-ctype.h"
+
#include "guestfs.h"
#include "options.h"
if (drv) {
next_drive = add_drives (drv->next, next_drive);
+ if (asprintf (&drv->device, "/dev/sd%c", next_drive) == -1) {
+ perror ("asprintf");
+ exit (EXIT_FAILURE);
+ }
+
switch (drv->type) {
case drv_a:
ad_optargs.bitmask = 0;
if (r == -1)
exit (EXIT_FAILURE);
+ drv->nr_drives = 1;
next_drive++;
break;
if (r == -1)
exit (EXIT_FAILURE);
+ drv->nr_drives = r;
next_drive += r;
break;
if (r == -1)
exit (EXIT_FAILURE);
- if (asprintf (&drv->N.device, "/dev/sd%c", next_drive) == -1) {
- perror ("asprintf");
- exit (EXIT_FAILURE);
- }
-
+ drv->nr_drives = 1;
next_drive++;
break;
return next_drive;
}
+static void display_mountpoints_on_failure (const char *mp_device);
+static void canonical_device_name (char *dev);
+
/* List is built in reverse order, so mount them in reverse order. */
void
mount_mps (struct mp *mp)
if (mp) {
mount_mps (mp->next);
+ const char *options;
+ if (mp->options)
+ options = mp->options;
+ else if (read_only)
+ options = "ro";
+ else
+ options = "";
+
/* Don't use guestfs_mount here because that will default to mount
* options -o sync,noatime. For more information, see guestfs(3)
* section "LIBGUESTFS GOTCHAS".
*/
- const char *options = read_only ? "ro" : "";
r = guestfs_mount_options (g, options, mp->device, mp->mountpoint);
if (r == -1) {
- /* Display possible mountpoints before exiting. */
- char **fses = guestfs_list_filesystems (g);
- if (fses == NULL || fses[0] == NULL)
- goto out;
- fprintf (stderr,
- _("%s: '%s' could not be mounted. Did you mean one of these?\n"),
- program_name, mp->device);
- size_t i;
- for (i = 0; fses[i] != NULL; i += 2)
- fprintf (stderr, "\t%s (%s)\n", fses[i], fses[i+1]);
-
- out:
+ display_mountpoints_on_failure (mp->device);
exit (EXIT_FAILURE);
}
}
}
+/* If the -m option fails on any command, display a useful error
+ * message listing the mountpoints.
+ */
+static void
+display_mountpoints_on_failure (const char *mp_device)
+{
+ char **fses;
+ size_t i;
+
+ fses = guestfs_list_filesystems (g);
+ if (fses == NULL)
+ return;
+ if (fses[0] == NULL) {
+ free (fses);
+ return;
+ }
+
+ fprintf (stderr,
+ _("%s: '%s' could not be mounted. Did you mean one of these?\n"),
+ program_name, mp_device);
+
+ for (i = 0; fses[i] != NULL; i += 2) {
+ canonical_device_name (fses[i]);
+ fprintf (stderr, "\t%s (%s)\n", fses[i], fses[i+1]);
+ free (fses[i]);
+ free (fses[i+1]);
+ }
+
+ free (fses);
+}
+
+static void
+canonical_device_name (char *dev)
+{
+ if (STRPREFIX (dev, "/dev/") &&
+ (dev[5] == 'h' || dev[5] == 'v') &&
+ dev[6] == 'd' &&
+ c_isalpha (dev[7]) &&
+ (c_isdigit (dev[8]) || dev[8] == '\0'))
+ dev[5] = 's';
+}
+
void
free_drives (struct drv *drv)
{
if (!drv) return;
free_drives (drv->next);
+ free (drv->device);
+
switch (drv->type) {
case drv_a: /* a.filename and a.format are optargs, don't free them */ break;
case drv_d: /* d.filename is optarg, don't free it */ break;
case drv_N:
free (drv->N.filename);
- free (drv->N.device);
drv->N.data_free (drv->N.data);
break;
default: ; /* keep GCC happy */