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