]> xenbits.xensource.com Git - libvirt.git/commitdiff
json: fix interface locale dependency
authorMartin Kletzander <mkletzan@redhat.com>
Sat, 11 Aug 2012 19:13:00 +0000 (21:13 +0200)
committerMartin Kletzander <mkletzan@redhat.com>
Tue, 14 Aug 2012 05:30:14 +0000 (07:30 +0200)
libvirt creates invalid commands if wrong locale is selected. For
example with locale that uses comma as a decimal point, JSON commands
created with decimal numbers are invalid because comma separates the
entries in JSON. Fortunately even when decimal point is affected,
thousands grouping is not, because for grouping to be enabled with
*printf, there has to be an apostrophe flag specified (and supported).

This patch adds specific internal function for converting doubles to
strings with C locale.

bootstrap.conf
configure.ac
src/libvirt_private.syms
src/util/json.c
src/util/util.c
src/util/util.h

index c112ccd8a889e72ed0dd0723180eac836d5c3cac..a4e1c2fa1b6349c770ad8e889a9540855901939a 100644 (file)
@@ -62,6 +62,7 @@ ioctl
 isatty
 largefile
 listen
+localeconv
 maintainer-makefile
 manywarnings
 mkstemp
index 8a04d912c7537191b84e5daaf63c535b8f799036..3951012051dd92e6b9912d07efd9803f9f51a448 100644 (file)
@@ -132,8 +132,8 @@ AC_CHECK_SIZEOF([long])
 dnl Availability of various common functions (non-fatal if missing),
 dnl and various less common threadsafe functions
 AC_CHECK_FUNCS_ONCE([cfmakeraw geteuid getgid getgrnam_r getmntent_r \
-  getpwuid_r getuid initgroups kill mmap posix_fallocate posix_memalign \
-  regexec sched_getaffinity])
+  getpwuid_r getuid initgroups kill mmap newlocale posix_fallocate \
+  posix_memalign regexec sched_getaffinity])
 
 dnl Availability of pthread functions (if missing, win32 threading is
 dnl assumed).  Because of $LIB_PTHREAD, we cannot use AC_CHECK_FUNCS_ONCE.
index c023dbf4cc68d3224e5dc82d498f381b4c998be0..018d3a93290b6e104be1b926ee85c69b318b36dc 100644 (file)
@@ -1140,6 +1140,7 @@ virArgvToString;
 virAsprintf;
 virBuildPathInternal;
 virDirCreate;
+virDoubleToStr;
 virEnumFromString;
 virEnumToString;
 virEventAddHandle;
index 51329897bc1b4ff573af37d93a42c873282eb91c..40d50a1db364436024fc07360ccbc9f10b0cd1c6 100644 (file)
@@ -201,7 +201,7 @@ virJSONValuePtr virJSONValueNewNumberDouble(double data)
 {
     virJSONValuePtr val = NULL;
     char *str;
-    if (virAsprintf(&str, "%lf", data) < 0)
+    if (virDoubleToStr(&str, data) < 0)
         return NULL;
     val = virJSONValueNewNumber(str);
     VIR_FREE(str);
index e5bb27b358511c5cf5a5c6b7979f0ced464efd77..4a720d8584fbfd27a96b6693048be183ae98c0f5 100644 (file)
@@ -44,6 +44,7 @@
 #include <signal.h>
 #include <termios.h>
 #include <pty.h>
+#include <locale.h>
 
 #if HAVE_LIBDEVMAPPER_H
 # include <libdevmapper.h>
@@ -2060,6 +2061,68 @@ int virEnumFromString(const char *const*types,
     return -1;
 }
 
+/* In case thread-safe locales are available */
+#if HAVE_NEWLOCALE
+
+static locale_t virLocale;
+
+static int
+virLocaleOnceInit(void)
+{
+    virLocale = newlocale(LC_ALL_MASK, "C", (locale_t)0);
+    if (!virLocale)
+        return -1;
+    return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(virLocale)
+#endif
+
+/**
+ * virDoubleToStr
+ *
+ * converts double to string with C locale (thread-safe).
+ *
+ * Returns -1 on error, size of the string otherwise.
+ */
+int
+virDoubleToStr(char **strp, double number)
+{
+    int ret = -1;
+
+#if HAVE_NEWLOCALE
+
+    locale_t old_loc;
+
+    if (virLocaleInitialize() < 0)
+        goto error;
+
+    old_loc = uselocale(virLocale);
+    ret = virAsprintf(strp, "%lf", number);
+    uselocale(old_loc);
+
+#else
+
+    char *radix, *tmp;
+    struct lconv *lc;
+
+    if ((ret = virVasprintf(strp, "%lf", number) < 0)
+        goto error;
+
+    lc = localeconv();
+    radix = lc->decimal_point;
+    tmp = strstr(*strp, radix);
+    if (tmp) {
+        *tmp = '.';
+        if (strlen(radix) > 1)
+            memmove(tmp + 1, tmp + strlen(radix), strlen(*strp) - (tmp - str));
+    }
+
+#endif /* HAVE_NEWLOCALE */
+ error:
+    return ret;
+}
+
 const char *virEnumToString(const char *const*types,
                             unsigned int ntypes,
                             int type)
index d151c274053d1c10fad7397f06758f5f12a16ab6..a5d892dd4c81cc26800553b642a2ccb765fab942 100644 (file)
@@ -209,6 +209,9 @@ char *virStrcpy(char *dest, const char *src, size_t destbytes)
     ATTRIBUTE_RETURN_CHECK;
 # define virStrcpyStatic(dest, src) virStrcpy((dest), (src), sizeof(dest))
 
+int virDoubleToStr(char **strp, double number)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
 int virDiskNameToIndex(const char* str);
 char *virIndexToDiskName(int idx, const char *prefix);