]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
blkid: add json output format
authorThomas Weißschuh <thomas.weissschuh@linutronix.de>
Wed, 6 Mar 2024 16:36:52 +0000 (17:36 +0100)
committerThomas Weißschuh <thomas.weissschuh@linutronix.de>
Thu, 7 Mar 2024 07:27:53 +0000 (08:27 +0100)
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
bash-completion/blkid
misc-utils/blkid.8.adoc
misc-utils/blkid.c
tests/expected/blkid/output-json-cache [new file with mode: 0644]
tests/expected/blkid/output-json-probe [new file with mode: 0644]
tests/ts/blkid/output

index 74de34284ca2163df14abde8083e919fc4fd7dda..581a90d3d2f55ba7009f842b2724ba63968ea441 100644 (file)
@@ -13,7 +13,7 @@ _blkid_module()
                        return 0
                        ;;
                '-o'|'--output')
-                       COMPREPLY=( $(compgen -W "value device export full" -- $cur) )
+                       COMPREPLY=( $(compgen -W "value device export full json" -- $cur) )
                        return 0
                        ;;
                '-s'|'--match-tag')
index 5e8002d73d317e86ed9abdc8a798dc6e2ebd1ed5..3386f47ef30ac9cf5076d0a209aec0280953d80e 100644 (file)
@@ -111,6 +111,8 @@ This output format is *DEPRECATED*.
 print key=value pairs for easy import into the environment; this output format is automatically enabled when I/O Limits (*--info* option) are requested.
 +
 The non-printing characters are encoded by ^ and M- notation and all potentially unsafe characters are escaped.
+*json*;;
+Print the tags entries in JSON objects.
 
 *-O*, *--offset* _offset_::
 Probe at the given _offset_ (only useful with *--probe*). This option can be used together with the *--info* option.
index bea5778fd9ad9d561a15cff9dc17d99caab1fcec..5381d14f72408903e95fb6a82582a6f91573dd63 100644 (file)
@@ -25,6 +25,7 @@
 #define OUTPUT_PRETTY_LIST     (1 << 3)                /* deprecated */
 #define OUTPUT_UDEV_LIST       (1 << 4)                /* deprecated */
 #define OUTPUT_EXPORT_LIST     (1 << 5)
+#define OUTPUT_JSON            (1 << 6)
 
 #define BLKID_EXIT_NOTFOUND    2       /* token or device not found */
 #define BLKID_EXIT_OTHER       4       /* bad usage or other error */
 #include "xalloc.h"
 
 #include "sysfs.h"
+#include "jsonwrt.h"
 
 struct blkid_control {
        int output;
        uintmax_t offset;
        uintmax_t size;
        char *show[128];
+       struct ul_jsonwrt *json_fmt;
        unsigned int
                eval:1,
                gc:1,
@@ -81,7 +84,7 @@ static void __attribute__((__noreturn__)) usage(void)
        fputs(_(        " -d, --no-encoding          don't encode non-printing characters\n"), out);
        fputs(_(        " -g, --garbage-collect      garbage collect the blkid cache\n"), out);
        fputs(_(        " -o, --output <format>      output format; can be one of:\n"
-                       "                              value, device, export or full; (default: full)\n"), out);
+                       "                              value, device, export, json or full; (default: full)\n"), out);
        fputs(_(        " -k, --list-filesystems     list all known filesystems/RAIDs and exit\n"), out);
        fputs(_(        " -s, --match-tag <tag>      show specified tag(s) (default show all tags)\n"), out);
        fputs(_(        " -t, --match-token <token>  find device with a specific token (NAME=value pair)\n"), out);
@@ -333,6 +336,9 @@ static void print_value(const struct blkid_control *ctl, int num,
                safe_print(ctl, value, valsz, " \\\"'$`<>");
                fputs("\n", stdout);
 
+       } else if (ctl->output & OUTPUT_JSON) {
+               ul_jsonwrt_value_s_sized(ctl->json_fmt, name, value, valsz);
+
        } else {
                if (num == 1 && devname)
                        printf("%s:", devname);
@@ -366,6 +372,11 @@ static void print_tags(const struct blkid_control *ctl, blkid_dev dev)
                return;
        }
 
