1#!/bin/ksh -p
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22
23#
24# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
25# Use is subject to license terms.
26#
27
28#
29# Copyright (c) 2012 by Delphix. All rights reserved.
30#
31
32. $STF_SUITE/tests/functional/acl/acl_common.kshlib
33
34#
35# DESCRIPTION:
36#	chmod A{+|-|=} could set compact ACL correctly.
37#
38# STRATEGY:
39#	1. Loop root and non-root user.
40#	2. Get the random compact ACL string.
41#	4. Separately chmod +|-|=
42#	5. Check compact ACL display as expected
43#
44
45verify_runnable "both"
46
47log_assert "chmod A{+|=} should set compact ACL correctly."
48log_onexit cleanup
49
50typeset a_flag=('owner' 'group' 'everyone')
51typeset a_access=('r' 'w' 'x' 'p' 'd' 'D' 'a' 'A' 'R' 'W' 'c' 'C' 'o' 's')
52typeset a_inherit_object=('f' 'd')
53typeset a_inherit_strategy=('i' 'n')
54typeset a_type=('allow' 'deny')
55
56#
57# Get a random item from an array.
58#
59# $1 the base set
60#
61function random_select
62{
63	typeset arr_name=$1
64	typeset -i ind
65
66	eval typeset -i cnt=\${#${arr_name}[@]}
67	((ind = $RANDOM % cnt))
68
69	eval print \${${arr_name}[$ind]}
70}
71
72#
73# Create a random string according to array name, the item number and
74# separated tag.
75#
76# $1 array name where the function get the elements
77# $2 the items number which you want to form the random string
78# $3 the separated tag
79#
80function form_random_str
81{
82	typeset arr_name=$1
83	typeset -i count=${2:-1}
84	typeset sep=${3:-""}
85
86	typeset str=""
87	while ((count > 0)); do
88		str="${str}$(random_select $arr_name)${sep}"
89
90		((count -= 1))
91	done
92
93	print $str
94}
95
96#
97# According to the input ACE access,ACE type, and inherit flags, return the
98# expect compact ACE that could be used by chmod A0{+|=}'.
99#
100# $1 ACE flag which is owner, group, or everyone
101# $2 ACE access generated by the element of a_access
102# $3 ACE inherit_object generated by the element of a_inherit_object
103# $4 ACE inherit_strategy generated by the element of a_inherit_strategy
104# $5 ACE type which is allow or deny
105#
106function cal_ace
107{
108	typeset acl_flag=$1
109	typeset acl_access=$2
110	typeset acl_inherit_object=$3
111	typeset acl_inherit_strategy=$4
112	typeset acl_type=$5
113
114	tmp_ace=${acl_flag}@:
115
116	for element in ${a_access[@]} ; do
117		if [[ $acl_access == *"$element"* ]]; then
118			tmp_ace="${tmp_ace}${element}"
119		else
120			tmp_ace="${tmp_ace}-"
121		fi
122	done
123	tmp_ace=${tmp_ace}:
124
125	for element in ${a_inherit_object[@]} ; do
126		if [[ $acl_inherit_object == *"$element"* ]]; then
127			tmp_ace="${tmp_ace}${element}"
128		else
129			tmp_ace="${tmp_ace}-"
130		fi
131	done
132	for element in ${a_inherit_strategy[@]} ; do
133		if [[ $acl_inherit_strategy == *"$element"* ]]; then
134			tmp_ace="${tmp_ace}${element}"
135		else
136			tmp_ace="${tmp_ace}-"
137		fi
138	done
139
140	tmp_ace=${tmp_ace}---:${acl_type}
141
142	echo "${tmp_ace}"
143}
144
145#
146# Check if chmod set the compact ACE correctly.
147#
148function check_test_result
149{
150	typeset node=$1
151	typeset acl_flag=$2
152	typeset acl_access=$3
153	typeset acl_inherit_object=$4
154	typeset acl_inherit_strategy=$5
155	typeset acl_type=$6
156
157	typeset expect_ace=$(cal_ace "$acl_flag" "$acl_access" \
158	    "$acl_inherit_object" "$acl_inherit_strategy" "$acl_type")
159
160	typeset cur_ace=$(get_ACE $node 0 "compact")
161
162	if [[ $cur_ace != $expect_ace ]]; then
163		log_fail "FAIL: Current map($cur_ace) !=  \
164		    expected ace($expect_ace)"
165	fi
166}
167
168function test_chmod_map
169{
170	typeset node=$1
171	typeset acl_flag acl_access acl_inherit_object acl_inherit_strategy \
172	    acl_type
173	typeset -i cnt
174
175	if ((${#node} == 0)); then
176		log_fail "FAIL: file name or directroy name is not defined."
177	fi
178
179        # Get ACL flag, access & type
180	acl_flag=$(form_random_str a_flag)
181	((cnt = ($RANDOM % ${#a_access[@]}) + 1))
182	acl_access=$(form_random_str a_access $cnt)
183	acl_access=${acl_access%/}
184	acl_type=$(form_random_str a_type 1)
185
186	acl_spec=${acl_flag}@:${acl_access}
187	if [[ -d $node ]]; then
188		# Get ACL inherit_object & inherit_strategy
189		((cnt = ($RANDOM % ${#a_inherit_object[@]}) + 1))
190		acl_inherit_object=$(form_random_str a_inherit_object $cnt)
191		((cnt = ($RANDOM % ${#a_inherit_strategy[@]}) + 1))
192		acl_inherit_strategy=$(form_random_str a_inherit_strategy $cnt)
193		acl_spec=${acl_spec}:${acl_inherit_object}${acl_inherit_strategy}
194	fi
195	acl_spec=${acl_spec}:${acl_type}
196
197	# Set the initial map and back the initial ACEs
198	typeset orig_ace=/tmp/orig_ace.$$
199	typeset cur_ace=/tmp/cur_ace.$$
200
201	for operator in "A0+" "A0="; do
202		log_must usr_exec eval "$LS -Vd $node > $orig_ace"
203
204		# To "A=", firstly add one ACE which can't modify map
205		if [[ $operator == "A0=" ]]; then
206			log_must $CHMOD A0+user:$ZFS_ACL_OTHER1:execute:deny \
207			    $node
208		fi
209		log_must usr_exec $CHMOD ${operator}${acl_spec} $node
210
211		check_test_result "$node" "$acl_flag" "$acl_access" \
212		    "$acl_inherit_object" "$acl_inherit_strategy" "$acl_type"
213
214		# Check "chmod A-"
215		log_must usr_exec $CHMOD A0- $node
216		log_must usr_exec eval "$LS -Vd $node > $cur_ace"
217
218		$DIFF $orig_ace $cur_ace
219		[[ $? -ne 0 ]] && log_fail "FAIL: 'chmod A-' failed."
220	done
221
222	[[ -f $orig_ace ]] && log_must usr_exec $RM -f $orig_ace
223	[[ -f $cur_ace ]] && log_must usr_exec $RM -f $cur_ace
224}
225
226for user in root $ZFS_ACL_STAFF1; do
227	set_cur_usr $user
228
229	typeset -i loop_cnt=2
230	while ((loop_cnt > 0)); do
231		log_must usr_exec $TOUCH $testfile
232		test_chmod_map $testfile
233		log_must $RM -f $testfile
234
235		log_must usr_exec $MKDIR $testdir
236		test_chmod_map $testdir
237		log_must $RM -rf $testdir
238
239		((loop_cnt -= 1))
240	done
241done
242
243log_pass "chmod A{+|=} set compact ACL correctly."
244