[Libguestfs] [PATCH] inspect: get windows drive letters for GPT disks.

Richard W.M. Jones rjones at redhat.com
Fri Feb 5 18:08:59 UTC 2016


On Fri, Feb 05, 2016 at 12:15:32PM -0500, Dawid Zamirski wrote:
> This patch updates the guestfs_inspect_get_drive_mappings API call to
> also return drive letters for GPT paritions. Previously this worked
> only for MBR partitions. This is achieved by matching the GPT partition
> GUID with the info stored in the blob from
> HKLM\SYSTEM\MountedDevices\DosDevices keys. For GPT partions this blob
> contains a "DMIO:ID:" prefix followed by a 16 byte binary GUID.
> ---
>  src/inspect-fs-windows.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 96 insertions(+), 2 deletions(-)

Attached is a patch with some stylistic updates.  Please combine it
with your patch.  More comments below.

> diff --git a/src/inspect-fs-windows.c b/src/inspect-fs-windows.c
> index ccf5cba..6571d37 100644
> --- a/src/inspect-fs-windows.c
> +++ b/src/inspect-fs-windows.c
> @@ -25,6 +25,7 @@
>  #include <string.h>
>  #include <errno.h>
>  #include <iconv.h>
> +#include <inttypes.h>
>  
>  #ifdef HAVE_ENDIAN_H
>  #include <endian.h>
> @@ -57,6 +58,8 @@ static int check_windows_arch (guestfs_h *g, struct inspect_fs *fs);
>  static int check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs);
>  static int check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs);
>  static char *map_registry_disk_blob (guestfs_h *g, const void *blob);
> +static char *map_registry_disk_blob_gpt(guestfs_h *g, const void *blob);
> +static char *extract_guid_from_registry_blob(guestfs_h *g, const void *blob);
>  
>  /* XXX Handling of boot.ini in the Perl version was pretty broken.  It
>   * essentially didn't do anything for modern Windows guests.
> @@ -386,6 +389,7 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
>    int r;
>    size_t len = strlen (fs->windows_systemroot) + 64;
>    char system[len];
> +  char gpt_prefix[] = "DMIO:ID:";
>    snprintf (system, len, "%s/system32/config/system",
>              fs->windows_systemroot);
>  
> @@ -493,9 +497,14 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
>  
>        type = guestfs_hivex_value_type (g, v);
>        blob = guestfs_hivex_value_value (g, v, &len);
> -      if (blob != NULL && type == 3 && len == 12) {
> +      bool is_gpt = memcmp(blob, gpt_prefix, 8) == 0;
> +      if (blob != NULL && type == 3 && (len == 12 || is_gpt)) {
>          /* Try to map the blob to a known disk and partition. */
> -        device = map_registry_disk_blob (g, blob);
> +        if (is_gpt)
> +          device = map_registry_disk_blob_gpt (g, blob);
> +        else
> +          device = map_registry_disk_blob (g, blob);
> +
>          if (device != NULL) {
>            fs->drive_mappings[count++] = safe_strndup (g, &key[12], 1);
>            fs->drive_mappings[count++] = device;
> @@ -605,6 +614,91 @@ map_registry_disk_blob (guestfs_h *g, const void *blob)
>    return safe_asprintf (g, "%s%d", devices[i], partitions->val[j].part_num);
>  }
>  
> +/* Matches Windows registry HKLM\SYSYTEM\MountedDevices\DosDevices blob to
> + * to libguestfs GPT partition device. For GPT disks, the blob is made of
> + * "DMIO:ID:" prefix followed by the GPT parition GUID.
> + */
> +static char *
> +map_registry_disk_blob_gpt (guestfs_h *g, const void *blob)
> +{
> +  CLEANUP_FREE_STRING_LIST char **fses = NULL;
> +  size_t i;
> +
> +  fses = guestfs_list_filesystems (g);
> +  if (fses == NULL)
> +    return NULL;

Did you really mean to call guestfs_list_filesystems here?  If you're
trying to get the list of partitions, then guestfs_list_partitions is
what you should be calling.

> +  for (i = 0; fses[i] != NULL; i += 2) {
> +    CLEANUP_FREE char *fs_guid = NULL;
> +    CLEANUP_FREE char *blob_guid = NULL;
> +    CLEANUP_FREE char *fs_dev  = NULL;
> +
> +    fs_dev = guestfs_canonical_device_name (g, fses[i]);
> +
> +    if (fs_dev == NULL)
> +        continue;
> +
> +    int partnum = guestfs_part_to_partnum (g, fs_dev);

Need to check that partnum != -1 and do something.

> +    CLEANUP_FREE char *device = guestfs_part_to_dev (g, fs_dev);
> +    CLEANUP_FREE char *type = guestfs_part_get_parttype (g, device);
> +
> +    if (STRCASENEQ(type, "gpt"))
> +        continue;
> +
> +    /* get the GPT parition GUID from the partition block device */
> +    fs_guid = guestfs_part_get_gpt_guid (g, device, partnum);
> +    
> +    if (fs_guid == NULL)
> +      continue;
> +
> +    /* extract the GUID from the Windows registry blob */
> +    blob_guid = extract_guid_from_registry_blob (g, blob);
> +
> +    /* if both GUIDs match, we have found mapping for out device */
> +    if (STRCASEEQ (fs_guid, blob_guid))
> +        return safe_strdup (g, fs_dev);
> +  }
> +
> +  return NULL;
> +}
> +
> +/* Extracts the binary GUID stored in blob from Windows registry 
> + * HKLM\SYSTYEM\MountedDevices\DosDevices value and converts it to a GUID string
> + * so that it can be matched against libguestfs partition device GPT GUID.
> + */
> +static char *
> +extract_guid_from_registry_blob (guestfs_h *g, const void *blob)
> +{
> +  char guid_bytes[16];
> +  size_t len = 37;
> +  uint32_t data1;
> +  uint16_t data2, data3;
> +  uint64_t data4;
> +
> +  char *guid = (char *) safe_calloc(g, len, sizeof (char * ));
> +
> +  /* get the GUID bytes from blob (skip 8 byte "DMIO:ID:" prefix) */
> +  memcpy (&guid_bytes, (char *) blob + 8, sizeof (guid_bytes));
> +
> +  /* copy relevant sections from blob to respective ints */
> +  memcpy (&data1, guid_bytes, sizeof (data1));
> +  memcpy (&data2, guid_bytes + 4, sizeof (data2));
> +  memcpy (&data3, guid_bytes + 6, sizeof (data3));
> +  memcpy (&data4, guid_bytes + 8, sizeof (data4));
> +
> +  /* ensure proper endianness */
> +  data1 = htole32 (data1);

Did you mean to use htole32?  Surely it should be le32toh?

> +  data2 = htole16 (data2);
> +  data3  = htole16 (data3);
> +  data4 = htobe64 (data4);

And is this really big endian?

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
libguestfs lets you edit virtual machines.  Supports shell scripting,
bindings from many languages.  http://libguestfs.org
-------------- next part --------------
>From 9bc43ef03944b6b2e1dfe0f7306a30e61a3f339d Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones at redhat.com>
Date: Fri, 5 Feb 2016 18:02:16 +0000
Subject: [PATCH] Update styles

---
 src/inspect-fs-windows.c | 38 +++++++++++++++++++-------------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/src/inspect-fs-windows.c b/src/inspect-fs-windows.c
index 6571d37..48670ce 100644
--- a/src/inspect-fs-windows.c
+++ b/src/inspect-fs-windows.c
@@ -58,8 +58,8 @@ static int check_windows_arch (guestfs_h *g, struct inspect_fs *fs);
 static int check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs);
 static int check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs);
 static char *map_registry_disk_blob (guestfs_h *g, const void *blob);
