1
0
Files
irix-657m-src/eoe/cmd/initpkg/restore_system-mr.sh
2022-09-29 17:59:04 +03:00

1034 lines
26 KiB
Bash

#!/bin/sh
sleep 5 # this is because sometimes we get re-invoked before shutdown
# really completes, so this holds off our first prompt...
# this script is the complement of the Backup script, for restoring
# system recovery tapes. The restore program that is the complement
# of dump is in /usr/etc, normally. This program should only
# exist in the miniroot. There is a much simpler version that
# is used for simply restoring backups, not recovering systems,
# that is installed as /etc/restore on the 'real' system.
#
NETIF=/etc/config/netif.options
HOSTS=/etc/hosts
# reset to null string if restoring from localhost tapedrive.
RSHCMD='rsh guest@$REM_HOST -n'
DEVNULL=/dev/null
# DEVNULL=/dev/console # for debugging
MTB=""
# standard su path from /etc/default/login
PATH=/usr/sbin:/usr/bsd:/sbin:/usr/bin:/etc:/usr/etc:/usr/bin/X11
export PATH
# run a shell, with interrupts enabled again, then disable on
# return; "knows" that it's only ever called when we do want
# interrupts disabled.
shell()
{
trap 2
stty sane intr '^c' echoe
csh <&5 >&6 2>&1
trap '' 2
}
# do a recovery run (as opposed to the label runs), and allow
# sigint to abort it.
do_a_tape()
{
while : #{
do
# now allow interrupts, so bru can be aborted
trap 'echo Interrupted; intrpt=1' 2
cd /root # extracted in "real root, with relative paths"
intrpt=0
# always rewind, just in case labelcmd leaves tape in strange place
mt -t $TAPE_PATH rewind
$extract_all
if [ "$intrpt" = 1 ]; then #{
while echo " Restore was interrupted, restart it ([y]es, [n]o [sh]): \c "
do read resp # {
case "$resp" {
y*|Y*)
break ;;
sh*)
shell ;;
n*|N*)
echo $1 restore will not be retried
break 2;
;;
}
done # }
else break;
fi #}
done # }
echo '\nRunning MAKEDEV in case devices have changed since backup \c'
(cd /root/dev; ./MAKEDEV > $DEVNULL)
echo '\n'
trap '' 2 # return with sigint ignored again
}
# shutdown the system. Can't use teleinit, because we are still in
# the middle of a level change. So we have to fake it ourselves.
# Otherwise we often simply hang, and user has to push reset button.
# argument is 1 or 0 for reboot or halt
shut_it_down()
{
sync
trap 2 # allow interrupts again, so if kernel config fails
# the can ^C and init will respawn us, if they notice
# errors from autoconfig and are quick.
if [ "$1" = 1 ]
then
echo "\n Recovery complete, restarting system."
# may need to reconfigure kernel; don't force it.
echo "Checking to see if kernel needs to be reconfigured"
/root/sbin/chroot /root /etc/init.d/autoconfig
else
echo "\n Recovery aborted, halting system."
fi
cd /
sleep 10
sync
umount -aTk efs,xfs -b /,/proc,/hw >$DEVNULL 2>&1
uadmin 2 $1
# make sure we shutdown; else we exit and might be restarted
# confusing the user, before the uadmin causes init to shut down.
sleep 30
echo '\07Shutdown failed!\07'
}
#########################################################################
# #
# Ask the user to insert the incremental tape, read the tape header, #
# #
#########################################################################
read_incremental_tape()
{
while : ; do #{
echo ""
echo " Insert the Incremental backup tape in the drive, then press \c"
echo "(<enter>, [q]uit (skip this tape)): \c"
read kstroke
case "$kstroke" {
"") ;;
sh*) shell
continue ;;
q*|Q*) return ;;
*) continue ;;
}
get_backup_type # get type on each tape; might be different
if $labelcmd; then continue; fi
echo " Do you want to proceed ([y]es, [r]etry, [q]uit): [y] \c"
read ans
case "$ans" {
""|y*|Y*)
break ;;
sh*)
shell
continue ;;
r*|R*)
continue ;;
q*|Q*)
shut_it_down 0 ;;
}
done #}
do_a_tape Incremental
}
#########################################################################
# #
# This function looks for the /tmp/volhdrlist file and to get the list #
# of the vol header contents and restores it from /stand. #
# #
#########################################################################
restore_volume_header()
{
cd /root
echo "Restoring the disk volume header."
if [ -s ./tmp/volhdrlist ] #{
then
cat ./tmp/volhdrlist | while read nm
do #{
if [ -s ./stand/$nm ]
then
dvhtool -v creat ./stand/$nm $nm
else
echo Volume header file "$nm" not found, so not restored to volume header.
fi
done #}
echo "Volume header restored."
fi #}
if [ -s ./tmp/vh_savedir ] #{
then
vhd="/root/`cat ./tmp/vh_savedir`"
if [ -d "$vhd" ] #{ restore files in vh not in /stand
then
(cd "$vhd"; for f in *; do
dvhtool -v c "$f" "$f"
done
)
fi #}
fi #}
}
#########################################################################
# #
# This function searches the head of the backup tape and sets the MTB #
# flag if the file /tmp/mtab is found and restores the file. #
# Also looks for lvtab, xlv, and mounts XLV vols #
# #
#########################################################################
look_for_mtab_file()
{
# the idea is to get only the files we want from bru, then kill
# it off. Otherwise it will go through the whole tape, and even
# prompt for additional tapes. This requires that bru line
# buffer output even when it is to a pipe.
# look at first 10 files/1MB only.
# run in subshell so the 'killed' message doesn't show up when
# tape command is killed
echo Extracting system configuration files ... \\c
$get_mtab_file > /tmp/.mtf
echo ''
if [ -s /tmp/.mtf ] #{
then
if [ -s /tmp/lvtab ]; then
echo "\n LV volumes are no longer supported in this release.";
echo " Please use lv_to_xlv(1) to convert to XLV volumes.\n";
fi
# check for prior existance of xlv volumes
if [ -s /tmp/xlv_vollist ]
then
echo "\nXLV volumes existed during original backup - machine name required."
# Taken from mrinitxlvrc.sh
# Mark the plex from which we booted up clean; mark the others stale.
normalroot=`devnm / | sed 's/. .*/0/'` # Jam '0' on end of swap device
xlv_set_primary $normalroot
rm -rf /dev/dsk/xlv > $DEVNULL 2>&1
rm -rf /dev/rdsk/xlv > $DEVNULL 2>&1
# use '/' for root since '/root' disk may be bad
xlv_assemble -Pq -h $machname > $DEVNULL 2>&1
# Make sure the configuration makes it out to disk
sync
# check if any xlv vols now exist
if [ -d /dev/dsk/xlv ]
then
ls /dev/dsk/xlv > /tmp/.xlv_list
else
cp /dev/null /tmp/.xlv_list
fi
# create an awk program file to compare xlv lists
echo 'BEGIN { i=0; j=0; fno=0;}\n{if (fno==0) if ($1=="SPLIT") fno=1; else a[i++]=$1; else b[j++]=$1;}\nEND {for (x=0; x<i; x++) {fnd=0; for (y=0; y<j; y++) if (a[x]==b[y]) {fnd=1; break;} if (fnd==0) print " XLV volume:", a[x], " missing";}}' > /tmp/.xlv_compare.awk
cat /tmp/xlv_vollist > /tmp/.xlv_derived
echo "SPLIT" >> /tmp/.xlv_derived
cat /tmp/.xlv_list >> /tmp/.xlv_derived
nawk -f /tmp/.xlv_compare.awk /tmp/.xlv_derived > /tmp/.xlv_result
rm -f /tmp/.xlv_derived /tmp/.xlv_list /tmp/.xlv_compare.awk
if [ -s /tmp/.xlv_result ]
then
#volumes missing, prompt user
echo "\n The following XLV volumes existed at the time this backup was created"
echo " which do not currently exist on your system:\n"
cat /tmp/.xlv_result
rm -f /tmp/.xlv_result
echo ""
echo " You may continue, enter the shell and recreate the volumes manually,"
echo " or exit from recovery.\n"
echo " Do you want to manually recreate the XLV volumes?"
echo " ([y]es, [s]kip, [sh]ell, [q]uit (from recovery)): [y] \c" ;
ans="`(read ans; echo $ans) < /dev/tty`" # don't read cat output
case "$ans" {
s|S)
echo "\n Skipping XLV restore...\n" ;;
""|y*|Y*|sh*)
echo "\nNOTE: The XLV configuration commands for the original XLV volume"
echo "configuration can be found in '/tmp/xlv_config_script'. If you have"
echo "replaced or moved disks since the last backup, do not use the file as is"
echo "since your new drive device names and partitions may be different.\n"
echo "Type 'exit' to return to System Recovery when you're done creating volumes.\n"
shell
echo "\nReturning to System Recovery...\n"
;;
q*|Q*)
shut_it_down 0 ;
return 1 ;;
*)
;;
}
fi
fi
cat /dev/null > /tmp/mtab_extra
typ=unknown # be paranoid
cat /tmp/mtab | while read dev dir typ rest
do #{
# used to eliminate /usr also, and recover was
# hardcoded to do it, but since some systems
# have / and /usr on the same partition, that
# was a bad idea...
if [ "$dir" != / ] #{
then
echo "$dev $dir "$typ"" >> /tmp/mtab_extra
fi #}
typ=unknown # be paranoid
done #}
if [ -s /tmp/mtab_extra ] #{
then
MTB="EXTRA"
else #}{
MTB="BASIC"
fi #}
else #}{
MTB=""
fi #}
echo $MTB > /tmp/.mtb
rm /tmp/mtab /tmp/.mtf > $DEVNULL 2>&1
}
LABEL_ERR='\n *** ERROR ***
Unable to read the recovery tape, check
tape device name and format.\n'
# get label from a bru tape
brulabel()
{
TAPE_LABEL=/tmp/.label # where we put the extracted tape label
bru -g -f $TAPE_PATH > $TAPE_LABEL 2>&1
if [ $? -ne 0 ] #{
then
echo "$LABEL_ERR"
return 0
fi #}
cat $TAPE_LABEL
return 1;
}
# get label from a tar tape.
# since tar has no real labels, we simply fake this one.
# if it's written in the "sgi system backup format", it
# has such a label, otherwise we fake it.
# basicly, we assume the first file is small, and extract it.
# of course, unlike bru, we have it only on the first tape
# in a backup, normally...
tarlabel()
{
eval $RSH dd if=$TAPE bs=1024k count=1 > /tmp/.$$L 2>$DEVNULL
file="`tar eRtf /tmp/.$$L 2>&1 | sed -n 1p`"
case "$file" {
*tmp/.info_*) # a label
finfo="`tar Rxvf /tmp/.$$L $file 2>&1 | sed -n 1p`"
if [ ! -f "$file" ] #{
then
echo "$LABEL_ERR"
return 0
fi #}
cat "$file"
;;
}
return 1;
}
# get label from a cpio tape.
cpiolabel()
{
file="`cpio -ti -I $1 2>&1 | sed -n 1p`"
if [ $? -ne 0 ] #{
then
echo "Error trying to read label file"
return 0
fi #}
# get the label file; first file on tape
(cd /; cpio -i -I $1 $file >/dev/null 2>&1; if [ -f "$file" ];
then cat $file; rm -f $file; fi)
return 1;
}
# get the stashed mtab file from the backup; it is assumed to be
# in the first few files on archive. The dd keeps us from going
# all the way through the tape (not as much of a problem as with thar)
# also stop after first 15, just to be paranoid (avoid running out
# of disk space)
bru_get_mtab()
{
x 4k of 436k [1] tmp/.ip.fragmatches.cache
(cd /; eval $RSH dd if=$TAPE bs=1024k count=1 2>$DEVNULL | bru -jxvf - 2>&1 |
(cnt=0 tabf=1; while read x sz of tot links name
do
case "$file" {
# could be full, which drops /, or ./, which doesn't with bru
*tmp/mtab|*tmp/lvtab|*tmp/vh_savedir|*tmp/xlv_vollist|*tmp/xlv_config_script)
tabf=0
echo $file
;;
}
cnt=`expr $cnt + 1`
if [ $cnt -gt 15 ]
then killall bru; exit $tabf
fi
done
exit $tabf
)
)
}
# get the stashed mtab file from the backup; it is assumed to be
# in the first few files on archive. The dd keeps us from going
# all the way through the tape looking for any later copies...
# also stop after first 15, just to be paranoid (avoid running out
# of disk space)
tar_get_mtab()
{
(cd /; eval $RSH dd if=$TAPE bs=1024k count=1 2>$DEVNULL | tar -BRvxf - 2>&1 |
(cnt=0 tabf=1; IFS=",$IFS" ; while read x file rest
do
case "$file" {
tmp/mtab|tmp/lvtab|tmp/vh_savedir|tmp/xlv_vollist|tmp/xlv_config_script)
tabf=0
echo $file
;;
}
cnt=`expr $cnt + 1`
if [ $cnt -gt 15 ]
then killall tar; exit $tabf
fi
done
exit $tabf
)
)
}
cpio_get_mtab()
{
(cd /; eval $RSH dd if=$TAPE bs=256k count=1 2>$DEVNULL | cpio -idmuvk 2>&1 |
(cnt=0 tabf=1; IFS=",$IFS" ; while read file rest
do
case "$file" {
tmp/mtab|tmp/lvtab|tmp/vh_savedir|tmp/xlv_vollist|tmp/xlv_config_script)
tabf=0
echo $file
;;
}
cnt=`expr $cnt + 1`
if [ $cnt -gt 15 ]
then killall cpio; exit $tabf
fi
done
exit $tabf
)
)
}
######
#
# Determine type of backup tape (bru, tar, xfsdump, cpio)
# and set commands to be used in the rest of the script.
# the rest
# xfsdump and cpio aren't yet really working for anything but "extra" tapes
#
######
get_backup_type()
{
eval $RSH dd if=$TAPE bs=256k count=1 > /tmp/$$type 2>$DEVNULL
LANG=C ttype="`file /tmp/$$type`"
case "$ttype" {
*xfsdump*) echo Backup is an xfsdump archive
echo Only supported for additional tapes, not recovery tape
labelcmd=
# only supported for incrementals or extra tapes, not primary
# this only really works for the first tape
extract_all="xfsrestore -v verbose -r -f $TAPE_PATH /root"
get_mtab_file=
;;
*cpio*) echo Backup is a cpio archive
labelcmd="cpiolabel /tmp/$$type"
# no relative pathname option, so so this is a bit of an issue...
# only supported for incrementals or extra tapes, not primary
extract_all="cpio -idmuvk -I $TAPE_PATH"
get_mtab_file=cpio_get_mtab
;;
*bru*) echo Backup is a bru archive
labelcmd=brulabel
extract_all="bru -xvj -ur -f $TAPE_PATH"
get_mtab_file=bru_get_mtab
;;
*tar*) echo Backup is a tar archive
labelcmd=tarlabel
extract_all="tar -xvRf $TAPE_PATH"
get_mtab_file=tar_get_mtab
;;
*) echo Unable to determine backup type, assuming tar
labelcmd=tarlabel
extract_all="tar -xvRf $TAPE_PATH"
get_mtab_file=tar_get_mtab
;;
}
}
#########################################################################
# #
# Ask the user to insert the first tape, read the tape header, #
# do some error checking, read the /tmp/mtab file off #
# the tape and set flag MTB if anything other than / and /usr #
# needs to be mounted. #
# #
#########################################################################
read_full_backup_header()
{
while : ; do #{
echo ""
echo " Insert the first Backup tape in the drive, then"
echo " press (<enter>, [q]uit (from recovery), [r]estart): \c"
read kstroke
case "$kstroke" {
"") ;;
r*|R*) echo ; return 1;;
sh*) shell
continue ;;
q*|Q*) shut_it_down 0 ;
break ;;
*) continue ;;
}
get_backup_type
if $labelcmd; then continue; fi
echo " Do you want to proceed ([y]es, [r]etry, [q]uit): [y] \c"
read ans
case "$ans" {
""|y*|Y*)
break ;;
sh*)
shell
continue ;;
r*|R*)
continue ;;
q*|Q*)
shut_it_down 0 ;;
}
done #}
look_for_mtab_file
#### At this point the MTB flag specifies the existance of valid mtab
#### file on tape.
return 0
}
# do minimal network setup for just ourselves; we needed
# some of this for some code I removed, but it's actually useful
# to have hostname return the right thing in some places, and will
# make it easier on customer if they shell out. It's cleaner to do
# this up front.
# There is no point in checking /root/etc/sys_id,
# because /root is never mounted at this point...
setup_minimal_net()
{
while : ; do #{
echo ""
# use ours as default if known, but allow to change in case of typos
myname=`hostname` 2>$DEVNULL
echo " Please enter your hostname (system name) \c"
if [ "$myname" ]; then echo "[$myname]\c"; fi
echo : \\c
read host
if [ -z "$host" ] #{
then
if [ "$myname" ]
then MY_NAM=$myname; break
else continue
fi
else #}{
MY_NAM=$host
break
fi #}
done #}
# set up IP addresses, etc. for all interfaces (usually just one)
# always write name and interface into NETIF, because
# hinv order may not match order (probaby won't) that
# network script uses to determine primary interface
# for the purposes of this program, it doesn't matter
# which is called host, and which is called gate-host,
# etc., as long as the correct IP address gets configured
# to the correct interface.
# Always ask for all network interfaces. Could try to
# check if already configured (in case a restart), but
# one of the reasons for restarting is that you answered
# a question about a host address incorrectly!
# same argument goes for re-creating netif every time
# if more than 2 interfaces; ln /unix so if user does
# a shell escape, netstat, etc. will work.
rm -f $NETIF
# move old host file aside, and then append, because
# first match wins, and we might have been through
# this code more than once on restarts, etc.
if [ -r $HOSTS ]; then mv $HOSTS ${HOSTS}-; fi
# need localhost for later use
echo '127.1\tlocalhost' > $HOSTS
# IFS diddling is to make parsing easier.
hinv -c network | (
IFS=":," gate=0
while read name interface junk; do
case "$name" {
*ISDN*) continue ;; # we never use isdn in miniroot; won't work; no driver
}
# strip spaces left in by IFS changes
interface=`echo $interface|sed 's/[ ]//g'`
if [ $gate -eq 0 ] #{
then hname=$MY_NAM gate=1
elif [ $gate -eq 1 ]
then hname=gate-$MY_NAM gate=2
else
hname=gate$gate-$MY_NAM
gate=`expr $gate + 1`
fi #}
echo if${gate}name=$interface >> $NETIF
echo if${gate}addr=$hname >> $NETIF
ipa=
guessipa="`nvram netaddr 2>$DEVNULL`"
while [ -z "$ipa" ]; do # in case they hit CR
echo " Please enter the IP address for $MY_NAM's"
echo " $name interface ($interface): $guessipa\c"
ipa="`(read ipa; echo $ipa) < /dev/tty`" # don't read hinv output
if [ -z "$ipa" ]; then ipa="$guessipa"; fi
done
echo "$ipa\t$hname" >> $HOSTS
done )
echo Starting networking with primary hostname $MY_NAM
echo $MY_NAM > /etc/sys_id
hostname $MY_NAM
chkconfig -f network on
/etc/init.d/network start
}
# get the name of the tape device to use.
get_tape_name()
{
####### Get the tape device, if remote, start networking after setting
####### up the hosts file, hostname and hostid.
#
set $@ `gettapedev`
REM_HOST=$1 TAPE=$2
if [ "$REM_HOST" = NULL ]; then REM_HOST=localhost RSH=;
else RSH="$RSHCMD"; fi
while :; do #{
resp=n
if [ "$TAPE" != NULL ]
then
if [ "$REM_HOST" != "localhost" ] || mt -t "$TAPE" exist
then
echo "Restore will be from $TAPE\c"
if [ "$REM_HOST" != "localhost" ]
# hostname may be long enough to overflow line
then echo " on remote host $REM_HOST.\n \c"
fi
echo " OK? ([y]es, [n]o): [y] \c"
read resp
fi
fi
case "$resp" {
"")
break;
;;
y|Y*)
break
;;
sh*)
shell
;;
n*|N*)
while :
do
echo "Remote or local restore ([r]emote, [l]ocal):\c"
if [ "$REM_HOST" != "localhost" ]
then
echo " [r] \c"
rlr=r
else
echo " [l] \c"
rlr=l
fi
read resp
if [ "$resp" = "" ]
then
resp=$rlr
fi
case "$resp" {
r*|R*)
echo "Enter the name of the remote system: \c"
if [ "$REM_HOST" != "localhost" ]
then
echo "[$REM_HOST] \c"
fi
read resp
if [ "$resp" = "sh" ]
then
shell
continue
fi
if [ "$resp" != "" ]
then
REM_HOST=$resp RSH="$RSHCMD"
fi
if [ "$REM_HOST" = "localhost" ]
then
RSH=
continue;
fi
;;
l*|L*)
REM_HOST=localhost RSH=
;;
sh*)
shell
continue
;;
}
if [ "$REM_HOST" != "localhost" ]
then
echo "Enter the name of the tape device on $REM_HOST: \c"
else
echo "Enter the name of the tape device: \c"
fi
if [ "$TAPE" != "NULL" ]
then
echo "[$TAPE] \c"
fi
read resp
if [ "$resp" = "sh" ]
then
shell
continue
fi
if [ "$resp" != "" ]
then
TAPE=$resp
fi
if [ "$REM_HOST" = "localhost" ]
then
if mt -t $TAPE exist
then
:
else
echo "Tape drive $TAPE is not available."
return 1
fi
fi
break
done
;;
}
done #}
if [ "$REM_HOST" != "localhost" ] #{
then
while : ; do #{
echo ""
echo " Please enter the IP address of "$REM_HOST" : \c"
read ipa
if [ "$ipa" = "" ] #{
then
continue
else #}{
REM_IPADDR=$ipa
break
fi #}
done #}
echo "$REM_IPADDR\t$REM_HOST" >> $HOSTS
if [ -r ${HOSTS}- ]
then cat ${HOSTS}- >> $HOSTS && rm -f ${HOSTS}-
fi
TAPE_PATH=guest@$REM_HOST:$TAPE
echo "Checking tape drive $TAPE on remote host $REM_HOST \c"
else #}{
TAPE_PATH=$TAPE
echo "Checking tape drive local tape drive $TAPE \c"
fi #}
if mt -t $TAPE_PATH exist
then :
else
echo "\nTape drive $TAPE is not available."
return 1
fi
echo "\nInformation for device $TAPE_PATH is: "
mt -t $TAPE_PATH status 2>&1 | grep -v Status:
return 0
} # end of get_tape_name
helperase()
{
echo ""
echo "If you would like to erase your disk(s) and start"
echo "with empty filesystem(s), then answer yes when prompted."
echo ""
echo "If you answer yes, you will be prompted to confirm for"
echo "each filesystem individually before it is erased."
echo ""
echo "If you answer no, then your filesystems will be checked"
echo "and mounted in their current state if possible."
echo "For any filesystems that are damaged beyond recovery,"
echo "you will be prompted for each damaged filesystem,"
echo "asking if you want to erase it."
echo ""
echo "You can answer with \"sh\" if you want to escape to the shell"
echo "to examine and salvage the data yourself."
echo ""
echo "Modifications made to files after the backup tape"
echo "was created will be overwritten by the restore."
echo ""
}
# ask if they want to create the filesystems.
do_filesystems()
{
while : ; do #{
echo ""
helperase
echo "Erase all old filesystems and make new ones ([y]es, [n]o, [sh]): [n] \c "
read answer
case "$answer" {
n*|N*|'') echo ""
if [ "$MTB" = EXTRA ] #{
then
recover -f /tmp/mtab_extra
else
recover
fi #}
if [ $? -ne 0 ]
then
echo Filesystem check and/or mount failed
continue
fi
echo ""
break ;;
y*|Y*) echo "" ;
umount -aT efs,xfs -b / >$DEVNULL 2>&1
if [ "$MTB" = "EXTRA" ] #{
then
recover -m -f /tmp/mtab_extra
else
recover -m
fi #}
if [ $? -ne 0 ] ; then
echo Filesystem check and/or mount failed
continue
fi
echo "" ;
break ;;
sh*) shell
continue ;;
q*|Q*) echo Recovery aborted, shutting down
shut_it_down 0 ;
break ;;
h*|H*) helperase ;;
*) echo Type \"help\" for more information. ;;
}
done #}
dusage="`df | grep -v '/$'`"
case "$dusage" {
"") echo "Warning: no filesystems appear to be mounted; restore will likely fail" ;;
*) echo "\nStarting recovery with these filesystems mounted (where /root is your"
echo "normal / directory).\n"
echo "$dusage" ;;
}
}
restore_incremental()
{
while : ; do #{
echo ""
echo " Do you have incremental backup tapes to restore ([y]es, [n]o (none)): [n] \c "
read resp
case "$resp" {
y*|Y*)
echo "" ;
read_incremental_tape ;
continue ;;
sh*)
shell
continue ;;
""|*)
break ;;
}
done #}
}
restore_quotas()
{
if [ -s tmp/quotatab ]
then
echo "Restoring quotas."
cd /
cp tmp/quotatab /root/var/tmp/restore_quotas
umount /root
mount -o quotas `devnm / | sed 's/. .*/0/'` /root
fi
}
#########################################################################
# #
# #
################ START OF THE MAIN SCRIPT #########################
# #
# #
#########################################################################
# {
trap '' 2 # ignore int for most of script
stty sane intr '^c' echoe
echo ""
echo ""
echo " ************************************************************"
echo " * *"
echo " * CRASH RECOVERY *"
echo " * *"
echo " ************************************************************"
echo ""
echo ""
echo "You may type sh to get a shell prompt at most questions"
# Grab input for later shell escapes, in scripts and subscripts
# that have to read from stdin for various reasons.
# similarly for stdout. Used in shell(), mainly, to be
# sure we get good stdin and out.
exec 5<&0
exec 6>&1
####### Ask the user to insert the first tape, read the tape header,
####### do all kinds of error checking, read the /tmp/mtab file off
####### the tape and set flag MTB if anything other than / and /usr
####### needs to be mounted. call function -- read_full_backup_header --
#
cd / # be paranoid
setup_minimal_net # do minimal setup for at least local networking
# if remote tape, we'll do more below.
while :
do
echo '\nChecking for tape devices'
if get_tape_name
then
if read_full_backup_header; then break; fi
fi
done
#
#######
#
MTB="`cat /tmp/.mtb`"
if [ "$MTB" = "" ] #{
then
while : ; do #{
echo ""
echo " Could not find the /tmp/mtab file on tape. Only the /"
echo " and /usr filesystems will be mounted and restored"
echo " unless you 'sh' and mkfs and mount others yourself."
echo " Do you want to proceed with recovery ([y]es, [q]uit (from recovery)): [y]\c "
read resp
case "$resp" {
y*|Y*|"")
break ;;
sh*)
shell
continue ;;
q*|Q*)
shut_it_down 0
break ;;
}
done #}
fi #}
while : ; do # {
do_filesystems
while : ; do # { # reloop on question if sh
echo "Is this the correct list of filesystems and sizes?"
echo "If not, answer no, to be asked again if you want to"
echo "erase and mount all filesystems. ([y]es, [n]o, [sh]): [y] \c"
read resp
case "$resp" {
""|y*|Y*) break 2;;
sh*) shell;;
n*|N*|"") break;;
}
done #}
done #}
while : ; do # {
do_a_tape Full
restore_volume_header
restore_incremental
restore_quotas
cd /
while : ; do # { # loop on question if sh or invalid reply
echo "Reboot, start over, or read first tape again? ([r]eboot, [s]tart, [f]irst) [r] \c"
read resp
case "$resp" {
r*|R*|"") break 2;;
sh*) shell;;
s*) exit 0;; # let init re-exec us
f*|F*) break;;
}
done #}
done #}
# remove INST from OSLoadOptions nvram variable
oval="`nvram OSLoadOptions`"
case "$oval" {
INST*) oval="inst${oval#INST}"
nvram OSLoadOptions "$oval" ;;
}
shut_it_down 1
# } end of MAIN