[Libguestfs] [PATCH 4/4] Update inspection and example programs to use new hivex* APIs (RHBZ#852394).

Richard W.M. Jones rjones at redhat.com
Wed Aug 29 15:15:35 UTC 2012


From: "Richard W.M. Jones" <rjones at redhat.com>

I tested this by comparing the output of virt-inspector over Windows
guests before and after the change, which was identical:

$ md5sum `ls -1 /tmp/*.before /tmp/*.after`
c292d6629b5a761eccb4a279754399b4  /tmp/Win2003.after
c292d6629b5a761eccb4a279754399b4  /tmp/Win2003.before
eb1e1ff29208a9ee46e9c100dfec26b2  /tmp/Win2012.after
eb1e1ff29208a9ee46e9c100dfec26b2  /tmp/Win2012.before
d060a95d7ffe5dce6c4e66feb80c2837  /tmp/Win7x32.after
d060a95d7ffe5dce6c4e66feb80c2837  /tmp/Win7x32.before
8914eee70ac4f8a0317659e09e00dcdc  /tmp/Win7x32Dynamic.after
8914eee70ac4f8a0317659e09e00dcdc  /tmp/Win7x32Dynamic.before
a2dcdfc0f9d64054640875aa791889e0  /tmp/Win7x32TwoDisks.after
a2dcdfc0f9d64054640875aa791889e0  /tmp/Win7x32TwoDisks.before
5ed49568a5147dce7517c99de41ebf2e  /tmp/Win8previewx64.after
5ed49568a5147dce7517c99de41ebf2e  /tmp/Win8previewx64.before
fdfc7d272b79a665ae3313ae1ae30660  /tmp/WinXP.after
fdfc7d272b79a665ae3313ae1ae30660  /tmp/WinXP.before
3c705444be664f1316b21c5d8d3cb0be  /tmp/WinXPRecConsole.after
3c705444be664f1316b21c5d8d3cb0be  /tmp/WinXPRecConsole.before
---
 TODO                         |    8 ++
 examples/Makefile.am         |    4 +-
 examples/virt-dhcp-address.c |   97 ++++++++------------
 src/Makefile.am              |    4 +-
 src/dbdump.c                 |    4 -
 src/guestfs-internal.h       |    8 --
 src/inspect-apps.c           |   92 ++++++-------------
 src/inspect-fs-cd.c          |    8 --
 src/inspect-fs-unix.c        |    8 --
 src/inspect-fs-windows.c     |  206 ++++++++++++++++++------------------------
 src/inspect-fs.c             |    8 --
 src/inspect.c                |  143 -----------------------------
 12 files changed, 163 insertions(+), 427 deletions(-)

diff --git a/TODO b/TODO
index 7561c3d..026c94a 100644
--- a/TODO
+++ b/TODO
@@ -570,3 +570,11 @@ mke2fs
 
 Add a mke2fs API call allowing full configuration of filesystems.
 Then fix tests/bigdirs/test-big-dirs.pl to use it.
+
+hivex
+-----
+
+Add more of hivex to the API, especially for writing.
+
+Reimplement virt-win-reg to use this API.  (This is difficult because
+the Perl libraries underneath access the hivex API directly).
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 35bf765..c79a1db 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -95,10 +95,8 @@ virt_dhcp_address_SOURCES = virt-dhcp-address.c
 virt_dhcp_address_CFLAGS = \
 	-DGUESTFS_WARN_DEPRECATED=1 \
 	-I$(top_srcdir)/src -I$(top_builddir)/src \
-	$(WARN_CFLAGS) $(WERROR_CFLAGS) \
-	$(HIVEX_CFLAGS)
+	$(WARN_CFLAGS) $(WERROR_CFLAGS)
 virt_dhcp_address_LDADD = \
-	$(HIVEX_LIBS) \
 	$(top_builddir)/src/libguestfs.la
 endif
 
diff --git a/examples/virt-dhcp-address.c b/examples/virt-dhcp-address.c
index c6f25c6..c4e3647 100644
--- a/examples/virt-dhcp-address.c
+++ b/examples/virt-dhcp-address.c
@@ -17,7 +17,6 @@
 #include <assert.h>
 
 #include <guestfs.h>
-#include <hivex.h>
 
 static int compare_keys_len (const void *p1, const void *p2);
 static size_t count_strings (char *const *argv);
@@ -198,11 +197,8 @@ static void
 print_dhcp_address_windows (guestfs_h *g, char *root_fs)
 {
   char *system_path;
-  char tmpfile[] = "/tmp/systemXXXXXX";
-  int fd, err;
-  hive_h *h;
-  hive_node_h root, node, *nodes;
-  hive_value_h value;
+  int64_t root, node, value;
+  struct guestfs_hivex_node_list *nodes;
   char *controlset;
   size_t i;
   char *p;
@@ -215,71 +211,52 @@ print_dhcp_address_windows (guestfs_h *g, char *root_fs)
     exit (EXIT_FAILURE);
   }
 
-  fd = mkstemp (tmpfile);
-  if (fd == -1) {
-    perror ("mkstemp");
-    exit (EXIT_FAILURE);
-  }
-
-  /* Download the SYSTEM hive. */
-  if (guestfs_download (g, system_path, tmpfile) == -1)
+  /* Open the hive to parse it.  Note that before libguestfs 1.19.35
+   * you had to download the file and parse it using hivex(3).  Since
+   * libguestfs 1.19.35, parts of the hivex(3) API are now exposed
+   * through libguestfs, and that is what we'll use here because it is
+   * more convenient and avoids having to download the hive.
+   */
+  if (guestfs_hivex_open (g, system_path, -1) == -1)
     exit (EXIT_FAILURE);
 
   free (system_path);
 
-  controlset = guestfs_inspect_get_windows_current_control_set (g, root_fs);
-  if (controlset == NULL)
-    exit (EXIT_FAILURE);
-
-  /* Open the hive to parse it. */
-  h = hivex_open (tmpfile, 0);
-  err = errno;
-  close (fd);
-  unlink (tmpfile);
-
-  if (h == NULL) {
-    errno = err;
-    perror ("hivex_open");
+  root = guestfs_hivex_root (g);
+  if (root == -1)
     exit (EXIT_FAILURE);
-  }
-
-  root = hivex_root (h);
-  if (root == 0) {
-    perror ("hivex_root");
-    exit (EXIT_FAILURE);
-  }
 
   /* Get ControlSetXXX\Services\Tcpip\Parameters\Interfaces. */
+  controlset = guestfs_inspect_get_windows_current_control_set (g, root_fs);
+  if (controlset == NULL)
+    exit (EXIT_FAILURE);
   const char *path[] = { controlset, "Services", "Tcpip", "Parameters",
                          "Interfaces" };
   node = root;
-  errno = 0;
-  for (i = 0; node != 0 && i < sizeof path / sizeof path[0]; ++i)
-    node = hivex_node_get_child (h, node, path[i]);
+  for (i = 0; node > 0 && i < sizeof path / sizeof path[0]; ++i)
+    node = guestfs_hivex_node_get_child (g, node, path[i]);
+
+  if (node == -1)
+    exit (EXIT_FAILURE);
 
   if (node == 0) {
-    if (errno != 0)
-      perror ("hivex_node_get_child");
-    else
-      fprintf (stderr, "virt-dhcp-address: HKLM\\System\\%s\\Services\\Tcpip\\Parameters\\Interfaces not found.", controlset);
+    fprintf (stderr, "virt-dhcp-address: HKLM\\System\\%s\\Services\\Tcpip\\Parameters\\Interfaces not found.", controlset);
     exit (EXIT_FAILURE);
   }
 
+  free (controlset);
+
   /* Look for a node under here which has a "DhcpIPAddress" entry in it. */
-  nodes = hivex_node_children (h, node);
-  if (nodes == NULL) {
-    perror ("hivex_node_children");
+  nodes = guestfs_hivex_node_children (g, node);
+  if (nodes == NULL)
     exit (EXIT_FAILURE);
-  }
 
   value = 0;
-  for (i = 0; value == 0 && nodes[i] != 0; ++i) {
-    errno = 0;
-    value = hivex_node_get_value (h, nodes[i], "DhcpIPAddress");
-    if (value == 0 && errno != 0) {
-      perror ("hivex_node_get_value");
+  for (i = 0; value == 0 && i < nodes->len; ++i) {
+    value = guestfs_hivex_node_get_value (g, nodes->val[i].hivex_node_h,
+                                          "DhcpIPAddress");
+    if (value == -1)
       exit (EXIT_FAILURE);
-    }
   }
 
   if (value == 0) {
@@ -287,21 +264,21 @@ print_dhcp_address_windows (guestfs_h *g, char *root_fs)
     exit (EXIT_FAILURE);
   }
 
-  /* Get the string and use hivex's auto-conversion to convert it to UTF-8
-   * for output.
+  guestfs_free_hivex_node_list (nodes);
+
+  /* Get the string and use libguestfs's auto-conversion to convert it
+   * to UTF-8 for output.
    */
-  p = hivex_value_string (h, value);
-  if (!p) {
-    perror ("hivex_value_string");
+  p = guestfs_hivex_value_utf8 (g, value);
+  if (!p)
     exit (EXIT_FAILURE);
-  }
 
   printf ("%s\n", p);
 
-  /* Close the hive handle. */
-  hivex_close (h);
+  free (p);
 
-  free (controlset);
+  /* Close the hive handle. */
+  guestfs_hivex_close (g);
 }
 
 static int
diff --git a/src/Makefile.am b/src/Makefile.am
index 5d3639a..5e79662 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -148,7 +148,7 @@ libguestfs_la_SOURCES = \
 	libguestfs.syms
 
 libguestfs_la_LIBADD = \
-	$(HIVEX_LIBS) $(PCRE_LIBS) $(MAGIC_LIBS) \
+	$(PCRE_LIBS) $(MAGIC_LIBS) \
 	$(LIBVIRT_LIBS) $(LIBXML2_LIBS) \
 	../gnulib/lib/libgnu.la \
 	$(GETADDRINFO_LIB) \
@@ -167,7 +167,7 @@ libguestfs_la_LIBADD += liberrnostring.la libprotocol.la
 libguestfs_la_CFLAGS = \
   -DGUESTFS_DEFAULT_PATH='"$(libdir)/guestfs"' \
   -DGUESTFS_WARN_DEPRECATED=1 \
-  $(HIVEX_CFLAGS) $(PCRE_CFLAGS) \
+  $(PCRE_CFLAGS) \
   $(LIBVIRT_CFLAGS) $(LIBXML2_CFLAGS) \
   $(WARN_CFLAGS) $(WERROR_CFLAGS) \
   $(GCC_VISIBILITY_HIDDEN)
diff --git a/src/dbdump.c b/src/dbdump.c
index ac20b67..0bdd9f4 100644
--- a/src/dbdump.c
+++ b/src/dbdump.c
@@ -34,10 +34,6 @@
 
 #include <pcre.h>
 
-#ifdef HAVE_HIVEX
-#include <hivex.h>
-#endif
-
 #include "c-ctype.h"
 #include "ignore-value.h"
 
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 2355f13..b2f7518 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -107,11 +107,6 @@
 #define MAX_SMALL_FILE_SIZE    (2 * 1000 * 1000)
 #define MAX_AUGEAS_FILE_SIZE        (100 * 1000)
 
-/* Maximum Windows Registry hive that we will download to /tmp.  Some
- * registries can be legitimately very large.
- */
-#define MAX_REGISTRY_SIZE    (100 * 1000 * 1000)
-
 /* Maximum RPM or dpkg database we will download to /tmp.  RPM
  * 'Packages' database can get very large: 70 MB is roughly the
  * standard size for a new Fedora install, and after lots of package
@@ -474,8 +469,6 @@ extern char *guestfs___download_to_tmp (guestfs_h *g, struct inspect_fs *fs, con
 extern char *guestfs___case_sensitive_path_silently (guestfs_h *g, const char *);
 extern struct inspect_fs *guestfs___search_for_root (guestfs_h *g, const char *root);
 extern char *guestfs___drive_name (size_t index, char *ret);
-
-#if defined(HAVE_HIVEX)
 extern int guestfs___check_for_filesystem_on (guestfs_h *g, const char *device, int is_block, int is_partnum);
 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);
@@ -491,7 +484,6 @@ extern int guestfs___check_netbsd_root (guestfs_h *g, struct inspect_fs *fs);
 extern int guestfs___check_hurd_root (guestfs_h *g, struct inspect_fs *fs);
 extern int guestfs___has_windows_systemroot (guestfs_h *g);
 extern int guestfs___check_windows_root (guestfs_h *g, struct inspect_fs *fs);
-#endif
 
 #define error(g,...) guestfs_error_errno((g),0,__VA_ARGS__)
 #define perrorf guestfs_perrorf
diff --git a/src/inspect-apps.c b/src/inspect-apps.c
index 1b0b5a5..06a02e2 100644
--- a/src/inspect-apps.c
+++ b/src/inspect-apps.c
@@ -34,10 +34,6 @@
 
 #include <pcre.h>
 
-#ifdef HAVE_HIVEX
-#include <hivex.h>
-#endif
-
 #include "c-ctype.h"
 #include "ignore-value.h"
 #include "xstrtol.h"
@@ -47,8 +43,6 @@
 #include "guestfs-internal-actions.h"
 #include "guestfs_protocol.h"
 
-#if defined(HAVE_HIVEX)
-
 #ifdef DB_DUMP
 static struct guestfs_application_list *list_applications_rpm (guestfs_h *g, struct inspect_fs *fs);
 #endif
@@ -414,7 +408,7 @@ list_applications_deb (guestfs_h *g, struct inspect_fs *fs)
   return ret;
 }
 
-static void list_applications_windows_from_path (guestfs_h *g, hive_h *h, struct guestfs_application_list *apps, const char **path, size_t path_len);
+static void list_applications_windows_from_path (guestfs_h *g, struct guestfs_application_list *apps, const char **path, size_t path_len);
 
 static struct guestfs_application_list *
 list_applications_windows (guestfs_h *g, struct inspect_fs *fs)
@@ -431,24 +425,12 @@ list_applications_windows (guestfs_h *g, struct inspect_fs *fs)
     return NULL;
   }
 
-  char *software_hive = NULL;
   struct guestfs_application_list *ret = NULL;
-  hive_h *h = NULL;
 
-  software_hive = guestfs___download_to_tmp (g, fs, software_path, "software",
-                                             MAX_REGISTRY_SIZE);
-  if (software_hive == NULL)
+  if (guestfs_hivex_open (g, software_path,
+                          GUESTFS_HIVEX_OPEN_VERBOSE, g->verbose, -1) == -1)
     goto out;
 
-  free (software_path);
-  software_path = NULL;
-
-  h = hivex_open (software_hive, g->verbose ? HIVEX_OPEN_VERBOSE : 0);
-  if (h == NULL) {
-    perrorf (g, "hivex_open");
-    goto out;
-  }
-
   /* Allocate apps list. */
   ret = safe_malloc (g, sizeof *ret);
   ret->len = 0;
@@ -457,7 +439,7 @@ list_applications_windows (guestfs_h *g, struct inspect_fs *fs)
   /* Ordinary native applications. */
   const char *hivepath[] =
     { "Microsoft", "Windows", "CurrentVersion", "Uninstall" };
-  list_applications_windows_from_path (g, h, ret, hivepath,
+  list_applications_windows_from_path (g, ret, hivepath,
                                        sizeof hivepath / sizeof hivepath[0]);
 
   /* 32-bit emulated Windows apps running on the WOW64 emulator.
@@ -465,35 +447,34 @@ list_applications_windows (guestfs_h *g, struct inspect_fs *fs)
    */
   const char *hivepath2[] =
     { "WOW6432node", "Microsoft", "Windows", "CurrentVersion", "Uninstall" };
-  list_applications_windows_from_path (g, h, ret, hivepath2,
+  list_applications_windows_from_path (g, ret, hivepath2,
                                        sizeof hivepath2 / sizeof hivepath2[0]);
 
  out:
-  if (h) hivex_close (h);
+  guestfs_hivex_close (g);
   free (software_path);
-  free (software_hive);
 
   return ret;
 }
 
 static void
-list_applications_windows_from_path (guestfs_h *g, hive_h *h,
+list_applications_windows_from_path (guestfs_h *g,
                                      struct guestfs_application_list *apps,
                                      const char **path, size_t path_len)
 {
-  hive_node_h *children = NULL;
-  hive_node_h node;
+  struct guestfs_hivex_node_list *children = NULL;
+  int64_t node;
   size_t i;
 
-  node = hivex_root (h);
+  node = guestfs_hivex_root (g);
 
   for (i = 0; node != 0 && i < path_len; ++i)
-    node = hivex_node_get_child (h, node, path[i]);
+    node = guestfs_hivex_node_get_child (g, node, path[i]);
 
   if (node == 0)
     return;
 
-  children = hivex_node_children (h, node);
+  children = guestfs_hivex_node_children (g, node);
   if (children == NULL)
     return;
 
@@ -501,8 +482,9 @@ list_applications_windows_from_path (guestfs_h *g, hive_h *h,
    * See also:
    * http://nsis.sourceforge.net/Add_uninstall_information_to_Add/Remove_Programs#Optional_values
    */
-  for (i = 0; children[i] != 0; ++i) {
-    hive_value_h value;
+  for (i = 0; i < children->len; ++i) {
+    int64_t child = children->val[i].hivex_node_h;
+    int64_t value;
     char *name = NULL;
     char *display_name = NULL;
     char *version = NULL;
@@ -514,29 +496,29 @@ list_applications_windows_from_path (guestfs_h *g, hive_h *h,
     /* Use the node name as a proxy for the package name in Linux.  The
      * display name is not language-independent, so it cannot be used.
      */
-    name = hivex_node_name (h, children[i]);
+    name = guestfs_hivex_node_name (g, child);
     if (name == NULL)
       continue;
 
-    value = hivex_node_get_value (h, children[i], "DisplayName");
+    value = guestfs_hivex_node_get_value (g, child, "DisplayName");
     if (value) {
-      display_name = hivex_value_string (h, value);
+      display_name = guestfs_hivex_value_utf8 (g, value);
       if (display_name) {
-        value = hivex_node_get_value (h, children[i], "DisplayVersion");
+        value = guestfs_hivex_node_get_value (g, child, "DisplayVersion");
         if (value)
-          version = hivex_value_string (h, value);
-        value = hivex_node_get_value (h, children[i], "InstallLocation");
+          version = guestfs_hivex_value_utf8 (g, value);
+        value = guestfs_hivex_node_get_value (g, child, "InstallLocation");
         if (value)
-          install_path = hivex_value_string (h, value);
-        value = hivex_node_get_value (h, children[i], "Publisher");
+          install_path = guestfs_hivex_value_utf8 (g, value);
+        value = guestfs_hivex_node_get_value (g, child, "Publisher");
         if (value)
-          publisher = hivex_value_string (h, value);
-        value = hivex_node_get_value (h, children[i], "URLInfoAbout");
+          publisher = guestfs_hivex_value_utf8 (g, value);
+        value = guestfs_hivex_node_get_value (g, child, "URLInfoAbout");
         if (value)
-          url = hivex_value_string (h, value);
-        value = hivex_node_get_value (h, children[i], "Comments");
+          url = guestfs_hivex_value_utf8 (g, value);
+        value = guestfs_hivex_node_get_value (g, child, "Comments");
         if (value)
-          comments = hivex_value_string (h, value);
+          comments = guestfs_hivex_value_utf8 (g, value);
 
         add_application (g, apps, name, display_name, 0,
                          version ? : "",
@@ -557,7 +539,7 @@ list_applications_windows_from_path (guestfs_h *g, hive_h *h,
     free (comments);
   }
 
-  free (children);
+  guestfs_free_hivex_node_list (children);
 }
 
 static void
@@ -606,19 +588,3 @@ sort_applications (struct guestfs_application_list *apps)
     qsort (apps->val, apps->len, sizeof (struct guestfs_application),
            compare_applications);
 }
-
-#else /* no hivex at compile time */
-
-/* XXX These functions should be in an optgroup. */
-
-#define NOT_IMPL(r)                                                     \
-  error (g, _("inspection API not available since this version of libguestfs was compiled without the hivex library")); \
-  return r
-
-struct guestfs_application_list *
-guestfs__inspect_list_applications (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-#endif /* no hivex at compile time */
diff --git a/src/inspect-fs-cd.c b/src/inspect-fs-cd.c
index 6fec8a5..614f9a4 100644
--- a/src/inspect-fs-cd.c
+++ b/src/inspect-fs-cd.c
@@ -34,10 +34,6 @@
 
 #include <pcre.h>
 
-#ifdef HAVE_HIVEX
-#include <hivex.h>
-#endif
-
 #include "c-ctype.h"
 #include "ignore-value.h"
 #include "xstrtol.h"
@@ -47,8 +43,6 @@
 #include "guestfs-internal-actions.h"
 #include "guestfs_protocol.h"
 
-#if defined(HAVE_HIVEX)
-
 /* Debian/Ubuntu install disks are easy ...
  *
  * These files are added by the debian-cd program, and it is worth
@@ -484,5 +478,3 @@ guestfs___check_installer_root (guestfs_h *g, struct inspect_fs *fs)
 
   return 0;
 }
-
-#endif /* defined(HAVE_HIVEX) */
diff --git a/src/inspect-fs-unix.c b/src/inspect-fs-unix.c
index 433ef5c..c00e69b 100644
--- a/src/inspect-fs-unix.c
+++ b/src/inspect-fs-unix.c
@@ -34,10 +34,6 @@
 
 #include <pcre.h>
 
-#ifdef HAVE_HIVEX
-#include <hivex.h>
-#endif
-
 #include "c-ctype.h"
 #include "ignore-value.h"
 #include "xstrtol.h"
@@ -49,8 +45,6 @@
 #include "guestfs-internal-actions.h"
 #include "guestfs_protocol.h"
 
-#if defined(HAVE_HIVEX)
-
 /* Compile all the regular expressions once when the shared library is
  * loaded.  PCRE is thread safe so we're supposedly OK here if
  * multiple threads call into the libguestfs API functions below
@@ -1536,5 +1530,3 @@ is_partition (guestfs_h *g, const char *partition)
 
   return 1;
 }
-
-#endif /* defined(HAVE_HIVEX) */
diff --git a/src/inspect-fs-windows.c b/src/inspect-fs-windows.c
index cd2bd6c..e972e97 100644
--- a/src/inspect-fs-windows.c
+++ b/src/inspect-fs-windows.c
@@ -35,10 +35,6 @@
 
 #include <pcre.h>
 
-#ifdef HAVE_HIVEX
-#include <hivex.h>
-#endif
-
 #include "c-ctype.h"
 #include "ignore-value.h"
 #include "xstrtol.h"
@@ -48,8 +44,6 @@
 #include "guestfs-internal-actions.h"
 #include "guestfs_protocol.h"
 
-#if defined(HAVE_HIVEX)
-
 /* Compile all the regular expressions once when the shared library is
  * loaded.  PCRE is thread safe so we're supposedly OK here if
  * multiple threads call into the libguestfs API functions below
@@ -215,6 +209,8 @@ check_windows_arch (guestfs_h *g, struct inspect_fs *fs)
 static int
 check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs)
 {
+  int ret = -1;
+
   size_t len = strlen (fs->windows_systemroot) + 64;
   char software[len];
   snprintf (software, len, "%s/system32/config/software",
@@ -227,60 +223,46 @@ check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs)
      */
     return 0;
 
-  char *software_hive = NULL;
-  int ret = -1;
-  hive_h *h = NULL;
-  hive_value_h *values = NULL;
-
-  software_hive = guestfs___download_to_tmp (g, fs, software_path, "software",
-                                             MAX_REGISTRY_SIZE);
-  if (software_hive == NULL)
+  if (guestfs_hivex_open (g, software_path,
+                          GUESTFS_HIVEX_OPEN_VERBOSE, g->verbose, -1) == -1)
     goto out;
 
-  h = hivex_open (software_hive, g->verbose ? HIVEX_OPEN_VERBOSE : 0);
-  if (h == NULL) {
-    perrorf (g, "hivex_open");
-    goto out;
-  }
-
-  hive_node_h node = hivex_root (h);
+  int64_t node = guestfs_hivex_root (g);
   const char *hivepath[] =
     { "Microsoft", "Windows NT", "CurrentVersion" };
   size_t i;
-  for (i = 0;
-       node != 0 && i < sizeof hivepath / sizeof hivepath[0];
-       ++i) {
-    node = hivex_node_get_child (h, node, hivepath[i]);
-  }
+  for (i = 0; node > 0 && i < sizeof hivepath / sizeof hivepath[0]; ++i)
+    node = guestfs_hivex_node_get_child (g, node, hivepath[i]);
+
+  if (node == -1)
+    goto out;
 
   if (node == 0) {
     perrorf (g, "hivex: cannot locate HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
     goto out;
   }
 
-  values = hivex_node_values (h, node);
+  struct guestfs_hivex_value_list *values = NULL;
+  values = guestfs_hivex_node_values (g, node);
 
-  for (i = 0; values[i] != 0; ++i) {
-    char *key = hivex_value_key (h, values[i]);
-    if (key == NULL) {
-      perrorf (g, "hivex_value_key");
-      goto out;
-    }
+  for (i = 0; i < values->len; ++i) {
+    int64_t value = values->val[i].hivex_value_h;
+    char *key = guestfs_hivex_value_key (g, value);
+    if (key == NULL)
+      goto out2;
 
     if (STRCASEEQ (key, "ProductName")) {
-      fs->product_name = hivex_value_string (h, values[i]);
+      fs->product_name = guestfs_hivex_value_utf8 (g, value);
       if (!fs->product_name) {
-        perrorf (g, "hivex_value_string");
         free (key);
-        goto out;
+        goto out2;
       }
     }
     else if (STRCASEEQ (key, "CurrentVersion")) {
-      char *version = hivex_value_string (h, values[i]);
+      char *version = guestfs_hivex_value_utf8 (g, value);
       if (!version) {
-        perrorf (g, "hivex_value_string");
         free (key);
-        goto out;
+        goto out2;
       }
       char *major, *minor;
       if (match2 (g, version, re_windows_version, &major, &minor)) {
@@ -290,25 +272,24 @@ check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs)
           free (minor);
           free (key);
           free (version);
-          goto out;
+          goto out2;
         }
         fs->minor_version = guestfs___parse_unsigned_int (g, minor);
         free (minor);
         if (fs->minor_version == -1) {
           free (key);
           free (version);
-          goto out;
+          goto out2;
         }
       }
 
       free (version);
     }
     else if (STRCASEEQ (key, "InstallationType")) {
-      fs->product_variant = hivex_value_string (h, values[i]);
+      fs->product_variant = guestfs_hivex_value_utf8 (g, value);
       if (!fs->product_variant) {
-        perrorf (g, "hivex_value_string");
         free (key);
-        goto out;
+        goto out2;
       }
     }
 
@@ -317,11 +298,11 @@ check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs)
 
   ret = 0;
 
+ out2:
+  guestfs_free_hivex_value_list (values);
  out:
-  if (h) hivex_close (h);
-  free (values);
+  guestfs_hivex_close (g);
   free (software_path);
-  free (software_hive);
 
   return ret;
 }
@@ -341,110 +322,94 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
      */
     return 0;
 
-  char *system_hive = NULL;
   int ret = -1;
-  hive_h *h = NULL;
-  hive_node_h root, node;
-  hive_value_h value, *values = NULL;
+  int64_t root, node, value;
+  struct guestfs_hivex_value_list *values = NULL;
   int32_t dword;
   size_t i, count;
+  char *buf = NULL;
+  size_t buflen;
 
-  system_hive =
-    guestfs___download_to_tmp (g, fs, system_path, "system",
-                               MAX_REGISTRY_SIZE);
-  if (system_hive == NULL)
+  if (guestfs_hivex_open (g, system_path,
+                          GUESTFS_HIVEX_OPEN_VERBOSE, g->verbose, -1) == -1)
     goto out;
 
-  h = hivex_open (system_hive, g->verbose ? HIVEX_OPEN_VERBOSE : 0);
-  if (h == NULL) {
-    perrorf (g, "hivex_open");
+  root = guestfs_hivex_root (g);
+  if (root == 0)
     goto out;
-  }
 
-  root = hivex_root (h);
-  if (root == 0) {
-    perrorf (g, "hivex_root");
+  /* Get the CurrentControlSet. */
+  node = guestfs_hivex_node_get_child (g, root, "Select");
+  if (node == -1)
     goto out;
-  }
 
-  /* Get the CurrentControlSet. */
-  errno = 0;
-  node = hivex_node_get_child (h, root, "Select");
   if (node == 0) {
-    if (errno != 0)
-      perrorf (g, "hivex_node_get_child");
-    else
-      error (g, "hivex: could not locate HKLM\\SYSTEM\\Select");
+    error (g, "hivex: could not locate HKLM\\SYSTEM\\Select");
     goto out;
   }
 
-  errno = 0;
-  value = hivex_node_get_value (h, node, "Current");
+  value = guestfs_hivex_node_get_value (g, node, "Current");
+  if (value == -1)
+    goto out;
+
   if (value == 0) {
-    if (errno != 0)
-      perrorf (g, "hivex_node_get_value");
-    else
-      error (g, "hivex: HKLM\\System\\Select Default entry not found.");
+    error (g, "hivex: HKLM\\System\\Select Default entry not found");
     goto out;
   }
 
   /* XXX Should check the type. */
-  dword = hivex_value_dword (h, value);
+  buf = guestfs_hivex_value_value (g, value, &buflen);
+  if (buflen != 4) {
+    error (g, "hivex: HKLM\\System\\Select\\Current expected to be DWORD");
+    goto out;
+  }
+  dword = le32toh (*(int32_t *)buf);
   fs->windows_current_control_set = safe_asprintf (g, "ControlSet%03d", dword);
 
   /* Get the drive mappings.
    * This page explains the contents of HKLM\System\MountedDevices:
    * http://www.goodells.net/multiboot/partsigs.shtml
    */
-  errno = 0;
-  node = hivex_node_get_child (h, root, "MountedDevices");
-  if (node == 0) {
-    if (errno == 0)
-      /* Not found: skip getting drive letter mappings (RHBZ#803664). */
-      goto skip_drive_letter_mappings;
-    /* errno != 0, so it's some other error from hivex */
-    perrorf (g, "hivex_node_get_child");
+  node = guestfs_hivex_node_get_child (g, root, "MountedDevices");
+  if (node == -1)
     goto out;
-  }
 
-  values = hivex_node_values (h, node);
+  if (node == 0)
+    /* Not found: skip getting drive letter mappings (RHBZ#803664). */
+    goto skip_drive_letter_mappings;
+
+  values = guestfs_hivex_node_values (g, node);
 
   /* Count how many DOS drive letter mappings there are.  This doesn't
    * ignore removable devices, so it overestimates, but that doesn't
    * matter because it just means we'll allocate a few bytes extra.
    */
-  for (i = count = 0; values[i] != 0; ++i) {
-    char *key = hivex_value_key (h, values[i]);
-    if (key == NULL) {
-      perrorf (g, "hivex_value_key");
+  for (i = count = 0; i < values->len; ++i) {
+    char *key = guestfs_hivex_value_key (g, values->val[i].hivex_value_h);
+    if (key == NULL)
       goto out;
-    }
     if (STRCASEEQLEN (key, "\\DosDevices\\", 12) &&
         c_isalpha (key[12]) && key[13] == ':')
       count++;
     free (key);
   }
 
-  fs->drive_mappings = calloc (2*count + 1, sizeof (char *));
-  if (fs->drive_mappings == NULL) {
-    perrorf (g, "calloc");
-    goto out;
-  }
+  fs->drive_mappings = safe_calloc (g, 2*count + 1, sizeof (char *));
 
-  for (i = count = 0; values[i] != 0; ++i) {
-    char *key = hivex_value_key (h, values[i]);
-    if (key == NULL) {
-      perrorf (g, "hivex_value_key");
+  for (i = count = 0; i < values->len; ++i) {
+    int64_t v = values->val[i].hivex_value_h;
+    char *key = guestfs_hivex_value_key (g, v);
+    if (key == NULL)
       goto out;
-    }
     if (STRCASEEQLEN (key, "\\DosDevices\\", 12) &&
         c_isalpha (key[12]) && key[13] == ':') {
       /* Get the binary value.  Is it a fixed disk? */
       char *blob, *device;
       size_t len;
-      hive_type type;
+      int64_t type;
 
-      blob = hivex_value_value (h, values[i], &type, &len);
+      type = guestfs_hivex_value_type (g, v);
+      blob = guestfs_hivex_value_value (g, v, &len);
       if (blob != NULL && type == 3 && len == 12) {
         /* Try to map the blob to a known disk and partition. */
         device = map_registry_disk_blob (g, blob);
@@ -463,31 +428,34 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
   const char *hivepath[] =
     { fs->windows_current_control_set, "Services", "Tcpip", "Parameters" };
   for (node = root, i = 0;
-       node != 0 && i < sizeof hivepath / sizeof hivepath[0];
+       node > 0 && i < sizeof hivepath / sizeof hivepath[0];
        ++i) {
-    node = hivex_node_get_child (h, node, hivepath[i]);
+    node = guestfs_hivex_node_get_child (g, node, hivepath[i]);
   }
 
+  if (node == -1)
+    goto out;
+
   if (node == 0) {
     perrorf (g, "hivex: cannot locate HKLM\\SYSTEM\\%s\\Services\\Tcpip\\Parameters",
              fs->windows_current_control_set);
     goto out;
   }
 
-  free (values);
-  values = hivex_node_values (h, node);
+  guestfs_free_hivex_value_list (values);
+  values = guestfs_hivex_node_values (g, node);
+  if (values == NULL)
+    goto out;
 
-  for (i = 0; values[i] != 0; ++i) {
-    char *key = hivex_value_key (h, values[i]);
-    if (key == NULL) {
-      perrorf (g, "hivex_value_key");
+  for (i = 0; i < values->len; ++i) {
+    int64_t v = values->val[i].hivex_value_h;
+    char *key = guestfs_hivex_value_key (g, v);
+    if (key == NULL)
       goto out;
-    }
 
     if (STRCASEEQ (key, "Hostname")) {
-      fs->hostname = hivex_value_string (h, values[i]);
+      fs->hostname = guestfs_hivex_value_utf8 (g, v);
       if (!fs->hostname) {
-        perrorf (g, "hivex_value_string");
         free (key);
         goto out;
       }
@@ -500,10 +468,10 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
   ret = 0;
 
  out:
-  if (h) hivex_close (h);
-  free (values);
+  guestfs_hivex_close (g);
+  if (values) guestfs_free_hivex_value_list (values);
   free (system_path);
-  free (system_hive);
+  free (buf);
 
   return ret;
 }
@@ -577,8 +545,6 @@ map_registry_disk_blob (guestfs_h *g, const char *blob)
   return ret;
 }
 
-#endif /* defined(HAVE_HIVEX) */
-
 char *
 guestfs___case_sensitive_path_silently (guestfs_h *g, const char *path)
 {
diff --git a/src/inspect-fs.c b/src/inspect-fs.c
index 33aff35..456a546 100644
--- a/src/inspect-fs.c
+++ b/src/inspect-fs.c
@@ -34,10 +34,6 @@
 
 #include <pcre.h>
 
-#ifdef HAVE_HIVEX
-#include <hivex.h>
-#endif
-
 #include "c-ctype.h"
 #include "ignore-value.h"
 #include "xstrtol.h"
@@ -47,8 +43,6 @@
 #include "guestfs-internal-actions.h"
 #include "guestfs_protocol.h"
 
-#if defined(HAVE_HIVEX)
-
 /* Compile all the regular expressions once when the shared library is
  * loaded.  PCRE is thread safe so we're supposedly OK here if
  * multiple threads call into the libguestfs API functions below
@@ -603,5 +597,3 @@ guestfs___first_egrep_of_file (guestfs_h *g, const char *filename,
 
   return 1;
 }
-
-#endif /* defined(HAVE_HIVEX) */
diff --git a/src/inspect.c b/src/inspect.c
index 44826c3..8cba6b1 100644
--- a/src/inspect.c
+++ b/src/inspect.c
@@ -34,10 +34,6 @@
 
 #include <pcre.h>
 
-#ifdef HAVE_HIVEX
-#include <hivex.h>
-#endif
-
 #include "c-ctype.h"
 #include "ignore-value.h"
 #include "xstrtol.h"
@@ -47,8 +43,6 @@
 #include "guestfs-internal-actions.h"
 #include "guestfs_protocol.h"
 
-#if defined(HAVE_HIVEX)
-
 /* The main inspection code. */
 char **
 guestfs__inspect_os (guestfs_h *g)
@@ -540,143 +534,6 @@ guestfs__inspect_get_hostname (guestfs_h *g, const char *root)
   return safe_strdup (g, fs->hostname ? : "unknown");
 }
 
-#else /* no hivex at compile time */
-
-/* XXX These functions should be in an optgroup. */
-
-#define NOT_IMPL(r)                                                     \
-  guestfs_error_errno (g, ENOTSUP, _("inspection API not available since this version of libguestfs was compiled without the hivex library")); \
-  return r
-
-char **
-guestfs__inspect_os (guestfs_h *g)
-{
-  NOT_IMPL(NULL);
-}
-
-char **
-guestfs__inspect_get_roots (guestfs_h *g)
-{
-  NOT_IMPL(NULL);
-}
-
-char *
-guestfs__inspect_get_type (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-char *
-guestfs__inspect_get_arch (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-char *
-guestfs__inspect_get_distro (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-int
-guestfs__inspect_get_major_version (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(-1);
-}
-
-int
-guestfs__inspect_get_minor_version (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(-1);
-}
-
-char *
-guestfs__inspect_get_product_name (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-char *
-guestfs__inspect_get_product_variant (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-char *
-guestfs__inspect_get_windows_systemroot (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-char *
-guestfs__inspect_get_windows_current_control_set (guestfs_h *g,
-                                                  const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-char **
-guestfs__inspect_get_mountpoints (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-char **
-guestfs__inspect_get_filesystems (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-char **
-guestfs__inspect_get_drive_mappings (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-char *
-guestfs__inspect_get_package_format (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-char *
-guestfs__inspect_get_package_management (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-char *
-guestfs__inspect_get_hostname (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-char *
-guestfs__inspect_get_format (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(NULL);
-}
-
-int
-guestfs__inspect_is_live (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(-1);
-}
-
-int
-guestfs__inspect_is_netinst (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(-1);
-}
-
-int
-guestfs__inspect_is_multipart (guestfs_h *g, const char *root)
-{
-  NOT_IMPL(-1);
-}
-
-#endif /* no hivex at compile time */
-
 void
 guestfs___free_inspect_info (guestfs_h *g)
 {
-- 
1.7.10.4




More information about the Libguestfs mailing list