[Libguestfs] [PATCH 3/3] inspect: Partial support for non-standard windows system root

Matthew Booth mbooth at redhat.com
Wed Jun 5 15:56:03 UTC 2013


Support arbitrary windows system root for pre-vista systems where
boot.ini is on the same partition as the system root.
---
 src/inspect-fs-windows.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/src/inspect-fs-windows.c b/src/inspect-fs-windows.c
index 8ddea95..61b2f3b 100644
--- a/src/inspect-fs-windows.c
+++ b/src/inspect-fs-windows.c
@@ -50,6 +50,8 @@
  * simultaneously.
  */
 static pcre *re_windows_version;
+static pcre *re_boot_ini_os_header;
+static pcre *re_boot_ini_os;
 
 static void compile_regexps (void) __attribute__((constructor));
 static void free_regexps (void) __attribute__((destructor));
@@ -70,12 +72,16 @@ compile_regexps (void)
   } while (0)
 
   COMPILE (re_windows_version, "^(\\d+)\\.(\\d+)", 0);
+  COMPILE (re_boot_ini_os_header, "^\\[operating systems\\]\\s*$", 0);
+  COMPILE (re_boot_ini_os, "^(multi|scsi)\\((\\d+)\\)disk\\((\\d+)\\)rdisk\\((\\d+)\\)partition\\((\\d+)\\)([^=]+)=", 0);
 }
 
 static void
 free_regexps (void)
 {
   pcre_free (re_windows_version);
+  pcre_free (re_boot_ini_os_header);
+  pcre_free (re_boot_ini_os);
 }
 
 static int check_windows_arch (guestfs_h *g, struct inspect_fs *fs);
@@ -143,6 +149,86 @@ guestfs___get_windows_systemroot (guestfs_h *g)
     }
   }
 
+  /* If the fs contains boot.ini, check it for non-standard
+   * systemroot locations */
+  CLEANUP_FREE char *boot_ini_path =
+    guestfs___case_sensitive_path_silently (g, "/boot.ini");
+  if (boot_ini_path) {
+    CLEANUP_FREE_STRING_LIST char **boot_ini =
+      guestfs_read_lines (g, boot_ini_path);
+    if (!boot_ini) {
+      debug (g, "error reading %s", boot_ini_path);
+      return NULL;
+    }
+
+    int found_os = 0;
+    for (char **i = boot_ini; *i != NULL; i++) {
+      CLEANUP_FREE char *controller_type = NULL;
+      CLEANUP_FREE char *controller = NULL;
+      CLEANUP_FREE char *disk = NULL;
+      CLEANUP_FREE char *rdisk = NULL;
+      CLEANUP_FREE char *partition = NULL;
+      CLEANUP_FREE char *path = NULL;
+
+      char *line = *i;
+
+      if (!found_os) {
+        if (match (g, line, re_boot_ini_os_header)) {
+          found_os = 1;
+          continue;
+        }
+      }
+
+      /* See http://support.microsoft.com/kb/102873 for a discussion
+       * of what this line means */
+      if (match6 (g, line, re_boot_ini_os, &controller_type,
+                  &controller, &disk, &rdisk, &partition, &path))
+      {
+        /* The Windows system root may be on any disk. However, there
+         * are currently (at least) 2 practical problems preventing us
+         * from locating it on another disk:
+         *
+         * 1. We don't have enough metadata about the disks we were
+         * given to know if what controller they were on and what
+         * index they had.
+         *
+         * 2. The way inspection of filesystems currently works, we
+         * can't mark another filesystem, which we may have already
+         * inspected, to be inspected for a specific Windows system
+         * root.
+         *
+         * Solving 1 properly would require a new API at a minimum. We
+         * might be able to fudge something practical without this,
+         * though, e.g. by looking at the <partition>th partition of
+         * every disk for the specific windows root.
+         *
+         * Solving 2 would probably require a significant refactoring
+         * of the way filesystems are inspected. We should probably do
+         * this some time.
+         *
+         * For the moment, we ignore all partition information and
+         * assume the system root is on the current partition. In
+         * practice, this will normally be correct.
+         */
+
+        /* Swap backslashes for forward slashes in the system root
+         * path */
+        for (char *j = path; *j != '\0'; j++) {
+          if (*j == '\\') *j = '/';
+        }
+
+        char *systemroot = guestfs___case_sensitive_path_silently (g, path);
+        if (systemroot && is_systemroot (g, systemroot)) {
+          debug (g, "windows %%SYSTEMROOT%% = %s", systemroot);
+
+          return systemroot;
+        } else {
+          free (systemroot);
+        }
+      }
+    }
+  }
+
   return NULL; /* not found */
 }
 
-- 
1.8.2.1




More information about the Libguestfs mailing list