1 #!/bin/ksh 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 # Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. 24 # 25 # Author: Jeff Bonwick 26 # 27 # Please report any bugs to bonwick@eng. 28 # 29 # How Install works: 30 # 31 # Install performs the following steps: 32 # 33 # 1. Get the list of modules, configuration files, and links 34 # that are desired. 35 # 36 # 2. Create the requested subset of /kernel in Install's temp space 37 # (/tmp/Install.username by default.) 38 # 39 # 3. Create a tar file (/tmp/Install.username/Install.tar) based on (3). 40 # 41 # 4. If -n was specified, exit. If a target was specified using -T, 42 # rcp the tarfile to the target and exit. If a target was specified 43 # using -t, rsh to the target machine and untar the tarfile in the 44 # target directory. 45 # 46 # If any of these steps fail, Install will give you an error message and, 47 # in most cases, suggest corrective measures. Then, you can recover the 48 # install with "Install -R". (This is not required; it's just faster than 49 # starting from scratch.) 50 # 51 # One final comment: Unfortunately, tar and I disagree on what 52 # constitutes a fatal error. (tar -x will exit 0 even if it can't write 53 # anything in the current directory.) Thus, I am reduced to grepping stderr 54 # for (what I consider) fatal and nonfatal error messages. If you run into 55 # a situation where this doesn't behave the way you think it should (either 56 # an "Install failed" message after a successful install, or an "Install 57 # complete" message after it bombs), please let me know. 58 59 # 60 # The CDPATH variable causes ksh's `cd' builtin to emit messages to stdout 61 # under certain circumstances, which can really screw things up; unset it. 62 # 63 unset CDPATH 64 65 INSTALL=`basename $0` 66 DOT=`pwd` 67 68 TRAILER="Install.$LOGNAME" 69 INSTALL_STATE=${INSTALL_STATE-$HOME/.Install.state} 70 export INSTALL_STATE 71 INSTALL_DIR=${INSTALL_DIR-/tmp/$TRAILER} 72 if [ "`basename $INSTALL_DIR`" != "$TRAILER" ]; then 73 INSTALL_DIR="$INSTALL_DIR/$TRAILER" 74 fi 75 export INSTALL_DIR 76 INSTALL_LIB=${INSTALL_LIB-$HOME/LibInstall} 77 export INSTALL_LIB 78 INSTALL_RC=${INSTALL_RC-$HOME/.Installrc} 79 export INSTALL_RC 80 INSTALL_CP=${INSTALL_CP-"cp -p"} 81 export INSTALL_CP 82 INSTALL_RCP=${INSTALL_RCP-"rcp -p"} 83 export INSTALL_RCP 84 85 STATE=0 86 87 DEFAULT_OPTIONS="-naq" 88 GLOM=no 89 GLOMNAME=kernel 90 IMPL="default" 91 WANT32="yes" 92 WANT64="yes" 93 94 modlist=/tmp/modlist$$ 95 # dummy directory for make state files. 96 modstatedir=/tmp/modstate$$ 97 98 trap 'fail "User Interrupt" "You can resume by typing \"$INSTALL -R\""' 1 2 3 15 99 100 function usage { 101 echo "" 102 echo $1 103 echo ' 104 Usage: Install [ -w workspace ] 105 [ -s srcdir (default: usr/src/uts) ] 106 [ -k karch (e.g. sun4u; required if not deducible from pwd) ] 107 [ -t target (extract tar file on target, e.g. user@machine:/) ] 108 [ -T target (copy tar file to target, e.g. user@machine:/tmp) ] 109 [ -n (no target, just create tar file in /tmp (default)) ] 110 [ -u (install unix only) ] 111 [ -m (install modules only) ] 112 [ -a (install everything, i.e. unix + modules (default)) ] 113 [ -v (verbose output) ] 114 [ -V (REALLY verbose output) ] 115 [ -q (quiet (default)) ] 116 [ -c (clean up (remove temp files) when done (default) ] 117 [ -p (preserve temp files -- useful for debugging) ] 118 [ -L (library create: put tarfile in $INSTALL_LIB/env.karch) ] 119 [ -l lib (library extract: use $INSTALL_LIB/lib as source) ] 120 [ -D libdir (default: $HOME/LibInstall) ] 121 [ -d tempdir (Install work area (default: /tmp)) ] 122 [ -G glomname (put all files under platform/karch/glomname) ] 123 [ -i impl (e.g. sunfire; recommended with -G) ] 124 [ -x (update /etc/name_to_major et al) ] 125 [ -X (do not update /etc/name_to_major et al (default)) ] 126 [ -P (update /etc/path_to_inst -- generally not advisable) ] 127 [ -h (help -- prints this message) ] 128 [ -R (recover a previous Install) ] 129 [ -o objdir (object directory - either obj or debug (the default)) ] 130 [ -K (do not copy kmdb) ] 131 [ -3 32-bit modules only ] 132 [ -6 64-bit modules only ] 133 [ list of modules to install ] 134 135 For full details: 136 137 man -M /ws/on297-gate/public/docs Install 138 ' 139 exit 1 140 } 141 142 # 143 # Save the current state of Install 144 # 145 146 function save_state { 147 rm -f $INSTALL_STATE 148 (echo "# State of previous Install 149 TARGET=$TARGET 150 ENV_PATH=$ENV_PATH 151 ENV_NAME=$ENV_NAME 152 KARCH=$KARCH 153 UTS=$UTS 154 INSTALL_DIR=$INSTALL_DIR 155 INSTALL_LIB=$INSTALL_LIB 156 IMODE=$IMODE 157 LIBCREATE=$LIBCREATE 158 LIBSRC=$LIBSRC 159 VERBOSE=$VERBOSE 160 CLEANUP=$CLEANUP 161 GLOM=$GLOM 162 GLOMNAME=$GLOMNAME 163 KMDB=$KMDB 164 files='$files' 165 STATE=$STATE" >$INSTALL_STATE) || verbose "Warning: cannot save state" 166 } 167 168 # 169 # Restore the previous state of Install 170 # 171 172 function restore_state { 173 test -s $INSTALL_STATE || fail "Can't find $INSTALL_STATE" 174 eval "`cat $INSTALL_STATE`" 175 } 176 177 # 178 # Install failed -- print error messages and exit 2 179 # 180 181 function fail { 182 save_state 183 # 184 # We might have gotten here via a trap. So wait for any 185 # children (especially "make modlist") to exit before giving 186 # the error message or cleaning up. 187 # 188 wait 189 while [ $# -gt 0 ] 190 do 191 echo $1 192 shift 193 done 194 rm -rf $modstatedir 195 rm -f $modlist 196 echo "Install failed" 197 exit 2 198 } 199 200 # 201 # Echo a string in verbose mode only 202 # 203 204 function verbose { 205 test "$VERBOSE" != "q" && echo $1 206 } 207 208 # 209 # hack for tmpfs bug -- remove files gradually 210 # 211 212 function remove_dir { 213 test -d $1 || return 214 local_dot=`pwd` 215 cd $1 216 touch foo 217 rm -f `find . -type f -print` 218 cd $local_dot 219 rm -rf $1 220 } 221 222 # 223 # Create a directory if it doesn't already exist. 224 # mkdir will provide an error message, so don't provide an additional 225 # message. 226 # 227 228 function tstmkdir { 229 [ -d $1 ] || mkdir -p $1 || fail 230 } 231 232 # 233 # Patch up target directories for glommed kernel. 234 # usage: fixglom listfile glomname 235 # 236 237 function fixglom { 238 nawk \ 239 -v glomname=$2 \ 240 -v karch=$KARCH ' 241 $1 == "MOD" || $1 == "SYMLINK" { 242 sub(/^platform.*kernel/, "platform/" karch "/" glomname, $4) 243 sub(/^kernel/, "platform/" karch "/" glomname, $4) 244 sub(/^usr.kernel/, "platform/" karch "/" glomname, $4) 245 print 246 } 247 $1 == "LINK" { 248 sub(/^platform.*kernel/, "platform/" karch "/" glomname, $3) 249 sub(/^kernel/, "platform/" karch "/" glomname, $3) 250 sub(/^usr.kernel/, "platform/" karch "/" glomname, $3) 251 sub(/^platform.*kernel/, "platform/" karch "/" glomname, $5) 252 sub(/^kernel/, "platform/" karch "/" glomname, $5) 253 sub(/^usr.kernel/, "platform/" karch "/" glomname, $5) 254 print 255 } 256 $1 == "CONF" { 257 sub(/^platform.*kernel/, "platform/" karch "/" glomname, $3) 258 sub(/^kernel/, "platform/" karch "/" glomname, $3) 259 sub(/^usr.kernel/, "platform/" karch "/" glomname, $3) 260 print 261 } 262 ' $1 > $1.new 263 mv $1.new $1 264 } 265 266 # 267 # Filter out implementation-specific modules, unless that 268 # implementation was requested by the user. 269 # usage: filtimpl listfile implname 270 # 271 272 function filtimpl { 273 nawk \ 274 -v impl=$2 ' 275 $1 == "MOD" || $1 == "SYMLINK" { 276 if ($6 == "all" || $6 == impl) 277 print 278 } 279 $1 == "CONF" { 280 if ($5 == "all" || $5 == impl) 281 print 282 } 283 $1 == "LINK" { 284 if ($7 == "all" || $7 == impl) 285 print 286 } 287 ' $1 > $1.new 288 mv $1.new $1 289 } 290 291 # 292 # Filter the module list to match the user's request. 293 # Usage: filtmod listfile modules 294 # 295 function filtmod { 296 nawk -v reqstring="$2" ' 297 function modmatch(modname) { 298 if (reqstring == "All") { 299 return (1) 300 } else if (reqstring == "Modules") { 301 if (modname != "unix" && modname != "genunix") 302 return (1) 303 } else { 304 if (modname in reqmods) 305 return (1) 306 } 307 return (0) 308 } 309 BEGIN { 310 # 311 # The split call creates indexes 1, 2, 3, ... We want 312 # the module names as indexes. 313 # 314 split(reqstring, tmpmods) 315 for (i in tmpmods) 316 reqmods[tmpmods[i]] = 1 317 } 318 $1 == "MOD" { 319 if (modmatch($3)) 320 print 321 } 322 $1 == "CONF" { 323 if (modmatch($6)) 324 print 325 } 326 $1 == "SYMLINK" { 327 if (modmatch($7)) 328 print 329 } 330 $1 == "LINK" { 331 if (modmatch($4)) 332 print 333 } 334 ' $1 > $1.new 335 mv $1.new $1 336 } 337 338 # 339 # Unpack the crypto tarball into the given tree, then massage the 340 # tree so that the binaries are all in objNN or debugNN directories. 341 # 342 function unpack_crypto { 343 typeset tarfile=$1 344 typeset ctop=$2 345 [ -d "$ctop" ] || fail "Can't create tree for crypto modules." 346 347 [ "$VERBOSE" = "V" ] && echo "unpacking crypto tarball into $ctop..." 348 bzcat "$tarfile" | (cd "$ctop"; tar xf -) 349 350 typeset root="$ctop/proto/root_$MACH" 351 [ $OBJD = obj ] && root="$ctop/proto/root_$MACH-nd" 352 [ -d "$root" ] || fail "Can't unpack crypto tarball." 353 354 (cd "$root"; for d in platform kernel usr/kernel; do 355 [ ! -d $d ] && continue 356 find $d -type f -print 357 done) | while read file; do 358 typeset dir=$(dirname "$file") 359 typeset base=$(basename "$file") 360 typeset type=$(basename "$dir") 361 if [ "$type" = amd64 ]; then 362 newdir="$dir/${OBJD}64" 363 elif [ "$type" = sparcv9 ]; then 364 newdir="$dir/${OBJD}64" 365 else 366 newdir="$dir/${OBJD}32" 367 fi 368 mkdir -p "$root/$newdir" 369 [ "$VERBOSE" = "V" ] && echo "mv $file $newdir" 370 mv "$root/$file" "$root/$newdir" 371 done 372 } 373 374 # 375 # Copy a module, or create a link, as needed. 376 # 377 function copymod { 378 case $1 in 379 MOD) 380 targdir=$INSTALL_FILES/$4 381 tstmkdir $targdir 382 target=$targdir/$3 383 verbose "$INSTALL_CP $2/${OBJD}$5/$3 $target" 384 $INSTALL_CP $2/${OBJD}$5/$3 $target || \ 385 fail "can't create $target" 386 ;; 387 SYMLINK) 388 targdir=$INSTALL_FILES/$4 389 tstmkdir $targdir 390 target=$targdir/$5 391 rm -f $target 392 verbose "ln -s $3 $target" 393 ln -s $3 $target || fail "can't create $target" 394 ;; 395 LINK) 396 targdir=$INSTALL_FILES/$5 397 tstmkdir $targdir 398 target=$targdir/$6 399 rm -f $target 400 verbose "ln $INSTALL_FILES/$3/$4 $target" 401 ln $INSTALL_FILES/$3/$4 $target || fail "can't create $target" 402 ;; 403 CONF) 404 target=$INSTALL_FILES/$3 405 tstmkdir `dirname $target` 406 conffile=`basename $3` 407 verbose "$INSTALL_CP $4/$conffile $target" 408 $INSTALL_CP $4/$conffile $target 409 ;; 410 *) 411 fail "unrecognized modlist entry: $*" 412 ;; 413 esac 414 } 415 416 # Sanity-check the given module list. 417 function check_modlist { 418 nawk ' 419 BEGIN { 420 nfields["MOD"] = 6 421 nfields["CONF"] = 6 422 nfields["LINK"] = 7 423 nfields["SYMLINK"] = 7 424 } 425 { 426 # This also catches unknown tags. 427 if (nfields[$1] != NF) { 428 print "error: invalid modlist record:" 429 print $0 430 print "expected", nfields[$1], "fields, found", NF 431 status=1 432 } 433 } 434 END { 435 exit status 436 } 437 ' $1 || fail "Errors in kernel module list" 438 } 439 440 # 441 # Copy kernel modules to $INSTALL_DIR 442 # 443 444 function copy_kernel { 445 446 case $KARCH in 447 sun4*) ISA=sparc; MACH=sparc ;; 448 i86*) ISA=intel; MACH=i386 ;; 449 *) fail "${KARCH}: invalid kernel architecture";; 450 esac 451 export MACH 452 453 if [ "$GLOM" = "no" ]; then 454 verbose "Source = $UTS, ISA = $ISA, kernel = $KARCH" 455 else 456 verbose "Source = $UTS, ISA = $ISA, kernel = $KARCH, impl = $IMPL" 457 fi 458 459 test -d $KARCH || fail "${KARCH}: invalid kernel architecture" 460 test -d $ISA || fail "${ISA}: invalid instruction set architecture" 461 462 tstmkdir $INSTALL_FILES 463 rm -rf $modstatedir 464 tstmkdir $modstatedir 465 export MODSTATE=$modstatedir/state 466 467 # 468 # Figure out which "make" to use. dmake is faster than serial 469 # make, but dmake 7.3 has a bug that causes it to lose log 470 # output, which means the modlist might be incomplete. 471 # 472 make=dmake 473 dmvers=`$make -version` 474 if [ $? -ne 0 ]; then 475 make=/usr/ccs/bin/make 476 elif [[ $dmvers = *Distributed?Make?7.3* ]]; then 477 unset make 478 searchpath="/ws/onnv-tools/SUNWspro/SOS10/bin 479 /opt/SUNWspro/SOS10/bin 480 /opt/SUNWspro/bin" 481 for dmpath in $searchpath; do 482 verbose "Trying $dmpath/dmake" 483 if [ -x $dmpath/dmake ]; then 484 dmvers=`$dmpath/dmake -version` 485 if [[ $dmvers != *Distributed?Make?7.3* ]]; then 486 make="$dmpath/dmake" 487 break; 488 fi 489 fi 490 done 491 if [ -z $make ]; then 492 make=/usr/ccs/bin/make 493 echo "Warning: dmake 7.3 doesn't work with Install;" \ 494 "using $make" 495 fi 496 fi 497 498 # 499 # Get a list of all modules, configuration files, and links 500 # that we might want to install. 501 # 502 verbose "Building module list..." 503 (cd $KARCH; MAKEFLAGS=e $make -K $MODSTATE modlist.karch) | \ 504 egrep "^MOD|^CONF|^LINK|^SYMLINK" > $modlist 505 [ "$VERBOSE" = "V" ] && cat $modlist 506 check_modlist $modlist 507 if [ "$GLOM" = "yes" ]; then 508 fixglom $modlist $GLOMNAME 509 filtimpl $modlist $IMPL 510 fi 511 if [[ -n "$files" && "$files" != All ]]; then 512 filtmod $modlist "$files" 513 fi 514 515 # 516 # Copy modules and create links. For architectures with both 517 # 32- and 64-bit modules, we'll likely have duplicate 518 # configuration files, so do those after filtering out the 519 # duplicates. 520 # 521 verbose "Copying files to ${INSTALL_FILES}..." 522 523 # 524 # The IFS is reset to the newline character so we can buffer the 525 # output of grep without piping it directly to copymod, otherwise 526 # if fail() is called, then it will deadlock in fail()'s wait call 527 # 528 OIFS="$IFS" 529 IFS=" 530 " 531 set -- `grep -v "^CONF" $modlist`; 532 IFS="$OIFS" 533 for onemod in "$@"; do 534 copymod $onemod 535 done 536 537 OIFS="$IFS" 538 IFS=" 539 " 540 set -- `grep "^CONF" $modlist | sort | uniq`; 541 IFS="$OIFS" 542 for onemod in "$@"; do 543 copymod $onemod 544 done 545 546 # 547 # Add the glommed kernel name to the root archive 548 # 549 if [[ $GLOM == "yes" ]]; 550 then 551 filelist="$INSTALL_FILES/etc/boot/solaris/filelist.ramdisk" 552 mkdir -p `dirname $filelist` 553 echo "platform/$KARCH/$GLOMNAME" >$filelist 554 fi 555 556 STATE=1 # all kernel modules copied correctly 557 save_state 558 } 559 560 function kmdb_copy { 561 typeset src="$1" 562 typeset destdir="$2" 563 564 if [[ ! -d $dest ]] ; then 565 [[ "$VERBOSE" != "q" ]] && echo "mkdir -p $destdir" 566 567 mkdir -p $destdir || fail "failed to create $destdir" 568 fi 569 570 [[ "$VERBOSE" != "q" ]] && echo "cp $src $destdir" 571 572 cp $src $destdir || fail "failed to copy $src to $destdir" 573 } 574 575 function kmdb_copy_machkmods { 576 typeset modbase="$1" 577 typeset destdir="$2" 578 typeset dir= 579 typeset kmod= 580 581 [[ ! -d $modbase ]] && return 582 583 for dir in $(find $modbase -name kmod) ; do 584 set -- $(echo $dir |tr '/' ' ') 585 586 [[ $# -lt 2 ]] && fail "invalid mach kmod dir $dir" 587 588 shift $(($# - 2)) 589 kmod=$1 590 591 [[ ! -f $dir/$kmod ]] && continue 592 593 kmdb_copy $dir/$kmod $destdir 594 done 595 } 596 597 function kmdb_copy_karchkmods { 598 typeset modbase="$1" 599 typeset destdir="$2" 600 typeset bitdir="$3" 601 typeset dir= 602 typeset kmod= 603 typeset karch= 604 605 [[ ! -d $modbase ]] && return 606 607 for dir in $(find $modbase -name kmod) ; do 608 set -- $(echo $dir | tr '/' ' ') 609 610 [[ $# -lt 3 ]] && fail "invalid karch kmod dir $dir" 611 612 shift $(($# - 3)) 613 kmod=$1 614 bdir=$2 615 616 [[ $bdir != $bitdir ]] && continue 617 [[ ! -f $dir/$1 ]] && continue 618 619 kmdb_copy $dir/$kmod $destdir 620 done 621 } 622 623 function kmdb_copy_kmdbmod { 624 typeset kmdbpath="$1" 625 typeset destdir="$2" 626 627 [[ ! -f $kmdbpath ]] && return 1 628 629 kmdb_copy $kmdbpath $destdir 630 631 return 0 632 } 633 634 function copy_kmdb { 635 typeset kmdbtgtdir=$INSTALL_FILES/platform/$KARCH/$GLOMNAME/misc 636 typeset bitdirs= 637 typeset isadir= 638 typeset b64srcdir= 639 typeset b64tgtdir= 640 typeset b32srcdir= 641 typeset b32tgtdir= 642 typeset machdir= 643 typeset platdir= 644 645 if [[ $KMDB = "no" || ! -d $SRC/cmd/mdb ]] ; then 646 # The kmdb copy was suppressed or the workspace doesn't contain 647 # the mdb subtree. Either way, there's nothing to do. 648 STATE=2 649 save_state 650 return 651 fi 652 653 if [[ $(mach) = "i386" ]] ; then 654 isadir="intel" 655 b64srcdir="amd64" 656 b64tgtdir="amd64" 657 b32srcdir="ia32" 658 b32tgtdir="." 659 else 660 isadir="sparc" 661 b64srcdir="v9" 662 b64tgtdir="sparcv9" 663 b32srcdir="v7" 664 b32tgtdir="." 665 fi 666 667 typeset foundkmdb=no 668 typeset kmdbpath= 669 typeset destdir= 670 671 platdir=$INSTALL_FILES/platform/$KARCH/$GLOMNAME 672 if [[ $GLOM = "yes" ]] ; then 673 machdir=$platdir 674 else 675 machdir=$INSTALL_FILES/kernel 676 fi 677 678 srctrees=$SRC 679 if [[ $WANT64 = "yes" ]] ; then 680 # kmdbmod for sparc and x86 are built and installed 681 # in different places 682 if [[ $(mach) = "i386" ]] ; then 683 kmdbpath=$SRC/cmd/mdb/$isadir/$b64srcdir/kmdb/kmdbmod 684 destdir=$machdir/misc/$b64tgtdir 685 else 686 kmdbpath=$SRC/cmd/mdb/$KARCH/$b64srcdir/kmdb/kmdbmod 687 destdir=$platdir/misc/$b64tgtdir 688 fi 689 690 if kmdb_copy_kmdbmod $kmdbpath $destdir ; then 691 foundkmdb="yes" 692 693 for tree in $srctrees; do 694 kmdb_copy_machkmods \ 695 $tree/cmd/mdb/$isadir/$b64srcdir \ 696 $machdir/kmdb/$b64tgtdir 697 kmdb_copy_karchkmods $tree/cmd/mdb/$KARCH \ 698 $platdir/kmdb/$b64tgtdir $b64srcdir 699 done 700 fi 701 fi 702 703 if [[ $WANT32 = "yes" ]] ; then 704 kmdbpath=$SRC/cmd/mdb/$isadir/$b32srcdir/kmdb/kmdbmod 705 destdir=$machdir/misc/$b32tgtdir 706 707 if kmdb_copy_kmdbmod $kmdbpath $destdir ; then 708 foundkmdb="yes" 709 710 for tree in $srctrees; do 711 kmdb_copy_machkmods \ 712 $tree/cmd/mdb/$isadir/$b32srcdir \ 713 $machdir/kmdb/$b32tgtdir 714 kmdb_copy_karchkmods $tree/cmd/mdb/$KARCH \ 715 $platdir/kmdb/$b32tgtdir $b32srcdir 716 done 717 fi 718 fi 719 720 # A kmdb-less workspace isn't fatal, but it is potentially problematic, 721 # as the changes made to uts may have altered something upon which kmdb 722 # depends. We will therefore remind the user that they haven't built it 723 # yet. 724 if [[ $foundkmdb != "yes" ]] ; then 725 echo "WARNING: kmdb isn't built, and won't be included" 726 fi 727 728 STATE=2 729 save_state 730 return 731 } 732 733 # 734 # Make tarfile 735 # 736 737 function make_tarfile { 738 echo "Creating tarfile $TARFILE" 739 test -d $INSTALL_FILES || fail "Can't find $INSTALL_FILES" 740 cd $INSTALL_FILES 741 rm -f $TARFILE files 742 743 # We don't want to change the permissions or ownership of pre-existing 744 # directories on the target machine, so we're going to take care to 745 # avoid including directories in the tarfile. On extraction, tar won't 746 # modify pre-existing directories, and will create non-existent ones as 747 # the user doing the extraction. 748 find . ! -type d -print |fgrep -vx './files' >files 749 tar cf $TARFILE -I files || fail "Couldn't create tarfile $TARFILE" 750 STATE=3 751 } 752 753 # 754 # Routines to copy files to the target machine 755 # 756 757 function remote_fail { 758 fail "" "$1" "" \ 759 "Make sure that $TARGET_MACHINE is up." \ 760 "Check .rhosts in the home directory of user $TARGET_USER on $TARGET_MACHINE." \ 761 "Check /etc/hosts.equiv, /etc/passwd, and /etc/shadow." \ 762 "Change permissions on $TARGET_MACHINE as necessary." \ 763 "Then, use \"$INSTALL -R\" to resume the install." "" 764 } 765 766 function remote_install { 767 if [ "$IMODE" = "n" ]; then 768 STATE=4 769 return 0 770 fi 771 test -s $TARFILE || fail "$TARFILE missing or empty" 772 verbose "Installing system on $TARGET" 773 test -d $INSTALL_DIR || fail "Can't find $INSTALL_DIR" 774 cd $INSTALL_DIR 775 rm -f errors fatal nonfatal 776 if [ "$IMODE" = "T" ]; then 777 EMESG="Can't rcp to $TARGET" 778 touch errors 779 sh -e${SHV}c "$INSTALL_RCP $TARFILE $TARGET/Install.tar" 780 else 781 EMESG="Can't rsh to $TARGET_MACHINE" 782 rsh -l $TARGET_USER $TARGET_MACHINE \ 783 "(cd $TARGET_DIR; /usr/bin/tar x${V}f -)" \ 784 <$TARFILE 2>errors 785 fi 786 test $? -ne 0 && remote_fail "$EMESG" 787 cd $INSTALL_DIR 788 egrep "set time|warning|blocksize" errors >nonfatal 789 egrep -v "set time|warning|blocksize" errors >fatal 790 if [ -s fatal ]; then 791 echo "Fatal errors from rsh:" 792 cat fatal 793 remote_fail "Can't install on $TARGET_MACHINE" 794 fi 795 if [ -s nonfatal -a "$VERBOSE" != "q" ]; then 796 echo "Non-fatal errors from rsh:" 797 cat nonfatal 798 fi 799 rm -f fatal nonfatal errors 800 test "$IMODE" = "T" && echo "Files can be extracted on \ 801 $TARGET_MACHINE using 'tar xvf $TARGET_DIR/Install.tar'" 802 STATE=4 803 } 804 805 function okexit { 806 cd /tmp 807 test "$CLEANUP" = c && remove_dir $INSTALL_DIR 808 save_state 809 rm -rf $modstatedir 810 rm -f $modlist 811 [ -n "$cryptotree" ] && rm -rf "$cryptotree" 812 verbose "Install complete" 813 exit 0 814 } 815 816 # 817 # Process options 818 # 819 820 RCOPTS="" 821 LIBCREATE="no" 822 LIBSRC="" 823 ENV_PATH=$CODEMGR_WS 824 OBJD="debug" 825 KMDB="yes" 826 827 test -s $INSTALL_RC && RCOPTS=`cat $INSTALL_RC` 828 set $INSTALL $DEFAULT_OPTIONS $RCOPTS $* 829 shift 830 831 while getopts acd:D:G:hi:k:Kl:Lmno:pPqRs:t:T:uvVw:xX36 opt 832 do 833 case $opt in 834 w) ENV_PATH="$OPTARG"; SRC="$ENV_PATH/usr/src";; 835 s) UTS="$OPTARG";; 836 k) KARCH="$OPTARG";; 837 t|T) TARGET="$OPTARG"; IMODE=$opt; CLEANUP="c";; 838 n) TARGET=""; IMODE="n"; CLEANUP="p";; 839 u) files="unix genunix";; 840 m) files="Modules";; 841 a) files="All";; 842 v|V|q) VERBOSE=$opt;; 843 c|p) CLEANUP=$opt;; 844 L) LIBCREATE="yes"; CLEANUP="c";; 845 l) LIBSRC="$OPTARG";; 846 D) INSTALL_LIB="$OPTARG";; 847 d) INSTALL_DIR="$OPTARG/$TRAILER";; 848 G) GLOM=yes; GLOMNAME="$OPTARG";; 849 P|X|x) echo "-$opt is obsolete; ignored";; 850 h) usage "${INSTALL}: installs unix and modules";; 851 R) x=$OPTIND; restore_state; OPTIND=$x;; 852 i) IMPL="$OPTARG";; 853 o) OBJD="$OPTARG";; 854 K) KMDB="no";; 855 3) WANT64="no";; 856 6) WANT32="no";; 857 \?) usage "Illegal option";; 858 esac 859 done 860 shift `expr $OPTIND - 1` 861 862 ENV_NAME=`basename $ENV_PATH` 863 864 # 865 # The rest of the command line is a list of individual files to copy. 866 # If non-null, this list overrides the -uma options. 867 # 868 869 if [[ $# -gt 0 ]] ; then 870 files="$*" 871 KMDB="no" 872 fi 873 874 case "$VERBOSE" in 875 v) V="v"; SHV="x";; 876 V) V="v"; SHV="x"; set -x;; 877 q) V=""; SHV="";; 878 esac 879 880 # 881 # Create temp directory for Install's files 882 # 883 884 tstmkdir $INSTALL_DIR 885 886 TARFILE=$INSTALL_DIR/Install.${KARCH}.tar 887 INSTALL_FILES=$INSTALL_DIR/$KARCH 888 889 # 890 # Extract the target machine and target directory from a target of the 891 # form [user@]machine:/dir . 892 # 893 894 if [ "$IMODE" != "n" ]; then 895 eval `echo $TARGET | nawk -F':' '{ 896 if (NF != 2 || !length($1) || !length($2)) 897 print "usage \"Invalid target\"" 898 m = $1; d = $2 899 if ($1 ~ /@/) { 900 k = split($1, f, "@"); 901 if (k != 2 || !length(f[1]) || !length (f[2])) 902 print "usage \"Invalid target\"" 903 u = f[1]; m = f[2] 904 } 905 print "TARGET_USER=" u ";" 906 print "TARGET_MACHINE=" m ";" 907 print "TARGET_DIR=" d ";" 908 }'` 909 if [ -z "$TARGET_USER" ]; then 910 TARGET_USER=$LOGNAME 911 fi 912 fi 913 914 # 915 # Allow the use of library source or target for the install 916 # 917 918 if [ -n "$LIBSRC" ]; then 919 LIBSRC="`basename $LIBSRC .tar`.tar" 920 TARFILE=$INSTALL_LIB/$LIBSRC 921 test -s $TARFILE || fail "Can't find tarfile $TARFILE" 922 verbose "Installing from library tarfile $TARFILE" 923 STATE=3 924 elif [ "$LIBCREATE" = "yes" ]; then 925 tstmkdir $INSTALL_LIB 926 TARFILE="$INSTALL_LIB/${ENV_NAME}.${KARCH}.tar" 927 fi 928 929 # 930 # The next few lines allow recovery and activation with -R, 931 # and library installs with -l. 932 # 933 934 [[ $STATE -eq 1 ]] && copy_kmdb 935 [[ $STATE -eq 2 ]] && make_tarfile 936 [[ $STATE -eq 3 ]] && remote_install 937 [[ $STATE -eq 4 ]] && okexit 938 939 save_state 940 941 cd $DOT 942 DOTDOT=`cd ..; pwd` 943 944 # 945 # Try to be smart: if DOTDOT ends in uts, then infer UTS and KARCH from DOT 946 # Otherwise, if SRC is set, infer UTS = $SRC/uts. 947 # 948 949 if [ "`basename $DOTDOT`" = "uts" ]; then 950 UTS=$DOTDOT 951 KARCH=`basename $DOT` 952 if [ ! -n "$SRC" ]; then 953 SRC=`dirname $DOTDOT` 954 verbose "Setting SRC to $SRC" 955 fi 956 export SRC 957 fi 958 959 if [ -z "$UTS" -a -n "$SRC" ]; then 960 UTS="${SRC}/uts" 961 test -n "$KARCH" || fail "no karch specified (e.g. -k sun4u)" 962 fi 963 964 if [ "$LIBCREATE" = "yes" ]; then 965 TARFILE=$INSTALL_LIB/${ENV_NAME}.${KARCH}.tar 966 else 967 TARFILE=$INSTALL_DIR/Install.${KARCH}.tar 968 fi 969 INSTALL_FILES=$INSTALL_DIR/$KARCH 970 save_state 971 972 cd $DOT 973 test -z "$UTS" && fail 'Cannot find kernel sources -- $SRC not set' 974 test -d "$UTS" || fail "${UTS}: no such directory" 975 976 # 977 # Convert UTS into an absolute path. 978 # 979 980 cd $UTS 981 UTS=`pwd` 982 983 test "`basename $UTS`" = "uts" || \ 984 verbose "Warning: source path $UTS doesn't end in 'uts'" 985 986 remove_dir $INSTALL_DIR/$KARCH 987 rm -f $TARFILE 988 989 copy_kernel # sets STATE=1 if successful 990 copy_kmdb # sets STATE=2 if successful 991 make_tarfile # sets STATE=3 if successful 992 remote_install # sets STATE=4 if successful 993 994 okexit