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