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