lib/info.c: Replace jansson with json-c

This commit is contained in:
Richard W.M. Jones
2024-10-22 15:55:00 +01:00
parent 8e34b37bcd
commit 13e3222f34
2 changed files with 47 additions and 42 deletions

View File

@@ -138,7 +138,8 @@ libguestfs_la_CFLAGS = \
$(PCRE2_CFLAGS) \ $(PCRE2_CFLAGS) \
$(LIBVIRT_CFLAGS) \ $(LIBVIRT_CFLAGS) \
$(LIBXML2_CFLAGS) \ $(LIBXML2_CFLAGS) \
$(JANSSON_CFLAGS) $(JANSSON_CFLAGS) \
$(JSON_C_CFLAGS)
libguestfs_la_LIBADD = \ libguestfs_la_LIBADD = \
../common/errnostring/liberrnostring.la \ ../common/errnostring/liberrnostring.la \
@@ -150,6 +151,7 @@ libguestfs_la_LIBADD = \
$(LIBVIRT_LIBS) $(LIBXML2_LIBS) \ $(LIBVIRT_LIBS) $(LIBXML2_LIBS) \
$(SELINUX_LIBS) \ $(SELINUX_LIBS) \
$(JANSSON_LIBS) \ $(JANSSON_LIBS) \
$(JSON_C_LIBS) \
../gnulib/lib/libgnu.la \ ../gnulib/lib/libgnu.la \
$(LIBSOCKET) \ $(LIBSOCKET) \
$(LIB_CLOCK_GETTIME) \ $(LIB_CLOCK_GETTIME) \

View File

@@ -37,42 +37,45 @@
#include <sys/resource.h> #include <sys/resource.h>
#endif #endif
#include <jansson.h> #include <json.h>
#include "guestfs.h" #include "guestfs.h"
#include "guestfs-internal.h" #include "guestfs-internal.h"
#include "guestfs-internal-actions.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 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 int qemu_img_supports_U_option (guestfs_h *g);
static void set_child_rlimits (struct command *); static void set_child_rlimits (struct command *);
char * char *
guestfs_impl_disk_format (guestfs_h *g, const char *filename) guestfs_impl_disk_format (guestfs_h *g, const char *filename)
{ {
CLEANUP_JSON_T_DECREF json_t *tree = get_json_output (g, filename); CLEANUP_JSON_OBJECT_PUT json_object *tree = get_json_output (g, filename);
json_t *node; json_object *node;
const char *format;
if (tree == NULL) if (tree == NULL)
return NULL; return NULL;
if (!json_is_object (tree)) if (json_object_get_type (tree) != json_type_object)
goto bad_type; goto bad_type;
node = json_object_get (tree, "format"); node = json_object_object_get (tree, "format");
if (!json_is_string (node)) if (node == NULL)
goto bad_type; goto bad_type;
return safe_strndup (g, json_string_value (node), format = json_object_get_string (node);
json_string_length (node)); /* caller frees */
return safe_strdup (g, format); /* caller frees */
bad_type: bad_type:
error (g, _("qemu-img info: JSON output did not contain format key")); 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 int64_t
guestfs_impl_disk_virtual_size (guestfs_h *g, const char *filename) guestfs_impl_disk_virtual_size (guestfs_h *g, const char *filename)
{ {
CLEANUP_JSON_T_DECREF json_t *tree = get_json_output (g, filename); CLEANUP_JSON_OBJECT_PUT json_object *tree = get_json_output (g, filename);
json_t *node; json_object *node;
if (tree == NULL) if (tree == NULL)
return -1; return -1;
if (!json_is_object (tree)) if (json_object_get_type (tree) != json_type_object)
goto bad_type; goto bad_type;
node = json_object_get (tree, "virtual-size"); node = json_object_object_get (tree, "virtual-size");
if (!json_is_integer (node)) if (node == NULL)
goto bad_type; goto bad_type;
return json_integer_value (node); return json_object_get_int64 (node);
bad_type: bad_type:
error (g, _("qemu-img info: JSON output did not contain virtual-size key")); 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 int
guestfs_impl_disk_has_backing_file (guestfs_h *g, const char *filename) guestfs_impl_disk_has_backing_file (guestfs_h *g, const char *filename)
{ {
CLEANUP_JSON_T_DECREF json_t *tree = get_json_output (g, filename); CLEANUP_JSON_OBJECT_PUT json_object *tree = get_json_output (g, filename);
json_t *node; json_object *node;
if (tree == NULL) if (tree == NULL)
return -1; return -1;
if (!json_is_object (tree)) if (json_object_get_type (tree) != json_type_object)
goto bad_type; goto bad_type;
node = json_object_get (tree, "backing-filename"); node = json_object_object_get (tree, "backing-filename");
if (node == NULL) if (node == NULL)
return 0; /* no backing-filename key means no backing file */ return 0; /* no backing-filename key or null 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; return 1;
bad_type: 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); static void parse_json (guestfs_h *g, void *treevp, const char *input, size_t len);
#define PARSE_JSON_NO_OUTPUT ((void *) -1) #define PARSE_JSON_NO_OUTPUT ((void *) -1)
static json_t * static json_object *
get_json_output (guestfs_h *g, const char *filename) get_json_output (guestfs_h *g, const char *filename)
{ {
CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g); CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
int r; int r;
json_t *tree = NULL; json_object *tree = NULL;
guestfs_int_cmd_add_arg (cmd, "qemu-img"); guestfs_int_cmd_add_arg (cmd, "qemu-img");
guestfs_int_cmd_add_arg (cmd, "info"); guestfs_int_cmd_add_arg (cmd, "info");
@@ -176,15 +173,16 @@ get_json_output (guestfs_h *g, const char *filename)
return NULL; 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. */ /* Parse the JSON document printed by qemu-img info --output json. */
static void static void
parse_json (guestfs_h *g, void *treevp, const char *input, size_t len) parse_json (guestfs_h *g, void *treevp, const char *input, size_t len)
{ {
json_t **tree_ret = treevp; json_tokener *tok = NULL;
json_error_t err; json_object **tree_ret = treevp;
enum json_tokener_error err;
assert (*tree_ret == NULL); assert (*tree_ret == NULL);
@@ -197,15 +195,20 @@ parse_json (guestfs_h *g, void *treevp, const char *input, size_t len)
return; 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); tok = json_tokener_new ();
if (*tree_ret == NULL) { json_tokener_set_flags (tok,
if (strlen (err.text) > 0) JSON_TOKENER_STRICT | JSON_TOKENER_VALIDATE_UTF8);
error (g, _("qemu-img info: JSON parse error: %s"), err.text); *tree_ret = json_tokener_parse_ex (tok, input, len);
else err = json_tokener_get_error (tok);
error (g, _("qemu-img info: unknown JSON parse error")); 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 static void