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