-static char *map_registry_disk_blob_gpt(guestfs_h *g, const void *blob);
-static char *extract_guid_from_registry_blob(guestfs_h *g, const void *blob);
+static char *map_registry_disk_blob_gpt (guestfs_h *g, const void *blob);
+static char *extract_guid_from_registry_blob (guestfs_h *g, const void *blob);
 
 /* XXX Handling of boot.ini in the Perl version was pretty broken.  It
  * essentially didn't do anything for modern Windows guests.
@@ -494,10 +494,11 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
       CLEANUP_FREE char *blob = NULL;
       char *device;
       int64_t type;
+      bool is_gpt;
 
       type = guestfs_hivex_value_type (g, v);
       blob = guestfs_hivex_value_value (g, v, &len);
-      bool is_gpt = memcmp(blob, gpt_prefix, 8) == 0;
+      is_gpt = memcmp (blob, gpt_prefix, 8) == 0;
       if (blob != NULL && type == 3 && (len == 12 || is_gpt)) {
         /* Try to map the blob to a known disk and partition. */
         if (is_gpt)
@@ -616,7 +617,7 @@ map_registry_disk_blob (guestfs_h *g, const void *blob)
 
 /* Matches Windows registry HKLM\SYSYTEM\MountedDevices\DosDevices blob to
  * to libguestfs GPT partition device. For GPT disks, the blob is made of
- * "DMIO:ID:" prefix followed by the GPT parition GUID.
+ * "DMIO:ID:" prefix followed by the GPT partition GUID.
  */
 static char *
 map_registry_disk_blob_gpt (guestfs_h *g, const void *blob)
