#!/bin/sh # # Amanda, The Advanced Maryland Automatic Network Disk Archiver # Copyright (c) 1991-1998 University of Maryland at College Park # All Rights Reserved. # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of U.M. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. U.M. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # # Author: James da Silva, Systems Design and Analysis Group # Computer Science Department # University of Maryland at College Park # # # chg-chs.sh - chs tape changer script # prefix=@prefix@ exec_prefix=@exec_prefix@ sbindir=@sbindir@ libexecdir=@libexecdir@ pname="chg-chs" PATH=$sbindir:$libexecdir:/usr/bin:/bin:/usr/sbin:/sbin:/usr/ucb export PATH if [ -d "@AMANDA_DBGDIR@" ]; then logfile=@AMANDA_DBGDIR@/changer.debug else logfile=/dev/null fi CHS=@CHS@ if [ -x $sbindir/ammt$SUF ]; then MT=$sbindir/ammt$SUF MTF=-f elif [ -x "@MT@" ]; then MT=@MT@ MTF=@MT_FILE_FLAG@ else answer=" $myname: mt program not found" code=1 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi echo MT "->" $MT $MTF >> $logfile USE_VERSION_SUFFIXES="@USE_VERSION_SUFFIXES@" if test "$USE_VERSION_SUFFIXES" = "yes"; then SUF="-@VERSION@" else SUF= fi ourconf=`amgetconf$SUF changerfile` changerdev=`amgetconf$SUF changerdev` if test -n "$changerdev" && test x"$changerdev" != x/dev/null; then CHS="$CHS -f$changerdev" fi # read in some config parameters if [ \! -f $ourconf ]; then answer=" $pname: $ourconf does not exist" code=2 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi firstslot=`awk '$1 == "firstslot" {print $2}' $ourconf 2>/dev/null` if [ "$firstslot" = "" ]; then answer=" $pname: firstslot not specified in $ourconf" code=2 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi lastslot=`awk '$1 == "lastslot" {print $2}' $ourconf 2>/dev/null` if [ "$lastslot" = "" ]; then answer=" $pname: lastslot not specified in $ourconf" code=2 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi nslots=`expr $lastslot - $firstslot + 1` gravity=`awk '$1 == "gravity" {print $2}' $ourconf 2>/dev/null` if [ "$gravity" = "" ]; then answer=" $pname: gravity not specified in $ourconf" code=2 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi needeject=`awk '$1 == "needeject" {print $2}' $ourconf 2>/dev/null` if [ "$needeject" = "" ]; then answer=" $pname: needeject not specified in $ourconf" code=2 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi multieject=`awk '$1 == "multieject" {print $2}' $ourconf 2>/dev/null` if [ "$multieject" = "" ]; then echo "Note -> multieject not specified in $ourconf" >> $logfile multieject=0 fi ejectdelay=`awk '$1 == "ejectdelay" {print $2}' $ourconf 2>/dev/null` if [ "$ejectdelay" = "" ]; then echo "Note -> ejectdelay not specified in $ourconf" >> $logfile ejectdelay=0 fi ourstate=`awk '$1 == "statefile" {print $2}' $ourconf 2>/dev/null` if [ "$ourstate" = "" ]; then answer=" $pname: statefile not specified in $ourconf" code=2 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi # read in state: only curslot and curloaded at the present time curslot=`awk '$1 == "curslot" {print $2}' $ourstate 2>/dev/null` if [ "$curslot" = "" ]; then curslot=$firstslot fi curloaded=`awk '$1 == "curloaded" {print $2}' $ourstate 2>/dev/null` if [ "$curloaded" = "" ]; then curloaded=0 fi # process the command-line # control vars to avoid code duplication: not all shells have functions! usage=0 checkgravity=0 ejectslot=0 loadslot=0 slotempty=0 if [ $# -ge 1 ]; then command=$1; else command="-usage"; fi case "$command" in -info) # return basic information about changer backwards=`expr 1 - $gravity` answer="$curslot $nslots $backwards" code=0 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code ;; -reset) # reset changer checkgravity=0 loadslot=1 newslot=$firstslot # XXX put changer-specific reset here, if applicable ;; -eject) # eject tape if loaded checkgravity=0 loadslot=0 newslot=$curslot ejectslot=1 if [ $curloaded -eq 0 ]; then answer="$curslot $pname: slot already empty" code=1 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi ;; -slot) # change to slot checkgravity=1 loadslot=1 slotparm=$2 case "$slotparm" in [0-9]*) newslot=$slotparm if [ \( $newslot -gt $lastslot \) -o \ \( $newslot -lt $firstslot \) ]; then answer="$newslot $pname: no slot $newslot: legal range is $firstslot ... $lastslot" code=1 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi ;; current) newslot=$curslot ;; first) newslot=$firstslot ;; last) newslot=$lastslot ;; next|advance) newslot=`expr $curslot + 1` if [ $newslot -gt $lastslot ]; then newslot=$firstslot fi if [ $slotparm = advance ]; then loadslot=0 fi ;; prev) newslot=`expr $curslot - 1` if [ $newslot -lt $firstslot ]; then newslot=$lastslot fi ;; *) answer=" $pname: bad slot name \"$slotparm\"" code=1 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code ;; esac ;; *) usage=1 ;; esac if [ $usage -eq 1 ]; then answer=" usage: $pname {-reset | -slot [|current|next|prev|advance]}" code=2 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi # check for legal move if [ \( $checkgravity -eq 1 \) -a \( $gravity -ne 0 \) ]; then if [ \( $newslot -lt $curslot \) -o \( "$slotparm" = "prev" \) ] then answer="$newslot $pname: cannot go backwards in gravity stacker" code=1 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi fi # get tape device name device=`awk '$1 == "slot" && $2 == '$newslot' {print $3}' $ourconf 2>/dev/null` if [ "$device" = "" ]; then answer="$newslot $pname: slot $newslot device not specified in $ourconf" code=2 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi # check if load needs an eject first if [ \( $needeject -eq 1 \) -a \( $loadslot -eq 1 \) -a \ \( $curloaded -eq 1 \) -a \( $newslot -ne $curslot \) ]; then ejectslot=1 fi if [ $ejectslot -eq 1 ]; then # eject the tape from the drive # XXX put changer-specific load command here, if applicable curloaded=0 # unless something goes wrong slotempty=0 # generically, first check that the device is there if [ ! -c $device ]; then answer="$newslot $pname: $device: not a device file" code=2 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi # if multiple eject is required, do it now if [ $multieject -eq 1 ]; then loopslot=$curslot while [ $loopslot -lt $newslot ]; do $MT $MTF $device offline >/dev/null 2>&1 if [ $? -ne 0 ]; then answer="$newslot $pname: $device: unable to change slot $loopslot" code=2 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi loopslot=`/usr/bin/expr $loopslot + 1` done fi # second, try to unload the device $MT $MTF $device offline >/dev/null 2>&1 $CHS deselect -d1 -s$curslot >/dev/null 2>&1 if [ $? -ne 0 ]; then # # XXX if the changer-specific eject command can distinguish # betweeen "slot empty" and more serious errors, return 1 # for the first case, 2 for the second case. Generically, # we just presume an error signifies an empty slot. # #slotempty=1 answer=" $pname: tape unload to slot $curslot failed" code=2 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code else sleep $ejectdelay fi fi if [ \( $loadslot -eq 1 \) -a \( \( $curloaded -ne 1 \) -o \( \( $curloaded -eq 1 \) -a \( $newslot -ne $curslot \) \) \) ]; then # load the tape from the slot # XXX put changer-specific load command here, if applicable curloaded=1 # unless something goes wrong slotempty=0 # generically, first check that the device is there if [ ! -c $device ]; then answer="$newslot $pname: $device: not a device file" code=2 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi $CHS select -s$newslot -d1 >/dev/null 2>&1 if [ $? -ne 0 ]; then answer=" $pname: tape load from slot $newslot failed" code=2 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi sleep 60 # second, try to rewind the device $MT $MTF $device rewind >/dev/null 2>&1 if [ $? -ne 0 ]; then # # XXX if the changer-specific load command can distinguish # betweeen "slot empty" and more serious errors, return 1 # for the first case, 2 for the second case. Generically, # we just presume an error signifies an empty slot. # slotempty=1 curloaded=0 fi fi # update state echo "# $pname state cache: DO NOT EDIT!" > $ourstate echo curslot $newslot >> $ourstate echo curloaded $curloaded >> $ourstate # return slot info if [ $slotempty -eq 1 ]; then answer=" $pname: $newslot slot is empty" code=1 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code fi if [ "$command" = -slot -a "$slotparm" = advance ]; then device=/dev/null fi answer="$newslot $device" code=0 echo "Exit -> $answer" >> $logfile echo "$answer" exit $code