Newsgroups: comp.sources.unix
From: rca@ingres.com (Bob Arnold)
Subject: v28i069: saenv_alldisks - sysadmin env, disk management and backups, Part05/06
References: <1.771948808.8446@gw.home.vix.com>
Sender: unix-sources-moderator@gw.home.vix.com
Approved: vixie@gw.home.vix.com
Submitted-By: rca@ingres.com (Bob Arnold)
Posting-Number: Volume 28, Issue 69
Archive-Name: saenv_alldisks/part05
#!/bin/sh
# this is saenv_alld.05 (part 5 of saenv_alld)
# do not concatenate these parts, unpack them in order with /bin/sh
# file src/backup/backup continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 5; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping src/backup/backup'
else
echo 'x - continuing file src/backup/backup'
sed 's/^X//' << 'SHAR_EOF' >> 'src/backup/backup' &&
X ;;
X noauto)
X autoverify=false
X autoarg=$1
X ;;
X nocheck)
X check=false
X ;;
X nofitguess)
X fitguess=false
X ;;
X nojoke)
X joke=false
X ;;
X nolabelq)
X labelq=false
X ;;
X nomail)
X mail=false
X mailarg=nomail
X ;;
X nooffline)
X offline=false
X ;;
X noprobq)
X probq=false
X ;;
X noupdate)
X update=false
X ;;
X notcont)
X cont2next=false
X ;;
X showdd)
X showdd=true
X BDDSHOW=true
X export BDDSHOW
X showddarg=$1
X ;;
X skip)
X shift
X fileskip="$1"
X getmode=knownskip
X labelq=false
X ;;
X target)
X shift
X target="$1"
X targetarg=true
X ;;
X verifytoo|verify2)
X verifytoo=true
X ;;
X [0-9]|[12][0-9])
X extravol=$1
X nvol=`expr $extravol + 1`
X n=$extravol
X while test $n -gt 0 ; do
X case "$2" in
X /*|unknown)
X shift
X firstfslist="$firstfslist $1"
X case "$2" in
X cont*)
X shift
X # use "cont" as canonical spelling
X firstfslist="$firstfslist cont"
X ;;
X esac
X n=`expr $n - 1`
X ;;
X *)
X break
X ;;
X esac
X done
X ;;
X [01][0-9][0123][0-9].*[a-z])
X parent=$1
X offline=false
X joke=false
X labelq=false
X ;;
X *)
X echo "$pr: Option '$1' not understood. Quitting."
X echo "$USAGE"
X exit 1
X ;;
X esac
X shift
Xdone
X# pass these args to any child backup processes, for example:
X# when a backup does a "verifytoo"
X# when a "verify alldisks" does a "verify onedisk"
Xchildargs="$cpioarg $showddarg $autoarg $mailarg"
X
X## make sure we know who is doing this backup ('cron' option sets $OPER to
X## cron, otherwise we hope to get it from our environment)
Xfor f in $oplist $oplistloc ; do
X test -f $f && opfiles="$opfiles $f"
Xdone
Xwhile test "$OPER" = "" -o "$OPER" = '??' -o -z "`egrep '^'$OPER'[ ]|^'$OPER'$' $opfiles`" ; do
X echo "$pr: I don't know who you are."
X echo $epre "$pr: Please enter your initials: "$esuf
X eval "$READ" OPER
X # break out of here if we know who $OPER is
X egrep "^$OPER[ ]|^$OPER\$" $opfiles > /dev/null && break
X # otherwise try to find out
X while : ; do
X echo "$pr: I don't know who '$OPER' is."
X echo $epre "$pr: Do you wish to be added as a backup operator? [yn] "$esuf
X eval "$READ" ans
X case $ans in
X [nN]*)
X break 2
X ;;
X [yY]*)
X echo $epre "$pr: Enter your login name: "$esuf
X eval "$READ" login
X case $login in
X *' '*|[A-Z0-9]*)
X echo "$pr: Invalid login name '$login'"
X continue
X ;;
X [a-z]*)
X : do nothing since we seem to be ok
X ;;
X *)
X echo "$pr: Invalid login name '$login'"
X continue
X ;;
X esac
X echo $epre "$pr: Enter your Full Name: "$esuf
X eval "$READ" name
X echo "$OPER $login $name" >> $oplist
X break 2
X ;;
X esac
X done
Xdone
Xoperlogin=`grep "^$OPER[ ]" $opfiles | awk '{print $2; exit}'`
Xexport OPER # in case we do verifytoo or this is a 'verify alldisks'
X
X## if backups have to be done as root, make sure the operator is su'd
Xif test `ls -l $0 2>&- | grep -c '^...x'` -eq 1 ; then
X # find out effective user id - this is a guessing game but the
X # following rule seems best: whoami > id > $USER > $LOGNAME
X whoami=`( whoami ) 2> /dev/null`
X id=`( id | sed -e 's/).*//' -e 's/.*(//' ) 2> /dev/null`
X for arg in whoami id USER LOGNAME ; do
X eval "test -n \"\$$arg\" && result=\$$arg && break"
X done
X case $result in
X *root) : we are root so we are OK ;;
X *) echo "$pr: Backups on $lhost must be done as root." ; exit 1 ;;
X esac
Xfi
X
X## check mode specs and make some early decisions
Xcase "$mode" in
X'')
X echo "$pr: 'mode' was not specified. Valid modes are:"
X echo "$pr: 'help', 'full', 'incr', 'get', 'verify', or 'devcheck'."
X echo "$USAGE"
X exit 1
X;;
Xfull|incr|tincr)
X report=$breport
X if test -z "$multi" ; then
X echo "$pr: 'filesystem' was not specified. Valid filesystems are:"
X echo "$pr: '/fsname', 'alldisks', 'listN', 'list listfile', or 'unlisted'."
X echo "$USAGE"
X exit 1
X fi
X;;
Xget|verify)
X report=$gvreport
X if test -z "$getmode" ; then
X echo "$pr: 'getmode' was not specified. Valid getmodes are:"
X echo "$pr: 'onedisk', 'listdisks', '/fsname', 'lastdisk', or alldisks'."
X echo "$USAGE"
X exit 1
X fi
X;;
Xdevcheck)
X : nothing special needs to be done here
X;;
X*)
X echo "$pr: Do not understand mode '$mode'."
X echo "$USAGE"
X exit 1
X;;
Xesac
X
X## double check on a couple of unusual possible requests
X# if the operator says to do an incremental of just one filesystem, verify it.
Xcase $mode$multi in
X*incrfalse)
X checkq="Do you REALLY want to run an INCREMENTAL on '$fs'?"
X eval "$CHECKQ"
X;;
X# if the operator specified a full alldisks but there are list files present
Xfulltrue)
X if test "$multitype" = alldisks -a "`echo bkp.list[0-9]*`" != "bkp.list[0-9]*" ; then
X echo "$pr: There are list files in backup's home directory,"
X echo "$pr: so we are probably managing tape usage for full"
X echo "$pr: backups of $lhost with a 'list1/unlisted' scheme."
X ls -l bkp.list[0-9]*
X checkq="Are you SURE you want to do a 'full alldisks'?"
X eval "$CHECKQ"
X fi
X;;
Xesac
X
X## check media stuff
X# select device data file
Xif test -f $hdir/$devdata ; then
X devdata=$hdir/$devdata
X echo "$pr: WARNING: using '$devdata' for device data."
Xelif test -f $DTGT/$devdata ; then
X devdata=$DTGT/$devdata
Xelse
X echo "$pr: No '$devdata' in '$DTGT' or '$hdir'. Quitting."
Xfi
X# see if $mhost and $media are ok; note: a host may have no valid local media
Xmtype=`expr "$media" : '\([^0-9]*\)'`
Xmdata=`egrep "^$mhost[ ]+$media[ ]" $devdata`
Xcase "$mtype" in
X# if operator didn't specify media
X'')
X echo "$pr: 'media' was not specified."
X badmedia=true
X;;
X# if $mtype is null, no more validation needed since we always have /dev/null
Xnull)
X : do nothing
X;;
X# $mtype is dir or file, so we are writing or reading a file, not a tape device
Xdir|file)
X # make sure we're doing the right thing
X case "$mode" in
X devcheck)
X echo "$pr: 'devcheck' mode not supported for 'file' archives. Quitting."
X exit 1
X ;;
X get|verify)
X case $diskfile$multi in
X -true) echo "$pr: Cannot read alldisks from STDIN" ; exit 1 ;;
X esac
X ;;
X # some kind of backup
X *)
X case $diskfile$multi in
X -true) echo "$pr: Cannot write alldisks to STDOUT" ; exit 1 ;;
X esac
X ;;
X esac
X;;
X# $mtype is devnames, so make sure we are in devcheck mode
Xdevnames)
X if test "$mode" != devcheck ; then
X echo "$pr: Cannot specify device names except in devcheck mode."
X badmedia=true
X fi
X;;
X# $mtype is dat or video, so we only need to see if $media is valid
Xdat|video)
X if test -z "$mdata" ; then
X echo "$pr: '$media' is not a valid media for host '$mhost'"
X badmedia=true
X fi
X;;
X# $mtype isn't null, dat or video, so see if $media is valid, and also
X# make sure we don't do a full multi-filesystem backup to non-video/dat media
X*)
X if test -z "$mdata" ; then
X echo "$pr: '$media' is not a valid media for host '$mhost'"
X badmedia=true
X elif test "$mode" = full -a "$multi" = true -a "$fitguess" = true ; then
X echo "$pr: A 'full alldisks' will not fit on a '$mtype'."
X badmedia=true
X fi
X;;
Xesac
Xif test "$badmedia" = true ; then
X # print devices available on the media host and quit
X vmedia=`egrep "^$mhost[ ]" $devdata | awk '{print $2}'`
X vmedia=`echo $vmedia` # strip newlines
X if test -n "vmedia" ; then
X echo "$pr: $mhost has these media: '$vmedia'."
X fi
X echo "$pr: Look at '$devdata' for a list of valid"
X echo "$pr: media hosts and their devices."
X echo "$pr: Quitting."
X exit 1
Xfi
X# now that media info is ok, get info from $devdata by way of $mdata
X# for dir, file, null, and devnames, obs of 5120 is arbitrary,
X# maxocount of 100000 blocks is very arbitrary, and we pick 330000
X# for backup program options because it's our biggest valid "$bopt"
Xcase $mtype in
Xdir|file|null)
X set $mhost $mtype xx 100000 null null 330000
X;;
Xdevnames)
X set $mhost $mtype xx 100000 $rewdev $norewdev
X;;
X*)
X set $mdata
X;;
Xesac
Xreserved=$3 # document that we don't use this field since 4.22
Xmaxocount=$4 # maximum number of output blocks per tape
Xrewdev=/dev/$5 # name of rewind device we're using
Xnorewdev=/dev/$6 # name of no-rewind device we're using
X# should say "shift 6" here but CCI's BSD "sh" doesn't like it
Xshift ; shift ; shift ; shift ; shift ; shift
Xbopts="$*" # backup program (cpio/dump) options, if any
X# if $media is null, check with user, and set variables
Xif test $media = null ; then
X echo "$pr: WARNING!!! media is '$media' !!!"
X echo "$pr: This backup will be USELESS !!!"
X eval "$EXITQ"
X update=false
X offline=false
Xfi
X# if we're skipping media checks and we haven't already checked it, then
Xif test $check != true -a -z "$parent" ; then
X echo "$pr: WARNING: You are skipping media checks !!!"
X echo "$pr: You had better know what YOU are doing !!!"
X eval "$EXITQ"
Xfi
X
X###### Handle some real strange problems
Xcase $mlocal$multi$OS_S in
X# This shouldn't be a problem, but it is, so we'd better not even try this:
XfalsefalseAIX)
X echo "$pr: AIX network cpio onedisk backups *don't* work."
X echo "$pr: FYI, this is mysterious, because, so far as we know:"
X echo "$pr: 1) AIX network cpio multi-filesystem backups *do* work."
X echo "$pr: 2) Both onedisk and multi-filesystem network cpio backups"
X echo "$pr: for other UNIXs *do* work."
X echo "$pr: The problem is that the archive is missing the first 88k or"
X echo "$pr: so of the archive. It is unknown why this happens."
X exit 1
X;;
Xesac
X# This is a real problem:
Xcase $mlocal$multi$mistape$OS_S$OSLEVEL_S$rewdev in
Xfalsetruetruedgux5.4*/dev/rmt/*)
X echo "$pr: WARNING: Under dgux 5.4, if a multi-filesystem network"
X echo "$pr: backup to a '/dev/rmt' device uses more than one tape,"
X echo "$pr: and it looks like it works beautifully, BE AWARE:"
X echo "$pr: the filesystem which is split accross two tapes may be"
X echo "$pr: missing 50 blocks (or so) of buffered data which the remote"
X echo "$pr: system was unable to write to it's tape drive when it hit"
X echo "$pr: physical EOT (end of tape)."
X echo "$pr: You can try setting up and using a pseudo mag tape"
X echo "$pr: '/dev/pmt' device on $lhost instead."
X eval "$EXITQ"
X;;
Xesac
X
X# now that our mode has been set, we can make sure we don't conflict
X# with another currently running backup/get/verify
Xif test -f $lockf -a $mode != devcheck -a -z "$parent" ; then
X echo "$pr: A conflicting cpio backup/get/verify seems to be in progress."
X cat $lockf
X echo "$pr: Check with 'ps $PSALL_K'. Quitting."
X # take the lock file out of $rmlist before exiting!
X rmlist=`echo $rmlist | sed -e "s,$lockf ,,"`
X exit
Xfi
X
X# See if we know how many extra volumes are in the backup set.
X# This only makes sense if we're doing a get or verify.
Xif test -n "$extravol" ; then
X case $mode in
X get|verify) : we are ok but do we do not have to do anything ;;
X *) echo "$USAGE" ; exit 1 ;;
X esac
Xfi
X
X# if user specified a restore target on the command line, make sure we're
X# in "get" mode and that they really did specify *some* target (which we'll
X# check out more thoroughly later).
Xif test "$targetarg" = true ; then
X case $mode in
X get)
X if test -z "$target" ; then
X echo "$pr: Target directory not specified. Quitting."
X echo "$USAGE"
X exit 1
X fi
X ;;
X *)
X echo "$pr: 'target
' only valid for 'get' mode. Quitting."
X echo "$USAGE"
X exit 1
X ;;
X esac
Xfi
X
X# if user specified a listfile on the command line, make sure it exists
X# and has something in it.
Xif test -n "$listf" ; then
X if test ! -f $listf ; then
X echo "$pr: No such listfile '$listf'. Quitting."
X exit 1
X elif test ! -s $listf ; then
X echo "$pr: Listfile '$listf' is empty. Quitting."
X exit 1
X fi
Xfi
X
X## we've checked as much command syntax as we can without making a working
X## directory, but we need one now.
X# It's name has a short form "$wdir" and long form "$workdir".
X# It's "$wdir" name is based on the
X# a) date, b) mode, and c) onedisk vs. multi-filesystem archive.
X# "g" for get, "f" for full, "i" for incremental, "t" for test_incremental,
X# and "v" for verify;
X# "m" for multi-filesystem (alldisks), "o" for onedisk
Xcase "$mode$multi" in
Xdevcheck*) wdir=$date4.${time6}d ;;
Xget*) wdir=$date4.${time6}g ;;
Xverifytrue) wdir=$date4.${time6}vm ;;
Xverify*) wdir=$date4.${time6}vo ;;
Xfulltrue) wdir=$date4.${time6}fm ;;
Xincrtrue) wdir=$date4.${time6}im ;;
Xtincrtrue) wdir=$date4.${time6}tm ;;
Xfull*) wdir=$date4.${time6}fo ;;
Xincr*) wdir=$date4.${time6}io ;;
Xtincr*) wdir=$date4.${time6}to ;;
Xesac
Xcase "$parent" in
X'') workdir=$hdir/$wdir ;;
X*) workdir=$hdir/$parent/$wdir ;;
Xesac
X# make sure creation of $workdir succeeds, because if it doesn't the
X# filesystem is probably full, and we can end up with a truncated bkp.donot
X# among other disasters.
Xmkdir $workdir
Xif test $? -ne 0 ; then
X echo "$pr: Could not make '$workdir'."
X echo "$pr: The filesystem holding backup's home directory is probably full."
X echo "$pr: Quitting."
X exit 1
Xfi
Xcd $workdir
X
X## sample "df" outputs - needed if we're doing a backup
X#
X## normal BSD output
X# Filesystem kbytes used avail capacity Mounted on
X# /dev/xd0a 15720 4564 9584 32% /
X#
X## System V output (including "/adj" multi-cpu concept from 3B4000 (bigbird))
X# / (/dev/dsk/c0t7d0s0): 0 blocks 51134 i-nodes
X# /adj (/dev/adj ): 32568 blocks 4582 i-nodes
X# /proc (/proc ): 0 blocks 859 i-nodes
X# /adj/pe96/dev (/adj/pe96/dev/icfs): 179 blocks 413 i-nodes
X# /install/62 (/adj/pe96/dev/dsk/c0t4d0s0): 328800 blocks 61126 i-nodes
X#
X## AIX 2.2.1: output with "/native" NFS-ish concept. Note 7 fields.
X# Device Mounted on total free used ifree used
X# /dev/hd0 / 38684 8144 78% 9297 7%
X# / /native 38684 8144 78% 9297 7%
X#
X## AIX 3.1: Note 7 fields but mountpoint is the last field as it should be.
X# Filesystem Total KB free %used iused %iused Mounted on
X# /dev/hd4 40960 1128 97% 1245 12% /
X# /dev/hd2 376832 47336 87% 7852 8% /usr
X#
X## TI Sys V 3.2.1: Note *two* colons:
X#/ (/dev/dsk/sys:root): 1726 blocks 2139 i-nodes
X#/pipe (/dev/dsk/sys:pipe): 989 blocks 452 i-nodes
X#/usr (/dev/dsk/sys:usr): 1357 blocks 5925 i-nodes
X#/install/62/supp (/dev/dsk/dsk2:supp): 91011 blocks 36947 i-nodes
X#
X## IRIX 3.3.2: note /debug which is not a real filesystem
X# Filesystem Type blocks use avail %use Mounted on
X# /dev/root efs 31360 26001 5359 83% /
X# /dev/usr efs 1860180 1132421 727759 61% /usr
X# /debug dbg 143936 12344 131592 9% /debug
X#
X## NonStop-UX 4.0 "df" doesn't show filesystem type so we have to look it
X## up in /etc/vfstab or use "df -n".
X## NonStop-UX 4.0 "df -k -l"
X# abalone 125# df -k -l
X# filesystem kbytes used avail capacity mounted on
X# /dev/vol/root 65536 56069 9467 86% /
X# /proc 0 0 0 0% /proc
X# /dev/fd 0 0 0 0% /dev/fd
X# /config 0 0 0 0% /config
X# /dev/vol/usr 256000 195626 60374 76% /usr
X# /dev/dsk/sc1d3s10 282933 149152 133781 53% /install/64
X## NonStop-UX 4.0 "df -n"
X# abalone 126# df -n
X# / : vxfs
X# /proc : proc
X# /dev/fd : fdfs
X# /config : cfs
X# /usr : vxfs
X# /install/64 : ufs
X# abalone 127#
X## NonStop-UX 4.0 end of "df" outputs
X#
X## END of "df" sample outputs
X
X# if we are doing a backup of one or more filesystems, then
X# get df output and make sure our bkp.donot file excludes strange filesystems
X# else take care of a few other little things
Xcase $mode$fsbkp in
Xdevcheck*|get*|verify*)
X : do nothing special
X;;
Xfullfalse)
X if test ! -d $fs ; then
X echo "$pr: $fs is not a directory. Quitting."
X exit 1
X fi
X devlist=$fs
X;;
X*false)
X echo "$pr: Incrementals OK for filesystems only. Quitting."
X exit 1
X;;
Xfull*|incr*|tincr*)
X ## get list of valid filesystems for backup.
X # see sample "df" outputs above
X # We use "df" because it's output is more similar across OS platforms
X # than "mount" and Sys V mount doesn't always show the root filesystem.
X # Unfortunately, df can hang waiting for info from an NFS filesystem.
X # "df > $dft1 & ; sleep 5 ; ..." isn't a workaround because in that
X # usage "df" won't put out any info until it completes.
X # Oh, well, there's no good answer yet, except on some machines
X # where "df" has a filesystem type key
X if test "$OS_S" = NonStop-UX ; then
X dfargs="-l"
X elif test -n "$DFFSTYPE_K" -a -n "$LOCFSTYPE_S" ; then
X dfargs="$DFFSTYPE_K $LOCFSTYPE_S"
X else
X dfargs=""
X fi
X df $dfargs | egrep '/dev/' > $dft1
X
X # if we have SysV df output
X if egrep '\):' $dft1 > /dev/null ; then
X sed -e 's/(/ /' -e 's/):/ /' $dft1 | awk '{printf "%-16s %6d %s %6d %s %s\n",$2,$3,$4,$5,$6,$1}' > $dft2
X # else if we're AIX 2.2.1
X elif awk '{print $2}' $dft1 | grep / > /dev/null ; then
X egrep '/dev/' $dft1 | awk '{printf "%-16s %6d %6d %4s %6d %4s %s\n",$1,$3,$4,$5,$6,$7,$2}' > $dft2
X # else we're normal BSD or AIX 3.1
X else
X cp $dft1 $dft2
X fi
X
X # Some operating systems have filesystems we never want to back up
X case "$OS_S$OSLEVEL_S" in
X AIX2.2.1|IRIX3*|NonStop-UX4.0)
X case "$OS_S$OSLEVEL_S" in
X AIX2.2.1) bumfs=/native ;;
X IRIX3*) bumfs=/debug ;;
X NonStop-UX4.0) bumfs=/config ;;
X esac
X if test ! -f $nobkp ; then
X echo $bumfs > $nobkp
X elif egrep $bumfs $nobkp > /dev/null ; then
X : do nothing we are already protected
X else
X echo $bumfs >> $nobkp
X sort -u -o $nobkp $nobkp
X fi
X ;;
X esac
X
X ## We have three filters for filesystems which we may not want
X ## to back up. Two of them are config files, and the third we
X ## implement in code.
X #
X # filesystem filters:
X # a) $nobkp, lists filesystems we never want to back up, and we make
X # sure it includes the following filesystems (see $bumfs above)
X # For AIX 2.2.1, don't back up /native (see above)
X # For IRIX 3.*, don't back up /debug
X # For NonStop-UX, don't back up /config
X # Otherwise, $nobkp is configured by the user
X # b) $nofm, lists filesystems we never want to do full multivolume
X # backups on (i.e. we don't do full alldisks with). Typically
X # this file might list 1Gig filesystems which we want to do
X # seperate full onedisk backups on.
X # c) don't backup /cdrom/unnamed_cdrom, /cdrom*, /export/swap, /proc,
X # /tmp, or NFS filesystems
X #
X ## We also may have some number of listfiles (e.g. bkp.list0) to check
X ## valid formats. The format for the listfiles is the same as the
X ## filesystem filter files.
X #
X # NOTE:
X # we must carefully delimit filesystem name for egrep, both here and
X # in $nobkptmp.
X # The regular expression must include '[]/fsname'
X # This example would prevent backing up a /scratch filesystem:
X # [ ]/scratch$
X
X # massage config file filesystem filters into $nobkptmp, if we
X # have them and want to use them;
X # also massage $listf into $listftmp if necessary
X rm -f $nobkptmp $listftmp
X case $mode$multi in
X fulltrue) fsfilters="$nobkp $nofm" ;;
X *) fsfilters="$nobkp" ;;
X esac
X case "$multitype" in
X unlisted)
X cd $hdir
X listfiles=`echo bkp.list[0-9]*`
X if test "$listfiles" != "bkp.list[0-9]*" ; then
X # sed strips comments and blank lines in $listfiles
X sed -e 's/[ ]*\#.*//' -e '/^[ ]*$/d' $listfiles > $workdir/bkp.listed
X fsfilters="$fsfilters $workdir/bkp.listed"
X fi
X cd $workdir
X ;;
X esac
X for ff in $fsfilters $listf ; do
X if test -f $ff ; then
X ## make sure $ff is in correct format
X # assume leading blanks, trailing blanks, and blank
X # lines are benign, and quietly fix them if present
X sed -e 's/^[ ]*//' -e 's/[ ]*$//' -e '/^$/d' $ff > $ff.t
X if test `wc -c < $ff.t` -lt `wc -c < $ff` ; then
X mv $ff.t $ff
X fi
X # strip comments, then see if $ff.t1 has any
X # real data left
X sed -e 's/[ ]*\#.*//' -e '/^[ ]*$/d' $ff > $ff.t1
X if test ! -s $ff.t1 ; then
X case $ff in
X */bkp.donot|*/bkp.nofm)
X echo "$pr: WARNING - '$ff' is empty or has only comments; please fix or remove; continuing ..." | tee -a $failrpt
X continue
X ;;
X *)
X echo "$pr: Listfile '$ff' is empty. Quitting." | tee -a $failrpt
X exit 1
X ;;
X esac
X fi
X # check for common mistakes: putting device name
X # instead of mount point.
X if egrep '^/(adj/.*)*dev/' $ff > /dev/null ; then
X echo "$pr: '$ff' contains device names"
X echo "$pr: instead of mount points. Quitting."
X exit 1
X fi
X ## make sure $nobkptmp is in correct format, with a
X # []filesystemname (for dump)
X # []directoryname (for cpio)
X sed -n -e 's,^\(/[a-zA-Z0-9_/\.\+-]*\)$,[ ]\1$,p' $ff.t1 > $ff.t
X nlinesorig=`wc -l < $ff.t1`
X nlinestmp=` wc -l < $ff.t`
X # if the number of lines in $ff.t1 and $ff.t
X # are unequal, create failure report and quit.
X if test $nlinesorig -eq $nlinestmp ; then
X case $ff in
X */bkp.donot|*/bkp.nofm|*/bkp.listed)
X cat $ff.t >> $nobkptmp
X ;;
X *)
X cat $ff.t >> $listftmp
X ;;
X esac
X else
X exec 1> $failrpt
X echo ""
X echo "$pr: '$ff' is not in correct format."
X echo "$pr: '$ff' must list one filesystem per line"
X echo "$pr: (although comments beginning with '#' are OK)"
X echo "$pr: Please fix '$ff'. Quitting."
X exec 1>&9
X cat $failrpt
X exit 1
X fi
X rm -f $ff.t1 $ff.t
X fi
X done
X
X # strip unwanted filesystems, now that we have $nobkptmp
X # "/adj/.*dev/" selects Sys V devices, e.g. /adj/pe96/dev/ on 3B4000's
X # "/cdrom" is for SunOS's read only CDROM
X # "/cdrom/unnamed_cdrom" is for Solaris's 2.2+ read only CDROM
X # "/export/swap", "/proc", and "/tmp" are scratch so we don't care
X #
X # first egrep strips filesystems we never want
X # "if" subshell strips any filesystems in $nobkptmp if it exists
X # second egrep selects info on devices
X egrep -v '[ ]/(cdrom.*|export/swap|proc|tmp)$' $dft2 \
X | if test ! -s $nobkptmp ; then
X cat
X else
X # $egrepff, $egrepfi, $egrepfo, and $egrepfv for $EGREPF
X egrepff=$nobkptmp
X egrepfi=""
X egrepfo=""
X egrepfv="-v"
X eval "$EGREPF"
X fi \
X | egrep '^/dev/|^/adj/.*dev/' > $dft3
X
X # put /, /usr, and /var *first*
X # (In alldisks versions before 3.00, / and /usr were last.)
X # (From alldisks versions 3.00 thru 4.46, / and /usr were first.)
X # (Since alldisks version 4.47, /, /usr, and /var are first.)
X egrep '[ ]/$' $dft3 > $dfout
X egrep '[ ]/usr$' $dft3 >> $dfout
X egrep '[ ]/var$' $dft3 >> $dfout
X egrep -v '[ ](/|/usr|/var)$' $dft3 >> $dfout
X
X # select filesystems from $listf
X if test -n "$listf" ; then
X mv $dfout $dflocal
X # $egrepff, $egrepfi, $egrepfo, and $egrepfv for $EGREPF
X egrepff=$listftmp
X egrepfi=$dflocal
X egrepfo=$dfout
X egrepfv=""
X eval "$EGREPF"
X fi
X
X if test ! -s $dfout ; then
X echo "$pr: '$dfout' is empty. Something is wrong."
X echo "$pr: Quitting."
X exit 1
X fi
X
X ## get list of actual filesystem devices - necessary because
X ## a) 4.1BSD dump matches 1st *similar* pattern, not real thing
X ## b) NCR SVR4 does not look up mount point in /etc/vfstab
X # if $fs wasn't specified then we're doing an alldisks backup
X if test -z "$fs" ; then
X devlist=`awk '{print $1}' $dfout`
X # else $fs was specified, so check its validity
X else
X # if $fs is in $dfout we're cool
X devlist=`egrep "[ ]$fs\$" $dfout | awk '{print $1}'`
X if test -z "$devlist" ; then
X # maybe $fs is in $nobkp (and hence in $dft2 but not $dfout)
X devlist=`egrep "[ ]$fs\$" $dft2 | awk '{print $1}'`
X if test -n "$devlist" ; then
X echo "$pr: Filesystem '$lhost:$fs' is not usually backed up."
X eval "$EXITQ"
X # else we really aren't a mounted filesystem
X else
X echo "$pr: Bad filesystem name '$fs'"
X exit 1
X fi
X fi
X fi
X;;
Xesac
X
Xecho "$pr: Your command looks AOK to me. Thanks."
X
X# build local and remote commands (no dd command since we're using $bdd script)
Xcase $mhost in
X$lhost) mlocal=true ;; # the media is local
X*) mlocal=false ;; # the media is remote
Xesac
Xif test $mlocal = true ; then
X cmp="cmp"
X ls="ls"
X mt="mt"
X rm="rm"
X tar="tar"
Xelif test -z "$rsh" ; then
X echo "$pr: \$RSH_C is not set in /etc/saenv:"
X grep '^RSH_C=' /etc/saenv
X echo "$pr: Quitting."
X exit 1
X# "date" output is same on BSD, SunOS, SysV, NCROS, UTS, AIX, Solaris, SVR4
X#elif test `$rsh $mhost date 2> /dev/null | wc -w` -ne 6 ; then
Xelif $rsh $mhost date > /dev/null 2>&1 ; then
X cmp="$rsh $mhost cmp"
X ls="$rsh $mhost ls"
X mt="$rsh $mhost mt"
X rm="$rsh $mhost rm"
X tar="$rsh $mhost tar"
Xelse
X echo "$pr: $rsh $mhost date"
X $rsh $mhost date
X echo "$pr: 'root' on $lhost does not have permission to run"
X echo "$pr: remote shell commands at media host $mhost. Check:"
X echo "$pr: -> Make sure '$lhost root' is in /.rhosts on $mhost."
X echo "$pr: -> Make sure '$lhost' has a valid entry in /etc/hosts on $mhost."
X echo "$pr: Quitting."
X exit
Xfi
X
X## make sure backup.dd script is usable
X# export environment variables needed by backup.dd
XMHOST=$mhost
XLHOST=$lhost
Xexport MHOST LHOST RSH_C
X# if we haven't tested it already, do so now
Xif test -z "$parent" ; then
X eval $SHOWDD Make sure $bdd script is usable
X echo "$pr: you should never see this" | $bdd of=/dev/null 2> err.dd
X if test $? -ne 0 ; then
X cat err.dd
X echo "$pr: '$bdd' is not usable for some reason. Quitting."
X exit 1
X fi
Xfi
Xrm -f err.dd
X
X# build mt command if mt exists
Xif test $mhost = $lhost ; then
X mtkey="$MT_K"
Xelse
X mtkey="`$rsh $mhost grep 'MT_K=' /etc/saenv | sed -n -e '/^MT_K=/s/^MT_K=\([^ ]*\)[ ].*/\1/p'`"
Xfi
Xcase "$mtkey" in
X'') mt='' ;; # mt command does not exist on media host
X*) mt="$mt $mtkey" ;; # mt command does exist on media host
Xesac
X
X## figure out which backup/get program(s) we're using
X# if the user specified cpio on the command line
Xif test "$bprog" = cpio ; then
X restore=cpio
X# else if we're on Dynix Sequent using a video drive
Xelif test -n "$HDUMP_P" -a $mtype = video ; then
X bprog=$HDUMP_P
X restore=$RESTOR_P
X# else if we have BSD dump by some name
Xelif test -n "$DUMP_P" ; then
X bprog=$DUMP_P
X restore=$RESTOR_P
X# else we're using cpio
Xelse
X bprog=cpio
X restore=cpio
Xfi
Xif test $mhost != $lhost ; then
X # set remote dump/restore if bprog is "dump"
X case $bprog in
X *dump*)
X # set remote dump - warn and die if unavailable
X case $bprog in
X $HDUMP_P) bprog=$HRDUMP_P ;; # Dynix "hdump/hrdump"
X *) bprog=$RDUMP_P ;; # normal "dump/rdump"
X esac
X if test -z "$bprog" ; then
X echo "$pr: Remote dump unavailable on '$lhost' (see \$RDUMP_P in /etc/saenv)."
X echo "$pr: Cannot do dumps over net from '$lhost'."
X echo "$pr: Try 'cpio' option to do network cpio backups."
X exit 1
X fi
X # set remote restore - warn and die if unavailable
X if test -n "$RRESTOR_P" ; then
X restore=$RRESTOR_P
X else
X echo "$pr: Remote restore unavailable on '$lhost' (see \$RRESTOR_P in /etc/saenv)."
X echo "$pr: Cannot do restores over net from '$lhost'."
X echo "$pr: Try 'cpio' option to do network cpio restores."
X exit 1
X fi
X ;;
X esac
Xfi
X# header program
Xcase $bprog in
Xcpio) headprog=cpio ;; # header archive is cpio format
X*dump*) headprog=tar ;; # header archive is tar format
Xesac
X# lock out other cpio backups/gets/verifies, or lock if we're asked to
Xif test $bprog = cpio -o $optlk = true ; then
X echo "$pr: LOCK: PID=$$, $workdir, $pr $cmdargs" > $lockf
Xfi
X# other initial stuff - if we're updating make sure we can
Xcase $update$bprog in
X*cpio)
X # if this is a bad (but real) joke
X if test $joke = true -a $mode != devcheck ; then
X echo "$pr: We are using cpio - help!"
X echo "$pr: Oh, I'm feeling sick ... "
X echo $epre "$pr: cough, "$esuf
X sleep 1
X echo $epre " choke . . . "$esuf
X sleep 1
X echo "gagghhhhh"
X echo "$pr: (THUD)."
X echo ''
X sleep 2
X echo "$pr: Bones: He's dead, Jim."
X sleep 2
X echo ''
X echo "$pr: Spock: Correction - he's braindead."
X echo ''
X sleep 2
X echo "$pr: Kirk: Well then, Bones, thanks to the miracle of"
X echo "$pr: the alldisks script, we can still do the backup."
X echo "$pr: Carry on."
X echo ''
X fi
X;;
Xtrue*dump*)
X # make sure /etc/dumpdates exists
X if test ! -f /etc/dumpdates ; then
X echo "$pr: /etc/dumpdates does not exist, creating /etc/dumpdates."
X echo "$pr: We do this because some versions of BSD dump abort if"
X echo "$pr: /etc/dumpdates doesn't exist."
X echo "$pr: This is probably the first time BSD dump has been used on $lhost."
X touch /etc/dumpdates
X echo "$pr: `ls -l$LSGROUP_K /etc/dumpdates`"
X echo "$pr: We're OK now, continuing with the backup."
X fi
X
X # Make a feeble effort to make sure dump can read and write dumpdates.
X # We test to see if the script can read and write dumpdates, and
X # act accordingly. However, that doesn't tell us what dump/rdump
X # will do when we call it. Unfortunately, this is the best we can do.
X # Even using "dump W" to test readability won't reliably produce
X # useful results, because under HP-UX 8.00 (and probably many other
X # UNIXs), if "dump W" is called from a setuid root script, it can read
X # /etc/dumpdates even if permissions are 000.
X if test ! -r /etc/dumpdates -o ! -w /etc/dumpdates ; then
X touch /etc/dumpdates
X echo "$pr: `ls -l$LSGROUP_K /etc/dumpdates`" | tee -a $workdir/$report
X echo chmod u+rw /etc/dumpdates | tee -a $workdir/$report
X chmod u+rw /etc/dumpdates
X fi
X # quit if we weren't able to fix it
X if test ! -r /etc/dumpdates -o ! -w /etc/dumpdates ; then
X echo "$pr: `ls -l$LSGROUP_K /etc/dumpdates`" | tee -a $workdir/$report
X echo "$pr: Cannot read/write /etc/dumpdates. Quitting."
X exit 1
X fi
X
X # HACK4HPUX8 is from $site; it may make dumpdates 664 group operator
X eval "$HACK4HPUX8"
X;;
Xesac
X
X# now that $bprog and $restore are set, turn off actual backup work
X# for demonstrations
Xif test $demo = true ; then
X bprog="echo $pr demo: $bprog" # echo backup command
X restore="echo $pr demo: $restore" # echo get command
X mt="echo $pr demo: $mt" # echo mt command
X # dd command is tricky, so tailor it wherever it is used
Xfi
X
X# decide whether we're using a file, dir, rewind device, norewind device
X# mdevbase wouldn't be needed if we were only supporting tape devices,
X# but since we're supporting alldisks to disk files, we'll be reasigning
X# mdev based on $mdevbase.
Xif test $mtype = dir ; then
X if test $mode = get -o $mode = verify ; then
X # a parent could be like either "0206.164423fm"
X # or "0206.164423fm/0206.164448vm"
X if test -n "$parent" ; then
X # $parenttop is roughly the opposite of basename $parent
X parenttop=`echo $parent | sed -e 's/\/.*//'`
X mdevbase=$diskfile/$parenttop
X # or we have no parent, and we assume the directory has
X # files from only one backup
X else
X cd $diskfile
X mdevbase=$diskfile/`echo [01][0-9][0123][0-9].*[a-z].[0-9][0-9] | sed -e 's/ .*$//' -e 's/\.[0-9][0-9]$//'`
X cd $workdir
X fi
X else
X mdevbase=$diskfile/$wdir
X fi
Xelif test $mtype = file ; then
X mdevbase=$diskfile
Xelif test $mode = get -o $mode = verify ; then
X mdevbase=$rewdev
Xelif test "$multi" = false ; then
X mdevbase=$rewdev
Xelse
X mdevbase=$norewdev
Xfi
Xmdev=$mdevbase
X
X## deal with cpio/dump/restore keys and options
X# if the backup/get/verify program is cpio
Xcase $bprog in
Xcpio)
X # check $maxocount
X case $maxocount in
X [1-9][0-9]*)
X : do nothing
X ;;
X *)
X echo "$pr: Maximum output blocks for $mhost:$media in"
X echo "$pr: $devdata is '$maxocount'. Quitting."
X exit 1
X ;;
X esac
X # get cpio options
X ckey='' # initialize cpio key
X for i in $bopts ; do
X # see comments in the NOTES file about making
X # "cpio ... | dd ... " work, given possible problems with
X # cpio output block size, pipesize, dd's ibs and obs, and
X # the device driver for the output device; also the size
X # $RSH_C on both hosts can handle if were doing a backup
X # over the net.
X # $cpioobs cpio's output blocksize
X # $ckey cpio key (ckey=C$obs || ckey=B)
X # $obs from $devdata
X # based on pipesize from $SAHOST:$SABIN/getpipesize
X case $i in
X C)
X ckey=${ckey}C$obs # cpio block size is $obs
X ibs=$obs # easiest if they match
X ;;
X DAT1|DAT2|E82|E85|QIC*|TK50|TK70)
X continue # this info for humans only
X ;;
X# TI Sys V can't read multiple cpio archives put on with their -T option
X# T)
X# ckey=${ckey}T # write portable cpio archives on TI's
X# ;;
X *)
X if test $mistape != true ; then
X echo "$pr: dump option '$i' in '$devdata' ignored."
X fi
X ;;
X esac
X done
X # if $ckey doesn't include "C" then
X if echo "$ckey" | grep -v C > /dev/null ; then
X ckey=B$ckey
X ibs=5120 # make dd ibs match
X fi
X;;
X# $bprog is BSD dump/restore (by some name)
X# we build the dump command line here. It's also convenient to build
X# most (not all) of the restore key. We'll need to finish the
X# job later if we're really doing a get, by asking the user whether
X# to do an interactive restore or to restore the entire dump.
X*dump*)
X # set dump level
X case $mode in
X full) dlevel=0 ;;
X incr) dlevel=$incr ;;
X tincr) dlevel=$test_incr ;;
X esac
X # if we're not supposed to update or we're dumping to the bit-bucket
X if test $update != true -o $media = null ; then
X updkey= # don't update /etc/dumpdates
X else
X updkey=u # update /etc/dumpdates
X fi
X # figure out restore opts key, restore opts, dump key, and dump opts
X # we have to deal with DEC_OSF/1 strangeness here for roptkey, since the
X # roptkey can't have an "f" in it because rrestore's command syntax is:
X # /usr/sbin/rrestore -f host:/device -$rmode$roptkey $ropts
X # According to the manual page DEC_OSF/1 doesn't mess with the
X # syntax for local restore's, but this works too:
X # /usr/sbin/restore -f /device -$rmode$roptkey $ropts
X case "$OS_S" in
X DEC_OSF/1) roptkey='' ;;
X *) roptkey=f ;;
X esac
X dkey=$dlevel${updkey}f
X dopts='' # dump options based on $dkey and $bopts
X d2mtype='' # DG dump2's media type option
X d2stats='' # DG dump2's statistics report option
X
X # modify the keys according to dump/restore options, if any
X for i in $bopts ; do
X case $i in
X # "-d" (density in BPI)
X # 1600, 3200 and 6250 for 9tracks
X # 6670 for tk50's
X # ???? for tk70's
X # 1000 for QIC11/QIC24/QIC150 carts,
X # 23000 for MIPS 120M carts
X # 141000 for auspex 8500 exabytes
X 1000|1600|3200|6250|6670|23000|141000)
X dkey=${dkey}d
X ;;
X # "-t" (tracks: cartridge only)
X # 4 for QIC11, 9 for QIC24, 18 for QIC150
X 4|9|18)
X dkey=${dkey}t
X ;;
X # "-b" (blocking factor: either 512 characters or
X # 1024 characters per tape block depending on the OS)
X # 126 for videos on suns, 346 for video on DYNIX,
X # 100 for auspex 8500 exabytes,
X # else any even two-digit number
X 100|126|346|[1-9][02468])
X dkey=${dkey}$DRB_K # tapeblock size ...
X roptkey=${roptkey}$DRB_K # was specified ...
X if test -n "$DRB_K" ; then
X ropts="$ropts $i" # and is $i
X else
X echo "$pr: Blocksize '$i' in $devdata"
X echo "$pf: ignored, because this OS does not support it."
X fi
X ;;
X # "-s" (size in feet)
X # 11500 for auspex 8500 exabytes
X # 70000 for dats
X # 165000 for Exabyte 8200s
X # 330000 for Exabyte 8500s
X # any other three- or four-digit number ending in "00" or "25"
X # (see $mdev for why)
X 11500|70000|165000|330000|[1-9][02][05]|[1-9][0-9][02][05])
X dkey=${dkey}s # size was specified
X ;;
X # "c" for Sun cartridge drives
X # "C" for Bull cartridge drives
X c|C)
X # only need to change dump key not restore key for suns
X dkey=${dkey}$i # cart was specified (suns)
X continue # so $i isn't put in $dopts
X ;;
X M)
X d2mtype="$i $mtype" # dump2's mediatype key and arg
X continue # so $i isn't put in $dopts
X ;;
X s)
X d2stats=s # dump2's statistics key
X continue # so $i isn't put in $dopts
X ;;
X DAT1|DAT2|E82|E85|QIC*|TK50|TK70)
X continue # this info for humans only
X ;;
X *)
X echo "$pr: I do not understand $bprog option '$i' in '$devdata'"
X echo "$pr: Quitting."
X exit 1
X ;;
X esac
X dopts="$dopts $i"
X done
X
X # Dec's OSF/1 version of dump/rdump automatically ejects the tape
X # after the dump is done, unless you put the "N" in the dump key.
X case "$OS_S" in
X DEC_OSF/1) dkey=${dkey}N ;;
X esac
X
X # build backup command for local vs. remote media
X # $DRMINUS is for Bull OS, ICL, and other weirdos
X # dump2 code is for DG's dump2
X case $bprog in
X *dump2)
X test -n "$opfifo" && d2opts="$d2opts $DRMINUS$opfifo"
X test -n "$d2mtype" && d2opts="$d2opts $DRMINUS$d2mtype"
X test -n "$d2stats" && d2opts="$d2opts $DRMINUS$d2stats"
X ;;
X *)
X if test -n "$opfifo$d2mtype$d2stats" ; then
X echo "$pr: Data General 'dump2' arguments '$opfifo$d2mtype$d2stats' in '$devdata'"
X echo "$pr: do not work on non-DG machines. Quitting."
X exit 1
X fi
X ;;
X esac
X case $mhost$diskfile in
X $lhost-)
X # the "sleep" is to give the shell time to open b.$fsnn.out
X bcmd='$bprog $DRMINUS$dkey $mdev $dopts $d2opts $fsdev 1>&8 2> b.$fsnn.out & bpid=$! ; sleep 2 ; tail -f b.$fsnn.out & tailpid=$!'
X ;;
X *-)
X echo "$pr: Cannot dump to standard out on remote host."
X exit 1
X ;;
X $lhost*)
X bcmd='$bprog $DRMINUS$dkey $mdev $dopts $d2opts $fsdev 2>&1 | tee -i b.$fsnn.out'
X ;;
X *)
X bcmd='$bprog $DRMINUS$dkey $mhost:$mdev $dopts $d2opts $fsdev 2>&1 | tee -i b.$fsnn.out'
X ;;
X esac
X;;
Xesac
X
X###############################################################################
X## Device testing
X## if $demo is false, $check is true, and $mtype isn't dir, file or null ; then
X## case $mode in
X## get|verify)
X## verify read of rewind device
X## ;;
X## full|incr|tincr|devcheck)
X## verify write to rewind *and* norewind devices
X## ;;
X## esac
X## endif
X## The actual test code is written to avoid indenting more than one level
X
X## First, make sure rewind and norewind devices are block/character
X## special files (trust symlinks).
X## (But don't do it if $mtype is dir or file.)
X# The "ls -l" writes to standard error if $rewdev doesn't exist,
X# so "wc -l" gives 0. This trickiness is needed because we may be
X# dealing with a remote machine. Remote shell (rsh) reports success
X# if it had permission to run a command on the remote box, and doesn't
X# care if the command itself works or not. Also, we assume symbolic
X# links are cool because it's really hard to verify them, especially on
X# remote boxes. That's why we egrep for '^[bcl]'.
Xif test $mtype != dir -a $mtype != file -a `$ls -l $rewdev | egrep -c '^[bcl]'` -ne 1 ; then
X badrewdev=true
X echo "$pr: No device node for rewind device '$rewdev'" >> $failrpt
Xfi
Xif test $mtype != dir -a $mtype != file -a `$ls -l $norewdev | egrep -c '^[bcl]'` -ne 1 ; then
X badnorewdev=true
X echo "$pr: No device node for norewind device '$norewdev'" >> $failrpt
Xfi
Xif test "$badrewdev" = true -o "$badnorewdev" = true ; then
X echo "$pr: Media data file '$devdata' is wrong." >> $failrpt
X echo "$pr: Notify a UNIX System Administrator IMMEDIATELY ! ! !" >> $failrpt
X cat $failrpt
X exit 1
Xfi
X
X## Second, set up media test block sizes and test files on the media host.
X## Do before all real media tests.
Xcase $bprog$multi in
Xcpio*)
X mtestibs=10b # header file is cpio, backup is cpio
X;;
X*dump*true)
X mtestibs=20b # header file is tar
X;;
X*dump*)
X mtestibs=63k # backup is dump, so choose max dump blocksize
X # deal here with special weird mtestibs requirements:
X # Bull's B.O.S. can't read more than 60k from a cart
X # DYNIX and DYNIX/ptx can't read more than 32k from "xt" devices;
X # we could get down to that level, but this ought to be good enough.
X case "$OS_S" in
X B.O.S.) mtestibs=60k ;;
X DYNIX|DYNIX/ptx) mtestibs=32k ;;
X esac
X;;
Xesac
X# For media test files, we can't just use /etc/passwd and /etc/group
X# because the test files must be modulus 512 in size for cartridge drives
X# (a hardware limitation). We also need test files to be modulus 10k for
X# some video units (we don't know why, but 1k is too small). On the
X# other hand 5k is the max on AT&T 3B5 (coyote), maybe because it's
X# pipesize is so strange (6144 characters). So, we create the first and
X# second test files on the fly. All media test files should be in a
X# world writeable directory, not $workdir, because we may have to create
X# it on a remote machine.
X#
X# We need test files for rewind/norewind device testing and also for
X# tape testing for cpio backups.
Xcase $mode in
Xdevcheck|full|incr|tincr)
X eval $SHOWDD Create two test files
X echo "script: '$pr', mtestf1 '$mtestf1'; workdir '$lhost:$workdir'" \
X | $bdd of=$mtestf1 bs=$mtestobs conv=sync 2> /dev/null
X echo "script: '$pr', mtestf2 '$mtestf2'; workdir '$lhost:$workdir'" \
X | $bdd of=$mtestf2 bs=$mtestobs conv=sync 2> /dev/null
X;;
Xesac
X
X## Third, if we're doing a get/verify, make sure we can read the rewind device
X## (But check other stuff if $mtype is dir or file)
Xwhile test $demo = false -a $check = true -a \( $mode = get -o $mode = verify \) -a $mtype != null ; do
X # if we're reading from file or directory, we have simple tests;
X # if it's null we don't do anything
X case "$mtype" in
X dir)
X if test ! -d $diskfile ; then
X if test $? -ne 0 ; then
X echo "$pr: Cannot read $mtype $diskfile. Quitting."
X exit 1
X fi
X fi
X ;;
X file)
X if test ! -f $diskfile ; then
X if test $? -ne 0 ; then
X echo "$pr: Cannot read $mtype $diskfile. Quitting."
X exit 1
X fi
X fi
X ;;
X esac
X if test -z "$parent" -a $mtype != file -a $mtype != dir ; then
X eval $SHOWDD Make sure we can read the rewind device
X $bdd if=$rewdev of=/dev/null count=1 bs=$mtestibs 2> err.dd
X if test $? -eq 0 ; then
X rm -f err.dd
X else
X cat err.dd
X eval "$CHKMREAD"
X eval "$EXITQ"
X continue
X fi
X fi
X break
Xdone
X
X## Fourth, if we're making a backup or doing a devcheck, we check both
X## the rewind and norewind device names from $devdata. This is so important
X## that we do it whether or not we'll end up using the norewind device.
X## (But check other stuff if $mtype is dir, file, or null)
X#
X# Later on, if it's a cart and we're using cpio, we'll need to test the
X# cart to make sure that we can write large amounts of data to it.
X# Oddly enough, low density (low "ftpi" (frame tracks per inch)) carts
X# work with high density drives if we're only writing a block or two.
X# This is strange, but I've tested it pretty extensively in 150M and
X# 120M cartridge drives using carts of 8000, 10000, and 12500 ftpi.
X# We only have to worry about this if it's cpio because BSD dump takes
X# care of this kind of problem for us.
X#
X# We only intend to do this code once, but we have to use a "while"
X# so we can "break" out of it if $rewdev is wrong.
Xwhile test $demo = false -a $check = true -a \( $mode = full -o $mode = incr -o $mode = tincr -o $mode = devcheck \) ; do
X
X # if we're writing to a file or directory, we have simple tests;
X # if it's null we don't do anything
X case "$mtype" in
X dir)
X if test ! -d $diskfile ; then
X mkdir $diskfile
X if test $? -ne 0 ; then
X echo "$pr: Cannot create $mtype $diskfile. Quitting."
X exit 1
X fi
X fi
X break
X ;;
X file)
X if test $diskfile != "-" -a ! -f $diskfile ; then
X echo "$pr: can we create $diskfile" > $diskfile
X if test $? -ne 0 ; then
X echo "$pr: Cannot create $mtype $diskfile. Quitting."
X exit 1
X fi
X fi
X break
X ;;
X null)
X break
X ;;
X esac
X
X ## First, make sure we can write to the rewind device - the operator may
X ## have forgotten to put the drive on line or left off the write ring.
X $rm -f $mtestf3 # just to make sure
X while : ; do
X # write 1st file, rewind media
X eval $SHOWDD Make sure we can write to the rewind device
X $bdd if=$mtestf1 of=$rewdev bs=$mtestobs 2> err.dd
X bddstat=$?
X recout=` egrep records err.dd | awk 'NR == 2 {print $1}'`
X if test $bddstat -eq 0 -a "$recout" = "1+0" ; then
X rm -f err.dd
X break
X else
X cat err.dd
X eval "$CHKMWRITE"
X eval "$EXITQ"
X fi
X done
X
X ## Second, make sure the rewind device name is really a rewind device.
X # Write 1st file, rewind media, then read it back out. The count=40
X # prevents humungous read from accidental norewind device, which
X # could mean writing to and possibly filling up the filesystem
X # containing $mtestf3.
X eval $SHOWDD Make sure rewind device name really does a rewind
X $bdd if=$mtestf1 of=$rewdev bs=$mtestobs 2> /dev/null
X $bdd if=$rewdev of=$mtestf3 bs=$mtestobs count=40 2> err.dd
X bddstat=$?
X recin=` egrep records err.dd | awk 'NR == 1 {print $1}'`
X # if we got a bad read from the media
X if test $bddstat -ne 0 -o "$recin" != "1+0" ; then
X
X exec 1> $failrpt
X echo "$pr: Expected '$bdd' status '0'; got status '$bddstat'."
X echo "$pr: Expected '1+0 records in/out'; got:"
X cat err.dd
X echo "$pr: This may be a real HARDWARE problem."
X exec 1>&9
X cat $failrpt
X eval "$CHKMREAD"
X echo "$pr: Quitting."
X exit 1
X fi
X rm -f err.dd
X # input should be identical to output
X if test `$cmp $mtestf1 $mtestf3 2>&1 | wc -l` -gt 0 ; then
X badrewdev=true
X $cmp $mtestf1 $mtestf3 >> $failrpt
X echo "$pr: '$mhost:$rewdev' is supposed to be a rewind device but is NOT." >> $failrpt
X break # can't reliably test the norewind device now
X fi
X
X ## Third and last, verify the norewind device is a norewind device.
X # The structure here is OK since we just verified the rewind device.
X # put first file on media, don't rewind
X # put different file on media, rewind it
X # read first file back out, rewind media
X eval $SHOWDD Make sure norewind device name really does not rewind
X $bdd if=$mtestf1 of=$norewdev bs=$mtestobs 2> /dev/null
X $bdd if=$mtestf2 of=$rewdev bs=$mtestobs 2> /dev/null
X $bdd if=$rewdev of=$mtestf3 bs=$mtestobs 2> /dev/null
X # input should be identical to output
X if test `$cmp $mtestf1 $mtestf3 2>&1 | wc -l` -gt 0 ; then
X badnorewdev=true
X $cmp $mtestf1 $mtestf3 >> $failrpt
X # check for possible reasons
X if test `$cmp $mtestf2 $mtestf3 2>&1 | wc -l` -eq 0 ; then
X echo "$pr: GACK! The so-called norewind device actually rewinds the $media!" >> $failrpt
X fi
X echo "$pr: '$mhost:$norewdev' is supposed to be a norewind device but is NOT." >> $failrpt
X fi
X
X break # defense! we only want to do this code once.
Xdone
X
X## Fifth - evaluate and report results of device testing
X# (note: keep media test files for later)
Xif test "$badrewdev" = true -o "$badnorewdev" = true ; then
X echo "$pr: Media data file '$devdata' is wrong." >> $failrpt
X echo "$pr: Notify a UNIX System Administrator IMMEDIATELY ! ! !" >> $failrpt
X cat $failrpt
X exit 1
Xfi
X
X## Sixth and last - clean up and quit if we were asked only to check the media
Xcase $mode in
Xdevcheck)
X echo "$pr devcheck: The rewind device: '$rewdev' and"
X echo "$pr devcheck: the norewind device: '$norewdev'"
X echo "$pr devcheck: on media host $mhost PASS the devcheck tests."
X exit 0
X;;
Xesac
X
X###############################################################################
X
X## start the report
Xcd $workdir
Xexec 1> $report
Xecho "#Invocation: $pr $cmdargs"
Xecho "#Version: $version"
Xecho "#Start time: $date"
Xecho "#Workdir: $wdir"
Xecho "#Dev Data: $devdata"
Xecho "#lhost mhost mode media mdevbase multi OPER voln hfstat"
X# print variables (note $hfstat isn't set since the header file hasn't
X# been put on the media yet)
Xecho "$lhost $mhost $mode $media $mdevbase $multi $OPER $voln ${hfstat-NA}"
Xexec 1>&9
X
X## OK! Ready to *make* the backup or *get/verify* files from the backup!
Xcase $mode in
Xfull|incr|tincr)
X
X # show operator our assumptions
X echo ""
X echo $pr:
X echo "backup media media media backup"
X echo "level host alias workdir device program"
X echo "------- ------- ------- ------------- --------------- -----------"
X echo "$mode $mhost $media $wdir $mdevbase $bprog"
X echo ""
X echo "$pr: About to backup:"
X case $multi$fsbkp in
X *false) echo "$devlist (directory, not a filesystem)" ;;
X true*) awk ' {print $1 " (" $NF ")" }' $dfout ;;
X *) awk '$1 == "'$devlist'" {print $1 " (" $NF ")" }' $dfout ;;
X esac
X echo ""
X
X # later on, if we're doing a cpio onedisk backup to a cart, we'll
X # need this $mtestf4 for every cart
X if test $bprog = cpio -a $mdev = $rewdev -a $mtype = cart ; then
X # create 150k test file - do it in 50k
X # chunks because many machines can't
X # do it all at once
X eval $SHOWDD Create 150k test file for carts
X echo "$pr: $workdir 150k $mtestf4" | $bdd of=$mtestf4 bs=50k conv=sync 2> err.dd
X echo "$pr: $workdir 150k $mtestf4" | $bdd of=$mtestf4 bs=50k conv=sync seek=1 2> err.dd
X echo "$pr: $workdir 150k $mtestf4" | $bdd of=$mtestf4 bs=50k conv=sync seek=2 2> err.dd
X # show user if it's not 150k
X $ls -l $mtestf4 | grep -v ' 153600 '
X fi
X
X ## do the backup
X fsnn=00 # 2-digit filesystem number
X # put the list of known problems into $problist and
X # list of known not_problems into $falseprob for later check
X echo "$KNOWNPROBS" > $problist
X echo "$KNOWNFALSEPROBS" > $falseprob
X # start the exit status list
X echo '#bstat devname fsname known_errors' > $statlist
X # if multi-volume backup or it's a onedisk but we're putting on a
X # header anyway, put tar/cpio header file onto media;
X # the header is tar if we're using dump, cpio if we're using cpio;
X # the header includes $dfout, $report, all scripts, and any/all
X # config files ($hdir/bkp.media overrides $DTGT/bkp.media)
X #if test $multi = true -o $header = true ; then
X if test $multi = true ; then
X # put required files in $workdir
X # we must make sure we have local paths, not absolute paths
X x="$dfout $report $pr `basename $bdd` bkp.media"
X ln ../$pr .
X cp $bdd .
X cp $devdata bkp.media
X case "$multitype" in
X list)
X # so we always have the standard name 'bkp.listf'
X bnlistf=`basename $listf`
X cp $listf $bnlistf
X ln $bnlistf bkp.listf
X ;;
X esac
X cp ../bkp.donot . 2> /dev/null && x="$x bkp.donot"
X cp ../bkp.host . 2> /dev/null && x="$x bkp.host"
X test -f bkp.listed && x="$x bkp.listed"
X test -f bkp.listf && x="$x bkp.listf"
X cp ../bkp.media . 2> /dev/null && x="$x bkp.media"
X cp ../bkp.nofm . 2> /dev/null && x="$x bkp.nofm"
X cp $DTGT/bkp.site . 2> /dev/null && x="$x bkp.site"
X test -n "$bnlistf" && x="$x $bnlistf"
X # added because NonStop-UX and other OS have multiple
X # filesystem types and it's often documented in thes files
X for f in $fstablist ; do
X cp /etc/$f . 2> /dev/null && x="$x $f"
X done
X headlist="$x"
X if test $bprog = cpio ; then
X echo "$pr: ================================backup>>> alldisks_header (cpio)"
X else
X echo "$pr: ================================backup>>> alldisks_header (tar)"
X fi
X # make absolutely sure the header gets on the media - don't
X # continue until it does
X
X eval "$MDEV"
X while : ; do
X # each case has 3 lines
X # 1) echo commented command line to $report
X # 2) echo command line to screen
X # 3) do or "demo" the command (prettified by ";:")
X eval $SHOWDD Put alldisks header on $mhost:$media using $bdd
X case $bprog$demo in
X cpiotrue)
X echo \#find $headlist -print "| { cpio -oc$ckey $copt" '2> err.head ; echo $? > stat.head ; } | {' $bdd of=$mdev obs=5k 2> err.dd '; echo $? > stat.dd ; }' >> $report
X echo find $headlist -print "| { cpio -oc$ckey $copt" '2> err.head ; echo $? > stat.head ; } | {' $bdd of=$mdev obs=5k 2> err.dd '; echo $? > stat.dd ; }'
X echo $pr: demo find $headlist -print "| { cpio -oc$ckey $copt" '2> err.head ; echo $? > stat.head ; } | {' $bdd of=$mdev obs=5k 2> err.dd '; echo $? > stat.dd ; }'
X ;;
X cpio*)
X echo \#find $headlist -print "| { cpio -oc$ckey $copt" '2> err.head ; echo $? > stat.head ; } | {' $bdd of=$mdev obs=5k 2> err.dd '; echo $? > stat.dd ; }' >> $report
X echo find $headlist -print "| { cpio -oc$ckey $copt" '2> err.head ; echo $? > stat.head ; } | {' $bdd of=$mdev obs=5k 2> err.dd '; echo $? > stat.dd ; }'
X : ; find $headlist -print | { cpio -oc$ckey $copt 2> err.head ; echo $? > stat.head ; } | { $bdd of=$mdev obs=5k 2> err.dd ; echo $? > stat.dd ; }
X ;;
X *dump*true)
X echo \#\{ tar cfb - 20 $headlist 2> err.head '; echo $? > stat.head ; } | {' $bdd of=$mdev obs=10k 2> err.dd '; echo $? > stat.dd ; }' >> $report
X echo \{ tar cfb - 20 $headlist 2> err.head '; echo $? > stat.head ; } | {' $bdd of=$mdev obs=10k 2> err.dd '; echo $? > stat.dd ; }'
X echo $pr: demo \{ tar cfb - 20 $headlist 2> err.head '; echo $? > stat.head ; } | {' $bdd of=$mdev obs=10k 2> err.dd '; echo $? > stat.dd ; }'
X ;;
X *dump*)
X #echo \#\{ tar cfb - 20 $headlist 2> err.head '; echo $? > stat.head ; } | {' $bdd of=$mdev obs=10k 2> err.dd '; echo $? > stat.dd ; }' >> $report
X #echo \{ tar cfb - 20 $headlist 2> err.head '; echo $? > stat.head ; } | {' $bdd of=$mdev obs=10k 2> err.dd '; echo $? > stat.dd ; }'
X #: ; { tar cfb - 20 $headlist 2> err.head ; echo $? > stat.head ; } | { $bdd of=$mdev obs=10k 2> err.dd ; echo $? > stat.dd ; }
X echo \#\{ tar cfb $tarhead 20 $headlist 2> err.head '; echo $? > stat.head ; } ; {' cat $tarhead | $bdd of=$mdev obs=10k 2> err.dd '; echo $? > stat.dd ; }' >> $report
X echo \{ tar cfb $tarhead 20 $headlist 2> err.head '; echo $? > stat.head ; } ; {' cat $tarhead | $bdd of=$mdev obs=10k 2> err.dd '; echo $? > stat.dd ; }'
X : ; { tar cfb $tarhead 20 $headlist 2> err.head ; echo $? > stat.head ; } ; { cat $tarhead | $bdd of=$mdev obs=10k 2> err.dd ; echo $? > stat.dd ; }
X# { tar cfb $tarfile 20 $headlist 2> err.head ; echo $? > stat.head ; } ; { $bdd if=$tarfile of=$mdev obs=20b 2> err.dd ; echo $? > stat.dd ; }
X ;;
X esac
X cat err.head err.dd | tee -a $report
X hfstat=`cat stat.head``cat stat.dd`
X # if the disk holding $bhdir fills up, $hfstat could
X # be a null string, and "sh" treats a null string
X # as numerically equal to zero, so test carefully
X if test -z "$hfstat" ; then
X echo "$pr: The disk holding $bhdir"
X echo "$pr: is probably full."
X df $bhdir # works on most newer UNIX's
X echo "$pr: Please consult a UNIX sysadmin."
X echo "$pr: Quitting."
X exit 1
X # else if $hfstat is "00" we are ok
X elif test "$hfstat" -eq 0 ; then
X break
X # else we've got a problem
X else
X echo "$pr: Something went wrong with putting the $headprog header archive"
X echo "$pr: on the $media. Check:"
X eval "$CHKMWRITE"
X eval "$EXITQ"
X fi
X done
X fi
X
X # put backups on tape, and keep track of which filesystems are on
X # which tapes
X voln=1 # volume number of cart/dat/tape/tk/video
X sumrecin=0 # sum of dd output records for cpio archives
X obleft=$maxocount # number of output blocks left on media
X nearend=false # are we so near the end of the media that
X # we have to change tapes
X echo $sumrecin $obleft > $pass # initialize $pass
X /bin/rm -f $firstblist
X for fsdev in $devlist ; do
X eval "$FSNNPLUS1"
X eval "$MDEV"
X case $fsbkp in
X # occasionally we back up a directory
X false)
X fs=$fsdev
X ;;
X # but normally we're backing up a filesystem
X *)
X # get $fs from $dft2 - if we're backing up a filesystem
X # listed in $nobkp, $fs will be in $dft2 but not $dfout
X fs=`egrep "^$fsdev[ ]" $dft2 | awk '{print $NF}'`
X ;;
X esac
X echo "$pr: ================================backup>>> $fs"
X
X # if we're using some version of dump
X case $bprog in
X *dump*)
X # special code for NonStop-UX4.0 which has both
X # vxfs and ufs filesystem types: choose which dump
X # to use ufsdump or vxdump.
X case "$OS_S$OSLEVEL_S" in
X NonStop-UX4.0)
X fstype=`awk '/^#/ {next} ; $3 == "'$fs'" {print $4}' /etc/vfstab`
X case $fstype in
X ufs) bprog=$DUMP_P ;;
X vxfs) bprog=/sbin/vxdump ;;
X esac
X ;;
X esac
X # echo the backup command - trickier than you'd think!!
X # we need the x=`echo ...` to get the desired evaluation
X # the first sed expression compresses whitespace to one
X # space, the second one puts a backquote in front
X # of every single shell-special character we might see
X # in $bcmd, the third puts single quotes around $! in
X # case we are dumping to standard out
X x=`echo $bcmd | sed -e 's/[ ][ ]*/ /g' -e 's/[&;|>]/\\\\&/g' -e "s/\$\!/'\$\!'/"`
X eval echo "$pr: $x"
X eval echo "\#bcmd: $x" \>\> $report
X
X # if we're rdumping to a disk file on another host
X # then make sure it exists, since SunOS, Solaris,
X # and perhaps other rdump's seem to require the
X # file to exist before it can open the file for
X # writing the dump archive.
X case $bprog$mtype in
X *dump*file|*dump*dir)
X if test $mhost != $lhost ; then
X $rsh $mhost touch $mdev
X fi
X ;;
X esac
X
X # now do it for real (but sync twice first just in case)
X sync ; sync
X # if we were dumping to a tape or diskfile
X if test -z "$diskfile" -o "$diskfile" != "-" ; then
X eval $bcmd # do dump in forground
X eval bstat$fsnn=$? # get exit status
X # else we're dumping to standard out
X else
X eval $bcmd # do dump in background
X wait $bpid # wait for it
X eval bstat$fsnn=$? # exit status from wait
X echo $epre "$pr: Killing 'tail' on b.$fsnn.out: "$esuf
X kill -9 $tailpid 2> /dev/null # kill tail
X fi
X # If we couldn't read/write dumpdates, then fix,
X # report, and break out of filesystem loop. If
X # it happened when trying to update dumpdates,
X # this is the best we can do because dump has
X # already written the entire archive before
X # trying the update. We might handle this earlier
X # with $HACK4HPUX8, but probably not.
X updateprob=`egrep '/etc/dumpdates: Permission denied' b.$fsnn.out`
X if test -n "$updateprob" ; then
X echo "$pr: There were permissions problems reading or writing /etc/dumpdates."
X echo "$pr: Permissions were (using 'ls -l /etc/dumpdates'):"
X echo "$pr: `ls -l$LSGROUP_K /etc/dumpdates`" | tee -a $workdir/$report
X chmod 664 /etc/dumpdates
X chgrp operator /etc/dumpdates
X echo "$pr: Fixed permissions are now:"
X echo "$pr: `ls -l$LSGROUP_K /etc/dumpdates`" | tee -a $workdir/$report
X echo "$pr: Try the backup again - it should work next time."
X # break out of loop so we can do postprocessing
X break
X fi
X # If we couldn't read the actual device we're dumping,
X # then fix and try the dump again. This strategy works
X # because we know dump hasn't moved the tape.
X permprob=`egrep '[cC]annot open' b.$fsnn.out`
X if test -n "$permprob" ; then
X # actual device dumped is often raw device, but
X # can be block device under some configurations
X # like DGUX with disk-spanning filesystems
X actualdev=`echo $permprob | awk '{print $NF}'`
X if test -n "`echo $actualdev | egrep '^/dev/[-a-zA-Z0-9_:/]*$'`" ; then
X echo "$pr: NOTE: There were permissions problems reading the actual device."
X echo "$pr: Permissions were (using 'ls -l$LSGROUP_K $actualdev'):"
X echo "$pr: `ls -l$LSGROUP_K $actualdev`" | tee -a $workdir/$report
X chgrp operator $actualdev
X chmod g+r $actualdev
X echo "$pr: Fixed permissions are now:"
X echo "$pr: `ls -l$LSGROUP_K $actualdev`" | tee -a $workdir/$report
X echo "$pr: Trying the dump again."
X mv b.$fsnn.out b.$fsnn.out.prob
X sync ; sync
X eval $bcmd
X eval bstat$fsnn=$?
X fi
X fi
X # else we're using cpio - much trickier than dump/rdump
X ;;
X cpio)
X # There's a ton of stuff to do here as a frontend
X # to cpio. As much as possible, we basically have
X # to do everything that BSD dump does.
X
X ## The first BIG problem is to generate a list of files
X # for $fs *only*. This list has to exclude any
X # filesystem mounted on top of the one we're backing
X # up, e.g. we exclude "/usr" if we're backing up "/".
X # We also exclude anything in $nobkp if it exists.
X # Once the list is generated we can basically do:
X # "cd $fs ; find $top $stayinfs $newer | fgrep -v -f $filter"
X # This requires adding a leading "X" and trailing "/" in
X # each dir/fs name.
X
X # First, build $filter to screen mounted subdirs
X # and anything relevant in $nobkp from list.
X # We're trying to create list of *excluded* stuff here.
X # Use $dft2, not $dfout, since it has all filesystems.
X cd $workdir
X case "$fs$fsbkp" in
X # we're backing up the root filesystem
X /true)
X # egrep -v filters root, awk appends "/"
X egrep -v "^$fsdev[ ]" $dft2 \
X | awk '{print $NF"/"}' > $filtert1
X if test -r $nobkp ; then
X cat $nobkp >> $filtert1
X fi
X # AIX 3.2 cpio does "exit 2" if it sees devices,
X # AIX 3.[01] cpio does "exit 0" but complains
X # if it sees devices,
X case "$OS_S" in
X AIX) echo /dev >> $filtert1 ;;
X esac
X # sed substitutes leading "X" and trailing "/"
X sed -e 's,^/,X,' -e 's,[^/]$,&/,' $filtert1 > $filter
X ;;
X # we're backing up some other filesystem
X *true)
X # awk appends "/", egrep matches for $fs,
X # next egrep -v filters $fs itself
X # Second egrep can't be grep because
X # a bug in AIX 2.2.1 grep -v yields a
X # newline when it's input is empty!
X # Bummer because Ultrix 2.0 egrep -v
X # has the same bug.
X awk '{print $NF"/"}' $dft2 \
X | egrep "^${fs}/" \
X | egrep -v "^${fs}/$" > $filtert1
X if test -r $nobkp ; then
X # sed appends "/", egrep matches $fs
X # egrep -v filters $fs itself
X sed -e 's,$,/,' $nobkp \
X | egrep "^$fs/" \
X | egrep -v "^$fs/$" >> $filtert1
X fi
X # sed substitutes "X" for $fs"/"
X sed -e "s,^$fs/,X," $filtert1 > $filter
X ;;
X # $fs isn't a filesystem so create an empty $filter
X *)
X > $filter
X ;;
X esac
X
X # Second, put list of files at the top level of $fs
X # in $top
X #
X # sneaky: .?* matches because ".." always exists
X # Pray there aren't too many files at top level of $fs.
X # (This could be made slightly more efficient, but
X # save that for later.)
X # Anyway, take our first cut at $top:
X top=`cd $fs ; echo .?* * | sed -e 's/\.\.//'`
X # if $filter has real stuff in it then use it to
X # strip mounted filesystems from $top.
X if test -s $filter ; then
X # Create $topfilter: the sed removes two-plus
X # level subdirs (with two slashes) since it's
X # too hard to deal with filtering those,
X # and changes trailing "/" to "X" for fgrep
X # which doesn't support metacharacters
X sed -e '/\/.*\//d' -e 's,^.\(.*\)/$,X\1X,' $filter > $topfilter
X # Needed the following "if test ..." to
X # deal with HP-UX's fgrep -v, which fails if
X # handed a null filter file. But what the
X # heck, this is smarter anyway.
X if test -s $topfilter ; then
X # "for" echo's X${i}X thru fgrep filter
X # thru sed to strip "X"s through
X # awk to merge back into one line
X for i in $top ; do echo X${i}X ; done \
X | fgrep -v -f $topfilter \
X | sed -e 's/^X\(.*\)X$/\1/' \
X | awk '{printf "%s ", $1}' > $toplist
X top=`cat $toplist`
X fi
X fi
X
X # Third, start $flist (list of files to be backed up).
X # Begin with hard-coded paths for $report and $flist;
X # we have to do this for ease of cpio file restoration.
X # Unfortunately, this means that we can only run one
X # backup at a time.
X echo "$pr: generating list of files to put in cpio archive for $fs"
X echo /usr/tmp/$report > $flist
X echo /usr/tmp/$flist >> $flist
X
X # Fourth, put list of files we're backing up into $flist
X # If we're doing an incremental of $fs, find out when
X # it's last successful full backup was.
X newer=''
X if test $mode = incr ; then
X lastfull=`grep '^full[ ].*[ ]'$fs'[ ]*$' $bdatef | awk '{print $2}'`
X if test -n "$lastfull" ; then
X touch $lastfull $touchf
X if test $? -ne 0 -o ! -f $touchf ; then
X echo "$pr: Something went wrong with creating the touch file. Quitting."
X exit 1
X fi
X newer="-newer $touchf"
X fi
X fi
X # try to force "find" to stay in the filesystem
X # use $FINDXDEV_S if we have it, else try "FINDFSTYPE_S"
X if test -n "$FINDXDEV_S" ; then
X stayinfs=$FINDXDEV_S
X elif test -n "$FINDFSTYPE_S" ; then
X stayinfs=$FINDFSTYPE_S
X else
X stayinfs=''
X fi
X cd $fs
X # get the start date of this backup
X # we'd like datecpio to be able to set to the nearest
X # second, unfortunately although date can report it
X # that way Sys V touch can't set it that way. Drat.
X datecpio=`date '+%m%d%H%M%y%t%a %h %d %H:%M 19%y'`
X # ideally we'd sort the output from find, but it
X # could be too big for sort to handle which would
X # be a bummer.
X # At last, we can use $top and $filter to generate
X # flist:
X if test -s $workdir/$filter ; then
X # sed's add and strip an "X" for fgrep filter
X find $top $stayinfs $newer -print | sed -e 's/^/X/' | fgrep -v -f $workdir/$filter | sed -e 's/^X//' >> $workdir/$flist
X else
X find $top $stayinfs $newer -print >> $workdir/$flist
X fi
X rm -f $touchf
X
X # Fifth and last, put $report and $flist into /usr/tmp
X # where we're planning to back them up *first*!
X # just in case we can save some space, try to hardlink
X # them to /usr/tmp - don't want to archive a symlink!
X # Remove them from /usr/tmp to prep for link attempt.
X echo "#cpio archive of '$fs' filesystem" >> $workdir/$report
X rm -f /usr/tmp/$flist /usr/tmp/$report
X ln $workdir/$flist $workdir/$report /usr/tmp 2> /dev/null \
X || cp $workdir/$flist $workdir/$report /usr/tmp
X # need to do this because /usr/tmp may not have enough room for $flist
X if test $? -ne 0 ; then
X echo "$pr: 'cp $workdir/$flist /usr/tmp' failed" | tee -a $workdir/b.$fsnn.out
X echo "$pr: Backup of '$fs' ABORTED, need more room in /usr/tmp." | tee -a $workdir/$b.$fsnn.out
X break
X fi
X
X ## The second BIG problem is that our backup may not
X # fit on the media. So we have to pipe the cpio into
X # a while loop which manages the process of changing
X # tapes and writing the archive onto the media.
X fsvoln=1 # volume number for cpio archive of *this* filesystem
X recinint= # dd records in (integer truncation)
X recoutint= # dd records out (integer truncation)
X # get info from initialization or "| while" loop
X set `cat $pass`
X sumrecin=$1
X obleft=$2
X ## if earlier cpio archives filled up most of the
X # current volume, change the media.
X # "100" is an arbitrary small number
X if test $obleft -lt 100 ; then
X # we use nearend later when tracking the
X # number of volumes in the backup
X nearend=true
X voln=`expr $voln + 1`
X sumrecin=0
X obleft=$maxocount
X eval "$REW"
X echo "$pr: Please put in $media volume $voln"
X eval "$BREAKQ"
X fi
X cd $fs
X # have to use a file to record cpio and dd exit status
X # This is weird: "{ date ; x=$? ; } ; echo $x" works
X # but "{ date ; x=$? ; } | cat ; echo $x" fails
X # We'll break out of the while when we're done or if
X # the user says to quit
X echo "$pr: dd'ing archive of '$fs' onto filesystem volume $fsvoln"
X echo "$pr: { cpio -oc$ckey < /usr/tmp/$flist 2> $workdir/err.cpio ; echo \$? > $workdir/stat.cpio ; } \\"
X echo "$pr: | while : ; do"
X { cpio -oc$ckey < /usr/tmp/$flist 2> $workdir/err.cpio ; echo $? > $workdir/stat.cpio ; } \
X | while : ; do
X cd $workdir
X ## but do some initial media checking first
X # if we're not an alldisks then it's OK for us
X # to check media for write protection or
X # other problems.
X # If we *are* doing an alldisks, it would still
X # be OK to check if we're at the beginning
X # of a tape, but since I don't know what
X # happens when cpio hits EOT there's no way
X # to test for this (yet).
X if test $mdev = $rewdev ; then
X eval $SHOWDD Make sure we can write to this volume
X $bdd if=$mtestf1 bs=$obs of=$rewdev count=1 2> err.dd
X if test $? -ne 0 ; then
X cat err.dd | tee -a b.$fsnn.out
X eval "$CHKMWRITE"
X eval "$BREAKQ"
X # continue if we don't break out
X continue
X fi
X fi
X
X # if it's a cart, test it for density (ftpi)
X # compatibility. We do this by trying to write
X # thirty blocks to the cart. If this fails
X # we have a problem. Empirical tests show that
X # it will fail within eighteen blocks (and
X # more often with fourteen or even seven),
X # but we'll write thirty just to make sure.
X # Also, only do this if it's a onedisk.
X # We may never get here but if we do this
X # test is very important.
X if test $mtype = cart -a $mdev = $rewdev ; then
X # write it to cart (use conv=sync in
X # case we fill up /tmp so it's not 150k)
X eval $SHOWDD Try to write 150k test file to $media to check density
X $bdd if=$mtestf4 bs=$obs of=$rewdev count=30 conv=sync 2> err.dd
X if test $? -ne 0 ; then
X cat err.dd | tee -a b.$fsnn.out
X echo "$pr: Your $mtype is incompatible with"
X echo "$pr: the density of drive $mhost:$media."
X echo "$pr: Replace your $mtype with a 12,500ftpi $mtype."
X eval "$BREAKQ"
X # continue if we don't break out
X continue
X fi
X fi
X
X ## ok, now we're finally putting the cpio
X ## archive on the media
X icount=`expr $obleft \* $obs / $ibs`
X # if we're writing to a local archive
X if test $MHOST = $LHOST ; then
X echo "$pr: $bdd of=$mdev ibs=$ibs obs=$obs count=$icount 2> err.dd"
X eval $SHOWDD Putting archive on this volume
X $bdd of=$mdev ibs=$ibs obs=$obs count=$icount 2> err.dd
X bddstat=$?
X # else we're doing backup over the net
X # we have to split up archive into 1k blocks
X # before sending it over the net
X else
X realmhost=$MHOST
X eval $SHOWDD Putting archive on this volume,
X eval $SHOWDD using one to split and the other to join
X echo "$pr: { MHOST=$LHOST ; $bdd ibs=5k obs=1k count=$icount 2> err.split ; echo \$? > stat.split ; } \\"
X echo "$pr: | { MHOST=$realmhost ; $bdd of=$mdev ibs=1k obs=$obs 2> err.join ; echo \$? > stat.join ; }"
X { MHOST=$LHOST ; $bdd ibs=5k obs=1k count=$icount 2> err.split ; echo $? > stat.split ; } \
X | { MHOST=$realmhost ; $bdd of=$mdev ibs=1k obs=$obs 2> err.join ; echo $? > stat.join ; }
X splitstat=`cat stat.split`
X joinstat=`cat stat.join`
X bddstat=$splitstat$joinstat
X # try to ignore data from split
X grep 'records in' err.split > err.dd
X grep 'records out' err.join >> err.dd
X fi
X # pass info to parent shell
X echo $bddstat > stat.dd
X cat err.dd >> b.$fsnn.out
X echo $fs volume $fsvoln dd status: $bddstat >> b.$fsnn.out
X # the semicolon in the awk shouldn't be needed,
X # but the AIX 3.1 version requires it
X recinint=` awk -F+ '$2 ~ /records in/ && $1 ~ /^[0-9][0-9]*$/ {x=$1} ; END {if (x == "") x=0 ; print x}' err.dd`
X recoutint=`awk -F+ '$2 ~ /records out/ && $1 ~ /^[0-9][0-9]*$/ {x=$1} ; END {if (x == "") x=0 ; print x}' err.dd`
X rm -f err.dd
X # if we had a problem or this filesystem is done
X if test $bddstat -ne 0 -o $recoutint -ne $obleft ; then
X sumrecin=`expr $sumrecin + $recinint`
X # if we had a problem with this
X # filesystem, change the media
X if test $bddstat -ne 0 ; then
X obleft=0 # force change
X # else we're ok
X else
X # this is a holdover from when we supported different block sizes,
X # but it could be simplified to:
X # obleft=`expr $maxocount - $sumrecin`
X obleft=`expr $maxocount - \( $sumrecin \* $ibs / $obs \)`
X fi
X # pass info from this "| while"
X # subshell to its parent
X echo $sumrecin $obleft > $pass
X if test $bddstat -eq 0 ; then
X break
X else
X errs='err.split err.join err.dd'
X for err in $errs ; do
X if test -f $err ; then
X echo $err
X cat $err
X fi
X done
X echo "$pr: Backup of '$fs' volume $fsvoln ABORTED." | tee -a b.$fsnn.out
X # exit of "| while" subshell
X # should abort only this
X # filesystem
X exit 1
X fi
X # else we need to change volumes for this filesystem
X else
X sumrecin=0
X obleft=$maxocount
X # pass info from this "| while"
X # subshell to its parent
X echo $sumrecin $obleft > $pass
X # make sure the media gets rewound
X eval "$REW"
X fsvoln=`expr $fsvoln + 1`
X # emulate dump's "Change Volumes" message
X echo "$pr: Change Volumes: put in filesystem '$fs' volume $fsvoln" | tee -a b.$fsnn.out
X eval "$BREAKQ"
X fi
X done
X # end of "| while" loop
X echo "$pr: done"
X # attempt to put cpio archive on $media is done.
X
X ## finish up the work for this cpio archive
X cd $workdir
X # show the user cpio's message if any
X cat err.cpio
X cat err.cpio >> b.$fsnn.out
X cpiostat=`cat stat.cpio`
X # The AIX 3.2 version of cpio has several "features"
X # 1) it won't back up special files or FIFOs (named
X # pipes); when asked to do so it exits with
X # status "2" and says something like:
X # cpio: special file not archived
X # 2) if cpio is asked to back up a file which doesn't
X # exist, it exits with status "2" and says roughly:
X # < tmp/Ex20006 > ?
X # (Other versions of cpio complain about missing files
X # but still exit with status 0.)
X # If these are the only problem in the logs, we can
X # safely "lie" about the exit status of the cpio
X # process. Lines we don't worry about in err.cpio
X # under AIX 3.x look like this:
X # cpio: special file not archived
X # < tmp/Ex20006 > ?
X # cpio: 0511-025 Cannot get information about /ingres/data/default/replicatedb/aaaaabgn.t00
X # 10 blocks
X # Hopefully, err.cpio includes only lines we don't
X # worry about.
X case $OS_S$cpiostat in
X AIX2)
X nlines=`wc -l < err.cpio`
X nottoworry=`egrep -c '^[0-9]* blocks$|special file' err.cpio`
X missingfiles=`awk '
X /^< .+ > \?$/ {print $2}
X /cpio: .*special file <.+> not archived/ {print substr($4,2,length($4)-2)}
X /cpio: .*Cannot get information about / {print $NF}'
X ' err.cpio`
X # make sure any supposedly missing files
X # are really missing
X x=0
X if test -n "$missingfiles" ; then
X cd $fs
X for f in $missingfiles ; do
X test ! -f $f && x=`expr $x + 1`
X done
X cd $workdir
X fi
X nottoworry=`expr $nottoworry + $x`
X if test $nlines -eq $nottoworry ; then
X cpiostat=0
X fi
X ;;
X esac
X echo $fs cpio status: $cpiostat >> b.$fsnn.out
X cpiostat=$cpiostat`cat stat.dd`
X rm -f err.cpio
X eval bstat$fsnn=$cpiostat
X # if cpio is successful and we're updating
X if test $cpiostat -eq 0 -a $update = true ; then
X if test -f $bdatef ; then
X # the sed is a tad clumsy because $fs
X # has slashes in it
X sed -e 's,^'$mode'[ ].*[ ]'$fs'[ ]*$,,' -e '/^[ ]*$/d' $bdatef > $bdatef.tmp
X fi
X echo "$mode $datecpio $fs" >> $bdatef.tmp
X sort +7 -8 +0 -1 $bdatef.tmp > $bdatef
X rm -f $bdatef.tmp
X fi
X ;;
X esac
X
X ## Kevin Malloy put this in - I suppose it's needed
X if test "$OS_S" = dgux ; then
X sleep 60
X fi
X
X ## warn about known problems in this backup (see $KNOWNPROBS
X ## and $KNOWNFALSEPROBS)
X bprogerr="`fgrep -f $problist b.$fsnn.out | fgrep -v -f $falseprob`"
X test -n "$bprogerr" && bprogerr=" $bprogerr"
X eval echo \""\$bstat$fsnn $fsdev $fs$bprogerr"\" \>\> $statlist
X
X ## report on first backups on each tape as we go along
X # We don't care about media write errors on the first
X # backup since that only means the tape was bad or
X # too short. The operator just restarts these, which
X # doesn't add a new volume to the set.
X if test $fsnn -eq 1 ; then
X echo "Volume '$voln': First backup is $fs" >> $firstblist
X # else if this backup is a dump and it got media write errors,
X # then it started in the middle of the media and had to be
X # restarted with a new volume. It's important to get
X # dump's "write error" message right.
X # Some message types (with samples from the listed OS):
X # Pyramid OSx, Ultrix 2.0/3.0, SunOS 3.2:
X # DUMP: Write error on tape 4
X # CCI SysV, Gould UTS 2.1a, Pyramid OSx, Seguent DYNIX:
X # DUMP: Tape write error on tape 1
X # 4.3BSD, CCI BSD, Mt. Xinu BSD, SunOS 4.X:
X # DUMP: Tape write error 277 feet into tape 4
X # DUMP: Write error on tape 1
X # Bull B.O.S. 02.00:
X # FSDUMP: Tape write error 815 feet into tape 1
X # SVR4 variants from NCR and ???:
X # UFSDUMP: ?????
X # SVR4 variants from Pyramid:
X # UFSDUMP: Tape write error: EOT (end of tape) encountered 419 feet into tape1
X # DG/UX says
X # write: No space left on device
X # Error writing tape: Address already in use
X # but notice that it does *not* say "DUMP: whatever".
X # We rely on this.
X # cpio - don't know what this looks like, maybe we avoid anyway
X elif egrep 'DUMP:.* [Ww]rite error:* .* tape *[1-9]' b.$fsnn.out > /dev/null ; then
X voln=`expr $voln + 1`
X echo "Volume '$voln': First backup is $fs" >> $firstblist
X # else we are doing a cpio alldisks backup and we got so close
X # to the end of the media that we had to prompt for a new one
X # before this cpio archive could start
X elif test "$nearend" = true ; then
X echo "Volume '$voln': First backup is $fs" >> $firstblist
X nearend=false
X fi
X # else do nothing - this backup started in the middle
X # of the media but did not run out room.
X
X ## Did this backup take more than one volume? In other
X ## words, was it continued onto the next tape?
X # This can happen if:
X # a) we're doing a onedisk backup that won't fit on one tape
X # b) we're doing an alldisks backup using cpio
X # c) we're doing an alldisks backup using a version of dump
X # that knows how to handle EOT (e.g. DG's "dump2" and
X # Solaris 2.X "ufsdump")
X # d) we're doing an incremental alldisks backup, and an
X # incremental of one of the filesystems is too big to fit
X # on one tape
X #
X # The key is to look for the following messages in
X # the b.$fsnn.out file:
X # This alldisks script says "Change Volumes",
X # SunOS 4.0.3 and Solaris 2.2 say "Change Volumes" too,
X # OSF from DEC says "Change Cartridges",
X # DG's "dump2" says "dump2: Time to change tapes." - dump2
X # does this even when it hits EOT on a video drive when using
X # using the -M option - gads!
X # Solaris 2.2 ufsdump says:
X # DUMP: End-of-tape detected
X # DUMP: Change Volumes: Mount volume #N
X # All others say "Change Tapes." when it's time to start the
X # next tape.
X #
X # Unfortunately, some versions of dump say "Change Tapes"
X # when they are rewriting the volume, too:
X # ULTRIX V3.1 dump gets a -SIGTERM, it says
X # DUMP: SIGTERM() try rewriting
X # DUMP: Rewriting attempted as response to unknown signal.
X # DUMP: Change Tapes: Mount tape #1
X #
X # Pyramid's OSx "dump" says:
X # DUMP: Tape write error on tape 1
X # .....
X # DUMP: replace the faulty tape with a new one;
X # DUMP: this dump volume will be rewritten.
X # DUMP: Change Tapes: Mount tape #1
X #
X # Pyramid's SVR4 OSx "ufsdump" says:
X # UFSDUMP: Tape write error: EOT (end of tape) encountered 419 feet into tape1
X # UFSDUMP: NEEDS ATTENTION: Do you want to restart?: ("yes" or "no")
X # UFSDUMP: This tape will rewind. After it is rewound,
X # UFSDUMP: replace the tape and this dump volume will be rewritten,
X # UFSDUMP: or abort and restart the dump, specifying correct tape capacity.
X # UFSDUMP: Closing tape device
X # Note that if it hits premature EOT,
X # it never says "Change Tapes: Mount tape #1",
X # but it does say "Change Tapes: Mount tape #2" (and 3, 4, ...)
X # and it also says "will be rewritten"
X
X # So, we have to get rather tricky.
X x=`egrep -c 'Change Tapes|Change Volumes|Change Cartridges|change tapes' b.$fsnn.out`
X y=`egrep -c 'try rewriting|will be rewritten' b.$fsnn.out`
X z=`egrep -c 'Mount tape #1' b.$fsnn.out`
X if test $y -eq 1 -a $z -eq 0 ; then
X y=0
X fi
X x=`expr $x - $y`
X while test $x -gt 0 ; do
X voln=`expr $voln + 1`
X x=`expr $x - 1`
X echo "Volume '$voln': First backup is $fs (continued)" >> $firstblist
X done
X done
X ## finished with writing backup to media!!
X
X ## do $REW/$OFFLINE as soon as loop finishes so user doesn't
X ## have to wait
X # if we're verifying this backup, rewind now, take it offline
X # after the verify completes
X if test $verifytoo = true ; then
X eval "$REW"
X # else do $OFFLINE work in "/" in case user wants to
X # umount a filesystem we may have just backed up
X # and do it in background so operator doesn't have to wait as long
X else
X cd /
X eval "$OFFLINE" &
X fi
X cd $workdir # now finish up in $workdir
X echo "Volume '$voln': Last volume." >> $firstblist
X rm -f $pass
X
X ## generate report for mailing to $rptto. Report to include:
X # put standard out in $report
X exec 1>> $report
X echo "#lhost mhost mode media mdevbase multi OPER voln hfstat"
X # print variables (if $hfstat is set use it else substitute "NA")
X echo "$lhost $mhost $mode $media $mdevbase $multi $OPER $voln ${hfstat-NA}"
X cat $statlist $firstblist
X if test -s $nobkptmp ; then
X sed -e 's/^\[[ ]*\]\(.*\)\$/#Not backed up: \1/' $nobkptmp
X fi
X echo "#End time: `date`"
X exec 1>&9
X
X ## mail semi-final backup report to $rptto
X eval "$MAILRPT"
X
X ## get operator info - known problems and operator report
X # Give BIG warning message if we had problems (see $KNOWNPROBS)
X # exit status 0 or 1 are OK for dump, but exit status 1 bad for cpio
X awk '
X BEGIN {bprog="'$bprog'"} # get $bprog
X $0 ~ /^\#bstat/ {next} # skip header if any
X NF != 3 {print; next} # we have known problems
X $1 > 1 {print; next} # exit status > 1 always bad
X $1 == 1 && bprog ~ /cpio/ {print; next} # status 1 bad for cpio
X ' $statlist > $statprob
X # if we have no problems, clean up
X if test ! -s $statprob ; then
X rm -f $statprob $probsent
X # else report them if we have to
X else
X # foreach problem filesystem
X grep '^[0-9][0-9]* ' $statprob \
X | while read probstat probfs probdir probdes ; do
X # if the problem has been reported
X if test -f $probsent && egrep " $probfs " $probsent ; then
X : do nothing - we already tried to report it
X # else get ready to report it now
X else
X echo "$wdir $probstat $probfs $probdir $probdes" | tee -a $probsend
X # "DUMP: read error! sector 49310 of /dev/rdsk/c0t1d0s6" (Solaris 2.3 ufsdump got a block read error)
X if egrep "$probfs.*(bread|read error!)" $statprob > /dev/null ; then
X echo "$pr: WARNING! Block read errors found!"
X echo "$pr: Block read errors could mean either:"
X echo "$pr: a) The disk has hard errors - a real bummer."
X echo "$pr: Check system logs with dmesg/messages/uerf/hdelogger/errpt/whatever."
X echo "$pr: b) The disk is ok but the filesystem is corrupt,"
X echo "$pr: e.g. an inode is pointing at impossibly large block numbers."
X echo "$pr: Fix by umount'ing and fsck'ing the filesystem."
X echo "$pr:"
X fi | tee -a $probsend
X fi
X done
X # tell operator
X echo ''
X echo "$pr: WARNING! The backup report shows big PROBLEMS:"
X cat $statprob
X echo "$pr: Please REPORT THIS to na-system !!!"
X eval "$EXITQ"
X fi
X
X ## finish report at last
X if test -f $failrpt ; then
X exec 1>> $report
X echo "Operator '$OPER' reported that this backup failed for the following reason:"
X cat $failrpt
X echo "" # make sure there's a newline
X echo "End of Operator failure report."
X exec 1>&9
X fi
X # report generation done, so put standard out back on the tty
X
X ## finish
X if test $verifytoo != true ; then
X echo "$pr: This backup is done."
X else
X echo "$pr: This backup is done; will start 'verifytoo'."
X # if we just made a multi-volume tape set, try to take the
X # tape offline and then tell the operator to put the
X # first tape in the drive
X case $mistape$voln in
X true[2-9]|true[1-9][0-9])
X eval "$OFFLINE"
X echo "$pr: This backup took $voln tapes."
X echo "$pr: Before we begin the 'verifytoo', please put"
X echo "$pr: volume '1' of this alldisks tape set into $media."
X eval "$MREADYQ"
X ;;
X esac
X extravol=`expr $voln - 1`
X case "$multi" in
X false) vfsarg=onedisk ;;
X true) vfsarg=alldisks ;;
X esac
X vcmd="./$pr verify $vfsarg $marg $diskfile $extravol $wdir $childargs nomail"
X echo ''
X echo $vcmd | tee -a $report
X echo ''
X cd $hdir
X $vcmd
X cd $workdir
X echo "#VerToo end: `date`" >> $report
X # take it offline in background so user doesn't have to wait
X eval "$OFFLINE" &
X fi
X;;
X
X## do get or verify if that's what we're doing
Xget|verify)
X
X ## onvol by definition is "1" if it's a onedisk backup, even
X ## if the backup spanned tapes (as in a 9track backup);
X ## otherwise we set it later
X if test $mode = verify -a $getmode = onedisk ; then
X onvol=1
X fi
X
X ## get number of volumes (in most cases we care but some we don't):
X ## $mode type do_we_care_about_$nvol_and_$onvol
X ## get onedisk no_and_no: we're not autoverifying
X ## get alldisks yes_and_yes: we need positioning
X ## verify onedisk yes_and_yes: to autoverify if we can
X ## verify alldisks yes_and_yes: we need positioning
X ## So, "$nvol" can be null if we're doing a get from a onedisk backup;
X #
X # if it's a get from a onedisk, we don't really care but user may
X # have specified so why not?
X if test $mode = get -a $getmode = onedisk ; then
X nvol=$nvol
X # else we care, so try to figure it out ...
X # if we're getting from disk file(s), we don't really have
X # any tapes but we need to act as if it's all on one tape
X elif test $mtype = file -o $mtype = dir ; then
X nvol=1
X # else if it's a onedisk, assume it will always fit on a video tape
X elif test $getmode = onedisk -a $mtype = video ; then
X nvol=1
X # else we've got to find out the number of volumes/tapes and the
X # name of the first filesystem on each volume/tape
X else
X # for any cpio backup or an alldisks backup, we need to know:
X # while test $bprog = cpio -o $getmode = knownfs -o $getmode = listdisks -o $getmode = lastdisk -o $getmode = alldisks ; do
X # for any onedisk or alldisks backup
X while : ; do
X if test -n "$nvol" ; then
X echo "$pr: This backup set has '$nvol' volume(s)."
X else
X echo "$pr: How many volumes are in this backup set?"
X echo $epre "$pr: Enter the number: "$esuf
X eval "$READ" nvol
X fi
X # validate $nvol
X if test "$nvol" -lt 1 -o "$nvol" -gt $maxvol ; then
X echo "$pr: '$nvol' can't be correct. Try again."
X nvol=''
X continue
X else
X extravol=`expr $nvol - 1`
X break
X fi
X done
X fi
X # if $nvol isn't set, then we don't need to know
X case "$nvol\X$mtype" in
X *file|*dir) x="$nvol (mtype=$mtype)" ;;
X X*) x=NA ;;
X *) x=$nvol ;;
X esac
X echo "#volumes in backup set: $x" >> $report
X
X # if we think we're getting from a multi-filesystem backup, then
X # extract the header archive and get positioning info
X case $getmode in
X knownfs|knownskip|listdisks|lastdisk|alldisks)
X # If this is a multi-fs backup we need to extract from the
X # tar/cpio header file, or get the necessary info from the
X # parent directory.
X #
X # If we are extracting from media, make absolutely sure it
X # succeeds, and don't continue until it does. This is the
X # second time we've actually tried to read from the media.
X fsnn=00
X eval "$MDEV"
X cd $workdir
X while : ; do
X # Do tar/cpio extraction (or get $dfout from the parent)
X # The count for the "dd" below is to make sure that
X # we don't read a huge file if we aren't reading a
X # header archive, which should be less than 200k.
X case $bprog$showdd$mhost in
X cpio*) : ;;
X *false*) : ;;
X *true$lhost) : ;;
X *true*) eval $SHOWDD Get alldisks header from $mhost:$media ;;
X esac
X case $parent-$bprog$demo$mhost in
X # parent is a backup called with "verifytoo"
X *[fit]?-*) eval "$LNFSTABLIST" ; ln ../$dfout ../$breport . ;;
X # parent is ordinary verify
X *[a-z]-*) eval "$LNFSTABLIST" ; ln ../$dfout ../$breport ../$volmap . ;;
X # the eight choices have no parent, i.e. this an
X # ordinary verify
X *cpiotrue$lhost) echo "$pr demo: cpio -icum$ckey < $mdev" ;;
X *cpio*$lhost) : ; cpio -icum$ckey < $mdev ;;
X *cpiotrue*) echo "$pr demo: $bdd if=$mdev bs=5k 2\> /dev/null \| cpio -icum$ckey" ;;
X *cpio*) : ; $bdd if=$mdev bs=5k 2> /dev/null | cpio -icum$ckey ;;
X *true$lhost) echo "$pr demo: tar xf $mdev" ;;
X *$lhost) : ; tar xf $mdev ;;
X *true*) echo "$pr demo: $bdd if=$mdev bs=10k count=20 2\> /dev/null \| tar xf -" ;;
X *) : ; $bdd if=$mdev bs=10k count=20 2> /dev/null | tar xf - ;;
X esac
X hfstat=$?
X # if we had no problems getting $dfout
X # note that SunOS 4.1.2 tar exits ok when it reads
X # a dump - very strange!
X if test "$hfstat" -eq 0 -a -s $dfout ; then
X break
X else
X echo "$pr: We had some trouble extracting the header archive from the $media."
X echo "$pr: Doing some investigating ..."
X if test ! -s $dfout ; then
X echo "$pr: Filesystem list '$dfout' was not extracted."
X echo "$pr: Extracting the header archive failed. Check:"
X echo "$pr: -> Is the $media a 'onedisk' backup (not an 'alldisks')?"
X eval "$CHKMEDIA"
X echo "$pr: Quitting."
X exit 1
X else
X echo "$pr: Filesystem list '$dfout' was extracted - ok so far ..."
X echo "$pr: Doing simple checks on '$dfout' ..."
X # $dfout should have same number of words on each line
X isit1=`awk '{print NF}' $dfout | sort -n -u | wc -l`
SHAR_EOF
true || echo 'restore of src/backup/backup failed'
fi
echo 'End of saenv_alld part 5'
echo 'File src/backup/backup is continued in part 6'
echo 6 > _shar_seq_.tmp
exit 0