aboutsummaryrefslogtreecommitdiff
path: root/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib
diff options
context:
space:
mode:
Diffstat (limited to 'tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib')
-rw-r--r--tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib1713
1 files changed, 1713 insertions, 0 deletions
diff --git a/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib b/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib
new file mode 100644
index 000000000000..e39b015b21b8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib
@@ -0,0 +1,1713 @@
+#
+# 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 http://www.opensolaris.org/os/licensing.
+# 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.
+# Copyright 2016 Nexenta Systems, Inc.
+# Copyright (c) 2018 George Melikov. All Rights Reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/delegate/delegate.cfg
+
+#
+# Cleanup exist user/group.
+#
+function cleanup_user_group
+{
+ typeset i
+ for i in $STAFF1 $STAFF2 $OTHER1 $OTHER2 ; do
+ del_user $i
+ done
+ for i in $STAFF_GROUP $OTHER_GROUP ; do
+ del_group $i
+ done
+
+ return 0
+}
+
+#
+# Restore test file system to the original status.
+#
+function restore_root_datasets
+{
+ destroy_dataset "$ROOT_TESTFS" "-Rf"
+ log_must zfs create $ROOT_TESTFS
+
+ if is_global_zone ; then
+ destroy_dataset "$ROOT_TESTVOL" "-Rf"
+ log_must zfs create -V $VOLSIZE $ROOT_TESTVOL
+ block_device_wait
+ fi
+
+ return 0
+}
+
+#
+# Verify the specified user have permission on the dataset
+#
+# $1 dataset
+# $2 permissions which are separated by comma(,)
+# $3-n users
+#
+function verify_perm
+{
+ typeset dtst=$1
+ typeset permissions=$2
+ shift 2
+
+ if [[ -z $@ || -z $permissions || -z $dtst ]]; then
+ return 1
+ fi
+
+ typeset type=$(get_prop type $dtst)
+ permissions=$(echo $permissions | tr -s "," " ")
+
+ typeset user
+ for user in $@; do
+ typeset perm
+ for perm in $permissions; do
+ typeset -i ret=1
+ if [[ $type == "filesystem" ]]; then
+ check_fs_perm $user $perm $dtst
+ ret=$?
+ elif [[ $type == "volume" ]]; then
+ check_vol_perm $user $perm $dtst
+ ret=$?
+ fi
+
+ log_note "Check $type $user $perm $dtst"
+ if ((ret != 0)) ; then
+ log_note "Fail: $user should have $perm" \
+ "on $dtst"
+ return 1
+ fi
+ done
+ done
+
+ return 0
+}
+
+#
+# Verify the specified user have no permission on the dataset
+#
+# $1 dataset
+# $2 permissions which are separated by comma(,)
+# $3-n users
+#
+function verify_noperm
+{
+ typeset dtst=$1
+ typeset permissions=$2
+ shift 2
+
+ if [[ -z $@ || -z $permissions || -z $dtst ]]; then
+ return 1
+ fi
+
+ typeset type=$(get_prop type $dtst)
+ permissions=$(echo $permissions | tr -s "," " ")
+
+ typeset user
+ for user in $@; do
+ typeset perm
+ for perm in $permissions; do
+ typeset -i ret=1
+ if [[ $type == "filesystem" ]]; then
+ check_fs_perm $user $perm $dtst
+ ret=$?
+ elif [[ $type == "volume" ]]; then
+ check_vol_perm $user $perm $dtst
+ ret=$?
+ fi
+
+ if ((ret == 0)) ; then
+ log_note "Fail: $user should not have $perm " \
+ "on $dtst"
+ return 1
+ fi
+ done
+ done
+
+ return 0
+}
+
+function common_perm
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset dtst=$3
+
+ typeset -i ret=1
+ case $perm in
+ send)
+ verify_send $user $perm $dtst
+ ret=$?
+ ;;
+ allow)
+ verify_allow $user $perm $dtst
+ ret=$?
+ ;;
+ userprop)
+ verify_userprop $user $perm $dtst
+ ret=$?
+ ;;
+ compression|checksum|readonly)
+ verify_ccr $user $perm $dtst
+ ret=$?
+ ;;
+ copies)
+ verify_copies $user $perm $dtst
+ ret=$?
+ ;;
+ reservation)
+ verify_reservation $user $perm $dtst
+ ret=$?
+ ;;
+ *)
+ ret=1
+ ;;
+ esac
+
+ return $ret
+}
+
+function check_fs_perm
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset -i ret=1
+ case $perm in
+ create)
+ verify_fs_create $user $perm $fs
+ ret=$?
+ ;;
+ destroy)
+ verify_fs_destroy $user $perm $fs
+ ret=$?
+ ;;
+ snapshot)
+ verify_fs_snapshot $user $perm $fs
+ ret=$?
+ ;;
+ rollback)
+ verify_fs_rollback $user $perm $fs
+ ret=$?
+ ;;
+ clone)
+ verify_fs_clone $user $perm $fs
+ ret=$?
+ ;;
+ rename)
+ verify_fs_rename $user $perm $fs
+ ret=$?
+ ;;
+ mount)
+ verify_fs_mount $user $perm $fs
+ ret=$?
+ ;;
+ share)
+ verify_fs_share $user $perm $fs
+ ret=$?
+ ;;
+ mountpoint)
+ verify_fs_mountpoint $user $perm $fs
+ ret=$?
+ ;;
+ promote)
+ verify_fs_promote $user $perm $fs
+ ret=$?
+ ;;
+ canmount)
+ verify_fs_canmount $user $perm $fs
+ ret=$?
+ ;;
+ dnodesize)
+ verify_fs_dnodesize $user $perm $fs
+ ret=$?
+ ;;
+ recordsize)
+ verify_fs_recordsize $user $perm $fs
+ ret=$?
+ ;;
+ quota)
+ verify_fs_quota $user $perm $fs
+ ret=$?
+ ;;
+ aclmode)
+ verify_fs_aclmode $user $perm $fs
+ ret=$?
+ ;;
+ aclinherit)
+ verify_fs_aclinherit $user $perm $fs
+ ret=$?
+ ;;
+ snapdir)
+ verify_fs_snapdir $user $perm $fs
+ ret=$?
+ ;;
+ atime|exec|devices|setuid|xattr)
+ verify_fs_aedsx $user $perm $fs
+ ret=$?
+ ;;
+ zoned)
+ verify_fs_zoned $user $perm $fs
+ ret=$?
+ ;;
+ sharenfs)
+ verify_fs_sharenfs $user $perm $fs
+ ret=$?
+ ;;
+ receive)
+ verify_fs_receive $user $perm $fs
+ ret=$?
+ ;;
+ *)
+ common_perm $user $perm $fs
+ ret=$?
+ ;;
+ esac
+
+ return $ret
+}
+
+function check_vol_perm
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ typeset -i ret=1
+ case $perm in
+ destroy)
+ verify_vol_destroy $user $perm $vol
+ ret=$?
+ ;;
+ snapshot)
+ verify_vol_snapshot $user $perm $vol
+ ret=$?
+ ;;
+ rollback)
+ verify_vol_rollback $user $perm $vol
+ ret=$?
+ ;;
+ clone)
+ verify_vol_clone $user $perm $vol
+ ret=$?
+ ;;
+ rename)
+ verify_vol_rename $user $perm $vol
+ ret=$?
+ ;;
+ promote)
+ verify_vol_promote $user $perm $vol
+ ret=$?
+ ;;
+ volsize)
+ verify_vol_volsize $user $perm $vol
+ ret=$?
+ ;;
+ *)
+ common_perm $user $perm $vol
+ ret=$?
+ ;;
+ esac
+
+ return $ret
+}
+
+function setup_unallow_testenv
+{
+ log_must restore_root_datasets
+
+ log_must zfs create $SUBFS
+
+ for dtst in $DATASETS ; do
+ log_must zfs allow -l $STAFF1 $LOCAL_SET $dtst
+ log_must zfs allow -d $STAFF2 $DESC_SET $dtst
+ log_must zfs allow $OTHER1 $LOCAL_DESC_SET $dtst
+ log_must zfs allow $OTHER2 $LOCAL_DESC_SET $dtst
+
+ log_must verify_perm $dtst $LOCAL_SET $STAFF1
+ log_must verify_perm $dtst $LOCAL_DESC_SET $OTHER1
+ log_must verify_perm $dtst $LOCAL_DESC_SET $OTHER2
+ if [[ $dtst == $ROOT_TESTFS ]]; then
+ log_must verify_perm $SUBFS $DESC_SET $STAFF2
+ log_must verify_perm $SUBFS $LOCAL_DESC_SET $OTHER1
+ log_must verify_perm $SUBFS $LOCAL_DESC_SET $OTHER2
+ fi
+ done
+
+ return 0
+}
+
+#
+# Verify permission send for specified user on the dataset
+# $1 user
+# $2 permission
+# $3 dataset
+#
+function verify_send
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset dtst=$3
+
+ typeset oldval
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset snap=$dtst@snap.$stamp
+
+ typeset -i ret=1
+
+ log_must zfs snapshot $snap
+ typeset bak_user=$TEST_BASE_DIR/bak.$user.$stamp
+ typeset bak_root=$TEST_BASE_DIR/bak.root.$stamp
+
+ user_run $user eval "zfs send $snap > $bak_user"
+ log_must eval "zfs send $snap > $bak_root"
+
+ if [[ $(checksum $bak_user) == $(checksum $bak_root) ]]; then
+ ret=0
+ fi
+
+ rm -rf $bak_user > /dev/null
+ rm -rf $bak_root > /dev/null
+
+ return $ret
+}
+
+function verify_fs_receive
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset dtst
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset newfs=$fs/newfs.$stamp
+ typeset newvol=$fs/newvol.$stamp
+ typeset bak_user=$TEST_BASE_DIR/bak.$user.$stamp
+ typeset bak_root=$TEST_BASE_DIR/bak.root.$stamp
+
+ log_must zfs create $newfs
+ typeset datasets="$newfs"
+ if is_global_zone ; then
+ log_must zfs create -V $VOLSIZE $newvol
+ block_device_wait
+ datasets="$newfs $newvol"
+ fi
+
+ for dtst in $datasets ; do
+
+ typeset dtstsnap=$dtst@snap.$stamp
+ log_must zfs snapshot $dtstsnap
+
+ log_must eval "zfs send $dtstsnap > $bak_root"
+ log_must_busy zfs destroy -rf $dtst
+
+ user_run $user eval "zfs receive $dtst < $bak_root"
+ if datasetexists $dtstsnap ; then
+ return 1
+ fi
+
+ log_must zfs allow $user create $fs
+ user_run $user eval "zfs receive $dtst < $bak_root"
+ log_must zfs unallow $user create $fs
+ if datasetexists $dtstsnap ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $fs
+ user_run $user eval "zfs receive $dtst < $bak_root"
+ log_must zfs unallow $user mount $fs
+ if datasetexists $dtstsnap ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount,create $fs
+ user_run $user eval "zfs receive $dtst < $bak_root"
+ log_must zfs unallow $user mount,create $fs
+ if ! datasetexists $dtstsnap ; then
+ return 1
+ fi
+
+ # check the data integrity
+ log_must eval "zfs send $dtstsnap > $bak_user"
+ log_must_busy zfs destroy -rf $dtst
+ log_must eval "zfs receive $dtst < $bak_root"
+ log_must eval "zfs send $dtstsnap > $bak_root"
+ log_must_busy zfs destroy -rf $dtst
+ if [[ $(checksum $bak_user) != $(checksum $bak_root) ]]; then
+ return 1
+ fi
+
+ rm -rf $bak_user > /dev/null
+ rm -rf $bak_root > /dev/null
+
+ done
+
+ return 0
+}
+
+function verify_userprop
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset dtst=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+
+ user_run $user zfs set "$user:ts=$stamp" $dtst
+ zpool sync ${dtst%%/*}
+ if [[ $stamp != $(get_prop "$user:ts" $dtst) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_ccr
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset dtst=$3
+
+ typeset oldval
+
+ set -A modes "on" "off"
+ oldval=$(get_prop $perm $dtst)
+ if [[ $oldval == "on" ]]; then
+ n=1
+ elif [[ $oldval == "off" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set $perm=${modes[$n]} $dtst"
+ user_run $user zfs set $perm=${modes[$n]} $dtst
+ if [[ ${modes[$n]} != $(get_prop $perm $dtst) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_copies
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset dtst=$3
+
+ typeset oldval
+
+ set -A modes 1 2 3
+ oldval=$(get_prop $perm $dtst)
+ if [[ $oldval -eq 1 ]]; then
+ n=1
+ elif [[ $oldval -eq 2 ]]; then
+ n=2
+ elif [[ $oldval -eq 3 ]]; then
+ n=0
+ fi
+ log_note "$user zfs set $perm=${modes[$n]} $dtst"
+ user_run $user zfs set $perm=${modes[$n]} $dtst
+ if [[ ${modes[$n]} != $(get_prop $perm $dtst) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_reservation
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset dtst=$3
+
+ typeset value32m=$(( 1024 * 1024 * 32 ))
+ typeset oldval=$(get_prop reservation $dtst)
+ user_run $user zfs set reservation=$value32m $dtst
+ if [[ $value32m != $(get_prop reservation $dtst) ]]; then
+ log_must zfs set reservation=$oldval $dtst
+ return 1
+ fi
+
+ log_must zfs set reservation=$oldval $dtst
+ return 0
+}
+
+function verify_fs_create
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset newfs=$fs/nfs.$stamp
+ typeset newvol=$fs/nvol.$stamp
+
+ user_run $user zfs create $newfs
+ if datasetexists $newfs ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $fs
+ user_run $user zfs create $newfs
+ log_must zfs unallow $user mount $fs
+ if ! datasetexists $newfs ; then
+ return 1
+ fi
+
+ log_must zfs destroy $newfs
+
+ if is_global_zone ; then
+ # mount permission is required for sparse volume
+ user_run $user zfs create -V 150m -s $newvol
+ block_device_wait
+ if datasetexists $newvol ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $fs
+ user_run $user zfs create -V 150m -s $newvol
+ log_must zfs unallow $user mount $fs
+ if ! datasetexists $newvol ; then
+ return 1
+ fi
+
+ block_device_wait
+ log_must zfs destroy $newvol
+ block_device_wait
+
+ # mount and reserveration permission are
+ # required for normal volume
+ user_run $user zfs create -V 150m $newvol
+ block_device_wait
+ if datasetexists $newvol ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $fs
+ user_run $user zfs create -V 150m $newvol
+ block_device_wait
+ log_must zfs unallow $user mount $fs
+ if datasetexists $newvol ; then
+ return 1
+ fi
+
+ log_must zfs allow $user reservation $fs
+ user_run $user zfs create -V 150m $newvol
+ block_device_wait
+ log_must zfs unallow $user reservation $fs
+ if datasetexists $newvol ; then
+ return 1
+ fi
+
+ log_must zfs allow $user refreservation $fs
+ user_run $user zfs create -V 150m $newvol
+ block_device_wait
+ log_must zfs unallow $user refreservation $fs
+ if datasetexists $newvol ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $fs
+ log_must zfs allow $user reservation $fs
+ log_must zfs allow $user refreservation $fs
+ user_run $user zfs create -V 150m $newvol
+ log_must zfs unallow $user mount $fs
+ log_must zfs unallow $user reservation $fs
+ log_must zfs unallow $user refreservation $fs
+ if ! datasetexists $newvol ; then
+ return 1
+ fi
+
+ block_device_wait
+ log_must zfs destroy $newvol
+ block_device_wait
+ fi
+
+ return 0
+}
+
+function verify_fs_destroy
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ if ! ismounted $fs ; then
+ user_run $user zfs destroy $fs
+ if datasetexists $fs ; then
+ return 1
+ fi
+ fi
+
+ if ismounted $fs ; then
+ user_run $user zfs destroy $fs
+ if ! datasetexists $fs ; then
+ return 1
+ fi
+
+ # mount permission is required
+ log_must zfs allow $user mount $fs
+ user_run $user zfs destroy $fs
+ if datasetexists $fs ; then
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+# Verify that given the correct delegation, a regular user can:
+# Take a snapshot of an unmounted dataset
+# Take a snapshot of a mounted dataset
+# Create a snapshot by making a directory in the .zfs/snapshot directory
+function verify_fs_snapshot
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset snap=$fs@snap.$stamp
+ typeset mntpt=$(get_prop mountpoint $fs)
+
+ if [[ "yes" == $(get_prop mounted $fs) ]]; then
+ log_must zfs umount $fs
+ fi
+
+ user_run $user zfs snapshot $snap
+ if ! datasetexists $snap ; then
+ return 1
+ fi
+ log_must zfs destroy $snap
+
+ if [[ "no" == $(get_prop mounted $fs) ]]; then
+ log_must zfs mount $fs
+ fi
+
+ user_run $user zfs snapshot $snap
+ if ! datasetexists $snap ; then
+ return 1
+ fi
+ log_must zfs destroy $snap
+
+ # Creating snaps via mkdir is not supported on FreeBSD
+ if ! is_freebsd; then
+ typeset snapdir=${mntpt}/.zfs/snapshot/snap.$stamp
+ user_run $user mkdir $snapdir
+ if ! datasetexists $snap ; then
+ return 1
+ fi
+ log_must zfs destroy $snap
+ fi
+
+ return 0
+}
+
+function verify_fs_rollback
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset oldval
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset snap=$fs@snap.$stamp
+ typeset mntpt=$(get_prop mountpoint $fs)
+
+ oldval=$(datasetcksum $fs)
+ log_must zfs snapshot $snap
+
+ if ! ismounted $fs; then
+ log_must zfs mount $fs
+ fi
+ log_must touch $mntpt/testfile.$stamp
+
+ user_run $user zfs rollback -R $snap
+ if is_global_zone ; then
+ if [[ $oldval != $(datasetcksum $fs) ]]; then
+ return 1
+ fi
+ else
+ # datasetcksum can not be used in local zone
+ if [[ -e $mntpt/testfile.$stamp ]]; then
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+function verify_fs_clone
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basefs=${fs%/*}
+ typeset snap=$fs@snap.$stamp
+ typeset clone=$basefs/cfs.$stamp
+
+ log_must zfs snapshot $snap
+ user_run $user zfs clone $snap $clone
+ if datasetexists $clone ; then
+ return 1
+ fi
+
+ log_must zfs allow $user create $basefs
+ user_run $user zfs clone $snap $clone
+ log_must zfs unallow $user create $basefs
+ if datasetexists $clone ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $basefs
+ user_run $user zfs clone $snap $clone
+ log_must zfs unallow $user mount $basefs
+ if datasetexists $clone ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $basefs
+ log_must zfs allow $user create $basefs
+ user_run $user zfs clone $snap $clone
+ log_must zfs unallow $user create $basefs
+ log_must zfs unallow $user mount $basefs
+ if ! datasetexists $clone ; then
+ return 1
+ fi
+
+ log_must zfs destroy -R $snap
+
+ return 0
+}
+
+function verify_fs_rename
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basefs=${fs%/*}
+ typeset snap=$fs@snap.$stamp
+ typeset renamefs=$basefs/nfs.$stamp
+
+ if ! ismounted $fs; then
+ log_must zfs mount $fs
+ fi
+
+ # case 1
+ user_run $user zfs rename $fs $renamefs
+ if datasetexists $renamefs ; then
+ return 1
+ fi
+
+ # case 2
+ log_must zfs allow $user create $basefs
+ user_run $user zfs rename $fs $renamefs
+ log_must zfs unallow $user create $basefs
+ if datasetexists $renamefs ; then
+ return 1
+ fi
+
+ # case 3
+ log_must zfs allow $user mount $basefs
+ user_run $user zfs rename $fs $renamefs
+ log_must zfs unallow $user mount $basefs
+ if datasetexists $renamefs ; then
+ return 1
+ fi
+
+ # case 4
+ log_must zfs allow $user mount $fs
+ user_run $user zfs rename $fs $renamefs
+ if datasetexists $renamefs ; then
+ log_must zfs unallow $user mount $renamefs
+ return 1
+ fi
+ log_must zfs unallow $user mount $fs
+
+ # case 5
+ log_must zfs allow $user create $basefs
+ log_must zfs allow $user mount $fs
+ user_run $user zfs rename $fs $renamefs
+ log_must zfs unallow $user create $basefs
+ if datasetexists $renamefs ; then
+ log_must zfs unallow $user mount $renamefs
+ return 1
+ fi
+ log_must zfs unallow $user mount $fs
+
+ # case 6
+ log_must zfs allow $user mount $basefs
+ log_must zfs allow $user mount $fs
+ user_run $user zfs rename $fs $renamefs
+ log_must zfs unallow $user mount $basefs
+ if datasetexists $renamefs ; then
+ log_must zfs unallow $user mount $renamefs
+ return 1
+ fi
+ log_must zfs unallow $user mount $fs
+
+ # case 7
+ log_must zfs allow $user create $basefs
+ log_must zfs allow $user mount $basefs
+ user_run $user zfs rename $fs $renamefs
+ log_must zfs unallow $user mount $basefs
+ log_must zfs unallow $user create $basefs
+ if ! datasetexists $renamefs ; then
+ return 1
+ fi
+
+ log_must zfs rename $renamefs $fs
+
+ return 0
+}
+
+function verify_fs_mount
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset mntpt=$(get_prop mountpoint $fs)
+ typeset newmntpt=$TEST_BASE_DIR/mnt.$stamp
+
+ if ismounted $fs ; then
+ user_run $user zfs unmount $fs
+ if ismounted $fs ; then
+ return 1
+ fi
+ fi
+
+ if ! ismounted $fs ; then
+ log_must zfs set mountpoint=$newmntpt $fs
+ log_must rm -rf $newmntpt
+ log_must mkdir $newmntpt
+
+ user_run $user zfs mount $fs
+ if ismounted $fs ; then
+ return 1
+ fi
+
+ # mountpoint's owner must be the user
+ log_must chown $user $newmntpt
+ user_run $user zfs mount $fs
+ if ! ismounted $fs ; then
+ return 1
+ fi
+ log_must zfs umount $fs
+ log_must rm -rf $newmntpt
+ log_must zfs set mountpoint=$mntpt $fs
+ fi
+
+ return 0
+}
+
+function verify_fs_share
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+ typeset -i ret=0
+
+ svcadm enable -rs nfs/server
+ typeset stat=$(svcs -H -o STA nfs/server:default)
+ if [[ $stat != "ON" ]]; then
+ log_fail "Could not enable nfs/server"
+ fi
+
+ log_must zfs set sharenfs=on $fs
+ zfs unshare $fs
+
+ user_run $user zfs share $fs
+ if ! is_shared $fs; then
+ ret=1
+ fi
+
+ zfs unshare $fs
+ log_must zfs set sharenfs=off $fs
+
+ return $ret
+}
+
+function verify_fs_mountpoint
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset mntpt=$(get_prop mountpoint $fs)
+ typeset newmntpt=$TEST_BASE_DIR/mnt.$stamp
+
+ if ! ismounted $fs ; then
+ user_run $user zfs set mountpoint=$newmntpt $fs
+ if [[ $newmntpt != \
+ $(get_prop mountpoint $fs) ]] ; then
+ return 1
+ fi
+ log_must zfs set mountpoint=$mntpt $fs
+ fi
+
+ if ismounted $fs ; then
+ user_run $user zfs set mountpoint=$newmntpt $fs
+ if [[ $mntpt != $(get_prop mountpoint $fs) ]]; then
+ return 1
+ fi
+
+ # require mount permission when fs is mounted
+ log_must zfs allow $user mount $fs
+ user_run $user zfs set mountpoint=$newmntpt $fs
+ log_must zfs unallow $user mount $fs
+ if [[ $newmntpt != \
+ $(get_prop mountpoint $fs) ]] ; then
+ return 1
+ fi
+ log_must zfs set mountpoint=$mntpt $fs
+ fi
+
+ return 0
+}
+
+function verify_fs_promote
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basefs=${fs%/*}
+ typeset snap=$fs@snap.$stamp
+ typeset clone=$basefs/cfs.$stamp
+
+ log_must zfs snapshot $snap
+ log_must zfs clone $snap $clone
+ log_must zfs promote $clone
+
+ typeset fs_orig=$(get_prop origin $fs)
+ typeset clone_orig=$(get_prop origin $clone)
+
+ user_run $user zfs promote $fs
+ # promote should fail if original fs does not have
+ # promote permission
+ if [[ $fs_orig != $(get_prop origin $fs) || \
+ $clone_orig != $(get_prop origin $clone) ]]; then
+ return 1
+ fi
+
+ log_must zfs allow $user promote $clone
+ user_run $user zfs promote $fs
+ log_must zfs unallow $user promote $clone
+ if [[ $fs_orig != $(get_prop origin $fs) || \
+ $clone_orig != $(get_prop origin $clone) ]]; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $fs
+ user_run $user zfs promote $fs
+ log_must zfs unallow $user mount $fs
+ if [[ $fs_orig != $(get_prop origin $fs) || \
+ $clone_orig != $(get_prop origin $clone) ]]; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $fs
+ log_must zfs allow $user promote $clone
+ user_run $user zfs promote $fs
+ log_must zfs unallow $user promote $clone
+ log_must zfs unallow $user mount $fs
+ if [[ $snap != $(get_prop origin $clone) || \
+ $clone_orig != $(get_prop origin $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_canmount
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset oldval
+ typeset stamp=${perm}.${user}.$RANDOM
+
+ if ! ismounted $fs ; then
+ set -A modes "on" "off"
+ oldval=$(get_prop $perm $fs)
+ if [[ $oldval == "on" ]]; then
+ n=1
+ elif [[ $oldval == "off" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set $perm=${modes[$n]} $fs"
+ user_run $user zfs set $perm=${modes[$n]} $fs
+ if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
+ return 1
+ fi
+ fi
+
+
+ # fs is mounted
+ if ismounted $fs ; then
+ # property value does not change if
+ # no mount permission
+ set -A modes "on" "off"
+ oldval=$(get_prop $perm $fs)
+ if [[ $oldval == "on" ]]; then
+ n=1
+ elif [[ $oldval == "off" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set $perm=${modes[$n]} $fs"
+ log_must zfs allow $user mount $fs
+ user_run $user zfs set $perm=${modes[$n]} $fs
+ log_must zfs unallow $user mount $fs
+ if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+function verify_fs_recordsize
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset value8k=$(( 1024 * 8 ))
+ user_run $user zfs set recordsize=$value8k $fs
+ if [[ $value8k != $(get_prop recordsize $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_dnodesize
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+ value="2k"
+
+ user_run $user zfs set dnodesize=$value $fs
+ if [[ $value != $(get_prop dnodesize $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_quota
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset value32m=$(( 1024 * 1024 * 32 ))
+ user_run $user zfs set quota=$value32m $fs
+ if [[ $value32m != $(get_prop quota $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_aclmode
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset oldval
+ set -A modes "discard" "groupmask" "passthrough"
+ oldval=$(get_prop $perm $fs)
+ if [[ $oldval == "discard" ]]; then
+ n=1
+ elif [[ $oldval == "groupmask" ]]; then
+ n=2
+ elif [[ $oldval == "passthrough" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set aclmode=${modes[$n]} $fs"
+ user_run $user zfs set aclmode=${modes[$n]} $fs
+ if [[ ${modes[$n]} != $(get_prop aclmode $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_aclinherit
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ #
+ # PSARC/2008/231 change the default value of aclinherit to "restricted"
+ # but still keep the old interface of "secure"
+ #
+
+ typeset oldval
+ set -A modes "discard" "noallow" "secure" "passthrough"
+ oldval=$(get_prop $perm $fs)
+ if [[ $oldval == "discard" ]]; then
+ n=1
+ elif [[ $oldval == "noallow" ]]; then
+ n=2
+ elif [[ $oldval == "secure" || $oldval == "restricted" ]]; then
+ n=3
+ elif [[ $oldval == "passthrough" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set aclinherit=${modes[$n]} $fs"
+ user_run $user zfs set aclinherit=${modes[$n]} $fs
+
+ typeset newval=$(get_prop aclinherit $fs)
+ if [[ ${modes[$n]} == "secure" && $newval == "restricted" ]]; then
+ return 0
+ elif [[ ${modes[$n]} != $(get_prop aclinherit $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_snapdir
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset oldval
+ set -A modes "visible" "hidden"
+ oldval=$(get_prop $perm $fs)
+ if [[ $oldval == "visible" ]]; then
+ n=1
+ elif [[ $oldval == "hidden" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set snapdir=${modes[$n]} $fs"
+ user_run $user zfs set snapdir=${modes[$n]} $fs
+ if [[ ${modes[$n]} != $(get_prop snapdir $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_aedsx
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset oldval
+ set -A modes "on" "off"
+ oldval=$(get_prop $perm $fs)
+ if [[ $oldval == "on" ]]; then
+ n=1
+ elif [[ $oldval == "off" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set $perm=${modes[$n]} $fs"
+ user_run $user zfs set $perm=${modes[$n]} $fs
+ if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_zoned
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset oldval
+ set -A modes "on" "off"
+ oldval=$(get_prop $perm $fs)
+ if [[ $oldval == "on" ]]; then
+ n=1
+ elif [[ $oldval == "off" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set $perm=${modes[$n]} $fs"
+ if is_global_zone ; then
+ if ! ismounted $fs ; then
+ user_run $user zfs set \
+ $perm=${modes[$n]} $fs
+ if [[ ${modes[$n]} != \
+ $(get_prop $perm $fs) ]]; then
+ return 1
+ fi
+ if [[ $n -eq 0 ]]; then
+ log_mustnot zfs mount $fs
+ else
+ log_must zfs mount $fs
+ fi
+ fi
+
+ if ismounted $fs; then
+ # n always is 1 in this case
+ user_run $user zfs set \
+ $perm=${modes[$n]} $fs
+ if [[ $oldval != \
+ $(get_prop $perm $fs) ]]; then
+ return 1
+ fi
+
+ # mount permission is needed
+ # to make zoned=on
+ log_must zfs allow $user mount $fs
+ user_run $user zfs set \
+ $perm=${modes[$n]} $fs
+ log_must zfs unallow $user mount $fs
+ if [[ ${modes[$n]} != \
+ $(get_prop $perm $fs) ]]; then
+ return 1
+ fi
+ fi
+ fi
+
+ if ! is_global_zone; then
+ user_run $user zfs set $perm=${modes[$n]} $fs
+ if [[ $oldval != $(get_prop $perm $fs) ]]; then
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+function verify_fs_sharenfs
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+ typeset nmode omode
+
+ omode=$(get_prop $perm $fs)
+ if [[ $omode == "off" ]]; then
+ nmode="on"
+ else
+ nmode="off"
+ fi
+
+ log_note "$user zfs set $perm=$nmode $fs"
+ user_run $user zfs set $perm=$nmode $fs
+ if [[ $(get_prop $perm $fs) != $nmode ]]; then
+ return 1
+ fi
+
+ log_note "$user zfs set $perm=$omode $fs"
+ user_run $user zfs set $perm=$omode $fs
+ if [[ $(get_prop $perm $fs) != $omode ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_vol_destroy
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ user_run $user zfs destroy $vol
+ if ! datasetexists $vol ; then
+ return 1
+ fi
+
+ # mount permission is required
+ log_must zfs allow $user mount $vol
+ user_run $user zfs destroy $vol
+ if datasetexists $vol ; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_vol_snapshot
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basevol=${vol%/*}
+ typeset snap=$vol@snap.$stamp
+
+ user_run $user zfs snapshot $snap
+ if datasetexists $snap ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $vol
+ user_run $user zfs snapshot $snap
+ log_must zfs unallow $user mount $vol
+ if ! datasetexists $snap ; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_vol_rollback
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basevol=${vol%/*}
+ typeset snap=$vol@snap.$stamp
+
+ typeset oldval
+ log_must zfs snapshot $snap
+ oldval=$(datasetcksum $vol)
+
+ log_must dd if=/dev/urandom of=$ZVOL_RDEVDIR/$vol \
+ bs=512 count=1
+
+ user_run $user zfs rollback -R $snap
+ sleep 10
+ if [[ $oldval == $(datasetcksum $vol) ]]; then
+ return 1
+ fi
+
+ # rollback on volume has to be with mount permission
+ log_must zfs allow $user mount $vol
+ user_run $user zfs rollback -R $snap
+ sleep 10
+ log_must zfs unallow $user mount $vol
+ if [[ $oldval != $(datasetcksum $vol) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_vol_clone
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basevol=${vol%/*}
+ typeset snap=$vol@snap.$stamp
+ typeset clone=$basevol/cvol.$stamp
+
+ log_must zfs snapshot $snap
+
+ user_run $user zfs clone $snap $clone
+ if datasetexists $clone ; then
+ return 1
+ fi
+
+ log_must zfs allow $user create $basevol
+ user_run $user zfs clone $snap $clone
+ log_must zfs unallow $user create $basevol
+ if datasetexists $clone ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $basevol
+ user_run $user zfs clone $snap $clone
+ log_must zfs unallow $user mount $basevol
+ if datasetexists $clone ; then
+ return 1
+ fi
+
+ # require create permission on parent and
+ # mount permission on itself as well
+ log_must zfs allow $user mount $basevol
+ log_must zfs allow $user create $basevol
+ user_run $user zfs clone $snap $clone
+ log_must zfs unallow $user create $basevol
+ log_must zfs unallow $user mount $basevol
+ if ! datasetexists $clone ; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_vol_rename
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basevol=${vol%/*}
+ typeset snap=$vol@snap.$stamp
+ typeset clone=$basevol/cvol.$stamp
+ typeset renamevol=$basevol/nvol.$stamp
+
+ user_run $user zfs rename $vol $renamevol
+ if datasetexists $renamevol ; then
+ return 1
+ fi
+
+ log_must zfs allow $user create $basevol
+ user_run $user zfs rename $vol $renamevol
+ log_must zfs unallow $user create $basevol
+ if datasetexists $renamevol ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $basevol
+ user_run $user zfs rename $vol $renamevol
+ log_must zfs unallow $user mount $basevol
+ if datasetexists $renamevol ; then
+ return 1
+ fi
+
+ # require both create permission on parent and
+ # mount permission on parent as well
+ log_must zfs allow $user mount $basevol
+ log_must zfs allow $user create $basevol
+ user_run $user zfs rename $vol $renamevol
+ log_must zfs unallow $user mount $basevol
+ log_must zfs unallow $user create $basevol
+ if ! datasetexists $renamevol ; then
+ return 1
+ fi
+
+ log_must zfs rename $renamevol $vol
+
+ return 0
+}
+
+function verify_vol_promote
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basevol=${vol%/*}
+ typeset snap=$vol@snap.$stamp
+ typeset clone=$basevol/cvol.$stamp
+
+ log_must zfs snapshot $snap
+ log_must zfs clone $snap $clone
+ log_must zfs promote $clone
+
+ typeset vol_orig=$(get_prop origin $vol)
+ typeset clone_orig=$(get_prop origin $clone)
+
+ # promote should fail if $vol and $clone
+ # miss either mount or promote permission
+ # case 1
+ user_run $user zfs promote $vol
+ if [[ $vol_orig != $(get_prop origin $vol) || \
+ $clone_orig != $(get_prop origin $clone) ]];
+ then
+ return 1
+ fi
+
+ # promote should fail if $vol and $clone
+ # miss either mount or promote permission
+ # case 2
+ log_must zfs allow $user promote $clone
+ user_run $user zfs promote $vol
+ log_must zfs unallow $user promote $clone
+ if [[ $vol_orig != $(get_prop origin $vol) || \
+ $clone_orig != $(get_prop origin $clone) ]];
+ then
+ return 1
+ fi
+
+ # promote should fail if $vol and $clone
+ # miss either mount or promote permission
+ # case 3
+ log_must zfs allow $user mount $vol
+ user_run $user zfs promote $vol
+ log_must zfs unallow $user mount $vol
+ if [[ $vol_orig != $(get_prop origin $vol) || \
+ $clone_orig != $(get_prop origin $clone) ]];
+ then
+ return 1
+ fi
+
+ # promote should fail if $vol and $clone
+ # miss either mount or promote permission
+ # case 4
+ log_must zfs allow $user mount $clone
+ user_run $user zfs promote $vol
+ log_must zfs unallow $user mount $clone
+ if [[ $vol_orig != $(get_prop origin $vol) || \
+ $clone_orig != $(get_prop origin $clone) ]];
+ then
+ return 1
+ fi
+
+ # promote should fail if $vol and $clone
+ # miss either mount or promote permission
+ # case 5
+ log_must zfs allow $user promote $clone
+ log_must zfs allow $user mount $vol
+ user_run $user zfs promote $vol
+ log_must zfs unallow $user promote $clone
+ log_must zfs unallow $user mount $vol
+ if [[ $vol_orig != $(get_prop origin $vol) || \
+ $clone_orig != $(get_prop origin $clone) ]];
+ then
+ return 1
+ fi
+
+ # promote should fail if $vol and $clone
+ # miss either mount or promote permission
+ # case 6
+ log_must zfs allow $user promote $clone
+ log_must zfs allow $user mount $clone
+ user_run $user zfs promote $vol
+ log_must zfs unallow $user promote $clone
+ log_must zfs unallow $user mount $vol
+ if [[ $vol_orig != $(get_prop origin $vol) || \
+ $clone_orig != $(get_prop origin $clone) ]];
+ then
+ return 1
+ fi
+
+ # promote should fail if $vol and $clone
+ # miss either mount or promote permission
+ # case 7
+ log_must zfs allow $user mount $vol
+ log_must zfs allow $user mount $clone
+ user_run $user zfs promote $vol
+ log_must zfs unallow $user mount $vol
+ log_must zfs unallow $user mount $clone
+ if [[ $vol_orig != $(get_prop origin $vol) || \
+ $clone_orig != $(get_prop origin $clone) ]];
+ then
+ return 1
+ fi
+
+ # promote only succeeds when $vol and $clone
+ # have both mount and promote permission
+ # case 8
+ log_must zfs allow $user promote $clone
+ log_must zfs allow $user mount $vol
+ log_must zfs allow $user mount $clone
+ user_run $user zfs promote $vol
+ log_must zfs unallow $user promote $clone
+ log_must zfs unallow $user mount $vol
+ log_must zfs unallow $user mount $clone
+ if [[ $snap != $(get_prop origin $clone) || \
+ $clone_orig != $(get_prop origin $vol) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_vol_volsize
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ typeset oldval
+ oldval=$(get_prop volsize $vol)
+ (( newval = oldval * 2 ))
+
+ reserv_size=$(get_prop refreservation $vol)
+
+ if [[ "0" == $reserv_size ]]; then
+ # sparse volume
+ user_run $user zfs set volsize=$newval $vol
+ if [[ $oldval == $(get_prop volsize $vol) ]];
+ then
+ return 1
+ fi
+
+ else
+ # normal volume, reservation permission
+ # is required
+ user_run $user zfs set volsize=$newval $vol
+ if [[ $newval == $(get_prop volsize $vol) ]];
+ then
+ return 1
+ fi
+
+ log_must zfs allow $user reservation $vol
+ log_must zfs allow $user refreservation $vol
+ user_run $user zfs set volsize=$newval $vol
+ log_must zfs unallow $user reservation $vol
+ log_must zfs unallow $user refreservation $vol
+ if [[ $oldval == $(get_prop volsize $vol) ]];
+ then
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+function verify_allow
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset dtst=$3
+
+ typeset -i ret
+
+ user_run $user zfs allow $user allow $dtst
+ ret=$?
+ if [[ $ret -eq 0 ]]; then
+ return 1
+ fi
+
+ log_must zfs allow $user copies $dtst
+ user_run $user zfs allow $user copies $dtst
+ ret=$?
+ log_must zfs unallow $user copies $dtst
+ if [[ $ret -eq 1 ]]; then
+ return 1
+ fi
+
+ return 0
+
+}