From: Karel Zak Date: Mon, 15 Jun 2015 11:18:09 +0000 (+0200) Subject: libfdisk: add JSON dump output X-Git-Tag: v2.27-rc1~147 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3c7fde5f922ce67ba773487e39f44db1eaa60f5e;p=thirdparty%2Futil-linux.git libfdisk: add JSON dump output Signed-off-by: Karel Zak --- diff --git a/libfdisk/docs/libfdisk-sections.txt b/libfdisk/docs/libfdisk-sections.txt index dd33255818..f69c6671c8 100644 --- a/libfdisk/docs/libfdisk-sections.txt +++ b/libfdisk/docs/libfdisk-sections.txt @@ -132,6 +132,7 @@ fdisk_script fdisk_new_script fdisk_new_script_from_file fdisk_ref_script +fdisk_script_enable_json fdisk_script_get_header fdisk_script_get_nlines fdisk_script_get_table diff --git a/libfdisk/src/libfdisk.h.in b/libfdisk/src/libfdisk.h.in index ba6539e23b..c83ae09757 100644 --- a/libfdisk/src/libfdisk.h.in +++ b/libfdisk/src/libfdisk.h.in @@ -624,6 +624,7 @@ void *fdisk_script_get_userdata(struct fdisk_script *dp); int fdisk_script_set_fgets(struct fdisk_script *dp, char *(*fn_fgets)(struct fdisk_script *, char *, size_t, FILE *)); int fdisk_script_read_context(struct fdisk_script *dp, struct fdisk_context *cxt); +int fdisk_script_enable_json(struct fdisk_script *dp, int json); int fdisk_script_write_file(struct fdisk_script *dp, FILE *f); int fdisk_script_read_file(struct fdisk_script *dp, FILE *f); int fdisk_script_read_line(struct fdisk_script *dp, FILE *f, char *buf, size_t bufsz); diff --git a/libfdisk/src/libfdisk.sym b/libfdisk/src/libfdisk.sym index 7cf5d2f0c7..c4d0a2526b 100644 --- a/libfdisk/src/libfdisk.sym +++ b/libfdisk/src/libfdisk.sym @@ -251,4 +251,5 @@ FDISK_2.27 { fdisk_script_set_userdata; fdisk_table_get_partition_by_partno; fdisk_get_disklabel_item; + fdisk_script_enable_json; } FDISK_2.26; diff --git a/libfdisk/src/script.c b/libfdisk/src/script.c index 452dd2d755..e582e1717f 100644 --- a/libfdisk/src/script.c +++ b/libfdisk/src/script.c @@ -1,6 +1,7 @@ #include "fdiskP.h" #include "strutils.h" +#include "carefulputc.h" /** * SECTION: script @@ -33,8 +34,9 @@ struct fdisk_script { /* parser's state */ size_t nlines; - int fmt; /* input format */ struct fdisk_label *label; + + unsigned int json : 1; /* JSON output */ }; @@ -404,41 +406,189 @@ int fdisk_script_read_context(struct fdisk_script *dp, struct fdisk_context *cxt rc = fdisk_script_set_header(dp, "unit", "sectors"); if (!rc && fdisk_is_label(cxt, GPT)) { + struct fdisk_labelitem item; char buf[64]; - snprintf(buf, sizeof(buf), "%ju", cxt->first_lba); - rc = fdisk_script_set_header(dp, "first-lba", buf); + rc = fdisk_get_disklabel_item(cxt, GPT_LABELITEM_FIRSTLBA, &item); + if (rc == 0) { + snprintf(buf, sizeof(buf), "%ju", item.data.num64); + rc = fdisk_script_set_header(dp, "first-lba", buf); + } + if (rc < 0) + goto done; - if (!rc) { - snprintf(buf, sizeof(buf), "%ju", cxt->last_lba); + rc = fdisk_get_disklabel_item(cxt, GPT_LABELITEM_LASTLBA, &item); + if (rc == 0) { + snprintf(buf, sizeof(buf), "%ju", item.data.num64); rc = fdisk_script_set_header(dp, "last-lba", buf); } + if (rc < 0) + goto done; } +done: DBG(SCRIPT, ul_debugobj(dp, "read context done [rc=%d]", rc)); return rc; } /** - * fdisk_script_write_file: + * fdisk_script_enable_json: * @dp: script - * @f: output file + * @json: 0 or 1 * - * Writes script @dp to the ile @f. + * Disable/Enable JSON output format. * * Returns: 0 on success, <0 on error. */ -int fdisk_script_write_file(struct fdisk_script *dp, FILE *f) +int fdisk_script_enable_json(struct fdisk_script *dp, int json) +{ + assert(dp); + + dp->json = json; + return 0; +} + +static void fput_indent(int indent, FILE *f) +{ + int i; + + for (i = 0; i <= indent; i++) + fputs(" ", f); +} + +static int write_file_json(struct fdisk_script *dp, FILE *f) { struct list_head *h; struct fdisk_partition *pa; struct fdisk_iter itr; const char *devname = NULL; + int ct = 0, indent = 0; assert(dp); assert(f); - DBG(SCRIPT, ul_debugobj(dp, "writing script to file")); + DBG(SCRIPT, ul_debugobj(dp, "writing json dump to file")); + + fputs("{\n", f); + + fput_indent(indent, f); + fputs("\"partitiontable\": {\n", f); + indent++; + + /* script headers */ + list_for_each(h, &dp->headers) { + struct fdisk_scriptheader *fi = list_entry(h, struct fdisk_scriptheader, headers); + const char *name = fi->name; + int num = 0; + + if (strcmp(name, "first-lba") == 0) { + name = "firstlba"; + num = 1; + } else if (strcmp(name, "last-lba") == 0) { + name = "lastlba"; + num = 1; + } else if (strcmp(name, "label-id") == 0) + name = "id"; + + fput_indent(indent, f); + fputs_quoted_lower(name, f); + fputs(": ", f); + if (!num) + fputs_quoted(fi->data, f); + else + fputs(fi->data, f); + if (!dp->table && fi == list_last_entry(&dp->headers, struct fdisk_scriptheader, headers)) + fputc('\n', f); + else + fputs(",\n", f); + + if (strcmp(name, "device") == 0) + devname = fi->data; + } + + + if (!dp->table) { + DBG(SCRIPT, ul_debugobj(dp, "script table empty")); + goto done; + } + + DBG(SCRIPT, ul_debugobj(dp, "%zu entries", fdisk_table_get_nents(dp->table))); + + fput_indent(indent, f); + fputs("\"partitions\": [\n", f); + indent++; + + fdisk_reset_iter(&itr, FDISK_ITER_FORWARD); + while (fdisk_table_next_partition(dp->table, &itr, &pa) == 0) { + char *p = NULL; + + ct++; + fput_indent(indent, f); + fputc('{', f); + if (devname) + p = fdisk_partname(devname, pa->partno + 1); + if (p) { + DBG(SCRIPT, ul_debugobj(dp, "write %s entry", p)); + fputs("\"node\": ", f); + fputs_quoted(p, f); + } + + if (fdisk_partition_has_start(pa)) + fprintf(f, ", \"start\": %ju", pa->start); + if (fdisk_partition_has_size(pa)) + fprintf(f, ", \"size\": %ju", pa->size); + + if (pa->type && fdisk_parttype_get_string(pa->type)) + fprintf(f, ", \"type\": \"%s\"", fdisk_parttype_get_string(pa->type)); + else if (pa->type) + fprintf(f, ", \"type\": \"%x\"", fdisk_parttype_get_code(pa->type)); + + if (pa->uuid) + fprintf(f, ", \"uuid\": \"%s\"", pa->uuid); + if (pa->name && *pa->name) { + fputs(", \"name\": ", f), + fputs_quoted(pa->name, f); + } + + /* for MBR attr=80 means bootable */ + if (pa->attrs) { + struct fdisk_label *lb = script_get_label(dp); + + if (!lb || fdisk_label_get_type(lb) != FDISK_DISKLABEL_DOS) + fprintf(f, ", \"attrs\": \"%s\"", pa->attrs); + } + if (fdisk_partition_is_bootable(pa)) + fprintf(f, ", \"bootable\": true"); + + if (ct < fdisk_table_get_nents(dp->table)) + fputs("},\n", f); + else + fputs("}\n", f); + } + + indent--; + fput_indent(indent, f); + fputs("]\n", f); +done: + indent--; + fput_indent(indent, f); + fputs("}\n}\n", f); + + DBG(SCRIPT, ul_debugobj(dp, "write script done")); + return 0; +} + +static int write_file_sfdisk(struct fdisk_script *dp, FILE *f) +{ + struct list_head *h; + struct fdisk_partition *pa; + struct fdisk_iter itr; + const char *devname = NULL; + + assert(dp); + assert(f); + + DBG(SCRIPT, ul_debugobj(dp, "writing sfdisk-like script to file")); /* script headers */ list_for_each(h, &dp->headers) { @@ -500,6 +650,25 @@ int fdisk_script_write_file(struct fdisk_script *dp, FILE *f) return 0; } +/** + * fdisk_script_write_file: + * @dp: script + * @f: output file + * + * Writes script @dp to the ile @f. + * + * Returns: 0 on success, <0 on error. + */ +int fdisk_script_write_file(struct fdisk_script *dp, FILE *f) +{ + assert(dp); + + if (dp->json) + return write_file_json(dp, f); + + return write_file_sfdisk(dp, f); +} + static inline int is_header_line(const char *s) { const char *p = strchr(s, ':');