@@ -632,22 +633,25 @@ map_registry_disk_blob_gpt (guestfs_h *g, const void *blob)
     CLEANUP_FREE char *fs_guid = NULL;
     CLEANUP_FREE char *blob_guid = NULL;
     CLEANUP_FREE char *fs_dev  = NULL;
+    int partnum;
+    CLEANUP_FREE char *device = NULL;
+    CLEANUP_FREE char *type = NULL;
 
     fs_dev = guestfs_canonical_device_name (g, fses[i]);
 
     if (fs_dev == NULL)
         continue;
 
-    int partnum = guestfs_part_to_partnum (g, fs_dev);
-    CLEANUP_FREE char *device = guestfs_part_to_dev (g, fs_dev);
-    CLEANUP_FREE char *type = guestfs_part_get_parttype (g, device);
+    partnum = guestfs_part_to_partnum (g, fs_dev);
+    device = guestfs_part_to_dev (g, fs_dev);
+    type = guestfs_part_get_parttype (g, device);
 
-    if (STRCASENEQ(type, "gpt"))
+    if (STRCASENEQ (type, "gpt"))
         continue;
 
     /* get the GPT parition GUID from the partition block device */
     fs_guid = guestfs_part_get_gpt_guid (g, device, partnum);
-    
+
     if (fs_guid == NULL)
       continue;
 
@@ -662,21 +666,19 @@ map_registry_disk_blob_gpt (guestfs_h *g, const void *blob)
   return NULL;
 }
 
-/* Extracts the binary GUID stored in blob from Windows registry 
- * HKLM\SYSTYEM\MountedDevices\DosDevices value and converts it to a GUID string
- * so that it can be matched against libguestfs partition device GPT GUID.
+/* Extracts the binary GUID stored in blob from Windows registry
+ * HKLM\SYSTYEM\MountedDevices\DosDevices value and converts it to a
+ * GUID string so that it can be matched against libguestfs partition
+ * device GPT GUID.
  */
 static char *
 extract_guid_from_registry_blob (guestfs_h *g, const void *blob)
 {
   char guid_bytes[16];
-  size_t len = 37;
   uint32_t data1;
   uint16_t data2, data3;
   uint64_t data4;
 
-  char *guid = (char *) safe_calloc(g, len, sizeof (char * ));
-
   /* get the GUID bytes from blob (skip 8 byte "DMIO:ID:" prefix) */
   memcpy (&guid_bytes, (char *) blob + 8, sizeof (guid_bytes));
 
@@ -689,14 +691,12 @@ extract_guid_from_registry_blob (guestfs_h *g, const void *blob)
   /* ensure proper endianness */
   data1 = htole32 (data1);
   data2 = htole16 (data2);
-  data3  = htole16 (data3);
+  data3 = htole16 (data3);
   data4 = htobe64 (data4);
 
-  snprintf (guid, len,
+  return safe_asprintf (g,
            "%08" PRIX32 "-%04" PRIX16 "-%04" PRIX16 "-%04" PRIX64 "-%06" PRIX64,
            data1, data2, data3, (data4 >> 48), (data4 << 16));
-
-  return guid;
 }
 
 /* NB: This function DOES NOT test for the existence of the file.  It
-- 
2.5.0



More information about the Libguestfs mailing list