]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: add JSON dump output
authorKarel Zak <kzak@redhat.com>
Mon, 15 Jun 2015 11:18:09 +0000 (13:18 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 15 Jun 2015 11:18:09 +0000 (13:18 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
libfdisk/docs/libfdisk-sections.txt
libfdisk/src/libfdisk.h.in
libfdisk/src/libfdisk.sym
libfdisk/src/script.c

index dd33255818a9afa574395df55754d28d2f40372f..f69c6671c894540b9d12657c206daeef25b49c51 100644 (file)
@@ -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
index ba6539e23bb336e9dd9aa254ee69deebee4071ee..c83ae09757b1f9c94176622f21e462ab9dd98c98 100644 (file)
@@ -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);
index 7cf5d2f0c7082f355f3eff2e609dfb51ea317847..c4d0a2526b6b7c7e503cd4236608f6e069c5f77f 100644 (file)
@@ -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;
index 452dd2d755866f3ed02b161dbb37454138ec6964..e582e1717f2d47ce1f8f249df481d472d8ed6a98 100644 (file)
@@ -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, ':');