1edfa49ffS# 2edfa49ffS# CDDL HEADER START 3edfa49ffS# 4edfa49ffS# The contents of this file are subject to the terms of the 5edfa49ffS# Common Development and Distribution License (the "License"). 6edfa49ffS# You may not use this file except in compliance with the License. 7edfa49ffS# 8edfa49ffS# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9edfa49ffS# or http://www.opensolaris.org/os/licensing. 10edfa49ffS# See the License for the specific language governing permissions 11edfa49ffS# and limitations under the License. 12edfa49ffS# 13edfa49ffS# When distributing Covered Code, include this CDDL HEADER in each 14edfa49ffS# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15edfa49ffS# If applicable, add the following below this CDDL HEADER, with the 16edfa49ffS# fields enclosed by brackets "[]" replaced with your own identifying 17edfa49ffS# information: Portions Copyright [yyyy] [name of copyright owner] 18edfa49ffS# 19edfa49ffS# CDDL HEADER END 20edfa49ffS# 21*6e1ae2a3SGary Pennington# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 22edfa49ffS# 23edfa49ffS 24edfa49ffS# 25edfa49ffS# Send the error message to the screen and to the logfile. 26edfa49ffS# 27edfa49ffSerror() 28edfa49ffS{ 29edfa49ffS typeset fmt="$1" 30edfa49ffS shift 31edfa49ffS 32edfa49ffS printf "${MSG_PREFIX}ERROR: ${fmt}\n" "$@" 33edfa49ffS [[ -n $LOGFILE ]] && printf "[$(date)] ERROR: ${fmt}\n" "$@" >&2 34edfa49ffS} 35edfa49ffS 36edfa49ffSfatal() 37edfa49ffS{ 38edfa49ffS typeset fmt="$1" 39edfa49ffS shift 40edfa49ffS 41edfa49ffS error "$fmt" "$@" 42edfa49ffS exit $EXIT_CODE 43edfa49ffS} 44edfa49ffS 45e71ca95cSGerald Jelinekfail_fatal() { 46e71ca95cSGerald Jelinek printf "ERROR: " 47e71ca95cSGerald Jelinek printf "$@" 48e71ca95cSGerald Jelinek printf "\n" 49e71ca95cSGerald Jelinek exit $ZONE_SUBPROC_FATAL 50e71ca95cSGerald Jelinek} 51e71ca95cSGerald Jelinek 52edfa49ffS# 53edfa49ffS# Send the provided printf()-style arguments to the screen and to the logfile. 54edfa49ffS# 55edfa49ffSlog() 56edfa49ffS{ 57edfa49ffS typeset fmt="$1" 58edfa49ffS shift 59edfa49ffS 60edfa49ffS printf "${MSG_PREFIX}${fmt}\n" "$@" 61edfa49ffS [[ -n $LOGFILE ]] && printf "[$(date)] ${MSG_PREFIX}${fmt}\n" "$@" >&2 62edfa49ffS} 63edfa49ffS 64edfa49ffS# 65edfa49ffS# Print provided text to the screen if the shell variable "OPT_V" is set. 66edfa49ffS# The text is always sent to the logfile. 67edfa49ffS# 68edfa49ffSvlog() 69edfa49ffS{ 70edfa49ffS typeset fmt="$1" 71edfa49ffS shift 72edfa49ffS 73edfa49ffS [[ -n $OPT_V ]] && printf "${MSG_PREFIX}${fmt}\n" "$@" 74edfa49ffS [[ -n $LOGFILE ]] && printf "[$(date)] ${MSG_PREFIX}${fmt}\n" "$@" >&2 75edfa49ffS} 76edfa49ffS 77e71ca95cSGerald Jelinek# 78edfa49ffS# Validate that the directory is safe. 79e71ca95cSGerald Jelinek# 80e71ca95cSGerald Jelinek# It is possible for a malicious zone root user to modify a zone's filesystem 81e71ca95cSGerald Jelinek# so that modifications made to the zone's filesystem by administrators in the 82e71ca95cSGerald Jelinek# global zone modify the global zone's filesystem. We can prevent this by 83e71ca95cSGerald Jelinek# ensuring that all components of paths accessed by scripts are real (i.e., 84e71ca95cSGerald Jelinek# non-symlink) directories. 85e71ca95cSGerald Jelinek# 86e71ca95cSGerald Jelinek# NOTE: The specified path should be an absolute path as would be seen from 87e71ca95cSGerald Jelinek# within the zone. Also, this function does not check parent directories. 88e71ca95cSGerald Jelinek# If, for example, you need to ensure that every component of the path 89e71ca95cSGerald Jelinek# '/foo/bar/baz' is a directory and not a symlink, then do the following: 90e71ca95cSGerald Jelinek# 91e71ca95cSGerald Jelinek# safe_dir /foo 92e71ca95cSGerald Jelinek# safe_dir /foo/bar 93e71ca95cSGerald Jelinek# safe_dir /foo/bar/baz 94e71ca95cSGerald Jelinek# 95edfa49ffSsafe_dir() 96edfa49ffS{ 97edfa49ffS typeset dir="$1" 98edfa49ffS 99edfa49ffS if [[ -h $ZONEROOT/$dir || ! -d $ZONEROOT/$dir ]]; then 100edfa49ffS fatal "$e_baddir" "$dir" 101edfa49ffS fi 102edfa49ffS} 103edfa49ffS 104e71ca95cSGerald Jelinek# Like safe_dir except the dir doesn't have to exist. 105e71ca95cSGerald Jelineksafe_opt_dir() 106e71ca95cSGerald Jelinek{ 107e71ca95cSGerald Jelinek typeset dir="$1" 108e71ca95cSGerald Jelinek 109e71ca95cSGerald Jelinek [[ ! -e $ZONEROOT/$dir ]] && return 110e71ca95cSGerald Jelinek 111e71ca95cSGerald Jelinek if [[ -h $ZONEROOT/$dir || ! -d $ZONEROOT/$dir ]]; then 112e71ca95cSGerald Jelinek fatal "$e_baddir" "$dir" 113e71ca95cSGerald Jelinek fi 114e71ca95cSGerald Jelinek} 115e71ca95cSGerald Jelinek 116edfa49ffS# Only make a copy if we haven't already done so. 117edfa49ffSsafe_backup() 118edfa49ffS{ 119edfa49ffS typeset src="$1" 120edfa49ffS typeset dst="$2" 121edfa49ffS 122edfa49ffS if [[ ! -h $src && ! -h $dst && ! -d $dst && ! -f $dst ]]; then 123edfa49ffS /usr/bin/cp -p $src $dst || fatal "$e_badfile" "$src" 124edfa49ffS fi 125edfa49ffS} 126edfa49ffS 127edfa49ffS# Make a copy even if the destination already exists. 128edfa49ffSsafe_copy() 129edfa49ffS{ 130edfa49ffS typeset src="$1" 131edfa49ffS typeset dst="$2" 132edfa49ffS 133edfa49ffS if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then 134edfa49ffS /usr/bin/cp -p $src $dst || fatal "$e_badfile" "$src" 135edfa49ffS fi 136edfa49ffS} 137edfa49ffS 138edfa49ffS# Move a file 139edfa49ffSsafe_move() 140edfa49ffS{ 141edfa49ffS typeset src="$1" 142edfa49ffS typeset dst="$2" 143edfa49ffS 144edfa49ffS if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then 145edfa49ffS /usr/bin/mv $src $dst || fatal "$e_badfile" "$src" 146edfa49ffS fi 147edfa49ffS} 148edfa49ffS 149e71ca95cSGerald Jelineksafe_rm() 150e71ca95cSGerald Jelinek{ 151e71ca95cSGerald Jelinek if [[ ! -h $ZONEROOT/$1 && -f $ZONEROOT/$1 ]]; then 152e71ca95cSGerald Jelinek rm -f "$ZONEROOT/$1" 153e71ca95cSGerald Jelinek fi 154e71ca95cSGerald Jelinek} 155e71ca95cSGerald Jelinek 156e71ca95cSGerald Jelinek# 157e71ca95cSGerald Jelinek# Replace the file with a wrapper pointing to the native brand code. 158e71ca95cSGerald Jelinek# However, we only do the replacement if the file hasn't already been 159e71ca95cSGerald Jelinek# replaced with our wrapper. This function expects the cwd to be the 160e71ca95cSGerald Jelinek# location of the file we're replacing. 161e71ca95cSGerald Jelinek# 162e71ca95cSGerald Jelinek# Some of the files we're replacing are hardlinks to isaexec so we need to 'rm' 163e71ca95cSGerald Jelinek# the file before we setup the wrapper while others are hardlinks to rc scripts 164e71ca95cSGerald Jelinek# that we need to maintain. 165e71ca95cSGerald Jelinek# 166e71ca95cSGerald Jelineksafe_replace() 167e71ca95cSGerald Jelinek{ 168e71ca95cSGerald Jelinek typeset filename="$1" 169e71ca95cSGerald Jelinek typeset runname="$2" 170e71ca95cSGerald Jelinek typeset mode="$3" 171e71ca95cSGerald Jelinek typeset own="$4" 172e71ca95cSGerald Jelinek typeset rem="$5" 173e71ca95cSGerald Jelinek 174e71ca95cSGerald Jelinek if [ -h $filename -o ! -f $filename ]; then 175e71ca95cSGerald Jelinek return 176e71ca95cSGerald Jelinek fi 177e71ca95cSGerald Jelinek 178e71ca95cSGerald Jelinek egrep -s "Solaris Brand Replacement" $filename 179e71ca95cSGerald Jelinek if [ $? -eq 0 ]; then 180e71ca95cSGerald Jelinek return 181e71ca95cSGerald Jelinek fi 182e71ca95cSGerald Jelinek 183e71ca95cSGerald Jelinek safe_backup $filename $filename.pre_p2v 184e71ca95cSGerald Jelinek if [ $rem = "remove" ]; then 185e71ca95cSGerald Jelinek rm -f $filename 186e71ca95cSGerald Jelinek fi 187e71ca95cSGerald Jelinek 188e71ca95cSGerald Jelinek cat <<-END >$filename || exit 1 1891022fd2aS #!/bin/sh -p 190e71ca95cSGerald Jelinek # 191e71ca95cSGerald Jelinek # Solaris Brand Replacement 192e71ca95cSGerald Jelinek # 193e71ca95cSGerald Jelinek # Attention. This file has been replaced with a new version for 194e71ca95cSGerald Jelinek # use in a virtualized environment. Modification of this script is not 195e71ca95cSGerald Jelinek # supported and all changes will be lost upon reboot. The 196e71ca95cSGerald Jelinek # {name}.pre_p2v version of this file is a backup copy of the 197e71ca95cSGerald Jelinek # original and should not be deleted. 198e71ca95cSGerald Jelinek # 199e71ca95cSGerald Jelinek END 200e71ca95cSGerald Jelinek 201e71ca95cSGerald Jelinek echo ". $runname \"\$@\"" >>$filename || exit 1 202e71ca95cSGerald Jelinek 203e71ca95cSGerald Jelinek chmod $mode $filename 204e71ca95cSGerald Jelinek chown $own $filename 205e71ca95cSGerald Jelinek} 206e71ca95cSGerald Jelinek 207ae104932SJonathan Adamssafe_wrap() 208ae104932SJonathan Adams{ 209ae104932SJonathan Adams typeset filename="$1" 210ae104932SJonathan Adams typeset runname="$2" 211ae104932SJonathan Adams typeset mode="$3" 212ae104932SJonathan Adams typeset own="$4" 213ae104932SJonathan Adams 214ae104932SJonathan Adams if [ -f $filename ]; then 215ae104932SJonathan Adams log "$e_cannot_wrap" "$filename" 216ae104932SJonathan Adams exit 1 217ae104932SJonathan Adams fi 218ae104932SJonathan Adams 219ae104932SJonathan Adams cat <<-END >$filename || exit 1 220ae104932SJonathan Adams #!/bin/sh 221ae104932SJonathan Adams # 222ae104932SJonathan Adams # Solaris Brand Wrapper 223ae104932SJonathan Adams # 224ae104932SJonathan Adams # Attention. This file has been created for use in a 225ae104932SJonathan Adams # virtualized environment. Modification of this script 226ae104932SJonathan Adams # is not supported and all changes will be lost upon reboot. 227ae104932SJonathan Adams # 228ae104932SJonathan Adams END 229ae104932SJonathan Adams 230ae104932SJonathan Adams echo ". $runname \"\$@\"" >>$filename || exit 1 231ae104932SJonathan Adams 232ae104932SJonathan Adams chmod $mode $filename 233ae104932SJonathan Adams chown $own $filename 234ae104932SJonathan Adams} 235ae104932SJonathan Adams 236edfa49ffS# 237*6e1ae2a3SGary Pennington# Read zonecfg fs entries and save the relevant data, one entry per 238edfa49ffS# line. 239edfa49ffS# This assumes the properties from the zonecfg output, e.g.: 240edfa49ffS# fs: 241edfa49ffS# dir: /opt 242edfa49ffS# special: /opt 243edfa49ffS# raw not specified 244edfa49ffS# type: lofs 245edfa49ffS# options: [noexec,ro,noatime] 246edfa49ffS# 247*6e1ae2a3SGary Pennington# and it assumes the order of the fs properties as above. 248edfa49ffS# 249edfa49ffSget_fs_info() 250edfa49ffS{ 251edfa49ffS zonecfg -z $zonename info fs | nawk '{ 252edfa49ffS if ($1 == "options:") { 253edfa49ffS # Remove brackets. 254edfa49ffS options=substr($2, 2, length($2) - 2); 255edfa49ffS printf("%s %s %s %s\n", dir, type, special, options); 256edfa49ffS } else if ($1 == "dir:") { 257edfa49ffS dir=$2; 258edfa49ffS } else if ($1 == "special:") { 259edfa49ffS special=$2; 260edfa49ffS } else if ($1 == "type:") { 261edfa49ffS type=$2 262edfa49ffS } 263edfa49ffS }' >> $fstmpfile 264edfa49ffS} 265edfa49ffS 266edfa49ffS# 267edfa49ffS# Mount zonecfg fs entries into the zonepath. 268edfa49ffS# 269edfa49ffSmnt_fs() 270edfa49ffS{ 271edfa49ffS if [ ! -s $fstmpfile ]; then 272edfa49ffS return; 273edfa49ffS fi 274edfa49ffS 275edfa49ffS # Sort the fs entries so we can handle nested mounts. 276edfa49ffS sort $fstmpfile | nawk -v zonepath=$zonepath '{ 277edfa49ffS if (NF == 4) 278edfa49ffS options="-o " $4; 279edfa49ffS else 280edfa49ffS options="" 281edfa49ffS 282edfa49ffS # Create the mount point. Ignore errors since we might have 283edfa49ffS # a nested mount with a pre-existing mount point. 284edfa49ffS cmd="/usr/bin/mkdir -p " zonepath "/root" $1 " >/dev/null 2>&1" 285edfa49ffS system(cmd); 286edfa49ffS 287edfa49ffS cmd="/usr/sbin/mount -F " $2 " " options " " $3 " " \ 288edfa49ffS zonepath "/root" $1; 289edfa49ffS if (system(cmd) != 0) { 290edfa49ffS printf("command failed: %s\n", cmd); 291edfa49ffS exit 1; 292edfa49ffS } 293edfa49ffS }' >>$LOGFILE 294edfa49ffS} 295edfa49ffS 296edfa49ffS# 297edfa49ffS# Unmount zonecfg fs entries from the zonepath. 298edfa49ffS# 299edfa49ffSumnt_fs() 300edfa49ffS{ 301edfa49ffS if [ ! -s $fstmpfile ]; then 302edfa49ffS return; 303edfa49ffS fi 304edfa49ffS 305edfa49ffS # Reverse sort the fs entries so we can handle nested unmounts. 306edfa49ffS sort -r $fstmpfile | nawk -v zonepath=$zonepath '{ 307edfa49ffS cmd="/usr/sbin/umount " zonepath "/root" $1 308edfa49ffS if (system(cmd) != 0) { 309edfa49ffS printf("command failed: %s\n", cmd); 310edfa49ffS } 311edfa49ffS }' >>$LOGFILE 312edfa49ffS} 313edfa49ffS 314e71ca95cSGerald Jelinek# Find the dataset mounted on the zonepath. 315e71ca95cSGerald Jelinekget_zonepath_ds() { 316e71ca95cSGerald Jelinek ZONEPATH_DS=`/usr/sbin/zfs list -H -t filesystem -o name,mountpoint | \ 317e71ca95cSGerald Jelinek /usr/bin/nawk -v zonepath=$1 '{ 318e71ca95cSGerald Jelinek if ($2 == zonepath) 319e71ca95cSGerald Jelinek print $1 320e71ca95cSGerald Jelinek }'` 321e71ca95cSGerald Jelinek 322e71ca95cSGerald Jelinek if [ -z "$ZONEPATH_DS" ]; then 323e71ca95cSGerald Jelinek fail_fatal "$f_no_ds" 324e71ca95cSGerald Jelinek fi 325e71ca95cSGerald Jelinek} 326e71ca95cSGerald Jelinek 327eba00995S# 328eba00995S# Perform any cleanup in the zoneroot after unpacking the archive. 329eba00995S# 330eba00995Spost_unpack() 331eba00995S{ 332eba00995S ( cd "$ZONEROOT" && \ 333eba00995S find . \( -type b -o -type c \) -exec rm -f "{}" \; ) 334eba00995S} 335eba00995S 336edfa49ffS# 337edfa49ffS# Determine flar compression style from identification file. 338edfa49ffS# 339edfa49ffSget_compression() 340edfa49ffS{ 341edfa49ffS typeset ident=$1 342edfa49ffS typeset line=$(grep "^files_compressed_method=" $ident) 343edfa49ffS 344edfa49ffS print ${line##*=} 345edfa49ffS} 346edfa49ffS 347edfa49ffS# 348edfa49ffS# Determine flar archive style from identification file. 349edfa49ffS# 350edfa49ffSget_archiver() 351edfa49ffS{ 352edfa49ffS typeset ident=$1 353edfa49ffS typeset line=$(grep "^files_archived_method=" $ident) 354edfa49ffS 355edfa49ffS print ${line##*=} 356edfa49ffS} 357edfa49ffS 358edfa49ffS# 359edfa49ffS# Unpack flar into current directory (which should be zoneroot). The flash 360edfa49ffS# archive is standard input. See flash_archive(4) man page. 361edfa49ffS# 362edfa49ffS# We can't use "flar split" since it will only unpack into a directory called 363edfa49ffS# "archive". We need to unpack in place in order to properly handle nested 364edfa49ffS# fs mounts within the zone root. This function does the unpacking into the 365edfa49ffS# current directory. 366edfa49ffS# 367edfa49ffS# This code is derived from the gen_split() function in /usr/sbin/flar so 368edfa49ffS# we keep the same style as the original. 369edfa49ffS# 370edfa49ffSinstall_flar() 371edfa49ffS{ 372edfa49ffS typeset result 373edfa49ffS typeset archiver_command 374edfa49ffS typeset archiver_arguments 375edfa49ffS 37674bbcaa8S vlog "cd $ZONEROOT && $stage1 "$insrc" | install_flar" 377edfa49ffS 378edfa49ffS # Read cookie 379edfa49ffS read -r input_line 380edfa49ffS if (( $? != 0 )); then 381edfa49ffS log "$not_readable" "$install_media" 382edfa49ffS return 1 383edfa49ffS fi 384edfa49ffS # The cookie has format FlAsH-aRcHiVe-m.n where m and n are integers. 385edfa49ffS if [[ ${input_line%%-[0-9]*.[0-9]*} != "FlAsH-aRcHiVe" ]]; then 386edfa49ffS log "$not_flar" 387edfa49ffS return 1 388edfa49ffS fi 389edfa49ffS 390edfa49ffS while [ true ] 391edfa49ffS do 392edfa49ffS # We should always be at the start of a section here 393edfa49ffS read -r input_line 394edfa49ffS if [[ ${input_line%%=*} != "section_begin" ]]; then 395edfa49ffS log "$bad_flar" 396edfa49ffS return 1 397edfa49ffS fi 398edfa49ffS section_name=${input_line##*=} 399edfa49ffS 400edfa49ffS # If we're at the archive, we're done skipping sections. 401edfa49ffS if [[ "$section_name" == "archive" ]]; then 402edfa49ffS break 403edfa49ffS fi 404edfa49ffS 405edfa49ffS # 406edfa49ffS # Save identification section to a file so we can determine 407edfa49ffS # how to unpack the archive. 408edfa49ffS # 409edfa49ffS if [[ "$section_name" == "identification" ]]; then 410edfa49ffS /usr/bin/rm -f identification 411edfa49ffS while read -r input_line 412edfa49ffS do 413edfa49ffS if [[ ${input_line%%=*} == \ 414edfa49ffS "section_begin" ]]; then 415edfa49ffS /usr/bin/rm -f identification 416edfa49ffS log "$bad_flar" 417edfa49ffS return 1 418edfa49ffS fi 419edfa49ffS 420edfa49ffS if [[ $input_line == \ 421edfa49ffS "section_end=$section_name" ]]; then 422edfa49ffS break; 423edfa49ffS fi 424edfa49ffS echo $input_line >> identification 425edfa49ffS done 426edfa49ffS 427edfa49ffS continue 428edfa49ffS fi 429edfa49ffS 430edfa49ffS # 431edfa49ffS # Otherwise skip past this section; read lines until detecting 432edfa49ffS # section_end. According to flash_archive(4) we can have 433edfa49ffS # an arbitrary number of sections but the archive section 434edfa49ffS # must be last. 435edfa49ffS # 436edfa49ffS success=0 437edfa49ffS while read -r input_line 438edfa49ffS do 439edfa49ffS if [[ $input_line == "section_end=$section_name" ]]; 440edfa49ffS then 441edfa49ffS success=1 442edfa49ffS break 443edfa49ffS fi 444edfa49ffS # Fail if we miss the end of the section 445edfa49ffS if [[ ${input_line%%=*} == "section_begin" ]]; then 446edfa49ffS /usr/bin/rm -f identification 447edfa49ffS log "$bad_flar" 448edfa49ffS return 1 449edfa49ffS fi 450edfa49ffS done 451edfa49ffS if (( $success == 0 )); then 452edfa49ffS # 453edfa49ffS # If we get here we read to the end of the file before 454edfa49ffS # seeing the end of the section we were reading. 455edfa49ffS # 456edfa49ffS /usr/bin/rm -f identification 457edfa49ffS log "$bad_flar" 458edfa49ffS return 1 459edfa49ffS fi 460edfa49ffS done 461edfa49ffS 462cec6066bS # Check for an archive made from a ZFS root pool. 463cec6066bS egrep -s "^rootpool=" identification 464cec6066bS if (( $? == 0 )); then 465cec6066bS /usr/bin/rm -f identification 466cec6066bS log "$bad_zfs_flar" 467cec6066bS return 1 468cec6066bS fi 469cec6066bS 470edfa49ffS # Get the information needed to unpack the archive. 471edfa49ffS archiver=$(get_archiver identification) 472edfa49ffS if [[ $archiver == "pax" ]]; then 473edfa49ffS # pax archiver specified 474edfa49ffS archiver_command="/usr/bin/pax" 475*6e1ae2a3SGary Pennington if [[ -s $fspaxfile ]]; then 476edfa49ffS archiver_arguments="-r -p e -c \ 477*6e1ae2a3SGary Pennington $(/usr/bin/cat $fspaxfile)" 478edfa49ffS else 479edfa49ffS archiver_arguments="-r -p e" 480edfa49ffS fi 481edfa49ffS elif [[ $archiver == "cpio" || -z $archiver ]]; then 482edfa49ffS # cpio archived specified OR no archiver specified - use default 483edfa49ffS archiver_command="/usr/bin/cpio" 484*6e1ae2a3SGary Pennington archiver_arguments="-icdumfE $fscpiofile" 485edfa49ffS else 486edfa49ffS # unknown archiver specified 487edfa49ffS log "$unknown_archiver" $archiver 488edfa49ffS return 1 489edfa49ffS fi 490edfa49ffS 491edfa49ffS if [[ ! -x $archiver_command ]]; then 492edfa49ffS /usr/bin/rm -f identification 493edfa49ffS log "$cmd_not_exec" $archiver_command 494edfa49ffS return 1 495edfa49ffS fi 496edfa49ffS 497edfa49ffS compression=$(get_compression identification) 498edfa49ffS 499edfa49ffS # We're done with the identification file 500edfa49ffS /usr/bin/rm -f identification 501edfa49ffS 502edfa49ffS # Extract archive 503edfa49ffS if [[ $compression == "compress" ]]; then 504eba00995S /usr/bin/zcat | \ 505edfa49ffS $archiver_command $archiver_arguments 2>/dev/null 506edfa49ffS else 507eba00995S $archiver_command $archiver_arguments 2>/dev/null 508edfa49ffS fi 509edfa49ffS result=$? 510edfa49ffS 511eba00995S post_unpack 512eba00995S 513edfa49ffS (( $result != 0 )) && return 1 514edfa49ffS 515edfa49ffS return 0 516edfa49ffS} 517edfa49ffS 5188c20418dSGerald Jelinek# 5198c20418dSGerald Jelinek# Get the archive base. 5208c20418dSGerald Jelinek# 5218c20418dSGerald Jelinek# We must unpack the archive in the right place within the zonepath so 5228c20418dSGerald Jelinek# that files are installed into the various mounted filesystems that are set 5238c20418dSGerald Jelinek# up in the zone's configuration. These are already mounted for us by the 5248c20418dSGerald Jelinek# mntfs function. 5258c20418dSGerald Jelinek# 5268c20418dSGerald Jelinek# Archives can be made of either a physical host's root file system or a 5278c20418dSGerald Jelinek# zone's zonepath. For a physical system, if the archive is made using an 5288c20418dSGerald Jelinek# absolute path (/...) we can't use it. For a zone the admin can make the 5298c20418dSGerald Jelinek# archive from a variety of locations; 5308c20418dSGerald Jelinek# 5318c20418dSGerald Jelinek# a) zonepath itself: This will be a single dir, probably named with the 5328c20418dSGerald Jelinek# zone name, it will contain a root dir and under the root we'll see all 5338c20418dSGerald Jelinek# the top level dirs; etc, var, usr... We must be above the ZONEPATH 5348c20418dSGerald Jelinek# when we unpack the archive but this will only work if the the archive's 5358c20418dSGerald Jelinek# top-level dir name matches the ZONEPATH base-level dir name. If not, 5368c20418dSGerald Jelinek# this is an error. 5378c20418dSGerald Jelinek# 5388c20418dSGerald Jelinek# b) inside the zonepath: We'll see root and it will contain all the top 5398c20418dSGerald Jelinek# level dirs; etc, var, usr.... We must be in the ZONEPATH when we unpack 5408c20418dSGerald Jelinek# the archive. 5418c20418dSGerald Jelinek# 5428c20418dSGerald Jelinek# c) inside the zonepath root: We'll see all the top level dirs, ./etc, 5438c20418dSGerald Jelinek# ./var, ./usr.... This is also the case we see when we get an archive 5448c20418dSGerald Jelinek# of a physical sytem. We must be in ZONEROOT when we unpack the archive. 5458c20418dSGerald Jelinek# 5468c20418dSGerald Jelinek# Note that there can be a directory named "root" under the ZONEPATH/root 5478c20418dSGerald Jelinek# directory. 5488c20418dSGerald Jelinek# 5498c20418dSGerald Jelinek# This function handles the above possibilities so that we reject absolute 5508c20418dSGerald Jelinek# path archives and figure out where in the file system we need to be to 5518c20418dSGerald Jelinek# properly unpack the archive into the zone. It sets the ARCHIVE_BASE 5528c20418dSGerald Jelinek# variable to the location where the achive should be unpacked. 5538c20418dSGerald Jelinek# 5548c20418dSGerald Jelinekget_archive_base() 5558c20418dSGerald Jelinek{ 5568c20418dSGerald Jelinek stage1=$1 5578c20418dSGerald Jelinek archive=$2 5588c20418dSGerald Jelinek stage2=$3 5598c20418dSGerald Jelinek 5608c20418dSGerald Jelinek vlog "$m_analyse_archive" 5618c20418dSGerald Jelinek 5628c20418dSGerald Jelinek base=`$stage1 $archive | $stage2 2>/dev/null | nawk -F/ '{ 5638c20418dSGerald Jelinek # Check for an absolute path archive 5648c20418dSGerald Jelinek if (substr($0, 1, 1) == "/") 5658c20418dSGerald Jelinek exit 1 5668c20418dSGerald Jelinek 5678c20418dSGerald Jelinek if ($1 != ".") 5688c20418dSGerald Jelinek dirs[$1] = 1 5698c20418dSGerald Jelinek else 5708c20418dSGerald Jelinek dirs[$2] = 1 5718c20418dSGerald Jelinek } 5728c20418dSGerald Jelinek END { 5738c20418dSGerald Jelinek for (d in dirs) { 5748c20418dSGerald Jelinek cnt++ 5758c20418dSGerald Jelinek if (d == "bin") sawbin = 1 5768c20418dSGerald Jelinek if (d == "etc") sawetc = 1 5778c20418dSGerald Jelinek if (d == "root") sawroot = 1 5788c20418dSGerald Jelinek if (d == "var") sawvar = 1 5798c20418dSGerald Jelinek } 5808c20418dSGerald Jelinek 5818c20418dSGerald Jelinek if (cnt == 1) { 5828c20418dSGerald Jelinek # If only one top-level dir named root, we are in the 5838c20418dSGerald Jelinek # zonepath, otherwise this must be an archive *of* 5848c20418dSGerald Jelinek # the zonepath so print the top-level dir name. 5858c20418dSGerald Jelinek if (sawroot) 5868c20418dSGerald Jelinek print "*zonepath*" 5878c20418dSGerald Jelinek else 5888c20418dSGerald Jelinek for (d in dirs) print d 5898c20418dSGerald Jelinek } else { 5908c20418dSGerald Jelinek # We are either in the zonepath or in the zonepath/root 5918c20418dSGerald Jelinek # (or at the top level of a full system archive which 5928c20418dSGerald Jelinek # looks like the zonepath/root case). Figure out which 5938c20418dSGerald Jelinek # one. 5948c20418dSGerald Jelinek if (sawroot && !sawbin && !sawetc && !sawvar) 5958c20418dSGerald Jelinek print "*zonepath*" 5968c20418dSGerald Jelinek else 5978c20418dSGerald Jelinek print "*zoneroot*" 5988c20418dSGerald Jelinek } 5998c20418dSGerald Jelinek }'` 6008c20418dSGerald Jelinek 6018c20418dSGerald Jelinek if (( $? != 0 )); then 6028c20418dSGerald Jelinek umnt_fs 6038c20418dSGerald Jelinek fatal "$e_absolute_archive" 6048c20418dSGerald Jelinek fi 6058c20418dSGerald Jelinek 6068c20418dSGerald Jelinek if [[ "$base" == "*zoneroot*" ]]; then 6078c20418dSGerald Jelinek ARCHIVE_BASE=$ZONEROOT 6088c20418dSGerald Jelinek elif [[ "$base" == "*zonepath*" ]]; then 6098c20418dSGerald Jelinek ARCHIVE_BASE=$ZONEPATH 6108c20418dSGerald Jelinek else 6118c20418dSGerald Jelinek # We need to be in the dir above the ZONEPATH but we need to 6128c20418dSGerald Jelinek # validate that $base matches the final component of ZONEPATH. 6138c20418dSGerald Jelinek bname=`basename $ZONEPATH` 6148c20418dSGerald Jelinek 6158c20418dSGerald Jelinek if [[ "$bname" != "$base" ]]; then 6168c20418dSGerald Jelinek umnt_fs 6178c20418dSGerald Jelinek fatal "$e_mismatch_archive" "$base" "$bname" 6188c20418dSGerald Jelinek fi 6198c20418dSGerald Jelinek ARCHIVE_BASE=`dirname $ZONEPATH` 6208c20418dSGerald Jelinek fi 6218c20418dSGerald Jelinek} 6228c20418dSGerald Jelinek 623edfa49ffS# 624edfa49ffS# Unpack cpio archive into zoneroot. 625edfa49ffS# 626edfa49ffSinstall_cpio() 627edfa49ffS{ 628edfa49ffS stage1=$1 629edfa49ffS archive=$2 630edfa49ffS 6318c20418dSGerald Jelinek get_archive_base "$stage1" "$archive" "cpio -it" 63262ac5336S 633*6e1ae2a3SGary Pennington cpioopts="-idmfE $fscpiofile" 634edfa49ffS 6358c20418dSGerald Jelinek vlog "cd \"$ARCHIVE_BASE\" && $stage1 \"$archive\" | cpio $cpioopts" 636eba00995S 637cec6066bS # Ignore errors from cpio since we expect some errors depending on 638cec6066bS # how the archive was made. 6398c20418dSGerald Jelinek ( cd "$ARCHIVE_BASE" && $stage1 "$archive" | cpio $cpioopts ) 640eba00995S 641eba00995S post_unpack 642edfa49ffS 643cec6066bS return 0 644edfa49ffS} 645edfa49ffS 646edfa49ffS# 647edfa49ffS# Unpack pax archive into zoneroot. 648edfa49ffS# 649edfa49ffSinstall_pax() 650edfa49ffS{ 651edfa49ffS archive=$1 652edfa49ffS 6538c20418dSGerald Jelinek get_archive_base "cat" "$archive" "pax" 65462ac5336S 655*6e1ae2a3SGary Pennington if [[ -s $fspaxfile ]]; then 656*6e1ae2a3SGary Pennington filtopt="-c $(/usr/bin/cat $fspaxfile)" 657edfa49ffS fi 658edfa49ffS 6598c20418dSGerald Jelinek vlog "cd \"$ARCHIVE_BASE\" && pax -r -f \"$archive\" $filtopt" 660edfa49ffS 661cec6066bS # Ignore errors from pax since we expect some errors depending on 662cec6066bS # how the archive was made. 6638c20418dSGerald Jelinek ( cd "$ARCHIVE_BASE" && pax -r -f "$archive" $filtopt ) 664eba00995S 665eba00995S post_unpack 666eba00995S 667cec6066bS return 0 668edfa49ffS} 669edfa49ffS 670edfa49ffS# 671edfa49ffS# Unpack UFS dump into zoneroot. 672edfa49ffS# 673edfa49ffSinstall_ufsdump() 674edfa49ffS{ 675edfa49ffS archive=$1 676edfa49ffS 677eba00995S vlog "cd \"$ZONEROOT\" && ufsrestore rf \"$archive\"" 678edfa49ffS 679edfa49ffS # 680edfa49ffS # ufsrestore goes interactive if you ^C it. To prevent that, 681edfa49ffS # we make sure its stdin is not a terminal. 682edfa49ffS # 683eba00995S ( cd "$ZONEROOT" && ufsrestore rf "$archive" < /dev/null ) 684eba00995S result=$? 685eba00995S 686eba00995S post_unpack 687eba00995S 688eba00995S return $result 689edfa49ffS} 690edfa49ffS 691edfa49ffS# 692edfa49ffS# Copy directory hierarchy into zoneroot. 693edfa49ffS# 694edfa49ffSinstall_dir() 695edfa49ffS{ 696edfa49ffS source_dir=$1 697edfa49ffS 698edfa49ffS cpioopts="-pdm" 699edfa49ffS 700edfa49ffS first=1 701*6e1ae2a3SGary Pennington filt=$(for i in $(cat $fspaxfile) 702edfa49ffS do 703edfa49ffS echo $i | egrep -s "/" && continue 704edfa49ffS if [[ $first == 1 ]]; then 705edfa49ffS printf "^%s" $i 706edfa49ffS first=0 707edfa49ffS else 708edfa49ffS printf "|^%s" $i 709edfa49ffS fi 710edfa49ffS done) 711edfa49ffS 712edfa49ffS list=$(cd "$source_dir" && ls -d * | egrep -v "$filt") 713edfa49ffS flist=$(for i in $list 714edfa49ffS do 715edfa49ffS printf "%s " "$i" 716edfa49ffS done) 717edfa49ffS findopts="-xdev ( -type d -o -type f -o -type l ) -print" 718edfa49ffS 719edfa49ffS vlog "cd \"$source_dir\" && find $flist $findopts | " 720eba00995S vlog "cpio $cpioopts \"$ZONEROOT\"" 721edfa49ffS 722cec6066bS # Ignore errors from cpio since we expect some errors depending on 723cec6066bS # how the archive was made. 724edfa49ffS ( cd "$source_dir" && find $flist $findopts | \ 725eba00995S cpio $cpioopts "$ZONEROOT" ) 726eba00995S 727eba00995S post_unpack 728eba00995S 729cec6066bS return 0 730edfa49ffS} 731edfa49ffS 73274bbcaa8S# 73374bbcaa8S# This is a common function for laying down a zone image from a variety of 73474bbcaa8S# different sources. This can be used to either install a fresh zone or as 73574bbcaa8S# part of zone migration during attach. 73674bbcaa8S# 73774bbcaa8S# The first argument specifies the type of image: archive, directory or stdin. 73874bbcaa8S# The second argument specifies the image itself. In the case of stdin, the 73974bbcaa8S# second argument specifies the format of the stream (cpio, flar, etc.). 74074bbcaa8S# Any validation or post-processing on the image is done elsewhere. 74174bbcaa8S# 74274bbcaa8S# This function calls a 'sanity_check' function which must be provided by 74374bbcaa8S# the script which includes this code. 74474bbcaa8S# 74574bbcaa8Sinstall_image() 74674bbcaa8S{ 74774bbcaa8S intype=$1 74874bbcaa8S insrc=$2 74974bbcaa8S 75074bbcaa8S if [[ -z "$intype" || -z "$insrc" ]]; then 75174bbcaa8S return 1 75274bbcaa8S fi 75374bbcaa8S 75474bbcaa8S filetype="unknown" 75574bbcaa8S filetypename="unknown" 75674bbcaa8S stage1="cat" 75774bbcaa8S 75874bbcaa8S if [[ "$intype" == "directory" ]]; then 75974bbcaa8S if [[ "$insrc" == "-" ]]; then 76074bbcaa8S # Indicates that the existing zonepath is prepopulated. 76174bbcaa8S filetype="existing" 76274bbcaa8S filetypename="existing" 76374bbcaa8S else 76474bbcaa8S if [[ "$(echo $insrc | cut -c 1)" != "/" ]]; then 76574bbcaa8S fatal "$e_path_abs" "$insrc" 76674bbcaa8S fi 76774bbcaa8S 76874bbcaa8S if [[ ! -e "$insrc" ]]; then 76974bbcaa8S log "$e_not_found" "$insrc" 77074bbcaa8S fatal "$e_install_abort" 77174bbcaa8S fi 77274bbcaa8S 77374bbcaa8S if [[ ! -r "$insrc" ]]; then 77474bbcaa8S log "$e_not_readable" "$insrc" 77574bbcaa8S fatal "$e_install_abort" 77674bbcaa8S fi 77774bbcaa8S 77874bbcaa8S if [[ ! -d "$insrc" ]]; then 77974bbcaa8S log "$e_not_dir" 78074bbcaa8S fatal "$e_install_abort" 78174bbcaa8S fi 78274bbcaa8S 78374bbcaa8S sanity_check $insrc 78474bbcaa8S 78574bbcaa8S filetype="directory" 78674bbcaa8S filetypename="directory" 78774bbcaa8S fi 78874bbcaa8S 78974bbcaa8S else 79074bbcaa8S # Common code for both archive and stdin stream. 79174bbcaa8S 79274bbcaa8S if [[ "$intype" == "archive" ]]; then 79374bbcaa8S if [[ ! -f "$insrc" ]]; then 79474bbcaa8S log "$e_unknown_archive" 79574bbcaa8S fatal "$e_install_abort" 79674bbcaa8S fi 79774bbcaa8S ftype="$(LC_ALL=C file $insrc | cut -d: -f 2)" 79874bbcaa8S else 79974bbcaa8S # For intype == stdin, the insrc parameter specifies 80074bbcaa8S # the stream format coming on stdin. 80174bbcaa8S ftype="$insrc" 80274bbcaa8S insrc="-" 80374bbcaa8S fi 80474bbcaa8S 80574bbcaa8S # Setup vars for the archive type we have. 80674bbcaa8S case "$ftype" in 80774bbcaa8S *cpio*) filetype="cpio" 80874bbcaa8S filetypename="cpio archive" 80974bbcaa8S ;; 81074bbcaa8S *bzip2*) filetype="bzip2" 81174bbcaa8S filetypename="bzipped cpio archive" 81274bbcaa8S ;; 81374bbcaa8S *gzip*) filetype="gzip" 81474bbcaa8S filetypename="gzipped cpio archive" 81574bbcaa8S ;; 81674bbcaa8S *ufsdump*) filetype="ufsdump" 81774bbcaa8S filetypename="ufsdump archive" 81874bbcaa8S ;; 81974bbcaa8S "flar") 82074bbcaa8S filetype="flar" 82174bbcaa8S filetypename="flash archive" 82274bbcaa8S ;; 82374bbcaa8S "flash") 82474bbcaa8S filetype="flar" 82574bbcaa8S filetypename="flash archive" 82674bbcaa8S ;; 82774bbcaa8S *Flash\ Archive*) 82874bbcaa8S filetype="flar" 82974bbcaa8S filetypename="flash archive" 83074bbcaa8S ;; 83174bbcaa8S "tar") 83274bbcaa8S filetype="tar" 83374bbcaa8S filetypename="tar archive" 83474bbcaa8S ;; 83574bbcaa8S *USTAR\ tar\ archive) 83674bbcaa8S filetype="tar" 83774bbcaa8S filetypename="tar archive" 83874bbcaa8S ;; 83974bbcaa8S "pax") 84074bbcaa8S filetype="xustar" 84174bbcaa8S filetypename="pax (xustar) archive" 84274bbcaa8S ;; 84374bbcaa8S *USTAR\ tar\ archive\ extended\ format*) 84474bbcaa8S filetype="xustar" 84574bbcaa8S filetypename="pax (xustar) archive" 84674bbcaa8S ;; 84774bbcaa8S "zfs") 84874bbcaa8S filetype="zfs" 84974bbcaa8S filetypename="ZFS send stream" 85074bbcaa8S ;; 85174bbcaa8S *ZFS\ snapshot\ stream*) 85274bbcaa8S filetype="zfs" 85374bbcaa8S filetypename="ZFS send stream" 85474bbcaa8S ;; 85574bbcaa8S *) log "$e_unknown_archive" 85674bbcaa8S fatal "$e_install_abort" 85774bbcaa8S ;; 85874bbcaa8S esac 85974bbcaa8S fi 86074bbcaa8S 86174bbcaa8S vlog "$filetypename" 86274bbcaa8S 86374bbcaa8S # Check for a non-empty root if no '-d -' option. 86474bbcaa8S if [[ "$filetype" != "existing" ]]; then 86574bbcaa8S cnt=$(ls $ZONEROOT | wc -l) 86674bbcaa8S if (( $cnt != 0 )); then 86774bbcaa8S fatal "$e_root_full" "$ZONEROOT" 86874bbcaa8S fi 86974bbcaa8S fi 87074bbcaa8S 87174bbcaa8S fstmpfile=$(/usr/bin/mktemp -t -p /var/tmp) 87274bbcaa8S if [[ -z "$fstmpfile" ]]; then 87374bbcaa8S fatal "$e_tmpfile" 87474bbcaa8S fi 87574bbcaa8S 87674bbcaa8S # Make sure we always have the files holding the directories to filter 87774bbcaa8S # out when extracting from a CPIO or PAX archive. We'll add the fs 878*6e1ae2a3SGary Pennington # entries to these files in get_fs_info() 879*6e1ae2a3SGary Pennington fscpiofile=$(/usr/bin/mktemp -t -p /var/tmp fs.cpio.XXXXXX) 880*6e1ae2a3SGary Pennington if [[ -z "$fscpiofile" ]]; then 88174bbcaa8S rm -f $fstmpfile 88274bbcaa8S fatal "$e_tmpfile" 88374bbcaa8S fi 88474bbcaa8S 885*6e1ae2a3SGary Pennington # Filter out these directories. 886*6e1ae2a3SGary Pennington echo 'dev/*' >>$fscpiofile 887*6e1ae2a3SGary Pennington echo 'devices/*' >>$fscpiofile 888*6e1ae2a3SGary Pennington echo 'devices' >>$fscpiofile 889*6e1ae2a3SGary Pennington echo 'proc/*' >>$fscpiofile 890*6e1ae2a3SGary Pennington echo 'tmp/*' >>$fscpiofile 891*6e1ae2a3SGary Pennington echo 'var/run/*' >>$fscpiofile 892*6e1ae2a3SGary Pennington echo 'system/contract/*' >>$fscpiofile 893*6e1ae2a3SGary Pennington echo 'system/object/*' >>$fscpiofile 894*6e1ae2a3SGary Pennington 895*6e1ae2a3SGary Pennington fspaxfile=$(/usr/bin/mktemp -t -p /var/tmp fs.pax.XXXXXX) 896*6e1ae2a3SGary Pennington if [[ -z "$fspaxfile" ]]; then 897*6e1ae2a3SGary Pennington rm -f $fstmpfile $fscpiofile 89874bbcaa8S fatal "$e_tmpfile" 89974bbcaa8S fi 90074bbcaa8S 90174bbcaa8S printf "%s " \ 90274bbcaa8S "dev devices proc tmp var/run system/contract system/object" \ 903*6e1ae2a3SGary Pennington >>$fspaxfile 90474bbcaa8S 90574bbcaa8S # Set up any fs mounts so the archive will install into the correct 90674bbcaa8S # locations. 90774bbcaa8S get_fs_info 90874bbcaa8S mnt_fs 90974bbcaa8S if (( $? != 0 )); then 91074bbcaa8S umnt_fs >/dev/null 2>&1 911*6e1ae2a3SGary Pennington rm -f $fstmpfile $fscpiofile $fspaxfile 91274bbcaa8S fatal "$mount_failed" 91374bbcaa8S fi 91474bbcaa8S 91574bbcaa8S if [[ "$filetype" == "existing" ]]; then 91674bbcaa8S log "$no_installing" 91774bbcaa8S else 91874bbcaa8S log "$installing" 91974bbcaa8S fi 92074bbcaa8S 92174bbcaa8S # 92274bbcaa8S # Install the image into the zonepath. 92374bbcaa8S # 92474bbcaa8S unpack_result=0 92574bbcaa8S stage1="cat" 92674bbcaa8S if [[ "$filetype" == "gzip" ]]; then 92774bbcaa8S stage1="gzcat" 92874bbcaa8S filetype="cpio" 92974bbcaa8S elif [[ "$filetype" == "bzip2" ]]; then 93074bbcaa8S stage1="bzcat" 93174bbcaa8S filetype="cpio" 93274bbcaa8S fi 93374bbcaa8S 93474bbcaa8S if [[ "$filetype" == "cpio" ]]; then 93574bbcaa8S install_cpio "$stage1" "$insrc" 93674bbcaa8S unpack_result=$? 93774bbcaa8S 93874bbcaa8S elif [[ "$filetype" == "flar" ]]; then 93974bbcaa8S ( cd "$ZONEROOT" && $stage1 $insrc | install_flar ) 94074bbcaa8S unpack_result=$? 94174bbcaa8S 94274bbcaa8S elif [[ "$filetype" == "xustar" ]]; then 94374bbcaa8S install_pax "$insrc" 94474bbcaa8S unpack_result=$? 94574bbcaa8S 94674bbcaa8S elif [[ "$filetype" = "tar" ]]; then 94774bbcaa8S vlog "cd \"$ZONEROOT\" && tar -xf \"$insrc\"" 948cec6066bS # Ignore errors from tar since we expect some errors depending 949cec6066bS # on how the archive was made. 95074bbcaa8S ( cd "$ZONEROOT" && tar -xf "$insrc" ) 951cec6066bS unpack_result=0 95274bbcaa8S post_unpack 95374bbcaa8S 95474bbcaa8S elif [[ "$filetype" == "ufsdump" ]]; then 95574bbcaa8S install_ufsdump "$insrc" 95674bbcaa8S unpack_result=$? 95774bbcaa8S 95874bbcaa8S elif [[ "$filetype" == "directory" ]]; then 95974bbcaa8S install_dir "$insrc" 96074bbcaa8S unpack_result=$? 96174bbcaa8S 96274bbcaa8S elif [[ "$filetype" == "zfs" ]]; then 96374bbcaa8S # 96474bbcaa8S # Given a 'zfs send' stream file, receive the snapshot into 96574bbcaa8S # the zone's dataset. We're getting the original system's 96674bbcaa8S # zonepath dataset. Destroy the existing dataset created 96774bbcaa8S # above since this recreates it. 96874bbcaa8S # 96974bbcaa8S if [[ -z "$DATASET" ]]; then 97074bbcaa8S fatal "$f_nodataset" 97174bbcaa8S fi 97274bbcaa8S /usr/sbin/zfs destroy "$DATASET" 97374bbcaa8S if (( $? != 0 )); then 97474bbcaa8S log "$f_zfsdestroy" "$DATASET" 97574bbcaa8S fi 97674bbcaa8S 97774bbcaa8S vlog "$stage1 $insrc | zfs receive -F $DATASET" 97874bbcaa8S ( $stage1 $insrc | /usr/sbin/zfs receive -F $DATASET ) 97974bbcaa8S unpack_result=$? 98074bbcaa8S fi 98174bbcaa8S 98274bbcaa8S # Clean up any fs mounts used during unpacking. 98374bbcaa8S umnt_fs 984*6e1ae2a3SGary Pennington rm -f $fstmpfile $fscpiofile $fspaxfile 98574bbcaa8S 98674bbcaa8S chmod 700 $zonepath 98774bbcaa8S 988cec6066bS (( $unpack_result != 0 )) && fatal "$f_unpack_failed" 989cec6066bS 99074bbcaa8S # Verify this is a valid image. 99174bbcaa8S sanity_check $ZONEROOT 99274bbcaa8S 99374bbcaa8S return 0 99474bbcaa8S} 99574bbcaa8S 996edfa49ffS# Setup i18n output 997edfa49ffSTEXTDOMAIN="SUNW_OST_OSCMD" 998edfa49ffSexport TEXTDOMAIN 999edfa49ffS 1000ae104932SJonathan Adamse_cannot_wrap=$(gettext "%s: error: wrapper file already exists") 1001edfa49ffSe_baddir=$(gettext "Invalid '%s' directory within the zone") 1002edfa49ffSe_badfile=$(gettext "Invalid '%s' file within the zone") 100374bbcaa8Se_path_abs=$(gettext "Pathname specified to -a '%s' must be absolute.") 100474bbcaa8Se_not_found=$(gettext "%s: error: file or directory not found.") 100574bbcaa8Se_install_abort=$(gettext "Installation aborted.") 100674bbcaa8Se_not_readable=$(gettext "Cannot read directory '%s'") 100774bbcaa8Se_not_dir=$(gettext "Error: must be a directory") 100874bbcaa8Se_unknown_archive=$(gettext "Error: Unknown archive format. Must be a flash archive, a cpio archive (can also be gzipped or bzipped), a pax XUSTAR archive, or a level 0 ufsdump archive.") 100962ac5336Se_absolute_archive=$(gettext "Error: archive contains absolute paths instead of relative paths.") 10108c20418dSGerald Jelineke_mismatch_archive=$(gettext "Error: the archive top-level directory (%s) does not match the zonepath (%s).") 101174bbcaa8Se_tmpfile=$(gettext "Unable to create temporary file") 101274bbcaa8Se_root_full=$(gettext "Zonepath root %s exists and contains data; remove or move aside prior to install.") 1013e71ca95cSGerald Jelinekf_mkdir=$(gettext "Unable to create directory %s.") 1014e71ca95cSGerald Jelinekf_chmod=$(gettext "Unable to chmod directory %s.") 1015e71ca95cSGerald Jelinekf_chown=$(gettext "Unable to chown directory %s.") 101674bbcaa8S 101774bbcaa8S 10188c20418dSGerald Jelinekm_analyse_archive=$(gettext "Analysing the archive") 10198c20418dSGerald Jelinek 102074bbcaa8Snot_readable=$(gettext "Cannot read file '%s'") 102174bbcaa8Snot_flar=$(gettext "Input is not a flash archive") 102274bbcaa8Sbad_flar=$(gettext "Flash archive is a corrupt") 1023cec6066bSbad_zfs_flar=$(gettext "Flash archive contains a ZFS send stream.\n\tRecreate the flar using the -L option with cpio or pax.") 1024cec6066bSf_unpack_failed=$(gettext "Unpacking the archive failed") 102574bbcaa8Sunknown_archiver=$(gettext "Archiver %s is not supported") 102674bbcaa8Scmd_not_exec=$(gettext "Required command '%s' not executable!") 1027edfa49ffS 1028edfa49ffS# 1029edfa49ffS# Exit values used by the script, as #defined in <sys/zone.h> 1030edfa49ffS# 1031edfa49ffS# ZONE_SUBPROC_OK 1032edfa49ffS# =============== 1033edfa49ffS# Installation was successful 1034edfa49ffS# 1035edfa49ffS# ZONE_SUBPROC_USAGE 1036edfa49ffS# ================== 1037edfa49ffS# Improper arguments were passed, so print a usage message before exiting 1038edfa49ffS# 1039edfa49ffS# ZONE_SUBPROC_NOTCOMPLETE 1040edfa49ffS# ======================== 1041edfa49ffS# Installation did not complete, but another installation attempt can be 1042edfa49ffS# made without an uninstall 1043edfa49ffS# 1044edfa49ffS# ZONE_SUBPROC_FATAL 1045edfa49ffS# ================== 1046edfa49ffS# Installation failed and an uninstall will be required before another 1047edfa49ffS# install can be attempted 1048edfa49ffS# 1049edfa49ffSZONE_SUBPROC_OK=0 1050edfa49ffSZONE_SUBPROC_USAGE=253 1051edfa49ffSZONE_SUBPROC_NOTCOMPLETE=254 1052edfa49ffSZONE_SUBPROC_FATAL=255 1053edfa49ffS 1054