diff --git a/SOURCES/0004-build-Assume-__attribute__-cleanup-always-works.patch b/SOURCES/0004-build-Assume-__attribute__-cleanup-always-works.patch new file mode 100644 index 0000000..a6551ad --- /dev/null +++ b/SOURCES/0004-build-Assume-__attribute__-cleanup-always-works.patch @@ -0,0 +1,412 @@ +From e37768d8892d6f467c7834f8b142b89f8f0af7dc Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 18 Oct 2024 21:52:21 +0100 +Subject: [PATCH] build: Assume __attribute__((cleanup)) always works + +All recent compilers support this (except MS compilers which we don't +care about). Assume it is supported. We test it in ./configure and +hard fail if it doesn't work. + +We still define HAVE_ATTRIBUTE_CLEANUP but you can now assume it is +always defined and don't have to check it. +--- + common | 2 +- + daemon/daemon.h | 9 --------- + daemon/sh.c | 5 ----- + daemon/yara.c | 8 -------- + generator/c.ml | 10 ---------- + generator/daemon.ml | 15 --------------- + lib/guestfs-internal.h | 8 -------- + lib/info.c | 5 ----- + lib/launch-libvirt.c | 5 ----- + lib/qemu.c | 5 ----- + m4/guestfs-c.m4 | 7 ++----- + 11 files changed, 3 insertions(+), 76 deletions(-) + +Submodule common b6e703dcc..01c532260: +diff --git a/common/structs/structs-cleanups.h b/common/structs/structs-cleanups.h +index b43dbd7..c6e7fd1 100644 +--- a/common/structs/structs-cleanups.h ++++ b/common/structs/structs-cleanups.h +@@ -28,7 +28,6 @@ + #ifndef GUESTFS_STRUCTS_CLEANUPS_H_ + #define GUESTFS_STRUCTS_CLEANUPS_H_ + +-#ifdef HAVE_ATTRIBUTE_CLEANUP + #define CLEANUP_FREE_INT_BOOL \ + __attribute__((cleanup(guestfs_int_cleanup_free_int_bool))) + #define CLEANUP_FREE_INT_BOOL_LIST \ +@@ -137,62 +136,6 @@ + __attribute__((cleanup(guestfs_int_cleanup_free_yara_detection))) + #define CLEANUP_FREE_YARA_DETECTION_LIST \ + __attribute__((cleanup(guestfs_int_cleanup_free_yara_detection_list))) +-#else /* !HAVE_ATTRIBUTE_CLEANUP */ +-#define CLEANUP_FREE_INT_BOOL +-#define CLEANUP_FREE_INT_BOOL_LIST +-#define CLEANUP_FREE_LVM_PV +-#define CLEANUP_FREE_LVM_PV_LIST +-#define CLEANUP_FREE_LVM_VG +-#define CLEANUP_FREE_LVM_VG_LIST +-#define CLEANUP_FREE_LVM_LV +-#define CLEANUP_FREE_LVM_LV_LIST +-#define CLEANUP_FREE_STAT +-#define CLEANUP_FREE_STAT_LIST +-#define CLEANUP_FREE_STATNS +-#define CLEANUP_FREE_STATNS_LIST +-#define CLEANUP_FREE_STATVFS +-#define CLEANUP_FREE_STATVFS_LIST +-#define CLEANUP_FREE_DIRENT +-#define CLEANUP_FREE_DIRENT_LIST +-#define CLEANUP_FREE_VERSION +-#define CLEANUP_FREE_VERSION_LIST +-#define CLEANUP_FREE_XATTR +-#define CLEANUP_FREE_XATTR_LIST +-#define CLEANUP_FREE_INOTIFY_EVENT +-#define CLEANUP_FREE_INOTIFY_EVENT_LIST +-#define CLEANUP_FREE_PARTITION +-#define CLEANUP_FREE_PARTITION_LIST +-#define CLEANUP_FREE_APPLICATION +-#define CLEANUP_FREE_APPLICATION_LIST +-#define CLEANUP_FREE_APPLICATION2 +-#define CLEANUP_FREE_APPLICATION2_LIST +-#define CLEANUP_FREE_ISOINFO +-#define CLEANUP_FREE_ISOINFO_LIST +-#define CLEANUP_FREE_MDSTAT +-#define CLEANUP_FREE_MDSTAT_LIST +-#define CLEANUP_FREE_BTRFSSUBVOLUME +-#define CLEANUP_FREE_BTRFSSUBVOLUME_LIST +-#define CLEANUP_FREE_BTRFSQGROUP +-#define CLEANUP_FREE_BTRFSQGROUP_LIST +-#define CLEANUP_FREE_BTRFSBALANCE +-#define CLEANUP_FREE_BTRFSBALANCE_LIST +-#define CLEANUP_FREE_BTRFSSCRUB +-#define CLEANUP_FREE_BTRFSSCRUB_LIST +-#define CLEANUP_FREE_XFSINFO +-#define CLEANUP_FREE_XFSINFO_LIST +-#define CLEANUP_FREE_UTSNAME +-#define CLEANUP_FREE_UTSNAME_LIST +-#define CLEANUP_FREE_HIVEX_NODE +-#define CLEANUP_FREE_HIVEX_NODE_LIST +-#define CLEANUP_FREE_HIVEX_VALUE +-#define CLEANUP_FREE_HIVEX_VALUE_LIST +-#define CLEANUP_FREE_INTERNAL_MOUNTABLE +-#define CLEANUP_FREE_INTERNAL_MOUNTABLE_LIST +-#define CLEANUP_FREE_TSK_DIRENT +-#define CLEANUP_FREE_TSK_DIRENT_LIST +-#define CLEANUP_FREE_YARA_DETECTION +-#define CLEANUP_FREE_YARA_DETECTION_LIST +-#endif /* !HAVE_ATTRIBUTE_CLEANUP */ + + /* These functions are used internally by the CLEANUP_* macros. + * Don't call them directly. +diff --git a/common/utils/cleanups.h b/common/utils/cleanups.h +index 932114f..be52d07 100644 +--- a/common/utils/cleanups.h ++++ b/common/utils/cleanups.h +@@ -19,7 +19,6 @@ + #ifndef GUESTFS_CLEANUPS_H_ + #define GUESTFS_CLEANUPS_H_ + +-#ifdef HAVE_ATTRIBUTE_CLEANUP + #define CLEANUP_FREE \ + __attribute__((cleanup(guestfs_int_cleanup_free))) + #define CLEANUP_HASH_FREE \ +@@ -50,23 +49,6 @@ + __attribute__((cleanup(guestfs_int_cleanup_xmlXPathFreeObject))) + #define CLEANUP_PCRE2_MATCH_DATA_FREE \ + __attribute__((cleanup(guestfs_int_cleanup_pcre2_match_data_free))) +-#else +-#define CLEANUP_FREE +-#define CLEANUP_HASH_FREE +-#define CLEANUP_UNLINK_FREE +-#define CLEANUP_CLOSE +-#define CLEANUP_FCLOSE +-#define CLEANUP_PCLOSE +-#define CLEANUP_FREE_STRING_LIST +-#define CLEANUP_XMLFREE +-#define CLEANUP_XMLBUFFERFREE +-#define CLEANUP_XMLFREEDOC +-#define CLEANUP_XMLFREEURI +-#define CLEANUP_XMLFREETEXTWRITER +-#define CLEANUP_XMLXPATHFREECONTEXT +-#define CLEANUP_XMLXPATHFREEOBJECT +-#define CLEANUP_PCRE2_MATCH_DATA_FREE +-#endif + + /* These functions are used internally by the CLEANUP_* macros. + * Don't call them directly. +diff --git a/daemon/daemon.h b/daemon/daemon.h +index e050588ca..5fc53245c 100644 +--- a/daemon/daemon.h ++++ b/daemon/daemon.h +@@ -93,11 +93,7 @@ extern char *read_whole_file (const char *filename, size_t *size_r); + extern char *mountable_to_string (const mountable_t *mountable); + extern void cleanup_free_mountable (mountable_t *mountable); + +-#ifdef HAVE_ATTRIBUTE_CLEANUP + #define CLEANUP_FREE_MOUNTABLE __attribute__((cleanup(cleanup_free_mountable))) +-#else +-#define CLEANUP_FREE_MOUNTABLE +-#endif + + /* cleanups.c */ + /* These functions are used internally by the CLEANUP_* macros. +@@ -106,13 +102,8 @@ extern void cleanup_free_mountable (mountable_t *mountable); + extern void cleanup_aug_close (void *ptr); + extern void cleanup_free_stringsbuf (void *ptr); + +-#ifdef HAVE_ATTRIBUTE_CLEANUP + #define CLEANUP_AUG_CLOSE __attribute__((cleanup(cleanup_aug_close))) + #define CLEANUP_FREE_STRINGSBUF __attribute__((cleanup(cleanup_free_stringsbuf))) +-#else +-#define CLEANUP_AUG_CLOSE +-#define CLEANUP_FREE_STRINGSBUF +-#endif + + /* mount.c */ + extern int is_root_mounted (void); +diff --git a/daemon/sh.c b/daemon/sh.c +index 92ce08be0..21d4deeab 100644 +--- a/daemon/sh.c ++++ b/daemon/sh.c +@@ -32,13 +32,8 @@ + + #include "ignore-value.h" + +-#ifdef HAVE_ATTRIBUTE_CLEANUP + #define CLEANUP_BIND_STATE __attribute__((cleanup(free_bind_state))) + #define CLEANUP_RESOLVER_STATE __attribute__((cleanup(free_resolver_state))) +-#else +-#define CLEANUP_BIND_STATE +-#define CLEANUP_RESOLVER_STATE +-#endif + + struct bind_state { + bool mounted; +diff --git a/daemon/yara.c b/daemon/yara.c +index 21137b733..9350dd27b 100644 +--- a/daemon/yara.c ++++ b/daemon/yara.c +@@ -39,12 +39,8 @@ + + #include + +-#ifdef HAVE_ATTRIBUTE_CLEANUP + #define CLEANUP_DESTROY_YARA_COMPILER \ + __attribute__((cleanup(cleanup_destroy_yara_compiler))) +-#else +-#define CLEANUP_DESTROY_YARA_COMPILER +-#endif + + struct write_callback_data { + int fd; +@@ -208,10 +204,6 @@ compile_rules_file (const char *rules_path) + } + + err: +-#ifndef HAVE_ATTRIBUTE_CLEANUP +- yr_compiler_destroy (compiler); +-#endif +- + return ret; + } + +diff --git a/generator/c.ml b/generator/c.ml +index 447059b8a..838e7f426 100644 +--- a/generator/c.ml ++++ b/generator/c.ml +@@ -817,7 +817,6 @@ and generate_client_structs_cleanups_h () = + #ifndef GUESTFS_STRUCTS_CLEANUPS_H_ + #define GUESTFS_STRUCTS_CLEANUPS_H_ + +-#ifdef HAVE_ATTRIBUTE_CLEANUP + "; + + List.iter ( +@@ -828,16 +827,7 @@ and generate_client_structs_cleanups_h () = + pr " __attribute__((cleanup(guestfs_int_cleanup_free_%s_list)))\n" name + ) structs; + +- pr "#else /* !HAVE_ATTRIBUTE_CLEANUP */\n"; +- +- List.iter ( +- fun { s_name = name } -> +- pr "#define CLEANUP_FREE_%s\n" (String.uppercase_ascii name); +- pr "#define CLEANUP_FREE_%s_LIST\n" (String.uppercase_ascii name) +- ) structs; +- + pr "\ +-#endif /* !HAVE_ATTRIBUTE_CLEANUP */ + + /* These functions are used internally by the CLEANUP_* macros. + * Don't call them directly. +diff --git a/generator/daemon.ml b/generator/daemon.ml +index 78a2412d2..9ab9e12df 100644 +--- a/generator/daemon.ml ++++ b/generator/daemon.ml +@@ -127,8 +127,6 @@ let generate_daemon_stubs actions () = + args_passed_to_daemon in + + if args_passed_to_daemon <> [] then ( +- pr "#ifdef HAVE_ATTRIBUTE_CLEANUP\n"; +- pr "\n"; + pr "#define CLEANUP_XDR_FREE_%s_ARGS \\\n" uc_name; + pr " __attribute__((cleanup(cleanup_xdr_free_%s_args)))\n" name; + pr "\n"; +@@ -140,9 +138,6 @@ let generate_daemon_stubs actions () = + name; + pr "}\n"; + pr "\n"; +- pr "#else /* !HAVE_ATTRIBUTE_CLEANUP */\n"; +- pr "#define CLEANUP_XDR_FREE_%s_ARGS\n" uc_name; +- pr "#endif /* !HAVE_ATTRIBUTE_CLEANUP */\n"; + pr "\n" + ); + +@@ -1315,7 +1310,6 @@ let generate_daemon_structs_cleanups_h () = + #ifndef GUESTFS_DAEMON_STRUCTS_CLEANUPS_H_ + #define GUESTFS_DAEMON_STRUCTS_CLEANUPS_H_ + +-#ifdef HAVE_ATTRIBUTE_CLEANUP + "; + + List.iter ( +@@ -1326,16 +1320,7 @@ let generate_daemon_structs_cleanups_h () = + pr " __attribute__((cleanup(cleanup_free_int_%s_list)))\n" name + ) structs; + +- pr "#else /* !HAVE_ATTRIBUTE_CLEANUP */\n"; +- +- List.iter ( +- fun { s_name = name } -> +- pr "#define CLEANUP_FREE_%s\n" (String.uppercase_ascii name); +- pr "#define CLEANUP_FREE_%s_LIST\n" (String.uppercase_ascii name) +- ) structs; +- + pr "\ +-#endif /* !HAVE_ATTRIBUTE_CLEANUP */ + + /* These functions are used internally by the CLEANUP_* macros. + * Don't call them directly. +diff --git a/lib/guestfs-internal.h b/lib/guestfs-internal.h +index 174ca135f..f9f4628aa 100644 +--- a/lib/guestfs-internal.h ++++ b/lib/guestfs-internal.h +@@ -661,11 +661,7 @@ extern void guestfs_int_end_stringsbuf (guestfs_h *g, struct stringsbuf *sb); + + extern void guestfs_int_free_stringsbuf (struct stringsbuf *sb); + +-#ifdef HAVE_ATTRIBUTE_CLEANUP + #define CLEANUP_FREE_STRINGSBUF __attribute__((cleanup(guestfs_int_cleanup_free_stringsbuf))) +-#else +-#define CLEANUP_FREE_STRINGSBUF +-#endif + extern void guestfs_int_cleanup_free_stringsbuf (struct stringsbuf *sb); + + /* proto.c */ +@@ -785,11 +781,7 @@ extern int guestfs_int_cmd_pipe_run (struct command *cmd, const char *mode); + extern int guestfs_int_cmd_pipe_wait (struct command *cmd); + extern char *guestfs_int_cmd_get_pipe_errors (struct command *cmd); + +-#ifdef HAVE_ATTRIBUTE_CLEANUP + #define CLEANUP_CMD_CLOSE __attribute__((cleanup(guestfs_int_cleanup_cmd_close))) +-#else +-#define CLEANUP_CMD_CLOSE +-#endif + extern void guestfs_int_cleanup_cmd_close (struct command **); + + /* launch-*.c constructors */ +diff --git a/lib/info.c b/lib/info.c +index 4dee7a26a..b60fc8b39 100644 +--- a/lib/info.c ++++ b/lib/info.c +@@ -43,7 +43,6 @@ + #include "guestfs-internal.h" + #include "guestfs-internal-actions.h" + +-#ifdef HAVE_ATTRIBUTE_CLEANUP + #define CLEANUP_JSON_T_DECREF __attribute__((cleanup(cleanup_json_t_decref))) + + static void +@@ -52,10 +51,6 @@ cleanup_json_t_decref (void *ptr) + json_decref (* (json_t **) ptr); + } + +-#else +-#define CLEANUP_JSON_T_DECREF +-#endif +- + static json_t *get_json_output (guestfs_h *g, const char *filename); + static int qemu_img_supports_U_option (guestfs_h *g); + static void set_child_rlimits (struct command *); +diff --git a/lib/launch-libvirt.c b/lib/launch-libvirt.c +index fed6dcc86..d01f65780 100644 +--- a/lib/launch-libvirt.c ++++ b/lib/launch-libvirt.c +@@ -97,7 +97,6 @@ xmlBufferDetach (xmlBufferPtr buf) + } + #endif + +-#ifdef HAVE_ATTRIBUTE_CLEANUP + #define CLEANUP_VIRSECRETFREE __attribute__((cleanup(cleanup_virSecretFree))) + + static void +@@ -108,10 +107,6 @@ cleanup_virSecretFree (void *ptr) + virSecretFree (secret_obj); + } + +-#else /* !HAVE_ATTRIBUTE_CLEANUP */ +-#define CLEANUP_VIRSECRETFREE +-#endif +- + /* List used to store a mapping of secret to libvirt secret UUID. */ + struct secret { + char *secret; +diff --git a/lib/qemu.c b/lib/qemu.c +index 027790e4e..886c92e5d 100644 +--- a/lib/qemu.c ++++ b/lib/qemu.c +@@ -46,7 +46,6 @@ + #include "guestfs-internal.h" + #include "guestfs_protocol.h" + +-#ifdef HAVE_ATTRIBUTE_CLEANUP + #define CLEANUP_JSON_T_DECREF __attribute__((cleanup(cleanup_json_t_decref))) + + static void +@@ -55,10 +54,6 @@ cleanup_json_t_decref (void *ptr) + json_decref (* (json_t **) ptr); + } + +-#else +-#define CLEANUP_JSON_T_DECREF +-#endif +- + struct qemu_data { + int generation; /* MEMO_GENERATION read from qemu.stat */ + uint64_t prev_size; /* Size of qemu binary when cached. */ +diff --git a/m4/guestfs-c.m4 b/m4/guestfs-c.m4 +index 44c64b6d6..49109cc8f 100644 +--- a/m4/guestfs-c.m4 ++++ b/m4/guestfs-c.m4 +@@ -109,15 +109,12 @@ main (int argc, char *argv[]) + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_ATTRIBUTE_CLEANUP],[1],[Define to 1 if '__attribute__((cleanup(...)))' works with this compiler.]) + ],[ +- AC_MSG_WARN( ++ AC_MSG_ERROR( + ['__attribute__((cleanup(...)))' does not work. + + You may not be using a sufficiently recent version of GCC or CLANG, or + you may be using a C compiler which does not support this attribute, +-or the configure test may be wrong. +- +-The code will still compile, but is likely to leak memory and other +-resources when it runs.])]) ++or the configure test may be wrong.])]) + dnl restore CFLAGS + CFLAGS="${acx_nbdkit_save_CFLAGS}" + +-- +2.43.0 + diff --git a/SOURCES/0005-appliance-Use-stable-owner-group-and-mtime-in-applia.patch b/SOURCES/0005-appliance-Use-stable-owner-group-and-mtime-in-applia.patch new file mode 100644 index 0000000..07e10a6 --- /dev/null +++ b/SOURCES/0005-appliance-Use-stable-owner-group-and-mtime-in-applia.patch @@ -0,0 +1,56 @@ +From 53632b4b8245a6dd67c95015d52d1f4c562b14ed Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 21 Oct 2024 11:50:05 +0100 +Subject: [PATCH] appliance: Use stable owner, group and mtime in appliance + tarballs + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2320025 +Signed-off-by: Richard W.M. Jones +--- + appliance/Makefile.am | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/appliance/Makefile.am b/appliance/Makefile.am +index 8cb9bd1ff..7edc90e61 100644 +--- a/appliance/Makefile.am ++++ b/appliance/Makefile.am +@@ -113,12 +113,17 @@ packagelist: packagelist.in Makefile guestfsd.deps + cmp -s $@ $@-t || mv $@-t $@ + rm -f $@-t + ++# Use stable times and owner/group (RHBZ#2320025). ++TAR_COMMAND := tar -z \ ++ --owner=0 --group=0 \ ++ $${SOURCE_DATE_EPOCH:+--mtime=@"$$SOURCE_DATE_EPOCH"} ++ + supermin.d/daemon.tar.gz: ../daemon/guestfsd + rm -f $@ $@-t + rm -rf tmp-d + mkdir -p tmp-d$(DAEMON_SUPERMIN_DIR) tmp-d/etc + ln ../daemon/guestfsd tmp-d$(DAEMON_SUPERMIN_DIR)/guestfsd +- ( cd tmp-d && tar zcf - * ) > $@-t ++ ( cd tmp-d && $(TAR_COMMAND) -cf - * ) > $@-t + rm -r tmp-d + mv $@-t $@ + +@@ -139,7 +144,7 @@ supermin.d/hostfiles: hostfiles.in Makefile + + supermin.d/init.tar.gz: init + rm -f $@ $@-t +- ( cd $(srcdir) && tar zcf - init ) > $@-t ++ ( cd $(srcdir) && $(TAR_COMMAND) -cf - init ) > $@-t + mv $@-t $@ + + # We should put this file in /lib/udev/rules.d, but put it in /etc so +@@ -149,7 +154,7 @@ supermin.d/udev-rules.tar.gz: 99-guestfs-serial.rules + rm -rf tmp-u + mkdir -p tmp-u/etc/udev/rules.d + for f in $^; do ln $$f tmp-u/etc/udev/rules.d/$$(basename $$f); done +- ( cd tmp-u && tar zcf - etc ) > $@-t ++ ( cd tmp-u && $(TAR_COMMAND) -cf - etc ) > $@-t + rm -r tmp-u + mv $@-t $@ + +-- +2.43.0 + diff --git a/SOURCES/0006-appliance-Refactor-the-TAR_COMMAND-macro.patch b/SOURCES/0006-appliance-Refactor-the-TAR_COMMAND-macro.patch new file mode 100644 index 0000000..5333947 --- /dev/null +++ b/SOURCES/0006-appliance-Refactor-the-TAR_COMMAND-macro.patch @@ -0,0 +1,58 @@ +From 798e3e59b2af5057521c170268c03ab88aaf1307 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 22 Oct 2024 09:14:15 +0100 +Subject: [PATCH] appliance: Refactor the TAR_COMMAND macro + +No change, just make it easier to understand. + +Updates: commit 53632b4b8245a6dd67c95015d52d1f4c562b14ed +--- + appliance/Makefile.am | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/appliance/Makefile.am b/appliance/Makefile.am +index 7edc90e61..ce9940358 100644 +--- a/appliance/Makefile.am ++++ b/appliance/Makefile.am +@@ -113,8 +113,9 @@ packagelist: packagelist.in Makefile guestfsd.deps + cmp -s $@ $@-t || mv $@-t $@ + rm -f $@-t + +-# Use stable times and owner/group (RHBZ#2320025). +-TAR_COMMAND := tar -z \ ++# Use stable owner/group and mtimes (RHBZ#2320025). ++TAR_OPTIONS := \ ++ -z \ + --owner=0 --group=0 \ + $${SOURCE_DATE_EPOCH:+--mtime=@"$$SOURCE_DATE_EPOCH"} + +@@ -123,7 +124,7 @@ supermin.d/daemon.tar.gz: ../daemon/guestfsd + rm -rf tmp-d + mkdir -p tmp-d$(DAEMON_SUPERMIN_DIR) tmp-d/etc + ln ../daemon/guestfsd tmp-d$(DAEMON_SUPERMIN_DIR)/guestfsd +- ( cd tmp-d && $(TAR_COMMAND) -cf - * ) > $@-t ++ ( cd tmp-d && tar $(TAR_OPTIONS) -cf - * ) > $@-t + rm -r tmp-d + mv $@-t $@ + +@@ -144,7 +145,7 @@ supermin.d/hostfiles: hostfiles.in Makefile + + supermin.d/init.tar.gz: init + rm -f $@ $@-t +- ( cd $(srcdir) && $(TAR_COMMAND) -cf - init ) > $@-t ++ ( cd $(srcdir) && tar $(TAR_OPTIONS) -cf - init ) > $@-t + mv $@-t $@ + + # We should put this file in /lib/udev/rules.d, but put it in /etc so +@@ -154,7 +155,7 @@ supermin.d/udev-rules.tar.gz: 99-guestfs-serial.rules + rm -rf tmp-u + mkdir -p tmp-u/etc/udev/rules.d + for f in $^; do ln $$f tmp-u/etc/udev/rules.d/$$(basename $$f); done +- ( cd tmp-u && $(TAR_COMMAND) -cf - etc ) > $@-t ++ ( cd tmp-u && tar $(TAR_OPTIONS) -cf - etc ) > $@-t + rm -r tmp-u + mv $@-t $@ + +-- +2.43.0 + diff --git a/SOURCES/0007-build-Add-new-dependency-on-json-c.patch b/SOURCES/0007-build-Add-new-dependency-on-json-c.patch new file mode 100644 index 0000000..3ba62a3 --- /dev/null +++ b/SOURCES/0007-build-Add-new-dependency-on-json-c.patch @@ -0,0 +1,48 @@ +From 53872a0a1a267040677572c30b68bd1e8b62ebe3 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. +--- + docs/guestfs-building.pod | 4 ++++ + m4/guestfs-libraries.m4 | 3 +++ + 2 files changed, 7 insertions(+) + +diff --git a/docs/guestfs-building.pod b/docs/guestfs-building.pod +index 2c0845212..de175aaff 100644 +--- a/docs/guestfs-building.pod ++++ b/docs/guestfs-building.pod +@@ -189,6 +189,10 @@ I. + + I. + ++=item json-c E 0.14 ++ ++I. ++ + =item po4a + + I if compiling from git. +diff --git a/m4/guestfs-libraries.m4 b/m4/guestfs-libraries.m4 +index 18c4cd307..ee406d273 100644 +--- a/m4/guestfs-libraries.m4 ++++ b/m4/guestfs-libraries.m4 +@@ -304,6 +304,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 C++ (optional, we just use this to test the header works). + AC_PROG_CXX + +-- +2.43.0 + diff --git a/SOURCES/0008-daemon-ldm.c-Replace-jansson-with-json-c.patch b/SOURCES/0008-daemon-ldm.c-Replace-jansson-with-json-c.patch new file mode 100644 index 0000000..a774a2e --- /dev/null +++ b/SOURCES/0008-daemon-ldm.c-Replace-jansson-with-json-c.patch @@ -0,0 +1,234 @@ +From 5ea1e899e00f49ed27f25697e632d864760faf96 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 18 Oct 2024 21:44:13 +0100 +Subject: [PATCH] daemon/ldm.c: Replace jansson with json-c + +--- + daemon/Makefile.am | 4 +-- + daemon/ldm.c | 89 +++++++++++++++++++++++++--------------------- + 2 files changed, 51 insertions(+), 42 deletions(-) + +diff --git a/daemon/Makefile.am b/daemon/Makefile.am +index bc74b6ef7..bb72c0244 100644 +--- a/daemon/Makefile.am ++++ b/daemon/Makefile.am +@@ -225,7 +225,7 @@ guestfsd_LDADD = \ + camldaemon.o \ + $(ACL_LIBS) \ + $(CAP_LIBS) \ +- $(JANSSON_LIBS) \ ++ $(JSON_C_LIBS) \ + $(SELINUX_LIBS) \ + $(AUGEAS_LIBS) \ + $(HIVEX_LIBS) \ +@@ -264,7 +264,7 @@ guestfsd_CFLAGS = \ + $(AUGEAS_CFLAGS) \ + $(HIVEX_CFLAGS) \ + $(SD_JOURNAL_CFLAGS) \ +- $(JANSSON_CFLAGS) \ ++ $(JSON_C_CFLAGS) \ + $(PCRE2_CFLAGS) \ + $(LIBRPM_CFLAGS) + +diff --git a/daemon/ldm.c b/daemon/ldm.c +index be4fb9701..1488b9259 100644 +--- a/daemon/ldm.c ++++ b/daemon/ldm.c +@@ -25,7 +25,7 @@ + #include + #include + +-#include ++#include + + #include "daemon.h" + #include "actions.h" +@@ -65,44 +65,54 @@ do_ldmtool_remove_all (void) + return 0; + } + +-static json_t * +-parse_json (const char *json, const char *func) ++static json_object * ++parse_json (const char *json, const char *caller) + { +- json_t *tree; +- json_error_t err; ++ json_object *tree = NULL; ++ json_tokener *tok = NULL; ++ enum json_tokener_error err; + + if (verbose) +- fprintf (stderr, "%s: parsing json: %s\n", func, json); ++ fprintf (stderr, "%s: parsing json: %s\n", caller, json); + +- tree = json_loads (json, 0, &err); +- if (tree == NULL) { +- reply_with_error ("parse error: %s", +- strlen (err.text) ? err.text : "unknown error"); ++ tok = json_tokener_new (); ++ json_tokener_set_flags (tok, ++ JSON_TOKENER_STRICT | JSON_TOKENER_VALIDATE_UTF8); ++ tree = json_tokener_parse_ex (tok, json, strlen (json)); ++ err = json_tokener_get_error (tok); ++ if (err != json_tokener_success) { ++ reply_with_error ("%s: parse error: %s", ++ caller, json_tokener_error_desc (err)); ++ json_tokener_free (tok); + return NULL; + } + +- /* Caller should free this by doing 'json_decref (tree);'. */ ++ json_tokener_free (tok); ++ ++ /* Caller should free this by doing json_object_put (tree). */ + return tree; + } + + #define TYPE_ERROR ((char **) -1) + + static char ** +-json_value_to_string_list (json_t *node) ++json_value_to_string_list (json_object *node) + { + CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (strs); +- json_t *n; ++ json_object *n; + size_t i; + +- if (!json_is_array (node)) ++ if (json_object_get_type (node) != json_type_array) + return TYPE_ERROR; + +- json_array_foreach (node, i, n) { +- if (!json_is_string (n)) ++ for (i = 0; i < json_object_array_length (node); ++i) { ++ n = json_object_array_get_idx (node, i); /* Doesn't incr the refcount. */ ++ if (json_object_get_type (n) != json_type_string) + return TYPE_ERROR; +- if (add_string (&strs, json_string_value (n)) == -1) ++ if (add_string (&strs, json_object_get_string (n)) == -1) + return NULL; + } ++ + if (end_stringsbuf (&strs) == -1) + return NULL; + +@@ -111,17 +121,17 @@ json_value_to_string_list (json_t *node) + + static char ** + parse_json_get_string_list (const char *json, +- const char *func, const char *cmd) ++ const char *caller, const char *cmd) + { + char **ret; +- json_t *tree = NULL; ++ json_object *tree = NULL; + +- tree = parse_json (json, func); ++ tree = parse_json (json, caller); + if (tree == NULL) + return NULL; + + ret = json_value_to_string_list (tree); +- json_decref (tree); ++ json_object_put (tree); + if (ret == TYPE_ERROR) { + reply_with_error ("output of '%s' was not a JSON array of strings", cmd); + return NULL; +@@ -133,74 +143,73 @@ parse_json_get_string_list (const char *json, + + static char * + parse_json_get_object_string (const char *json, const char *key, int flags, +- const char *func, const char *cmd) ++ const char *caller, const char *cmd) + { + const char *str; + char *ret; +- json_t *tree = NULL, *node; ++ json_object *tree = NULL, *node; + +- tree = parse_json (json, func); ++ tree = parse_json (json, caller); + if (tree == NULL) + return NULL; + +- if (!json_is_object (tree)) ++ if (json_object_get_type (tree) != json_type_object) + goto bad_type; + +- node = json_object_get (tree, key); ++ node = json_object_object_get (tree, key); + if (node == NULL) + goto bad_type; + +- if ((flags & GET_STRING_NULL_TO_EMPTY) && json_is_null (node)) ++ if ((flags & GET_STRING_NULL_TO_EMPTY) && ++ json_object_get_type (node) == json_type_null) + ret = strdup (""); + else { +- str = json_string_value (node); +- if (str == NULL) +- goto bad_type; +- ret = strndup (str, json_string_length (node)); ++ str = json_object_get_string (node); ++ ret = strndup (str, strlen (str)); + } + if (ret == NULL) + reply_with_perror ("strdup"); + +- json_decref (tree); ++ json_object_put (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); +- json_decref (tree); ++ json_object_put (tree); + return NULL; + } + + static char ** + parse_json_get_object_string_list (const char *json, const char *key, +- const char *func, const char *cmd) ++ const char *caller, const char *cmd) + { + char **ret; +- json_t *tree, *node; ++ json_object *tree, *node; + +- tree = parse_json (json, func); ++ tree = parse_json (json, caller); + if (tree == NULL) + return NULL; + +- if (!json_is_object (tree)) ++ if (json_object_get_type (tree) != json_type_object) + goto bad_type; + +- node = json_object_get (tree, key); ++ node = json_object_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); ++ json_object_put (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); +- json_decref (tree); ++ json_object_put (tree); + return NULL; + } + +-- +2.43.0 + diff --git a/SOURCES/0010-lib-info.c-Replace-jansson-with-json-c.patch b/SOURCES/0010-lib-info.c-Replace-jansson-with-json-c.patch new file mode 100644 index 0000000..53fc2c3 --- /dev/null +++ b/SOURCES/0010-lib-info.c-Replace-jansson-with-json-c.patch @@ -0,0 +1,217 @@ +From 13e3222f3463578ab18ee8efc8502c6dfd9f51a4 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 22 Oct 2024 15:55:00 +0100 +Subject: [PATCH] lib/info.c: Replace jansson with json-c + +--- + lib/Makefile.am | 4 ++- + lib/info.c | 85 +++++++++++++++++++++++++------------------------ + 2 files changed, 47 insertions(+), 42 deletions(-) + +diff --git a/lib/Makefile.am b/lib/Makefile.am +index 0ed1576f8..60567b04b 100644 +--- a/lib/Makefile.am ++++ b/lib/Makefile.am +@@ -138,7 +138,8 @@ libguestfs_la_CFLAGS = \ + $(PCRE2_CFLAGS) \ + $(LIBVIRT_CFLAGS) \ + $(LIBXML2_CFLAGS) \ +- $(JANSSON_CFLAGS) ++ $(JANSSON_CFLAGS) \ ++ $(JSON_C_CFLAGS) + + libguestfs_la_LIBADD = \ + ../common/errnostring/liberrnostring.la \ +@@ -150,6 +151,7 @@ libguestfs_la_LIBADD = \ + $(LIBVIRT_LIBS) $(LIBXML2_LIBS) \ + $(SELINUX_LIBS) \ + $(JANSSON_LIBS) \ ++ $(JSON_C_LIBS) \ + ../gnulib/lib/libgnu.la \ + $(LIBSOCKET) \ + $(LIB_CLOCK_GETTIME) \ +diff --git a/lib/info.c b/lib/info.c +index b60fc8b39..f325bfabc 100644 +--- a/lib/info.c ++++ b/lib/info.c +@@ -37,42 +37,45 @@ + #include + #endif + +-#include ++#include + + #include "guestfs.h" + #include "guestfs-internal.h" + #include "guestfs-internal-actions.h" + +-#define CLEANUP_JSON_T_DECREF __attribute__((cleanup(cleanup_json_t_decref))) ++#define CLEANUP_JSON_OBJECT_PUT \ ++ __attribute__((cleanup(cleanup_json_object_put))) + + static void +-cleanup_json_t_decref (void *ptr) ++cleanup_json_object_put (void *ptr) + { +- json_decref (* (json_t **) ptr); ++ json_object_put (* (json_object **) ptr); + } + +-static json_t *get_json_output (guestfs_h *g, const char *filename); ++static json_object *get_json_output (guestfs_h *g, const char *filename); + static int qemu_img_supports_U_option (guestfs_h *g); + static void set_child_rlimits (struct command *); + + char * + guestfs_impl_disk_format (guestfs_h *g, const char *filename) + { +- CLEANUP_JSON_T_DECREF json_t *tree = get_json_output (g, filename); +- json_t *node; ++ CLEANUP_JSON_OBJECT_PUT json_object *tree = get_json_output (g, filename); ++ json_object *node; ++ const char *format; + + if (tree == NULL) + return NULL; + +- if (!json_is_object (tree)) ++ if (json_object_get_type (tree) != json_type_object) + goto bad_type; + +- node = json_object_get (tree, "format"); +- if (!json_is_string (node)) ++ node = json_object_object_get (tree, "format"); ++ if (node == NULL) + goto bad_type; + +- return safe_strndup (g, json_string_value (node), +- json_string_length (node)); /* caller frees */ ++ format = json_object_get_string (node); ++ ++ return safe_strdup (g, format); /* caller frees */ + + bad_type: + error (g, _("qemu-img info: JSON output did not contain ‘format’ key")); +@@ -82,20 +85,20 @@ guestfs_impl_disk_format (guestfs_h *g, const char *filename) + int64_t + guestfs_impl_disk_virtual_size (guestfs_h *g, const char *filename) + { +- CLEANUP_JSON_T_DECREF json_t *tree = get_json_output (g, filename); +- json_t *node; ++ CLEANUP_JSON_OBJECT_PUT json_object *tree = get_json_output (g, filename); ++ json_object *node; + + if (tree == NULL) + return -1; + +- if (!json_is_object (tree)) ++ if (json_object_get_type (tree) != json_type_object) + goto bad_type; + +- node = json_object_get (tree, "virtual-size"); +- if (!json_is_integer (node)) ++ node = json_object_object_get (tree, "virtual-size"); ++ if (node == NULL) + goto bad_type; + +- return json_integer_value (node); ++ return json_object_get_int64 (node); + + bad_type: + error (g, _("qemu-img info: JSON output did not contain ‘virtual-size’ key")); +@@ -105,24 +108,18 @@ guestfs_impl_disk_virtual_size (guestfs_h *g, const char *filename) + int + guestfs_impl_disk_has_backing_file (guestfs_h *g, const char *filename) + { +- CLEANUP_JSON_T_DECREF json_t *tree = get_json_output (g, filename); +- json_t *node; ++ CLEANUP_JSON_OBJECT_PUT json_object *tree = get_json_output (g, filename); ++ json_object *node; + + if (tree == NULL) + return -1; + +- if (!json_is_object (tree)) ++ if (json_object_get_type (tree) != json_type_object) + goto bad_type; + +- node = json_object_get (tree, "backing-filename"); ++ node = json_object_object_get (tree, "backing-filename"); + if (node == NULL) +- 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 0; /* no backing-filename key or null means no backing file */ + return 1; + + bad_type: +@@ -136,12 +133,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 json_t * ++static json_object * + get_json_output (guestfs_h *g, const char *filename) + { + CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g); + int r; +- json_t *tree = NULL; ++ json_object *tree = NULL; + + guestfs_int_cmd_add_arg (cmd, "qemu-img"); + guestfs_int_cmd_add_arg (cmd, "info"); +@@ -176,15 +173,16 @@ get_json_output (guestfs_h *g, const char *filename) + return NULL; + } + +- return tree; /* caller must call json_decref (tree) */ ++ return tree; /* caller must call json_object_put (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) + { +- json_t **tree_ret = treevp; +- json_error_t err; ++ json_tokener *tok = NULL; ++ json_object **tree_ret = treevp; ++ enum json_tokener_error err; + + assert (*tree_ret == NULL); + +@@ -197,15 +195,20 @@ parse_json (guestfs_h *g, void *treevp, const char *input, size_t len) + return; + } + +- debug (g, "%s: qemu-img info JSON output:\n%.*s\n", __func__, (int) len, input); ++ debug (g, "%s: qemu-img info JSON output:\n%.*s\n", ++ __func__, (int) len, input); + +- *tree_ret = json_loadb (input, len, 0, &err); +- if (*tree_ret == NULL) { +- 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")); ++ tok = json_tokener_new (); ++ json_tokener_set_flags (tok, ++ JSON_TOKENER_STRICT | JSON_TOKENER_VALIDATE_UTF8); ++ *tree_ret = json_tokener_parse_ex (tok, input, len); ++ err = json_tokener_get_error (tok); ++ if (err != json_tokener_success) { ++ error (g, _("qemu-img info: JSON parse error: %s"), ++ json_tokener_error_desc (err)); ++ *tree_ret = NULL; /* should already be */ + } ++ json_tokener_free (tok); + } + + static void +-- +2.43.0 + diff --git a/SOURCES/0011-lib-direct-Remove-test-for-qemu-mandatory-locking.patch b/SOURCES/0011-lib-direct-Remove-test-for-qemu-mandatory-locking.patch new file mode 100644 index 0000000..e9eea8a --- /dev/null +++ b/SOURCES/0011-lib-direct-Remove-test-for-qemu-mandatory-locking.patch @@ -0,0 +1,132 @@ +From 47857751a78108617e1e25d4949564bc2a182381 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 22 Oct 2024 16:23:07 +0100 +Subject: [PATCH] lib: direct: Remove test for qemu mandatory locking + +We tested for QEMU >= 2.10 support for mandatory locking. I believe +this is for all practical purposes always enabled now (and qemu 2.10 +is ancient history) so simply assume it's true always. +--- + lib/guestfs-internal.h | 1 - + lib/launch-direct.c | 19 ++++++----------- + lib/qemu.c | 48 ------------------------------------------ + 3 files changed, 7 insertions(+), 61 deletions(-) + +diff --git a/lib/guestfs-internal.h b/lib/guestfs-internal.h +index f9f4628aa..bb3772cb5 100644 +--- a/lib/guestfs-internal.h ++++ b/lib/guestfs-internal.h +@@ -796,7 +796,6 @@ extern struct qemu_data *guestfs_int_test_qemu (guestfs_h *g); + extern struct version guestfs_int_qemu_version (guestfs_h *g, struct qemu_data *); + extern int guestfs_int_qemu_supports (guestfs_h *g, const struct qemu_data *, const char *option); + extern int guestfs_int_qemu_supports_device (guestfs_h *g, const struct qemu_data *, const char *device_name); +-extern int guestfs_int_qemu_mandatory_locking (guestfs_h *g, const struct qemu_data *data); + extern bool guestfs_int_platform_has_kvm (guestfs_h *g, const struct qemu_data *data); + extern char *guestfs_int_drive_source_qemu_param (guestfs_h *g, const struct drive_source *src); + extern bool guestfs_int_discard_possible (guestfs_h *g, struct drive *drv, const struct version *qemu_version); +diff --git a/lib/launch-direct.c b/lib/launch-direct.c +index cdfd25a9a..9d0c2215b 100644 +--- a/lib/launch-direct.c ++++ b/lib/launch-direct.c +@@ -57,7 +57,6 @@ struct backend_direct_data { + pid_t recoverypid; /* Recovery process PID. */ + + struct version qemu_version; /* qemu version (0 if unable to parse). */ +- int qemu_mandatory_locking; /* qemu >= 2.10 does mandatory locking */ + struct qemu_data *qemu_data; /* qemu -help output etc. */ + + char guestfsd_sock[UNIX_PATH_MAX]; /* Path to daemon socket. */ +@@ -240,13 +239,13 @@ add_drive_standard_params (guestfs_h *g, struct backend_direct_data *data, + } + } + else { +- /* Writable qcow2 overlay on top of read-only drive. */ +- if (data->qemu_mandatory_locking && +- /* Add the file-specific locking option only for files, as +- * qemu won't accept options unknown to the block driver in +- * use. +- */ +- drv->src.protocol == drive_protocol_file) { ++ /* Writable qcow2 overlay on top of read-only drive. ++ * ++ * Add the file-specific locking option only for files, as ++ * qemu won't accept options unknown to the block driver in ++ * use. ++ */ ++ if (drv->src.protocol == drive_protocol_file) { + append_list_format ("file.file.filename=%s", drv->overlay); + append_list ("file.driver=qcow2"); + append_list ("file.backing.file.locking=off"); +@@ -495,10 +494,6 @@ launch_direct (guestfs_h *g, void *datav, const char *arg) + data->qemu_version = guestfs_int_qemu_version (g, data->qemu_data); + debug (g, "qemu version: %d.%d", + data->qemu_version.v_major, data->qemu_version.v_minor); +- data->qemu_mandatory_locking = +- guestfs_int_qemu_mandatory_locking (g, data->qemu_data); +- debug (g, "qemu mandatory locking: %s", +- data->qemu_mandatory_locking ? "yes" : "no"); + } + + /* Work out if KVM is supported or if the user wants to force TCG. */ +diff --git a/lib/qemu.c b/lib/qemu.c +index 886c92e5d..f92707710 100644 +--- a/lib/qemu.c ++++ b/lib/qemu.c +@@ -662,54 +662,6 @@ guestfs_int_qemu_supports_device (guestfs_h *g, + return strstr (data->qemu_devices, device_name) != NULL; + } + +-/** +- * Test if the qemu binary uses mandatory file locking, added in +- * QEMU >= 2.10 (but sometimes disabled). +- */ +-int +-guestfs_int_qemu_mandatory_locking (guestfs_h *g, +- const struct qemu_data *data) +-{ +- 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. */ +- if (!data->qmp_schema_tree) { +- fallback: +- return guestfs_int_version_ge (&data->qemu_version, 2, 10, 0); +- } +- +- /* Top element of qmp_schema_tree is the { "return": ... } wrapper. +- * Extract the schema from the wrapper. Note the returned ‘schema’ +- * will be an array. +- */ +- schema = json_object_get (data->qmp_schema_tree, "return"); +- if (!json_is_array (schema)) +- goto fallback; +- +- /* Now look for any member of the array which has: +- * { "meta-type": "object", +- * "members": [ ... { "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 (m, "name"); +- if (json_is_string (name) && +- STREQ (json_string_value (name), "locking")) +- return 1; +- } +- } +- } +- } +- +- return 0; +-} +- + bool + guestfs_int_platform_has_kvm (guestfs_h *g, const struct qemu_data *data) + { +-- +2.43.0 + diff --git a/SOURCES/0012-lib-qemu.c-Replace-jansson-with-json-c.patch b/SOURCES/0012-lib-qemu.c-Replace-jansson-with-json-c.patch new file mode 100644 index 0000000..e189b5e --- /dev/null +++ b/SOURCES/0012-lib-qemu.c-Replace-jansson-with-json-c.patch @@ -0,0 +1,158 @@ +From 9e3c1f44cafc2ce568462fcedc0033cab7d94cae Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 22 Oct 2024 16:24:30 +0100 +Subject: [PATCH] lib/qemu.c: Replace jansson with json-c + +--- + lib/qemu.c | 73 ++++++++++++++++++++++++++++-------------------------- + 1 file changed, 38 insertions(+), 35 deletions(-) + +diff --git a/lib/qemu.c b/lib/qemu.c +index f92707710..1d7f45f00 100644 +--- a/lib/qemu.c ++++ b/lib/qemu.c +@@ -37,7 +37,7 @@ + + #include + +-#include ++#include + + #include "full-write.h" + #include "ignore-value.h" +@@ -46,12 +46,13 @@ + #include "guestfs-internal.h" + #include "guestfs_protocol.h" + +-#define CLEANUP_JSON_T_DECREF __attribute__((cleanup(cleanup_json_t_decref))) ++#define CLEANUP_JSON_OBJECT_PUT \ ++ __attribute__((cleanup(cleanup_json_object_put))) + + static void +-cleanup_json_t_decref (void *ptr) ++cleanup_json_object_put (void *ptr) + { +- json_decref (* (json_t **) ptr); ++ json_object_put (* (json_object **) ptr); + } + + struct qemu_data { +@@ -66,7 +67,7 @@ struct qemu_data { + + /* The following fields are derived from the fields above. */ + struct version qemu_version; /* Parsed qemu version number. */ +- json_t *qmp_schema_tree; /* qmp_schema parsed into a JSON tree */ ++ json_object *qmp_schema_tree; /* qmp_schema parsed into a JSON tree */ + bool has_kvm; /* If KVM is available. */ + }; + +@@ -86,7 +87,7 @@ static int write_cache_query_kvm (guestfs_h *g, const struct qemu_data *data, co + 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 *, json_t **); ++static void parse_json (guestfs_h *g, const char *, json_object **); + static void parse_has_kvm (guestfs_h *g, const char *, bool *); + 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); +@@ -442,20 +443,24 @@ parse_qemu_version (guestfs_h *g, const char *qemu_help, + * is not possible. + */ + static void +-parse_json (guestfs_h *g, const char *json, json_t **treep) ++parse_json (guestfs_h *g, const char *json, json_object **treep) + { +- json_error_t err; ++ json_tokener *tok; ++ enum json_tokener_error err; + + if (!json) + return; + +- *treep = json_loads (json, 0, &err); +- if (*treep == NULL) { +- if (strlen (err.text) > 0) +- debug (g, "QMP parse error: %s (ignored)", err.text); +- else +- debug (g, "QMP unknown parse error (ignored)"); +- } ++ tok = json_tokener_new (); ++ json_tokener_set_flags (tok, ++ JSON_TOKENER_STRICT | JSON_TOKENER_VALIDATE_UTF8); ++ *treep = json_tokener_parse_ex (tok, json, strlen (json)); ++ err = json_tokener_get_error (tok); ++ if (err != json_tokener_success) ++ debug (g, "QMP parse error: %s (ignored)", json_tokener_error_desc (err)); ++ json_tokener_free (tok); ++ ++ /* Caller should do json_object_put (*treep) */ + } + + /** +@@ -469,37 +474,35 @@ parse_json (guestfs_h *g, const char *json, json_t **treep) + static void + parse_has_kvm (guestfs_h *g, const char *json, bool *ret) + { +- CLEANUP_JSON_T_DECREF json_t *tree = NULL; +- json_error_t err; +- json_t *return_node, *enabled_node; ++ CLEANUP_JSON_OBJECT_PUT json_object *tree = NULL; ++ json_tokener *tok; ++ enum json_tokener_error err; ++ json_object *return_node, *enabled_node; + + *ret = true; /* Assume KVM is enabled. */ + + if (!json) + return; + +- tree = json_loads (json, 0, &err); +- if (tree == NULL) { +- if (strlen (err.text) > 0) +- debug (g, "QMP parse error: %s (ignored)", err.text); +- else +- debug (g, "QMP unknown parse error (ignored)"); ++ tok = json_tokener_new (); ++ json_tokener_set_flags (tok, ++ JSON_TOKENER_STRICT | JSON_TOKENER_VALIDATE_UTF8); ++ tree = json_tokener_parse_ex (tok, json, strlen (json)); ++ err = json_tokener_get_error (tok); ++ if (err != json_tokener_success) { ++ debug (g, "QMP parse error: %s (ignored)", json_tokener_error_desc (err)); ++ json_tokener_free (tok); + return; + } ++ json_tokener_free (tok); + +- return_node = json_object_get (tree, "return"); +- if (!json_is_object (return_node)) { ++ return_node = json_object_object_get (tree, "return"); ++ if (json_object_get_type (return_node) != json_type_object) { + debug (g, "QMP query-kvm: no \"return\" node (ignored)"); + return; + } +- enabled_node = json_object_get (return_node, "enabled"); +- /* Note that json_is_boolean will check that enabled_node != NULL. */ +- if (!json_is_boolean (enabled_node)) { +- debug (g, "QMP query-kvm: no \"enabled\" node or not a boolean (ignored)"); +- return; +- } +- +- *ret = json_is_true (enabled_node); ++ enabled_node = json_object_object_get (return_node, "enabled"); ++ *ret = json_object_get_boolean (enabled_node); + } + + /** +@@ -975,7 +978,7 @@ guestfs_int_free_qemu_data (struct qemu_data *data) + free (data->qemu_devices); + free (data->qmp_schema); + free (data->query_kvm); +- json_decref (data->qmp_schema_tree); ++ json_object_put (data->qmp_schema_tree); + free (data); + } + } +-- +2.43.0 + diff --git a/SOURCES/0013-build-Remove-Jansson-dependency.patch b/SOURCES/0013-build-Remove-Jansson-dependency.patch new file mode 100644 index 0000000..d77be34 --- /dev/null +++ b/SOURCES/0013-build-Remove-Jansson-dependency.patch @@ -0,0 +1,68 @@ +From 9255abee029e35dd5c6783b8b6037eb71104650c 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 +guestfs-tools commit e6dcf7e3a7e9170978e57ce6df1b34f92fac5ae3) +--- + docs/guestfs-building.pod | 4 ---- + lib/Makefile.am | 2 -- + m4/guestfs-libraries.m4 | 3 --- + 3 files changed, 9 deletions(-) + +diff --git a/docs/guestfs-building.pod b/docs/guestfs-building.pod +index de175aaff..aef716ffc 100644 +--- a/docs/guestfs-building.pod ++++ b/docs/guestfs-building.pod +@@ -185,10 +185,6 @@ I. + + I. + +-=item Jansson E 2.7 +- +-I. +- + =item json-c E 0.14 + + I. +diff --git a/lib/Makefile.am b/lib/Makefile.am +index 60567b04b..6949884d5 100644 +--- a/lib/Makefile.am ++++ b/lib/Makefile.am +@@ -138,7 +138,6 @@ libguestfs_la_CFLAGS = \ + $(PCRE2_CFLAGS) \ + $(LIBVIRT_CFLAGS) \ + $(LIBXML2_CFLAGS) \ +- $(JANSSON_CFLAGS) \ + $(JSON_C_CFLAGS) + + libguestfs_la_LIBADD = \ +@@ -150,7 +149,6 @@ libguestfs_la_LIBADD = \ + $(PCRE2_LIBS) \ + $(LIBVIRT_LIBS) $(LIBXML2_LIBS) \ + $(SELINUX_LIBS) \ +- $(JANSSON_LIBS) \ + $(JSON_C_LIBS) \ + ../gnulib/lib/libgnu.la \ + $(LIBSOCKET) \ +diff --git a/m4/guestfs-libraries.m4 b/m4/guestfs-libraries.m4 +index ee406d273..515651717 100644 +--- a/m4/guestfs-libraries.m4 ++++ b/m4/guestfs-libraries.m4 +@@ -301,9 +301,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]) + +-- +2.43.0 + diff --git a/SOURCES/0014-website-Fix-link-to-latest-development-version.patch b/SOURCES/0014-website-Fix-link-to-latest-development-version.patch new file mode 100644 index 0000000..4646459 --- /dev/null +++ b/SOURCES/0014-website-Fix-link-to-latest-development-version.patch @@ -0,0 +1,26 @@ +From 4ea26a26557e0e648477526bae2313275e975f20 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 22 Oct 2024 17:44:06 +0100 +Subject: [PATCH] website: Fix link to latest development version + +Fixes: commit 0edaea8f91bf08025651eeff32f53b9335003842 +--- + website/index.html.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/website/index.html.in b/website/index.html.in +index 2a0d32217..13c5ff25f 100644 +--- a/website/index.html.in ++++ b/website/index.html.in +@@ -183,7 +183,7 @@ git clone https://github.com/ +

+ + + Latest development version: @PACKAGE_VERSION@ (released @RELEASE_DATE@).
+-- +2.43.0 + diff --git a/SOURCES/0004-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch b/SOURCES/0015-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch similarity index 99% rename from SOURCES/0004-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch rename to SOURCES/0015-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch index 7900899..32a89d9 100644 --- a/SOURCES/0004-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch +++ b/SOURCES/0015-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch @@ -1,4 +1,4 @@ -From 5efb2b2ab438f7621897e0da8602cf6d81a03ce2 Mon Sep 17 00:00:00 2001 +From c508b3390245bbecfa8acf785b7d7bfd215859ae Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Mon, 29 Jul 2013 14:47:56 +0100 Subject: [PATCH] RHEL: Disable unsupported remote drive protocols diff --git a/SOURCES/0005-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch b/SOURCES/0016-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch similarity index 93% rename from SOURCES/0005-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch rename to SOURCES/0016-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch index edf09f4..af931cd 100644 --- a/SOURCES/0005-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch +++ b/SOURCES/0016-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch @@ -1,4 +1,4 @@ -From e23ae7abc6b92235a7ccb72db9eaa23728511f18 Mon Sep 17 00:00:00 2001 +From b8c15791942f56030b49c5e725e61bbba4a990d2 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 7 Jul 2015 09:28:03 -0400 Subject: [PATCH] RHEL: Reject use of libguestfs-winsupport features except for @@ -13,10 +13,10 @@ edits. 3 files changed, 19 insertions(+) diff --git a/generator/c.ml b/generator/c.ml -index 447059b8a..a32d959d7 100644 +index 838e7f426..09181028b 100644 --- a/generator/c.ml +++ b/generator/c.ml -@@ -1846,6 +1846,22 @@ and generate_client_actions actions () = +@@ -1836,6 +1836,22 @@ and generate_client_actions actions () = check_args_validity c_name style; trace_call name c_name style; diff --git a/SPECS/libguestfs.spec b/SPECS/libguestfs.spec index f0a612c..05cbd25 100644 --- a/SPECS/libguestfs.spec +++ b/SPECS/libguestfs.spec @@ -42,7 +42,7 @@ Summary: Access and modify virtual machine disk images Name: libguestfs Epoch: 1 Version: 1.54.0 -Release: 2%{?dist} +Release: 3%{?dist} License: LGPL-2.1-or-later # Build only for architectures that have a kernel @@ -83,8 +83,19 @@ Source8: copy-patches.sh Patch0001: 0001-website-Add-links-for-1.54-and-1.55-download-locatio.patch Patch0002: 0002-tests-gdisk-test-expand-gpt.pl-Implement-SKIP-rule-f.patch Patch0003: 0003-lib-inspect-osinfo.c-Add-Windows-Server-2025-osinfo.patch -Patch0004: 0004-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch -Patch0005: 0005-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch +Patch0004: 0004-build-Assume-__attribute__-cleanup-always-works.patch +Patch0005: 0005-appliance-Use-stable-owner-group-and-mtime-in-applia.patch +Patch0006: 0006-appliance-Refactor-the-TAR_COMMAND-macro.patch +Patch0007: 0007-build-Add-new-dependency-on-json-c.patch +Patch0008: 0008-daemon-ldm.c-Replace-jansson-with-json-c.patch +#Patch0009: 0009-common-Update-common-submodule.patch +Patch0010: 0010-lib-info.c-Replace-jansson-with-json-c.patch +Patch0011: 0011-lib-direct-Remove-test-for-qemu-mandatory-locking.patch +Patch0012: 0012-lib-qemu.c-Replace-jansson-with-json-c.patch +Patch0013: 0013-build-Remove-Jansson-dependency.patch +Patch0014: 0014-website-Fix-link-to-latest-development-version.patch +Patch0015: 0015-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch +Patch0016: 0016-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch BuildRequires: autoconf, automake, libtool, gettext-devel @@ -136,7 +147,7 @@ BuildRequires: libcap-devel %if !0%{?rhel} BuildRequires: libldm-devel %endif -BuildRequires: jansson-devel +BuildRequires: json-c-devel BuildRequires: systemd-devel BuildRequires: bash-completion BuildRequires: /usr/bin/ping @@ -295,7 +306,7 @@ Requires: (%{name}-appliance = %{epoch}:%{version}-%{release} or %{name}-no # The daemon dependencies are not included automatically, because it # is buried inside the appliance, so list them here. Requires: augeas-libs%{?_isa} >= 1.7.0 -Requires: jansson%{?_isa} +Requires: json-c%{?_isa} Requires: libacl%{?_isa} Requires: libcap%{?_isa} Requires: libselinux%{?_isa} @@ -1110,14 +1121,16 @@ rm ocaml/html/.gitignore %changelog -* Fri Oct 25 2024 MSVSphere Packaging Team - 1:1.54.0-2 -- Rebuilt for MSVSphere 10 - -* Thu Oct 17 2024 Richard W.M. Jones - 1:1.54.0-2 +* Wed Oct 30 2024 Richard W.M. Jones - 1:1.54.0-3 - Rebase to libguestfs 1.54.0 resolves: RHEL-56810 - Fix osinfo for Windows Server 2025 resolves: RHEL-62989 +- Replace Jansson with json-c + resolves: RHEL-65293 + +* Fri Oct 25 2024 MSVSphere Packaging Team - 1:1.52.2-4 +- Rebuilt for MSVSphere 10 * Wed Aug 28 2024 Richard W.M. Jones - 1:1.52.2-4 - Synchronize patches with RHEL 9.5