From 54bf19a2a31371e944bbbf310091dd0a958b363c Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 30 Oct 2024 12:24:16 +0000 Subject: [PATCH] Replace Jansson with json-c resolves: RHEL-65294 --- 0004-build-Add-new-dependency-on-json-c.patch | 33 +++ ...-builder-Replace-jansson-with-json-c.patch | 267 ++++++++++++++++++ 0006-build-Remove-Jansson-dependency.patch | 27 ++ guestfs-tools.spec | 9 +- 4 files changed, 334 insertions(+), 2 deletions(-) create mode 100644 0004-build-Add-new-dependency-on-json-c.patch create mode 100644 0005-builder-Replace-jansson-with-json-c.patch create mode 100644 0006-build-Remove-Jansson-dependency.patch diff --git a/0004-build-Add-new-dependency-on-json-c.patch b/0004-build-Add-new-dependency-on-json-c.patch new file mode 100644 index 0000000..74b65ce --- /dev/null +++ b/0004-build-Add-new-dependency-on-json-c.patch @@ -0,0 +1,33 @@ +From 9cdb27fb0fde8b2eb57453480c4fed4746414aeb Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 22 Oct 2024 11:01:25 +0100 +Subject: [PATCH] build: Add new dependency on json-c + +This will eventually replace Jansson for all JSON parsing. However +this commit simply introduces the new dependency in the configure +script and documents it. + +I chose json-c 0.14 as the baseline since that is the version in RHEL 9. +Probably earlier versions would work. + +(cherry picked from libguestfs commit 53872a0a1a267040677572c30b68bd1e8b62ebe3) + +(cherry picked from commit 0d7fe8a0b0b429152ea02fc7a7e4f5a1b0eba590) +--- + m4/guestfs-libraries.m4 | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/m4/guestfs-libraries.m4 b/m4/guestfs-libraries.m4 +index 32f93afda..b76511982 100644 +--- a/m4/guestfs-libraries.m4 ++++ b/m4/guestfs-libraries.m4 +@@ -167,6 +167,9 @@ LIBS="$old_LIBS" + dnl Check for Jansson JSON library (required). + PKG_CHECK_MODULES([JANSSON], [jansson >= 2.7]) + ++dnl Check for JSON-C library (required). ++PKG_CHECK_MODULES([JSON_C], [json-c >= 0.14]) ++ + dnl Check for libosinfo (mandatory) + PKG_CHECK_MODULES([LIBOSINFO], [libosinfo-1.0]) + diff --git a/0005-builder-Replace-jansson-with-json-c.patch b/0005-builder-Replace-jansson-with-json-c.patch new file mode 100644 index 0000000..32e2e53 --- /dev/null +++ b/0005-builder-Replace-jansson-with-json-c.patch @@ -0,0 +1,267 @@ +From 02a911960b5916df93bf896afc94c8d250797f17 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 22 Oct 2024 11:07:01 +0100 +Subject: [PATCH] builder: Replace jansson with json-c + +This pulls in the following common module commit which ports the +JSON_parser module from jansson to json-c: + + Richard W.M. Jones (1): + mltools: Replace jansson with json-c + +(cherry picked from commit 12997768d231b80dc219a518c287ecf10c83ff0e) +--- + builder/Makefile.am | 2 +- + common | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/builder/Makefile.am b/builder/Makefile.am +index b474f0c9d..0761eff4c 100644 +--- a/builder/Makefile.am ++++ b/builder/Makefile.am +@@ -206,7 +206,7 @@ OCAMLCLIBS = \ + $(LIBLZMA_LIBS) \ + $(LIBXML2_LIBS) \ + $(LIBOSINFO_LIBS) \ +- $(JANSSON_LIBS) \ ++ $(JSON_C_LIBS) \ + $(LIBINTL) \ + -lgnu + +Submodule common a78839676..766384a45: +diff --git a/common/mltools/JSON_parser-c.c b/common/mltools/JSON_parser-c.c +index bf38dd1bf..fb67b4632 100644 +--- a/common/mltools/JSON_parser-c.c ++++ b/common/mltools/JSON_parser-c.c +@@ -23,7 +23,7 @@ + #include + #include + +-#include ++#include + + #include + #include +@@ -40,7 +40,7 @@ value virt_builder_json_parser_tree_parse (value stringv); + value virt_builder_json_parser_tree_parse_file (value stringv); + + static value +-convert_json_t (json_t *val, int level) ++convert_json_t (json_object *val, int level) + { + CAMLparam0 (); + CAMLlocal5 (rv, v, tv, sv, consv); +@@ -48,9 +48,11 @@ convert_json_t (json_t *val, int level) + if (level > 20) + caml_invalid_argument ("too many levels of object/array nesting"); + +- if (json_is_object (val)) { ++ switch (json_object_get_type (val)) { ++ case json_type_object: { ++ struct json_object_iterator it, itend; + const char *key; +- json_t *jvalue; ++ json_object *jvalue; + + rv = caml_alloc (1, JSON_DICT_TAG); + v = Val_int (0); +@@ -60,29 +62,39 @@ convert_json_t (json_t *val, int level) + * matter (eg. simplestreams which incorrectly uses a dict when it + * really should use an array). + */ +- json_object_foreach (val, key, jvalue) { ++ it = json_object_iter_begin (val); ++ itend = json_object_iter_end (val); ++ while (!json_object_iter_equal (&it, &itend)) { ++ key = json_object_iter_peek_name (&it); + tv = caml_alloc_tuple (2); + sv = caml_copy_string (key); + Store_field (tv, 0, sv); ++ ++ jvalue = json_object_iter_peek_value (&it); + sv = convert_json_t (jvalue, level + 1); + Store_field (tv, 1, sv); ++ + consv = caml_alloc (2, 0); + Store_field (consv, 1, v); + Store_field (consv, 0, tv); + v = consv; ++ ++ json_object_iter_next (&it); + } + Store_field (rv, 0, v); ++ break; + } +- else if (json_is_array (val)) { +- const size_t len = json_array_size (val); ++ ++ case json_type_array: { ++ const size_t len = json_object_array_length (val); + size_t i; +- json_t *jvalue; ++ json_object *jvalue; + + rv = caml_alloc (1, JSON_LIST_TAG); + v = Val_int (0); + for (i = 0; i < len; ++i) { + /* Note we have to create the OCaml list backwards. */ +- jvalue = json_array_get (val, len-i-1); ++ jvalue = json_object_array_get_idx (val, len-i-1); + tv = convert_json_t (jvalue, level + 1); + consv = caml_alloc (2, 0); + Store_field (consv, 1, v); +@@ -90,32 +102,36 @@ convert_json_t (json_t *val, int level) + v = consv; + } + Store_field (rv, 0, v); ++ break; + } +- else if (json_is_string (val)) { ++ ++ case json_type_string: + rv = caml_alloc (1, JSON_STRING_TAG); +- v = caml_copy_string (json_string_value (val)); ++ v = caml_copy_string (json_object_get_string (val)); + Store_field (rv, 0, v); +- } +- else if (json_is_real (val)) { ++ break; ++ ++ case json_type_double: + rv = caml_alloc (1, JSON_FLOAT_TAG); +- v = caml_copy_double (json_real_value (val)); ++ v = caml_copy_double (json_object_get_double (val)); + Store_field (rv, 0, v); +- } +- else if (json_is_integer (val)) { ++ break; ++ ++ case json_type_int: + rv = caml_alloc (1, JSON_INT_TAG); +- v = caml_copy_int64 (json_integer_value (val)); ++ v = caml_copy_int64 (json_object_get_int64 (val)); + Store_field (rv, 0, v); +- } +- else if (json_is_true (val)) { ++ break; ++ ++ case json_type_boolean: + rv = caml_alloc (1, JSON_BOOL_TAG); +- Store_field (rv, 0, Val_true); +- } +- else if (json_is_false (val)) { +- rv = caml_alloc (1, JSON_BOOL_TAG); +- Store_field (rv, 0, Val_false); +- } +- else ++ Store_field (rv, 0, json_object_get_boolean (val) ? Val_true : Val_false); ++ break; ++ ++ case json_type_null: + rv = JSON_NULL; ++ break; ++ } + + CAMLreturn (rv); + } +@@ -125,45 +141,28 @@ virt_builder_json_parser_tree_parse (value stringv) + { + CAMLparam1 (stringv); + CAMLlocal1 (rv); +- json_t *tree; +- json_error_t err; ++ json_object *tree = NULL; ++ json_tokener *tok = NULL; ++ enum json_tokener_error err; + +- tree = json_loads (String_val (stringv), JSON_DECODE_ANY, &err); +- if (tree == NULL) { +- 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"); ++ tok = json_tokener_new (); ++ json_tokener_set_flags (tok, ++ JSON_TOKENER_STRICT | JSON_TOKENER_VALIDATE_UTF8); ++ tree = json_tokener_parse_ex (tok, ++ String_val (stringv), ++ caml_string_length (stringv)); ++ err = json_tokener_get_error (tok); ++ if (err != json_tokener_success) { ++ char buf[256]; ++ snprintf (buf, sizeof buf, "JSON parse error: %s", ++ json_tokener_error_desc (err)); ++ json_tokener_free (tok); + caml_invalid_argument (buf); + } ++ json_tokener_free (tok); + + rv = convert_json_t (tree, 1); +- json_decref (tree); +- +- CAMLreturn (rv); +-} +- +-value +-virt_builder_json_parser_tree_parse_file (value filev) +-{ +- CAMLparam1 (filev); +- CAMLlocal1 (rv); +- json_t *tree; +- json_error_t err; +- +- tree = json_load_file (String_val (filev), JSON_DECODE_ANY, &err); +- if (tree == NULL) { +- char buf[1024 + JSON_ERROR_TEXT_LENGTH]; +- if (strlen (err.text) > 0) +- snprintf (buf, sizeof buf, "%s: JSON parse error: %s", String_val (filev), err.text); +- else +- snprintf (buf, sizeof buf, "%s: unknown JSON parse error", String_val (filev)); +- caml_invalid_argument (buf); +- } +- +- rv = convert_json_t (tree, 1); +- json_decref (tree); ++ json_object_put (tree); + + CAMLreturn (rv); + } +diff --git a/common/mltools/JSON_parser.ml b/common/mltools/JSON_parser.ml +index 933057277..8bc35abdc 100644 +--- a/common/mltools/JSON_parser.ml ++++ b/common/mltools/JSON_parser.ml +@@ -21,7 +21,10 @@ open Tools_utils + open Common_gettext.Gettext + + external json_parser_tree_parse : string -> JSON.json_t = "virt_builder_json_parser_tree_parse" +-external json_parser_tree_parse_file : string -> JSON.json_t = "virt_builder_json_parser_tree_parse_file" ++ ++let json_parser_tree_parse_file filename = ++ let content = read_whole_file filename in ++ json_parser_tree_parse content + + let object_find_optional key = function + | JSON.Dict fields -> +diff --git a/common/mltools/Makefile.am b/common/mltools/Makefile.am +index f510a6747..684c26946 100644 +--- a/common/mltools/Makefile.am ++++ b/common/mltools/Makefile.am +@@ -116,7 +116,7 @@ libmltools_a_CFLAGS = \ + $(LIBVIRT_CFLAGS) \ + $(LIBXML2_CFLAGS) \ + $(LIBGUESTFS_CFLAGS) \ +- $(JANSSON_CFLAGS) \ ++ $(JSON_C_CFLAGS) \ + $(LIBOSINFO_CFLAGS) \ + -fPIC + +@@ -148,7 +148,7 @@ OCAMLCLIBS = \ + $(LIBCRYPT_LIBS) \ + $(LIBVIRT_LIBS) \ + $(LIBXML2_LIBS) \ +- $(JANSSON_LIBS) \ ++ $(JSON_C_LIBS) \ + $(LIBOSINFO_LIBS) \ + $(LIBINTL) \ + -lgnu diff --git a/0006-build-Remove-Jansson-dependency.patch b/0006-build-Remove-Jansson-dependency.patch new file mode 100644 index 0000000..7aea798 --- /dev/null +++ b/0006-build-Remove-Jansson-dependency.patch @@ -0,0 +1,27 @@ +From 5879249a32d50ab746f515abc2679b91f64a2098 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 22 Oct 2024 15:22:18 +0100 +Subject: [PATCH] build: Remove Jansson dependency + +After previous changes, this library is no longer used. We have +switched to json-c, for better compatibility with libvirt. + +(cherry picked from commit e6dcf7e3a7e9170978e57ce6df1b34f92fac5ae3) +--- + m4/guestfs-libraries.m4 | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/m4/guestfs-libraries.m4 b/m4/guestfs-libraries.m4 +index b76511982..80f9425f0 100644 +--- a/m4/guestfs-libraries.m4 ++++ b/m4/guestfs-libraries.m4 +@@ -164,9 +164,6 @@ LIBS="$LIBS $LIBXML2_LIBS" + AC_CHECK_FUNCS([xmlBufferDetach]) + LIBS="$old_LIBS" + +-dnl Check for Jansson JSON library (required). +-PKG_CHECK_MODULES([JANSSON], [jansson >= 2.7]) +- + dnl Check for JSON-C library (required). + PKG_CHECK_MODULES([JSON_C], [json-c >= 0.14]) + diff --git a/guestfs-tools.spec b/guestfs-tools.spec index 98f63b3..d35ad6b 100644 --- a/guestfs-tools.spec +++ b/guestfs-tools.spec @@ -51,6 +51,9 @@ Source3: copy-patches.sh Patch0001: 0001-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch Patch0002: 0002-RHEL-builder-Disable-opensuse-repository.patch Patch0003: 0003-customize-Implement-inject-blnsvr-operation.patch +Patch0004: 0004-build-Add-new-dependency-on-json-c.patch +Patch0005: 0005-builder-Replace-jansson-with-json-c.patch +Patch0006: 0006-build-Remove-Jansson-dependency.patch %if 0%{patches_touch_autotools} BuildRequires: autoconf, automake, libtool, gettext-devel @@ -69,7 +72,7 @@ BuildRequires: /usr/bin/pod2text BuildRequires: po4a BuildRequires: pcre2-devel BuildRequires: libxml2-devel -BuildRequires: jansson-devel +BuildRequires: json-c-devel BuildRequires: libvirt-devel BuildRequires: libosinfo-devel BuildRequires: libxcrypt-devel @@ -409,9 +412,11 @@ end %changelog -* Fri Oct 04 2024 Richard W.M. Jones - 1.52.2-1 +* Wed Oct 30 2024 Richard W.M. Jones - 1.52.2-2 - Rebase to guestfs-tools 1.52.2 resolves: RHEL-56811 +- Replace Jansson with json-c + resolves: RHEL-65294 * Tue Aug 27 2024 Richard W.M. Jones - 1.51.6-5 - Reboot Windows between each firstboot script to improve reliability