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