+       if (ctl->output == OUTPUT_JSON) {
+               ul_jsonwrt_init(ctl->json_fmt, stdout, 0);
+               ul_jsonwrt_open(ctl->json_fmt, NULL, UL_JSON_OBJECT);
+       }
+
        iter = blkid_tag_iterate_begin(dev);
        while (blkid_tag_next(iter, &type, &value) == 0) {
                if (ctl->show[0] && !has_item(ctl, type))
@@ -380,9 +391,13 @@ static void print_tags(const struct blkid_control *ctl, blkid_dev dev)
        }
        blkid_tag_iterate_end(iter);
 
+       if (ctl->output == OUTPUT_JSON)
+               ul_jsonwrt_close(ctl->json_fmt, UL_JSON_OBJECT);
+
        if (num > 1) {
                if (!(ctl->output & (OUTPUT_VALUE_ONLY | OUTPUT_UDEV_LIST |
-                                               OUTPUT_EXPORT_LIST)))
+                                               OUTPUT_EXPORT_LIST |
+                                               OUTPUT_JSON)))
                        printf("\n");
                first = 0;
        }
@@ -539,6 +554,11 @@ static int lowprobe_device(blkid_probe pr, const char *devname,
                /* add extra line between output from devices */
                fputc('\n', stdout);
 
+       if (ctl->output == OUTPUT_JSON) {
+               ul_jsonwrt_init(ctl->json_fmt, stdout, 0);
+               ul_jsonwrt_open(ctl->json_fmt, NULL, UL_JSON_OBJECT);
+       }
+
        if (nvals && (ctl->output & OUTPUT_DEVICE_ONLY)) {
                printf("%s\n", devname);
                goto done;
@@ -557,8 +577,12 @@ static int lowprobe_device(blkid_probe pr, const char *devname,
                first = 0;
 
        if (nvals >= 1 && !(ctl->output & (OUTPUT_VALUE_ONLY |
-                                       OUTPUT_UDEV_LIST | OUTPUT_EXPORT_LIST)))
+                                       OUTPUT_UDEV_LIST | OUTPUT_EXPORT_LIST |
+                                       OUTPUT_JSON)))
                printf("\n");
+
+       if (ctl->output == OUTPUT_JSON)
+               ul_jsonwrt_close(ctl->json_fmt, UL_JSON_OBJECT);
 done:
        if (rc == -2) {
                if (ctl->output & OUTPUT_UDEV_LIST)
@@ -664,7 +688,11 @@ static void free_types_list(char *list[])
 
 int main(int argc, char **argv)
 {
-       struct blkid_control ctl = { .output = OUTPUT_FULL, 0 };
+       struct ul_jsonwrt json_fmt;
+       struct blkid_control ctl = {
+               .output = OUTPUT_FULL,
+               .json_fmt = &json_fmt,
+       };
        blkid_cache cache = NULL;
        char **devices = NULL;
        char *search_type = NULL, *search_value = NULL;
@@ -777,6 +805,8 @@ int main(int argc, char **argv)
                                ctl.output = OUTPUT_UDEV_LIST;
                        else if (!strcmp(optarg, "export"))
                                ctl.output = OUTPUT_EXPORT_LIST;
+                       else if (!strcmp(optarg, "json"))
+                               ctl.output = OUTPUT_JSON;
                        else if (!strcmp(optarg, "full"))
                                ctl.output = 0;
                        else
diff --git a/tests/expected/blkid/output-json-cache b/tests/expected/blkid/output-json-cache
new file mode 100644 (file)
index 0000000..3d3c782
--- /dev/null
@@ -0,0 +1,4 @@
+{
+   "label": "tés\"'\n t",
+   "type": "cramfs"
+}
diff --git a/tests/expected/blkid/output-json-probe b/tests/expected/blkid/output-json-probe
new file mode 100644 (file)
index 0000000..b1c1248
--- /dev/null
@@ -0,0 +1,8 @@
+{
+   "label": "tés\"'\n t",
+   "fssize": "4096",
+   "version": "2",
+   "endianness": "LITTLE",
+   "type": "cramfs",
+   "usage": "filesystem"
+}
index ff77f1dbe2b65797938820a847502d66b85c9d67..d9dab58596cfc85f6e5a7cc0fccbdd359306d35b 100755 (executable)
@@ -33,7 +33,7 @@ _blkid() {
        "$TS_CMD_BLKID" --cache-file "$TS_OUTDIR"/blkid.cache "$@" "$outimg" | sed -e "s#$TS_OUTDIR/##"
 }
 
-for format in value udev export full device; do
+for format in value udev export full device json; do
        ts_init_subtest "$format-probe"
        _blkid --probe --output "$format" >> "$TS_OUTPUT"
        ts_finalize_subtest