[Libguestfs] [PATCH stable-1.24] Fix fstab block device resolution for FreeBSD

Nikos Skalkotos skalkoto at grnet.gr
Tue Nov 5 10:15:47 UTC 2013


The device name prefix for IDE hard drives used to be `ad' but now
is `ada' (http://www.freebsd.org/doc/handbook/disks-naming.html).
For virtio hard drives it is `vtbd'.

Under an MBR partition table a slice will be used, so the name of
the first partitions will be either `ada0s1a' or `vtbd0s1a'. Under a
GPT partition table, where no slice is needed, the name of the first
partition will be either `ada0p1' or `vtbd0p1'.

Signed-off-by: Nikos Skalkotos <skalkoto at grnet.gr>
---
 src/guestfs-internal.h |  2 ++
 src/inspect-fs-unix.c  | 27 +++++++++++++++++++++++----
 src/match.c            | 25 +++++++++++++++++++++++++
 3 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 9936c84..5356920 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -630,12 +630,14 @@ extern int guestfs___match (guestfs_h *g, const char *str, const pcre *re);
 extern char *guestfs___match1 (guestfs_h *g, const char *str, const pcre *re);
 extern int guestfs___match2 (guestfs_h *g, const char *str, const pcre *re, char **ret1, char **ret2);
 extern int guestfs___match3 (guestfs_h *g, const char *str, const pcre *re, char **ret1, char **ret2, char **ret3);
+extern int guestfs___match4 (guestfs_h *g, const char *str, const pcre *re, char **ret1, char **ret2, char **ret3, char **ret4);
 extern int guestfs___match6 (guestfs_h *g, const char *str, const pcre *re, char **ret1, char **ret2, char **ret3, char **ret4, char **ret5, char **ret6);
 
 #define match guestfs___match
 #define match1 guestfs___match1
 #define match2 guestfs___match2
 #define match3 guestfs___match3
+#define match4 guestfs___match4
 #define match6 guestfs___match6
 
 /* stringsbuf.c */
diff --git a/src/inspect-fs-unix.c b/src/inspect-fs-unix.c
index 60b081d..8e0f135 100644
--- a/src/inspect-fs-unix.c
+++ b/src/inspect-fs-unix.c
@@ -64,7 +64,8 @@ static pcre *re_major_minor;
 static pcre *re_xdev;
 static pcre *re_cciss;
 static pcre *re_mdN;
-static pcre *re_freebsd;
+static pcre *re_freebsd_mbr;
+static pcre *re_freebsd_gpt;
 static pcre *re_diskbyid;
 static pcre *re_netbsd;
 static pcre *re_opensuse;
@@ -115,7 +116,8 @@ compile_regexps (void)
   COMPILE (re_xdev, "^/dev/(h|s|v|xv)d([a-z]+)(\\d*)$", 0);
   COMPILE (re_cciss, "^/dev/(cciss/c\\d+d\\d+)(?:p(\\d+))?$", 0);
   COMPILE (re_mdN, "^(/dev/md\\d+)$", 0);
-  COMPILE (re_freebsd, "^/dev/ad(\\d+)s(\\d+)([a-z])$", 0);
+  COMPILE (re_freebsd_mbr, "^/dev/(ada{0,1}|vtbd)(\\d+)s(\\d+)([a-z])$", 0);
+  COMPILE (re_freebsd_gpt, "^/dev/(ada{0,1}|vtbd)(\\d+)p(\\d+)$", 0);
   COMPILE (re_diskbyid, "^/dev/disk/by-id/.*-part(\\d+)$", 0);
   COMPILE (re_netbsd, "^NetBSD (\\d+)\\.(\\d+)", 0);
   COMPILE (re_opensuse, "^(openSUSE|SuSE Linux|SUSE LINUX) ", 0);
@@ -143,7 +145,8 @@ free_regexps (void)
   pcre_free (re_xdev);
   pcre_free (re_cciss);
   pcre_free (re_mdN);
-  pcre_free (re_freebsd);
+  pcre_free (re_freebsd_mbr);
+  pcre_free (re_freebsd_gpt);
   pcre_free (re_diskbyid);
   pcre_free (re_netbsd);
   pcre_free (re_opensuse);
@@ -1464,7 +1467,22 @@ resolve_fstab_device (guestfs_h *g, const char *spec, Hash_table *md_map)
 
     free (disk);
   }
-  else if (match3 (g, spec, re_freebsd, &disk, &slice, &part)) {
+  else if (match3 (g, spec, re_freebsd_gpt, &type, &disk, &part)) {
+    /* If the FreeBSD disk contains GPT partitions, the translation to Linux
+     * device names is straight forward. Partitions on a virtio disk are
+     * prefixed with vtbd. IDE hard drives used to be prefixed with ad and now
+     * are with ada.
+     */
+    int disk_i = guestfs___parse_unsigned_int (g, disk);
+    int part_i = guestfs___parse_unsigned_int (g, part);
+    free (type);
+    free (disk);
+    free (part);
+
+    if (disk_i != -1 && disk_i <= 26 && part_i > 0 && part_i <= 128)
+      device = safe_asprintf (g, "/dev/sd%c%d", disk_i + 'a', part_i);
+  }
+  else if (match4 (g, spec, re_freebsd_mbr, &type, &disk, &slice, &part)) {
     /* FreeBSD disks are organized quite differently.  See:
      * http://www.freebsd.org/doc/handbook/disk-organization.html
      * FreeBSD "partitions" are exposed as quasi-extended partitions
@@ -1474,6 +1492,7 @@ resolve_fstab_device (guestfs_h *g, const char *spec, Hash_table *md_map)
     int disk_i = guestfs___parse_unsigned_int (g, disk);
     int slice_i = guestfs___parse_unsigned_int (g, slice);
     int part_i = part[0] - 'a' /* counting from 0 */;
+    free (type);
     free (disk);
     free (slice);
     free (part);
diff --git a/src/match.c b/src/match.c
index 86c0a31..2a3e5a9 100644
--- a/src/match.c
+++ b/src/match.c
@@ -104,6 +104,31 @@ guestfs___match3 (guestfs_h *g, const char *str, const pcre *re,
   return 1;
 }
 
+/* Match a regular expression which contains exactly four captures. */
+int
+guestfs___match4 (guestfs_h *g, const char *str, const pcre *re,
+                  char **ret1, char **ret2, char **ret3, char **ret4)
+{
+  size_t len = strlen (str);
+  int vec[30], r;
+
+  r = pcre_exec (re, NULL, str, len, 0, 0, vec, 30);
+  if (r == PCRE_ERROR_NOMATCH)
+    return 0;
+
+  *ret1 = NULL;
+  *ret2 = NULL;
+  *ret3 = NULL;
+  *ret4 = NULL;
+
+  if (r > 1) *ret1 = safe_strndup (g, &str[vec[2]], vec[3]-vec[2]);
+  if (r > 2) *ret2 = safe_strndup (g, &str[vec[4]], vec[5]-vec[4]);
+  if (r > 3) *ret3 = safe_strndup (g, &str[vec[6]], vec[7]-vec[6]);
+  if (r > 4) *ret4 = safe_strndup (g, &str[vec[8]], vec[9]-vec[8]);
+
+  return 1;
+}
+
 /* Match a regular expression which contains exactly six captures. */
 int
 guestfs___match6 (guestfs_h *g, const char *str, const pcre *re,
-- 
1.8.4.2




More information about the Libguestfs mailing list