diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index 35f48334a771..13a66361ba14 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -3863,6 +3863,7 @@ zfs_do_list(int argc, char **argv) zfs_sort_column_t *sortcol = NULL; int flags = ZFS_ITER_PROP_LISTSNAPS | ZFS_ITER_ARGS_CAN_BE_PATHS; nvlist_t *data = NULL; + char full_fields[1024]; struct option long_options[] = { {"json", no_argument, NULL, 'j'}, @@ -3875,7 +3876,23 @@ zfs_do_list(int argc, char **argv) NULL)) != -1) { switch (c) { case 'o': - fields = optarg; + if (optarg[0] == '+') { + /* +2 for the , and the null terminator */ + if (strlen(fields) + strlen(optarg + 1) + 2 <= + 1024) { + (void) snprintf(full_fields, + sizeof (full_fields), "%s,%s", + fields, optarg + 1); + } else { + (void) fprintf(stderr, gettext( + "argument too long for '-o'" + " option.\n")); + usage(B_FALSE); + } + fields = full_fields; + } else { + fields = optarg; + } break; case 'p': cb.cb_literal = B_TRUE; diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index bec3f94d9602..832a5758dd16 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -7400,6 +7400,7 @@ zpool_do_list(int argc, char **argv) boolean_t first = B_TRUE; nvlist_t *data = NULL; current_prop_type = ZFS_TYPE_POOL; + char full_props[1024]; struct option long_options[] = { {"json", no_argument, NULL, 'j'}, @@ -7423,7 +7424,23 @@ zpool_do_list(int argc, char **argv) cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS; break; case 'o': - props = optarg; + if (optarg[0] == '+') { + /* +2 for the , and the null terminator */ + if (strlen(props) + strlen(optarg + 1) + 2 <= + 1024) { + (void) snprintf(full_props, + sizeof (full_props), "%s,%s", + props, optarg + 1); + } else { + (void) fprintf(stderr, gettext( + "argument too long for '-o'" + " option.\n")); + usage(B_FALSE); + } + props = full_props; + } else { + props = optarg; + } break; case 'P': cb.cb_name_flags |= VDEV_NAME_PATH; diff --git a/man/man8/zfs-list.8 b/man/man8/zfs-list.8 index 42eff94f9762..62aa8a3ec88d 100644 --- a/man/man8/zfs-list.8 +++ b/man/man8/zfs-list.8 @@ -107,6 +107,13 @@ This is a shortcut for specifying .Sy usedds , Ns Sy usedrefreserv , Ns Sy usedchild .Fl t Sy filesystem , Ns Sy volume . .El +.Pp +The default list of properties can be extended by using +.Sy +property +instead of +.Sy property . +For example, +.Sy zfs list -o +guid . .It Fl p Display numbers in parsable .Pq exact diff --git a/man/man8/zpool-list.8 b/man/man8/zpool-list.8 index 106399941f98..fe44f57456e5 100644 --- a/man/man8/zpool-list.8 +++ b/man/man8/zpool-list.8 @@ -84,6 +84,13 @@ manual page for a list of valid properties. The default list is .Sy name , size , allocated , free , checkpoint, expandsize , fragmentation , .Sy capacity , dedupratio , health , altroot . +.Pp +The default list of properties can be extended by using +.Sy +property +instead of +.Sy property . +For example, +.Sy zpool list -o +guid . .It Fl L Display real paths for vdevs resolving all symbolic links. This can be used to look up the current block device name regardless of the diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_009_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_009_pos.ksh new file mode 100755 index 000000000000..771bfad3c4b2 --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_009_pos.ksh @@ -0,0 +1,59 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Copyright (c) 2013, 2016 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# Verify 'zfs list -o+' allows users to append a column to the defaults +# +# STRATEGY: +# 1. Add a user comment to dataset +# 2. Execute `zfs list -o +comment:`. +# 3. Verify the first column of the defaults gets printed. +# 4. Verify the user comment appears as the last column. +# 5. Verify we see both one of the default entries and the user comment in JSON. + +verify_runnable "both" + +log_assert "Verify 'zfs list -o+<...>' appends columns to the defaults." + +log_must zfs set comment:=helloworld $TESTPOOL + +log_must eval zfs list $TESTPOOL -o +comment: | grep -Eq '^NAME.+COMMENT:$' +log_must eval zfs list $TESTPOOL -o +comment: | grep -Eq "^$TESTPOOL.+helloworld$" +val=$(zfs list -j -o +comment: $TESTPOOL | jq -r '.datasets.'$TESTPOOL'.properties."comment:".value') ++log_must test $val == "helloworld" +val=$(zfs list -j -o +comment: $TESTPOOL | jq -r ".datasets.$TESTPOOL.properties.mountpoint.value") ++log_must test $val == "/$TESTPOOL" + +log_pass "'zfs list -o+<...>' successfully added columns to the defaults." diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_003_pos.ksh new file mode 100755 index 000000000000..dc47af5d16ba --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_003_pos.ksh @@ -0,0 +1,66 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Copyright (c) 2013, 2016 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# Verify that 'zpool list -o+' allows users to append a column to the defaults. +# +# STRATEGY: +# 1. Add a user comment to the pool +# 2. Execute `zfs list -o +comment`. +# 3. Verify the first column of the defaults gets printed. +# 4. Verify the user comment appears as the last column. +# 5. Verify we see both one of the default entries and the user comment in JSON. + +verify_runnable "both" + +if ! is_global_zone; then + TESTPOOL=${TESTPOOL%%/*} +fi + +log_assert "Verify 'zpool list -o+<...>' appends columns to the defaults." + +log_must zpool set comment="helloworld" $TESTPOOL + +# Verify the first and last columns are correct +log_must eval zpool list -o +comment | grep -Eq '^NAME.+COMMENT$' +log_must eval zpool list -o +comment | grep -Eq "^$TESTPOOL.+helloworld$" + +# Verify we see both a default value and our added value in the JSON +val=$(zpool list -j -o +comment | jq -r ".pools.$TESTPOOL.properties.comment.value") ++log_must test "$val" == "helloworld" +val=$(zpool list -j -o +comment | jq -r ".pools.$TESTPOOL.properties.health.value") ++log_must test "$val" == "ONLINE" + +log_pass "'zpool list -o+<...>' successfully added columns to the defaults."