提交 43bfa23e 编写于 作者: M Martin Kletzander

json: fix interface locale dependency

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.
上级 863399f0
......@@ -62,6 +62,7 @@ ioctl
isatty
largefile
listen
localeconv
maintainer-makefile
manywarnings
mkstemp
......
......@@ -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.
......
......@@ -1140,6 +1140,7 @@ virArgvToString;
virAsprintf;
virBuildPathInternal;
virDirCreate;
virDoubleToStr;
virEnumFromString;
virEnumToString;
virEventAddHandle;
......
......@@ -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);
......
......@@ -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)
......
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册