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