#!/usr/bin/ksh # (c)Copyright 1998 Hewlett-Packard Co., All Rights Reserved. # $Header: /ignite/cold_fusion/src/scripts/copy_boot_tape 10.4 1998/04/22 21:26:33 hmgr Exp $ # @(#) copy_boot_tape $Revision: 10.4 $ ######################################################################## # This command takes the two sections off of a boot install tape # and puts the boot section in a regular file, and extracts the system # archive via dd (or pax on multi-volume tapes) to the tmp_dir. Then the # command can be used to put them back to another tape. # # The boot area requires 32MB and the system archive depends on the # amount of inclusion done for make_recovery (typical minimum is # 400MB). So to duplicate a tape you will need approximately 450MB # of free diskspace if you aren't doing tape-to-tape copy. # # If two tape drives are available on the same machine you can do a # tape-to-tape copy by combining the -u and -p options on the same line. # ######################################################################## ############## # usage() # # called from: MAIN # checkopts () # checkandsetup() usage (){ typeset cmd=$1 usagexit=1 print "usage: $cmd [-u|-p] no_rewind_tape_device [-d] tmp_dir [-abmr] -u unpack a make_recovery tape onto disk, or to another tape if used with the -p option and a second tape device. -p put make_recovery components previously extracted, onto tape. (may be combined with -u to do tape-to-tape copy if multiple tape drives are available.) -d directory to unpack make_recovery tape to. (not needed if doing tape-to-tape copy) -a only extract the system archive from the tape. (-u) only write the archive to tape (tape will not be bootable). (-p) -b only extract the bootlif from the tape. (-u) only write the bootlif to tape (tape will be bootable w/o software to install ) (-p) -m indicates that the boot tape is the first of a multiple tape recovery kit. (tape-to-tape copy not allowed for multi-tape kits.) -r overwrite the system archive on a boot tape with the contents of the tmp_dir." print "unpack example: $cmd -u /dev/rmt/c0t0d0DDS1n -d /extra_space" exit 1 } # end usage() ############## # checkopts() # check for illegal option combinations # called from: MAIN # checkopts () { if (( partial != 0 ));then print "\nERROR: Options a, b, and r cannot be used together.\n" usage ${1} fi } # end checkopts() ############## # skipboot() # skip over the the first logical tape that contains the boot section. # # called from: unpacktape() # packagetape() # skipboot() { typeset tapedev=$1 print "Skipping boot section of tape ${tapedev}." mt -t ${tapedev} fsf 1 } # end skipboot() ############## # tapetest() # test that device exists, is no_rewind, and has a tape. # also rewinds the tape. # # called from: checkandsetup() # tapetest() { typeset tapedev=$1 # check that it exists and is a character device # if [[ ! -c ${tapedev} ]]; then print "ERROR: ${tapedev} not found or not a character device." usagexit=1 exit 1 fi # check that it is a no rewind device # if (( $(echo ${tapedev}|awk '{if($0 !~ /n$|nb$/) print 1;else print 0}') == 1 )) then print "ERROR: ${tapedev} not a no_rewind device. Try ${tapedev}n or ${tapedev}nb." exit 1 fi print "Rewinding tape ${tapedev}." mt -t ${tapedev} rew if (( $? == 1 )) ; then print "Make sure there is a tape in ${tapedev}." usagexit=1 exit 1 fi } # end tapetest() ############## # dderror() # print some helpfull information if 'dd' fails # # called from: unpacktape() # packagetape() # dderror() { print "Tape may be write protected." usagexit=1 exit 1 } # end dderror() ############## # unpacktape() # extract one or both parts of the make_recovery tape to # either a temporary disk location or directly to another tape. # # 'partial' indicates if one or both of the tape sections are to be extracted # partial=0 both bootarea and system archive # partial=1 bootarea only # partial=2 system archive only # # called from: tapeaction # unpacktape() { # extract the boot area # if (( partial == 1 || partial == 0 )); then print "Extracting the boot area to ${bootimage}." dd if=${utdev} of=${bootimage} bs=2k (( $? > 0 )) && dderror #list the contents of the lif to check for corruption # if (( ! tape2tape )) ; then print "Boot file contents." lifls -l ${bootimage} if (( $? > 0 )) ; then print "ERROR: lif image corrupted. Tape heads may need cleaning." exit 1 fi fi fi # extract the system archive # if (( partial == 2 || partial == 0 )); then (( partial == 2 )) && skipboot ${utdev} print "Extracting the system archive to ${systemimage}." if (( ! multitape )) then dd if=${utdev} bs=10k of=${sysimage} (( $? > 0 )) && dderror else mkdir -p ${sysimage} cd ${sysimage} pax -pe -rf ${utdev} fi fi # if this isn't a tape2tape operation then ask if you # want to immediately write the extracted stuff to a new tape # or exit and examine the extracted parts. # if ((! tape2tape));then print "\nRewinding and ejecting $utdev." mt -t $utdev offline print "\n" read ans?"[C]opy to new tape or [E]xit: " if [[ $ans = [cC] ]];then read ans?"Put blank tape in $utdev, [Enter] when tape is ready." ptdev=$utdev packagetape else upack=0 # prevents trying to eject tape twice fi fi } # end unpacktape() ############## # packagetape() # Write one or both extracted make_recovery parts to another tape. # partial=0 both bootarea and system archive # partial=1 bootarea only and no recovery archive # partial=2 system archive only and not bootable # partial=3 system archive only and preserve bootarea # # called from: tapeaction() # unpacktape() # packagetape() { # put the boot area down # if (( partial == 1 || partial == 0 )); then print "Putting the boot area on tape." dd if=${bootimage} of=${ptdev} bs=2k (( $? > 0 )) && dderror fi # put the system archive down # if (( partial == 2 || partial == 0 || partial == 3 )); then (( partial == 3 )) && skipboot ${ptdev} print "Putting the system archive on tape." if (( ! multitape )) then dd if=${sysimage} of=${ptdev} bs=10k (( $? > 0 )) && dderror else cd ${sysimage} pax -twf ${ptdev} . fi fi } # end packagetape() ############## # checkandsetup() # Check that the tape devices and temporary directory are OK # and that enough command line info has been given. # # called from: MAIN # checkandsetup(){ typeset cmd=$1 typeset argno=$2 # check for enough command line arguments (( $argno < 4 )) && usage ${cmd##*/} # if both -u and -p options used, check if the device file # given is the same for both, if so convert back to just -u case. # if dev files are different then this is a tape2tape operation. # if (( upack && pack )) ;then if [[ $utdev = $ptdev ]]; then pack=0 else tdir=/dev/null tape2tape=1 fi fi # because we have to use pax for multitape recovery kits, and # pax won't write tape2tape we can't get there from here # if (( tape2tape && multitape )) ;then print "ERROR: Cannot do tape-to-tape copy of multi-tape make_recovery kit." exit 1 fi # check that we have a tape device to work with # if [[ $ptdev = "" && $utdev = "" ]];then print "ERROR: Need to specify -u, -p or both.\n" usage ${cmd##*/} fi # # if this isn't a tape2tape operation then a temp dir is # required. # if [[ $tdir = "" && $tape2tape = 0 ]];then usage ${cmd##*/} fi # validate tape devices # (( upack )) && tapetest $utdev (( pack )) && tapetest $ptdev # make sure tdir is something we can write to. # allow tdir to be /dev/null for testing. # if [[ ! -d $tdir && ! -c $tdir ]]; then print "$tdir not found or not a directory." exit 1 fi if (( tape2tape )); then bootimage="${ptdev}" sysimage="${ptdev}" else bootimage="${tdir}/bootimage" sysimage="${tdir}/systemimage" fi } # end checkandsetup() ############## # tapeaction() # Unpackage tape, package tape or both. # If a tape2tape copy is asked for (-u and -p given on cmd line) # then unpacktape will do both the extract and call packagetape # to make the copy. # # called from: MAIN # tapeaction() { (( upack )) && unpacktape # If -p on the command line and no -u then assume there are images # in the tdir to put on to tape. # (( pack && ! tape2tape )) && packagetape } # end tapeaction() ############## # actiondone() # We're done, rewind and eject tapes. # If the same device used for unpack and pack don't try eject twice. # If exitting from the usage function don't try to rewind anything. # # called from: trap on exit # actiondone() { typeset -i samedev=0 [[ $ptdev = $utdev ]] && samedev=1 (( ! usagexit )) && ( print "Rewinding and ejecting tape(s)." (( pack )) && mt -t ${ptdev} offline (( upack && ! samedev )) && mt -t ${utdev} offline ) } # end actiondone() ######################### MAIN ############################### typeset -i upack=0 pack=0 partial=0 tape2tape=0 multitape=0 typeset -i usagexit=0 typeset tdir ptdev utdev bootimage sysimage opt trap actiondone EXIT 1 2 3 15 while getopts :u:p:d:abmr opt do case $opt in a) # extract/replace system archive only checkopts ${0##*/} partial=2 ;; b) # extract/replace bootlif only checkopts ${0##*/} partial=1 ;; d) # temp dir tdir=$OPTARG ;; p) # put to tape pack=1 ptdev=${OPTARG} ;; m) # multiple tapes so use pax instead of dd for system archive multitape=1 ;; r) # replace archive on a boot tape and preserve bootlif checkopts ${0##*/} partial=3 ;; u) # extract from tape upack=1 utdev=${OPTARG} ;; *) usage ${0##*/} ;; esac done #check supplied args and such # checkandsetup $0 $# #perform requested tape actions # tapeaction #cleanup and leave # # actiondone() called on exit via trap exit 0