The branch main has been updated by imp:

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

commit b2b8fa1a64af81e940d7b3ab71fd4c583b4abe0f
Author:     Nathan Huff <nh...@acm.org>
AuthorDate: 2024-04-29 04:59:18 +0000
Commit:     Warner Losh <i...@freebsd.org>
CommitDate: 2024-04-29 14:22:39 +0000

    Add libxo support to du
    
    Convert du to use libxo enabling structured output.
    
    [[ minor style fixes by imp ]]
    
    Signed-off-by: Nathan Huff <nh...@acm.org>
    Reviewed by: imp
    Pull Request: https://github.com/freebsd/freebsd-src/pull/1145
---
 usr.bin/du/Makefile |  2 +-
 usr.bin/du/du.1     | 12 ++++++++++-
 usr.bin/du/du.c     | 57 ++++++++++++++++++++++++++++++++++-------------------
 3 files changed, 49 insertions(+), 22 deletions(-)

diff --git a/usr.bin/du/Makefile b/usr.bin/du/Makefile
index 38f638a04de6..7fb61d0423df 100644
--- a/usr.bin/du/Makefile
+++ b/usr.bin/du/Makefile
@@ -3,7 +3,7 @@
 
 PACKAGE=       runtime
 PROG=  du
-LIBADD=        util
+LIBADD=        xo util
 
 HAS_TESTS=
 SUBDIR.${MK_TESTS}+=   tests
diff --git a/usr.bin/du/du.1 b/usr.bin/du/du.1
index 931ca137ee9b..568fded38073 100644
--- a/usr.bin/du/du.1
+++ b/usr.bin/du/du.1
@@ -25,7 +25,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd August 1, 2019
+.Dd April 29, 2024
 .Dt DU 1
 .Os
 .Sh NAME
@@ -33,6 +33,7 @@
 .Nd display disk usage statistics
 .Sh SYNOPSIS
 .Nm
+.Op Fl -libxo
 .Op Fl Aclnx
 .Op Fl H | L | P
 .Op Fl g | h | k | m
@@ -52,6 +53,13 @@ the current directory is displayed.
 .Pp
 The options are as follows:
 .Bl -tag -width indent
+.It Fl -libxo
+Generate output via
+.Xr libxo 3
+in a selection of different human and machine readable formats.
+See
+.Xr xo_parse_args 3
+for details on command line arguments.
 .It Fl A
 Display the apparent size instead of the disk usage.
 This can be helpful when operating on compressed volumes or sparse files.
@@ -216,6 +224,8 @@ Also display a grand total at the end:
 .Xr df 1 ,
 .Xr chflags 2 ,
 .Xr fts 3 ,
+.Xr libxo 3 ,
+.Xr xo_parse_args 3 ,
 .Xr symlink 7 ,
 .Xr quot 8
 .Sh STANDARDS
diff --git a/usr.bin/du/du.c b/usr.bin/du/du.c
index cda2470ccca9..96ad7c037dfd 100644
--- a/usr.bin/du/du.c
+++ b/usr.bin/du/du.c
@@ -48,6 +48,7 @@
 #include <string.h>
 #include <sysexits.h>
 #include <unistd.h>
+#include <libxo/xo.h>
 
 #define SI_OPT (CHAR_MAX + 1)
 
