Date: Sun, 15 Sep 2019 02:36:51 +0000 (UTC) From: Kyle Evans <kevans@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r352344 - stable/12/sbin/bectl Message-ID: <201909150236.x8F2apXf006450@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kevans Date: Sun Sep 15 02:36:50 2019 New Revision: 352344 URL: https://svnweb.freebsd.org/changeset/base/352344 Log: MFC r351813, r352092: bectl(8) list sorting MFC r351813: bectl(8): implement sorting for 'bectl list' output Allow 'bectl list' to sort output by a given property name. The property name is passed in using a command-line flag, '-c' for ascending order and '-C' for descending order. The properties allowed to sort by are: - name (the default output, even if '-c' or '-C' are not used) - creation - origin - used - usedds - usedsnap - usedrefreserv The default output for 'bectl list' is now ascending alphabetical order of BE name. To sort by creation time from earliest to latest, the command would be 'bectl list -c creation' MFC r352092: bectl(8): initialize reverse earlier This turns into a warning in GCC 4.2 that 'reverse' may be used uninitialized in this function. While I don't immediately see where it's deciding this from (there's only two paths that make column != NULL, and they both set reverse), initializing reverse earlier is good for clarity. Modified: stable/12/sbin/bectl/bectl.8 stable/12/sbin/bectl/bectl.c stable/12/sbin/bectl/bectl_list.c Directory Properties: stable/12/ (props changed) Modified: stable/12/sbin/bectl/bectl.8 ============================================================================== --- stable/12/sbin/bectl/bectl.8 Sun Sep 15 02:17:30 2019 (r352343) +++ stable/12/sbin/bectl/bectl.8 Sun Sep 15 02:36:50 2019 (r352344) @@ -18,7 +18,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 9, 2019 +.Dd September 14, 2019 .Dt BECTL 8 .Os .Sh NAME @@ -57,6 +57,9 @@ .Nm .Cm list .Op Fl aDHs +.Op Fl c Ar property +.Op Fl C Ar property +.Oo Bro Fl c Ar property | Fl C Ar property Brc Oc .Nm .Cm mount .Ar beName @@ -234,7 +237,12 @@ generated by .El .Pp All default parameters may be overwritten. -.It Cm list Op Fl aDHs +.It Xo +.Cm list +.Op Fl DHas +.Oo Bro Fl c Ar property | Fl C Ar property Brc Oc +.Xc +.Pp Display all boot environments. The .Em Active @@ -245,21 +253,44 @@ active on reboot or both .Pq Em \&NR . .Pp -If -.Fl a -is used, display all datasets. -If -.Fl D -is used, display the full space usage for each boot environment, assuming all +.Bl -tag -width indent +.It Fl a +Display all datasets. +.It Fl D +Display the full space usage for each boot environment, assuming all other boot environments were destroyed. -The -.Fl H -option is used for scripting. -It does not print headers and separate fields by a single tab instead of +.It Fl H +Used for scripting. +Do not print headers and separate fields by a single tab instead of arbitrary white space. -If +.It Fl s +Display all snapshots as well. +.It Fl c Ar property +Sort boot environments by given property name. +The following properties are supported: +.Pp +.Bl -tag -width 4n -offset indent -compact +.It name (default output) +.It creation +.It origin +.It used +.It usedds +.It usedsnap +.It usedrefreserv +.El +.It Fl C Ar property +Same as the +.Fl c +option, but displays in descending order. +.El +.Pp +The +.Fl D +option is ignored when either the .Fl s -is used, display all snapshots as well. +or +.Fl a +option is used. .It Cm mount Ar beName Op Ar mountpoint Temporarily mount the boot environment. Mount at the specified Modified: stable/12/sbin/bectl/bectl.c ============================================================================== --- stable/12/sbin/bectl/bectl.c Sun Sep 15 02:17:30 2019 (r352343) +++ stable/12/sbin/bectl/bectl.c Sun Sep 15 02:36:50 2019 (r352344) @@ -80,7 +80,7 @@ usage(bool explicit) "\tbectl jail {-b | -U} [{-o key=value | -u key}]... " "{jailID | jailName}\n" "\t bootenv [utility [argument ...]]\n" - "\tbectl list [-DHas]\n" + "\tbectl list [-DHas] [{-c property | -C property}]\n" "\tbectl mount beName [mountpoint]\n" "\tbectl rename origBeName newBeName\n" "\tbectl {ujail | unjail} {jailID | jailName} bootenv\n" Modified: stable/12/sbin/bectl/bectl_list.c ============================================================================== --- stable/12/sbin/bectl/bectl_list.c Sun Sep 15 02:17:30 2019 (r352343) +++ stable/12/sbin/bectl/bectl_list.c Sun Sep 15 02:36:50 2019 (r352344) @@ -38,6 +38,12 @@ __FBSDID("$FreeBSD$"); #include "bectl.h" +struct sort_column { + char *name; + char *val; + nvlist_t *nvl; +}; + struct printc { int active_colsz_def; int be_colsz; @@ -324,6 +330,74 @@ print_headers(nvlist_t *props, struct printc *pc) printf("\n"); } +/* + * Sort the given nvlist of boot environments by property. + */ +static int +prop_list_sort(nvlist_t *props, char *property, bool reverse) +{ + nvpair_t *nvp; + nvlist_t *nvl; + int i, nvp_count; + uint64_t lval, rval; + struct sort_column sc_prev, sc_next; + + /* a temporary list to work with */ + nvlist_dup(props, &nvl, 0); + + nvp_count = fnvlist_num_pairs(nvl); + for (i = 0; i < nvp_count; i++) { + + nvp = nvlist_next_nvpair(nvl, NULL); + nvpair_value_nvlist(nvp, &sc_prev.nvl); + nvlist_lookup_string(sc_prev.nvl, "name", &sc_prev.name); + nvlist_lookup_string(sc_prev.nvl, property, &sc_prev.val); + + while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) { + + nvpair_value_nvlist(nvp, &sc_next.nvl); + nvlist_lookup_string(sc_next.nvl, "name", &sc_next.name); + nvlist_lookup_string(sc_next.nvl, property, &sc_next.val); + + /* properties that use numerical comparison */ + if (strcmp(property, "creation") == 0 || + strcmp(property, "used") == 0 || + strcmp(property, "usedds") == 0 || + strcmp(property, "usedsnap") == 0 || + strcmp(property, "usedrefreserv") == 0) { + + lval = strtoull(sc_prev.val, NULL, 10); + rval = strtoull(sc_next.val, NULL, 10); + + if ((lval < rval && reverse) || + (lval > rval && !reverse)) + sc_prev = sc_next; + } + + /* properties that use string comparison */ + else if (strcmp(property, "name") == 0 || + strcmp(property, "origin") == 0) { + if ((strcmp(sc_prev.val, sc_next.val) < 0 && reverse) || + (strcmp(sc_prev.val, sc_next.val) > 0 && !reverse)) + sc_prev = sc_next; + } + } + + /* + * The 'props' nvlist has been created to only have unique names. + * When a name is added, any existing nvlist's with the same name + * will be removed. Eventually, all existing nvlist's are replaced + * in sorted order. + */ + nvlist_add_nvlist(props, sc_prev.name, sc_prev.nvl); + nvlist_remove_all(nvl, sc_prev.name); + } + + be_prop_list_free(nvl); + + return 0; +} + int bectl_cmd_list(int argc, char *argv[]) { @@ -331,12 +405,15 @@ bectl_cmd_list(int argc, char *argv[]) nvpair_t *cur; nvlist_t *dsprops, *props; int opt, printed; - boolean_t active_now, active_reboot; + char *column; + bool reverse; + column = NULL; props = NULL; printed = 0; bzero(&pc, sizeof(pc)); - while ((opt = getopt(argc, argv, "aDHs")) != -1) { + reverse = false; + while ((opt = getopt(argc, argv, "aDHsc:C:")) != -1) { switch (opt) { case 'a': pc.show_all_datasets = true; @@ -350,6 +427,18 @@ bectl_cmd_list(int argc, char *argv[]) case 's': pc.show_snaps = true; break; + case 'c': + if (column != NULL) + free(column); + column = strdup(optarg); + reverse = false; + break; + case 'C': + if (column != NULL) + free(column); + column = strdup(optarg); + reverse = true; + break; default: fprintf(stderr, "bectl list: unknown option '-%c'\n", optopt); @@ -374,44 +463,31 @@ bectl_cmd_list(int argc, char *argv[]) return (1); } + /* List boot environments in alphabetical order by default */ + if (column == NULL) + column = strdup("name"); + + prop_list_sort(props, column, reverse); + /* Force -D off if either -a or -s are specified */ if (pc.show_all_datasets || pc.show_snaps) pc.show_space = false; if (!pc.script_fmt) print_headers(props, &pc); - /* Do a first pass to print active and next active first */ - for (cur = nvlist_next_nvpair(props, NULL); cur != NULL; - cur = nvlist_next_nvpair(props, cur)) { - nvpair_value_nvlist(cur, &dsprops); - active_now = active_reboot = false; - nvlist_lookup_boolean_value(dsprops, "active", &active_now); - nvlist_lookup_boolean_value(dsprops, "nextboot", - &active_reboot); - if (!active_now && !active_reboot) - continue; - if (printed > 0 && (pc.show_all_datasets || pc.show_snaps)) - printf("\n"); - print_info(nvpair_name(cur), dsprops, &pc); - printed++; - } - - /* Now pull everything else */ + /* Print boot environments */ for (cur = nvlist_next_nvpair(props, NULL); cur != NULL; cur = nvlist_next_nvpair(props, cur)) { nvpair_value_nvlist(cur, &dsprops); - active_now = active_reboot = false; - nvlist_lookup_boolean_value(dsprops, "active", &active_now); - nvlist_lookup_boolean_value(dsprops, "nextboot", - &active_reboot); - if (active_now || active_reboot) - continue; if (printed > 0 && (pc.show_all_datasets || pc.show_snaps)) printf("\n"); + print_info(nvpair_name(cur), dsprops, &pc); printed++; } + + free(column); be_prop_list_free(props); return (0);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201909150236.x8F2apXf006450>