On Fri, 09/06 15:12, Max Reitz wrote: > Add a function for generically dumping the ImageInfoSpecific information > in a human-readable format to block/qapi.c. > > Use this function in bdrv_image_info_dump and qemu-io-cmds.c:info_f to > allow qemu-img info resp. qemu-io -c info to print that format specific > information. > > Signed-off-by: Max Reitz <mre...@redhat.com> > --- > block/qapi.c | 121 > +++++++++++++++++++++++++++++++++++++++++++++++++++ > include/block/qapi.h | 2 + > qemu-io-cmds.c | 3 ++ > 3 files changed, 126 insertions(+) > > diff --git a/block/qapi.c b/block/qapi.c > index f13fbd5..4fe45d5 100644 > --- a/block/qapi.c > +++ b/block/qapi.c > @@ -25,6 +25,9 @@ > #include "block/qapi.h" > #include "block/block_int.h" > #include "qmp-commands.h" > +#include "qapi-visit.h" > +#include "qapi/qmp-output-visitor.h" > +#include "qapi/qmp/types.h" > > /* > * Returns 0 on success, with *p_list either set to describe snapshot > @@ -401,6 +404,119 @@ void bdrv_snapshot_dump(fprintf_function func_fprintf, > void *f, > } > } > > +static void dump_qdict(fprintf_function func_fprintf, void *f, int > indentation, > + QDict *dict); > +static void dump_qlist(fprintf_function func_fprintf, void *f, int > indentation, > + QList *list); > + > +static void dump_qobject(fprintf_function func_fprintf, void *f, > + int comp_indent, QObject *obj) > +{ > + switch (qobject_type(obj)) { > + case QTYPE_QINT: { > + QInt *value = qobject_to_qint(obj); > + func_fprintf(f, "%" PRId64, qint_get_int(value)); > + break; > + } > + case QTYPE_QSTRING: { > + QString *value = qobject_to_qstring(obj); > + func_fprintf(f, "%s", qstring_get_str(value)); > + break; > + } > + case QTYPE_QDICT: { > + QDict *value = qobject_to_qdict(obj); > + dump_qdict(func_fprintf, f, comp_indent, value); > + break; > + } > + case QTYPE_QLIST: { > + QList *value = qobject_to_qlist(obj); > + dump_qlist(func_fprintf, f, comp_indent, value); > + break; > + } > + case QTYPE_QFLOAT: { > + QFloat *value = qobject_to_qfloat(obj); > + func_fprintf(f, "%g", qfloat_get_double(value)); > + break; > + } > + case QTYPE_QBOOL: { > + QBool *value = qobject_to_qbool(obj); > + func_fprintf(f, "%s", qbool_get_int(value) ? "true" : "false"); > + break; > + } > + case QTYPE_QERROR: { > + QString *value = qerror_human((QError *)obj); > + func_fprintf(f, "%s", qstring_get_str(value)); > + break; > + } > + case QTYPE_NONE: > + break; > + case QTYPE_MAX: > + default: > + abort(); > + } > +} > + > +static void dump_qlist(fprintf_function func_fprintf, void *f, int > indentation, > + QList *list) > +{ > + const QListEntry *entry; > + int i = 0; > + > + for (entry = qlist_first(list); entry; entry = qlist_next(entry), i++) { > + qtype_code type = qobject_type(entry->value); > + bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST); > + const char *format = composite ? "%*s[%i]:\n" : "%*s[%i]: "; > + > + func_fprintf(f, format, indentation * 4, "", i); > + dump_qobject(func_fprintf, f, indentation + 1, entry->value); > + if (!composite) { > + func_fprintf(f, "\n"); > + } > + } > +} > + > +static void dump_qdict(fprintf_function func_fprintf, void *f, int > indentation, > + QDict *dict) > +{ > + const QDictEntry *entry; > + > + for (entry = qdict_first(dict); entry; entry = qdict_next(dict, entry)) { > + qtype_code type = qobject_type(entry->value); > + bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST); > + const char *format = composite ? "%*s%s:\n" : "%*s%s: "; > + char key[strlen(entry->key) + 1]; > + int i; > + > + /* replace dashes with spaces in key (variable) names */ > + for (i = 0; entry->key[i]; i++) { > + key[i] = entry->key[i] == '-' ? ' ' : entry->key[i]; > + } > + key[i] = 0; > + > + func_fprintf(f, format, indentation * 4, "", key); > + dump_qobject(func_fprintf, f, indentation + 1, entry->value); > + if (!composite) { > + func_fprintf(f, "\n"); > + } > + } > +} > + > +void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f, > + ImageInfoSpecific *info_spec) > +{ > + Error *local_err = NULL; > + QmpOutputVisitor *ov = qmp_output_visitor_new(); > + QObject *obj, *data; > + > + visit_type_ImageInfoSpecific(qmp_output_get_visitor(ov), &info_spec, > NULL, > + &local_err); > + obj = qmp_output_get_qobject(ov); > + assert(qobject_type(obj) == QTYPE_QDICT); > + data = qdict_get(qobject_to_qdict(obj), "data"); > + dump_qobject(func_fprintf, f, 0, data); > + qmp_output_visitor_cleanup(ov); > +} > + > void bdrv_image_info_dump(fprintf_function func_fprintf, void *f, > ImageInfo *info) > { > @@ -471,4 +587,9 @@ void bdrv_image_info_dump(fprintf_function func_fprintf, > void *f, > func_fprintf(f, "\n"); > } > } > + > + if (info->has_format_specific) { > + func_fprintf(f, "Format specific information:\n"); > + bdrv_image_info_specific_dump(func_fprintf, f, > info->format_specific); > + } > } > diff --git a/include/block/qapi.h b/include/block/qapi.h > index 0496cc9..9518ee4 100644 > --- a/include/block/qapi.h > +++ b/include/block/qapi.h > @@ -42,6 +42,8 @@ BlockStats *bdrv_query_stats(const BlockDriverState *bs); > > void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f, > QEMUSnapshotInfo *sn); > +void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f, > + ImageInfoSpecific *info_spec); > void bdrv_image_info_dump(fprintf_function func_fprintf, void *f, > ImageInfo *info); > #endif > diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c > index 563dd40..d90ae4a 100644 > --- a/qemu-io-cmds.c > +++ b/qemu-io-cmds.c > @@ -10,6 +10,7 @@ > > #include "qemu-io.h" > #include "block/block_int.h" > +#include "block/qapi.h" > #include "qemu/main-loop.h" > > #define CMD_NOFILE_OK 0x01 > @@ -1700,6 +1701,8 @@ static int info_f(BlockDriverState *bs, int argc, char > **argv) > printf("vm state offset: %s\n", s2); > > if (bdi.format_specific) { > + puts("Format specific information:");
Could use printf for more consistence. Fam > + bdrv_image_info_specific_dump(fprintf, stdout, bdi.format_specific); > qapi_free_ImageInfoSpecific(bdi.format_specific); > } > > -- > 1.8.3.1 > >