diff options
author | Karel Zak | 2015-06-15 13:18:09 +0200 |
---|---|---|
committer | Karel Zak | 2015-06-15 13:18:09 +0200 |
commit | 3c7fde5f922ce67ba773487e39f44db1eaa60f5e (patch) | |
tree | af07b8a1e8169260ec1ea1ab02b71d0ec3988e75 /libfdisk/src/script.c | |
parent | libfdisk: rename script functions to improve readability (diff) | |
download | kernel-qcow2-util-linux-3c7fde5f922ce67ba773487e39f44db1eaa60f5e.tar.gz kernel-qcow2-util-linux-3c7fde5f922ce67ba773487e39f44db1eaa60f5e.tar.xz kernel-qcow2-util-linux-3c7fde5f922ce67ba773487e39f44db1eaa60f5e.zip |
libfdisk: add JSON dump output
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libfdisk/src/script.c')
-rw-r--r-- | libfdisk/src/script.c | 189 |
1 files changed, 179 insertions, 10 deletions
diff --git a/libfdisk/src/script.c b/libfdisk/src/script.c index 452dd2d75..e582e1717 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, ':'); |