|
|
e76f14 |
From 3d23c51e654f479de8ddbfd1cd7e44753d4bb19d Mon Sep 17 00:00:00 2001
|
|
|
e76f14 |
From: Dawid Zamirski <dzamirski@datto.com>
|
|
|
e76f14 |
Date: Sat, 6 Feb 2016 11:50:05 -0500
|
|
|
e76f14 |
Subject: [PATCH] inspect: get windows drive letters for GPT disks.
|
|
|
e76f14 |
|
|
|
e76f14 |
This patch updates the guestfs_inspect_get_drive_mappings API call to
|
|
|
e76f14 |
also return drive letters for GPT paritions. Previously this worked
|
|
|
e76f14 |
only for MBR partitions. This is achieved by matching the GPT partition
|
|
|
e76f14 |
GUID with the info stored in the blob from
|
|
|
e76f14 |
HKLM\SYSTEM\MountedDevices\DosDevices keys. For GPT partions this blob
|
|
|
e76f14 |
contains a "DMIO:ID:" prefix followed by a 16 byte binary GUID.
|
|
|
e76f14 |
|
|
|
e76f14 |
(cherry picked from commit 7cb28488a6b974c86a9dd0264d892cd01739c36e)
|
|
|
e76f14 |
---
|
|
|
e76f14 |
src/inspect-fs-windows.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++-
|
|
|
e76f14 |
1 file changed, 94 insertions(+), 2 deletions(-)
|
|
|
e76f14 |
|
|
|
e76f14 |
diff --git a/src/inspect-fs-windows.c b/src/inspect-fs-windows.c
|
|
|
e76f14 |
index 7e3ead5..f8717fc 100644
|
|
|
e76f14 |
--- a/src/inspect-fs-windows.c
|
|
|
e76f14 |
+++ b/src/inspect-fs-windows.c
|
|
|
e76f14 |
@@ -25,6 +25,7 @@
|
|
|
e76f14 |
#include <string.h>
|
|
|
e76f14 |
#include <errno.h>
|
|
|
e76f14 |
#include <iconv.h>
|
|
|
e76f14 |
+#include <inttypes.h>
|
|
|
e76f14 |
|
|
|
e76f14 |
#ifdef HAVE_ENDIAN_H
|
|
|
e76f14 |
#include <endian.h>
|
|
|
e76f14 |
@@ -57,6 +58,8 @@ static int check_windows_arch (guestfs_h *g, struct inspect_fs *fs);
|
|
|
e76f14 |
static int check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs);
|
|
|
e76f14 |
static int check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs);
|
|
|
e76f14 |
static char *map_registry_disk_blob (guestfs_h *g, const void *blob);
|
|
|
e76f14 |
+static char *map_registry_disk_blob_gpt (guestfs_h *g, const void *blob);
|
|
|
e76f14 |
+static char *extract_guid_from_registry_blob (guestfs_h *g, const void *blob);
|
|
|
e76f14 |
|
|
|
e76f14 |
/* XXX Handling of boot.ini in the Perl version was pretty broken. It
|
|
|
e76f14 |
* essentially didn't do anything for modern Windows guests.
|
|
|
e76f14 |
@@ -386,6 +389,7 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
|
|
|
e76f14 |
int r;
|
|
|
e76f14 |
size_t len = strlen (fs->windows_systemroot) + 64;
|
|
|
e76f14 |
char system[len];
|
|
|
e76f14 |
+ char gpt_prefix[] = "DMIO:ID:";
|
|
|
e76f14 |
snprintf (system, len, "%s/system32/config/system",
|
|
|
e76f14 |
fs->windows_systemroot);
|
|
|
e76f14 |
|
|
|
e76f14 |
@@ -490,12 +494,18 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
|
|
|
e76f14 |
CLEANUP_FREE char *blob = NULL;
|
|
|
e76f14 |
char *device;
|
|
|
e76f14 |
int64_t type;
|
|
|
e76f14 |
+ bool is_gpt;
|
|
|
e76f14 |
|
|
|
e76f14 |
type = guestfs_hivex_value_type (g, v);
|
|
|
e76f14 |
blob = guestfs_hivex_value_value (g, v, &len;;
|
|
|
e76f14 |
- if (blob != NULL && type == 3 && len == 12) {
|
|
|
e76f14 |
+ is_gpt = memcmp (blob, gpt_prefix, 8) == 0;
|
|
|
e76f14 |
+ if (blob != NULL && type == 3 && (len == 12 || is_gpt)) {
|
|
|
e76f14 |
/* Try to map the blob to a known disk and partition. */
|
|
|
e76f14 |
- device = map_registry_disk_blob (g, blob);
|
|
|
e76f14 |
+ if (is_gpt)
|
|
|
e76f14 |
+ device = map_registry_disk_blob_gpt (g, blob);
|
|
|
e76f14 |
+ else
|
|
|
e76f14 |
+ device = map_registry_disk_blob (g, blob);
|
|
|
e76f14 |
+
|
|
|
e76f14 |
if (device != NULL) {
|
|
|
e76f14 |
fs->drive_mappings[count++] = safe_strndup (g, &key[12], 1);
|
|
|
e76f14 |
fs->drive_mappings[count++] = device;
|
|
|
e76f14 |
@@ -605,6 +615,88 @@ map_registry_disk_blob (guestfs_h *g, const void *blob)
|
|
|
e76f14 |
return safe_asprintf (g, "%s%d", devices[i], partitions->val[j].part_num);
|
|
|
e76f14 |
}
|
|
|
e76f14 |
|
|
|
e76f14 |
+/* Matches Windows registry HKLM\SYSYTEM\MountedDevices\DosDevices blob to
|
|
|
e76f14 |
+ * to libguestfs GPT partition device. For GPT disks, the blob is made of
|
|
|
e76f14 |
+ * "DMIO:ID:" prefix followed by the GPT partition GUID.
|
|
|
e76f14 |
+ */
|
|
|
e76f14 |
+static char *
|
|
|
e76f14 |
+map_registry_disk_blob_gpt (guestfs_h *g, const void *blob)
|
|
|
e76f14 |
+{
|
|
|
e76f14 |
+ CLEANUP_FREE_STRING_LIST char **parts = NULL;
|
|
|
e76f14 |
+ CLEANUP_FREE char *blob_guid = extract_guid_from_registry_blob (g, blob);
|
|
|
e76f14 |
+ size_t i;
|
|
|
e76f14 |
+
|
|
|
e76f14 |
+ parts = guestfs_list_partitions (g);
|
|
|
e76f14 |
+ if (parts == NULL)
|
|
|
e76f14 |
+ return NULL;
|
|
|
e76f14 |
+
|
|
|
e76f14 |
+ for (i = 0; parts[i] != NULL; ++i) {
|
|
|
e76f14 |
+ CLEANUP_FREE char *fs_guid = NULL;
|
|
|
e76f14 |
+ int partnum;
|
|
|
e76f14 |
+ CLEANUP_FREE char *device = NULL;
|
|
|
e76f14 |
+ CLEANUP_FREE char *type = NULL;
|
|
|
e76f14 |
+
|
|
|
e76f14 |
+ partnum = guestfs_part_to_partnum (g, parts[i]);
|
|
|
e76f14 |
+ if (partnum == -1)
|
|
|
e76f14 |
+ continue;
|
|
|
e76f14 |
+
|
|
|
e76f14 |
+ device = guestfs_part_to_dev (g, parts[i]);
|
|
|
e76f14 |
+ if (device == NULL)
|
|
|
e76f14 |
+ continue;
|
|
|
e76f14 |
+
|
|
|
e76f14 |
+ type = guestfs_part_get_parttype (g, device);
|
|
|
e76f14 |
+ if (type == NULL)
|
|
|
e76f14 |
+ continue;
|
|
|
e76f14 |
+
|
|
|
e76f14 |
+ if (STRCASENEQ (type, "gpt"))
|
|
|
e76f14 |
+ continue;
|
|
|
e76f14 |
+
|
|
|
e76f14 |
+ /* get the GPT parition GUID from the partition block device */
|
|
|
e76f14 |
+ fs_guid = guestfs_part_get_gpt_guid (g, device, partnum);
|
|
|
e76f14 |
+ if (fs_guid == NULL)
|
|
|
e76f14 |
+ continue;
|
|
|
e76f14 |
+
|
|
|
e76f14 |
+ /* if both GUIDs match, we have found the mapping for our device */
|
|
|
e76f14 |
+ if (STRCASEEQ (fs_guid, blob_guid))
|
|
|
e76f14 |
+ return safe_strdup (g, parts[i]);
|
|
|
e76f14 |
+ }
|
|
|
e76f14 |
+
|
|
|
e76f14 |
+ return NULL;
|
|
|
e76f14 |
+}
|
|
|
e76f14 |
+
|
|
|
e76f14 |
+/* Extracts the binary GUID stored in blob from Windows registry
|
|
|
e76f14 |
+ * HKLM\SYSTYEM\MountedDevices\DosDevices value and converts it to a
|
|
|
e76f14 |
+ * GUID string so that it can be matched against libguestfs partition
|
|
|
e76f14 |
+ * device GPT GUID.
|
|
|
e76f14 |
+ */
|
|
|
e76f14 |
+static char *
|
|
|
e76f14 |
+extract_guid_from_registry_blob (guestfs_h *g, const void *blob)
|
|
|
e76f14 |
+{
|
|
|
e76f14 |
+ char guid_bytes[16];
|
|
|
e76f14 |
+ uint32_t data1;
|
|
|
e76f14 |
+ uint16_t data2, data3;
|
|
|
e76f14 |
+ uint64_t data4;
|
|
|
e76f14 |
+
|
|
|
e76f14 |
+ /* get the GUID bytes from blob (skip 8 byte "DMIO:ID:" prefix) */
|
|
|
e76f14 |
+ memcpy (&guid_bytes, (char *) blob + 8, sizeof (guid_bytes));
|
|
|
e76f14 |
+
|
|
|
e76f14 |
+ /* copy relevant sections from blob to respective ints */
|
|
|
e76f14 |
+ memcpy (&data1, guid_bytes, sizeof (data1));
|
|
|
e76f14 |
+ memcpy (&data2, guid_bytes + 4, sizeof (data2));
|
|
|
e76f14 |
+ memcpy (&data3, guid_bytes + 6, sizeof (data3));
|
|
|
e76f14 |
+ memcpy (&data4, guid_bytes + 8, sizeof (data4));
|
|
|
e76f14 |
+
|
|
|
e76f14 |
+ /* ensure proper endianness */
|
|
|
e76f14 |
+ data1 = le32toh (data1);
|
|
|
e76f14 |
+ data2 = le16toh (data2);
|
|
|
e76f14 |
+ data3 = le16toh (data3);
|
|
|
e76f14 |
+ data4 = be64toh (data4);
|
|
|
e76f14 |
+
|
|
|
e76f14 |
+ return safe_asprintf (g,
|
|
|
e76f14 |
+ "%08" PRIX32 "-%04" PRIX16 "-%04" PRIX16 "-%04" PRIX64 "-%012" PRIX64,
|
|
|
e76f14 |
+ data1, data2, data3, data4 >> 48, data4 & 0xffffffffffff);
|
|
|
e76f14 |
+}
|
|
|
e76f14 |
+
|
|
|
e76f14 |
/* NB: This function DOES NOT test for the existence of the file. It
|
|
|
e76f14 |
* will return non-NULL even if the file/directory does not exist.
|
|
|
e76f14 |
* You have to call guestfs_is_file{,_opts} etc.
|
|
|
e76f14 |
--
|
|
|
aa0300 |
2.7.4
|
|
|
e76f14 |
|