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