libfdisk: add JSON dump output
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
parent
0baeca2aef
commit
3c7fde5f92
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,31 +406,179 @@ 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 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;
|
||||
|
@ -438,7 +588,7 @@ int fdisk_script_write_file(struct fdisk_script *dp, FILE *f)
|
|||
assert(dp);
|
||||
assert(f);
|
||||
|
||||
DBG(SCRIPT, ul_debugobj(dp, "writing script to file"));
|
||||
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, ':');
|
||||
|
|
Loading…
Reference in New Issue