The branch main has been updated by mckusick:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=0d4642a67e59f8da5e00a05001c342bdad2a806f

commit 0d4642a67e59f8da5e00a05001c342bdad2a806f
Author:     Kirk McKusick <[email protected]>
AuthorDate: 2025-10-13 21:15:05 +0000
Commit:     Kirk McKusick <[email protected]>
CommitDate: 2025-10-13 21:15:51 +0000

    Add --libxo support for geom status and list sub commands.
    
    Submitted-by: Johan Söllvander
    MFC-after:    1 week
    Differential Revision: https://reviews.freebsd.org/D37615
---
 sbin/geom/Makefile    |   2 +-
 sbin/geom/core/geom.c | 232 +++++++++++++++++++++++++++++++++-----------------
 2 files changed, 157 insertions(+), 77 deletions(-)

diff --git a/sbin/geom/Makefile b/sbin/geom/Makefile
index 078503d3ae67..61561ef1ff1b 100644
--- a/sbin/geom/Makefile
+++ b/sbin/geom/Makefile
@@ -9,7 +9,7 @@ MAN=            geom.8
 CFLAGS+=       -I${.CURDIR} -I${.CURDIR}/core
 CFLAGS+=       -DGEOM_CLASS_DIR=\"${GEOM_CLASS_DIR}\"
 
-LIBADD=                geom util
+LIBADD=                geom util xo
 
 .if defined(RESCUE)
 .PATH: ${SRCTOP}/lib/geom/part \
diff --git a/sbin/geom/core/geom.c b/sbin/geom/core/geom.c
index b78021194ddd..496123f08274 100644
--- a/sbin/geom/core/geom.c
+++ b/sbin/geom/core/geom.c
@@ -49,9 +49,12 @@
 #include <assert.h>
 #include <libgeom.h>
 #include <geom.h>
+#include <libxo/xo.h>
 
 #include "misc/subr.h"
 
+#define GEOM_XO_VERSION "1"
+
 #ifdef STATIC_GEOM_CLASSES
 extern uint32_t gpart_version;
 extern struct g_command gpart_class_commands[];
@@ -513,6 +516,7 @@ run_command(int argc, char *argv[])
        gctl_free(req);
        if (verbose)
                printf("Done.\n");
+       xo_finish();
        exit(EXIT_SUCCESS);
 }
 
@@ -810,6 +814,10 @@ main(int argc, char *argv[])
        provider_name = NULL;
        tflag = false;
 
