1#
2# CDDL HEADER START
3#
4# The contents of this file are subject to the terms of the
5# Common Development and Distribution License (the "License").
6# You may not use this file except in compliance with the License.
7#
8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9# or http://www.opensolaris.org/os/licensing.
10# See the License for the specific language governing permissions
11# and limitations under the License.
12#
13# When distributing Covered Code, include this CDDL HEADER in each
14# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15# If applicable, add the following below this CDDL HEADER, with the
16# fields enclosed by brackets "[]" replaced with your own identifying
17# information: Portions Copyright [yyyy] [name of copyright owner]
18#
19# CDDL HEADER END
20#
21
22#
23# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26
27#
28# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
29# Copyright 2016 Nexenta Systems, Inc.
30# Copyright (c) 2018 George Melikov. All Rights Reserved.
31#
32
33. $STF_SUITE/include/libtest.shlib
34. $STF_SUITE/tests/functional/delegate/delegate.cfg
35
36#
37# Cleanup exist user/group.
38#
39function cleanup_user_group
40{
41	typeset i
42	for i in $STAFF1 $STAFF2 $OTHER1 $OTHER2 ; do
43		del_user $i
44	done
45	for i in $STAFF_GROUP $OTHER_GROUP ; do
46		del_group $i
47	done
48
49	return 0
50}
51
52#
53# Restore test file system to the original status.
54#
55function restore_root_datasets
56{
57	destroy_dataset "$ROOT_TESTFS" "-Rf"
58	log_must zfs create $ROOT_TESTFS
59
60	if is_global_zone ; then
61		destroy_dataset "$ROOT_TESTVOL" "-Rf"
62		log_must zfs create -V $VOLSIZE $ROOT_TESTVOL
63		block_device_wait
64	fi
65
66	return 0
67}
68
69#
70# Verify the specified user have permission on the dataset
71#
72# $1 dataset
73# $2 permissions which are separated by comma(,)
74# $3-n users
75#
76function verify_perm
77{
78	typeset dtst=$1
79	typeset permissions=$2
80	shift 2
81
82	if [[ -z $@ || -z $permissions || -z $dtst ]]; then
83		return 1
84	fi
85
86	typeset type=$(get_prop type $dtst)
87	permissions=$(echo $permissions | tr -s "," " ")
88
89	typeset user
90	for user in $@; do
91		typeset perm
92		for perm in $permissions; do
93			typeset -i ret=1
94			if [[ $type == "filesystem" ]]; then
95				check_fs_perm $user $perm $dtst
96				ret=$?
97			elif [[ $type == "volume" ]]; then
98				check_vol_perm $user $perm $dtst
99				ret=$?
100			fi
101
102			log_note "Check $type $user $perm $dtst"
103			if ((ret != 0)) ; then
104				log_note "Fail: $user should have $perm" \
105					"on $dtst"
106				return 1
107			fi
108		done
109	done
110
111	return 0
112}
113
114#
115# Verify the specified user have no permission on the dataset
116#
117# $1 dataset
118# $2 permissions which are separated by comma(,)
119# $3-n users
120#
121function verify_noperm
122{
123	typeset dtst=$1
124	typeset permissions=$2
125	shift 2
126
127	if [[ -z $@ || -z $permissions || -z $dtst ]]; then
128		return 1
129	fi
130
131	typeset type=$(get_prop type $dtst)
132	permissions=$(echo $permissions | tr -s "," " ")
133
134	typeset user
135	for user in $@; do
136		typeset perm
137		for perm in $permissions; do
138			typeset -i ret=1
139			if [[ $type == "filesystem" ]]; then
140				check_fs_perm $user $perm $dtst
141				ret=$?
142			elif [[ $type == "volume" ]]; then
143				check_vol_perm $user $perm $dtst
144				ret=$?
145			fi
146
147			if ((ret == 0)) ; then
148				log_note "Fail: $user should not have $perm " \
149					"on $dtst"
150				return 1
151			fi
152		done
153	done
154
155	return 0
156}
157
158function common_perm
159{
160	typeset user=$1
161	typeset perm=$2
162	typeset dtst=$3
163
164	typeset -i ret=1
165	case $perm in
166		send)
167			verify_send $user $perm $dtst
168			ret=$?
169			;;
170		allow)
171			verify_allow $user $perm $dtst
172			ret=$?
173			;;
174		userprop)
175			verify_userprop $user $perm $dtst
176			ret=$?
177			;;
178		compression|checksum|readonly)
179			verify_ccr $user $perm $dtst
180			ret=$?
181			;;
182		copies)
183			verify_copies $user $perm $dtst
184			ret=$?
185			;;
186		reservation)
187			verify_reservation $user $perm $dtst
188			ret=$?
189			;;
190		*)
191			ret=1
192			;;
193	esac
194
195	return $ret
196}
197
198function check_fs_perm
199{
200	typeset user=$1
201	typeset perm=$2
202	typeset fs=$3
203
204	typeset -i ret=1
205	case $perm in
206		create)
207			verify_fs_create $user $perm $fs
208			ret=$?
209			;;
210		destroy)
211			verify_fs_destroy $user $perm $fs
212			ret=$?
213			;;
214		snapshot)
215			verify_fs_snapshot $user $perm $fs
216			ret=$?
217			;;
218		rollback)
219			verify_fs_rollback $user $perm $fs
220			ret=$?
221			;;
222		clone)
223			verify_fs_clone $user $perm $fs
224			ret=$?
225			;;
226		rename)
227			verify_fs_rename $user $perm $fs
228			ret=$?
229			;;
230		mount)
231			verify_fs_mount $user $perm $fs
232			ret=$?
233			;;
234		share)
235			verify_fs_share $user $perm $fs
236			ret=$?
237			;;
238		mountpoint)
239			verify_fs_mountpoint $user $perm $fs
240			ret=$?
241			;;
242		promote)
243			verify_fs_promote $user $perm $fs
244			ret=$?
245			;;
246		canmount)
247			verify_fs_canmount $user $perm $fs
248			ret=$?
249			;;
250		dnodesize)
251			verify_fs_dnodesize $user $perm $fs
252			ret=$?
253			;;
254		recordsize)
255			verify_fs_recordsize $user $perm $fs
256			ret=$?
257			;;
258		quota)
259			verify_fs_quota $user $perm $fs
260			ret=$?
261			;;
262		aclmode)
263			verify_fs_aclmode $user $perm $fs
264			ret=$?
265			;;
266		aclinherit)
267			verify_fs_aclinherit $user $perm $fs
268			ret=$?
269			;;
270		snapdir)
271			verify_fs_snapdir $user $perm $fs
272			ret=$?
273			;;
274		atime|exec|devices|setuid|xattr)
275			verify_fs_aedsx $user $perm $fs
276			ret=$?
277			;;
278		zoned)
279			verify_fs_zoned $user $perm $fs
280			ret=$?
281			;;
282		sharenfs)
283			verify_fs_sharenfs $user $perm $fs
284			ret=$?
285			;;
286		receive)
287			verify_fs_receive $user $perm $fs
288			ret=$?
289			;;
290		*)
291			common_perm $user $perm $fs
292			ret=$?
293			;;
294	esac
295
296	return $ret
297}
298
299function check_vol_perm
300{
301	typeset user=$1
302	typeset perm=$2
303	typeset vol=$3
304
305	typeset -i ret=1
306	case $perm in
307		destroy)
308			verify_vol_destroy $user $perm $vol
309			ret=$?
310			;;
311		snapshot)
312			verify_vol_snapshot $user $perm $vol
313			ret=$?
314			;;
315		rollback)
316			verify_vol_rollback $user $perm $vol
317			ret=$?
318			;;
319		clone)
320			verify_vol_clone $user $perm $vol
321			ret=$?
322			;;
323		rename)
324			verify_vol_rename $user $perm $vol
325			ret=$?
326			;;
327		promote)
328			verify_vol_promote $user $perm $vol
329			ret=$?
330			;;
331		volsize)
332			verify_vol_volsize $user $perm $vol
333			ret=$?
334			;;
335		*)
336			common_perm $user $perm $vol
337			ret=$?
338			;;
339	esac
340
341	return $ret
342}
343
344function setup_unallow_testenv
345{
346	log_must restore_root_datasets
347
348	log_must zfs create $SUBFS
349
350	for dtst in $DATASETS ; do
351		log_must zfs allow -l $STAFF1 $LOCAL_SET $dtst
352		log_must zfs allow -d $STAFF2 $DESC_SET  $dtst
353		log_must zfs allow $OTHER1 $LOCAL_DESC_SET $dtst
354		log_must zfs allow $OTHER2 $LOCAL_DESC_SET $dtst
355
356		log_must verify_perm $dtst $LOCAL_SET $STAFF1
357		log_must verify_perm $dtst $LOCAL_DESC_SET $OTHER1
358		log_must verify_perm $dtst $LOCAL_DESC_SET $OTHER2
359		if [[ $dtst == $ROOT_TESTFS ]]; then
360			log_must verify_perm $SUBFS $DESC_SET $STAFF2
361			log_must verify_perm $SUBFS $LOCAL_DESC_SET $OTHER1
362			log_must verify_perm $SUBFS $LOCAL_DESC_SET $OTHER2
363		fi
364	done
365
366	return 0
367}
368
369#
370# Verify permission send for specified user on the dataset
371# $1 user
372# $2 permission
373# $3 dataset
374#
375function verify_send
376{
377	typeset user=$1
378	typeset perm=$2
379	typeset dtst=$3
380
381	typeset oldval
382	typeset stamp=${perm}.${user}.$RANDOM
383	typeset snap=$dtst@snap.$stamp
384
385	typeset -i ret=1
386
387	log_must zfs snapshot $snap
388	typeset bak_user=$TEST_BASE_DIR/bak.$user.$stamp
389	typeset bak_root=$TEST_BASE_DIR/bak.root.$stamp
390
391	user_run $user eval "zfs send $snap > $bak_user"
392	log_must eval "zfs send $snap > $bak_root"
393
394	if [[ $(checksum $bak_user) == $(checksum $bak_root) ]]; then
395		ret=0
396	fi
397
398	rm -rf $bak_user > /dev/null
399	rm -rf $bak_root > /dev/null
400
401	return $ret
402}
403
404function verify_fs_receive
405{
406	typeset user=$1
407	typeset perm=$2
408	typeset fs=$3
409
410	typeset dtst
411	typeset stamp=${perm}.${user}.$RANDOM
412	typeset newfs=$fs/newfs.$stamp
413	typeset newvol=$fs/newvol.$stamp
414	typeset bak_user=$TEST_BASE_DIR/bak.$user.$stamp
415	typeset bak_root=$TEST_BASE_DIR/bak.root.$stamp
416
417	log_must zfs create $newfs
418	typeset datasets="$newfs"
419	if is_global_zone ; then
420		log_must zfs create -V $VOLSIZE $newvol
421		block_device_wait
422		datasets="$newfs $newvol"
423	fi
424
425	for dtst in $datasets ; do
426
427		typeset dtstsnap=$dtst@snap.$stamp
428		log_must zfs snapshot $dtstsnap
429
430		log_must eval "zfs send $dtstsnap > $bak_root"
431		log_must_busy zfs destroy -rf $dtst
432
433		user_run $user eval "zfs receive $dtst < $bak_root"
434		if datasetexists $dtstsnap ; then
435			return 1
436		fi
437
438		log_must zfs allow $user create $fs
439		user_run $user eval "zfs receive $dtst < $bak_root"
440		log_must zfs unallow $user create $fs
441		if datasetexists $dtstsnap ; then
442			return 1
443		fi
444
445		log_must zfs allow $user mount $fs
446		user_run $user eval "zfs receive $dtst < $bak_root"
447		log_must zfs unallow $user mount $fs
448		if datasetexists $dtstsnap ; then
449			return 1
450		fi
451
452		log_must zfs allow $user mount,create $fs
453		user_run $user eval "zfs receive $dtst < $bak_root"
454		log_must zfs unallow $user mount,create $fs
455		if ! datasetexists $dtstsnap ; then
456			return 1
457		fi
458
459		# check the data integrity
460		log_must eval "zfs send $dtstsnap > $bak_user"
461		log_must_busy zfs destroy -rf $dtst
462		log_must eval "zfs receive $dtst < $bak_root"
463		log_must eval "zfs send $dtstsnap > $bak_root"
464		log_must_busy zfs destroy -rf $dtst
465		if [[ $(checksum $bak_user) != $(checksum $bak_root) ]]; then
466			return 1
467		fi
468
469		rm -rf $bak_user > /dev/null
470		rm -rf $bak_root > /dev/null
471
472	done
473
474	return 0
475}
476
477function verify_userprop
478{
479	typeset user=$1
480	typeset perm=$2
481	typeset dtst=$3
482
483	typeset stamp=${perm}.${user}.$RANDOM
484
485	user_run $user zfs set "$user:ts=$stamp" $dtst
486	sync_pool ${dtst%%/*}
487	if [[ $stamp != $(get_prop "$user:ts" $dtst) ]]; then
488		return 1
489	fi
490
491	return 0
492}
493
494function verify_ccr
495{
496	typeset user=$1
497	typeset perm=$2
498	typeset dtst=$3
499
500	typeset oldval
501
502	set -A modes "on" "off"
503	oldval=$(get_prop $perm $dtst)
504	if [[ $oldval == "on" ]]; then
505		n=1
506	elif [[ $oldval == "off" ]]; then
507		n=0
508	fi
509	log_note "$user zfs set $perm=${modes[$n]} $dtst"
510	user_run $user zfs set $perm=${modes[$n]} $dtst
511	if [[ ${modes[$n]} != $(get_prop $perm $dtst) ]]; then
512		return 1
513	fi
514
515	return 0
516}
517
518function verify_copies
519{
520	typeset user=$1
521	typeset perm=$2
522	typeset dtst=$3
523
524	typeset oldval
525
526	set -A modes 1 2 3
527	oldval=$(get_prop $perm $dtst)
528	if [[ $oldval -eq 1 ]]; then
529		n=1
530	elif [[ $oldval -eq 2 ]]; then
531		n=2
532	elif [[ $oldval -eq 3 ]]; then
533		n=0
534	fi
535	log_note "$user zfs set $perm=${modes[$n]} $dtst"
536	user_run $user zfs set $perm=${modes[$n]} $dtst
537	if [[ ${modes[$n]} != $(get_prop $perm $dtst) ]]; then
538		return 1
539	fi
540
541	return 0
542}
543
544function verify_reservation
545{
546	typeset user=$1
547	typeset perm=$2
548	typeset dtst=$3
549
550	typeset value32m=$(( 1024 * 1024 * 32 ))
551	typeset oldval=$(get_prop reservation $dtst)
552	user_run $user zfs set reservation=$value32m $dtst
553	if [[ $value32m != $(get_prop reservation $dtst) ]]; then
554		log_must zfs set reservation=$oldval $dtst
555		return 1
556	fi
557
558	log_must zfs set reservation=$oldval $dtst
559	return 0
560}
561
562function verify_fs_create
563{
564	typeset user=$1
565	typeset perm=$2
566	typeset fs=$3
567
568	typeset stamp=${perm}.${user}.$RANDOM
569	typeset newfs=$fs/nfs.$stamp
570	typeset newvol=$fs/nvol.$stamp
571
572	user_run $user zfs create $newfs
573	if datasetexists $newfs ; then
574		return 1
575	fi
576
577	log_must zfs allow $user mount $fs
578	user_run $user zfs create $newfs
579	log_must zfs unallow $user mount $fs
580	if ! datasetexists $newfs ; then
581		return 1
582	fi
583
584	log_must zfs destroy $newfs
585
586	if is_global_zone ; then
587		# mount permission is required for sparse volume
588		user_run $user zfs create -V 150m -s $newvol
589		block_device_wait
590		if datasetexists $newvol ; then
591			return 1
592		fi
593
594		log_must zfs allow $user mount $fs
595		user_run $user zfs create -V 150m -s $newvol
596		log_must zfs unallow $user mount $fs
597		if ! datasetexists $newvol ; then
598			return 1
599		fi
600
601		block_device_wait
602		log_must zfs destroy $newvol
603		block_device_wait
604
605		# mount and reserveration permission are
606		# required for normal volume
607		user_run $user zfs create -V 150m $newvol
608		block_device_wait
609		if datasetexists $newvol ; then
610			return 1
611		fi
612
613		log_must zfs allow $user mount $fs
614		user_run $user zfs create -V 150m $newvol
615		block_device_wait
616		log_must zfs unallow $user mount $fs
617		if datasetexists $newvol ; then
618			return 1
619		fi
620
621		log_must zfs allow $user reservation $fs
622		user_run $user zfs create -V 150m $newvol
623		block_device_wait
624		log_must zfs unallow $user reservation $fs
625		if datasetexists $newvol ; then
626			return 1
627		fi
628
629		log_must zfs allow $user refreservation $fs
630		user_run $user zfs create -V 150m $newvol
631		block_device_wait
632		log_must zfs unallow $user refreservation $fs
633		if datasetexists $newvol ; then
634			return 1
635		fi
636
637		log_must zfs allow $user mount $fs
638		log_must zfs allow $user reservation $fs
639		log_must zfs allow $user refreservation $fs
640		user_run $user zfs create -V 150m $newvol
641		log_must zfs unallow $user mount $fs
642		log_must zfs unallow $user reservation $fs
643		log_must zfs unallow $user refreservation $fs
644		if ! datasetexists $newvol ; then
645			return 1
646		fi
647
648		block_device_wait
649		log_must zfs destroy $newvol
650		block_device_wait
651	fi
652
653	return 0
654}
655
656function verify_fs_destroy
657{
658	typeset user=$1
659	typeset perm=$2
660	typeset fs=$3
661
662	if ! ismounted $fs ; then
663		user_run $user zfs destroy $fs
664		if datasetexists $fs ; then
665			return 1
666		fi
667	fi
668
669	if ismounted $fs ; then
670		user_run $user zfs destroy $fs
671		if ! datasetexists $fs ; then
672			return 1
673		fi
674
675		# mount permission is required
676		log_must zfs allow $user mount $fs
677		user_run $user zfs destroy $fs
678		if datasetexists $fs ; then
679			return 1
680		fi
681	fi
682
683	return 0
684}
685
686# Verify that given the correct delegation, a regular user can:
687#	Take a snapshot of an unmounted dataset
688# 	Take a snapshot of a mounted dataset
689#	Create a snapshot by making a directory in the .zfs/snapshot directory
690function verify_fs_snapshot
691{
692	typeset user=$1
693	typeset perm=$2
694	typeset fs=$3
695
696	typeset stamp=${perm}.${user}.$RANDOM
697	typeset snap=$fs@snap.$stamp
698	typeset mntpt=$(get_prop mountpoint $fs)
699
700	if [[ "yes" == $(get_prop mounted $fs) ]]; then
701		log_must zfs umount $fs
702	fi
703
704	user_run $user zfs snapshot $snap
705	if ! datasetexists $snap ; then
706		return 1
707	fi
708	log_must zfs destroy $snap
709
710	if [[ "no" == $(get_prop mounted $fs) ]]; then
711		log_must zfs mount $fs
712	fi
713
714	user_run $user zfs snapshot $snap
715	if ! datasetexists $snap ; then
716		return 1
717	fi
718	log_must zfs destroy $snap
719
720	# Creating snaps via mkdir is not supported on FreeBSD
721	if ! is_freebsd; then
722		typeset snapdir=${mntpt}/.zfs/snapshot/snap.$stamp
723		user_run $user mkdir $snapdir
724		if ! datasetexists $snap ; then
725			return 1
726		fi
727		log_must zfs destroy $snap
728	fi
729
730	return 0
731}
732
733function verify_fs_rollback
734{
735	typeset user=$1
736	typeset perm=$2
737	typeset fs=$3
738
739	typeset oldval
740	typeset stamp=${perm}.${user}.$RANDOM
741	typeset snap=$fs@snap.$stamp
742	typeset mntpt=$(get_prop mountpoint $fs)
743
744	oldval=$(datasetcksum $fs)
745	log_must zfs snapshot $snap
746
747	if ! ismounted $fs; then
748		log_must zfs mount $fs
749	fi
750	log_must touch $mntpt/testfile.$stamp
751
752	user_run $user zfs rollback -R $snap
753	if is_global_zone ; then
754		if [[ $oldval != $(datasetcksum $fs) ]]; then
755			return 1
756		fi
757	else
758		# datasetcksum can not be used in local zone
759		if [[ -e $mntpt/testfile.$stamp ]]; then
760			return 1
761		fi
762	fi
763
764	return 0
765}
766
767function verify_fs_clone
768{
769	typeset user=$1
770	typeset perm=$2
771	typeset fs=$3
772
773	typeset stamp=${perm}.${user}.$RANDOM
774	typeset basefs=${fs%/*}
775	typeset snap=$fs@snap.$stamp
776	typeset clone=$basefs/cfs.$stamp
777
778	log_must zfs snapshot $snap
779	user_run $user zfs clone $snap $clone
780	if datasetexists $clone ; then
781		return 1
782	fi
783
784	log_must zfs allow $user create $basefs
785	user_run $user zfs clone $snap $clone
786	log_must zfs unallow $user create $basefs
787	if datasetexists $clone ; then
788		return 1
789	fi
790
791	log_must zfs allow $user mount $basefs
792	user_run $user zfs clone $snap $clone
793	log_must zfs unallow $user mount $basefs
794	if datasetexists $clone ; then
795		return 1
796	fi
797
798	log_must zfs allow $user mount $basefs
799	log_must zfs allow $user create $basefs
800	user_run $user zfs clone $snap $clone
801	log_must zfs unallow $user create $basefs
802	log_must zfs unallow $user mount $basefs
803	if ! datasetexists $clone ; then
804		return 1
805	fi
806
807	log_must zfs destroy -R $snap
808
809	return 0
810}
811
812function verify_fs_rename
813{
814	typeset user=$1
815	typeset perm=$2
816	typeset fs=$3
817
818	typeset stamp=${perm}.${user}.$RANDOM
819	typeset basefs=${fs%/*}
820	typeset snap=$fs@snap.$stamp
821	typeset renamefs=$basefs/nfs.$stamp
822
823	if ! ismounted $fs; then
824		log_must zfs mount $fs
825	fi
826
827	# case 1
828	user_run $user zfs rename $fs $renamefs
829	if datasetexists $renamefs ; then
830		return 1
831	fi
832
833	# case 2
834	log_must zfs allow $user create $basefs
835	user_run $user zfs rename $fs $renamefs
836	log_must zfs unallow $user create $basefs
837	if datasetexists $renamefs ; then
838		return 1
839	fi
840
841	# case 3
842	log_must zfs allow $user mount $basefs
843	user_run $user zfs rename $fs $renamefs
844	log_must zfs unallow $user mount $basefs
845	if datasetexists $renamefs ; then
846		return 1
847	fi
848
849	# case 4
850	log_must zfs allow $user mount $fs
851	user_run $user zfs rename $fs $renamefs
852	if datasetexists $renamefs ; then
853		log_must zfs unallow $user mount $renamefs
854		return 1
855	fi
856	log_must zfs unallow $user mount $fs
857
858	# case 5
859	log_must zfs allow $user create $basefs
860	log_must zfs allow $user mount $fs
861	user_run $user zfs rename $fs $renamefs
862	log_must zfs unallow $user create $basefs
863	if datasetexists $renamefs ; then
864		log_must zfs unallow $user mount $renamefs
865		return 1
866	fi
867	log_must zfs unallow $user mount $fs
868
869	# case 6
870	log_must zfs allow $user mount $basefs
871	log_must zfs allow $user mount $fs
872	user_run $user zfs rename $fs $renamefs
873	log_must zfs unallow $user mount $basefs
874	if datasetexists $renamefs ; then
875		log_must zfs unallow $user mount $renamefs
876		return 1
877	fi
878	log_must zfs unallow $user mount $fs
879
880	# case 7
881	log_must zfs allow $user create $basefs
882	log_must zfs allow $user mount $basefs
883	user_run $user zfs rename $fs $renamefs
884	log_must zfs unallow $user mount $basefs
885	log_must zfs unallow $user create $basefs
886	if ! datasetexists $renamefs ; then
887		return 1
888	fi
889
890	log_must zfs rename $renamefs $fs
891
892	return 0
893}
894
895function verify_fs_mount
896{
897	typeset user=$1
898	typeset perm=$2
899	typeset fs=$3
900
901	typeset stamp=${perm}.${user}.$RANDOM
902	typeset mntpt=$(get_prop mountpoint $fs)
903	typeset newmntpt=$TEST_BASE_DIR/mnt.$stamp
904
905	if ismounted $fs ; then
906		user_run $user zfs unmount $fs
907		if ismounted $fs ; then
908			return 1
909		fi
910	fi
911
912	if ! ismounted $fs ; then
913		log_must zfs set mountpoint=$newmntpt $fs
914		log_must rm -rf $newmntpt
915		log_must mkdir $newmntpt
916
917		user_run $user zfs mount $fs
918		if ismounted $fs ; then
919			return 1
920		fi
921
922		# mountpoint's owner must be the user
923		log_must chown $user $newmntpt
924		user_run $user zfs mount $fs
925		if ! ismounted $fs ; then
926			return 1
927		fi
928		log_must zfs umount $fs
929		log_must rm -rf $newmntpt
930		log_must zfs set mountpoint=$mntpt $fs
931	fi
932
933	return 0
934}
935
936function verify_fs_share
937{
938	typeset user=$1
939	typeset perm=$2
940	typeset fs=$3
941	typeset -i ret=0
942
943	svcadm enable -rs nfs/server
944	typeset stat=$(svcs -H -o STA nfs/server:default)
945	if [[ $stat != "ON" ]]; then
946		log_fail "Could not enable nfs/server"
947	fi
948
949	log_must zfs set sharenfs=on $fs
950	zfs unshare $fs
951
952	user_run $user zfs share $fs
953	if ! is_shared $fs; then
954		ret=1
955	fi
956
957	zfs unshare $fs
958	log_must zfs set sharenfs=off $fs
959
960	return $ret
961}
962
963function verify_fs_mountpoint
964{
965	typeset user=$1
966	typeset perm=$2
967	typeset fs=$3
968
969	typeset stamp=${perm}.${user}.$RANDOM
970	typeset mntpt=$(get_prop mountpoint $fs)
971	typeset newmntpt=$TEST_BASE_DIR/mnt.$stamp
972
973	if ! ismounted $fs ; then
974		user_run $user zfs set mountpoint=$newmntpt $fs
975		if [[ $newmntpt != \
976			$(get_prop mountpoint $fs) ]] ; then
977			return 1
978		fi
979		log_must zfs set mountpoint=$mntpt $fs
980	fi
981
982	if ismounted $fs ; then
983		user_run $user zfs set mountpoint=$newmntpt $fs
984		if [[ $mntpt != $(get_prop mountpoint $fs) ]]; then
985			return 1
986		fi
987
988		# require mount permission when fs is mounted
989		log_must zfs allow $user mount $fs
990		user_run $user zfs set mountpoint=$newmntpt $fs
991		log_must zfs unallow $user mount $fs
992		if [[ $newmntpt != \
993			$(get_prop mountpoint $fs) ]] ; then
994			return 1
995		fi
996		log_must zfs set mountpoint=$mntpt $fs
997	fi
998
999	return 0
1000}
1001
1002function verify_fs_promote
1003{
1004	typeset user=$1
1005	typeset perm=$2
1006	typeset fs=$3
1007
1008	typeset stamp=${perm}.${user}.$RANDOM
1009	typeset basefs=${fs%/*}
1010	typeset snap=$fs@snap.$stamp
1011	typeset clone=$basefs/cfs.$stamp
1012
1013	log_must zfs snapshot $snap
1014	log_must zfs clone $snap $clone
1015	log_must zfs promote $clone
1016
1017	typeset fs_orig=$(get_prop origin $fs)
1018	typeset clone_orig=$(get_prop origin $clone)
1019
1020	user_run $user zfs promote $fs
1021	# promote should fail if original fs does not have
1022	# promote permission
1023	if [[ $fs_orig != $(get_prop origin $fs) || \
1024		$clone_orig != $(get_prop origin $clone) ]]; then
1025		return 1
1026	fi
1027
1028	log_must zfs allow $user promote $clone
1029	user_run $user zfs promote $fs
1030	log_must zfs unallow $user promote $clone
1031	if [[ $fs_orig != $(get_prop origin $fs) || \
1032		$clone_orig != $(get_prop origin $clone) ]]; then
1033		return 1
1034	fi
1035
1036	log_must zfs allow $user mount $fs
1037	user_run $user zfs promote $fs
1038	log_must zfs unallow $user mount $fs
1039	if [[ $fs_orig != $(get_prop origin $fs) || \
1040		$clone_orig != $(get_prop origin $clone) ]]; then
1041		return 1
1042	fi
1043
1044	log_must zfs allow $user mount $fs
1045	log_must zfs allow $user promote $clone
1046	user_run $user zfs promote $fs
1047	log_must zfs unallow $user promote $clone
1048	log_must zfs unallow $user mount $fs
1049	if [[ $snap != $(get_prop origin $clone) || \
1050		$clone_orig != $(get_prop origin $fs) ]]; then
1051		return 1
1052	fi
1053
1054	return 0
1055}
1056
1057function verify_fs_canmount
1058{
1059	typeset user=$1
1060	typeset perm=$2
1061	typeset fs=$3
1062
1063	typeset oldval
1064	typeset stamp=${perm}.${user}.$RANDOM
1065
1066	if ! ismounted $fs ; then
1067		set -A modes "on" "off"
1068		oldval=$(get_prop $perm $fs)
1069		if [[ $oldval == "on" ]]; then
1070			n=1
1071		elif [[ $oldval == "off" ]]; then
1072			n=0
1073		fi
1074		log_note "$user zfs set $perm=${modes[$n]} $fs"
1075		user_run $user zfs set $perm=${modes[$n]} $fs
1076		if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
1077			return 1
1078		fi
1079	fi
1080
1081
1082	# fs is mounted
1083	if ismounted $fs ; then
1084		# property value does not change if
1085		# no mount permission
1086		set -A modes "on" "off"
1087		oldval=$(get_prop $perm $fs)
1088		if [[ $oldval == "on" ]]; then
1089			n=1
1090		elif [[ $oldval == "off" ]]; then
1091			n=0
1092		fi
1093		log_note "$user zfs set $perm=${modes[$n]} $fs"
1094		log_must zfs allow $user mount $fs
1095		user_run $user zfs set $perm=${modes[$n]} $fs
1096		log_must zfs unallow $user mount $fs
1097		if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
1098			return 1
1099		fi
1100	fi
1101
1102	return 0
1103}
1104
1105function verify_fs_recordsize
1106{
1107	typeset user=$1
1108	typeset perm=$2
1109	typeset fs=$3
1110
1111	typeset value8k=$(( 1024 * 8 ))
1112	user_run $user zfs set recordsize=$value8k $fs
1113	if [[ $value8k != $(get_prop recordsize $fs) ]]; then
1114		return 1
1115	fi
1116
1117	return 0
1118}
1119
1120function verify_fs_dnodesize
1121{
1122	typeset user=$1
1123	typeset perm=$2
1124	typeset fs=$3
1125	value="2k"
1126
1127	user_run $user zfs set dnodesize=$value $fs
1128	if [[ $value != $(get_prop dnodesize $fs) ]]; then
1129		return 1
1130	fi
1131
1132	return 0
1133}
1134
1135function verify_fs_quota
1136{
1137	typeset user=$1
1138	typeset perm=$2
1139	typeset fs=$3
1140
1141	typeset value32m=$(( 1024 * 1024 * 32 ))
1142	user_run $user zfs set quota=$value32m $fs
1143	if [[ $value32m != $(get_prop quota $fs) ]]; then
1144		return 1
1145	fi
1146
1147	return 0
1148}
1149
1150function verify_fs_aclmode
1151{
1152	typeset user=$1
1153	typeset perm=$2
1154	typeset fs=$3
1155
1156	typeset oldval
1157	set -A modes "discard" "groupmask" "passthrough"
1158	oldval=$(get_prop $perm $fs)
1159	if [[ $oldval == "discard" ]]; then
1160		n=1
1161	elif [[ $oldval == "groupmask" ]]; then
1162		n=2
1163	elif [[ $oldval == "passthrough" ]]; then
1164		n=0
1165	fi
1166	log_note "$user zfs set aclmode=${modes[$n]} $fs"
1167	user_run $user zfs set aclmode=${modes[$n]} $fs
1168	if [[ ${modes[$n]} != $(get_prop aclmode $fs) ]]; then
1169		return 1
1170	fi
1171
1172	return 0
1173}
1174
1175function verify_fs_aclinherit
1176{
1177	typeset user=$1
1178	typeset perm=$2
1179	typeset fs=$3
1180
1181	#
1182	# PSARC/2008/231 change the default value of aclinherit to "restricted"
1183	# but still keep the old interface of "secure"
1184	#
1185
1186	typeset oldval
1187	set -A modes "discard" "noallow" "secure" "passthrough"
1188	oldval=$(get_prop $perm $fs)
1189	if [[ $oldval == "discard" ]]; then
1190		n=1
1191	elif [[ $oldval == "noallow" ]]; then
1192		n=2
1193	elif [[ $oldval == "secure" || $oldval == "restricted" ]]; then
1194		n=3
1195	elif [[ $oldval == "passthrough" ]]; then
1196		n=0
1197	fi
1198	log_note "$user zfs set aclinherit=${modes[$n]} $fs"
1199	user_run $user zfs set aclinherit=${modes[$n]} $fs
1200
1201	typeset newval=$(get_prop aclinherit $fs)
1202	if [[ ${modes[$n]} == "secure" && $newval == "restricted" ]]; then
1203		return 0
1204	elif [[ ${modes[$n]} != $(get_prop aclinherit $fs) ]]; then
1205		return 1
1206	fi
1207
1208	return 0
1209}
1210
1211function verify_fs_snapdir
1212{
1213	typeset user=$1
1214	typeset perm=$2
1215	typeset fs=$3
1216
1217	typeset oldval
1218	set -A modes "visible" "hidden"
1219	oldval=$(get_prop $perm $fs)
1220	if [[ $oldval == "visible" ]]; then
1221		n=1
1222	elif [[ $oldval == "hidden" ]]; then
1223		n=0
1224	fi
1225	log_note "$user zfs set snapdir=${modes[$n]} $fs"
1226	user_run $user zfs set snapdir=${modes[$n]} $fs
1227	if [[ ${modes[$n]} != $(get_prop snapdir $fs) ]]; then
1228		return 1
1229	fi
1230
1231	return 0
1232}
1233
1234function verify_fs_aedsx
1235{
1236	typeset user=$1
1237	typeset perm=$2
1238	typeset fs=$3
1239
1240	typeset oldval
1241	set -A modes "on" "off"
1242	oldval=$(get_prop $perm $fs)
1243	if [[ $oldval == "on" ]]; then
1244		n=1
1245	elif [[ $oldval == "off" ]]; then
1246		n=0
1247	fi
1248	log_note "$user zfs set $perm=${modes[$n]} $fs"
1249	user_run $user zfs set $perm=${modes[$n]} $fs
1250	if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
1251		return 1
1252	fi
1253
1254	return 0
1255}
1256
1257function verify_fs_zoned
1258{
1259	typeset user=$1
1260	typeset perm=$2
1261	typeset fs=$3
1262
1263	typeset oldval
1264	set -A modes "on" "off"
1265	oldval=$(get_prop $perm $fs)
1266	if [[ $oldval == "on" ]]; then
1267		n=1
1268	elif [[ $oldval == "off" ]]; then
1269		n=0
1270	fi
1271	log_note "$user zfs set $perm=${modes[$n]} $fs"
1272	if is_global_zone ; then
1273		if ! ismounted $fs ; then
1274			user_run $user zfs set \
1275				$perm=${modes[$n]} $fs
1276			if [[ ${modes[$n]} != \
1277				$(get_prop $perm $fs) ]]; then
1278				return 1
1279			fi
1280			if [[ $n -eq 0 ]]; then
1281				log_mustnot zfs mount $fs
1282			else
1283				log_must zfs mount $fs
1284			fi
1285		fi
1286
1287		if ismounted $fs; then
1288			# n always is 1 in this case
1289			user_run $user zfs set \
1290				$perm=${modes[$n]} $fs
1291			if [[ $oldval != \
1292				$(get_prop $perm $fs) ]]; then
1293				return 1
1294			fi
1295
1296			# mount permission is needed
1297			# to make zoned=on
1298			log_must zfs allow $user mount $fs
1299			user_run $user zfs set \
1300				$perm=${modes[$n]} $fs
1301			log_must zfs unallow $user mount $fs
1302			if [[ ${modes[$n]} != \
1303				$(get_prop $perm $fs) ]]; then
1304				return 1
1305			fi
1306		fi
1307	fi
1308
1309	if ! is_global_zone; then
1310		user_run $user zfs set $perm=${modes[$n]} $fs
1311		if [[ $oldval != $(get_prop $perm $fs) ]]; then
1312			return 1
1313		fi
1314	fi
1315
1316	return 0
1317}
1318
1319function verify_fs_sharenfs
1320{
1321	typeset user=$1
1322	typeset perm=$2
1323	typeset fs=$3
1324	typeset nmode omode
1325
1326	omode=$(get_prop $perm $fs)
1327	if [[ $omode == "off" ]]; then
1328		nmode="on"
1329	else
1330		nmode="off"
1331	fi
1332
1333	log_note "$user zfs set $perm=$nmode $fs"
1334	user_run $user zfs set $perm=$nmode $fs
1335	if [[ $(get_prop $perm $fs) != $nmode ]]; then
1336		return 1
1337	fi
1338
1339	log_note "$user zfs set $perm=$omode $fs"
1340	user_run $user zfs set $perm=$omode $fs
1341	if [[ $(get_prop $perm $fs) != $omode ]]; then
1342		return 1
1343	fi
1344
1345	return 0
1346}
1347
1348function verify_vol_destroy
1349{
1350	typeset user=$1
1351	typeset perm=$2
1352	typeset vol=$3
1353
1354	user_run $user zfs destroy $vol
1355	if ! datasetexists $vol ; then
1356		return 1
1357	fi
1358
1359	# mount permission is required
1360	log_must zfs allow $user mount $vol
1361	user_run $user zfs destroy $vol
1362	if datasetexists $vol ; then
1363		return 1
1364	fi
1365
1366	return 0
1367}
1368
1369function verify_vol_snapshot
1370{
1371	typeset user=$1
1372	typeset perm=$2
1373	typeset vol=$3
1374
1375	typeset stamp=${perm}.${user}.$RANDOM
1376	typeset basevol=${vol%/*}
1377	typeset snap=$vol@snap.$stamp
1378
1379	user_run $user zfs snapshot $snap
1380	if datasetexists $snap ; then
1381		return 1
1382	fi
1383
1384	log_must zfs allow $user mount $vol
1385	user_run $user zfs snapshot $snap
1386	log_must zfs unallow $user mount $vol
1387	if ! datasetexists $snap ; then
1388		return 1
1389	fi
1390
1391	return 0
1392}
1393
1394function verify_vol_rollback
1395{
1396	typeset user=$1
1397	typeset perm=$2
1398	typeset vol=$3
1399
1400	typeset stamp=${perm}.${user}.$RANDOM
1401	typeset basevol=${vol%/*}
1402	typeset snap=$vol@snap.$stamp
1403
1404	typeset oldval
1405	log_must zfs snapshot $snap
1406	oldval=$(datasetcksum $vol)
1407
1408	log_must dd if=/dev/urandom of=$ZVOL_RDEVDIR/$vol \
1409		bs=512 count=1
1410
1411	user_run $user zfs rollback -R $snap
1412	sleep 10
1413	if [[ $oldval == $(datasetcksum $vol) ]]; then
1414		return 1
1415	fi
1416
1417	# rollback on volume has to be with mount permission
1418	log_must zfs allow $user mount $vol
1419	user_run $user zfs rollback -R $snap
1420	sleep 10
1421	log_must zfs unallow $user mount $vol
1422	if [[ $oldval != $(datasetcksum $vol) ]]; then
1423		return 1
1424	fi
1425
1426	return 0
1427}
1428
1429function verify_vol_clone
1430{
1431	typeset user=$1
1432	typeset perm=$2
1433	typeset vol=$3
1434
1435	typeset stamp=${perm}.${user}.$RANDOM
1436	typeset basevol=${vol%/*}
1437	typeset snap=$vol@snap.$stamp
1438	typeset clone=$basevol/cvol.$stamp
1439
1440	log_must zfs snapshot $snap
1441
1442	user_run $user zfs clone $snap $clone
1443	if datasetexists $clone ; then
1444		return 1
1445	fi
1446
1447	log_must zfs allow $user create $basevol
1448	user_run $user zfs clone $snap $clone
1449	log_must zfs unallow $user create $basevol
1450	if datasetexists $clone ; then
1451		return 1
1452	fi
1453
1454	log_must zfs allow $user mount $basevol
1455	user_run $user zfs clone $snap $clone
1456	log_must zfs unallow $user mount $basevol
1457	if datasetexists $clone ; then
1458		return 1
1459	fi
1460
1461	# require create permission on parent and
1462	# mount permission on itself as well
1463	log_must zfs allow $user mount $basevol
1464	log_must zfs allow $user create $basevol
1465	user_run $user zfs clone $snap $clone
1466	log_must zfs unallow $user create $basevol
1467	log_must zfs unallow $user mount $basevol
1468	if ! datasetexists $clone ; then
1469		return 1
1470	fi
1471
1472	return 0
1473}
1474
1475function verify_vol_rename
1476{
1477	typeset user=$1
1478	typeset perm=$2
1479	typeset vol=$3
1480
1481	typeset stamp=${perm}.${user}.$RANDOM
1482	typeset basevol=${vol%/*}
1483	typeset snap=$vol@snap.$stamp
1484	typeset clone=$basevol/cvol.$stamp
1485	typeset renamevol=$basevol/nvol.$stamp
1486
1487	user_run $user zfs rename $vol $renamevol
1488	if datasetexists $renamevol ; then
1489		return 1
1490	fi
1491
1492	log_must zfs allow $user create $basevol
1493	user_run $user zfs rename $vol $renamevol
1494	log_must zfs unallow $user create $basevol
1495	if datasetexists $renamevol ; then
1496		return 1
1497	fi
1498
1499	log_must zfs allow $user mount $basevol
1500	user_run $user zfs rename $vol $renamevol
1501	log_must zfs unallow $user mount $basevol
1502	if datasetexists $renamevol ; then
1503		return 1
1504	fi
1505
1506	# require both create permission on parent and
1507	# mount permission on parent as well
1508	log_must zfs allow $user mount $basevol
1509	log_must zfs allow $user create $basevol
1510	user_run $user zfs rename $vol $renamevol
1511	log_must zfs unallow $user mount $basevol
1512	log_must zfs unallow $user create $basevol
1513	if ! datasetexists $renamevol ; then
1514		return 1
1515	fi
1516
1517	log_must zfs rename $renamevol $vol
1518
1519	return 0
1520}
1521
1522function verify_vol_promote
1523{
1524	typeset user=$1
1525	typeset perm=$2
1526	typeset vol=$3
1527
1528	typeset stamp=${perm}.${user}.$RANDOM
1529	typeset basevol=${vol%/*}
1530	typeset snap=$vol@snap.$stamp
1531	typeset clone=$basevol/cvol.$stamp
1532
1533	log_must zfs snapshot $snap
1534	log_must zfs clone $snap $clone
1535	log_must zfs promote $clone
1536
1537	typeset vol_orig=$(get_prop origin $vol)
1538	typeset clone_orig=$(get_prop origin $clone)
1539
1540	# promote should fail if $vol and $clone
1541	# miss either mount or promote permission
1542	# case 1
1543	user_run $user zfs promote $vol
1544	if [[ $vol_orig != $(get_prop origin $vol) || \
1545		$clone_orig != $(get_prop origin $clone) ]];
1546	then
1547		return 1
1548	fi
1549
1550	# promote should fail if $vol and $clone
1551	# miss either mount or promote permission
1552	# case 2
1553	log_must zfs allow $user promote $clone
1554	user_run $user zfs promote $vol
1555	log_must zfs unallow $user promote $clone
1556	if [[ $vol_orig != $(get_prop origin $vol) || \
1557		$clone_orig != $(get_prop origin $clone) ]];
1558	then
1559		return 1
1560	fi
1561
1562	# promote should fail if $vol and $clone
1563	# miss either mount or promote permission
1564	# case 3
1565	log_must zfs allow $user mount $vol
1566	user_run $user zfs promote $vol
1567	log_must zfs unallow $user mount $vol
1568	if [[ $vol_orig != $(get_prop origin $vol) || \
1569		$clone_orig != $(get_prop origin $clone) ]];
1570	then
1571		return 1
1572	fi
1573
1574	# promote should fail if $vol and $clone
1575	# miss either mount or promote permission
1576	# case 4
1577	log_must zfs allow $user mount $clone
1578	user_run $user zfs promote $vol
1579	log_must zfs unallow $user mount $clone
1580	if [[ $vol_orig != $(get_prop origin $vol) || \
1581		$clone_orig != $(get_prop origin $clone) ]];
1582	then
1583		return 1
1584	fi
1585
1586	# promote should fail if $vol and $clone
1587	# miss either mount or promote permission
1588	# case 5
1589	log_must zfs allow $user promote $clone
1590	log_must zfs allow $user mount $vol
1591	user_run $user zfs promote $vol
1592	log_must zfs unallow $user promote $clone
1593	log_must zfs unallow $user mount $vol
1594	if [[ $vol_orig != $(get_prop origin $vol) || \
1595		$clone_orig != $(get_prop origin $clone) ]];
1596	then
1597		return 1
1598	fi
1599
1600	# promote should fail if $vol and $clone
1601	# miss either mount or promote permission
1602	# case 6
1603	log_must zfs allow $user promote $clone
1604	log_must zfs allow $user mount $clone
1605	user_run $user zfs promote $vol
1606	log_must zfs unallow $user promote $clone
1607	log_must zfs unallow $user mount $vol
1608	if [[ $vol_orig != $(get_prop origin $vol) || \
1609		$clone_orig != $(get_prop origin $clone) ]];
1610	then
1611		return 1
1612	fi
1613
1614	# promote should fail if $vol and $clone
1615	# miss either mount or promote permission
1616	# case 7
1617	log_must zfs allow $user mount $vol
1618	log_must zfs allow $user mount $clone
1619	user_run $user zfs promote $vol
1620	log_must zfs unallow $user mount $vol
1621	log_must zfs unallow $user mount $clone
1622	if [[ $vol_orig != $(get_prop origin $vol) || \
1623		$clone_orig != $(get_prop origin $clone) ]];
1624	then
1625		return 1
1626	fi
1627
1628	# promote only succeeds when $vol and $clone
1629	# have both mount and promote permission
1630	# case 8
1631	log_must zfs allow $user promote $clone
1632	log_must zfs allow $user mount $vol
1633	log_must zfs allow $user mount $clone
1634	user_run $user zfs promote $vol
1635	log_must zfs unallow $user promote $clone
1636	log_must zfs unallow $user mount $vol
1637	log_must zfs unallow $user mount $clone
1638	if [[ $snap != $(get_prop origin $clone) || \
1639		$clone_orig != $(get_prop origin $vol) ]]; then
1640		return 1
1641	fi
1642
1643	return 0
1644}
1645
1646function verify_vol_volsize
1647{
1648	typeset user=$1
1649	typeset perm=$2
1650	typeset vol=$3
1651
1652	typeset oldval
1653	oldval=$(get_prop volsize $vol)
1654	(( newval = oldval * 2 ))
1655
1656	reserv_size=$(get_prop refreservation $vol)
1657
1658	if [[ "0" == $reserv_size ]]; then
1659		# sparse volume
1660		user_run $user zfs set volsize=$newval $vol
1661		if [[ $oldval == $(get_prop volsize $vol) ]];
1662		then
1663			return 1
1664		fi
1665
1666	else
1667		# normal volume, reservation permission
1668		# is required
1669		user_run $user zfs set volsize=$newval $vol
1670		if [[ $newval == $(get_prop volsize $vol) ]];
1671		then
1672			return 1
1673		fi
1674
1675		log_must zfs allow $user reservation $vol
1676		log_must zfs allow $user refreservation $vol
1677		user_run $user zfs set volsize=$newval $vol
1678		log_must zfs unallow $user reservation $vol
1679		log_must zfs unallow $user refreservation $vol
1680		if [[ $oldval == $(get_prop volsize $vol) ]];
1681		then
1682			return 1
1683		fi
1684	fi
1685
1686	return 0
1687}
1688
1689function verify_allow
1690{
1691	typeset user=$1
1692	typeset perm=$2
1693	typeset dtst=$3
1694
1695	typeset -i ret
1696
1697	user_run $user zfs allow $user allow $dtst
1698	ret=$?
1699	if [[ $ret -eq 0 ]]; then
1700		return 1
1701	fi
1702
1703	log_must zfs allow $user copies $dtst
1704	user_run $user zfs allow $user copies $dtst
1705	ret=$?
1706	log_must zfs unallow $user copies $dtst
1707	if [[ $ret -eq 1 ]]; then
1708		return 1
1709	fi
1710
1711	return 0
1712
1713}
1714