@@ -62,7 +63,7 @@ struct ignentry {
 
 static int     linkchk(FTSENT *);
 static void    usage(void);
-static void    prthumanval(int64_t);
+static void    prthumanval(const char *, int64_t);
 static void    ignoreadd(const char *);
 static void    ignoreclean(void);
 static int     ignorep(FTSENT *);
@@ -107,6 +108,10 @@ main(int argc, char *argv[])
        depth = INT_MAX;
        SLIST_INIT(&ignores);
 
+       argc = xo_parse_args(argc, argv);
+       if (argc < 0)
+               exit(EX_USAGE);
+
        while ((ch = getopt_long(argc, argv, "+AB:HI:LPasd:cghklmnrt:x",
            long_options, NULL)) != -1)
                switch (ch) {
@@ -117,7 +122,7 @@ main(int argc, char *argv[])
                        errno = 0;
                        cblocksize = atoi(optarg);
                        if (errno == ERANGE || cblocksize <= 0) {
-                               warnx("invalid argument to option B: %s",
+                               xo_warnx("invalid argument to option B: %s",
                                    optarg);
                                usage();
                        }
@@ -147,7 +152,7 @@ main(int argc, char *argv[])
                        errno = 0;
                        depth = atoi(optarg);
                        if (errno == ERANGE || depth < 0) {
-                               warnx("invalid argument to option d: %s",
+                               xo_warnx("invalid argument to option d: %s",
                                    optarg);
                                usage();
                        }
@@ -181,7 +186,7 @@ main(int argc, char *argv[])
                case 't' :
                        if (expand_number(optarg, &threshold) != 0 ||
                            threshold == 0) {
-                               warnx("invalid threshold: %s", optarg);
+                               xo_warnx("invalid threshold: %s", optarg);
                                usage();
                        } else if (threshold < 0)
                                threshold_sign = -1;
@@ -254,6 +259,8 @@ main(int argc, char *argv[])
        if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL)
                err(1, "fts_open");
 
+       xo_open_container("disk-usage-information");
+       xo_open_list("paths");
        while (errno = 0, (p = fts_read(fts)) != NULL) {
                switch (p->fts_info) {
                case FTS_D:                     /* Ignore. */
@@ -273,15 +280,18 @@ main(int argc, char *argv[])
                        if (p->fts_level <= depth && threshold <=
                            threshold_sign * howmany(p->fts_bignum *
                            cblocksize, blocksize)) {
+                               xo_open_instance("paths");
                                if (hflag > 0) {
-                                       prthumanval(p->fts_bignum);
-                                       (void)printf("\t%s\n", p->fts_path);
+                                       prthumanval("{:blocks/%4s}",
+                                           p->fts_bignum);
+                                       xo_emit("\t{:path/%s}\n", p->fts_path);
                                } else {
-                                       (void)printf("%jd\t%s\n",
+                                       xo_emit("{:blocks/%jd}\t{:path/%s}\n",
                                            (intmax_t)howmany(p->fts_bignum *
                                            cblocksize, blocksize),
                                            p->fts_path);
                                }
+                               xo_close_instance("paths");
                        }
                        if (info) {
                                info = 0;
@@ -293,7 +303,7 @@ main(int argc, char *argv[])
                case FTS_DNR:                   /* Warn, continue. */
                case FTS_ERR:
                case FTS_NS:
-                       warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
+                       xo_warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
                        rval = 1;
                        break;
                default:
@@ -309,36 +319,43 @@ main(int argc, char *argv[])
                            howmany(p->fts_statp->st_blocks, cblocksize);
 
                        if (aflag || p->fts_level == 0) {
+                               xo_open_instance("paths");
                                if (hflag > 0) {
-                                       prthumanval(curblocks);
-                                       (void)printf("\t%s\n", p->fts_path);
+                                       prthumanval("{:blocks/%4s}", curblocks);
+                                       xo_emit("\t{:path/%s}\n", p->fts_path);
                                } else {
-                                       (void)printf("%jd\t%s\n",
+                                       xo_emit("{:blocks/%jd}\t{:path/%s}\n",
                                            (intmax_t)howmany(curblocks *
                                            cblocksize, blocksize),
                                            p->fts_path);
                                }
+                               xo_close_instance("paths");
                        }
 
                        p->fts_parent->fts_bignum += curblocks;
                }
                savednumber = p->fts_parent->fts_bignum;
        }
+       xo_close_list("paths");
 
        if (errno)
-               err(1, "fts_read");
+               xo_err(1, "fts_read");
 
        if (cflag) {
                if (hflag > 0) {
-                       prthumanval(savednumber);
-                       (void)printf("\ttotal\n");
+                       prthumanval("{:total-blocks/%4s}\ttotal\n",
+                           savednumber);
                } else {
-                       (void)printf("%jd\ttotal\n", (intmax_t)howmany(
+                       xo_emit("{:total-blocks/%jd}\ttotal\n",
+                           (intmax_t)howmany(
                            savednumber * cblocksize, blocksize));
                }
        }
 
        ignoreclean();
+       xo_close_container("disk-usage-information");
+       if (xo_finish() < 0)
+               xo_err(1, "stdout");
        exit(rval);
 }
 
@@ -392,7 +409,7 @@ linkchk(FTSENT *p)
 
                if (new_buckets == NULL) {
                        stop_allocating = 1;
-                       warnx("No more memory for tracking hard links");
+                       xo_warnx("No more memory for tracking hard links");
                } else {
                        for (i = 0; i < number_buckets; i++) {
                                while (buckets[i] != NULL) {
@@ -458,7 +475,7 @@ linkchk(FTSENT *p)
                le = malloc(sizeof(struct links_entry));
        if (le == NULL) {
                stop_allocating = 1;
-               warnx("No more memory for tracking hard links");
+               xo_warnx("No more memory for tracking hard links");
                return (0);
        }
        le->dev = st->st_dev;
@@ -474,7 +491,7 @@ linkchk(FTSENT *p)
 }
 
 static void
-prthumanval(int64_t bytes)
+prthumanval(const char *fmt, int64_t bytes)
 {
        char buf[5];
        int flags;
@@ -488,13 +505,13 @@ prthumanval(int64_t bytes)
 
        humanize_number(buf, sizeof(buf), bytes, "", HN_AUTOSCALE, flags);
 
-       (void)printf("%4s", buf);
+       xo_emit(fmt, buf);
 }
 
 static void
 usage(void)
 {
-       (void)fprintf(stderr,
+       xo_error(
                "usage: du [-Aclnx] [-H | -L | -P] [-g | -h | -k | -m] "
                "[-a | -s | -d depth] [-B blocksize] [-I mask] "
                "[-t threshold] [file ...]\n");

Reply via email to