[Libguestfs] [PATCH v12 04/11] New API: Deprecate hivex_value_utf8 and replace with hivex_value_string.

Richard W.M. Jones rjones at redhat.com
Wed Aug 9 17:23:39 UTC 2017


hivex has a function hivex_value_string.  We were not calling it under
the mistaken belief that because hivex implements this using iconv,
the function wouldn't work inside the daemon.  Instead we
reimplemented the functionality in the library.

This commit deprecates hivex_value_utf8 and removes the library side
code.  It replaces it with a plain wrapper around hivex_value_string.

Thanks: Pino Toscano
---
 daemon/hivex.c                         |  23 +++++++
 docs/C_SOURCE_FILES                    |   1 -
 examples/virt-dhcp-address.c           |   2 +-
 generator/Makefile.am                  |   3 +
 generator/actions.ml                   |   2 +-
 generator/actions_hivex.ml             |  35 +++++------
 generator/actions_hivex.mli            |   1 -
 generator/actions_hivex_deprecated.ml  |  43 +++++++++++++
 generator/actions_hivex_deprecated.mli |  21 +++++++
 generator/proc_nr.ml                   |   2 +
 lib/MAX_PROC_NR                        |   2 +-
 lib/Makefile.am                        |   1 -
 lib/hivex.c                            | 111 ---------------------------------
 lib/inspect-apps.c                     |  12 ++--
 lib/inspect-fs-windows.c               |   8 +--
 v2v/convert_windows.ml                 |   6 +-
 16 files changed, 124 insertions(+), 149 deletions(-)

diff --git a/daemon/hivex.c b/daemon/hivex.c
index 1cbfb3458..2d0913f43 100644
--- a/daemon/hivex.c
+++ b/daemon/hivex.c
@@ -335,6 +335,29 @@ do_hivex_value_value (int64_t valueh, size_t *size_r)
   return r;
 }
 
