[Libguestfs] [PATCH 1/1] inspect: Fix a bug in the *BSD root detection

Nikos Skalkotos skalkoto at grnet.gr
Thu Nov 27 16:30:33 UTC 2014


The assumption that Linux will map the MBR partition to /dev/sda1
and the BSD 'a' partition to /dev/sda5 is not always correct.

Signed-off-by: Nikos Skalkotos <skalkoto at grnet.gr>
---
 src/guestfs-internal.h |  1 +
 src/inspect-fs.c       | 55 +++++++++++++++++++++++++++++++++-----------------
 src/inspect.c          |  6 ++++++
 3 files changed, 43 insertions(+), 19 deletions(-)

diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index fd0c4a1..2460d25 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -746,6 +746,7 @@ extern int guestfs___is_file_nocase (guestfs_h *g, const char *);
 extern int guestfs___is_dir_nocase (guestfs_h *g, const char *);
 extern int guestfs___check_for_filesystem_on (guestfs_h *g,
                                               const char *mountable);
+extern void guestfs___check_for_dublicated_bsd_root(guestfs_h *g);
 extern int guestfs___parse_unsigned_int (guestfs_h *g, const char *str);
 extern int guestfs___parse_unsigned_int_ignore_trailing (guestfs_h *g, const char *str);
 extern int guestfs___parse_major_minor (guestfs_h *g, struct inspect_fs *fs);
diff --git a/src/inspect-fs.c b/src/inspect-fs.c
index 539d814..99a8658 100644
--- a/src/inspect-fs.c
+++ b/src/inspect-fs.c
@@ -47,7 +47,7 @@
  * multiple threads call into the libguestfs API functions below
  * simultaneously.
  */
-static pcre *re_first_partition;
+static pcre *re_primary_partition;
 static pcre *re_major_minor;
 
 static void compile_regexps (void) __attribute__((constructor));
@@ -68,14 +68,14 @@ compile_regexps (void)
     }                                                                   \
   } while (0)
 
-  COMPILE (re_first_partition, "^/dev/(?:h|s|v)d.1$", 0);
+  COMPILE (re_primary_partition, "^/dev/(?:h|s|v)d.[1234]$", 0);
   COMPILE (re_major_minor, "(\\d+)\\.(\\d+)", 0);
 }
 
 static void
 free_regexps (void)
 {
-  pcre_free (re_first_partition);
+  pcre_free (re_primary_partition);
   pcre_free (re_major_minor);
 }
 
@@ -84,6 +84,39 @@ static int check_filesystem (guestfs_h *g, const char *mountable,
                              int whole_device);
 static int extend_fses (guestfs_h *g);
 
+/* On *BSD systems, sometimes /dev/sda[1234] is a shadow of the real root
+ * filesystem that is probably /dev/sda5
+ * (see: http://www.freebsd.org/doc/handbook/disk-organization.html)
+ */
+void
+guestfs___check_for_dublicated_bsd_root(guestfs_h *g)
+{
+  size_t i;
+  bool is_primary, is_bsd;
+  struct inspect_fs *fs, *bsd_primary = NULL;
+
+  for (i = 0; i < g->nr_fses; ++i) {
+    fs = &g->fses[i];
+
+    is_primary = match (g, fs->mountable, re_primary_partition);
+    is_bsd = ((fs->type == OS_TYPE_FREEBSD) || \
+              (fs->type == OS_TYPE_NETBSD) || \
+              (fs->type == OS_TYPE_OPENBSD));
+
+    if (fs->is_root && is_primary && is_bsd) {
+      bsd_primary = fs;
+      continue;
+    }
+
+    if (fs->is_root && bsd_primary && (bsd_primary->type == fs->type)) {
+      /* remove the is root flag from the bsd_primary */
+      bsd_primary->is_root = 0;
+      bsd_primary->format = OS_FORMAT_UNKNOWN;
+      return;
+    }
+  }
+}
+
 /* Find out if 'device' contains a filesystem.  If it does, add
  * another entry in g->fses.
  */
@@ -207,14 +240,6 @@ check_filesystem (guestfs_h *g, const char *mountable,
            is_dir_bin &&
            guestfs_is_file (g, "/etc/freebsd-update.conf") > 0 &&
            guestfs_is_file (g, "/etc/fstab") > 0) {
-    /* Ignore /dev/sda1 which is a shadow of the real root filesystem
-     * that is probably /dev/sda5 (see:
-     * http://www.freebsd.org/doc/handbook/disk-organization.html)
-     */
-    if (m->im_type == MOUNTABLE_DEVICE &&
-        match (g, m->im_device, re_first_partition))
-      return 0;
-
     fs->is_root = 1;
     fs->format = OS_FORMAT_INSTALLED;
     if (guestfs___check_freebsd_root (g, fs) == -1)
@@ -225,14 +250,6 @@ check_filesystem (guestfs_h *g, const char *mountable,
            guestfs_is_file (g, "/netbsd") > 0 &&
            guestfs_is_file (g, "/etc/fstab") > 0 &&
            guestfs_is_file (g, "/etc/release") > 0) {
-    /* Ignore /dev/sda1 which is a shadow of the real root filesystem
-     * that is probably /dev/sda5 (see:
-     * http://www.freebsd.org/doc/handbook/disk-organization.html)
-     */
-    if (m->im_type == MOUNTABLE_DEVICE &&
-        match (g, m->im_device, re_first_partition))
-      return 0;
-
     fs->is_root = 1;
     fs->format = OS_FORMAT_INSTALLED;
     if (guestfs___check_netbsd_root (g, fs) == -1)
diff --git a/src/inspect.c b/src/inspect.c
index 9248b06..048b059 100644
--- a/src/inspect.c
+++ b/src/inspect.c
@@ -64,6 +64,12 @@ guestfs__inspect_os (guestfs_h *g)
     }
   }
 
+  /* Check if the same filesystem was listed twice as root in g->fses.
+   * This may happen for the *BSD root partition where an MBR partition
+   * is a shadow of the real root partition probably /dev/sda5
+   */
+  guestfs___check_for_dublicated_bsd_root(g);
+
   /* At this point we have, in the handle, a list of all filesystems
    * found and data about each one.  Now we assemble the list of
    * filesystems which are root devices and return that to the user.
-- 
2.1.3




More information about the Libguestfs mailing list