+       argc = xo_parse_args(argc, argv);
+       if (argc < 0)
+               return (argc);
+
        if (strcmp(getprogname(), "geom") == 0) {
                while ((ch = getopt(argc, argv, "hp:t")) != -1) {
                        switch (ch) {
@@ -831,6 +839,7 @@ main(int argc, char *argv[])
                 * Don't adjust argc and argv, it would break get_class().
                 */
        }
+       xo_set_version(GEOM_XO_VERSION);
 
        if (tflag && provider_name != NULL) {
                errx(EXIT_FAILURE,
@@ -839,6 +848,7 @@ main(int argc, char *argv[])
 
        if (provider_name != NULL) {
                list_one_geom_by_provider(provider_name);
+               xo_finish();
                return (0);
        }
 
@@ -882,29 +892,33 @@ find_geom(struct gclass *classp, const char *name)
 }
 
 static void
-list_one_provider(struct gprovider *pp, const char *prefix)
+list_one_provider(struct gprovider *pp, const char *padding)
 {
        struct gconfig *conf;
        char buf[5];
 
-       printf("Name: %s\n", pp->lg_name);
+       xo_emit("{Lcw:Name}{:Name}\n", pp->lg_name);
        humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
            HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
-       printf("%sMediasize: %jd (%s)\n", prefix, (intmax_t)pp->lg_mediasize,
-           buf);
-       printf("%sSectorsize: %u\n", prefix, pp->lg_sectorsize);
+       xo_emit("{P:/%s}{Lcw:Mediasize}{:Mediasize/%jd} ({N:/%s})\n",
+           padding, (intmax_t)pp->lg_mediasize, buf);
+       xo_emit("{P:/%s}{Lcw:Sectorsize}{:Sectorsize/%u} \n",
+           padding, pp->lg_sectorsize);
        if (pp->lg_stripesize > 0 || pp->lg_stripeoffset > 0) {
-               printf("%sStripesize: %ju\n", prefix, pp->lg_stripesize);
-               printf("%sStripeoffset: %ju\n", prefix, pp->lg_stripeoffset);
+               xo_emit("{P:/%s}{Lcw:Stripesize}{Stripesize/%ju}\n",
+                   padding, pp->lg_stripesize);
+               xo_emit("{P:/%s}{Lcw:Stripeoffset}{Stripeoffset/%ju}\n",
+                   padding, pp->lg_stripeoffset);
        }
-       printf("%sMode: %s\n", prefix, pp->lg_mode);
+       xo_emit("{P:/%s}{Lcw:Mode}{Mode}\n", padding, pp->lg_mode);
        LIST_FOREACH(conf, &pp->lg_config, lg_config) {
-               printf("%s%s: %s\n", prefix, conf->lg_name, conf->lg_val);
+               xo_emit("{P:/%s}{Lcwa:}{a:}\n", padding, conf->lg_name,
+                   conf->lg_name, conf->lg_val);
        }
 }
 
 static void
-list_one_consumer(struct gconsumer *cp, const char *prefix)
+list_one_consumer(struct gconsumer *cp, const char *padding)
 {
        struct gprovider *pp;
        struct gconfig *conf;
@@ -915,20 +929,24 @@ list_one_consumer(struct gconsumer *cp, const char 
*prefix)
        else {
                char buf[5];
 
-               printf("Name: %s\n", pp->lg_name);
+               xo_emit("{Lcw:Name}{:Name}\n", pp->lg_name);
                humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
                    HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
-               printf("%sMediasize: %jd (%s)\n", prefix,
-                   (intmax_t)pp->lg_mediasize, buf);
-               printf("%sSectorsize: %u\n", prefix, pp->lg_sectorsize);
+               xo_emit("{P:/%s}{Lcw:Mediasize}{:Mediasize/%jd} ({N:/%s})\n",
+                   padding, (intmax_t)pp->lg_mediasize, buf);
+               xo_emit("{P:/%s}{Lcw:Sectorsize}{:Sectorsize/%u}\n",
+                   padding, pp->lg_sectorsize);
                if (pp->lg_stripesize > 0 || pp->lg_stripeoffset > 0) {
-                       printf("%sStripesize: %ju\n", prefix, 
pp->lg_stripesize);
-                       printf("%sStripeoffset: %ju\n", prefix, 
pp->lg_stripeoffset);
+                       xo_emit("{P:/%s}{Lcw:Stripesize}{:Stripesize/%ju}\n",
+                           padding, pp->lg_stripesize);
+                       xo_emit("{P:/%s}{Lcw:Stripeoffset}{:Stripesize/%ju}\n",
+                           padding, pp->lg_stripeoffset);
                }
-               printf("%sMode: %s\n", prefix, cp->lg_mode);
+               xo_emit("{P:/%s}{Lcw:Mode}{:Mode}\n", padding, pp->lg_mode);
        }
        LIST_FOREACH(conf, &cp->lg_config, lg_config) {
-               printf("%s%s: %s\n", prefix, conf->lg_name, conf->lg_val);
+               xo_emit("{P:/%s}{Lcwa:}{a:}\n", padding, conf->lg_name,
+                   conf->lg_name, conf->lg_val);
        }
 }
 
@@ -940,27 +958,36 @@ list_one_geom(struct ggeom *gp)
        struct gconfig *conf;
        unsigned n;
 
-       printf("Geom name: %s\n", gp->lg_name);
+       xo_emit("{Lcw:Geom name}{:Name}\n", gp->lg_name);
        LIST_FOREACH(conf, &gp->lg_config, lg_config) {
-               printf("%s: %s\n", conf->lg_name, conf->lg_val);
+               xo_emit("{Lcwa:}{a:}\n", conf->lg_name, conf->lg_name,
+                   conf->lg_val);
        }
        if (!LIST_EMPTY(&gp->lg_provider)) {
-               printf("Providers:\n");
+               xo_open_list("Providers");
+               xo_emit("{Tc:Providers}\n");
                n = 1;
                LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
-                       printf("%u. ", n++);
+                       xo_emit("{T:/%u} ", n++);
+                       xo_open_instance("provider");
                        list_one_provider(pp, "   ");
+                       xo_close_instance("provider");
                }
+               xo_close_list("Providers");
        }
        if (!LIST_EMPTY(&gp->lg_consumer)) {
-               printf("Consumers:\n");
+               xo_open_list("Consumers");
+               xo_emit("{Tc:Consumers}\n");
                n = 1;
                LIST_FOREACH(cp, &gp->lg_consumer, lg_consumer) {
-                       printf("%u. ", n++);
+                       xo_emit("{T:/%u} ", n++);
+                       xo_open_instance("consumer");
                        list_one_consumer(cp, "   ");
+                       xo_close_instance("consumer");
                }
+               xo_close_list("Consumers");
        }
-       printf("\n");
+       xo_emit("\n");
 }
 
 static void
@@ -978,8 +1005,10 @@ list_one_geom_by_provider(const char *provider_name)
        if (gp == NULL)
                errx(EXIT_FAILURE, "Cannot find provider '%s'.", provider_name);
 
-       printf("Geom class: %s\n", gp->lg_class->lg_name);
+       xo_open_container("Geom");
+       xo_emit("{Lwc:Geom class}{:Class}\n", gp->lg_class->lg_name);
        list_one_geom(gp);
+       xo_close_container("Geom");
 }
 
 static void