+char *
+do_hivex_value_string (int64_t valueh)
+{
+  char *r;
+
+  NEED_HANDLE (NULL);
+
+  r = hivex_value_string (h, valueh);
+  if (r == NULL) {
+    reply_with_perror ("failed");
+    return NULL;
+  }
+
+  return r;
+}
+
+/* Deprecated alias for hivex_value_string. */
+char *
+do_hivex_value_utf8 (int64_t valueh)
+{
+  return do_hivex_value_string (valueh);
+}
+
 int
 do_hivex_commit (const char *filename)
 {
diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES
index 65e62f643..d5e358140 100644
--- a/docs/C_SOURCE_FILES
+++ b/docs/C_SOURCE_FILES
@@ -310,7 +310,6 @@ lib/guestfs-internal.h
 lib/guestfs.h
 lib/guid.c
 lib/handle.c
-lib/hivex.c
 lib/info.c
 lib/inspect-apps.c
 lib/inspect-fs-unix.c
diff --git a/examples/virt-dhcp-address.c b/examples/virt-dhcp-address.c
index 0c7e763ff..caf89b88e 100644
--- a/examples/virt-dhcp-address.c
+++ b/examples/virt-dhcp-address.c
@@ -266,7 +266,7 @@ print_dhcp_address_windows (guestfs_h *g, char *root_fs)
   /* Get the string and use libguestfs's auto-conversion to convert it
    * to UTF-8 for output.
    */
-  p = guestfs_hivex_value_utf8 (g, value);
+  p = guestfs_hivex_value_string (g, value);
   if (!p)
     exit (EXIT_FAILURE);
 
diff --git a/generator/Makefile.am b/generator/Makefile.am
index 35b7a4209..7c1ac9ee2 100644
--- a/generator/Makefile.am
+++ b/generator/Makefile.am
@@ -31,6 +31,8 @@ sources = \
 	actions_debug.mli \
 	actions_hivex.ml \
 	actions_hivex.mli \
+	actions_hivex_deprecated.ml \
+	actions_hivex_deprecated.mli \
 	actions_inspection.ml \
 	actions_inspection.mli \
 	actions_inspection_deprecated.ml \
@@ -122,6 +124,7 @@ objects = \
 	actions_core_deprecated.cmo \
 	actions_debug.cmo \
 	actions_hivex.cmo \
+	actions_hivex_deprecated.cmo \
 	actions_inspection.cmo \
 	actions_inspection_deprecated.cmo \
 	actions_internal_tests.cmo \
diff --git a/generator/actions.ml b/generator/actions.ml
index 75742397a..79e2265d2 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -33,7 +33,6 @@ let non_daemon_functions =
   Actions_core.non_daemon_functions @
   Actions_core_deprecated.non_daemon_functions @
   Actions_debug.non_daemon_functions @
-  Actions_hivex.non_daemon_functions @
   Actions_inspection.non_daemon_functions @
   Actions_inspection_deprecated.non_daemon_functions @
   Actions_properties.non_daemon_functions @
@@ -51,6 +50,7 @@ let daemon_functions =
   Actions_core_deprecated.daemon_functions @
   Actions_debug.daemon_functions @
   Actions_hivex.daemon_functions @
+  Actions_hivex_deprecated.daemon_functions @
   Actions_tsk.daemon_functions @
   Actions_yara.daemon_functions
 
diff --git a/generator/actions_hivex.ml b/generator/actions_hivex.ml
index 0a3d6dd20..6ccb65fa6 100644
--- a/generator/actions_hivex.ml
+++ b/generator/actions_hivex.ml
@@ -22,25 +22,6 @@ open Types
 
 (* Hivex APIs. *)
 
-let non_daemon_functions = [
-  { defaults with
-    name = "hivex_value_utf8"; added = (1, 19, 35);
-    style = RString (RPlainString, "databuf"), [Int64 "valueh"], [];
-    optional = Some "hivex";
-    shortdesc = "return the data field from the (key, datatype, data) tuple";
-    longdesc = "\
-This calls C<guestfs_hivex_value_value> (which returns the
-data field from a hivex value tuple).  It then assumes that
-the field is a UTF-16LE string and converts the result to
-UTF-8 (or if this is not possible, it returns an error).
-
-This is useful for reading strings out of the Windows registry.
-However it is not foolproof because the registry is not
-strongly-typed and fields can contain arbitrary or unexpected
-data." };
-
-]
-
 let daemon_functions = [
   { defaults with
     name = "hivex_open"; added = (1, 19, 35);
@@ -179,6 +160,22 @@ This is a wrapper around the L<hivex(3)> call of the same name.
 See also: C<guestfs_hivex_value_utf8>." };
 
   { defaults with
+    name = "hivex_value_string"; added = (1, 37, 22);
+    style = RString (RPlainString, "databuf"), [Int64 "valueh"], [];
+    optional = Some "hivex";
+    shortdesc = "return the data field as a UTF-8 string";
+    longdesc = "\
+This calls C<guestfs_hivex_value_value> (which returns the
+data field from a hivex value tuple).  It then assumes that
+the field is a UTF-16LE string and converts the result to
+UTF-8 (or if this is not possible, it returns an error).
+
+This is useful for reading strings out of the Windows registry.
+However it is not foolproof because the registry is not
+strongly-typed and fields can contain arbitrary or unexpected
+data." };
+
+  { defaults with
     name = "hivex_commit"; added = (1, 19, 35);
     style = RErr, [OptString "filename"], [];
     optional = Some "hivex";
diff --git a/generator/actions_hivex.mli b/generator/actions_hivex.mli
index 06b8116c4..23eefe068 100644
--- a/generator/actions_hivex.mli
+++ b/generator/actions_hivex.mli
@@ -18,5 +18,4 @@
 
 (* Please read generator/README first. *)
 
-val non_daemon_functions : Types.action list
 val daemon_functions : Types.action list
diff --git a/generator/actions_hivex_deprecated.ml b/generator/actions_hivex_deprecated.ml
new file mode 100644
index 000000000..dcb92fd05
--- /dev/null
+++ b/generator/actions_hivex_deprecated.ml
@@ -0,0 +1,43 @@
+(* libguestfs
+ * Copyright (C) 2009-2017 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *)
+
+(* Please read generator/README first. *)
+
+open Types
+
+(* Deprecated hivex APIs. *)
+
+let daemon_functions = [
+  { defaults with
+    name = "hivex_value_utf8"; added = (1, 19, 35);
+    style = RString (RPlainString, "databuf"), [Int64 "valueh"], [];
+    optional = Some "hivex";
+    deprecated_by = Replaced_by "hivex_value_string";
+    shortdesc = "return the data field as a UTF-8 string";
+    longdesc = "\
+This calls C<guestfs_hivex_value_value> (which returns the
+data field from a hivex value tuple).  It then assumes that
+the field is a UTF-16LE string and converts the result to
+UTF-8 (or if this is not possible, it returns an error).
+
+This is useful for reading strings out of the Windows registry.
+However it is not foolproof because the registry is not
+strongly-typed and fields can contain arbitrary or unexpected
+data." };
+
+]
diff --git a/generator/actions_hivex_deprecated.mli b/generator/actions_hivex_deprecated.mli
new file mode 100644
index 000000000..23eefe068
--- /dev/null
+++ b/generator/actions_hivex_deprecated.mli
@@ -0,0 +1,21 @@
+(* libguestfs
+ * Copyright (C) 2009-2017 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *)
+
+(* Please read generator/README first. *)
+
+val daemon_functions : Types.action list
diff --git a/generator/proc_nr.ml b/generator/proc_nr.ml
index 7895063b6..046f424ea 100644
--- a/generator/proc_nr.ml
+++ b/generator/proc_nr.ml
@@ -485,6 +485,8 @@ let proc_nr = [
 475, "file_architecture";
 476, "list_filesystems";
 477, "part_resize";
+478, "hivex_value_utf8";
+479, "hivex_value_string";
 ]
 
 (* End of list.  If adding a new entry, add it at the end of the list
diff --git a/lib/MAX_PROC_NR b/lib/MAX_PROC_NR
index bf2c10d23..bf110299d 100644
--- a/lib/MAX_PROC_NR
+++ b/lib/MAX_PROC_NR
@@ -1 +1 @@
-477
+479
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 83b33ac8d..c7b6be955 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -92,7 +92,6 @@ libguestfs_la_SOURCES = \
 	fuse.c \
 	guid.c \
 	handle.c \
-	hivex.c \
 	info.c \
 	inspect.c \
 	inspect-apps.c \
diff --git a/lib/hivex.c b/lib/hivex.c
deleted file mode 100644
index 2d782e192..000000000
--- a/lib/hivex.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/* libguestfs
- * Copyright (C) 2010-2012 Red Hat Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <iconv.h>
-
-#include "guestfs.h"
-#include "guestfs-internal.h"
-#include "guestfs-internal-actions.h"
-
-/* Read the data from 'valueh', assume it is UTF16LE and convert it to
- * UTF8.  This is copied from hivex_value_string which doesn't work in
- * the appliance because it uses iconv_open which doesn't work because
- * we delete all the i18n databases.
- */
-static char *utf16_to_utf8 (/* const */ char *input, size_t len);
-
-char *
-guestfs_impl_hivex_value_utf8 (guestfs_h *g, int64_t valueh)
-{
-  char *ret;
-  size_t buflen;
-
-  CLEANUP_FREE char *buf = guestfs_hivex_value_value (g, valueh, &buflen);
-  if (buf == NULL)
-    return NULL;
-
-  ret = utf16_to_utf8 (buf, buflen);
-  if (ret == NULL) {
-    perrorf (g, "hivex: conversion of registry value to UTF8 failed");
-    return NULL;
-  }
-
-  return ret;
-}
-
-static char *
-utf16_to_utf8 (/* const */ char *input, size_t len)
-{
-  iconv_t ic = iconv_open ("UTF-8", "UTF-16LE");
-  if (ic == (iconv_t) -1)
-    return NULL;
-
-  /* iconv(3) has an insane interface ... */
-
-  /* Mostly UTF-8 will be smaller, so this is a good initial guess. */
-  size_t outalloc = len;
-
- again:;
-  size_t inlen = len;
-  size_t outlen = outalloc;
-  char *out = malloc (outlen + 1);
-  if (out == NULL) {
-    int err = errno;
-    iconv_close (ic);
-    errno = err;
-    return NULL;
-  }
-  char *inp = input;
-  char *outp = out;
-
-  const size_t r =
-    iconv (ic, (ICONV_CONST char **) &inp, &inlen, &outp, &outlen);
-  if (r == (size_t) -1) {
-    if (errno == E2BIG) {
-      const int err = errno;
-      const size_t prev = outalloc;
-      /* Try again with a larger output buffer. */
-      free (out);
-      outalloc *= 2;
-      if (outalloc < prev) {
-        iconv_close (ic);
-        errno = err;
-        return NULL;
-      }
-      goto again;
-    }
-    else {
-      /* Else some conversion failure, eg. EILSEQ, EINVAL. */
-      const int err = errno;
-      iconv_close (ic);
-      free (out);
-      errno = err;
-      return NULL;
-    }
-  }
-
-  *outp = '\0';
-  iconv_close (ic);
-
-  return out;
-}
diff --git a/lib/inspect-apps.c b/lib/inspect-apps.c
index 25192340c..0ea962a73 100644
--- a/lib/inspect-apps.c
+++ b/lib/inspect-apps.c
@@ -919,23 +919,23 @@ list_applications_windows_from_path (guestfs_h *g,
 
     value = guestfs_hivex_node_get_value (g, child, "DisplayName");
     if (value) {
-      display_name = guestfs_hivex_value_utf8 (g, value);
+      display_name = guestfs_hivex_value_string (g, value);
       if (display_name) {
         value = guestfs_hivex_node_get_value (g, child, "DisplayVersion");
         if (value)
-          version = guestfs_hivex_value_utf8 (g, value);
+          version = guestfs_hivex_value_string (g, value);
         value = guestfs_hivex_node_get_value (g, child, "InstallLocation");
         if (value)
-          install_path = guestfs_hivex_value_utf8 (g, value);
+          install_path = guestfs_hivex_value_string (g, value);
         value = guestfs_hivex_node_get_value (g, child, "Publisher");
         if (value)
-          publisher = guestfs_hivex_value_utf8 (g, value);
+          publisher = guestfs_hivex_value_string (g, value);
         value = guestfs_hivex_node_get_value (g, child, "URLInfoAbout");
         if (value)
-          url = guestfs_hivex_value_utf8 (g, value);
+          url = guestfs_hivex_value_string (g, value);
         value = guestfs_hivex_node_get_value (g, child, "Comments");
         if (value)
-          comments = guestfs_hivex_value_utf8 (g, value);
+          comments = guestfs_hivex_value_string (g, value);
 
         add_application (g, apps, name, display_name, 0,
                          version ? : "",
diff --git a/lib/inspect-fs-windows.c b/lib/inspect-fs-windows.c
index 34f33c908..9d31c1e6b 100644
--- a/lib/inspect-fs-windows.c
+++ b/lib/inspect-fs-windows.c
@@ -355,7 +355,7 @@ check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs)
       goto out;
 
     if (STRCASEEQ (key, "ProductName")) {
-      fs->product_name = guestfs_hivex_value_utf8 (g, value);
+      fs->product_name = guestfs_hivex_value_string (g, value);
       if (!fs->product_name)
         goto out;
     }
@@ -396,7 +396,7 @@ check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs)
       ignore_currentversion = true;
     }
     else if (!ignore_currentversion && STRCASEEQ (key, "CurrentVersion")) {
-      CLEANUP_FREE char *version = guestfs_hivex_value_utf8 (g, value);
+      CLEANUP_FREE char *version = guestfs_hivex_value_string (g, value);
       if (!version)
         goto out;
       if (guestfs_int_version_from_x_y_re (g, &fs->version, version,
@@ -404,7 +404,7 @@ check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs)
         goto out;
     }
     else if (STRCASEEQ (key, "InstallationType")) {
-      fs->product_variant = guestfs_hivex_value_utf8 (g, value);
+      fs->product_variant = guestfs_hivex_value_string (g, value);
       if (!fs->product_variant)
         goto out;
     }
@@ -568,7 +568,7 @@ check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs)
       goto out;
 
     if (STRCASEEQ (key, "Hostname")) {
-      fs->hostname = guestfs_hivex_value_utf8 (g, v);
+      fs->hostname = guestfs_hivex_value_string (g, v);
       if (!fs->hostname)
         goto out;
     }
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
index 2c8708878..ac2b8180b 100644
--- a/v2v/convert_windows.ml
+++ b/v2v/convert_windows.ml
@@ -145,7 +145,7 @@ let convert (g : G.guestfs) inspect source output rcaps =
                if valueh = 0L then
                  raise Not_found;
 
-               let dispname = g#hivex_value_utf8 valueh in
+               let dispname = g#hivex_value_string valueh in
                if not (Str.string_match (Str.regexp ".*\\(Parallels\\|Virtuozzo\\) Tools.*")
                                         dispname 0) then
                  raise Not_found;
@@ -159,7 +159,7 @@ let convert (g : G.guestfs) inspect source output rcaps =
                  raise Not_found
                );
 
-               let uninst = (g#hivex_value_utf8 valueh) ^
+               let uninst = (g#hivex_value_string valueh) ^
                      " /quiet /norestart /l*v+ \"%~dpn0.log\"" ^
                      " REBOOT=ReallySuppress REMOVE=ALL" ^
                      (* without these custom Parallels-specific MSI properties the
@@ -570,7 +570,7 @@ if errorlevel 3010 exit /b 0
             match Registry.get_node reg path with
             | None -> raise Not_found
             | Some node -> node in
-          let current_boot_entry = g#hivex_value_utf8 (
+          let current_boot_entry = g#hivex_value_string (
             g#hivex_node_get_value boot_mgr_default_link "Element") in
           let path = ["Objects"; current_boot_entry; "Elements"; "16000046"] in
           match Registry.get_node reg path with
-- 
2.13.2




More information about the Libguestfs mailing list