config: allow chacl to be in any directory in $PATH
[xfstests-dev.git] / common / attr
1 ##/bin/bash
2 #-----------------------------------------------------------------------
3 #  Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
4 #  This program is free software; you can redistribute it and/or modify
5 #  it under the terms of the GNU General Public License as published by
6 #  the Free Software Foundation; either version 2 of the License, or
7 #  (at your option) any later version.
8 #
9 #  This program is distributed in the hope that it will be useful,
10 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 #  GNU General Public License for more details.
13 #
14 #  You should have received a copy of the GNU General Public License
15 #  along with this program; if not, write to the Free Software
16 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
17 #  USA
18 #
19 #  Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
20 #  Mountain View, CA 94043, USA, or: http://www.sgi.com
21 #-----------------------------------------------------------------------
22 # common extended attribute and ACL support
23
24 # filesystems that want to test maximum supported acl counts need to
25 # add support in here
26 _acl_get_max()
27 {
28         case $FSTYP in
29         xfs)
30                 # CRC format filesystems have much larger ACL counts. The actual
31                 # number is into the thousands, but testing that meany takes too
32                 # long, so just test well past the old limit of 25.
33                 xfs_info $TEST_DIR | _filter_mkfs > /dev/null 2> $tmp.info
34                 . $tmp.info
35                 rm $tmp.info
36                 if [ $_fs_has_crcs -eq 0 ]; then
37                         echo 25
38                 else
39                         echo 5461
40                 fi
41                 ;;
42         jfs)
43                 echo 8191
44                 ;;
45         *)
46                 echo 0
47                 ;;
48         esac
49 }
50
51 _require_acl_get_max()
52 {
53         if [ $(_acl_get_max) -eq 0 ]; then
54                 _notrun "$FSTYP does not define maximum ACL count"
55         fi
56 }
57
58 # pick three unused user/group ids, store them as $acl[1-3]
59 #
60 _acl_setup_ids()
61 {
62     eval `(_cat_passwd; _cat_group) | awk -F: '
63       { ids[$3]=1 }
64       END {
65         j=1
66         for(i=1; i<1000000 && j<=3;i++){
67           if (! (i in ids)) {
68              printf "acl%d=%d;", j, i;           
69              j++
70           }
71         }       
72       }'`
73 }
74
75 # filter for the acl ids selected above
76 #
77 _acl_filter_id()
78 {
79     sed \
80        -e "s/u:$acl1/u:id1/" \
81        -e "s/u:$acl2/u:id2/" \
82        -e "s/u:$acl3/u:id3/" \
83        -e "s/g:$acl1/g:id1/" \
84        -e "s/g:$acl2/g:id2/" \
85        -e "s/g:$acl3/g:id3/" \
86        -e "s/ $acl1 / id1 /" \
87        -e "s/ $acl2 / id2 /" \
88        -e "s/ $acl3 / id3 /"
89 }
90
91 _getfacl_filter_id()
92 {
93     sed \
94        -e "s/user:$acl1/user:id1/" \
95        -e "s/user:$acl2/user:id2/" \
96        -e "s/user:$acl3/user:id3/" \
97        -e "s/group:$acl1/group:id1/" \
98        -e "s/group:$acl2/group:id2/" \
99        -e "s/group:$acl3/group:id3/" \
100        -e "s/: $acl1/: id1/" \
101        -e "s/: $acl2/: id2/" \
102        -e "s/: $acl3/: id3/"
103 }
104
105 # filtered ls
106 #
107 _acl_ls()
108 {
109     _ls_l -n $* | awk '{ print $1, $3, $4, $NF }' | _acl_filter_id
110
111
112 #
113 _acl_list()
114 {
115     _file1=$1
116
117     if [ $HOSTOS = "IRIX" ]; then
118         ls -dD $_file1 | _acl_filter_id
119     else 
120         chacl -l $_file1 | _acl_filter_id
121     fi
122 }
123
124 # create an ACL with n ACEs in it
125 #
126 _create_n_aces()
127 {
128     let n=$1-4
129     acl='u::rwx,g::rwx,o::rwx,m::rwx' # 4 ace acl start
130     while [ $n -ne 0 ]; do
131         acl="$acl,u:$n:rwx"
132         let n=$n-1
133     done
134     echo $acl
135 }
136
137 # filter user ace names to user ids
138 #
139 _filter_aces()
140 {
141     tmp_file=`mktemp /tmp/ace.XXXXXX`
142
143     (_cat_passwd; _cat_group) > $tmp_file
144
145     $AWK_PROG -v tmpfile=$tmp_file '
146         BEGIN {
147             FS=":"
148             while ( getline <tmpfile > 0 ) {
149                 idlist[$1] = $3 
150             }
151         }
152         /^user/ { if ($2 in idlist) sub($2, idlist[$2]); print; next}
153         /^u/ { if ($2 in idlist) sub($2, idlist[$2]); print; next}
154         /^default:user/ { if ($3 in idlist) sub($3, idlist[$3]); print; next}
155         {print}
156     '
157     rm -f $tmp_file
158 }
159
160 _filter_aces_notypes()
161 {
162     tr '\[' '\012' | tr ']' '\012' | tr ',' '\012' | _filter_aces|\
163     sed -e 's/u:/user:/' -e 's/g:/group:/' -e 's/o:/other:/' -e 's/m:/mask:/'
164 }
165
166 _require_acls()
167 {
168     [ -n $CHACL_PROG ] || _notrun "chacl command not found"
169
170     #
171     # Test if chacl is able to list ACLs on the target filesystems.  On really
172     # old kernels the system calls might not be implemented at all, but the
173     # more common case is that the tested filesystem simply doesn't support
174     # ACLs.
175     #
176     touch $TEST_DIR/syscalltest
177     chacl -l $TEST_DIR/syscalltest > $TEST_DIR/syscalltest.out 2>&1
178     cat $TEST_DIR/syscalltest.out >> $seqres.full
179
180     if grep -q 'Function not implemented' $TEST_DIR/syscalltest.out; then
181       _notrun "kernel does not support ACLs"
182     fi
183     if grep -q 'Operation not supported' $TEST_DIR/syscalltest.out; then
184       _notrun "ACLs not supported by this filesystem type: $FSTYP"
185     fi
186
187     rm -f $TEST_DIR/syscalltest.out
188 }
189
190 _list_acl()
191 {
192     file=$1
193
194     ls -dD $file | _acl_filter_id
195 }
196
197 _require_attrs()
198 {
199     [ -n $ATTR_PROG ] || _notrun "attr command not found"
200     [ -n $GETFATTR_PROG ] || _notrun "getfattr command not found"
201     [ -n $SETFATTR_PROG ] || _notrun "setfattr command not found"
202
203     #
204     # Test if chacl is able to write an attribute on the target filesystems.
205     # On really old kernels the system calls might not be implemented at all,
206     # but the more common case is that the tested filesystem simply doesn't
207     # support attributes.  Note that we can't simply list attributes as
208     # various security modules generate synthetic attributes not actually
209     # stored on disk.
210     #
211     touch $TEST_DIR/syscalltest
212     attr -s "user.xfstests" -V "attr" $TEST_DIR > $TEST_DIR/syscalltest.out 2>&1
213     cat $TEST_DIR/syscalltest.out >> $seqres.full
214
215     if grep -q 'Function not implemented' $TEST_DIR/syscalltest.out; then
216       _notrun "kernel does not support attrs"
217     fi
218     if grep -q 'Operation not supported' $TEST_DIR/syscalltest.out; then
219       _notrun "attrs not supported by this filesystem type: $FSTYP"
220     fi
221
222     rm -f $TEST_DIR/syscalltest.out
223 }
224
225 _require_attr_v1()
226 {
227         _scratch_mkfs_xfs_supported -i attr=1 >/dev/null 2>&1 \
228                 || _notrun "attr v1 not supported on $SCRATCH_DEV"
229 }
230
231 # check if we support the noattr2 mount option
232 _require_noattr2()
233 {
234         _scratch_mkfs_xfs > /dev/null 2>&1 \
235                 || _fail "_scratch_mkfs_xfs failed on $SCRATCH_DEV"
236         _mount -o noattr2 $SCRATCH_DEV > /dev/null 2>&1 \
237                 || _notrun "noattr2 mount option not supported on $SCRATCH_DEV"
238         _scratch_unmount
239 }
240
241 # getfattr -R returns info in readdir order which varies from fs to fs.
242 # This sorts the output by filename
243 _sort_getfattr_output()
244 {
245     awk '{a[FNR]=$0}END{n = asort(a); for(i=1; i <= n; i++) print a[i]"\n"}' RS=''
246 }
247
248 # set maximum total attr space based on fs type
249 if [ "$FSTYP" == "xfs" -o "$FSTYP" == "udf" ]; then
250         MAX_ATTRS=1000
251 else # Assume max ~1 block of attrs
252         BLOCK_SIZE=`stat -f $TEST_DIR | grep "Block size" | cut -d " " -f3`
253         # user.attribute_XXX="value.XXX" is about 32 bytes; leave some overhead
254         let MAX_ATTRS=$BLOCK_SIZE/40
255 fi
256
257 export MAX_ATTRS
258
259 # Set max attr value size based on fs type
260 if [ "$FSTYP" == "xfs" -o "$FSTYP" == "udf" -o "$FSTYP" == "btrfs" ]; then
261         MAX_ATTRVAL_SIZE=64
262 else # Assume max ~1 block of attrs
263         BLOCK_SIZE=`stat -f $TEST_DIR | grep "Block size" | cut -d " " -f3`
264         # leave a little overhead
265         let MAX_ATTRVAL_SIZE=$BLOCK_SIZE-256
266 fi
267
268 export MAX_ATTRVAL_SIZE
269 # make sure this script returns success
270 /bin/true