diff --git a/sbin/bectl/bectl_list.c b/sbin/bectl/bectl_list.c --- a/sbin/bectl/bectl_list.c +++ b/sbin/bectl/bectl_list.c @@ -5,6 +5,8 @@ */ #include +#include +#include #include #include #include @@ -314,6 +316,13 @@ printf("\n"); } +static bool +prop_must_exist(char *property) +{ + + return (strcmp(property, "origin") != 0); +} + /* * Sort the given nvlist of boot environments by property. */ @@ -322,7 +331,7 @@ { nvpair_t *nvp; nvlist_t *nvl; - int i, nvp_count; + int error, i, nvp_count; uint64_t lval, rval; struct sort_column sc_prev, sc_next; @@ -335,13 +344,35 @@ 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); + error = nvlist_lookup_string(sc_prev.nvl, property, + &sc_prev.val); + if (error != 0) { + if (prop_must_exist(property)) { + fprintf(stderr, + "bectl list: sort field '%s' on BE '%s': %s\n", + property, sc_prev.name, strerror(error)); + return (error); + } + + 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); + error = nvlist_lookup_string(sc_next.nvl, property, + &sc_next.val); + if (error != 0) { + if (prop_must_exist(property)) { + fprintf(stderr, + "bectl list: sort field '%s' on BE '%s': %s\n", + property, sc_next.name, strerror(error)); + return (error); + } + + sc_next.val = ""; + } /* properties that use numerical comparison */ if (strcmp(property, "creation") == 0 || @@ -379,7 +410,7 @@ be_prop_list_free(nvl); - return 0; + return (0); } int @@ -451,7 +482,10 @@ if (column == NULL) column = strdup("name"); - prop_list_sort(props, column, reverse); + if (prop_list_sort(props, column, reverse) != 0) { + /* Error reported already in prop_list_sort(). */ + return (1); + } /* Force -D off if either -a or -s are specified */ if (pc.show_all_datasets || pc.show_snaps) diff --git a/sbin/bectl/tests/bectl_test.sh b/sbin/bectl/tests/bectl_test.sh --- a/sbin/bectl/tests/bectl_test.sh +++ b/sbin/bectl/tests/bectl_test.sh @@ -292,6 +292,20 @@ atf_check -e ignore bectl -r ${zpool}/ROOT destroy default2 atf_check -o save:list.out bectl -r ${zpool}/ROOT list atf_check -s not-exit:0 grep 'default2' list.out + + # Valid sort keys + atf_check -o ignore bectl -r ${zpool}/ROOT list -c name + atf_check -o ignore bectl -r ${zpool}/ROOT list -c origin + atf_check -o ignore bectl -r ${zpool}/ROOT list -c creation + atf_check -o ignore bectl -r ${zpool}/ROOT list -c used + atf_check -o ignore bectl -r ${zpool}/ROOT list -c usedds + atf_check -o ignore bectl -r ${zpool}/ROOT list -c usedsnap + atf_check -o ignore bectl -r ${zpool}/ROOT list -c usedrefreserv + + # Invalid sort key + atf_check -s not-exit:0 -o ignore -e not-empty \ + bectl -r ${zpool}/ROOT list -c creatio + # XXX TODO: Formatting checks } bectl_list_cleanup()