On Tue, 20 Feb 2018 12:59:46 +0300 Viktor Prutyanov <viktor.prutyanov@xxxxxxxxxxxxx> wrote: ping > This patch adds JSON objects and lists and methods to print them > > Signed-off-by: Viktor Prutyanov <viktor.prutyanov@xxxxxxxxxxxxx> > --- > lib/support/Makefile.in | 7 +- > lib/support/json-out.c | 326 > ++++++++++++++++++++++++++++++++++++++++++++++++ > lib/support/json-out.h | 69 ++++++++++ misc/dumpe2fs.c | > 17 ++- 4 files changed, 416 insertions(+), 3 deletions(-) > create mode 100644 lib/support/json-out.c > create mode 100644 lib/support/json-out.h > > diff --git a/lib/support/Makefile.in b/lib/support/Makefile.in > index 40206b74..42fa3324 100644 > --- a/lib/support/Makefile.in > +++ b/lib/support/Makefile.in > @@ -22,7 +22,8 @@ OBJS= cstring.o \ > quotaio.o \ > quotaio_v2.o \ > quotaio_tree.o \ > - dict.o > + dict.o \ > + json-out.o > > SRCS= $(srcdir)/argv_parse.c \ > $(srcdir)/cstring.c \ > @@ -35,7 +36,8 @@ SRCS= $(srcdir)/argv_parse.c \ > $(srcdir)/quotaio.c \ > $(srcdir)/quotaio_tree.c \ > $(srcdir)/quotaio_v2.c \ > - $(srcdir)/dict.c > + $(srcdir)/dict.c \ > + $(srcdir)/json-out.c > > LIBRARY= libsupport > LIBDIR= support > @@ -165,3 +167,4 @@ quotaio_v2.o: $(srcdir)/quotaio_v2.c > $(top_builddir)/lib/config.h \ $(srcdir)/dqblk_v2.h > $(srcdir)/quotaio_tree.h dict.o: $(srcdir)/dict.c > $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h > $(srcdir)/dict.h +json-out.o: $(srcdir)/json-out.c > $(srcdir)/json-out.h diff --git a/lib/support/json-out.c > b/lib/support/json-out.c new file mode 100644 > index 00000000..8c822f35 > --- /dev/null > +++ b/lib/support/json-out.c > @@ -0,0 +1,326 @@ > +/* > + * json-out.c -- JSON output > + * > + * Copyright (c) 2018 Virtuozzo International GmbH > + * > + * %Begin-Header% > + * This file may be redistributed under the terms of the GNU Public > + * License. > + * %End-Header% > + */ > + > +#include <stdio.h> > +#include <string.h> > +#include <stdlib.h> > +#include <stdarg.h> > + > +#include "json-out.h" > + > +static void *xmalloc(size_t size) > +{ > + void *p = malloc(size); > + > + if (!p) > + exit(1); > + > + return p; > +} > + > +static void *xstrdup(const char *str) > +{ > + size_t size = strlen(str) + 1; > + char *p = xmalloc(size); > + > + return strcpy(p, str); > +} > + > +struct json_list *json_list_create(enum json_val_type type) > +{ > + struct json_list *list = xmalloc(sizeof(struct json_list)); > + > + list->node = NULL; > + list->type = type; > + > + return list; > +} > + > +struct json_list *json_list_create_in_obj(struct json_obj > *parent_obj, char *key, enum json_val_type type) +{ > + struct json_list *list = json_list_create(type); > + > + json_obj_add_list(parent_obj, key, list); > + > + return list; > +} > + > +void json_list_delete(struct json_list *list) > +{ > + struct json_list_node *node = list->node, *next; > + > + while (node) { > + switch (list->type) { > + case JSON_VAL_STRING: > + free(node->val.str); > + break; > + case JSON_VAL_LIST: > + json_list_delete(node->val.list); > + break; > + case JSON_VAL_OBJECT: > + json_obj_delete(node->val.obj); > + break; > + default: > + break; > + } > + next = node->next; > + free(node); > + node = next; > + } > + free(list); > +} > + > +struct json_obj *json_obj_create(void) > +{ > + struct json_obj *obj = xmalloc(sizeof(struct json_obj)); > + > + obj->pair = NULL; > + > + return obj; > +} > + > +struct json_obj *json_obj_create_in_obj(struct json_obj *parent_obj, > char *key) +{ > + struct json_obj *obj = json_obj_create(); > + > + json_obj_add_obj(parent_obj, key, obj); > + > + return obj; > +} > + > +static void json_pair_delete(struct json_pair *pair) > +{ > + switch (pair->type) > + { > + case JSON_VAL_STRING: > + free(pair->val.str); > + break; > + case JSON_VAL_LIST: > + json_list_delete(pair->val.list); > + break; > + case JSON_VAL_OBJECT: > + json_obj_delete(pair->val.obj); > + break; > + default: > + break; > + } > + free(pair->key); > + free(pair); > +} > + > +void json_obj_delete(struct json_obj *obj) > +{ > + struct json_pair *pair = obj->pair, *next; > + > + while (pair) { > + next = pair->next; > + json_pair_delete(pair); > + pair = next; > + } > + free(obj); > +} > + > +void json_obj_delete_pair(struct json_obj *obj, char *key) > +{ > + struct json_pair *pair = obj->pair, *next, *prev = NULL; > + > + while (pair) { > + next = pair->next; > + if (!strcmp(pair->key, key)) { > + json_pair_delete(pair); > + if (prev) > + prev->next = next; > + else > + obj->pair = next; > + break; > + } > + prev = pair; > + pair = next; > + } > +} > + > +static struct json_list_node *json_list_add_node(struct json_list > *list) +{ > + struct json_list_node *new_node = xmalloc(sizeof(struct > json_list_node)); + > + new_node->next = NULL; > + > + if (list->node) { > + struct json_list_node *node; > + > + for (node = list->node; node && node->next; node = > node->next); > + node->next = new_node; > + } else > + list->node = new_node; > + > + return new_node; > +} > + > +void json_list_add_str(struct json_list *list, const char *str) > +{ > + struct json_list_node *new_node = json_list_add_node(list); > + > + new_node->val.str = xstrdup(str); > +} > + > +void json_list_add_obj(struct json_list *list, struct json_obj *obj) > +{ > + struct json_list_node *new_node = json_list_add_node(list); > + > + new_node->val.obj = obj; > +} > + > +static struct json_pair *json_obj_add_pair(struct json_obj *obj, > const char *key, enum json_val_type type) +{ > + struct json_pair *new_pair = xmalloc(sizeof(struct > json_pair)); > + new_pair->key = xstrdup(key); > + new_pair->next = NULL; > + new_pair->type = type; > + > + if (obj->pair) { > + struct json_pair *pair; > + > + for (pair = obj->pair; pair && pair->next; pair = > pair->next); > + pair->next = new_pair; > + } else > + obj->pair = new_pair; > + > + return new_pair; > +} > + > +void json_obj_add_str(struct json_obj *obj, const char *key, const > char *str) +{ > + struct json_pair *new_pair = json_obj_add_pair(obj, key, > JSON_VAL_STRING); + > + new_pair->val.str = xstrdup(str); > +} > + > +void json_obj_add_fmt_buf_str(struct json_obj *obj, const char *key, > char *buf, size_t size, const char *fmt, ...) +{ > + va_list ap; > + > + va_start(ap, fmt); > + vsnprintf(buf, size, fmt, ap); > + va_end(ap); > + > + json_obj_add_str(obj, key, buf); > +} > + > +void json_obj_add_fmt_str(struct json_obj *obj, const char *key, > size_t size, const char *fmt, ...) +{ > + va_list ap; > + char *buf = malloc(size); > + > + va_start(ap, fmt); > + vsnprintf(buf, size, fmt, ap); > + va_end(ap); > + > + json_obj_add_str(obj, key, buf); > + free(buf); > +} > + > +void json_obj_add_list(struct json_obj *obj, const char *key, struct > json_list *list) +{ > + struct json_pair *new_pair = json_obj_add_pair(obj, key, > JSON_VAL_LIST); + > + new_pair->val.list = list; > +} > + > +void json_obj_add_obj(struct json_obj *obj, const char *key, struct > json_obj *new_obj) +{ > + struct json_pair *new_pair = json_obj_add_pair(obj, key, > JSON_VAL_OBJECT); + > + new_pair->val.obj = new_obj; > +} > + > +static void json_pair_print_json(struct json_pair *pair, int > ind_lvl); +static void json_list_node_print_json(struct > json_list_node *node, enum json_val_type type, int ind_lvl); + > +static void > +print_ind(int ind_lvl) > +{ > + int i; > + > + putchar('\n'); > + for (i = 0; i < ind_lvl; i++) > + fputs(" ", stdout); > +} > + > +void json_obj_print_json(struct json_obj *obj, int ind_lvl) > +{ > + struct json_pair *pair; > + > + printf("{"); > + for (pair = obj->pair; pair; pair = pair->next) { > + json_pair_print_json(pair, ind_lvl+1); > + if (pair->next) > + printf(", "); > + } > + if (obj->pair) /* Do not indent if object was empty */ > + print_ind(ind_lvl); > + printf("}"); > +} > + > +void json_list_print_json(struct json_list *list, int ind_lvl) > +{ > + struct json_list_node *node; > + > + printf("["); > + for (node = list->node; node; node = node->next) { > + json_list_node_print_json(node, list->type, > ind_lvl+1); > + if (node->next) > + printf(", "); > + } > + if (list->node) /* Do not indent if list was empty */ > + print_ind(ind_lvl); > + printf("]"); > +} > + > +static void > +json_list_node_print_json(struct json_list_node *node, enum > json_val_type type, int ind_lvl) +{ > + print_ind(ind_lvl); > + switch (type) { > + case JSON_VAL_STRING: > + printf("\"%s\"", node->val.str); > + break; > + case JSON_VAL_LIST: > + json_list_print_json(node->val.list, ind_lvl); > + break; > + case JSON_VAL_OBJECT: > + json_obj_print_json(node->val.obj, ind_lvl); > + break; > + case JSON_VAL_FLAG: > + printf("%s", node->val.flag ? "true" : "false"); > + break; > + default: > + break; > + } > +} > + > +static void json_pair_print_json(struct json_pair *pair, int ind_lvl) > +{ > + print_ind(ind_lvl); > + printf("\"%s\": ", pair->key); > + switch (pair->type) { > + case JSON_VAL_STRING: > + printf("\"%s\"", pair->val.str); > + break; > + case JSON_VAL_LIST: > + json_list_print_json(pair->val.list, ind_lvl); > + break; > + case JSON_VAL_OBJECT: > + json_obj_print_json(pair->val.obj, ind_lvl); > + break; > + default: > + break; > + } > +} > diff --git a/lib/support/json-out.h b/lib/support/json-out.h > new file mode 100644 > index 00000000..0132bd2c > --- /dev/null > +++ b/lib/support/json-out.h > @@ -0,0 +1,69 @@ > +/* > + * json-out.h -- JSON output > + * > + * Copyright (c) 2018 Virtuozzo International GmbH > + * > + * %Begin-Header% > + * This file may be redistributed under the terms of the GNU Public > + * License. > + * %End-Header% > + */ > + > +#ifndef H_JSON_OUT > +#define H_JSON_OUT > + > +enum json_val_type { > + JSON_VAL_STRING, > + JSON_VAL_OBJECT, > + JSON_VAL_LIST, > + JSON_VAL_FLAG > +}; > + > +struct json_obj { > + struct json_pair *pair; > +}; > + > +union json_val { > + char *str; > + struct json_obj *obj; > + struct json_list *list; > + char flag; > +}; > + > +struct json_pair { > + char *key; > + enum json_val_type type; > + union json_val val; > + struct json_pair *next; > +}; > + > +struct json_list { > + enum json_val_type type; > + struct json_list_node *node; > +}; > + > +struct json_list_node { > + union json_val val; > + struct json_list_node *next; > +}; > + > +struct json_obj *json_obj_create(void); > +struct json_obj *json_obj_create_in_obj(struct json_obj *parent_obj, > char *key); +void json_obj_add_str(struct json_obj *obj, const char > *key, const char *str); +void json_obj_add_list(struct json_obj *obj, > const char *key, struct json_list *list); +void > json_obj_add_obj(struct json_obj *obj, const char *key, struct > json_obj *new_obj); +void json_obj_add_flag(struct json_obj *obj, > const char *key, char flag); +void json_obj_add_fmt_str(struct > json_obj *obj, const char *key, size_t size, const char *fmt, ...); > +void json_obj_add_fmt_buf_str(struct json_obj *obj, const char *key, > char *buf, size_t size, const char *fmt, ...); +void > json_obj_print_json(struct json_obj *obj, int ind_lvl); +void > json_obj_delete_pair(struct json_obj *obj, char *key); +void > json_obj_delete(struct json_obj *obj); + +struct json_list > *json_list_create(enum json_val_type type); +struct json_list > *json_list_create_in_obj(struct json_obj *parent_obj, char *key, enum > json_val_type type); +void json_list_add_str(struct json_list *list, > const char *str); +void json_list_add_obj(struct json_list *list, > struct json_obj *obj); +void json_list_print_json(struct json_list > *list, int ind_lvl); +void json_list_delete(struct json_list *list); > + +#endif diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c > index 395ea9ee..ca9953a1 100644 > --- a/misc/dumpe2fs.c > +++ b/misc/dumpe2fs.c > @@ -607,7 +607,12 @@ try_open_again: > goto just_descriptors; > list_super (fs->super); > if (ext2fs_has_feature_journal_dev(fs->super)) { > - print_journal_information(fs); > + print_journal_information(fs, dump_obj); > + if (json) { > + json_obj_print_json(dump_obj, 0); > + putchar('\n'); > + json_obj_delete(dump_obj); > + } > ext2fs_close_free(&fs); > exit(0); > } > @@ -616,6 +621,11 @@ try_open_again: > print_inline_journal_information(fs); > list_bad_blocks(fs, 0); > if (header_only) { > + if (json) { > + json_obj_print_json(dump_obj, 0); > + putchar('\n'); > + json_obj_delete(dump_obj); > + } > ext2fs_close_free(&fs); > exit (0); > } > @@ -636,6 +646,11 @@ just_descriptors: > error_message(retval)); > } > } > + if (json) { > + json_obj_print_json(dump_obj, 0); > + putchar('\n'); > + json_obj_delete(dump_obj); > + } > ext2fs_close_free(&fs); > remove_error_table(&et_ext2_error_table); > exit (0);