@@ -1038,14 +1067,20 @@ std_list(struct gctl_req *req, unsigned flags __unused)
                                    "an instance named '%s'.",
                                    gclass_name, name);
                        }
+                       xo_open_container("Geom");
                        list_one_geom(gp);
+                       xo_close_container("Geom");
                }
        } else {
+               xo_open_list("Geoms");
                LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
                        if (LIST_EMPTY(&gp->lg_provider) && !all)
                                continue;
+                       xo_open_instance("geom");
                        list_one_geom(gp);
+                       xo_close_instance("geom");
                }
+               xo_close_list("Geoms");
        }
        geom_deletetree(&mesh);
 }
@@ -1115,34 +1150,24 @@ status_update_len_prs(struct ggeom *gp, int *name_len, 
int *status_len)
 }
 
 static char *
-status_one_consumer(struct gconsumer *cp)
+status_one_consumer(struct gconsumer *cp, const char *value)
 {
-       static char buf[256];
        struct gprovider *pp;
        struct gconfig *conf;
-       const char *state, *syncr;
+       char *ret;
 
        pp = cp->lg_provider;
        if (pp == NULL)
                return (NULL);
-       state = NULL;
-       syncr = NULL;
+       ret = NULL;
        LIST_FOREACH(conf, &cp->lg_config, lg_config) {
-               if (strcasecmp(conf->lg_name, "state") == 0)
-                       state = conf->lg_val;
-               if (strcasecmp(conf->lg_name, "synchronized") == 0)
-                       syncr = conf->lg_val;
-       }
-       if (state == NULL && syncr == NULL)
-               snprintf(buf, sizeof(buf), "%s", pp->lg_name);
-       else if (state != NULL && syncr != NULL) {
-               snprintf(buf, sizeof(buf), "%s (%s, %s)", pp->lg_name,
-                   state, syncr);
-       } else {
-               snprintf(buf, sizeof(buf), "%s (%s)", pp->lg_name,
-                   state ? state : syncr);
+               if (strcasecmp(conf->lg_name, value) == 0)
+                       ret = conf->lg_val;
        }
-       return (buf);
+
+       if (ret == NULL)
+               return (NULL);
+       return (ret);
 }
 
 static void
@@ -1150,8 +1175,8 @@ status_one_geom(struct ggeom *gp, int script, int 
name_len, int status_len)
 {
        struct gconsumer *cp;
        struct gconfig *conf;
-       const char *name, *status, *component;
-       int gotone;
+       const char *name, *status, *cstate, *csyncr;
+       int gotone, len;
 
        name = gp->lg_name;
        status = "N/A";
@@ -1161,21 +1186,49 @@ status_one_geom(struct ggeom *gp, int script, int 
name_len, int status_len)
                        break;
                }
        }
-       gotone = 0;
+       gotone = len = 0;
+       xo_open_instance("status");
        LIST_FOREACH(cp, &gp->lg_consumer, lg_consumer) {
-               component = status_one_consumer(cp);
-               if (component == NULL)
+               cstate = status_one_consumer(cp, "state");
+               csyncr = status_one_consumer(cp, "synchronized");
+               if (cstate == NULL && csyncr == NULL)
                        continue;
+               if (!gotone || script) {
+                       if (!gotone) {
+                               xo_emit("{:name/%*s}  {:status/%*s}  ",
+                                   name_len, name, status_len, status);
+                       } else {
+                               xo_emit("{d:name/%*s}  {d:status/%*s}  ",
+                                   name_len, name, status_len, status);
+                       }
+                       xo_open_list("components");
+               }
+
+               xo_open_instance("components");
+               if (cstate != NULL && csyncr != NULL) {
+                       xo_emit("{P:/%*s}{:compontent} ({:state}, 
{:synchronized})\n",
+                       len, "", cp->lg_provider->lg_name, cstate, csyncr);
+               } else if (cstate != NULL) {
+                       xo_emit("{P:/%*s}{:compontent} ({:state})\n",
+                       len, "", cp->lg_provider->lg_name, cstate);
+               } else {
+                       xo_emit("{P:/%*s}{:compontent} ({:synchronized})\n",
+                       len, "", cp->lg_provider->lg_name, csyncr);
+               }
+               xo_close_instance("components");
                gotone = 1;
