1d583b39bSJohn Wren Kennedy#!/usr/bin/ksh -p
2d583b39bSJohn Wren Kennedy#
3d583b39bSJohn Wren Kennedy# CDDL HEADER START
4d583b39bSJohn Wren Kennedy#
5d583b39bSJohn Wren Kennedy# The contents of this file are subject to the terms of the
6d583b39bSJohn Wren Kennedy# Common Development and Distribution License (the "License").
7d583b39bSJohn Wren Kennedy# You may not use this file except in compliance with the License.
8d583b39bSJohn Wren Kennedy#
9d583b39bSJohn Wren Kennedy# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10d583b39bSJohn Wren Kennedy# or http://www.opensolaris.org/os/licensing.
11d583b39bSJohn Wren Kennedy# See the License for the specific language governing permissions
12d583b39bSJohn Wren Kennedy# and limitations under the License.
13d583b39bSJohn Wren Kennedy#
14d583b39bSJohn Wren Kennedy# When distributing Covered Code, include this CDDL HEADER in each
15d583b39bSJohn Wren Kennedy# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16d583b39bSJohn Wren Kennedy# If applicable, add the following below this CDDL HEADER, with the
17d583b39bSJohn Wren Kennedy# fields enclosed by brackets "[]" replaced with your own identifying
18d583b39bSJohn Wren Kennedy# information: Portions Copyright [yyyy] [name of copyright owner]
19d583b39bSJohn Wren Kennedy#
20d583b39bSJohn Wren Kennedy# CDDL HEADER END
21d583b39bSJohn Wren Kennedy#
22d583b39bSJohn Wren Kennedy
23d583b39bSJohn Wren Kennedy#
24d583b39bSJohn Wren Kennedy# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
25d583b39bSJohn Wren Kennedy# Use is subject to license terms.
26d583b39bSJohn Wren Kennedy#
27d583b39bSJohn Wren Kennedy
28d583b39bSJohn Wren Kennedy#
29*1d32ba66SJohn Wren Kennedy# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
30232f5a2eSYuri Pankov# Copyright 2016 Nexenta Systems, Inc.
31d583b39bSJohn Wren Kennedy#
32d583b39bSJohn Wren Kennedy
33d583b39bSJohn Wren Kennedy
34d583b39bSJohn Wren Kennedy. $STF_SUITE/tests/functional/acl/acl_common.kshlib
35d583b39bSJohn Wren Kennedy
36d583b39bSJohn Wren Kennedy# DESCRIPTION:
37232f5a2eSYuri Pankov# Verify chmod have correct behaviour on directories and files when
38232f5a2eSYuri Pankov# filesystem has the different aclmode setting
39d583b39bSJohn Wren Kennedy#
40d583b39bSJohn Wren Kennedy# STRATEGY:
41232f5a2eSYuri Pankov# 1. Loop super user and non-super user to run the test case.
42232f5a2eSYuri Pankov# 2. Create basedir and a set of subdirectores and files within it.
43232f5a2eSYuri Pankov# 3. Separately chmod basedir with different aclmode options,
44232f5a2eSYuri Pankov#    combine with the variable setting of aclmode:
45232f5a2eSYuri Pankov#    "discard", "groupmask", or "passthrough".
46232f5a2eSYuri Pankov# 4. Verify each directories and files have the correct access control
47232f5a2eSYuri Pankov#    capability.
48d583b39bSJohn Wren Kennedy
49d583b39bSJohn Wren Kennedyverify_runnable "both"
50d583b39bSJohn Wren Kennedy
51d583b39bSJohn Wren Kennedyfunction cleanup
52d583b39bSJohn Wren Kennedy{
53d583b39bSJohn Wren Kennedy	(( ${#cwd} != 0 )) && cd $cwd
54d583b39bSJohn Wren Kennedy
55*1d32ba66SJohn Wren Kennedy	[[ -f $TARFILE ]] && log_must rm -f $TARFILE
56*1d32ba66SJohn Wren Kennedy	[[ -d $basedir ]] && log_must rm -rf $basedir
57d583b39bSJohn Wren Kennedy}
58d583b39bSJohn Wren Kennedy
59232f5a2eSYuri Pankovlog_assert "Verify chmod have correct behaviour to directory and file when" \
60232f5a2eSYuri Pankov    "filesystem has the different aclmode setting"
61d583b39bSJohn Wren Kennedylog_onexit cleanup
62d583b39bSJohn Wren Kennedy
63232f5a2eSYuri Pankovset -A aclmode_flag "discard" "groupmask" "passthrough"
64232f5a2eSYuri Pankov
65232f5a2eSYuri Pankovset -A ace_prefix \
66232f5a2eSYuri Pankov    "user:$ZFS_ACL_OTHER1" \
67232f5a2eSYuri Pankov    "user:$ZFS_ACL_OTHER2" \
68232f5a2eSYuri Pankov    "group:$ZFS_ACL_STAFF_GROUP" \
69232f5a2eSYuri Pankov    "group:$ZFS_ACL_OTHER_GROUP"
70232f5a2eSYuri Pankov
71232f5a2eSYuri Pankovset -A argv "000" "444" "644" "777" "755" "231" "562" "413"
72232f5a2eSYuri Pankov
73232f5a2eSYuri Pankovset -A ace_file_preset \
74232f5a2eSYuri Pankov    "read_data" \
75232f5a2eSYuri Pankov    "write_data" \
76232f5a2eSYuri Pankov    "append_data" \
77232f5a2eSYuri Pankov    "execute" \
78232f5a2eSYuri Pankov    "read_data/write_data" \
79232f5a2eSYuri Pankov    "read_data/write_data/append_data" \
80232f5a2eSYuri Pankov    "write_data/append_data" \
81232f5a2eSYuri Pankov    "read_data/execute" \
82232f5a2eSYuri Pankov    "write_data/append_data/execute" \
83232f5a2eSYuri Pankov    "read_data/write_data/append_data/execute"
84232f5a2eSYuri Pankov
85232f5a2eSYuri Pankov# Define the base directory and file
86d583b39bSJohn Wren Kennedybasedir=$TESTDIR/basedir;  ofile=$basedir/ofile; odir=$basedir/odir
87d583b39bSJohn Wren Kennedynfile=$basedir/nfile; ndir=$basedir/ndir
88d583b39bSJohn Wren Kennedy
89d583b39bSJohn Wren KennedyTARFILE=$TESTDIR/tarfile
90d583b39bSJohn Wren Kennedy
91d583b39bSJohn Wren Kennedy# Verify all the node have expected correct access control
92d583b39bSJohn Wren Kennedyallnodes="$nfile $ndir"
93d583b39bSJohn Wren Kennedy
94d583b39bSJohn Wren Kennedy# According to the original bits, the input ACE access and ACE type, return the
95d583b39bSJohn Wren Kennedy# expect bits after 'chmod A0{+|=}'.
96d583b39bSJohn Wren Kennedy#
97d583b39bSJohn Wren Kennedy# $1 isdir indicate if the target is a directory
98d583b39bSJohn Wren Kennedy# $2 bits which was make up of three bit 'rwx'
99d583b39bSJohn Wren Kennedy# $3 bits_limit which was make up of three bit 'rwx'
100d583b39bSJohn Wren Kennedy# $4 ACE access which is read_data, write_data or execute
101d583b39bSJohn Wren Kennedy# $5 ctrl which is to determine allow or deny according to owner/group bit
102d583b39bSJohn Wren Kennedyfunction cal_bits # isdir bits bits_limit acl_access ctrl
103d583b39bSJohn Wren Kennedy{
104d583b39bSJohn Wren Kennedy	typeset -i isdir=$1
105d583b39bSJohn Wren Kennedy	typeset -i bits=$2
106d583b39bSJohn Wren Kennedy	typeset -i bits_limit=$3
107d583b39bSJohn Wren Kennedy	typeset acl_access=$4
108d583b39bSJohn Wren Kennedy	typeset -i ctrl=${5:-0}
109d583b39bSJohn Wren Kennedy	typeset flagr=0 flagw=0 flagx=0
110d583b39bSJohn Wren Kennedy	typeset tmpstr
111d583b39bSJohn Wren Kennedy
112d583b39bSJohn Wren Kennedy	if (( ctrl == 0 )); then
113d583b39bSJohn Wren Kennedy		if (( (( bits & 4 )) != 0 )); then
114d583b39bSJohn Wren Kennedy			flagr=1
115d583b39bSJohn Wren Kennedy		fi
116d583b39bSJohn Wren Kennedy		if (( (( bits & 2 )) != 0 )); then
117d583b39bSJohn Wren Kennedy			flagw=1
118d583b39bSJohn Wren Kennedy		fi
119d583b39bSJohn Wren Kennedy		if (( (( bits & 1 )) != 0 )); then
120d583b39bSJohn Wren Kennedy			flagx=1
121d583b39bSJohn Wren Kennedy		fi
122d583b39bSJohn Wren Kennedy	else
123232f5a2eSYuri Pankov		# Determine ACE as per owner/group bit
124d583b39bSJohn Wren Kennedy		flagr=1
125d583b39bSJohn Wren Kennedy		flagw=1
126d583b39bSJohn Wren Kennedy		flagx=1
127d583b39bSJohn Wren Kennedy
128d583b39bSJohn Wren Kennedy		if (( ((bits & 4)) != 0 )) && \
129d583b39bSJohn Wren Kennedy			(( ((bits_limit & 4)) != 0 )); then
130d583b39bSJohn Wren Kennedy			flagr=0
131d583b39bSJohn Wren Kennedy		fi
132d583b39bSJohn Wren Kennedy		if (( ((bits & 2)) != 0 )) && \
133d583b39bSJohn Wren Kennedy			(( ((bits_limit & 2)) != 0 )); then
134d583b39bSJohn Wren Kennedy			flagw=0
135d583b39bSJohn Wren Kennedy		fi
136d583b39bSJohn Wren Kennedy		if (( ((bits & 1)) != 0 )) && \
137d583b39bSJohn Wren Kennedy			(( ((bits_limit & 1)) != 0 )); then
138d583b39bSJohn Wren Kennedy			flagx=0
139d583b39bSJohn Wren Kennedy		fi
140d583b39bSJohn Wren Kennedy	fi
141232f5a2eSYuri Pankov
142d583b39bSJohn Wren Kennedy	if ((flagr != 0)); then
143d583b39bSJohn Wren Kennedy		if [[ $acl_access == *"read_data"* ]]; then
144232f5a2eSYuri Pankov			if [[ $acl_access == *"allow"* &&
145232f5a2eSYuri Pankov			    $passthrough == 0 ]]; then
146232f5a2eSYuri Pankov				tmpstr=${tmpstr}
147232f5a2eSYuri Pankov			elif ((isdir == 0)); then
148232f5a2eSYuri Pankov				tmpstr=${tmpstr}/read_data
149d583b39bSJohn Wren Kennedy			else
150232f5a2eSYuri Pankov				tmpstr=${tmpstr}/list_directory/read_data
151d583b39bSJohn Wren Kennedy			fi
152d583b39bSJohn Wren Kennedy		fi
153d583b39bSJohn Wren Kennedy	fi
154d583b39bSJohn Wren Kennedy
155d583b39bSJohn Wren Kennedy	if ((flagw != 0)); then
156d583b39bSJohn Wren Kennedy		if [[ $acl_access == *"allow"* && $passthrough == 0 ]]; then
157d583b39bSJohn Wren Kennedy			tmpstr=${tmpstr}
158d583b39bSJohn Wren Kennedy		else
159d583b39bSJohn Wren Kennedy			if [[ $acl_access == *"write_data"* ]]; then
160d583b39bSJohn Wren Kennedy				if ((isdir == 0)); then
161d583b39bSJohn Wren Kennedy					tmpstr=${tmpstr}/write_data
162d583b39bSJohn Wren Kennedy				else
163d583b39bSJohn Wren Kennedy					tmpstr=${tmpstr}/add_file/write_data
164d583b39bSJohn Wren Kennedy				fi
165d583b39bSJohn Wren Kennedy			fi
166d583b39bSJohn Wren Kennedy			if [[ $acl_access == *"append_data"* ]]; then
167d583b39bSJohn Wren Kennedy				if ((isdir == 0)); then
168d583b39bSJohn Wren Kennedy					tmpstr=${tmpstr}/append_data
169d583b39bSJohn Wren Kennedy				else
170232f5a2eSYuri Pankov					tmpstr=${tmpstr}/add_subdirectory
171232f5a2eSYuri Pankov					tmpstr=${tmpstr}/append_data
172d583b39bSJohn Wren Kennedy				fi
173d583b39bSJohn Wren Kennedy			fi
174d583b39bSJohn Wren Kennedy		fi
175d583b39bSJohn Wren Kennedy	fi
176232f5a2eSYuri Pankov
177d583b39bSJohn Wren Kennedy	if ((flagx != 0)); then
178d583b39bSJohn Wren Kennedy		if [[ $acl_access == *"execute"* ]]; then
179232f5a2eSYuri Pankov			if [[ $acl_access == *"allow"* &&
180232f5a2eSYuri Pankov			    $passthrough == 0 ]]; then
181d583b39bSJohn Wren Kennedy				tmpstr=${tmpstr}
182d583b39bSJohn Wren Kennedy			else
183d583b39bSJohn Wren Kennedy				tmpstr=${tmpstr}/execute
184d583b39bSJohn Wren Kennedy			fi
185d583b39bSJohn Wren Kennedy		fi
186d583b39bSJohn Wren Kennedy	fi
187d583b39bSJohn Wren Kennedy
188d583b39bSJohn Wren Kennedy	tmpstr=${tmpstr#/}
189d583b39bSJohn Wren Kennedy
190*1d32ba66SJohn Wren Kennedy	echo "$tmpstr"
191d583b39bSJohn Wren Kennedy}
192d583b39bSJohn Wren Kennedy
193d583b39bSJohn Wren Kennedy#
194d583b39bSJohn Wren Kennedy# To translate an ace if the node is dir
195d583b39bSJohn Wren Kennedy#
196d583b39bSJohn Wren Kennedy# $1 isdir indicate if the target is a directory
197d583b39bSJohn Wren Kennedy# $2 acl to be translated
198d583b39bSJohn Wren Kennedy#
199d583b39bSJohn Wren Kennedyfunction translate_acl # isdir acl
200d583b39bSJohn Wren Kennedy{
201d583b39bSJohn Wren Kennedy	typeset -i isdir=$1
202d583b39bSJohn Wren Kennedy	typeset acl=$2
203d583b39bSJohn Wren Kennedy	typeset who prefix acltemp action
204d583b39bSJohn Wren Kennedy
205d583b39bSJohn Wren Kennedy	if ((isdir != 0)); then
206d583b39bSJohn Wren Kennedy		who=${acl%%:*}
207d583b39bSJohn Wren Kennedy		prefix=$who
208d583b39bSJohn Wren Kennedy		acltemp=${acl#*:}
209d583b39bSJohn Wren Kennedy		acltemp=${acltemp%%:*}
210d583b39bSJohn Wren Kennedy		prefix=$prefix:$acltemp
211d583b39bSJohn Wren Kennedy		action=${acl##*:}
212d583b39bSJohn Wren Kennedy		acl=$prefix:$(cal_bits $isdir 7 7 $acl 0):$action
213d583b39bSJohn Wren Kennedy	fi
214*1d32ba66SJohn Wren Kennedy	echo "$acl"
215d583b39bSJohn Wren Kennedy}
216d583b39bSJohn Wren Kennedy
217d583b39bSJohn Wren Kennedy#
218d583b39bSJohn Wren Kennedy# To verify if a new ACL is generated as result of
219d583b39bSJohn Wren Kennedy# chmod operation.
220d583b39bSJohn Wren Kennedy#
221d583b39bSJohn Wren Kennedy# $1 bit indicates whether owner/group bit
222d583b39bSJohn Wren Kennedy# $2 newmode indicates the mode changed using chmod
223d583b39bSJohn Wren Kennedy# $3 isdir indicate if the target is a directory
224d583b39bSJohn Wren Kennedy#
225d583b39bSJohn Wren Kennedyfunction check_new_acl # bit newmode isdir
226d583b39bSJohn Wren Kennedy{
227d583b39bSJohn Wren Kennedy	typeset bits=$1
228d583b39bSJohn Wren Kennedy	typeset mode=$2
229d583b39bSJohn Wren Kennedy	typeset -i isdir=$3
230d583b39bSJohn Wren Kennedy	typeset new_acl
231d583b39bSJohn Wren Kennedy	typeset gbit
232d583b39bSJohn Wren Kennedy	typeset ebit
233d583b39bSJohn Wren Kennedy	typeset str=":"
234232f5a2eSYuri Pankov	typeset dc=""
235232f5a2eSYuri Pankov
23601ff4119SYuri Pankov	gbit=${mode:1:1}
23701ff4119SYuri Pankov	ebit=${mode:2:1}
238d583b39bSJohn Wren Kennedy	if (( ((bits & 4)) == 0 )); then
239d583b39bSJohn Wren Kennedy		if (( ((gbit & 4)) != 0 || \
240d583b39bSJohn Wren Kennedy		    ((ebit & 4)) != 0 )); then
241d583b39bSJohn Wren Kennedy			if ((isdir == 0)); then
242d583b39bSJohn Wren Kennedy				new_acl=${new_acl}${str}read_data
243d583b39bSJohn Wren Kennedy			else
244d583b39bSJohn Wren Kennedy				new_acl=${new_acl}${str}list_directory/read_data
245d583b39bSJohn Wren Kennedy			fi
246d583b39bSJohn Wren Kennedy			str="/"
247d583b39bSJohn Wren Kennedy		fi
248d583b39bSJohn Wren Kennedy	fi
249d583b39bSJohn Wren Kennedy	if (( ((bits & 2)) == 0 )); then
250d583b39bSJohn Wren Kennedy		if (( ((gbit & 2)) != 0 || \
251d583b39bSJohn Wren Kennedy		    ((ebit & 2)) != 0 )); then
252d583b39bSJohn Wren Kennedy			if ((isdir == 0)); then
253d583b39bSJohn Wren Kennedy				new_acl=${new_acl}${str}write_data/append_data
254d583b39bSJohn Wren Kennedy			else
255d583b39bSJohn Wren Kennedy				new_acl=${new_acl}${str}add_file/write_data/
256d583b39bSJohn Wren Kennedy				new_acl=${new_acl}add_subdirectory/append_data
257232f5a2eSYuri Pankov				dc="/delete_child"
258d583b39bSJohn Wren Kennedy			fi
259d583b39bSJohn Wren Kennedy			str="/"
260d583b39bSJohn Wren Kennedy		fi
261d583b39bSJohn Wren Kennedy	fi
262d583b39bSJohn Wren Kennedy	if (( ((bits & 1)) == 0 )); then
263d583b39bSJohn Wren Kennedy		if (( ((gbit & 1)) != 0 || \
264d583b39bSJohn Wren Kennedy		    ((ebit & 1)) != 0 )); then
265d583b39bSJohn Wren Kennedy				new_acl=${new_acl}${str}execute
266d583b39bSJohn Wren Kennedy		fi
267d583b39bSJohn Wren Kennedy	fi
268232f5a2eSYuri Pankov	new_acl=${new_acl}${dc}
269*1d32ba66SJohn Wren Kennedy	echo "$new_acl"
270d583b39bSJohn Wren Kennedy}
271d583b39bSJohn Wren Kennedy
272d583b39bSJohn Wren Kennedyfunction build_new_acl # newmode isdir
273d583b39bSJohn Wren Kennedy{
274d583b39bSJohn Wren Kennedy	typeset newmode=$1
275d583b39bSJohn Wren Kennedy	typeset isdir=$2
276d583b39bSJohn Wren Kennedy	typeset expect
277d583b39bSJohn Wren Kennedy	if ((flag == 0)); then
278d583b39bSJohn Wren Kennedy		prefix="owner@"
27901ff4119SYuri Pankov		bit=${newmode:0:1}
280d583b39bSJohn Wren Kennedy		status=$(check_new_acl $bit $newmode $isdir)
281d583b39bSJohn Wren Kennedy
282d583b39bSJohn Wren Kennedy	else
283d583b39bSJohn Wren Kennedy		prefix="group@"
28401ff4119SYuri Pankov		bit=${newmode:1:1}
285d583b39bSJohn Wren Kennedy		status=$(check_new_acl $bit $newmode $isdir)
286d583b39bSJohn Wren Kennedy	fi
287d583b39bSJohn Wren Kennedy	expect=$prefix$status:deny
288*1d32ba66SJohn Wren Kennedy	echo $expect
289d583b39bSJohn Wren Kennedy}
290d583b39bSJohn Wren Kennedy
291d583b39bSJohn Wren Kennedy# According to inherited flag, verify subdirectories and files within it has
292d583b39bSJohn Wren Kennedy# correct inherited access control.
293d583b39bSJohn Wren Kennedyfunction verify_aclmode # <aclmode> <node> <newmode>
294d583b39bSJohn Wren Kennedy{
295d583b39bSJohn Wren Kennedy	# Define the nodes which will be affected by inherit.
296d583b39bSJohn Wren Kennedy	typeset aclmode=$1
297d583b39bSJohn Wren Kennedy	typeset node=$2
298d583b39bSJohn Wren Kennedy	typeset newmode=$3
299d583b39bSJohn Wren Kennedy
300d583b39bSJohn Wren Kennedy	# count: the ACE item to fetch
301d583b39bSJohn Wren Kennedy	# pass: to mark if the current ACE should apply to the target
302d583b39bSJohn Wren Kennedy	# passcnt: counter, if it achieves to maxnumber,
303d583b39bSJohn Wren Kennedy	#	then no additional ACE should apply.
304d583b39bSJohn Wren Kennedy
305d583b39bSJohn Wren Kennedy	typeset -i count=0 pass=0 passcnt=0
306d583b39bSJohn Wren Kennedy	typeset -i bits=0 obits=0 bits_owner=0 isdir=0
307d583b39bSJohn Wren Kennedy	typeset -i total_acl
308d583b39bSJohn Wren Kennedy	typeset -i acl_count=$(count_ACE $node)
309d583b39bSJohn Wren Kennedy
310d583b39bSJohn Wren Kennedy	((total_acl = maxnumber + 3))
311d583b39bSJohn Wren Kennedy
312d583b39bSJohn Wren Kennedy	if [[ -d $node ]]; then
313d583b39bSJohn Wren Kennedy		((isdir = 1))
314d583b39bSJohn Wren Kennedy	fi
315d583b39bSJohn Wren Kennedy
316d583b39bSJohn Wren Kennedy	((i = maxnumber - 1))
317d583b39bSJohn Wren Kennedy	count=0
318d583b39bSJohn Wren Kennedy	passcnt=0
319d583b39bSJohn Wren Kennedy	flag=0
320d583b39bSJohn Wren Kennedy	while ((i >= 0)); do
321d583b39bSJohn Wren Kennedy		pass=0
322d583b39bSJohn Wren Kennedy		expect1=${acls[$i]}
323d583b39bSJohn Wren Kennedy		passthrough=0
324d583b39bSJohn Wren Kennedy		#
325d583b39bSJohn Wren Kennedy		# aclmode=passthrough,
326d583b39bSJohn Wren Kennedy		# no changes will be made to the ACL other than
327d583b39bSJohn Wren Kennedy		# generating the necessary ACL entries to represent
328d583b39bSJohn Wren Kennedy		# the new mode of the file or directory.
329d583b39bSJohn Wren Kennedy		#
330d583b39bSJohn Wren Kennedy		# aclmode=discard,
331d583b39bSJohn Wren Kennedy		# delete all ACL entries that don't represent
332d583b39bSJohn Wren Kennedy		# the mode of the file.
333d583b39bSJohn Wren Kennedy		#
334d583b39bSJohn Wren Kennedy		# aclmode=groupmask,
335d583b39bSJohn Wren Kennedy		# reduce user or group permissions.  The permissions are
336d583b39bSJohn Wren Kennedy		# reduced, such that they are no greater than the group
337d583b39bSJohn Wren Kennedy		# permission bits, unless it is a user entry that has the
338d583b39bSJohn Wren Kennedy		# same UID as the owner of the file or directory.
339d583b39bSJohn Wren Kennedy		# Then, the ACL permissions are reduced so that they are
340d583b39bSJohn Wren Kennedy		# no greater than owner permission bits.
341d583b39bSJohn Wren Kennedy		#
342d583b39bSJohn Wren Kennedy
343d583b39bSJohn Wren Kennedy		case $aclmode in
344232f5a2eSYuri Pankov		passthrough)
345232f5a2eSYuri Pankov			if ((acl_count > total_acl)); then
346232f5a2eSYuri Pankov				expect1=$(build_new_acl $newmode $isdir)
347232f5a2eSYuri Pankov				flag=1
348232f5a2eSYuri Pankov				((total_acl = total_acl + 1))
349232f5a2eSYuri Pankov				((i = i + 1))
350232f5a2eSYuri Pankov			else
351232f5a2eSYuri Pankov				passthrough=1
352232f5a2eSYuri Pankov				expect1=$(translate_acl $isdir $expect1)
353232f5a2eSYuri Pankov			fi
354232f5a2eSYuri Pankov			;;
355232f5a2eSYuri Pankov		groupmask)
356232f5a2eSYuri Pankov			if ((acl_count > total_acl)); then
357232f5a2eSYuri Pankov				expect1=$(build_new_acl $newmode $isdir)
358232f5a2eSYuri Pankov				flag=1
359232f5a2eSYuri Pankov				((total_acl = total_acl + 1))
360232f5a2eSYuri Pankov				((i = i + 1))
361232f5a2eSYuri Pankov			elif [[ $expect1 == *":allow"* ]]; then
362232f5a2eSYuri Pankov				who=${expect1%%:*}
363232f5a2eSYuri Pankov				aclaction=${expect1##*:}
364232f5a2eSYuri Pankov				prefix=$who
365232f5a2eSYuri Pankov				acltemp=""
366232f5a2eSYuri Pankov				reduce=0
367232f5a2eSYuri Pankov				# To determine the mask bits
368232f5a2eSYuri Pankov				# according to the entry type.
369232f5a2eSYuri Pankov				#
370232f5a2eSYuri Pankov				case $who in
371232f5a2eSYuri Pankov				owner@)
372232f5a2eSYuri Pankov					pos=0
373232f5a2eSYuri Pankov					;;
374232f5a2eSYuri Pankov				group@)
375232f5a2eSYuri Pankov					pos=1
376232f5a2eSYuri Pankov					;;
377232f5a2eSYuri Pankov				everyone@)
378232f5a2eSYuri Pankov					pos=2
379232f5a2eSYuri Pankov					;;
380232f5a2eSYuri Pankov				user)
381232f5a2eSYuri Pankov					acltemp=${expect1#*:}
382232f5a2eSYuri Pankov					acltemp=${acltemp%%:*}
383232f5a2eSYuri Pankov					owner=$(get_owner $node)
384232f5a2eSYuri Pankov					group=$(get_group $node)
385232f5a2eSYuri Pankov					if [[ $acltemp == $owner ]]; then
386232f5a2eSYuri Pankov						pos=0
387232f5a2eSYuri Pankov					else
388232f5a2eSYuri Pankov						pos=1
389232f5a2eSYuri Pankov					fi
390232f5a2eSYuri Pankov					prefix=$prefix:$acltemp
391232f5a2eSYuri Pankov					;;
392232f5a2eSYuri Pankov				group)
393232f5a2eSYuri Pankov					acltemp=${expect1#*:}
394232f5a2eSYuri Pankov					acltemp=${acltemp%%:*}
395232f5a2eSYuri Pankov					pos=1
396232f5a2eSYuri Pankov					prefix=$prefix:$acltemp
397232f5a2eSYuri Pankov					reduce=1
398232f5a2eSYuri Pankov					;;
399232f5a2eSYuri Pankov				esac
400232f5a2eSYuri Pankov
401232f5a2eSYuri Pankov				obits=${newmode:$pos:1}
402232f5a2eSYuri Pankov				((bits = $obits))
403232f5a2eSYuri Pankov				# permission should be no greater than the
404232f5a2eSYuri Pankov				# group permission bits
405232f5a2eSYuri Pankov				if ((reduce != 0)); then
406232f5a2eSYuri Pankov					((bits &= ${newmode:1:1}))
407d583b39bSJohn Wren Kennedy					# The ACL permissions are reduced so
408d583b39bSJohn Wren Kennedy					# that they are no greater than owner
409d583b39bSJohn Wren Kennedy					# permission bits.
410232f5a2eSYuri Pankov					((bits_owner = ${newmode:0:1}))
411232f5a2eSYuri Pankov					((bits &= $bits_owner))
412232f5a2eSYuri Pankov				fi
413d583b39bSJohn Wren Kennedy
414232f5a2eSYuri Pankov				if ((bits < obits)) && [[ -n $acltemp ]]; then
415232f5a2eSYuri Pankov					expect2=$prefix:
416232f5a2eSYuri Pankov					new_bit=$(cal_bits $isdir $obits \
417232f5a2eSYuri Pankov					    $bits_owner $expect1 1)
418232f5a2eSYuri Pankov					expect2=${expect2}${new_bit}:allow
419d583b39bSJohn Wren Kennedy				else
420232f5a2eSYuri Pankov					expect2=$prefix:
421232f5a2eSYuri Pankov					new_bit=$(cal_bits $isdir $obits \
422232f5a2eSYuri Pankov					    $obits $expect1 1)
423232f5a2eSYuri Pankov					expect2=${expect2}${new_bit}:allow
424d583b39bSJohn Wren Kennedy				fi
425232f5a2eSYuri Pankov
426232f5a2eSYuri Pankov				priv=$(cal_bits $isdir $obits $bits_owner \
427232f5a2eSYuri Pankov				    $expect2 0)
428232f5a2eSYuri Pankov				expect1=$prefix:$priv:$aclaction
429232f5a2eSYuri Pankov			else
430232f5a2eSYuri Pankov				expect1=$(translate_acl $isdir $expect1)
431232f5a2eSYuri Pankov			fi
432232f5a2eSYuri Pankov			;;
433232f5a2eSYuri Pankov		discard)
434232f5a2eSYuri Pankov			passcnt=maxnumber
435232f5a2eSYuri Pankov			break
436232f5a2eSYuri Pankov			;;
437d583b39bSJohn Wren Kennedy		esac
438d583b39bSJohn Wren Kennedy
439d583b39bSJohn Wren Kennedy		if ((pass == 0)) ; then
440d583b39bSJohn Wren Kennedy			# Get the first ACE to do comparison
441d583b39bSJohn Wren Kennedy			aclcur=$(get_ACE $node $count)
442d583b39bSJohn Wren Kennedy			aclcur=${aclcur#$count:}
443d583b39bSJohn Wren Kennedy			if [[ -n $expect1 && $expect1 != $aclcur ]]; then
444*1d32ba66SJohn Wren Kennedy				ls -vd $node
445d583b39bSJohn Wren Kennedy				log_fail "$aclmode $i #$count " \
446d583b39bSJohn Wren Kennedy					"ACE: $aclcur, expect to be " \
447d583b39bSJohn Wren Kennedy					"$expect1"
448d583b39bSJohn Wren Kennedy			fi
449d583b39bSJohn Wren Kennedy		((count = count + 1))
450d583b39bSJohn Wren Kennedy		fi
451d583b39bSJohn Wren Kennedy		((i = i - 1))
452d583b39bSJohn Wren Kennedy	done
453d583b39bSJohn Wren Kennedy
454d583b39bSJohn Wren Kennedy	#
455d583b39bSJohn Wren Kennedy	# If there's no any ACE be checked, it should be identify as
456d583b39bSJohn Wren Kennedy	# an normal file/dir, verify it.
457d583b39bSJohn Wren Kennedy	#
458d583b39bSJohn Wren Kennedy	if ((passcnt == maxnumber)); then
459d583b39bSJohn Wren Kennedy		if [[ -d $node ]]; then
460d583b39bSJohn Wren Kennedy			compare_acls $node $odir
461d583b39bSJohn Wren Kennedy		elif [[	-f $node ]]; then
462d583b39bSJohn Wren Kennedy			compare_acls $node $ofile
463d583b39bSJohn Wren Kennedy		fi
464d583b39bSJohn Wren Kennedy
465d583b39bSJohn Wren Kennedy		if [[ $? -ne 0 ]]; then
466*1d32ba66SJohn Wren Kennedy			ls -vd $node
467d583b39bSJohn Wren Kennedy			log_fail "Unexpect acl: $node, $aclmode ($newmode)"
468d583b39bSJohn Wren Kennedy		fi
469d583b39bSJohn Wren Kennedy	fi
470d583b39bSJohn Wren Kennedy}
471d583b39bSJohn Wren Kennedy
472d583b39bSJohn Wren Kennedy
473d583b39bSJohn Wren Kennedy
474d583b39bSJohn Wren Kennedytypeset -i maxnumber=0
475d583b39bSJohn Wren Kennedytypeset acl
476d583b39bSJohn Wren Kennedytypeset target
477d583b39bSJohn Wren Kennedytypeset -i passthrough=0
478d583b39bSJohn Wren Kennedytypeset -i flag=0
479d583b39bSJohn Wren Kennedy
480d583b39bSJohn Wren Kennedyfor mode in "${aclmode_flag[@]}"; do
481*1d32ba66SJohn Wren Kennedy	log_must zfs set aclmode=$mode $TESTPOOL/$TESTFS
482d583b39bSJohn Wren Kennedy
483d583b39bSJohn Wren Kennedy	for user in root $ZFS_ACL_STAFF1; do
484d583b39bSJohn Wren Kennedy		log_must set_cur_usr $user
485d583b39bSJohn Wren Kennedy
486*1d32ba66SJohn Wren Kennedy		log_must usr_exec mkdir $basedir
487d583b39bSJohn Wren Kennedy
488*1d32ba66SJohn Wren Kennedy		log_must usr_exec mkdir $odir
489*1d32ba66SJohn Wren Kennedy		log_must usr_exec touch $ofile
490*1d32ba66SJohn Wren Kennedy		log_must usr_exec mkdir $ndir
491*1d32ba66SJohn Wren Kennedy		log_must usr_exec touch $nfile
492d583b39bSJohn Wren Kennedy
493d583b39bSJohn Wren Kennedy		for obj in $allnodes; do
494d583b39bSJohn Wren Kennedy			maxnumber=0
495d583b39bSJohn Wren Kennedy			for preset in "${ace_file_preset[@]}"; do
496d583b39bSJohn Wren Kennedy				for prefix in "${ace_prefix[@]}"; do
497d583b39bSJohn Wren Kennedy					acl=$prefix:$preset
498d583b39bSJohn Wren Kennedy
499d583b39bSJohn Wren Kennedy					case $((maxnumber % 2)) in
500232f5a2eSYuri Pankov					0)
501232f5a2eSYuri Pankov						acl=$acl:deny
502232f5a2eSYuri Pankov						;;
503232f5a2eSYuri Pankov					1)
504232f5a2eSYuri Pankov						acl=$acl:allow
505232f5a2eSYuri Pankov						;;
506d583b39bSJohn Wren Kennedy					esac
507d583b39bSJohn Wren Kennedy
508*1d32ba66SJohn Wren Kennedy					log_must usr_exec chmod A+$acl $obj
509d583b39bSJohn Wren Kennedy					acls[$maxnumber]=$acl
510d583b39bSJohn Wren Kennedy
511d583b39bSJohn Wren Kennedy					((maxnumber = maxnumber + 1))
512d583b39bSJohn Wren Kennedy				done
513d583b39bSJohn Wren Kennedy			done
514d583b39bSJohn Wren Kennedy			# Archive the file and directory
515*1d32ba66SJohn Wren Kennedy			log_must tar cpf@ $TARFILE $basedir
516d583b39bSJohn Wren Kennedy
517d583b39bSJohn Wren Kennedy			if [[ -d $obj ]]; then
518d583b39bSJohn Wren Kennedy				target=$odir
519d583b39bSJohn Wren Kennedy			elif [[ -f $obj ]]; then
520d583b39bSJohn Wren Kennedy				target=$ofile
521d583b39bSJohn Wren Kennedy			fi
522d583b39bSJohn Wren Kennedy			for newmode in "${argv[@]}"; do
523*1d32ba66SJohn Wren Kennedy				log_must usr_exec chmod $newmode $obj
524*1d32ba66SJohn Wren Kennedy				log_must usr_exec chmod $newmode $target
525d583b39bSJohn Wren Kennedy				log_must verify_aclmode $mode $obj $newmode
526