[Libguestfs] [PATCH v3 1/2] common: extract UTF-8 conversion function

Cédric Bosdonnat
Wed, 28 Feb 2018 08:59:02 -0000

libxml2-utils.c local_string_to_utf8() function could easily be reused
in other places. This commit extracts it with a new parameter to allow
giving the encoding of the input string and publishes it in
guestfs-utils.h as guestfs_int_string_to_utf8()
---
 common/utils/guestfs-utils.h | 11 +++++++
 common/utils/libxml2-utils.c | 69 +-------------------------------------------
 common/utils/utils.c         | 64 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 76 insertions(+), 68 deletions(-)

diff --git a/common/utils/guestfs-utils.h b/common/utils/guestfs-utils.h
index 90e7c3dd9..86da693bc 100644
--- a/common/utils/guestfs-utils.h
+++ b/common/utils/guestfs-utils.h
@@ -33,6 +33,7 @@
 #define GUESTFS_UTILS_H_

 #include <stdbool.h>
+#include <langinfo.h>

 #include "guestfs-internal-all.h"
 #include "cleanups.h"
@@ -70,6 +71,16 @@ extern int guestfs_int_is_fifo (int64_t mode);
 extern int guestfs_int_is_lnk (int64_t mode);
 extern int guestfs_int_is_sock (int64_t mode);
 extern char *guestfs_int_full_path (const char *dir, const char *name);
+extern char *guestfs_int_string_to_utf8 (/* const */ char *input, const char
*encoding);
+
+/* Would be const, but the interface to iconv is not const-correct on
+ * all platforms.  The input string is not touched.
+ */
+static inline char *
+guestfs_int_local_string_to_utf8 (/* const */ char *input)
+{
+  return guestfs_int_string_to_utf8 (input, nl_langinfo (CODESET));
+}

 /* Not all language bindings know how to deal with Pointer arguments.
  * Those that don't will use this macro which complains noisily and
diff --git a/common/utils/libxml2-utils.c b/common/utils/libxml2-utils.c
index 8a05aa5b1..a71db30dd 100644
--- a/common/utils/libxml2-utils.c
+++ b/common/utils/libxml2-utils.c
@@ -30,8 +30,6 @@
 #include <string.h>
 #include <errno.h>
 #include <locale.h>
-#include <langinfo.h>
-#include <iconv.h>

 #include <libxml/uri.h>

@@ -42,8 +40,6 @@
 #include "guestfs-utils.h"
 #include "libxml2-utils.h"

-static char *local_string_to_utf8 (/* const */ char *input);
-
 /**
  * This is a wrapper around C<xmlParseURI>.  That function cannot
  * handle spaces and some non-ASCII characters found in URIs.  This
@@ -73,7 +69,7 @@ guestfs_int_parse_nonstandard_uri (const char *arg)
   xmlURIPtr ret;

   /* Convert the string to UTF-8. */
-  uri = local_string_to_utf8 ((char *) arg);
+  uri = guestfs_int_local_string_to_utf8 ((char *) arg);
   if (uri == NULL)
     return NULL;

@@ -113,66 +109,3 @@ guestfs_int_parse_nonstandard_uri (const char *arg)

   return ret;
 }
-
-/* Would be const, but the interface to iconv is not const-correct on
- * all platforms.  The input string is not touched.
- */
-static char *
-local_string_to_utf8 (/* const */ char *input)
-{
-  iconv_t ic;
-  size_t len, inlen, outlen, outalloc, r, prev;
-  int err;
-  char *out, *inp, *outp;
-
-  /* Convert from input locale to UTF-8. */
-  ic = iconv_open ("UTF-8", nl_langinfo (CODESET));
-  if (ic == (iconv_t) -1)
-    return NULL;
-
-  len = strlen (input);
-  outalloc = len;               /* Initial guess. */
-
- again:
-  inlen = len;
-  outlen = outalloc;
-  out = malloc (outlen + 1);
-  if (out == NULL) {
-    err = errno;
-    iconv_close (ic);
-    errno = err;
-    return NULL;
-  }
-  inp = input;
-  outp = out;
-
-  r = iconv (ic, (ICONV_CONST char **) &inp, &inlen, &outp,
&outlen);
-  if (r == (size_t) -1) {
-    if (errno == E2BIG) {
-      err = errno;
-      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 other conversion failure, eg. EILSEQ, EINVAL. */
-      err = errno;
-      iconv_close (ic);
-      free (out);
-      errno = err;
-      return NULL;
-    }
-  }
-
-  *outp = '\0';
-  iconv_close (ic);
-
-  return out;
-}
diff --git a/common/utils/utils.c b/common/utils/utils.c
index 22af62b0f..faef7c089 100644
--- a/common/utils/utils.c
+++ b/common/utils/utils.c
@@ -35,6 +35,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <libintl.h>
+#include <iconv.h>

 /* NB: MUST NOT require linking to gnulib, because that will break the
  * Python 'sdist' which includes a copy of this file.  It's OK to
@@ -733,3 +734,66 @@ guestfs_int_full_path (const char *dir, const char *name)

   return path;
 }
+
+/* Would be const, but the interface to iconv is not const-correct on
+ * all platforms.  The input string is not touched.
+ */
+char *
+guestfs_int_string_to_utf8 (/* const */ char *input, const char *encoding)
+{
+  iconv_t ic;
+  size_t len, inlen, outlen, outalloc, r, prev;
+  int err;
+  char *out, *inp, *outp;
+
+  /* Convert from input encoding to UTF-8. */
+  ic = iconv_open ("UTF-8", encoding);
+  if (ic == (iconv_t) -1)
+    return NULL;
+
+  len = strlen (input);
+  outalloc = len;               /* Initial guess. */
+
+ again:
+  inlen = len;
+  outlen = outalloc;
+  out = malloc (outlen + 1);
+  if (out == NULL) {
+    err = errno;
+    iconv_close (ic);
+    errno = err;
+    return NULL;
+  }
+  inp = input;
+  outp = out;
+
+  r = iconv (ic, (ICONV_CONST char **) &inp, &inlen, &outp,
&outlen);
+  if (r == (size_t) -1) {
+    if (errno == E2BIG) {
+      err = errno;
+      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 other conversion failure, eg. EILSEQ, EINVAL. */
+      err = errno;
+      iconv_close (ic);
+      free (out);
+      errno = err;
+      return NULL;
+    }
+  }
+
+  *outp = '\0';
+  iconv_close (ic);
+
+  return out;
+}
--
2.16.1