import libguestfs-1.40.2-25.module+el8.3.0+7421+642fe24f
This commit is contained in:
parent
efeedb8128
commit
893b57ed4a
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
SOURCES/RHEV-Application-Provisioning-Tool.exe_4.43-3
|
||||
SOURCES/libguestfs-1.38.4.tar.gz
|
||||
SOURCES/RHEV-Application-Provisioning-Tool.exe_4.43-5
|
||||
SOURCES/libguestfs-1.40.2.tar.gz
|
||||
SOURCES/libguestfs.keyring
|
||||
SOURCES/rhsrvany.exe
|
||||
|
@ -1,4 +1,4 @@
|
||||
ac8722917cc31c36836e241bd7a4beb5f8a8b0c8 SOURCES/RHEV-Application-Provisioning-Tool.exe_4.43-3
|
||||
15c8f487ee163374cb7be9436fb1bb697cef7d9e SOURCES/libguestfs-1.38.4.tar.gz
|
||||
130adbc011dc0af736465b813c2b22a600c128c1 SOURCES/RHEV-Application-Provisioning-Tool.exe_4.43-5
|
||||
45755f0f73b503790974484053ff482f32665b13 SOURCES/libguestfs-1.40.2.tar.gz
|
||||
1bbc40f501a7fef9eef2a39b701a71aee2fea7c4 SOURCES/libguestfs.keyring
|
||||
2bd96e478fc004cd323b5bd754c856641877dac6 SOURCES/rhsrvany.exe
|
||||
|
@ -1,974 +0,0 @@
|
||||
From 21f0a22072f0543c416c440665bcf75ae09e6233 Mon Sep 17 00:00:00 2001
|
||||
From: Pino Toscano <ptoscano@redhat.com>
|
||||
Date: Mon, 12 Feb 2018 11:24:06 +0100
|
||||
Subject: [PATCH] Switch from YAJL to Jansson
|
||||
|
||||
While YAJL mostly works fine, it did not see any active development in
|
||||
the last 3 years. OTOH, Jansson is another JSON C implementation, with
|
||||
a very liberal license, and a much nicer API.
|
||||
|
||||
Hence, switch all of libguestfs from YAJL to Jansson:
|
||||
- configure checks, and buildsystem in general
|
||||
- packages pulled in the appliance
|
||||
- actual implementations
|
||||
- contrib scripts
|
||||
- documentation
|
||||
|
||||
This also makes use of the better APIs available (e.g. json_object_get,
|
||||
json_array_foreach, and json_object_foreach). This does not change the
|
||||
API of our OCaml Yajl module.
|
||||
|
||||
(cherry picked from commit bd1c5c9f4dcf38458099db8a0bf4659a07ef055d)
|
||||
---
|
||||
appliance/packagelist.in | 13 ++--
|
||||
builder/Makefile.am | 4 +-
|
||||
builder/yajl-c.c | 66 ++++++++--------
|
||||
contrib/p2v/aux-scripts/do-build.sh | 8 +-
|
||||
contrib/p2v/build-p2v-iso.sh | 3 +-
|
||||
daemon/Makefile.am | 4 +-
|
||||
daemon/ldm.c | 115 ++++++++++++----------------
|
||||
docs/guestfs-building.pod | 2 +-
|
||||
lib/Makefile.am | 4 +-
|
||||
lib/info.c | 113 +++++++++++----------------
|
||||
lib/qemu.c | 64 ++++++----------
|
||||
m4/guestfs-libraries.m4 | 4 +-
|
||||
12 files changed, 169 insertions(+), 231 deletions(-)
|
||||
|
||||
diff --git a/appliance/packagelist.in b/appliance/packagelist.in
|
||||
index 8ded2588a..f92a6ce95 100644
|
||||
--- a/appliance/packagelist.in
|
||||
+++ b/appliance/packagelist.in
|
||||
@@ -35,6 +35,7 @@ ifelse(REDHAT,1,
|
||||
hivex
|
||||
iproute
|
||||
iputils
|
||||
+ jansson
|
||||
kernel
|
||||
libcap
|
||||
libldm
|
||||
@@ -51,7 +52,6 @@ ifelse(REDHAT,1,
|
||||
systemd dnl for /sbin/reboot and udevd
|
||||
vim-minimal
|
||||
xz
|
||||
- yajl
|
||||
yara
|
||||
zfs-fuse
|
||||
)
|
||||
@@ -82,12 +82,12 @@ dnl iproute has been renamed to iproute2
|
||||
libc-bin
|
||||
libcap2
|
||||
libhivex0
|
||||
+ libjansson4
|
||||
libpcre3
|
||||
libsystemd0
|
||||
libsystemd-id128-0
|
||||
libsystemd-journal0
|
||||
libtirpc1
|
||||
- libyajl2
|
||||
libyara3
|
||||
linux-image
|
||||
dnl syslinux 'suggests' mtools, but in reality it's a hard dependency:
|
||||
@@ -116,6 +116,7 @@ ifelse(ARCHLINUX,1,
|
||||
hivex
|
||||
iproute2
|
||||
iputils
|
||||
+ jansson
|
||||
libcap
|
||||
libtirpc
|
||||
linux
|
||||
@@ -131,7 +132,6 @@ ifelse(ARCHLINUX,1,
|
||||
systemd
|
||||
vim
|
||||
xz
|
||||
- yajl
|
||||
yara
|
||||
)
|
||||
|
||||
@@ -153,9 +153,9 @@ ifelse(SUSE,1,
|
||||
iputils
|
||||
libcap2
|
||||
libhivex0
|
||||
+ libjansson4
|
||||
libselinux1
|
||||
libtirpc3
|
||||
- libyajl2
|
||||
libyara3
|
||||
mkisofs
|
||||
ntfsprogs
|
||||
@@ -177,6 +177,7 @@ ifelse(FRUGALWARE,1,
|
||||
hfsplus
|
||||
iproute2
|
||||
iputils
|
||||
+ jansson
|
||||
kernel
|
||||
libcap
|
||||
libtirpc
|
||||
@@ -188,7 +189,6 @@ ifelse(FRUGALWARE,1,
|
||||
systemd
|
||||
vim
|
||||
xz
|
||||
- yajl
|
||||
xfsprogs-acl
|
||||
xfsprogs-attr
|
||||
gptfdisk
|
||||
@@ -209,9 +209,9 @@ ifelse(MAGEIA,1,
|
||||
iproute2
|
||||
iputils
|
||||
libcap
|
||||
+ libjansson4
|
||||
libldm
|
||||
libtirpc
|
||||
- libyajl
|
||||
dnl syslinux uses mtools without depending on it
|
||||
mtools
|
||||
nilfs-utils
|
||||
@@ -224,7 +224,6 @@ ifelse(MAGEIA,1,
|
||||
systemd /* for /sbin/reboot and udevd */
|
||||
vim-minimal
|
||||
xz
|
||||
- yajl
|
||||
)
|
||||
|
||||
acl
|
||||
diff --git a/builder/Makefile.am b/builder/Makefile.am
|
||||
index e5872bdd9..c7b50778a 100644
|
||||
--- a/builder/Makefile.am
|
||||
+++ b/builder/Makefile.am
|
||||
@@ -157,7 +157,7 @@ virt_builder_CFLAGS = \
|
||||
$(LIBLZMA_CFLAGS) \
|
||||
$(LIBTINFO_CFLAGS) \
|
||||
$(LIBXML2_CFLAGS) \
|
||||
- $(YAJL_CFLAGS)
|
||||
+ $(JANSSON_CFLAGS)
|
||||
|
||||
BOBJECTS = $(SOURCES_ML:.ml=.cmo)
|
||||
XOBJECTS = $(BOBJECTS:.cmo=.cmx)
|
||||
@@ -211,7 +211,7 @@ OCAMLCLIBS = \
|
||||
$(LIBCRYPT_LIBS) \
|
||||
$(LIBLZMA_LIBS) \
|
||||
$(LIBXML2_LIBS) \
|
||||
- $(YAJL_LIBS) \
|
||||
+ $(JANSSON_LIBS) \
|
||||
$(LIBINTL) \
|
||||
-lgnu
|
||||
|
||||
diff --git a/builder/yajl-c.c b/builder/yajl-c.c
|
||||
index 3c2402e42..e53755f55 100644
|
||||
--- a/builder/yajl-c.c
|
||||
+++ b/builder/yajl-c.c
|
||||
@@ -23,24 +23,17 @@
|
||||
#include <caml/memory.h>
|
||||
#include <caml/mlvalues.h>
|
||||
|
||||
-#include <yajl/yajl_tree.h>
|
||||
+#include <jansson.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
-/* GCC can't work out that the YAJL_IS_<foo> test is sufficient to
|
||||
- * ensure that YAJL_GET_<foo> later doesn't return NULL.
|
||||
- */
|
||||
-#if defined(__GNUC__) && __GNUC__ >= 6 /* gcc >= 6 */
|
||||
-#pragma GCC diagnostic ignored "-Wnull-dereference"
|
||||
-#endif
|
||||
-
|
||||
#define Val_none (Val_int (0))
|
||||
|
||||
value virt_builder_yajl_tree_parse (value stringv);
|
||||
|
||||
static value
|
||||
-convert_yajl_value (yajl_val val, int level)
|
||||
+convert_json_t (json_t *val, int level)
|
||||
{
|
||||
CAMLparam0 ();
|
||||
CAMLlocal4 (rv, lv, v, sv);
|
||||
@@ -48,46 +41,51 @@ convert_yajl_value (yajl_val val, int level)
|
||||
if (level > 20)
|
||||
caml_invalid_argument ("too many levels of object/array nesting");
|
||||
|
||||
- if (YAJL_IS_OBJECT (val)) {
|
||||
- const size_t len = YAJL_GET_OBJECT(val)->len;
|
||||
+ if (json_is_object (val)) {
|
||||
+ const size_t len = json_object_size (val);
|
||||
size_t i;
|
||||
+ const char *key;
|
||||
+ json_t *jvalue;
|
||||
rv = caml_alloc (1, 3);
|
||||
lv = caml_alloc_tuple (len);
|
||||
- for (i = 0; i < len; ++i) {
|
||||
+ i = 0;
|
||||
+ json_object_foreach (val, key, jvalue) {
|
||||
v = caml_alloc_tuple (2);
|
||||
- sv = caml_copy_string (YAJL_GET_OBJECT(val)->keys[i]);
|
||||
+ sv = caml_copy_string (key);
|
||||
Store_field (v, 0, sv);
|
||||
- sv = convert_yajl_value (YAJL_GET_OBJECT(val)->values[i], level + 1);
|
||||
+ sv = convert_json_t (jvalue, level + 1);
|
||||
Store_field (v, 1, sv);
|
||||
Store_field (lv, i, v);
|
||||
+ ++i;
|
||||
}
|
||||
Store_field (rv, 0, lv);
|
||||
- } else if (YAJL_IS_ARRAY (val)) {
|
||||
- const size_t len = YAJL_GET_ARRAY(val)->len;
|
||||
+ } else if (json_is_array (val)) {
|
||||
+ const size_t len = json_array_size (val);
|
||||
size_t i;
|
||||
+ json_t *jvalue;
|
||||
rv = caml_alloc (1, 4);
|
||||
lv = caml_alloc_tuple (len);
|
||||
- for (i = 0; i < len; ++i) {
|
||||
- v = convert_yajl_value (YAJL_GET_ARRAY(val)->values[i], level + 1);
|
||||
+ json_array_foreach (val, i, jvalue) {
|
||||
+ v = convert_json_t (jvalue, level + 1);
|
||||
Store_field (lv, i, v);
|
||||
}
|
||||
Store_field (rv, 0, lv);
|
||||
- } else if (YAJL_IS_STRING (val)) {
|
||||
+ } else if (json_is_string (val)) {
|
||||
rv = caml_alloc (1, 0);
|
||||
- v = caml_copy_string (YAJL_GET_STRING(val));
|
||||
+ v = caml_copy_string (json_string_value (val));
|
||||
Store_field (rv, 0, v);
|
||||
- } else if (YAJL_IS_DOUBLE (val)) {
|
||||
+ } else if (json_is_real (val)) {
|
||||
rv = caml_alloc (1, 2);
|
||||
- v = caml_copy_double (YAJL_GET_DOUBLE(val));
|
||||
+ v = caml_copy_double (json_real_value (val));
|
||||
Store_field (rv, 0, v);
|
||||
- } else if (YAJL_IS_INTEGER (val)) {
|
||||
+ } else if (json_is_integer (val)) {
|
||||
rv = caml_alloc (1, 1);
|
||||
- v = caml_copy_int64 (YAJL_GET_INTEGER(val));
|
||||
+ v = caml_copy_int64 (json_integer_value (val));
|
||||
Store_field (rv, 0, v);
|
||||
- } else if (YAJL_IS_TRUE (val)) {
|
||||
+ } else if (json_is_true (val)) {
|
||||
rv = caml_alloc (1, 5);
|
||||
Store_field (rv, 0, Val_true);
|
||||
- } else if (YAJL_IS_FALSE (val)) {
|
||||
+ } else if (json_is_false (val)) {
|
||||
rv = caml_alloc (1, 5);
|
||||
Store_field (rv, 0, Val_false);
|
||||
} else
|
||||
@@ -101,21 +99,21 @@ virt_builder_yajl_tree_parse (value stringv)
|
||||
{
|
||||
CAMLparam1 (stringv);
|
||||
CAMLlocal1 (rv);
|
||||
- yajl_val tree;
|
||||
- char error_buf[256];
|
||||
+ json_t *tree;
|
||||
+ json_error_t err;
|
||||
|
||||
- tree = yajl_tree_parse (String_val (stringv), error_buf, sizeof error_buf);
|
||||
+ tree = json_loads (String_val (stringv), JSON_DECODE_ANY, &err);
|
||||
if (tree == NULL) {
|
||||
- char buf[256 + sizeof error_buf];
|
||||
- if (strlen (error_buf) > 0)
|
||||
- snprintf (buf, sizeof buf, "JSON parse error: %s", error_buf);
|
||||
+ char buf[256 + JSON_ERROR_TEXT_LENGTH];
|
||||
+ if (strlen (err.text) > 0)
|
||||
+ snprintf (buf, sizeof buf, "JSON parse error: %s", err.text);
|
||||
else
|
||||
snprintf (buf, sizeof buf, "unknown JSON parse error");
|
||||
caml_invalid_argument (buf);
|
||||
}
|
||||
|
||||
- rv = convert_yajl_value (tree, 1);
|
||||
- yajl_tree_free (tree);
|
||||
+ rv = convert_json_t (tree, 1);
|
||||
+ json_decref (tree);
|
||||
|
||||
CAMLreturn (rv);
|
||||
}
|
||||
diff --git a/contrib/p2v/aux-scripts/do-build.sh b/contrib/p2v/aux-scripts/do-build.sh
|
||||
index 5edb53d0e..dd6424bb4 100644
|
||||
--- a/contrib/p2v/aux-scripts/do-build.sh
|
||||
+++ b/contrib/p2v/aux-scripts/do-build.sh
|
||||
@@ -53,8 +53,8 @@ case $osversion in
|
||||
# This just forces configure to ignore these missing dependencies.
|
||||
export LIBTINFO_CFLAGS=-D_GNU_SOURCE
|
||||
export LIBTINFO_LIBS=-lncurses
|
||||
- export YAJL_CFLAGS=-D_GNU_SOURCE
|
||||
- export YAJL_LIBS=-lyajl
|
||||
+ export JANSSON_CFLAGS=-D_GNU_SOURCE
|
||||
+ export JANSSON_LIBS=-ljansson
|
||||
# Remove some unsupported flags that the configure script hard codes.
|
||||
sed -i -e 's/-fno-strict-overflow//' configure
|
||||
sed -i -e 's/-Wno-strict-overflow//' configure
|
||||
@@ -66,8 +66,8 @@ case $osversion in
|
||||
# This just forces configure to ignore these missing dependencies.
|
||||
export LIBTINFO_CFLAGS=-D_GNU_SOURCE
|
||||
export LIBTINFO_LIBS=-lncurses
|
||||
- export YAJL_CFLAGS=-D_GNU_SOURCE
|
||||
- export YAJL_LIBS=-lyajl
|
||||
+ export JANSSON_CFLAGS=-D_GNU_SOURCE
|
||||
+ export JANSSON_LIBS=-ljansson
|
||||
;;
|
||||
esac
|
||||
|
||||
diff --git a/contrib/p2v/build-p2v-iso.sh b/contrib/p2v/build-p2v-iso.sh
|
||||
index c80a1b134..ae25cebc8 100755
|
||||
--- a/contrib/p2v/build-p2v-iso.sh
|
||||
+++ b/contrib/p2v/build-p2v-iso.sh
|
||||
@@ -86,7 +86,6 @@ done
|
||||
# Various hacks for different versions of RHEL.
|
||||
if=virtio
|
||||
netdev=virtio-net-pci
|
||||
-pkgs="$pkgs,yajl-devel"
|
||||
declare -a epel
|
||||
case $osversion in
|
||||
rhel-5.*|centos-5.*)
|
||||
@@ -105,10 +104,12 @@ case $osversion in
|
||||
rhel-6.*|centos-6.*)
|
||||
epel[0]="--run-command"
|
||||
epel[1]="yum install -y --nogpgcheck https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm"
|
||||
+ pkgs="$pkgs,jansson-devel"
|
||||
;;
|
||||
rhel-7.*|centos-7.*)
|
||||
epel[0]="--run-command"
|
||||
epel[1]="yum install -y --nogpgcheck https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm"
|
||||
+ pkgs="$pkgs,jansson-devel"
|
||||
;;
|
||||
esac
|
||||
|
||||
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
|
||||
index 6240f517d..d9ed5625e 100644
|
||||
--- a/daemon/Makefile.am
|
||||
+++ b/daemon/Makefile.am
|
||||
@@ -218,7 +218,7 @@ guestfsd_LDADD = \
|
||||
camldaemon.o \
|
||||
$(ACL_LIBS) \
|
||||
$(CAP_LIBS) \
|
||||
- $(YAJL_LIBS) \
|
||||
+ $(JANSSON_LIBS) \
|
||||
$(SELINUX_LIBS) \
|
||||
$(AUGEAS_LIBS) \
|
||||
$(HIVEX_LIBS) \
|
||||
@@ -256,7 +256,7 @@ guestfsd_CFLAGS = \
|
||||
$(AUGEAS_CFLAGS) \
|
||||
$(HIVEX_CFLAGS) \
|
||||
$(SD_JOURNAL_CFLAGS) \
|
||||
- $(YAJL_CFLAGS) \
|
||||
+ $(JANSSON_CFLAGS) \
|
||||
$(PCRE_CFLAGS)
|
||||
|
||||
# Parts of the daemon are written in OCaml. These are linked into a
|
||||
diff --git a/daemon/ldm.c b/daemon/ldm.c
|
||||
index 2f4d2aef3..be4fb9701 100644
|
||||
--- a/daemon/ldm.c
|
||||
+++ b/daemon/ldm.c
|
||||
@@ -25,19 +25,12 @@
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
|
||||
-#include <yajl/yajl_tree.h>
|
||||
+#include <jansson.h>
|
||||
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
#include "optgroups.h"
|
||||
|
||||
-/* GCC can't work out that the YAJL_IS_<foo> test is sufficient to
|
||||
- * ensure that YAJL_GET_<foo> later doesn't return NULL.
|
||||
- */
|
||||
-#if defined(__GNUC__) && GUESTFS_GCC_VERSION >= 60000 /* gcc >= 6 */
|
||||
-#pragma GCC diagnostic ignored "-Wnull-dereference"
|
||||
-#endif
|
||||
-
|
||||
int
|
||||
optgroup_ldm_available (void)
|
||||
{
|
||||
@@ -72,44 +65,42 @@ do_ldmtool_remove_all (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static yajl_val
|
||||
+static json_t *
|
||||
parse_json (const char *json, const char *func)
|
||||
{
|
||||
- yajl_val tree;
|
||||
- char parse_error[1024];
|
||||
+ json_t *tree;
|
||||
+ json_error_t err;
|
||||
|
||||
if (verbose)
|
||||
fprintf (stderr, "%s: parsing json: %s\n", func, json);
|
||||
|
||||
- tree = yajl_tree_parse (json, parse_error, sizeof parse_error);
|
||||
+ tree = json_loads (json, 0, &err);
|
||||
if (tree == NULL) {
|
||||
reply_with_error ("parse error: %s",
|
||||
- strlen (parse_error) ? parse_error : "unknown error");
|
||||
+ strlen (err.text) ? err.text : "unknown error");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- /* Caller should free this by doing 'yajl_tree_free (tree);'. */
|
||||
+ /* Caller should free this by doing 'json_decref (tree);'. */
|
||||
return tree;
|
||||
}
|
||||
|
||||
#define TYPE_ERROR ((char **) -1)
|
||||
|
||||
static char **
|
||||
-json_value_to_string_list (yajl_val node)
|
||||
+json_value_to_string_list (json_t *node)
|
||||
{
|
||||
CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (strs);
|
||||
- yajl_val n;
|
||||
- size_t i, len;
|
||||
+ json_t *n;
|
||||
+ size_t i;
|
||||
|
||||
- if (! YAJL_IS_ARRAY (node))
|
||||
+ if (!json_is_array (node))
|
||||
return TYPE_ERROR;
|
||||
|
||||
- len = YAJL_GET_ARRAY (node)->len;
|
||||
- for (i = 0; i < len; ++i) {
|
||||
- n = YAJL_GET_ARRAY (node)->values[i];
|
||||
- if (! YAJL_IS_STRING (n))
|
||||
+ json_array_foreach (node, i, n) {
|
||||
+ if (!json_is_string (n))
|
||||
return TYPE_ERROR;
|
||||
- if (add_string (&strs, YAJL_GET_STRING (n)) == -1)
|
||||
+ if (add_string (&strs, json_string_value (n)) == -1)
|
||||
return NULL;
|
||||
}
|
||||
if (end_stringsbuf (&strs) == -1)
|
||||
@@ -123,14 +114,14 @@ parse_json_get_string_list (const char *json,
|
||||
const char *func, const char *cmd)
|
||||
{
|
||||
char **ret;
|
||||
- yajl_val tree = NULL;
|
||||
+ json_t *tree = NULL;
|
||||
|
||||
tree = parse_json (json, func);
|
||||
if (tree == NULL)
|
||||
return NULL;
|
||||
|
||||
ret = json_value_to_string_list (tree);
|
||||
- yajl_tree_free (tree);
|
||||
+ json_decref (tree);
|
||||
if (ret == TYPE_ERROR) {
|
||||
reply_with_error ("output of '%s' was not a JSON array of strings", cmd);
|
||||
return NULL;
|
||||
@@ -144,43 +135,40 @@ static char *
|
||||
parse_json_get_object_string (const char *json, const char *key, int flags,
|
||||
const char *func, const char *cmd)
|
||||
{
|
||||
- char *str, *ret;
|
||||
- yajl_val tree = NULL, node;
|
||||
- size_t i, len;
|
||||
+ const char *str;
|
||||
+ char *ret;
|
||||
+ json_t *tree = NULL, *node;
|
||||
|
||||
tree = parse_json (json, func);
|
||||
if (tree == NULL)
|
||||
return NULL;
|
||||
|
||||
- if (! YAJL_IS_OBJECT (tree))
|
||||
+ if (!json_is_object (tree))
|
||||
+ goto bad_type;
|
||||
+
|
||||
+ node = json_object_get (tree, key);
|
||||
+ if (node == NULL)
|
||||
goto bad_type;
|
||||
|
||||
- len = YAJL_GET_OBJECT (tree)->len;
|
||||
- for (i = 0; i < len; ++i) {
|
||||
- if (STREQ (YAJL_GET_OBJECT (tree)->keys[i], key)) {
|
||||
- node = YAJL_GET_OBJECT (tree)->values[i];
|
||||
-
|
||||
- if ((flags & GET_STRING_NULL_TO_EMPTY) && YAJL_IS_NULL (node))
|
||||
- ret = strdup ("");
|
||||
- else {
|
||||
- str = YAJL_GET_STRING (node);
|
||||
- if (str == NULL)
|
||||
- goto bad_type;
|
||||
- ret = strdup (str);
|
||||
- }
|
||||
- if (ret == NULL)
|
||||
- reply_with_perror ("strdup");
|
||||
-
|
||||
- yajl_tree_free (tree);
|
||||
-
|
||||
- return ret;
|
||||
- }
|
||||
+ if ((flags & GET_STRING_NULL_TO_EMPTY) && json_is_null (node))
|
||||
+ ret = strdup ("");
|
||||
+ else {
|
||||
+ str = json_string_value (node);
|
||||
+ if (str == NULL)
|
||||
+ goto bad_type;
|
||||
+ ret = strndup (str, json_string_length (node));
|
||||
}
|
||||
+ if (ret == NULL)
|
||||
+ reply_with_perror ("strdup");
|
||||
+
|
||||
+ json_decref (tree);
|
||||
+
|
||||
+ return ret;
|
||||
|
||||
bad_type:
|
||||
reply_with_error ("output of '%s' was not a JSON object "
|
||||
"containing a key '%s' of type string", cmd, key);
|
||||
- yajl_tree_free (tree);
|
||||
+ json_decref (tree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -189,33 +177,30 @@ parse_json_get_object_string_list (const char *json, const char *key,
|
||||
const char *func, const char *cmd)
|
||||
{
|
||||
char **ret;
|
||||
- yajl_val tree, node;
|
||||
- size_t i, len;
|
||||
+ json_t *tree, *node;
|
||||
|
||||
tree = parse_json (json, func);
|
||||
if (tree == NULL)
|
||||
return NULL;
|
||||
|
||||
- if (! YAJL_IS_OBJECT (tree))
|
||||
+ if (!json_is_object (tree))
|
||||
goto bad_type;
|
||||
|
||||
- len = YAJL_GET_OBJECT (tree)->len;
|
||||
- for (i = 0; i < len; ++i) {
|
||||
- if (STREQ (YAJL_GET_OBJECT (tree)->keys[i], key)) {
|
||||
- node = YAJL_GET_OBJECT (tree)->values[i];
|
||||
- ret = json_value_to_string_list (node);
|
||||
- if (ret == TYPE_ERROR)
|
||||
- goto bad_type;
|
||||
- yajl_tree_free (tree);
|
||||
- return ret;
|
||||
- }
|
||||
- }
|
||||
+ node = json_object_get (tree, key);
|
||||
+ if (node == NULL)
|
||||
+ goto bad_type;
|
||||
+
|
||||
+ ret = json_value_to_string_list (node);
|
||||
+ if (ret == TYPE_ERROR)
|
||||
+ goto bad_type;
|
||||
+ json_decref (tree);
|
||||
+ return ret;
|
||||
|
||||
bad_type:
|
||||
reply_with_error ("output of '%s' was not a JSON object "
|
||||
"containing a key '%s' of type array of strings",
|
||||
cmd, key);
|
||||
- yajl_tree_free (tree);
|
||||
+ json_decref (tree);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
diff --git a/docs/guestfs-building.pod b/docs/guestfs-building.pod
|
||||
index d350b1d73..2029429fd 100644
|
||||
--- a/docs/guestfs-building.pod
|
||||
+++ b/docs/guestfs-building.pod
|
||||
@@ -172,7 +172,7 @@ I<Required>.
|
||||
|
||||
I<Required>.
|
||||
|
||||
-=item yajl E<ge> 2.0.4
|
||||
+=item Jansson
|
||||
|
||||
I<Required>.
|
||||
|
||||
diff --git a/lib/Makefile.am b/lib/Makefile.am
|
||||
index 91c4e0a2e..d075174d9 100644
|
||||
--- a/lib/Makefile.am
|
||||
+++ b/lib/Makefile.am
|
||||
@@ -141,7 +141,7 @@ libguestfs_la_CFLAGS = \
|
||||
$(PCRE_CFLAGS) \
|
||||
$(LIBVIRT_CFLAGS) \
|
||||
$(LIBXML2_CFLAGS) \
|
||||
- $(YAJL_CFLAGS)
|
||||
+ $(JANSSON_CFLAGS)
|
||||
|
||||
libguestfs_la_LIBADD = \
|
||||
../common/errnostring/liberrnostring.la \
|
||||
@@ -152,7 +152,7 @@ libguestfs_la_LIBADD = \
|
||||
$(PCRE_LIBS) \
|
||||
$(LIBVIRT_LIBS) $(LIBXML2_LIBS) \
|
||||
$(SELINUX_LIBS) \
|
||||
- $(YAJL_LIBS) \
|
||||
+ $(JANSSON_LIBS) \
|
||||
../gnulib/lib/libgnu.la \
|
||||
$(GETADDRINFO_LIB) \
|
||||
$(HOSTENT_LIB) \
|
||||
diff --git a/lib/info.c b/lib/info.c
|
||||
index 93fadcd39..2eadc1c11 100644
|
||||
--- a/lib/info.c
|
||||
+++ b/lib/info.c
|
||||
@@ -37,53 +37,46 @@
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
-#include <yajl/yajl_tree.h>
|
||||
+#include <jansson.h>
|
||||
|
||||
#include "guestfs.h"
|
||||
#include "guestfs-internal.h"
|
||||
#include "guestfs-internal-actions.h"
|
||||
|
||||
#ifdef HAVE_ATTRIBUTE_CLEANUP
|
||||
-#define CLEANUP_YAJL_TREE_FREE __attribute__((cleanup(cleanup_yajl_tree_free)))
|
||||
+#define CLEANUP_JSON_T_DECREF __attribute__((cleanup(cleanup_json_t_decref)))
|
||||
|
||||
static void
|
||||
-cleanup_yajl_tree_free (void *ptr)
|
||||
+cleanup_json_t_decref (void *ptr)
|
||||
{
|
||||
- yajl_tree_free (* (yajl_val *) ptr);
|
||||
+ json_decref (* (json_t **) ptr);
|
||||
}
|
||||
|
||||
#else
|
||||
-#define CLEANUP_YAJL_TREE_FREE
|
||||
+#define CLEANUP_JSON_T_DECREF
|
||||
#endif
|
||||
|
||||
-static yajl_val get_json_output (guestfs_h *g, const char *filename);
|
||||
+static json_t *get_json_output (guestfs_h *g, const char *filename);
|
||||
static void set_child_rlimits (struct command *);
|
||||
|
||||
char *
|
||||
guestfs_impl_disk_format (guestfs_h *g, const char *filename)
|
||||
{
|
||||
- size_t i, len;
|
||||
- CLEANUP_YAJL_TREE_FREE yajl_val tree = get_json_output (g, filename);
|
||||
+ CLEANUP_JSON_T_DECREF json_t *tree = get_json_output (g, filename);
|
||||
+ json_t *node;
|
||||
|
||||
if (tree == NULL)
|
||||
return NULL;
|
||||
|
||||
- if (! YAJL_IS_OBJECT (tree))
|
||||
+ if (!json_is_object (tree))
|
||||
goto bad_type;
|
||||
|
||||
- len = YAJL_GET_OBJECT(tree)->len;
|
||||
- for (i = 0; i < len; ++i) {
|
||||
- if (STREQ (YAJL_GET_OBJECT(tree)->keys[i], "format")) {
|
||||
- const char *str;
|
||||
- yajl_val node = YAJL_GET_OBJECT(tree)->values[i];
|
||||
- if (YAJL_IS_NULL (node))
|
||||
- goto bad_type;
|
||||
- str = YAJL_GET_STRING (node);
|
||||
- if (str == NULL)
|
||||
- goto bad_type;
|
||||
- return safe_strdup (g, str); /* caller frees */
|
||||
- }
|
||||
- }
|
||||
+ node = json_object_get (tree, "format");
|
||||
+ if (!json_is_string (node))
|
||||
+ goto bad_type;
|
||||
+
|
||||
+ return safe_strndup (g, json_string_value (node),
|
||||
+ json_string_length (node)); /* caller frees */
|
||||
|
||||
bad_type:
|
||||
error (g, _("qemu-img info: JSON output did not contain ‘format’ key"));
|
||||
@@ -93,30 +86,20 @@ guestfs_impl_disk_format (guestfs_h *g, const char *filename)
|
||||
int64_t
|
||||
guestfs_impl_disk_virtual_size (guestfs_h *g, const char *filename)
|
||||
{
|
||||
- size_t i, len;
|
||||
- CLEANUP_YAJL_TREE_FREE yajl_val tree = get_json_output (g, filename);
|
||||
+ CLEANUP_JSON_T_DECREF json_t *tree = get_json_output (g, filename);
|
||||
+ json_t *node;
|
||||
|
||||
if (tree == NULL)
|
||||
return -1;
|
||||
|
||||
- if (! YAJL_IS_OBJECT (tree))
|
||||
+ if (!json_is_object (tree))
|
||||
goto bad_type;
|
||||
|
||||
- len = YAJL_GET_OBJECT(tree)->len;
|
||||
- for (i = 0; i < len; ++i) {
|
||||
- if (STREQ (YAJL_GET_OBJECT(tree)->keys[i], "virtual-size")) {
|
||||
- yajl_val node = YAJL_GET_OBJECT(tree)->values[i];
|
||||
- if (YAJL_IS_NULL (node))
|
||||
- goto bad_type;
|
||||
- if (! YAJL_IS_NUMBER (node))
|
||||
- goto bad_type;
|
||||
- if (! YAJL_IS_INTEGER (node)) {
|
||||
- error (g, _("qemu-img info: ‘virtual-size’ is not representable as a 64 bit integer"));
|
||||
- return -1;
|
||||
- }
|
||||
- return YAJL_GET_INTEGER (node);
|
||||
- }
|
||||
- }
|
||||
+ node = json_object_get (tree, "virtual-size");
|
||||
+ if (!json_is_integer (node))
|
||||
+ goto bad_type;
|
||||
+
|
||||
+ return json_integer_value (node);
|
||||
|
||||
bad_type:
|
||||
error (g, _("qemu-img info: JSON output did not contain ‘virtual-size’ key"));
|
||||
@@ -126,29 +109,25 @@ guestfs_impl_disk_virtual_size (guestfs_h *g, const char *filename)
|
||||
int
|
||||
guestfs_impl_disk_has_backing_file (guestfs_h *g, const char *filename)
|
||||
{
|
||||
- size_t i, len;
|
||||
- CLEANUP_YAJL_TREE_FREE yajl_val tree = get_json_output (g, filename);
|
||||
+ CLEANUP_JSON_T_DECREF json_t *tree = get_json_output (g, filename);
|
||||
+ json_t *node;
|
||||
|
||||
if (tree == NULL)
|
||||
return -1;
|
||||
|
||||
- if (! YAJL_IS_OBJECT (tree))
|
||||
+ if (!json_is_object (tree))
|
||||
goto bad_type;
|
||||
|
||||
- len = YAJL_GET_OBJECT(tree)->len;
|
||||
- for (i = 0; i < len; ++i) {
|
||||
- if (STREQ (YAJL_GET_OBJECT(tree)->keys[i], "backing-filename")) {
|
||||
- yajl_val node = YAJL_GET_OBJECT(tree)->values[i];
|
||||
- /* Work on the assumption that if this field is null, it means
|
||||
- * no backing file, rather than being an error.
|
||||
- */
|
||||
- if (YAJL_IS_NULL (node))
|
||||
- return 0;
|
||||
- return 1;
|
||||
- }
|
||||
- }
|
||||
+ node = json_object_get (tree, "backing-filename");
|
||||
+ if (node == NULL)
|
||||
+ return 0; /* no backing-filename key means no backing file */
|
||||
|
||||
- return 0; /* no backing-filename key means no backing file */
|
||||
+ /* Work on the assumption that if this field is null, it means
|
||||
+ * no backing file, rather than being an error.
|
||||
+ */
|
||||
+ if (json_is_null (node))
|
||||
+ return 0;
|
||||
+ return 1;
|
||||
|
||||
bad_type:
|
||||
error (g, _("qemu-img info: JSON output was not an object"));
|
||||
@@ -161,12 +140,12 @@ guestfs_impl_disk_has_backing_file (guestfs_h *g, const char *filename)
|
||||
static void parse_json (guestfs_h *g, void *treevp, const char *input, size_t len);
|
||||
#define PARSE_JSON_NO_OUTPUT ((void *) -1)
|
||||
|
||||
-static yajl_val
|
||||
+static json_t *
|
||||
get_json_output (guestfs_h *g, const char *filename)
|
||||
{
|
||||
CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
|
||||
int r;
|
||||
- yajl_val tree = NULL;
|
||||
+ json_t *tree = NULL;
|
||||
|
||||
guestfs_int_cmd_add_arg (cmd, "qemu-img");
|
||||
guestfs_int_cmd_add_arg (cmd, "info");
|
||||
@@ -196,16 +175,15 @@ get_json_output (guestfs_h *g, const char *filename)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- return tree; /* caller must call yajl_tree_free (tree) */
|
||||
+ return tree; /* caller must call json_decref (tree) */
|
||||
}
|
||||
|
||||
/* Parse the JSON document printed by qemu-img info --output json. */
|
||||
static void
|
||||
parse_json (guestfs_h *g, void *treevp, const char *input, size_t len)
|
||||
{
|
||||
- yajl_val *tree_ret = treevp;
|
||||
- CLEANUP_FREE char *input_copy = NULL;
|
||||
- char parse_error[256];
|
||||
+ json_t **tree_ret = treevp;
|
||||
+ json_error_t err;
|
||||
|
||||
assert (*tree_ret == NULL);
|
||||
|
||||
@@ -218,15 +196,12 @@ parse_json (guestfs_h *g, void *treevp, const char *input, size_t len)
|
||||
return;
|
||||
}
|
||||
|
||||
- /* 'input' is not \0-terminated; we have to make it so. */
|
||||
- input_copy = safe_strndup (g, input, len);
|
||||
-
|
||||
- debug (g, "%s: qemu-img info JSON output:\n%s\n", __func__, input_copy);
|
||||
+ debug (g, "%s: qemu-img info JSON output:\n%.*s\n", __func__, (int) len, input);
|
||||
|
||||
- *tree_ret = yajl_tree_parse (input_copy, parse_error, sizeof parse_error);
|
||||
+ *tree_ret = json_loadb (input, len, 0, &err);
|
||||
if (*tree_ret == NULL) {
|
||||
- if (strlen (parse_error) > 0)
|
||||
- error (g, _("qemu-img info: JSON parse error: %s"), parse_error);
|
||||
+ if (strlen (err.text) > 0)
|
||||
+ error (g, _("qemu-img info: JSON parse error: %s"), err.text);
|
||||
else
|
||||
error (g, _("qemu-img info: unknown JSON parse error"));
|
||||
}
|
||||
diff --git a/lib/qemu.c b/lib/qemu.c
|
||||
index 6159b5a52..a50eca988 100644
|
||||
--- a/lib/qemu.c
|
||||
+++ b/lib/qemu.c
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
#include <libxml/uri.h>
|
||||
|
||||
-#include <yajl/yajl_tree.h>
|
||||
+#include <jansson.h>
|
||||
|
||||
#include "full-write.h"
|
||||
#include "ignore-value.h"
|
||||
@@ -57,7 +57,7 @@ struct qemu_data {
|
||||
|
||||
/* The following fields are derived from the fields above. */
|
||||
struct version qemu_version; /* Parsed qemu version number. */
|
||||
- yajl_val qmp_schema_tree; /* qmp_schema parsed into a JSON tree */
|
||||
+ json_t *qmp_schema_tree; /* qmp_schema parsed into a JSON tree */
|
||||
};
|
||||
|
||||
static char *cache_filename (guestfs_h *g, const char *cachedir, const struct stat *, const char *suffix);
|
||||
@@ -73,7 +73,7 @@ static int write_cache_qmp_schema (guestfs_h *g, const struct qemu_data *data, c
|
||||
static int read_cache_qemu_stat (guestfs_h *g, struct qemu_data *data, const char *filename);
|
||||
static int write_cache_qemu_stat (guestfs_h *g, const struct qemu_data *data, const char *filename);
|
||||
static void parse_qemu_version (guestfs_h *g, const char *, struct version *qemu_version);
|
||||
-static void parse_json (guestfs_h *g, const char *, yajl_val *);
|
||||
+static void parse_json (guestfs_h *g, const char *, json_t **);
|
||||
static void read_all (guestfs_h *g, void *retv, const char *buf, size_t len);
|
||||
static int generic_read_cache (guestfs_h *g, const char *filename, char **strp);
|
||||
static int generic_write_cache (guestfs_h *g, const char *filename, const char *str);
|
||||
@@ -405,17 +405,17 @@ parse_qemu_version (guestfs_h *g, const char *qemu_help,
|
||||
* is not possible.
|
||||
*/
|
||||
static void
|
||||
-parse_json (guestfs_h *g, const char *json, yajl_val *treep)
|
||||
+parse_json (guestfs_h *g, const char *json, json_t **treep)
|
||||
{
|
||||
- char parse_error[256] = "";
|
||||
+ json_error_t err;
|
||||
|
||||
if (!json)
|
||||
return;
|
||||
|
||||
- *treep = yajl_tree_parse (json, parse_error, sizeof parse_error);
|
||||
+ *treep = json_loads (json, 0, &err);
|
||||
if (*treep == NULL) {
|
||||
- if (strlen (parse_error) > 0)
|
||||
- debug (g, "QMP parse error: %s (ignored)", parse_error);
|
||||
+ if (strlen (err.text) > 0)
|
||||
+ debug (g, "QMP parse error: %s (ignored)", err.text);
|
||||
else
|
||||
debug (g, "QMP unknown parse error (ignored)");
|
||||
}
|
||||
@@ -580,17 +580,6 @@ guestfs_int_qemu_supports_device (guestfs_h *g,
|
||||
return strstr (data->qemu_devices, device_name) != NULL;
|
||||
}
|
||||
|
||||
-/* GCC can't work out that the YAJL_IS_<foo> test is sufficient to
|
||||
- * ensure that YAJL_GET_<foo> later doesn't return NULL.
|
||||
- */
|
||||
-#pragma GCC diagnostic push
|
||||
-#if defined(__GNUC__) && __GNUC__ >= 6 /* gcc >= 6 */
|
||||
-#pragma GCC diagnostic ignored "-Wnull-dereference"
|
||||
-#endif
|
||||
-#if defined(__GNUC__) && GUESTFS_GCC_VERSION >= 40800 /* gcc >= 4.8.0 */
|
||||
-#pragma GCC diagnostic ignored "-Wnonnull"
|
||||
-#endif
|
||||
-
|
||||
/**
|
||||
* Test if the qemu binary uses mandatory file locking, added in
|
||||
* QEMU >= 2.10 (but sometimes disabled).
|
||||
@@ -599,11 +588,7 @@ int
|
||||
guestfs_int_qemu_mandatory_locking (guestfs_h *g,
|
||||
const struct qemu_data *data)
|
||||
{
|
||||
- const char *return_path[] = { "return", NULL };
|
||||
- const char *meta_type_path[] = { "meta-type", NULL };
|
||||
- const char *members_path[] = { "members", NULL };
|
||||
- const char *name_path[] = { "name", NULL };
|
||||
- yajl_val schema, v, meta_type, members, m, name;
|
||||
+ json_t *schema, *v, *meta_type, *members, *m, *name;
|
||||
size_t i, j;
|
||||
|
||||
/* If there's no QMP schema, fall back to checking the version. */
|
||||
@@ -616,27 +601,24 @@ guestfs_int_qemu_mandatory_locking (guestfs_h *g,
|
||||
* Extract the schema from the wrapper. Note the returned ‘schema’
|
||||
* will be an array.
|
||||
*/
|
||||
- schema = yajl_tree_get (data->qmp_schema_tree, return_path, yajl_t_array);
|
||||
- if (schema == NULL)
|
||||
+ schema = json_object_get (data->qmp_schema_tree, "return");
|
||||
+ if (!json_is_array (schema))
|
||||
goto fallback;
|
||||
- assert (YAJL_IS_ARRAY(schema));
|
||||
|
||||
/* Now look for any member of the array which has:
|
||||
* { "meta-type": "object",
|
||||
* "members": [ ... { "name": "locking", ... } ... ] ... }
|
||||
*/
|
||||
- for (i = 0; i < YAJL_GET_ARRAY(schema)->len; ++i) {
|
||||
- v = YAJL_GET_ARRAY(schema)->values[i];
|
||||
- meta_type = yajl_tree_get (v, meta_type_path, yajl_t_string);
|
||||
- if (meta_type && YAJL_IS_STRING (meta_type) &&
|
||||
- STREQ (YAJL_GET_STRING (meta_type), "object")) {
|
||||
- members = yajl_tree_get (v, members_path, yajl_t_array);
|
||||
- if (members) {
|
||||
- for (j = 0; j < YAJL_GET_ARRAY(members)->len; ++j) {
|
||||
- m = YAJL_GET_ARRAY(members)->values[j];
|
||||
- name = yajl_tree_get (m, name_path, yajl_t_string);
|
||||
- if (name && YAJL_IS_STRING (name) &&
|
||||
- STREQ (YAJL_GET_STRING (name), "locking"))
|
||||
+ json_array_foreach (schema, i, v) {
|
||||
+ meta_type = json_object_get (v, "meta-type");
|
||||
+ if (json_is_string (meta_type) &&
|
||||
+ STREQ (json_string_value (meta_type), "object")) {
|
||||
+ members = json_object_get (v, "members");
|
||||
+ if (json_is_array (members)) {
|
||||
+ json_array_foreach (members, j, m) {
|
||||
+ name = json_object_get (v, "name");
|
||||
+ if (json_is_string (name) &&
|
||||
+ STREQ (json_string_value (name), "locking"))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -646,8 +628,6 @@ guestfs_int_qemu_mandatory_locking (guestfs_h *g,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-#pragma GCC diagnostic pop
|
||||
-
|
||||
/**
|
||||
* Escape a qemu parameter.
|
||||
*
|
||||
@@ -996,7 +976,7 @@ guestfs_int_free_qemu_data (struct qemu_data *data)
|
||||
free (data->qemu_help);
|
||||
free (data->qemu_devices);
|
||||
free (data->qmp_schema);
|
||||
- yajl_tree_free (data->qmp_schema_tree);
|
||||
+ json_decref (data->qmp_schema_tree);
|
||||
free (data);
|
||||
}
|
||||
}
|
||||
diff --git a/m4/guestfs-libraries.m4 b/m4/guestfs-libraries.m4
|
||||
index 78a9e792f..2fdbd9669 100644
|
||||
--- a/m4/guestfs-libraries.m4
|
||||
+++ b/m4/guestfs-libraries.m4
|
||||
@@ -299,8 +299,8 @@ LIBS="$LIBS $LIBXML2_LIBS"
|
||||
AC_CHECK_FUNCS([xmlBufferDetach])
|
||||
LIBS="$old_LIBS"
|
||||
|
||||
-dnl Check for yajl JSON library (required).
|
||||
-PKG_CHECK_MODULES([YAJL], [yajl >= 2.0.4])
|
||||
+dnl Check for Jansson JSON library (required).
|
||||
+PKG_CHECK_MODULES([JANSSON], [jansson])
|
||||
|
||||
dnl Check for C++ (optional, we just use this to test the header works).
|
||||
AC_PROG_CXX
|
||||
--
|
||||
2.21.0
|
||||
|
@ -0,0 +1,126 @@
|
||||
From 6e0dbefde3ddb0711e2b0961ee913084dc5e6a41 Mon Sep 17 00:00:00 2001
|
||||
From: Pino Toscano <ptoscano@redhat.com>
|
||||
Date: Tue, 19 Feb 2019 10:50:01 +0100
|
||||
Subject: [PATCH] common/mlpcre: add offset flag for PCRE.matches
|
||||
|
||||
This way it is possible to change where the matching start, instead of
|
||||
always assuming it is the beginning.
|
||||
|
||||
(cherry picked from commit 0ed2e5c14a302d15fd3b75ee2c1cb808a06cb746)
|
||||
---
|
||||
common/mlpcre/PCRE.ml | 2 +-
|
||||
common/mlpcre/PCRE.mli | 5 ++++-
|
||||
common/mlpcre/pcre-c.c | 16 +++++++++++++---
|
||||
common/mlpcre/pcre_tests.ml | 11 ++++++++---
|
||||
4 files changed, 26 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/common/mlpcre/PCRE.ml b/common/mlpcre/PCRE.ml
|
||||
index b054928f9..33074af1c 100644
|
||||
--- a/common/mlpcre/PCRE.ml
|
||||
+++ b/common/mlpcre/PCRE.ml
|
||||
@@ -23,7 +23,7 @@ exception Error of string * int
|
||||
type regexp
|
||||
|
||||
external compile : ?anchored:bool -> ?caseless:bool -> ?dotall:bool -> ?extended:bool -> ?multiline:bool -> string -> regexp = "guestfs_int_pcre_compile_byte" "guestfs_int_pcre_compile"
|
||||
-external matches : regexp -> string -> bool = "guestfs_int_pcre_matches"
|
||||
+external matches : ?offset:int -> regexp -> string -> bool = "guestfs_int_pcre_matches"
|
||||
external sub : int -> string = "guestfs_int_pcre_sub"
|
||||
external subi : int -> int * int = "guestfs_int_pcre_subi"
|
||||
|
||||
diff --git a/common/mlpcre/PCRE.mli b/common/mlpcre/PCRE.mli
|
||||
index eacb6fd90..e10d512fc 100644
|
||||
--- a/common/mlpcre/PCRE.mli
|
||||
+++ b/common/mlpcre/PCRE.mli
|
||||
@@ -62,7 +62,7 @@ val compile : ?anchored:bool -> ?caseless:bool -> ?dotall:bool -> ?extended:bool
|
||||
See pcreapi(3) for details of what they do.
|
||||
All flags default to false. *)
|
||||
|
||||
-val matches : regexp -> string -> bool
|
||||
+val matches : ?offset:int -> regexp -> string -> bool
|
||||
(** Test whether the regular expression matches the string. This
|
||||
returns true if the regexp matches or false otherwise.
|
||||
|
||||
@@ -71,6 +71,9 @@ val matches : regexp -> string -> bool
|
||||
or the thread/program exits. You can call {!sub} to return
|
||||
these substrings.
|
||||
|
||||
+ The [?offset] flag is used to change the start of the search,
|
||||
+ which by default is at the beginning of the string (position 0).
|
||||
+
|
||||
This can raise {!Error} if PCRE returns an error. *)
|
||||
|
||||
val sub : int -> string
|
||||
diff --git a/common/mlpcre/pcre-c.c b/common/mlpcre/pcre-c.c
|
||||
index 0762a8341..be054a004 100644
|
||||
--- a/common/mlpcre/pcre-c.c
|
||||
+++ b/common/mlpcre/pcre-c.c
|
||||
@@ -121,6 +121,15 @@ is_Some_true (value v)
|
||||
Bool_val (Field (v, 0)) /* Some true */;
|
||||
}
|
||||
|
||||
+static int
|
||||
+Optint_val (value intv, int defval)
|
||||
+{
|
||||
+ if (intv == Val_int (0)) /* None */
|
||||
+ return defval;
|
||||
+ else /* Some int */
|
||||
+ return Int_val (Field (intv, 0));
|
||||
+}
|
||||
+
|
||||
value
|
||||
guestfs_int_pcre_compile (value anchoredv, value caselessv, value dotallv,
|
||||
value extendedv, value multilinev,
|
||||
@@ -165,9 +174,9 @@ guestfs_int_pcre_compile_byte (value *argv, int argn)
|
||||
}
|
||||
|
||||
value
|
||||
-guestfs_int_pcre_matches (value rev, value strv)
|
||||
+guestfs_int_pcre_matches (value offsetv, value rev, value strv)
|
||||
{
|
||||
- CAMLparam2 (rev, strv);
|
||||
+ CAMLparam3 (offsetv, rev, strv);
|
||||
pcre *re = Regexp_val (rev);
|
||||
struct last_match *m, *oldm;
|
||||
size_t len = caml_string_length (strv);
|
||||
@@ -205,7 +214,8 @@ guestfs_int_pcre_matches (value rev, value strv)
|
||||
caml_raise_out_of_memory ();
|
||||
}
|
||||
|
||||
- m->r = pcre_exec (re, NULL, m->subject, len, 0, 0, m->vec, veclen);
|
||||
+ m->r = pcre_exec (re, NULL, m->subject, len, Optint_val (offsetv, 0), 0,
|
||||
+ m->vec, veclen);
|
||||
if (m->r < 0 && m->r != PCRE_ERROR_NOMATCH) {
|
||||
int ret = m->r;
|
||||
free_last_match (m);
|
||||
diff --git a/common/mlpcre/pcre_tests.ml b/common/mlpcre/pcre_tests.ml
|
||||
index 346019c40..3e5981107 100644
|
||||
--- a/common/mlpcre/pcre_tests.ml
|
||||
+++ b/common/mlpcre/pcre_tests.ml
|
||||
@@ -30,9 +30,9 @@ let compile ?(anchored = false) ?(caseless = false)
|
||||
patt;
|
||||
PCRE.compile ~anchored ~caseless ~dotall ~extended ~multiline patt
|
||||
|
||||
-let matches re str =
|
||||
- eprintf "PCRE.matches %s ->%!" str;
|
||||
- let r = PCRE.matches re str in
|
||||
+let matches ?(offset = 0) re str =
|
||||
+ eprintf "PCRE.matches %s, %d ->%!" str offset;
|
||||
+ let r = PCRE.matches ~offset re str in
|
||||
eprintf " %b\n%!" r;
|
||||
r
|
||||
|
||||
@@ -103,6 +103,11 @@ let () =
|
||||
assert (subi 1 = (2, 3));
|
||||
assert (subi 2 = (3, 3));
|
||||
|
||||
+ assert (matches ~offset:5 re0 "aaabcabc" = true);
|
||||
+ assert (sub 0 = "ab");
|
||||
+
|
||||
+ assert (matches ~offset:5 re0 "aaabcbaac" = false);
|
||||
+
|
||||
assert (replace re0 "dd" "abcabcaabccca" = "ddcabcaabccca");
|
||||
assert (replace ~global:true re0 "dd" "abcabcaabccca" = "ddcddcddccca");
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
@ -1,31 +0,0 @@
|
||||
From 898e6c1e39deb130566220a11a2eaf2dcb2cb733 Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Thu, 29 Mar 2018 20:18:34 +0100
|
||||
Subject: [PATCH] qemu: Fix transcription error in conversion of yajl to
|
||||
jansson.
|
||||
|
||||
This broke qemu mandatory locking detection.
|
||||
|
||||
Fixes commit bd1c5c9f4dcf38458099db8a0bf4659a07ef055d.
|
||||
|
||||
(cherry picked from commit e79286f71738d9385157d9e87211be02645722c3)
|
||||
---
|
||||
lib/qemu.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/qemu.c b/lib/qemu.c
|
||||
index a50eca988..3e7f15946 100644
|
||||
--- a/lib/qemu.c
|
||||
+++ b/lib/qemu.c
|
||||
@@ -616,7 +616,7 @@ guestfs_int_qemu_mandatory_locking (guestfs_h *g,
|
||||
members = json_object_get (v, "members");
|
||||
if (json_is_array (members)) {
|
||||
json_array_foreach (members, j, m) {
|
||||
- name = json_object_get (v, "name");
|
||||
+ name = json_object_get (m, "name");
|
||||
if (json_is_string (name) &&
|
||||
STREQ (json_string_value (name), "locking"))
|
||||
return 1;
|
||||
--
|
||||
2.21.0
|
||||
|
415
SOURCES/0002-v2v-add-Var_expander.patch
Normal file
415
SOURCES/0002-v2v-add-Var_expander.patch
Normal file
@ -0,0 +1,415 @@
|
||||
From a98136d6ee36df15a226f853d47bd803a7a25329 Mon Sep 17 00:00:00 2001
|
||||
From: Pino Toscano <ptoscano@redhat.com>
|
||||
Date: Tue, 19 Feb 2019 14:54:31 +0100
|
||||
Subject: [PATCH] v2v: add Var_expander
|
||||
|
||||
This helper module provides a facility to replace %{FOO}-like variables
|
||||
in text strings with user-provided content.
|
||||
|
||||
(cherry picked from commit a27748d7000f417c16045967497208d275a09ce8)
|
||||
---
|
||||
.gitignore | 1 +
|
||||
v2v/Makefile.am | 32 ++++++++++-
|
||||
v2v/dummy.c | 2 +
|
||||
v2v/var_expander.ml | 72 ++++++++++++++++++++++++
|
||||
v2v/var_expander.mli | 82 +++++++++++++++++++++++++++
|
||||
v2v/var_expander_tests.ml | 113 ++++++++++++++++++++++++++++++++++++++
|
||||
6 files changed, 300 insertions(+), 2 deletions(-)
|
||||
create mode 100644 v2v/dummy.c
|
||||
create mode 100644 v2v/var_expander.ml
|
||||
create mode 100644 v2v/var_expander.mli
|
||||
create mode 100644 v2v/var_expander_tests.ml
|
||||
|
||||
diff --git a/.gitignore b/.gitignore
|
||||
index 637bf7765..f2efcdde2 100644
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -693,6 +693,7 @@ Makefile.in
|
||||
/v2v/uefi.ml
|
||||
/v2v/uefi.mli
|
||||
/v2v/v2v_unit_tests
|
||||
+/v2v/var_expander_tests
|
||||
/v2v/virt-v2v
|
||||
/v2v/virt-v2v.1
|
||||
/v2v/virt-v2v-copy-to-local
|
||||
diff --git a/v2v/Makefile.am b/v2v/Makefile.am
|
||||
index 2312812fb..f196be81d 100644
|
||||
--- a/v2v/Makefile.am
|
||||
+++ b/v2v/Makefile.am
|
||||
@@ -98,6 +98,7 @@ SOURCES_MLI = \
|
||||
utils.mli \
|
||||
v2v.mli \
|
||||
vCenter.mli \
|
||||
+ var_expander.mli \
|
||||
windows.mli \
|
||||
windows_virtio.mli
|
||||
|
||||
@@ -106,6 +107,7 @@ SOURCES_ML = \
|
||||
types.ml \
|
||||
uefi.ml \
|
||||
utils.ml \
|
||||
+ var_expander.ml \
|
||||
python_script.ml \
|
||||
name_from_disk.ml \
|
||||
vCenter.ml \
|
||||
@@ -442,7 +444,7 @@ TESTS += \
|
||||
endif
|
||||
|
||||
if HAVE_OCAML_PKG_OUNIT
|
||||
-TESTS += v2v_unit_tests
|
||||
+TESTS += v2v_unit_tests var_expander_tests
|
||||
endif
|
||||
|
||||
if ENABLE_APPLIANCE
|
||||
@@ -651,7 +653,7 @@ EXTRA_DIST += \
|
||||
# Unit tests.
|
||||
check_PROGRAMS =
|
||||
if HAVE_OCAML_PKG_OUNIT
|
||||
-check_PROGRAMS += v2v_unit_tests
|
||||
+check_PROGRAMS += v2v_unit_tests var_expander_tests
|
||||
endif
|
||||
|
||||
v2v_unit_tests_BOBJECTS = \
|
||||
@@ -671,13 +673,28 @@ v2v_unit_tests_SOURCES = $(virt_v2v_SOURCES)
|
||||
v2v_unit_tests_CPPFLAGS = $(virt_v2v_CPPFLAGS)
|
||||
v2v_unit_tests_CFLAGS = $(virt_v2v_CFLAGS)
|
||||
|
||||
+var_expander_tests_BOBJECTS = \
|
||||
+ var_expander.cmo \
|
||||
+ var_expander_tests.cmo
|
||||
+var_expander_tests_XOBJECTS = $(var_expander_tests_BOBJECTS:.cmo=.cmx)
|
||||
+
|
||||
+var_expander_tests_SOURCES = dummy.c
|
||||
+var_expander_tests_CPPFLAGS = $(virt_v2v_CPPFLAGS)
|
||||
+var_expander_tests_CFLAGS = $(virt_v2v_CFLAGS)
|
||||
+
|
||||
if !HAVE_OCAMLOPT
|
||||
# Can't call this v2v_unit_tests_OBJECTS because automake gets confused.
|
||||
v2v_unit_tests_THEOBJECTS = $(v2v_unit_tests_BOBJECTS)
|
||||
v2v_unit_tests.cmo: OCAMLPACKAGES += -package oUnit
|
||||
+
|
||||
+var_expander_tests_THEOBJECTS = $(var_expander_tests_BOBJECTS)
|
||||
+var_expander_tests.cmo: OCAMLPACKAGES += -package oUnit
|
||||
else
|
||||
v2v_unit_tests_THEOBJECTS = $(v2v_unit_tests_XOBJECTS)
|
||||
v2v_unit_tests.cmx: OCAMLPACKAGES += -package oUnit
|
||||
+
|
||||
+var_expander_tests_THEOBJECTS = $(var_expander_tests_XOBJECTS)
|
||||
+var_expander_tests.cmx: OCAMLPACKAGES += -package oUnit
|
||||
endif
|
||||
|
||||
v2v_unit_tests_DEPENDENCIES = \
|
||||
@@ -696,6 +713,17 @@ v2v_unit_tests_LINK = \
|
||||
$(OCAMLLINKFLAGS) \
|
||||
$(v2v_unit_tests_THEOBJECTS) -o $@
|
||||
|
||||
+var_expander_tests_DEPENDENCIES = \
|
||||
+ $(var_expander_tests_THEOBJECTS) \
|
||||
+ ../common/mlpcre/mlpcre.$(MLARCHIVE) \
|
||||
+ $(top_srcdir)/ocaml-link.sh
|
||||
+var_expander_tests_LINK = \
|
||||
+ $(top_srcdir)/ocaml-link.sh -cclib '$(OCAMLCLIBS)' -- \
|
||||
+ $(OCAMLFIND) $(BEST) $(OCAMLFLAGS) \
|
||||
+ $(OCAMLPACKAGES) -package oUnit \
|
||||
+ $(OCAMLLINKFLAGS) \
|
||||
+ $(var_expander_tests_THEOBJECTS) -o $@
|
||||
+
|
||||
# Dependencies.
|
||||
.depend: \
|
||||
$(srcdir)/*.mli \
|
||||
diff --git a/v2v/dummy.c b/v2v/dummy.c
|
||||
new file mode 100644
|
||||
index 000000000..ebab6198c
|
||||
--- /dev/null
|
||||
+++ b/v2v/dummy.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+/* Dummy source, to be used for OCaml-based tools with no C sources. */
|
||||
+enum { foo = 1 };
|
||||
diff --git a/v2v/var_expander.ml b/v2v/var_expander.ml
|
||||
new file mode 100644
|
||||
index 000000000..24b9bafe3
|
||||
--- /dev/null
|
||||
+++ b/v2v/var_expander.ml
|
||||
@@ -0,0 +1,72 @@
|
||||
+(* virt-v2v
|
||||
+ * Copyright (C) 2019 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.
|
||||
+ *)
|
||||
+
|
||||
+open Std_utils
|
||||
+
|
||||
+exception Invalid_variable of string
|
||||
+
|
||||
+let var_re = PCRE.compile "(^|[^%])%{([^}]+)}"
|
||||
+
|
||||
+let check_variable var =
|
||||
+ String.iter (
|
||||
+ function
|
||||
+ | '0'..'9'
|
||||
+ | 'a'..'z'
|
||||
+ | 'A'..'Z'
|
||||
+ | '_'
|
||||
+ | '-' -> ()
|
||||
+ | _ -> raise (Invalid_variable var)
|
||||
+ ) var
|
||||
+
|
||||
+let scan_variables str =
|
||||
+ let res = ref [] in
|
||||
+ let offset = ref 0 in
|
||||
+ while PCRE.matches ~offset:!offset var_re str; do
|
||||
+ let var = PCRE.sub 2 in
|
||||
+ check_variable var;
|
||||
+ let _, end_ = PCRE.subi 0 in
|
||||
+ List.push_back res var;
|
||||
+ offset := end_
|
||||
+ done;
|
||||
+ List.remove_duplicates !res
|
||||
+
|
||||
+let replace_fn str fn =
|
||||
+ let res = ref str in
|
||||
+ let offset = ref 0 in
|
||||
+ while PCRE.matches ~offset:!offset var_re !res; do
|
||||
+ let var = PCRE.sub 2 in
|
||||
+ check_variable var;
|
||||
+ let start_, end_ = PCRE.subi 0 in
|
||||
+ match fn var with
|
||||
+ | None ->
|
||||
+ offset := end_
|
||||
+ | Some text ->
|
||||
+ let prefix_len =
|
||||
+ let prefix_start, prefix_end = PCRE.subi 1 in
|
||||
+ prefix_end - prefix_start in
|
||||
+ res := (String.sub !res 0 (start_ + prefix_len)) ^ text ^ (String.sub !res end_ (String.length !res - end_));
|
||||
+ offset := start_ + prefix_len + String.length text
|
||||
+ done;
|
||||
+ !res
|
||||
+
|
||||
+let replace_list str lst =
|
||||
+ let fn var =
|
||||
+ try Some (List.assoc var lst)
|
||||
+ with Not_found -> None
|
||||
+ in
|
||||
+ replace_fn str fn
|
||||
diff --git a/v2v/var_expander.mli b/v2v/var_expander.mli
|
||||
new file mode 100644
|
||||
index 000000000..80aa33c2c
|
||||
--- /dev/null
|
||||
+++ b/v2v/var_expander.mli
|
||||
@@ -0,0 +1,82 @@
|
||||
+(* virt-v2v
|
||||
+ * Copyright (C) 2019 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.
|
||||
+ *)
|
||||
+
|
||||
+(** Simple variable expander.
|
||||
+
|
||||
+ This module provides the support to expand variables in strings,
|
||||
+ specified in the form of [%{name}].
|
||||
+
|
||||
+ For example:
|
||||
+
|
||||
+{v
|
||||
+let str = "variable-%{INDEX} in %{INDEX} replaced %{INDEX} times"
|
||||
+let index = ref 0
|
||||
+let fn = function
|
||||
+ | "INDEX" ->
|
||||
+ incr index;
|
||||
+ Some (string_of_int !index)
|
||||
+ | _ -> None
|
||||
+in
|
||||
+let str = Var_expander.replace_fn str fn
|
||||
+(* now str is "variable-1 in 2 replaced 3 times" *)
|
||||
+v}
|
||||
+
|
||||
+ The names of variables can contain only ASCII letters (uppercase,
|
||||
+ and lowercase), digits, underscores, and dashes.
|
||||
+
|
||||
+ The replacement is done in a single pass: this means that if a
|
||||
+ variable is replaced with the text of a variable, that new text
|
||||
+ is kept as is in the final output. In practice:
|
||||
+
|
||||
+{v
|
||||
+let str = "%{VAR}"
|
||||
+let str = Var_expander.replace_list str [("VAR", "%{VAR}")]
|
||||
+(* now str is "%{VAR}" *)
|
||||
+v}
|
||||
+*)
|
||||
+
|
||||
+exception Invalid_variable of string
|
||||
+(** Invalid variable name error.
|
||||
+
|
||||
+ In case a variable contains characters not allowed, then this
|
||||
+ exception with the actual unacceptable variable. *)
|
||||
+
|
||||
+val scan_variables : string -> string list
|
||||
+(** Scan the pattern string for all the variables available.
|
||||
+
|
||||
+ This can raise {!Invalid_variable} in case there are invalid
|
||||
+ variable names. *)
|
||||
+
|
||||
+val replace_fn : string -> (string -> string option) -> string
|
||||
+(** Replaces a string expanding all the variables.
|
||||
+
|
||||
+ The replacement function specify how a variable is replaced;
|
||||
+ if [None] is returned, then that variable is not replaced.
|
||||
+
|
||||
+ This can raise {!Invalid_variable} in case there are invalid
|
||||
+ variable names. *)
|
||||
+
|
||||
+val replace_list : string -> (string * string) list -> string
|
||||
+(** Replaces a string expanding all the variables.
|
||||
+
|
||||
+ The replacement list specify how a variable is replaced;
|
||||
+ if it is not specified in the list, then that variable is not
|
||||
+ replaced.
|
||||
+
|
||||
+ This can raise {!Invalid_variable} in case there are invalid
|
||||
+ variable names. *)
|
||||
diff --git a/v2v/var_expander_tests.ml b/v2v/var_expander_tests.ml
|
||||
new file mode 100644
|
||||
index 000000000..35b628369
|
||||
--- /dev/null
|
||||
+++ b/v2v/var_expander_tests.ml
|
||||
@@ -0,0 +1,113 @@
|
||||
+(* virt-v2v
|
||||
+ * Copyright (C) 2019 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.
|
||||
+ *)
|
||||
+
|
||||
+open Printf
|
||||
+open OUnit
|
||||
+
|
||||
+open Std_utils
|
||||
+
|
||||
+let assert_equal_string = assert_equal ~printer:identity
|
||||
+let assert_equal_stringlist = assert_equal ~printer:(fun x -> "(" ^ (String.escaped (String.concat "," x)) ^ ")")
|
||||
+
|
||||
+let replace_none_fn _ = None
|
||||
+let replace_empty_fn _ = Some ""
|
||||
+
|
||||
+let test_no_replacement () =
|
||||
+ assert_equal_string "" (Var_expander.replace_fn "" replace_none_fn);
|
||||
+ assert_equal_string "x" (Var_expander.replace_fn "x" replace_none_fn);
|
||||
+ assert_equal_string "%{}" (Var_expander.replace_fn "%{}" replace_none_fn);
|
||||
+ assert_equal_string "%{EMPTY}" (Var_expander.replace_fn "%{EMPTY}" replace_none_fn);
|
||||
+ assert_equal_string "%{EMPTY} %{no}" (Var_expander.replace_fn "%{EMPTY} %{no}" replace_none_fn);
|
||||
+ assert_equal_string "a %{EMPTY} b" (Var_expander.replace_fn "a %{EMPTY} b" replace_none_fn);
|
||||
+ ()
|
||||
+
|
||||
+let test_replacements () =
|
||||
+ assert_equal_string "" (Var_expander.replace_fn "%{EMPTY}" replace_empty_fn);
|
||||
+ assert_equal_string "x " (Var_expander.replace_fn "x %{EMPTY}" replace_empty_fn);
|
||||
+ assert_equal_string "xy" (Var_expander.replace_fn "x%{EMPTY}y" replace_empty_fn);
|
||||
+ assert_equal_string "x<->y" (Var_expander.replace_fn "x%{FOO}y" (function | "FOO" -> Some "<->" | _ -> None));
|
||||
+ assert_equal_string "a x b" (Var_expander.replace_fn "a %{FOO} b" (function | "FOO" -> Some "x" | _ -> None));
|
||||
+ assert_equal_string "%{FOO} x" (Var_expander.replace_fn "%{FOO} %{BAR}" (function | "BAR" -> Some "x" | _ -> None));
|
||||
+ assert_equal_string "%{FOO}" (Var_expander.replace_fn "%{BAR}" (function | "BAR" -> Some "%{FOO}" | _ -> None));
|
||||
+ assert_equal_string "%{FOO} x" (Var_expander.replace_fn "%{BAR} %{FOO}" (function | "BAR" -> Some "%{FOO}" | "FOO" -> Some "x" | _ -> None));
|
||||
+ begin
|
||||
+ let str = "%{INDEX}, %{INDEX}, %{INDEX}" in
|
||||
+ let index = ref 0 in
|
||||
+ let fn = function
|
||||
+ | "INDEX" ->
|
||||
+ incr index;
|
||||
+ Some (string_of_int !index)
|
||||
+ | _ -> None
|
||||
+ in
|
||||
+ assert_equal_string "1, 2, 3" (Var_expander.replace_fn str fn)
|
||||
+ end;
|
||||
+ ()
|
||||
+
|
||||
+let test_escape () =
|
||||
+ assert_equal_string "%%{FOO}" (Var_expander.replace_fn "%%{FOO}" replace_empty_fn);
|
||||
+ assert_equal_string "x %%{FOO} x" (Var_expander.replace_fn "%{FOO} %%{FOO} %{FOO}" (function | "FOO" -> Some "x" | _ -> None));
|
||||
+ ()
|
||||
+
|
||||
+let test_list () =
|
||||
+ assert_equal_string "x %{NONE}" (Var_expander.replace_list "%{FOO} %{NONE}" [("FOO", "x")]);
|
||||
+ ()
|
||||
+
|
||||
+let test_scan_variables () =
|
||||
+ let assert_invalid_variable var =
|
||||
+ let str = "%{" ^ var ^ "}" in
|
||||
+ assert_raises (Var_expander.Invalid_variable var)
|
||||
+ (fun () -> Var_expander.scan_variables str)
|
||||
+ in
|
||||
+ assert_equal_stringlist [] (Var_expander.scan_variables "");
|
||||
+ assert_equal_stringlist [] (Var_expander.scan_variables "foo");
|
||||
+ assert_equal_stringlist ["FOO"] (Var_expander.scan_variables "%{FOO}");
|
||||
+ assert_equal_stringlist ["FOO"; "BAR"] (Var_expander.scan_variables "%{FOO} %{BAR}");
|
||||
+ assert_equal_stringlist ["FOO"; "BAR"] (Var_expander.scan_variables "%{FOO} %{BAR} %{FOO}");
|
||||
+ assert_equal_stringlist ["FOO"; "BAR"] (Var_expander.scan_variables "%{FOO} %%{ESCAPED} %{BAR}");
|
||||
+ assert_invalid_variable "FOO/BAR";
|
||||
+ ()
|
||||
+
|
||||
+let test_errors () =
|
||||
+ let assert_invalid_variable var =
|
||||
+ let str = "%{" ^ var ^ "}" in
|
||||
+ assert_raises (Var_expander.Invalid_variable var)
|
||||
+ (fun () -> Var_expander.replace_fn str replace_none_fn)
|
||||
+ in
|
||||
+ assert_invalid_variable "FOO/BAR";
|
||||
+ assert_invalid_variable "FOO:BAR";
|
||||
+ assert_invalid_variable "FOO(BAR";
|
||||
+ assert_invalid_variable "FOO)BAR";
|
||||
+ assert_invalid_variable "FOO@BAR";
|
||||
+ ()
|
||||
+
|
||||
+(* Suites declaration. *)
|
||||
+let suite =
|
||||
+ TestList ([
|
||||
+ "basic" >::: [
|
||||
+ "no_replacement" >:: test_no_replacement;
|
||||
+ "replacements" >:: test_replacements;
|
||||
+ "escape" >:: test_escape;
|
||||
+ "list" >:: test_list;
|
||||
+ "scan_variables" >:: test_scan_variables;
|
||||
+ "errors" >:: test_errors;
|
||||
+ ];
|
||||
+ ])
|
||||
+
|
||||
+let () =
|
||||
+ ignore (run_test_tt_main suite);
|
||||
+ Printf.fprintf stderr "\n"
|
||||
--
|
||||
2.26.2
|
||||
|
785
SOURCES/0003-v2v-add-o-json-output-mode.patch
Normal file
785
SOURCES/0003-v2v-add-o-json-output-mode.patch
Normal file
@ -0,0 +1,785 @@
|
||||
From 480c7169c341fc2f86609a13100c42e10f599b83 Mon Sep 17 00:00:00 2001
|
||||
From: Pino Toscano <ptoscano@redhat.com>
|
||||
Date: Mon, 25 Feb 2019 13:14:43 +0100
|
||||
Subject: [PATCH] v2v: add -o json output mode
|
||||
|
||||
Add a new output mode to virt-v2v: similar to -o local, the written
|
||||
metadata is a JSON file with the majority of the data that virt-v2v
|
||||
knowns about (or collects) during the conversion.
|
||||
|
||||
This is meant to be used only when no existing output mode is usable,
|
||||
and a guest needs to be converted to run on KVM anyway. The user of
|
||||
this mode is supposed to use all the data in the JSON, as they contain
|
||||
important details on how even run the guest (e.g. w.r.t. firmware,
|
||||
drivers of disks/NICs, etc).
|
||||
|
||||
(cherry picked from commit f190e08d85556dac293ef15bfeee38e54471570f)
|
||||
---
|
||||
v2v/Makefile.am | 4 +
|
||||
v2v/cmdline.ml | 29 +++
|
||||
v2v/create_json.ml | 348 ++++++++++++++++++++++++++++++++++
|
||||
v2v/create_json.mli | 29 +++
|
||||
v2v/output_json.ml | 116 ++++++++++++
|
||||
v2v/output_json.mli | 31 +++
|
||||
v2v/virt-v2v-output-local.pod | 55 ++++++
|
||||
v2v/virt-v2v.pod | 15 +-
|
||||
8 files changed, 625 insertions(+), 2 deletions(-)
|
||||
create mode 100644 v2v/create_json.ml
|
||||
create mode 100644 v2v/create_json.mli
|
||||
create mode 100644 v2v/output_json.ml
|
||||
create mode 100644 v2v/output_json.mli
|
||||
|
||||
diff --git a/v2v/Makefile.am b/v2v/Makefile.am
|
||||
index f196be81d..53c137fc6 100644
|
||||
--- a/v2v/Makefile.am
|
||||
+++ b/v2v/Makefile.am
|
||||
@@ -52,6 +52,7 @@ SOURCES_MLI = \
|
||||
config.mli \
|
||||
convert_linux.mli \
|
||||
convert_windows.mli \
|
||||
+ create_json.mli \
|
||||
create_libvirt_xml.mli \
|
||||
create_ovf.mli \
|
||||
DOM.mli \
|
||||
@@ -75,6 +76,7 @@ SOURCES_MLI = \
|
||||
networks.mli \
|
||||
openstack_image_properties.mli \
|
||||
output_glance.mli \
|
||||
+ output_json.mli \
|
||||
output_libvirt.mli \
|
||||
output_local.mli \
|
||||
output_null.mli \
|
||||
@@ -117,6 +119,7 @@ SOURCES_ML = \
|
||||
parse_ovf_from_ova.ml \
|
||||
parse_ova.ml \
|
||||
create_ovf.ml \
|
||||
+ create_json.ml \
|
||||
linux.ml \
|
||||
windows.ml \
|
||||
windows_virtio.ml \
|
||||
@@ -141,6 +144,7 @@ SOURCES_ML = \
|
||||
convert_windows.ml \
|
||||
output_null.ml \
|
||||
output_glance.ml \
|
||||
+ output_json.ml \
|
||||
output_libvirt.ml \
|
||||
output_local.ml \
|
||||
output_qemu.ml \
|
||||
diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml
|
||||
index 46f6910d0..4d390f249 100644
|
||||
--- a/v2v/cmdline.ml
|
||||
+++ b/v2v/cmdline.ml
|
||||
@@ -138,6 +138,7 @@ let parse_cmdline () =
|
||||
| "glance" -> output_mode := `Glance
|
||||
| "libvirt" -> output_mode := `Libvirt
|
||||
| "disk" | "local" -> output_mode := `Local
|
||||
+ | "json" -> output_mode := `JSON
|
||||
| "null" -> output_mode := `Null
|
||||
| "openstack" | "osp" | "rhosp" -> output_mode := `Openstack
|
||||
| "ovirt" | "rhv" | "rhev" -> output_mode := `RHV
|
||||
@@ -413,6 +414,17 @@ read the man page virt-v2v(1).
|
||||
| `RHV -> no_options (); `RHV
|
||||
| `QEmu -> no_options (); `QEmu
|
||||
|
||||
+ | `JSON ->
|
||||
+ if is_query then (
|
||||
+ Output_json.print_output_options ();
|
||||
+ exit 0
|
||||
+ )
|
||||
+ else (
|
||||
+ let json_options =
|
||||
+ Output_json.parse_output_options output_options in
|
||||
+ `JSON json_options
|
||||
+ )
|
||||
+
|
||||
| `Openstack ->
|
||||
if is_query then (
|
||||
Output_openstack.print_output_options ();
|
||||
@@ -546,6 +558,23 @@ read the man page virt-v2v(1).
|
||||
Output_libvirt.output_libvirt output_conn output_storage,
|
||||
output_format, output_alloc
|
||||
|
||||
+ | `JSON json_options ->
|
||||
+ if output_password <> None then
|
||||
+ error_option_cannot_be_used_in_output_mode "json" "-op";
|
||||
+ if output_conn <> None then
|
||||
+ error_option_cannot_be_used_in_output_mode "json" "-oc";
|
||||
+ let os =
|
||||
+ match output_storage with
|
||||
+ | None ->
|
||||
+ error (f_"-o json: output directory was not specified, use '-os /dir'")
|
||||
+ | Some d when not (is_directory d) ->
|
||||
+ error (f_"-os %s: output directory does not exist or is not a directory") d
|
||||
+ | Some d -> d in
|
||||
+ if qemu_boot then
|
||||
+ error_option_cannot_be_used_in_output_mode "json" "--qemu-boot";
|
||||
+ Output_json.output_json os json_options,
|
||||
+ output_format, output_alloc
|
||||
+
|
||||
| `Local ->
|
||||
if output_password <> None then
|
||||
error_option_cannot_be_used_in_output_mode "local" "-op";
|
||||
diff --git a/v2v/create_json.ml b/v2v/create_json.ml
|
||||
new file mode 100644
|
||||
index 000000000..fdf7b12f5
|
||||
--- /dev/null
|
||||
+++ b/v2v/create_json.ml
|
||||
@@ -0,0 +1,348 @@
|
||||
+(* virt-v2v
|
||||
+ * Copyright (C) 2019 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.
|
||||
+ *)
|
||||
+
|
||||
+open Std_utils
|
||||
+open C_utils
|
||||
+open Tools_utils
|
||||
+
|
||||
+open Types
|
||||
+open Utils
|
||||
+
|
||||
+module G = Guestfs
|
||||
+
|
||||
+let json_list_of_string_list =
|
||||
+ List.map (fun x -> JSON.String x)
|
||||
+
|
||||
+let json_list_of_string_string_list =
|
||||
+ List.map (fun (x, y) -> x, JSON.String y)
|
||||
+
|
||||
+let push_optional_string lst name = function
|
||||
+ | None -> ()
|
||||
+ | Some v -> List.push_back lst (name, JSON.String v)
|
||||
+
|
||||
+let push_optional_int lst name = function
|
||||
+ | None -> ()
|
||||
+ | Some v -> List.push_back lst (name, JSON.Int (Int64.of_int v))
|
||||
+
|
||||
+let json_unknown_string = function
|
||||
+ | "unknown" -> JSON.Null
|
||||
+ | v -> JSON.String v
|
||||
+
|
||||
+let find_target_disk targets { s_disk_id = id } =
|
||||