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 2009 Sun Microsystems, Inc. All rights reserved. 24 # Use is subject to license terms. 25 # 26 27 . $STF_SUITE/tests/functional/acl/acl.cfg 28 . $STF_SUITE/include/libtest.shlib 29 30 # 31 # Get the given file/directory access mode 32 # 33 # $1 object -- file or directroy 34 # 35 function get_mode #<obj> 36 { 37 typeset obj=$1 38 if (( ${#obj} == 0 )); then 39 return 1 40 fi 41 42 $LS -ld $obj | $AWK '{print $1}' 43 } 44 45 # 46 # Get the given file/directory ACL 47 # 48 # $1 object -- file or directroy 49 # 50 function get_acl #<obj> 51 { 52 typeset obj=$1 53 if (( ${#obj} == 0 )); then 54 return 1 55 fi 56 57 $LS -vd $obj | $NAWK '(NR != 1) {print $0}' 58 } 59 60 # 61 # Get the given file/directory ACL 62 # 63 # $1 object -- file or directroy 64 # 65 function get_compact_acl #<obj> 66 { 67 typeset obj=$1 68 if (( ${#obj} == 0 )); then 69 return 1 70 fi 71 72 $LS -Vd $obj | $NAWK '(NR != 1) {print $0}' 73 } 74 75 # 76 # Check the given two files/directories have the same ACLs 77 # 78 # Return 0, if source object acl is equal to target object acl. 79 # 80 # $1 source object 81 # $2 target object 82 # 83 function compare_acls #<src> <tgt> 84 { 85 typeset src=$1 86 typeset tgt=$2 87 88 (( ${#src} == 0 || ${#tgt} == 0 )) && return 1 89 [[ $src == $tgt ]] && return 0 90 91 typeset tmpsrc=/tmp/compare_acls.src.$$ 92 typeset tmptgt=/tmp/compare_acls.tgt.$$ 93 94 get_acl $src > $tmpsrc 95 get_acl $tgt > $tmptgt 96 typeset -i ret=0 97 $DIFF $tmpsrc $tmptgt > /dev/null 2>&1 98 ret=$? 99 $RM -f $tmpsrc $tmptgt 100 101 if (( ret != 0 )); then 102 return $ret 103 fi 104 105 get_compact_acl $src > $tmpsrc 106 get_compact_acl $tgt > $tmptgt 107 $DIFF $tmpsrc $tmptgt > /dev/null 2>&1 108 ret=$? 109 $RM -f $tmpsrc $tmptgt 110 111 return $ret 112 } 113 114 # 115 # Check that the given two objects have the same modes. 116 # Return 0, if their modes are equal with each other. Otherwise, return 1. 117 # 118 # $1 source object 119 # $2 target object 120 # 121 function compare_modes #<src> <tgt> 122 { 123 typeset src=$1 124 typeset tgt=$2 125 typeset -i i=0 126 set -A mode 127 128 (( ${#src} == 0 || ${#tgt} == 0 )) && return 1 129 [[ $src == $tgt ]] && return 0 130 131 typeset obj 132 for obj in $src $tgt 133 do 134 mode[i]=$(get_mode $obj) 135 136 (( i = i + 1 )) 137 done 138 139 [[ ${mode[0]} != ${mode[1]} ]] && return 1 140 141 return 0 142 } 143 144 # 145 # Check that the given two objects have the same xattrs. 146 # Return 0, if their xattrs are equal with each other. Otherwise, return 1. 147 # 148 # $1 source object 149 # $2 target object 150 # 151 function compare_xattrs #<src> <tgt> 152 { 153 typeset src=$1 154 typeset tgt=$2 155 156 (( ${#src} == 0 || ${#tgt} == 0 )) && return 1 157 [[ $src == $tgt ]] && return 0 158 159 typeset tmpsrc=/tmp/compare_xattrs.src.$$ 160 typeset tmptgt=/tmp/compare_xattrs.tgt.$$ 161 162 get_xattr $src > $tmpsrc 163 get_xattr $tgt > $tmptgt 164 typeset -i ret=0 165 $DIFF $tmpsrc $tmptgt > /dev/null 2>&1 166 ret=$? 167 $RM -f $tmpsrc $tmptgt 168 169 return $ret 170 } 171 172 # 173 # Check '+' is set for a given file/directory with 'ls [-l]' command 174 # 175 # $1 object -- file or directory. 176 # 177 function plus_sign_check_l #<obj> 178 { 179 typeset obj=$1 180 if (( ${#obj} == 0 )); then 181 return 1 182 fi 183 184 $LS -ld $obj | $AWK '{print $1}' | $GREP "+\>" > /dev/null 185 186 return $? 187 } 188 189 # 190 # Check '+' is set for a given file/directory with 'ls [-v]' command 191 # 192 # $1 object -- file or directory. 193 # 194 function plus_sign_check_v #<obj> 195 { 196 typeset obj=$1 197 if (( ${#obj} == 0 )); then 198 return 1 199 fi 200 201 $LS -vd $obj | $NAWK '(NR == 1) {print $1}' | $GREP "+\>" > /dev/null 202 203 return $? 204 } 205 206 # 207 # A wrapper function of c program 208 # 209 # $1 legal login name 210 # $2-n commands and options 211 # 212 function chgusr_exec #<login_name> <commands> [...] 213 { 214 $CHG_USR_EXEC $@ 215 return $? 216 } 217 218 # 219 # Export the current user for the following usr_exec operating. 220 # 221 # $1 legal login name 222 # 223 function set_cur_usr #<login_name> 224 { 225 export ZFS_ACL_CUR_USER=$1 226 } 227 228 # 229 # Run commands by $ZFS_ACL_CUR_USER 230 # 231 # $1-n commands and options 232 # 233 function usr_exec #<commands> [...] 234 { 235 $CHG_USR_EXEC "$ZFS_ACL_CUR_USER" $@ 236 return $? 237 } 238 239 # 240 # Count how many ACEs for the speficied file or directory. 241 # 242 # $1 file or directroy name 243 # 244 function count_ACE #<file or dir name> 245 { 246 if [[ ! -e $1 ]]; then 247 log_note "Need input file or directroy name." 248 return 1 249 fi 250 251 $LS -vd $1 | $NAWK 'BEGIN {count=0} 252 (NR != 1)&&(/[0-9]:/) {count++} 253 END {print count}' 254 255 return 0 256 } 257 258 # 259 # Get specified number ACE content of specified file or directory. 260 # 261 # $1 file or directory name 262 # $2 specified number 263 # 264 function get_ACE #<file or dir name> <specified number> <verbose|compact> 265 { 266 if [[ ! -e $1 || $2 -ge $(count_ACE $1) ]]; then 267 return 1 268 fi 269 270 typeset file=$1 271 typeset -i num=$2 272 typeset format=${3:-verbose} 273 typeset -i next_num=-1 274 275 typeset tmpfile=/tmp/tmp_get_ACE.$$ 276 typeset line="" 277 typeset args 278 279 case $format in 280 verbose) args="-vd" 281 ;; 282 compact) args="-Vd" 283 ;; 284 *) log_fail "Invalid parameter as ($format), " \ 285 "only verbose|compact is supported." 286 ;; 287 esac 288 289 $LS $args $file > $tmpfile 290 (( $? != 0 )) && log_fail "FAIL: $LS $args $file > $tmpfile" 291 while read line; do 292 [[ -z $line ]] && continue 293 if [[ $args == -vd ]]; then 294 if [[ $line == "$num":* ]]; then 295 (( next_num = num + 1 )) 296 fi 297 if [[ $line == "$next_num":* ]]; then 298 break 299 fi 300 if (( next_num != -1 )); then 301 print -n $line 302 fi 303 else 304 if (( next_num == num )); then 305 print -n $line 306 fi 307 (( next_num += 1 )) 308 fi 309 done < $tmpfile 310 311 $RM -f $tmpfile 312 (( $? != 0 )) && log_fail "FAIL: $RM -f $tmpfile" 313 } 314 315 # 316 # Cleanup exist user/group. 317 # 318 function cleanup_user_group 319 { 320 del_user $ZFS_ACL_ADMIN 321 322 del_user $ZFS_ACL_STAFF1 323 del_user $ZFS_ACL_STAFF2 324 del_group $ZFS_ACL_STAFF_GROUP 325 326 del_user $ZFS_ACL_OTHER1 327 del_user $ZFS_ACL_OTHER2 328 del_group $ZFS_ACL_OTHER_GROUP 329 330 return 0 331 } 332 333 # 334 # Clean up testfile and test directory 335 # 336 function cleanup 337 { 338 if [[ -d $TESTDIR ]]; then 339 cd $TESTDIR 340 $RM -rf $TESTDIR/* 341 fi 342 } 343 344 # 345 # According to specified access or acl_spec, do relevant operating by using the 346 # specified user. 347 # 348 # $1 specified user 349 # $2 node 350 # $3 acl_spec or access 351 # 352 function rwx_node #user node acl_spec|access 353 { 354 typeset user=$1 355 typeset node=$2 356 typeset acl_spec=$3 357 358 if [[ $user == "" || $node == "" || $acl_spec == "" ]]; then 359 log_note "node or acl_spec are not defined." 360 return 1 361 fi 362 363 if [[ -d $node ]]; then 364 case $acl_spec in 365 *:read_data:*|read_data) 366 chgusr_exec $user $LS -l $node > /dev/null 2>&1 367 return $? ;; 368 *:write_data:*|write_data) 369 if [[ -f ${node}/tmpfile ]]; then 370 log_must $RM -f ${node}/tmpfile 371 fi 372 chgusr_exec $user $TOUCH ${node}/tmpfile > \ 373 /dev/null 2>&1 374 return $? ;; 375 *"execute:"*|execute) 376 chgusr_exec $user $FIND $node > /dev/null 2>&1 377 return $? ;; 378 esac 379 else 380 case $acl_spec in 381 *:read_data:*|read_data) 382 chgusr_exec $user $CAT $node > /dev/null 2>&1 383 return $? ;; 384 *:write_data:*|write_data) 385 chgusr_exec $user $DD if=/usr/bin/ls of=$node > \ 386 /dev/null 2>&1 387 return $? ;; 388 *"execute:"*|execute) 389 ZFS_ACL_ERR_STR=$(chgusr_exec $user $node 2>&1) 390 return $? ;; 391 esac 392 fi 393 } 394 395 # 396 # Get the given file/directory xattr 397 # 398 # $1 object -- file or directroy 399 # 400 function get_xattr #<obj> 401 { 402 typeset obj=$1 403 typeset xattr 404 if (( ${#obj} == 0 )); then 405 return 1 406 fi 407 408 for xattr in `$RUNAT $obj $LS | \ 409 /usr/xpg4/bin/egrep -v -e SUNWattr_ro -e SUNWattr_rw` ; do 410 $RUNAT $obj $SUM $xattr 411 done 412 } 413 414 # 415 # Get the owner of a file/directory 416 # 417 function get_owner #node 418 { 419 typeset node=$1 420 typeset value 421 422 if [[ -z $node ]]; then 423 log_fail "node are not defined." 424 fi 425 426 if [[ -d $node ]]; then 427 value=$($LS -dl $node | $AWK '{print $3}') 428 elif [[ -e $node ]]; then 429 value=$($LS -l $node | $AWK '{print $3}') 430 fi 431 432 $ECHO $value 433 } 434 435 # 436 # Get the group of a file/directory 437 # 438 function get_group #node 439 { 440 typeset node=$1 441 typeset value 442 443 if [[ -z $node ]]; then 444 log_fail "node are not defined." 445 fi 446 447 if [[ -d $node ]]; then 448 value=$($LS -dl $node | $AWK '{print $4}') 449 elif [[ -e $node ]]; then 450 value=$($LS -l $node | $AWK '{print $4}') 451 fi 452 453 $ECHO $value 454 } 455 456 457 # 458 # Get the group name that a UID belongs to 459 # 460 function get_user_group #uid 461 { 462 typeset uid=$1 463 typeset value 464 465 if [[ -z $uid ]]; then 466 log_fail "UID not defined." 467 fi 468 469 value=$(id $uid) 470 471 if [[ $? -eq 0 ]]; then 472 value=${value##*\(} 473 value=${value%%\)*} 474 $ECHO $value 475 else 476 log_fail "Invalid UID (uid)." 477 fi 478 } 479 480 # 481 # Get the specified item of the specified string 482 # 483 # $1: Item number, count from 0. 484 # $2-n: strings 485 # 486 function getitem 487 { 488 typeset -i n=$1 489 shift 490 491 (( n += 1 )) 492 eval echo \${$n} 493 } 494 495 # 496 # This function calculate the specified directory files checksum and write 497 # to the specified array. 498 # 499 # $1 directory in which the files will be cksum. 500 # $2 file array name which was used to store file cksum information. 501 # $3 attribute array name which was used to store attribute information. 502 # 503 function cksum_files #<dir> <file_array_name> <attribute_array_name> 504 { 505 typeset dir=$1 506 typeset farr_name=$2 507 typeset aarr_name=$3 508 509 [[ ! -d $dir ]] && return 510 typeset oldpwd=$PWD 511 cd $dir 512 typeset files=$($LS file*) 513 514 typeset -i i=0 515 typeset -i n=0 516 while (( i < NUM_FILE )); do 517 typeset f=$(getitem $i $files) 518 eval $farr_name[$i]=\$\(\$CKSUM $f\) 519 520 typeset -i j=0 521 while (( j < NUM_ATTR )); do 522 eval $aarr_name[$n]=\$\(\$RUNAT \$f \$CKSUM \ 523 attribute.$j\) 524 525 (( j += 1 )) 526 (( n += 1 )) 527 done 528 529 (( i += 1 )) 530 done 531 532 cd $oldpwd 533 } 534 535 # 536 # This function compare two cksum results array. 537 # 538 # $1 The array name which stored the cksum before operation. 539 # $2 The array name which stored the cksum after operation. 540 # 541 function compare_cksum #<array1> <array2> 542 { 543 typeset before=$1 544 typeset after=$2 545 eval typeset -i count=\${#$before[@]} 546 547 typeset -i i=0 548 while (( i < count )); do 549 eval typeset var1=\${$before[$i]} 550 eval typeset var2=\${$after[$i]} 551 552 if [[ $var1 != $var2 ]]; then 553 return 1 554 fi 555 556 (( i += 1 )) 557 done 558 559 return 0 560 } 561 562 # 563 # This function calculate all the files cksum information in current directory 564 # and output them to the specified file. 565 # 566 # $1 directory from which the files will be cksum. 567 # $2 cksum output file 568 # 569 function record_cksum #<outfile> 570 { 571 typeset dir=$1 572 typeset outfile=$2 573 574 [[ ! -d ${outfile%/*} ]] && usr_exec $MKDIR -p ${outfile%/*} 575 576 usr_exec cd $dir ; $FIND . -depth -type f -exec cksum {} \\\; | \ 577 $SORT > $outfile 578 usr_exec cd $dir ; $FIND . -depth -type f -xattr -exec runat {} \ 579 cksum attribute* \\\; | $SORT >> $outfile 580 } 581 582 # 583 # The function create_files creates the directories and files that the script 584 # will operate on to test extended attribute functionality. 585 # 586 # $1 The base directory in which to create directories and files. 587 # 588 function create_files #<directory> 589 { 590 typeset basedir=$1 591 592 [[ ! -d $basedir ]] && usr_exec $MKDIR -m 777 $basedir 593 [[ ! -d $RES_DIR ]] && usr_exec $MKDIR -m 777 $RES_DIR 594 [[ ! -d $INI_DIR ]] && usr_exec $MKDIR -m 777 $INI_DIR 595 [[ ! -d $TST_DIR ]] && usr_exec $MKDIR -m 777 $TST_DIR 596 [[ ! -d $TMP_DIR ]] && usr_exec $MKDIR -m 777 $TMP_DIR 597 598 # 599 # Create the original file and its attribute files. 600 # 601 [[ ! -a $RES_DIR/file ]] && \ 602 usr_exec $FILE_WRITE -o create -f $RES_DIR/file \ 603 -b 1024 -d 0 -c 1 604 [[ ! -a $RES_DIR/attribute ]] && \ 605 usr_exec $CP $RES_DIR/file $RES_DIR/attribute 606 607 typeset oldpwd=$PWD 608 cd $INI_DIR 609 610 typeset -i i=0 611 while (( i < NUM_FILE )); do 612 typeset dstfile=$INI_DIR/file.$$.$i 613 usr_exec $CP $RES_DIR/file $dstfile 614 615 typeset -i j=0 616 while (( j < NUM_ATTR )); do 617 usr_exec $RUNAT $dstfile \ 618 $CP $RES_DIR/attribute ./attribute.$j 619 (( j += 1 )) 620 done 621 622 (( i += 1 )) 623 done 624 625 cd $oldpwd 626 }