summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generator/generator_actions.ml7
-rwxr-xr-xregressions/test-inspect-fstab.sh36
-rw-r--r--src/guestfs-internal.h1
-rw-r--r--src/guestfs.c1
-rw-r--r--src/inspect_fs_unix.c55
-rw-r--r--src/launch.c8
6 files changed, 84 insertions, 24 deletions
diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml
index 4967ce20..e8a32ac0 100644
--- a/generator/generator_actions.ml
+++ b/generator/generator_actions.ml
@@ -1007,7 +1007,7 @@ be mountable but require special options. Filesystems may
not all belong to a single logical operating system
(use C<guestfs_inspect_os> to look for OSes).");
- ("add_drive_opts", (RErr, [String "filename"], [Bool "readonly"; String "format"; String "iface"]), -1, [FishAlias "add"],
+ ("add_drive_opts", (RErr, [String "filename"], [Bool "readonly"; String "format"; String "iface"; String "name"]), -1, [FishAlias "add"],
[],
"add an image to examine or modify",
"\
@@ -1050,6 +1050,11 @@ this security hole.
This rarely-used option lets you emulate the behaviour of the
deprecated C<guestfs_add_drive_with_if> call (q.v.)
+=item C<name>
+
+The name the drive had in the original guest, e.g. /dev/sdb. This is used as a
+hint to the guest inspection process if it is available.
+
=back");
("inspect_get_windows_systemroot", (RString "systemroot", [Device "root"], []), -1, [],
diff --git a/regressions/test-inspect-fstab.sh b/regressions/test-inspect-fstab.sh
index fb284152..bb79a817 100755
--- a/regressions/test-inspect-fstab.sh
+++ b/regressions/test-inspect-fstab.sh
@@ -49,15 +49,11 @@ $guestfish -a test1.img <<'EOF'
upload test.fstab /etc/fstab
EOF
-rm test.fstab
-
# This will give a warning, but should not fail.
$guestfish -a test1.img -i <<'EOF' | sort > test.output
inspect-get-mountpoints /dev/VG/Root
EOF
-rm test1.img
-
if [ "$(cat test.output)" != "/: /dev/VG/Root
/boot: /dev/vda1
/nosuchfile: /dev/VG/LV1
@@ -67,4 +63,36 @@ if [ "$(cat test.output)" != "/: /dev/VG/Root
exit 1
fi
+# Test device name hints
+
+cat <<'EOF' > test.fstab
+/dev/VG/Root / ext2 default 0 0
+
+# Device name which requires a hint
+/dev/xvdg1 /boot ext2 default 0 0
+EOF
+
+$guestfish -a test1.img <<'EOF'
+ run
+ mount-options "" /dev/VG/Root /
+ upload test.fstab /etc/fstab
+EOF
+
+$guestfish <<'EOF' > test.output
+ add-drive-opts test1.img readonly:true name:xvdg
+ run
+ inspect-os
+ inspect-get-mountpoints /dev/VG/Root
+EOF
+
+if [ "$(cat test.output)" != "/dev/VG/Root
+/: /dev/VG/Root
+/boot: /dev/vda1" ]; then
+ echo "$0: error: unexpected output from inspect-get-mountpoints command"
+ cat test.output
+ exit 1
+fi
+
+rm test.fstab
+rm test1.img
rm test.output
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 7bdb4e44..9b690b4a 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -158,6 +158,7 @@ struct drive {
int readonly;
char *format;
char *iface;
+ char *name;
int use_cache_off;
};
diff --git a/src/guestfs.c b/src/guestfs.c
index 170d0d32..f4b79e76 100644
--- a/src/guestfs.c
+++ b/src/guestfs.c
@@ -1008,6 +1008,7 @@ guestfs___free_drives (struct drive **drives)
free (i->path);
free (i->format);
free (i->iface);
+ free (i->name);
free (i);
i = next;
diff --git a/src/inspect_fs_unix.c b/src/inspect_fs_unix.c
index 34e65bf6..77834a1d 100644
--- a/src/inspect_fs_unix.c
+++ b/src/inspect_fs_unix.c
@@ -107,7 +107,7 @@ compile_regexps (void)
"Scientific Linux.*release (\\d+)", 0);
COMPILE (re_major_minor, "(\\d+)\\.(\\d+)", 0);
COMPILE (re_aug_seq, "/\\d+$", 0);
- COMPILE (re_xdev, "^/dev/(?:h|s|v|xv)d([a-z]+)(\\d*)$", 0);
+ COMPILE (re_xdev, "^/dev/(h|s|v|xv)d([a-z]+)(\\d*)$", 0);
COMPILE (re_freebsd, "^/dev/ad(\\d+)s(\\d+)([a-z])$", 0);
COMPILE (re_netbsd, "^NetBSD (\\d+)\\.(\\d+)", 0);
}
@@ -817,7 +817,7 @@ static char *
resolve_fstab_device (guestfs_h *g, const char *spec)
{
char *device = NULL;
- char *slice, *disk, *part;
+ char *type, *slice, *disk, *part;
if (STRPREFIX (spec, "/dev/mapper/")) {
/* LVM2 does some strange munging on /dev/mapper paths for VGs and
@@ -832,33 +832,50 @@ resolve_fstab_device (guestfs_h *g, const char *spec)
*/
device = guestfs_lvm_canonical_lv_name (g, spec);
}
- else if (match2 (g, spec, re_xdev, &disk, &part)) {
- /* disk: ([a-z]+)
+ else if (match3 (g, spec, re_xdev, &type, &disk, &part)) {
+ /* type: (h|s|v|xv)
+ * disk: ([a-z]+)
* part: (\d*) */
char **devices = guestfs_list_devices (g);
if (devices == NULL)
return NULL;
- /* Count how many disks the libguestfs appliance has */
- size_t count;
- for (count = 0; devices[count] != NULL; count++)
- ;
+ /* Check any hints we were passed for a non-heuristic mapping */
+ char *name = safe_asprintf (g, "%sd%s", type, disk);
+ size_t i = 0;
+ struct drive *drive = g->drives;
+ while (drive) {
+ if (drive->name && STREQ(drive->name, name)) {
+ device = safe_asprintf (g, "%s%s", devices[i], part);
+ break;
+ }
- /* Calculate the numerical index of the disk */
- size_t i = disk[0] - 'a';
- for (char *p = disk + 1; *p != '\0'; p++) {
- i += 1; i *= 26;
- i += *p - 'a';
+ i++; drive = drive->next;
}
+ free (name);
+
+ /* Guess the appliance device name if we didn't find a matching hint */
+ if (!device) {
+ /* Count how many disks the libguestfs appliance has */
+ size_t count;
+ for (count = 0; devices[count] != NULL; count++)
+ ;
+
+ /* Calculate the numerical index of the disk */
+ i = disk[0] - 'a';
+ for (char *p = disk + 1; *p != '\0'; p++) {
+ i += 1; i *= 26;
+ i += *p - 'a';
+ }
- /* Check the index makes sense wrt the number of disks the appliance has.
- * If it does, map it to an appliance disk. */
- if (i < count) {
- size_t len = strlen (devices[i]) + strlen (part) + 1;
- device = safe_malloc (g, len);
- snprintf (device, len, "%s%s", devices[i], part);
+ /* Check the index makes sense wrt the number of disks the appliance has.
+ * If it does, map it to an appliance disk. */
+ if (i < count) {
+ device = safe_asprintf (g, "%s%s", devices[i], part);
+ }
}
+ free (type);
free (disk);
free (part);
guestfs___free_string_list (devices);
diff --git a/src/launch.c b/src/launch.c
index d6e99f72..ed8d9bdd 100644
--- a/src/launch.c
+++ b/src/launch.c
@@ -289,6 +289,7 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
int readonly;
char *format;
char *iface;
+ char *name;
int use_cache_off;
if (strchr (filename, ',') != NULL) {
@@ -302,12 +303,15 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
? safe_strdup (g, optargs->format) : NULL;
iface = optargs->bitmask & GUESTFS_ADD_DRIVE_OPTS_IFACE_BITMASK
? safe_strdup (g, optargs->iface) : safe_strdup (g, DRIVE_IF);
+ name = optargs->bitmask & GUESTFS_ADD_DRIVE_OPTS_NAME_BITMASK
+ ? safe_strdup (g, optargs->name) : NULL;
if (format && !valid_format_iface (format)) {
error (g, _("%s parameter is empty or contains disallowed characters"),
"format");
free (format);
free (iface);
+ free (name);
return -1;
}
if (!valid_format_iface (iface)) {
@@ -315,6 +319,7 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
"iface");
free (format);
free (iface);
+ free (name);
return -1;
}
@@ -326,6 +331,7 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
if (use_cache_off == -1) {
free (format);
free (iface);
+ free (name);
return -1;
}
@@ -334,6 +340,7 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
perrorf (g, "%s", filename);
free (format);
free (iface);
+ free (name);
return -1;
}
}
@@ -347,6 +354,7 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename,
(*i)->readonly = readonly;
(*i)->format = format;
(*i)->iface = iface;
+ (*i)->name = name;
(*i)->use_cache_off = use_cache_off;
return 0;