1 #
   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 # ident "@(#)fs_common.ksh      1.4     09/03/09 SMI"
  28 #
  29 
  30 . ${TET_SUITE_ROOT}/lofi-tests/lib/util_common
  31 
  32 LOFIADM="/usr/sbin/lofiadm"
  33 LS=/usr/bin/ls
  34 MKFILE=/usr/sbin/mkfile
  35 MKISOFS=/usr/bin/mkisofs
  36 RM=/usr/bin/rm
  37 TMPDIR=/tmp
  38 NEWFS=/usr/sbin/newfs
  39 FSTYP=/usr/sbin/fstyp
  40 ZPOOL=/usr/sbin/zpool
  41 
  42 #
  43 # Minimum and maximum sizes of files that will be created to populate
  44 # reference tree.
  45 #
  46 MIN_ADJ_FILE_SIZE=0
  47 MAX_ADJ_FILE_SIZE=65536
  48 
  49 DEFAULT_FILE_SIZE="10M"
  50 LOFI_DEV_NUM_LIMIT=128
  51 
  52 #
  53 # NAME
  54 #       make_and_verify_file
  55 #
  56 # SYNOPSIS
  57 #       make_and_verify_file <file size> <full pathname>
  58 #
  59 # DESCRIPTION
  60 #       Use mkfile(1M) to create a file with the specified size and name.
  61 #       If the mkfile returns good status, use ls to verify the existence
  62 #       of the file.
  63 #
  64 # RETURN VALUES
  65 #       0       File created and verified
  66 #       1       File creation or verification failed
  67 #       
  68 function make_and_verify_file {
  69         typeset size="$1"
  70         typeset filename="$2"
  71         typeset cmd
  72 
  73         # If the specified file already exists, delete it.
  74         if [[ -f "$filename" ]]; then
  75                 $RM -f $filename
  76                 if (( $? != 0 )); then
  77                         cti_unresolved "Error: File '$filename' already" \
  78                             "exists and this process can't delete it."
  79                         return 1
  80                 fi
  81         fi
  82 
  83         # Build the command to create the file.  Any size parameter that
  84         # starts with a zero (excluding leading whitespace) we interpret as
  85         # being zero (this is so that we'll catch 0, 0k, 0m, 0G, etc.).
  86         echo $size | sed 's/^[ \t]*//' | grep "^0" >/dev/null
  87         if (( $? == 0 )); then
  88                 # Use 'touch' to create zero-length file.
  89                 cmd="/usr/bin/touch $filename"
  90         else
  91                 # Use 'mkfile' to create file.
  92                 cmd="$MKFILE $size $filename"
  93         fi
  94 
  95         # Create the file
  96         record_cmd_execution "$cmd"
  97         cti_execute "UNRESOLVED" "$cmd"
  98         if (( $? != 0 )); then
  99                 cti_report "Error: Unable to create file via '$cmd'"
 100                 return 1
 101         fi
 102 
 103         # Verify that the file exists
 104         cmd="ls $filename"
 105         record_cmd_execution "$cmd"
 106         cti_execute "UNRESOLVED" "$cmd"
 107         if (( $? != 0 )); then
 108                 cti_report "Error: '$cmd' returned good status but an 'ls'" \
 109                     "of the file fails"
 110                 return 1
 111         fi
 112 
 113         if [[ -n "$VERBOSE" ]]; then
 114                 cti_report "File $filename of size $size successfully created"
 115         fi
 116 
 117         return 0
 118 }
 119 
 120 
 121 #
 122 # NAME
 123 #       cleanup_lofi_files
 124 #
 125 # SYNOPSIS
 126 #       cleanup_lofi_files
 127 #
 128 # DESCRIPTION
 129 #       Find all lofi files (assuming they were created using the predefined
 130 #       lofi files names) and delete them.
 131 #
 132 # RETURN VALUES
 133 #       0       All lofi files delete or no lofi files found.
 134 #       1       Unable to delete one or more lofi files.
 135 #       
 136 function cleanup_lofi_files {
 137         typeset lofi_file_list=`$LS $SCRATCH_DIR | grep lofi_file_`
 138         typeset retval=0
 139         typeset cmd lofi_file
 140 
 141         if [[ -z "$lofi_file_list" ]]; then
 142                 # No files to delete
 143                 return 0
 144         fi
 145 
 146         for lofi_file in $lofi_file_list
 147         do
 148                 cmd="$RM $SCRATCH_DIR/$lofi_file"
 149                 record_cmd_execution "$cmd"
 150                 cti_execute "UNRESOLVED" "$cmd"
 151                 if (( $? != 0 )); then
 152                         retval=1
 153                 fi
 154         done
 155 
 156         return $retval
 157 }
 158 
 159 
 160 #
 161 # NAME
 162 #       associate_lofidev_and_file
 163 #
 164 # SYNOPSIS
 165 #       associate_lofidev_and_file <type> <name>
 166 #
 167 # DESCRIPTION
 168 #       For a given file name determine the associated lofi device, or
 169 #       vice versa.  The calling function identifies the type of name it's
 170 #       passing in and the name itself.  This function determines the name
 171 #       of the associated item and prints it to standard out so it can be
 172 #       captured by the caller.
 173 #
 174 # RETURN VALUES
 175 #       0       Found a 1-to-1 match between the lofi device and a file
 176 #       1       lofiadm command failed or produced no output
 177 #       2       lofi device listed more than once, associated with multiple
 178 #               files (shouldn't happen)
 179 #       3       lofi device not listed, associated with no files
 180 function associate_lofidev_and_file {
 181         typeset type="$1"
 182         typeset name="$2"
 183         typeset retval=0
 184         typeset cmd match_list line
 185 
 186         # Execute 'lofiadm' command without any arguments, which should
 187         # output the current lofi setup.  Not knowing if we're being called
 188         # for a positive or negative test case, we'll pass a status value
 189         # of "PASS" to cti_execute() to prevent it from setting the tet status
 190         # to something negative on failure.  The calling function will be the
 191         # one to set the tet status.
 192         cmd="$LOFIADM"
 193         record_cmd_execution "$cmd"
 194         cti_execute "PASS" "$cmd"
 195         if (( $? != 0 )); then
 196                 return 1
 197         fi
 198 
 199         # Make sure the output isn't null (shouldn't ever be, as lofiadm
 200         # should still print out column headers even when no lofiadm
 201         # devices are configured).
 202         if [[ ! -s cti_stdout ]]; then
 203                 cti_report "'lofiadm' command returned good status but" \
 204                     "printed nothing to stdout"
 205                 return 1
 206         fi
 207 
 208         # Walk through every line in the file, looking for ones in which
 209         # the lofi block device name (first column) matches the device name
 210         # provided to us by the calling function.  
 211         { while read line; do
 212                 if [[ -n "$line" ]]; then
 213                         set $line
 214                         if [[ "$type" = "lofi_dev" ]]; then
 215                                 # Match on lofi device name (first column)
 216                                 if [[ "$1" = "$name" ]]; then
 217                                         # Capture matching file
 218                                         match_list="$match_list $2"
 219                                 fi
 220                         else
 221                                 # Match on file name (second column)
 222                                 if [[ "$2" = "$name" ]]; then
 223                                         # Capture matching lofi dev
 224                                         match_list="$match_list $1"
 225                                 fi
 226                         fi
 227                 fi
 228         done } < cti_stdout
 229 
 230         # Did we find a match?
 231         if [[ -n "$match_list" ]]; then
 232                 set $match_list
 233                 if (( $# > 1 )); then
 234                         if [[ "$type" = "lofi_dev" ]]; then
 235                                 cti_report "Error: 'lofiadm' command showed" \
 236                                     "more than one file associated with" \
 237                                     "device ${name}: $match_list"
 238                         else
 239                                 cti_report "Error: 'lofiadm' command showed" \
 240                                     "more than one lofi dev associated with" \
 241                                     "file ${name}: $match_list"
 242                         fi
 243                         retval=2
 244                 fi
 245         else
 246                 # Didn't find an entry for the specified lofi device.  Don't
 247                 # print a failure as this might have been expected.
 248                 retval=3
 249         fi
 250 
 251         # Output the list of files we generated so it can be captured by
 252         # the calling function, stripping off any leading whitespace.
 253         echo $match_list | sed 's/^ //'
 254 
 255         return $retval
 256 }
 257 
 258 
 259 #
 260 # NAME
 261 #       add_lofi_device
 262 #
 263 # SYNOPSIS
 264 #       add_lofi_device <file> <optional lofi dev>
 265 #
 266 # DESCRIPTION
 267 #       Execute the 'lofiadm -a' command to create a lofi device based on
 268 #       the specified file (the file must already exist).  In addition to
 269 #       checking the return code from 'lofiadm -a', the function performs
 270 #       additional checks to be sure the command behaved as expected.
 271 #
 272 # RETURN VALUES
 273 #       0       lofi device successfully created and verified.
 274 #       1       creation of lofi device failed.
 275 #       2       creation of lofi device returned good status but additional
 276 #               verification failed.
 277 #       In addition to return codes, if no lofi device name was specified,
 278 #       the name of the lofi device chosen by 'lofiadm -a' will be echoed
 279 #       so that it can be captured by the calling function.
 280 #
 281 function add_lofi_device {
 282         typeset file="$1"
 283         typeset desired_lofi_dev="$2"
 284         typeset desired_lofi_dev lofi_dev cmd_retval line dev_match_count
 285         typeset file_match_count dev_match cmd
 286         typeset retval=0
 287 
 288         # Build the lofiadm command
 289         typeset cmd="$LOFIADM -a $file $desired_lofi_dev"
 290 
 291         # Execute lofiadm command.  Note:  We don't know if the lofiadm -a
 292         # command is expected to pass or fail as we could be called by a
 293         # negative test case.  For that reason, we pass in a "PASS" status to
 294         # cti_execute so that it won't set a failing TET status if the
 295         # command doesn't succeed.
 296         record_cmd_execution "$cmd"
 297         cti_execute "PASS" "$cmd"
 298         cmd_retval=$?
 299 
 300         # 'lofiadm -a' failed.  Nothing else for us to do.
 301         if (( $cmd_retval != 0 )); then
 302                 cti_reportfile cti_stderr
 303                 return 1
 304         fi
 305 
 306         # Retrieve whatever lofiadm printed to stdout
 307         typeset lofi_dev_returned="`cat cti_stdout`"
 308 
 309         if [[ -n "$desired_lofi_dev" ]]; then
 310                 lofi_dev="$desired_lofi_dev"
 311                 # We specified a particular lofi device, in which case
 312                 # lofiadm should not have printed anything to stdout.
 313                 if [[ -n "$lofi_dev_returned" ]]; then
 314                         cti_report "Err: 'lofiadm -a' cmd should not print" \
 315                             "to stdout when the lofi dev is specified"
 316                         cti_report "The following was printed to stdout:" \
 317                             "$lofi_returned_dev"
 318                         retval=2
 319                 fi
 320         else
 321                 lofi_dev="$lofi_dev_returned"
 322                 # We did not specify a particular lofi device, so lofiadm
 323                 # should have printed the name of the lofi device it created
 324                 # to stdout.
 325                 if [[ -n "$lofi_dev_returned" ]]; then
 326                         set $lofi_dev_returned
 327                         if (( $# > 1 )); then
 328                                 retval=2
 329                         fi
 330                 else
 331                         cti_report "Error:  $LOFIADM -a succeeded but did" \
 332                             "not provide a lofi device name"
 333                         retval=2
 334                 fi
 335         fi
 336 
 337         # Verify that 'lofiadm' shows the correct block device and file
 338         # for the just created lofi dev.
 339         lofi_dev_reported_back=`associate_lofidev_and_file file $file`
 340         if (( $? != 0 )); then
 341                 cti_report "'lofiadm -a' command returned good status but" \
 342                     "'lofiadm' output shows irregularities."
 343                 retval=2
 344         else
 345                 if [[ "$lofi_dev_reported_back" = "$lofi_dev" ]]; then
 346                         if [[ -n "$VERBOSE" ]]; then
 347                                 cti_report "'lofiadm' shows file '$file'" \
 348                                     "associated with device $lofi_dev as" \
 349                                     "expected"
 350                         fi
 351                 else
 352                         cti_report "Error: File $file should be associated" \
 353                            "with lofi device $desired_lofi_dev but 'lofiadm'" \
 354                            "shows it associated with $lofi_dev_reported_back"
 355                         retval=2
 356                 fi
 357         fi
 358 
 359         if (( $retval != 0 )); then
 360                 cti_report "Output of 'lofiadm -a' follows:"
 361                 cti_reportfile cti_stdout
 362         fi
 363 
 364         # If a lofi devname was output by the lofiadm command, echo it so
 365         # it can be captured by the function that called us.
 366         if [[ -n "$lofi_dev_returned" ]]; then
 367                 echo $lofi_dev_returned
 368         fi
 369 
 370         return $retval
 371 }
 372 
 373 
 374 #
 375 # NAME
 376 #       del_lofi_device
 377 #
 378 # SYNOPSIS
 379 #       del_lofi_device <lofi dev or filename>
 380 #
 381 # DESCRIPTION
 382 #       Delete a lofiadm device based on the provided lofi device name or
 383 #       file name.
 384 #
 385 # RETURN VALUES
 386 #       0       Delete completed successfully
 387 #       1       Delete or verification of delete was unsuccessful
 388 #
 389 function del_lofi_device {
 390         typeset lofi_dev_or_file="$1"
 391         typeset cmd
 392 
 393         cmd="$LOFIADM -d $lofi_dev_or_file"
 394         record_cmd_execution "$cmd"
 395 
 396         cti_execute "FAIL" "$cmd"
 397         if (( $? != 0 )); then
 398                 return 1
 399         fi
 400 
 401         return 0
 402 }
 403 
 404 
 405 #
 406 # NAME
 407 #       del_lofi_dev_and_file
 408 #
 409 # SYNOPSIS
 410 #       del_lofi_dev_and_file <filename>
 411 #
 412 # DESCRIPTION
 413 #       Since most test cases will have to delete both the lofi device they
 414 #       created and the file associated with that device, this function
 415 #       exists to allow them to do both with a single function call.
 416 #
 417 # RETURN VALUES
 418 #       0       Deletion of both lofi device and file was successful
 419 #       1       Deletion of lofi device and/or file was unsuccessful
 420 #
 421 function del_lofi_dev_and_file {
 422         typeset filename=$1
 423         typeset retval=0
 424         typeset cmd
 425 
 426         # Delete the lofi device
 427         del_lofi_device $filename
 428         if (( $? != 0 )); then
 429                 retval=1
 430         fi
 431 
 432         # Delete the file
 433         cmd="$RM $filename"
 434         record_cmd_execution "$cmd"
 435         cti_execute "FAIL" "$cmd"
 436         if (( $? != 0 )); then
 437                 retval=1
 438         fi
 439 
 440         return $retval
 441 }
 442 
 443 
 444 #
 445 # NAME
 446 #       get_supported_compression_types
 447 #
 448 # SYNOPSIS
 449 #       get_supported_compression_types
 450 #
 451 # DESCRIPTION:
 452 #       Determine which compression types are supported by lofi on the
 453 #       system the test suite is being run on.
 454 #
 455 # RETURN VALUES
 456 #       No value is returned.  The names of the supported compression
 457 #       algorithms (if any) are printed to stdout do they can be captured
 458 #       by the calling function.
 459 #
 460 function get_supported_compression_types {
 461 
 462         #
 463         # Get usage message for lofiadm and extract the line containing
 464         # compression info, if it's there.  If no compression info is found,
 465         # we're running on an OS version that doesn't support lofi compression.
 466         #
 467         typeset compression_info=`$LOFIADM -h 2>&1 | grep "lofiadm -C"`
 468         if [[ -n $compression_info ]]; then
 469                 #
 470                 # Found line containing compression info.  Parse it to extract
 471                 # the supported compression types.
 472                 #
 473                 comp_list=`print $compression_info | \
 474                     sed -e 's/^lofiadm -C *//' | sed -e 's/\] .*//' | \
 475                     sed -e 's/\[//' | sed -e 's/|/ /g'`
 476 
 477                 #
 478                 # Depending on the OS version, the usage message will contain
 479                 # one of the following descriptions of compression algorithms:
 480                 #       -C [algorithm]
 481                 # or
 482                 #       -C [<algorithm1>|<algorithm2>|...|<algorithmN>]
 483                 # The former is the style used by the initial compression
 484                 # support putback into Solaris and you just have to know that
 485                 # the supported types are 'gzip', 'gzip6', and 'gzip9'.  The
 486                 # latter is the style for subsequent additions of compression
 487                 # algorithms and specifically identifies which algorithms are
 488                 # supported.
 489                 #
 490                 if [[ $comp_list == 'algorithm' ]]; then
 491                         print "gzip gzip-6 gzip-9"
 492                 else
 493                         print $comp_list
 494                 fi
 495         fi
 496 }
 497 
 498 
 499 #
 500 # NAME
 501 #       is_compression_type_supported
 502 #
 503 # DESCRIPTION
 504 #       Determine if the desired compression type is supported by lofi on the
 505 #       system the test suite is running on.
 506 #
 507 # SYNOPSIS
 508 #       is_compression_type_supported <desired compression type>
 509 #
 510 # RETURN VALUES
 511 #       0       Desired compression type is supported
 512 #       1       Desired compression type is not supported
 513 #       2       No lofi compression supported on system
 514 #
 515 function is_compression_type_supported {
 516         typeset desired_compression_type="$1"
 517         typeset supported_compression_types=`get_supported_compression_types`
 518 
 519         if [[ ! -n $supported_compression_types ]]; then
 520                 # lofi compression not supported at all on this system
 521                 return 2
 522         fi
 523 
 524         #
 525         # Compression is supported, so check if the desired compression type
 526         # is one of the supported ones.
 527         #
 528         for comp_type in $supported_compression_types
 529         do
 530                 if [[ $desired_compression_type = $comp_type ]]; then
 531                         # Desired compression type is supported
 532                         return 0
 533                 fi
 534         done
 535 
 536         # Desired compression type is not supported
 537         return 1
 538 }
 539 
 540 
 541 #
 542 # NAME
 543 #       create_ufs
 544 #
 545 # SYNOPSIS
 546 #       create_ufs -f <file> -l <lofi device>
 547 #
 548 # DESCRIPTION:
 549 #
 550 #       Create a ufs filesystem. The <file> argument passed in is
 551 #       first lofi mounted and then a ufs is created on the lofi
 552 #       mounted device.  The <lofi_device> specifies a particular
 553 #       lofi device name to use.
 554 #
 555 # RETURN VALUES
 556 #       0       ufs filesystem successfully created
 557 #       1       ufs filesystem not successfully created
 558 #
 559 function create_ufs {
 560 
 561         typeset file_name_arg lofi_dev option
 562 
 563         while getopts f:l:z: option
 564         do
 565                 case $option in
 566                         f)      file_name_arg="$OPTARG";;
 567                         l)      lofi_dev="$OPTARG";;
 568                 esac
 569         done
 570 
 571         # Build 'raw' lofi device name based on block name
 572         raw_lofi_dev=`echo $lofi_dev | sed 's/\/lofi/\/rlofi/'`
 573 
 574         # Create ufs filesystem on the specified device
 575         cmd="$NEWFS $raw_lofi_dev"
 576         record_cmd_execution "$cmd"
 577         cti_execute "UNRESOLVED" "$cmd"
 578         if (( $? != 0 )); then
 579                 cti_report "unable to create ufs on lofi device" \
 580                     "$lofi_device_arg."
 581                 return 1
 582         fi
 583 
 584         if [[ -n "$VERBOSE" ]]; then
 585                 cti_report "Creation of ufs on lofi device $lofi_device_arg" \
 586                    "succeeded."
 587         fi
 588 
 589         # The newfs command returned successfully, so check to make
 590         # sure that a ufs filesystem has been created on the lofi
 591         # device.
 592         cmd="$FSTYP $raw_lofi_dev"
 593         record_cmd_execution "$cmd"
 594         fstype=`$cmd`
 595         if (( $? != 0 )); then
 596                 cti_report "ufs does not appear to be correctly associated" \
 597                     "with lofi device lofi device $lofi_device_arg."
 598                 cti_unresolved
 599                 return 1
 600         fi
 601 
 602         return 0
 603 
 604 }
 605 
 606 
 607 #
 608 # NAME
 609 #       create_zfs <file>
 610 #
 611 # SYNOPSIS
 612 #       create_zfs -f <file> -z <zpool name> -l <lofi device>
 613 #
 614 # DESCRIPTION:
 615 #
 616 #       Create a lofi device using the specified file and then place a
 617 #       zfs filesystem on it.
 618 #
 619 # RETURN VALUES
 620 #       0       zfs filesystem successfully created
 621 #       1       zfs filesystem not successfully created
 622 #
 623 function create_zfs {
 624 
 625         typeset file_name_arg lofi_dev zpool_name option
 626 
 627         while getopts f:l:z: option
 628         do
 629                 case $option in
 630                         f)      file_name_arg="$OPTARG";;
 631                         l)      lofi_dev="$OPTARG";;
 632                         z)      zpool_name="$OPTARG";;
 633                 esac
 634         done
 635 
 636         typeset lofi_device_returned fstype
 637         typeset retval=0
 638         typeset add_status=0
 639 
 640         # Now that a file has been successfully mounted as a lofi device,
 641         # create a zfs filesystem on it.
 642         cmd="$ZPOOL create $zpool_name $lofi_dev"
 643         record_cmd_execution "$cmd"
 644         cti_execute "UNRESOLVED" "$cmd"
 645         if (( $? != 0 )); then
 646                 cti_report "Unable to create a zpool using lofi device" \
 647                     "$lofi_dev."
 648                 return 1
 649         fi
 650 
 651         if [[ -n "$VERBOSE" ]]; then
 652                 cti_report "Creation of zpool using lofi device" \
 653                     "$lofi_device_arg succeeded."
 654         fi
 655 
 656         # The following checks to see if zpool status is returned.
 657         cmd="$ZPOOL status"
 658         record_cmd_execution "$cmd"
 659         cti_execute "UNRESOLVED" "$cmd"
 660         if (( $? != 0 )); then
 661                 cti_report "Check of zpool $zpool_name failed."
 662                 cleanup_lofi_zfs -z $zpool_name -l $file_name_arg
 663                 return 1
 664         fi
 665 
 666 
 667         # The zpool command returned successfully, so check to make
 668         # sure that a zfs filesystem has been created on the lofi
 669         # device.
 670         cmd="$FSTYP $lofi_dev"
 671         record_cmd_execution "$cmd"
 672         fstype=`$cmd`
 673         if (( $? != 0 )) || [[ $fstype != "zfs" ]]; then
 674                 cti_report "zfs does not appear to be correctly associated"\
 675                     "lofi device $lofi_device_arg."
 676                 cti_unresolved
 677                 cleanup_lofi_zfs -z $zpool_name -l $file_name_arg
 678                 return 1 
 679         fi
 680 
 681         return 0
 682 }
 683 
 684 
 685 #
 686 # NAME
 687 #       cleanup_lofi_zfs
 688 #
 689 # SYNOPSIS
 690 #       cleanup_lofi_zfs -z <zpool name> -l <lofi device or file name>
 691 #
 692 # RETURN VALUES
 693 #       0       zfs filesystem and lofi device successfully deleted
 694 #       1       zfs filesystem or lofi device could not be deleted
 695 #
 696 function cleanup_lofi_zfs {
 697 
 698         typeset lofi_dev_or_file zpool_name
 699 
 700         while getopts l:z: option
 701         do
 702                 case $option in
 703                         l)      lofi_dev_or_file="$OPTARG";;
 704                         z)      zpool_name="$OPTARG";;
 705                 esac
 706         done
 707 
 708         cmd="$ZPOOL destroy $zpool_name"
 709         record_cmd_execution "$cmd"
 710         cti_execute "UNRESOLVED" "$cmd"
 711         if (( $? != 0 )); then
 712                 cti_report "Unable to remove zpool '$zpool_arg'"
 713                 return 1
 714         fi
 715 
 716         if [[ -n "$VERBOSE" ]]; then
 717                 cti_report "zpool '$zpool_arg' removed"
 718         fi
 719 
 720         del_lofi_device $lofi_dev_or_file
 721         if (( $? != 0 )); then
 722                 cti_report "Deleting the lofi device associated with" \
 723                     "$lofi_dev_or_file failed."
 724                 return 2
 725         fi
 726 
 727         if [[ -n "$VERBOSE" ]]; then
 728                 cti_report "lofi device associated with '$lofi_dev_or_file'" \
 729                     "deleted"
 730         fi
 731 
 732         return 0
 733 }
 734 
 735 
 736 #
 737 # NAME
 738 #       import_zfs
 739 #
 740 # SYNOPSIS
 741 #       import_zfs <path to device> <zpool name>
 742 #
 743 # DESCRIPTION
 744 #       Import the specified zpool.
 745 #
 746 # RETURN VALUE
 747 #       0       ZFS filesystem successfully imported
 748 #       1       Unable to import ZFS filesystem
 749 #
 750 function import_zfs {
 751         typeset path_to_dev="$1"
 752         typeset zpool_name="$2"
 753 
 754         typeset dir=`dirname $1`
 755         typeset cmd="zpool import -d $dir $zpool_name"
 756         record_cmd_execution "$cmd"
 757 
 758         cti_execute "FAIL" "$cmd"
 759         if (( $? != 0 )); then
 760                 return 1
 761         fi
 762 
 763         if [[ -n "$VERBOSE" ]]; then
 764                 cti_report "zpool '$zpool_name' associated with" \
 765                     "'$path_to_dev' imported"
 766         fi
 767 
 768         return 0
 769 }
 770 
 771 
 772 #
 773 # NAME
 774 #       build_reference_tree
 775 #
 776 # SYNOPSIS
 777 #       build_reference_tree <directory>
 778 #
 779 # DESCRIPTION
 780 #       Build a hierarchy of directories and files, covering a variety of
 781 #       permission values and sizes.  The expectation is that the resulting
 782 #       tree will copied to a filesystem, and that the contents of that
 783 #       filesystem can be compared back against this tree for validation.
 784 #
 785 # RETURN VALUES
 786 #       0 - reference tree built successfully
 787 #       1 - errors encountered, reference tree not created or not complete
 788 function build_reference_tree {
 789         typeset ref_dir="$1"
 790         typeset owner=0;
 791         typeset group=0;
 792         typeset other=0;
 793 
 794         typeset def_other=4
 795         typeset def_group=4
 796         typeset def_owner=4
 797         typeset def_misc=0
 798 
 799         # Delete previous version if one exists
 800         if [[ -d "$ref_dir" ]]; then
 801                 cti_report "$ref_dir exists; deleting to create fresh version"
 802                 $RM -rf $ref_dir
 803                 if (( $? != 0 )); then
 804                         cti_report "Unable to delete existing $ref_dir"
 805                         return 1
 806                 fi
 807         fi
 808 
 809         # Create top-level directory
 810         cti_execute "FAIL" "mkdir -p $ref_dir"
 811         if (( $? != 0 )); then
 812                 cti_report "Unable to make directory $ref_dir"
 813                 return 1
 814         fi
 815 
 816         typeset counter=0
 817         typeset size=$MIN_ADJ_FILE_SIZE
 818         typeset size_inc
 819         let size_inc=$MAX_ADJ_FILE_SIZE/10
 820         typeset perm_type bits cur_dir
 821 
 822         # The 'for' and nested 'while' loop create a subdirectory for each
 823         # type of file permissions ('other', 'group', 'owner', and 'misc'),
 824         # then for each combination of permissions bits for that type (0-7)
 825         # creates a file and sets the permissions.  The sizes of the files
 826         # created is varied.
 827         for perm_type in other group owner misc
 828         do
 829                 # Create subdirectory for the permissions type
 830                 cur_dir=$ref_dir/$perm_type
 831                 cti_execute "FAIL" "mkdir $cur_dir"
 832                 if (( $? != 0 )); then
 833                         cti_report "Error: Unable to make directory $cur_dir"
 834                         return 1
 835                 fi
 836 
 837                 # For each set of permissions bits for this type, create the
 838                 # file and set the permissions.
 839                 bits=0
 840                 while (( $bits <= 7 )); do
 841                         # Build the set of permissions that the file to be
 842                         # created will have.
 843                         if [[ $perm_type = "other" ]]; then
 844                                 perms=$def_misc$def_owner$def_group$bits
 845                         elif [[ $perm_type = "group" ]]; then
 846                                 perms=$def_misc$def_owner$bits$def_other
 847                         elif [[ $perm_type = "owner" ]]; then
 848                                 perms=$def_misc$bits$def_group$def_other
 849                         else
 850                                 perms=$bits$def_owner$def_group$def_other
 851                         fi
 852 
 853                         # 'mkfile' won't create files with a size of zero, so
 854                         # depending on the size of this file we'll use 'touch'
 855                         # (zero length file) or 'mkfile' (non zero length) to
 856                         # perform the file creation.
 857                         if (( $size == 0 )); then
 858                                 cti_execute "FAIL" "touch $cur_dir/f$perms"
 859                         else
 860                                 cti_execute "FAIL" \
 861                                     "mkfile $size $cur_dir/f$perms"
 862                         fi
 863 
 864                         if (( $? != 0 )); then
 865                                 cti_report "Error: Unable to create file" \
 866                                     "$cur_dir/f$perms"
 867                                 return 1
 868                         fi
 869 
 870                         # Set permissions on the file.
 871                         cti_execute "FAIL" "chmod $perms $cur_dir/f$perms"
 872                         if (( $? != 0 )); then
 873                                 cti_report "Error: Unable to set permissions" \
 874                                     "for file $cur_dir/f$perms"
 875                                 return 1
 876                         fi
 877 
 878                         # Increment the 'bits' used to set the permissions
 879                         # so that the next file will have a different value
 880                         # than this one.
 881                         let bits=$bits+1
 882 
 883                         # Increase the size for the next file, wrapping around
 884                         # back to zero if the size exceeds the maximum allowed.
 885                         let size=$size+$size_inc
 886                         if (( $size > $MAX_ADJ_FILE_SIZE )); then
 887                                 size=$MIN_ADJ_FILE_SIZE
 888                         fi
 889                 done
 890         done
 891 
 892         if [[ -n "$VERBOSE" ]]; then
 893                 cti_report "Reference tree created at '$ref_dir'"
 894         fi
 895 
 896         return 0
 897 }
 898 
 899 
 900 #
 901 # NAME
 902 #       create_isofs
 903 #
 904 # SYNOPSIS
 905 #       create_isofs <filename> <source directory>
 906 #
 907 # DESCRIPTION
 908 #       Create file <filename> as an iso image of <directory> using
 909 #       mkisofs(8) and then do some basic santity testing of the
 910 #       command output.
 911 #       
 912 # RETURN VALUE
 913 #       0 - Creation returned good status and output to stderr seems sane
 914 #       1 - Creation returned non-zero status
 915 #       2 - Creation returned good status but output to stderr doesn't seem
 916 #           right
 917 #
 918 function create_isofs {
 919         typeset file="$1"
 920         typeset src_dir="$2"
 921 
 922         # Build and execute mkisofs command
 923         typeset cmd="$MKISOFS -o $file $src_dir"
 924         record_cmd_execution "$cmd"
 925         cti_execute FAIL "$cmd"
 926         if (( $? != 0 )); then
 927                 cti_report "Creation of iso image unsuccessful"
 928 
 929                 # Delete iso image file if it was created.
 930                 if [[ -f "$file" ]]; then
 931                         $RM -rf $file 2>/dev/null
 932                 fi
 933                 return 1
 934         fi
 935 
 936         # mkisofs should print various bits of information to stderr when
 937         # it succeeds.  First make sure output was written to stderr...
 938         if [[ ! -s cti_stderr ]]; then
 939                 cti_report "Cmd '$cmd' returned good status but did not" \
 940                     "print anything to stderr (which it's expected to)"
 941                 return 2
 942         fi
 943 
 944         # ...then make sure the output looks sane by looking for the string
 945         # 'extents written' which should have been printed on the last line.
 946         grep "extents written" cti_stderr >/dev/null
 947         if (( $? != 0 )); then
 948                 cti_report "Cmd 'cmd' returned good status but did not find" \
 949                     "information about extents written in stderr as expected"
 950                 return 2
 951         fi
 952 
 953         if [[ -n "$VERBOSE" ]]; then
 954                 cti_report "Creation of iso fs ($cmd) succeeded"
 955         fi
 956 
 957         return 0
 958 }
 959 
 960 
 961 #
 962 # NAME
 963 #       validate_file
 964 #
 965 # SYNOPSIS
 966 #       validate_file <src_path> <dest_path> <file_basename> <fs_type>
 967 #
 968 # DESCRIPTION
 969 #       Arguments:
 970 #         src_path - Path to the directory in the original set of dirs/files
 971 #               containing the dir/file that was copied to the destination.
 972 #         dest_path - Path to the directory in the destination/copy that
 973 #               contains the dir/file.
 974 #         file_basename - 'basename' of the file/dir being validated.
 975 #         fs_type - The filesystem type of the destination/copy (e.g.
 976 #               ufs, zfs, iso.
 977 #
 978 # RETURN VALUES
 979 #       0 - All validation checks of the dir/file passed
 980 #       1 - One or more validation checks of the dir/file failed
 981 #
 982 function validate_file {
 983         typeset src_path="$1"
 984         typeset dest_path="$2"
 985         typeset file_basename="$3"
 986         typeset fs_type="$4"
 987 
 988         typeset retval=0
 989 
 990         src_listing=`ls -l $src_path | grep "$file_basename\$"`
 991         dest_listing=`ls -l $dest_path | grep "$file_basename\$"`
 992 
 993         if [[ -z "$src_listing" ]]; then
 994                 cti_report "Error: 'ls' doesn't show $file_basename in" \
 995                     "$src_path"
 996                 return 1
 997         fi
 998 
 999         if [[ -n "$dest_listing" ]]; then
1000                 dest_file=$dest_path/$file_basename
1001         else
1002                 # Didn't find a matching file in the destination.  If the
1003                 # destination is an hsfs filesystem, this could be because a
1004                 # '.' was appended to the filename when the iso image was
1005                 # created.
1006                 if [[ $fs_type = "hsfs" ]]; then
1007                         typeset alt_dest_basename="${file_basename}."
1008                         dest_listing=`ls -l $dest_path | grep "$alt_dest_basename\$"`
1009                         if [[ -z "$dest_listing" ]]; then
1010                                 cti_report "Error: 'ls' doesn't show" \
1011                                     "$file_basename $alt_dest_basename in" \
1012                                     "$dest_path"
1013                                 retval=1
1014                         fi
1015                         dest_file=$dest_path/$alt_dest_basename
1016                 else
1017                         cti_report "Error: 'ls' doesn't show $file_basename" \
1018                             "in $dest_path"
1019                         retval=1
1020                 fi
1021         fi
1022 
1023         # Make sure we found a corresponding file in the destination.
1024         if (( $retval != 0 )); then
1025                 cti_report "Error: Unable to find file corresponding to" \
1026                     "$src_path in $dest_path"
1027                 return 1
1028         fi
1029 
1030         # Determine the expected permissions for the file and what the
1031         # actual permissions are.
1032         if [[ $fs_type = "hsfs" ]]; then
1033                 # HSFS filesystems are read only, with permissions set to
1034                 # '-r-xr-xr-x' for all files and 'dr-xr-xr-x' for all
1035                 # directories.
1036                 if [[ -d $dest_file ]]; then
1037                         exp_perms="dr-xr-xr-x"
1038                 else
1039                         exp_perms="-r-xr-xr-x"
1040                 fi
1041         else
1042                 # For other filesystem types, we expect the file permissions
1043                 # to be the same as they were in the source.
1044                 typeset exp_perms=`echo $src_listing | awk ' { print $1 } ' `
1045         fi
1046         typeset dest_perms=`echo $dest_listing | awk ' { print $1 } ' `
1047 
1048         if [[ "$exp_perms" != "$dest_perms" ]]; then
1049                 cti_report "Error: Expected $dest_file to have permissions" \
1050                     "'$exp_perms' but found '$dest_perms' instead"
1051                 retval=1
1052         fi
1053 
1054         # Verify file size is correct (n/a for directories)
1055         if [[ ! -d $dest_file ]]; then
1056                 typeset src_size=`echo $src_listing | awk ' { print $5 } ' `
1057                 typeset dest_size=`echo $dest_listing | awk ' { print $5 } ' `
1058 
1059                 if [[ "$src_size" != "$dest_size" ]]; then
1060                         cti_report "Error:  Sizes of files" \
1061                             "$src_path/$file_basename ($src_size) and" \
1062                             "$dest_file ($dest_size) do not match"
1063                         cti_report "$src_listing"
1064                         cti_report "$dest_listing"
1065                         retval=1
1066                 fi
1067         fi
1068 
1069         return $retval
1070 }
1071 
1072 
1073 #
1074 # NAME
1075 #       validate_test_fs
1076 #
1077 # SYNOPSIS
1078 #       validate_test_fs <mount point> <src dir> <fs type>
1079 #
1080 # DESCRIPTION
1081 #
1082 # RETURN CODES
1083 #       0       Comparison of FS against source dir found no problems
1084 #       1       Contents of FS and source dir don't match or trouble accessing
1085 #               FS.
1086 #
1087 function validate_test_fs {
1088         typeset fs_mnt_point="$1"
1089         typeset src_dir="$2"
1090         typeset fs_type="$3"
1091         typeset start_dir=`pwd`
1092         typeset status=0
1093 
1094         # Make sure the fs is mounted
1095         cti_execute "PASS" "df -k $fs_mnt_point"
1096         if (( $? != 0 )); then
1097                 cti_report "Specified $fs_type fs '$fs_mnt_point' does not" \
1098                     "appear to be mounted"
1099                 return 1
1100         fi
1101 
1102         cd $src_dir
1103         typeset src_file_list=$TMPDIR/src_file_list_$$
1104         find . -print > $src_file_list
1105         cd $start_dir
1106 
1107         typeset mod_src src_path dest_path file_basename
1108         { while read src_filename; do
1109                 # Strip the leading "./" off the filename
1110                 mod_src_filename=`echo $src_filename | sed 's/^\.\///'`
1111                 src_path=`dirname $src_dir/$mod_src_filename`
1112                 dest_path=`dirname $fs_mnt_point/$mod_src_filename`
1113                 file_basename=`basename $src_dir/$mod_src_filename`
1114                 if [[ "$file_basename" = "." ]]; then
1115                         continue
1116                 fi
1117                 validate_file $src_path $dest_path $file_basename $fs_type
1118                 if (( $? != 0 )); then
1119                         status=1
1120                 fi
1121         done } < $src_file_list
1122 
1123         if [[ -n "$VERBOSE" ]] && (( $status == 0 )); then
1124                 cti_report "Comparision of '$fs_mnt_point' against" \
1125                     "'$src_dir' shows no errors (fs type '$fs_type')"
1126         fi
1127 
1128         # Clean up
1129         $RM -f $src_file_list 2>/dev/null
1130 
1131         return 0
1132 }
1133 
1134 
1135 #
1136 # NAME
1137 #       lofi_and_fs_tidy_up
1138 #
1139 # SYNOPSIS
1140 #       lofi_and_fs_tidy_up [ -f lofi file ] \
1141 #           [ -m hsfs or ufs mnt point ] [ -s status ] [ -z zfs pool name ]
1142 #
1143 # DESCRIPTION
1144 #       Tidy up after execution of a typical lofi test purpose, where there
1145 #       is a single filesystem associated with a single lofi device and a
1146 #       single file.  The caller tells this function about the filesystem and
1147 #       lofi device that were configured.  This function tears down that
1148 #       configuration.
1149 #
1150 # RETURN VALUE
1151 #       0       Tidying-up was successful.
1152 #       1       Problems encountered while tidying-up.
1153 #
1154 function lofi_and_fs_tidy_up {
1155         typeset lofi_file hufs_mnt_point zpool_name delete_file
1156 
1157         # Process arguments
1158         typeset option
1159         while getopts df:m:z: option
1160         do
1161                 case $option in
1162                         d)      delete_file="yes";;
1163                         f)      lofi_file="$OPTARG";;
1164                         m)      hufs_mnt_point="$OPTARG";;
1165                         z)      zpool_name="$OPTARG";;
1166                 esac
1167         done
1168 
1169         # Clean up ZFS config
1170         if [[ -n "$zpool_name" ]]; then
1171                 status=1
1172                 errmsg='device is busy'
1173                 until [ $status == 0 ]; do
1174                         cmd="zpool export $zpool_name"
1175                         record_cmd_execution "$cmd"
1176                         $cmd 2>/tmp/err
1177                         if (( $? != 0)); then
1178                                 # if this is busy signal then we want to retry
1179                                 if [ "`grep "$errmsg" /tmp/err`" != "" ]; then
1180                                         cti_report "zpool '$zpool_name' not cleaned up;" \
1181                                             "can't delete lofi device based on file" \
1182                                             "'$lofi_file'"
1183                                 else # return here if error is something else
1184                                         return 1
1185                                 fi      
1186                         else
1187                                 status=0
1188                         fi
1189                 done
1190         fi
1191 
1192         # Clean up UFS config
1193         if [[ -n "$hufs_mnt_point" ]]; then
1194                 cmd="umount $hufs_mnt_point"
1195                 record_cmd_execution "$cmd"
1196                 cti_execute "FAIL" "$cmd"
1197                 if (( $? != 0 )); then
1198                         cti_report "ufs fs mounted at '$ufs_mount_point" \
1199                             "would not unmount; can't delete lofi device" \
1200                             "based on file '$lofi_file'"
1201                         return 1
1202                 fi
1203         fi
1204 
1205         # Clean up lofi device
1206         if [[ -n "$lofi_file" ]]; then
1207                 lofi_dev=`associate_lofidev_and_file file $lofi_file`
1208                 if [[ -n "$lofi_dev" ]]; then
1209                         # There appears to be a lofi device based on the file
1210                         del_lofi_device $lofi_dev
1211                         if (( $? != 0 )); then
1212                                 cti_report "Can't delete lofi device" \
1213                                     "'$lofi_dev' and so can't delete file" \
1214                                     "'$lofi_file'"
1215                                 return 1
1216                         fi
1217                 fi
1218 
1219                 if [[ -n "$delete_file" ]]; then
1220                         cmd="$RM -f $lofi_file"
1221                         record_cmd_execution "$cmd"
1222                         $cmd
1223                         if (( $? != 0 )); then
1224                                 cti_report "Could not remove file '$lofi_file'"
1225                                 return 1
1226                         fi
1227                 fi
1228         fi
1229 
1230         return 0
1231 }
1232 
1233 
1234 #
1235 # NAME
1236 #       create_populated_fs_in_file
1237 #
1238 # SYNOPSIS
1239 #       create_populated_fs_in_file -f <fs type> -l <file> -s <source dir> \
1240 #           -r <file size> [-c compression type] [-d desired lofi device] \
1241 #           [-z zpool_name]
1242 #
1243 # DESCRIPTION:
1244 #       Create and populate a filesystem of the specified type in the
1245 #       specified file.  When this function is complete, the specified
1246 #       file will contain a filesystem image that can be accessed by
1247 #       associating the file with a lofi device.  The filesystem is
1248 #       populated by copying (via cpio) the contents of the source dir
1249 #       specified by the -s flag.
1250 #
1251 # RETURN CODES:
1252 #       0       File system created and populated
1253 #       1       Problem with file system creation or populating
1254 #
1255 function create_populated_fs_in_file {
1256         typeset compression_type desired_lofi_dev file_system_param
1257         typeset lofi_file file_size_param src_dir zpool_name
1258         typeset status=0
1259 
1260         # Process arguments
1261         typeset option
1262         while getopts c:f:l:r:s:z: option
1263         do
1264                 case $option in
1265                         c)      compression_type="$OPTARG";;
1266                         d)      desired_lofi_dev="$OPTARG";;
1267                         f)      file_system_param="$OPTARG";;
1268                         l)      lofi_file="$OPTARG";;
1269                         r)      file_size_param="$OPTARG";;
1270                         s)      src_dir="$OPTARG";;
1271                         z)      zpool_name="$OPTARG";;
1272                 esac
1273         done
1274 
1275         # Verify that the source directory exists
1276         if [[ ! -d $src_dir ]]; then
1277                 cti_uninitiated "Error:  Specified source dir to copy from" \
1278                     "($src_dir) does not exist or is not a directory."
1279                 return 1
1280         fi
1281 
1282         typeset status=0 fs_creation_status=0 fs_population_status=0
1283         typeset lofi_dev_name mount_point
1284         typeset lofi_dev
1285         typeset ufs_finish_arg zfs_finish_arg
1286         typeset cmd
1287 
1288         if [[ $file_system_param == "ufs" || $file_system_param = "hsfs" ]]
1289         then
1290                 mount_point="/mnt"
1291         fi
1292 
1293         # For ufs and zfs filesystems creating the lofi file, creating the
1294         # filesystem, and populating it are all separate steps.
1295         if [[ $file_system_param == "ufs" || $file_system_param = "zfs" ]]
1296         then
1297                 # Create the file
1298                 make_and_verify_file $file_size_param $lofi_file
1299                 if (( $? != 0 )); then
1300                         # File creation failed.
1301                         return 1
1302                 fi
1303 
1304                 # Add lofi device based on just-created file.
1305                 # $desired_lofi_dev may or may not be set, so
1306                 # add_lofi_device() may return a lofi dev name to us.
1307                 lofi_dev=`add_lofi_device $lofi_file $desired_lofi_dev`
1308                 if (( $? != 0 )); then
1309                         # Addition of lofi device failed
1310                         lofi_and_fs_tidy_up -f $lofi_file
1311                         return 1
1312                 fi
1313 
1314                 # If we specified a desired lofi dev name, then
1315                 # add_lofi_device() will not have output a lofi dev name.
1316                 if [[ -n "$desired_lofi_dev" ]]; then
1317                         lofi_dev="$desired_lofi_dev"
1318                 fi
1319 
1320                 # Create filesystem
1321                 if [[ $file_system_param == "ufs" ]]; then
1322                         create_ufs -f $lofi_file -l $lofi_dev
1323                         fs_creation_status=$?
1324                 else
1325                         create_zfs -f $lofi_file -z $zpool_name -l $lofi_dev
1326                         fs_creation_status=$?
1327                 fi
1328 
1329                 if (( $fs_creation_status != 0 )); then
1330                         # Filesystem creation failed
1331                         lofi_and_fs_tidy_up -f $lofi_file
1332                         return 1
1333                 fi
1334 
1335                 # Take care of filesystem mounting
1336                 typeset mount_status=0
1337                 if [[ $file_system_param = "ufs" ]]; then
1338                         # ufs filesystem must be mounted after
1339                         # creation.
1340                         cmd="mount -F $file_system_param $lofi_dev"
1341                         cmd="$cmd $mount_point"
1342                         record_cmd_execution "$cmd"
1343                         cti_execute "FAIL" "$cmd"
1344                         if (( $? != 0 )); then
1345                                 lofi_and_fs_tidy_up \
1346                                     -f $lofi_file -m $mount_point
1347                                 return 1
1348                         fi
1349                         ufs_finish_arg="-m $mount_point"
1350                 else
1351                         # ZFS filesystem should have been mounted at
1352                         # creation time.
1353                         zfs_finish_arg="-z $zpool_name"
1354                         mount_point="/${zpool_name}"
1355                         grep "$mount_point" /etc/mnttab >/dev/null
1356                         if (( $? != 0 )); then
1357                                 cti_fail "ZFS file system $zpool_name not" \
1358                                             "mounted at creation time"
1359                                 lofi_and_fs_tidy_up \
1360                                     -f $lofi_file $zfs_finish_arg
1361                                 return 1
1362                         fi
1363                 fi
1364 
1365                 # 'cd' to the top directory of the reference tree
1366                 typeset mypwd=`pwd`
1367                 cmd="cd $src_dir"
1368                 record_cmd_execution "$cmd"
1369                 $cmd
1370 
1371                 # Use cpio to copy the reference tree to the target
1372                 # filesystem.  We won't use cti_execute to execute this as
1373                 # is will create cti_stdout and cti_stderr files in the
1374                 # reference tree as that is our current working directory.
1375                 # This means we'll have to manage command output ourselves.
1376                 #
1377                 # Command with a pipe ("|") in it won't execute correctly
1378                 # if we try to execute it out of a variable, so have to
1379                 # explicitly write out the command twice (once to log it
1380                 # in the execution record, once to execute it).
1381                 record_cmd_execution "find . -print | cpio -pdm $mount_point"
1382                 find . -print | cpio -pdm $mount_point >/dev/null \
1383                     2>${TMPDIR}/$$_cpio_stderr
1384                 typeset populate_status=$?
1385 
1386                 # 'cd' back to our original location before doing anything
1387                 # else.
1388                 cmd="cd $mypwd"
1389                 record_cmd_execution "$cmd"
1390                 $cmd
1391 
1392                 # Abort if populating the filesystem failed
1393                 if (( $populate_status != 0 )); then
1394                         cti_report "Populating $file_system_param file" \
1395                             "system failed.  stderr for find/cpio:"
1396                         cti_reportfile ${TMPDIR}/$$_cpio_stderr
1397                         $RM -f ${TMPDIR}/$$_cpio_stderr 2>/dev/null
1398                         lofi_and_fs_tidy_up -f $lofi_file \
1399                             $ufs_finish_arg $zfs_finish_arg
1400                         return 1
1401                 fi
1402                 $RM -f ${TMPDIR}/$$_cpio_stderr 2>/dev/null
1403 
1404                 if [[ -n "$VERBOSE" ]]; then
1405                         cti_report "Populating of $file_system_param file" \
1406                             "system completed"
1407                 fi
1408 
1409                 lofi_and_fs_tidy_up -f $lofi_file $ufs_finish_arg \
1410                     $zfs_finish_arg
1411                 if (( $? != 0 )); then
1412                         return 1
1413                 fi
1414 
1415                 if [[ -n "$VERBOSE" ]]; then
1416                         cti_report "Unmounted the $file_system_param" \
1417                             "filesystem and deleted lofi device"
1418                 fi
1419 
1420         elif [[ $file_system_param == "hsfs" ]]; then
1421                 # For an hsfs filesystem, creation of the file and population
1422                 # by the file system all happen at once.
1423                 create_isofs $lofi_file $src_dir
1424                 if (( $? != 0 )); then
1425                         lofi_and_fs_tidy_up -f $lofi_file
1426                         return 1
1427                 fi
1428         fi
1429 
1430         return 0
1431 }
1432 
1433 
1434 #
1435 # NAME:
1436 #       verify_populated_fs_in_file
1437 #
1438 # SYNOPSIS:
1439 #       verify_populated_fs_in_file -f <fs type> -l <lofi file> -s <src dir> \
1440 #           [-c] [-z <zpool name>]
1441 #
1442 # DESCRIPTION:
1443 #       Verify the filesystem contents of the specified lofi file against
1444 #       the original source.  At this time the verification is restricted
1445 #       to file/directory names and permissions, as the files were created
1446 #       via 'mkfile' [by build_reference_tree()] and so don't actually
1447 #       have contents for us to verify.
1448 #
1449 # RETURN CODES:
1450 #       0       Contents of filesystem on lofi device verified
1451 #       1       Filesystem on lofi device inaccessible or doesn't match source
1452 #
1453 function verify_populated_fs_in_file {
1454         typeset lofi_file file_system_param compression zpool_name
1455         typeset status=0
1456 
1457         # Process function arguments
1458         typeset option
1459         while getopts cf:l:s:z: option
1460         do
1461                 case $option in
1462                         c)      compression="yes";;
1463                         f)      file_system_param="$OPTARG";;
1464                         l)      lofi_file="$OPTARG";;
1465                         s)      src_dir="$OPTARG";;
1466                         z)      zpool_name="$OPTARG";;
1467                 esac
1468         done
1469 
1470         # Add lofi device based on the file.
1471         lofi_dev=`add_lofi_device $lofi_file`
1472         if (( $? != 0 )); then
1473                 # Addition of lofi device failed
1474                 lofi_and_fs_tidy_up -f $lofi_file
1475                 return 1
1476         fi
1477 
1478         # Verify that the correct file system type is reported.
1479         cmd="$FSTYP $lofi_dev"
1480         record_cmd_execution "$cmd"
1481         cti_execute "FAIL" "$cmd"
1482         typeset fs_type=`cat cti_stdout`
1483         if [[ "$fs_type" != "$file_system_param" ]]; then
1484                 cti_fail "$FSTYP for $lofi_dev returns type '$fs_type';" \
1485                     "expected '$file_system_param'"
1486                 lofi_and_fs_tidy_up -f $lofi_file
1487                 return 1
1488         fi
1489 
1490         if [[ -n "$compression" && $file_system_param = "zfs" ]]; then
1491                 # With a compressed zfs zpool, the only check we can make is
1492                 # executing fstyp above to verify that the on-the-fly
1493                 # decompression allows the file system type to be determined.
1494                 # We can't import or otherwise use the zpool so we'll return
1495                 # now.
1496                 lofi_and_fs_tidy_up -f $lofi_file
1497                 return 0
1498         fi
1499 
1500         # Need to specify mount point for ufs or hsfs; zfs fs has mount
1501         # point defined in itself.
1502         if [[ $file_system_param == "ufs" || $file_system_param = "hsfs" ]]
1503         then
1504                 mount_point="/mnt"
1505         fi
1506 
1507         # If the file is compressed and contains a UFS filesystem, first try
1508         # mounting it read/write.  This should fail.
1509         if [[ -n "$compression" && "$file_system_param" = "ufs" ]]; then
1510                 cti_report "Attempt mounting compressed UFS filesystem" \
1511                     "read/write.  This is expected to fail."
1512                 cmd="mount -F ufs $lofi_dev $mount_point"
1513                 record_cmd_execution "$cmd"
1514                 cti_execute "PASS" "$cmd"
1515                 if (( $? == 0 )); then
1516                         cti_fail "Mounting of compressed ufs filesystem at" \
1517                             "$lofi/dev/ with read/write permissions" \
1518                             "succeeded when it was expected to fail."
1519                         lofi_and_fs_tidy_up -f $lofi_file \
1520                             -m $mount_point
1521                         cmd="mount -F ufs $lofi_dev $mount_point"
1522                         record_cmd_execution "$cmd"
1523                         cti_execute "PASS" "$cmd"
1524                         if (( $? == 0 )); then
1525                                 return 1
1526                         fi
1527                         status=1
1528                 fi
1529 
1530                 if [[ -n "$VERBOSE" ]]; then
1531                         cti_report "Attempted mounting of compressed ufs" \
1532                             "filesystem with read/write permissions failed" \
1533                             "as expected."
1534                 fi
1535         fi
1536 
1537         typeset hufs_finish_arg zfs_finish_arg
1538         if [[ "$file_system_param" = "ufs" || "$file_system_param" = "hsfs" ]]
1539         then
1540                 # Set mount options to read-only if file is compressed.
1541                 typeset mopts
1542                 if [[ -n "$compression" ]]; then
1543                         mopts="-o ro"
1544                 fi
1545 
1546                 # Mount the FS.
1547                 cmd="mount -F $file_system_param $mopts $lofi_dev $mount_point"
1548                 record_cmd_execution "$cmd"
1549                 cti_execute "PASS" "$cmd"
1550                 if (( $? != 0 )); then
1551                         if [[ -n "$compression" ]]; then
1552                                 cti_fail "Mounting of compressed" \
1553                                     "$file_system_param filesystem at" \
1554                                     "$lofi_dev with read-only option failed" \
1555                                     "when it was expected to pass"
1556                         else
1557                                 cti_fail "Mounting of $file_system_param" \
1558                                     "filesystem with default options failed" \
1559                                     "when it was expected to pass"
1560                         fi
1561                         lofi_and_fs_tidy_up -f $lofi_file \
1562                             -m $mount_point
1563                         return 1
1564                 fi
1565                 hufs_finish_arg="-m $mount_point"
1566         elif [[ "$file_system_param" = "zfs" ]]; then
1567                 mount_point="/${zpool_name}"
1568                 import_zfs $lofi_dev $zpool_name
1569                 if (( $? != 0 )); then
1570                         lofi_and_fs_tidy_up -f $lofi_file
1571                         return
1572                 fi
1573 
1574                 zfs_finish_arg="-z $zpool_name"
1575         fi
1576 
1577         # Validate the contents of the file system on the lofi device
1578         # associated with the decompressed file.
1579         validate_test_fs $mount_point $src_dir $file_system_param
1580         if (( $? == 0 )); then
1581                 if [[ -n "$VERBOSE" ]]; then
1582                         cti_report "Validation of $file_system_param" \
1583                             "filesystem succeeded"
1584                 fi
1585         else
1586                 if [[ -n "$VERBOSE" ]]; then
1587                         cti_report "Validation of $file_system_param" \
1588                             "filesystem failed"
1589                 fi
1590                 status=1
1591         fi
1592 
1593         # Unmount the filesystem and dissasociate the lofi device from it.
1594         lofi_and_fs_tidy_up -f $lofi_file $hufs_finish_arg $zfs_finish_arg
1595         if (( $? != 0 )); then
1596                 return 1
1597         fi
1598 
1599         return $status
1600 }