-               printf("%*s  %*s  %s\n", name_len, name, status_len, status,
-                   component);
-               if (!script)
-                       name = status = "";
+               if (!len && !script)
+                       len = name_len + status_len + 4;
        }
        if (!gotone) {
-               printf("%*s  %*s  %s\n", name_len, name, status_len, status,
-                   "N/A");
+               xo_emit("{:name/%*s}  {:status/%*s}  ", name_len, name, 
status_len, status);
+               xo_open_list("components");
+               xo_open_instance("components");
+               xo_emit("{P:/%*s}{d:compontent}\n", len, "", "N/A");
+               xo_close_instance("components");
        }
+       xo_close_list("components");
+       xo_close_instance("status");
 }
 
 static void
@@ -1184,9 +1237,10 @@ status_one_geom_prs(struct ggeom *gp, int script, int 
name_len, int status_len)
        struct gprovider *pp;
        struct gconsumer *cp;
        struct gconfig *conf;
-       const char *name, *status, *component;
-       int gotone;
+       const char *name, *status, *cstate, *csyncr;
+       int gotone, len;
 
+       xo_open_instance("status");
        LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
                name = pp->lg_name;
                status = "N/A";
@@ -1202,22 +1256,50 @@ status_one_geom_prs(struct ggeom *gp, int script, int 
name_len, int status_len)
                                break;
                        }
                }
-               gotone = 0;
+               gotone = len = 0;
                LIST_FOREACH(cp, &gp->lg_consumer, lg_consumer) {
-                       component = status_one_consumer(cp);
-                       if (component == NULL)
+                       cstate = status_one_consumer(cp, "state");
+                       csyncr = status_one_consumer(cp, "synchronized");
+                       if (cstate == NULL && csyncr == NULL)
                                continue;
+
+                       if (!gotone || script) {
+                               if (!gotone) {
+                                       xo_emit("{:name/%*s}  {:status/%*s}  ",
+                                           name_len, name, status_len, status);
+                               } else {
+                                       xo_emit("{d:name/%*s}  {d:status/%*s}  
",
+                                           name_len, name, status_len, status);
+                               }
+                               xo_open_list("components");
+                       }
+
+                       xo_open_instance("component");
+                       if (cstate != NULL && csyncr != NULL) {
+                               xo_emit("{P:/%*s}{:compontent} ({:state}, 
{:synchronized})\n",
+                               len, "", cp->lg_provider->lg_name, cstate, 
csyncr);
+                       } else if (cstate != NULL) {
+                               xo_emit("{P:/%*s}{:compontent} ({:state})\n",
+                               len, "", cp->lg_provider->lg_name, cstate);
+                       } else {
+                               xo_emit("{P:/%*s}{:compontent} 
({:synchronized})\n",
+                               len, "", cp->lg_provider->lg_name, csyncr);
+                       }
+                       xo_close_instance("component");
                        gotone = 1;
-                       printf("%*s  %*s  %s\n", name_len, name,
-                           status_len, status, component);
-                       if (!script)
-                               name = status = "";
+                       if (!len && !script)
+                               len = name_len + status_len + 4;
                }
                if (!gotone) {
-                       printf("%*s  %*s  %s\n", name_len, name,
-                           status_len, status, "N/A");
+                       xo_emit("{:name/%*s}  {:status/%*s}  ", name_len, name, 
status_len, status);
+                       xo_open_list("components");
+                       xo_open_instance("components");
+                       xo_emit("{P:/%*s}{d:compontent}\n", len, "", "N/A");
+                       xo_close_instance("components");
                }
+               xo_close_list("components");
        }
+       xo_close_instance("status");
 }
 
 static void
@@ -1240,13 +1322,9 @@ std_status(struct gctl_req *req, unsigned flags __unused)
        all = gctl_get_int(req, "all");
        geoms = gctl_get_int(req, "geoms");
        script = gctl_get_int(req, "script");
-       if (script) {
-               name_len = 0;
-               status_len = 0;
-       } else {
-               name_len = strlen("Name");
-               status_len = strlen("Status");
-       }
+       name_len = strlen("Name");
+       status_len = strlen("Status");
+
        if (nargs > 0) {
                for (i = 0, n = 0; i < nargs; i++) {
                        name = gctl_get_ascii(req, "arg%d", i);
@@ -1282,9 +1360,10 @@ std_status(struct gctl_req *req, unsigned flags __unused)
                        goto end;
        }
        if (!script) {
-               printf("%*s  %*s  %s\n", name_len, "Name", status_len, "Status",
-                   "Components");
+               xo_emit("{T:/%*s}  {T:/%*s}  {T:Components}\n",
+                   name_len, "Name", status_len, "Status");
        }
+       xo_open_list("status");
        if (nargs > 0) {
                for (i = 0; i < nargs; i++) {
                        name = gctl_get_ascii(req, "arg%d", i);
@@ -1312,6 +1391,7 @@ std_status(struct gctl_req *req, unsigned flags __unused)
                        }
                }
        }
+       xo_close_list("status");
 end:
        geom_deletetree(&mesh);
 }

Reply via email to