063084b75d43df7087dc6e616de1bf31c236f95d
[debian/amanda] / changer-src / chg-chs.sh.in
1 #!/bin/sh
2 #
3 # Amanda, The Advanced Maryland Automatic Network Disk Archiver
4 # Copyright (c) 1991-1998 University of Maryland at College Park
5 # All Rights Reserved.
6 #
7 # Permission to use, copy, modify, distribute, and sell this software and its
8 # documentation for any purpose is hereby granted without fee, provided that
9 # the above copyright notice appear in all copies and that both that
10 # copyright notice and this permission notice appear in supporting
11 # documentation, and that the name of U.M. not be used in advertising or
12 # publicity pertaining to distribution of the software without specific,
13 # written prior permission.  U.M. makes no representations about the
14 # suitability of this software for any purpose.  It is provided "as is"
15 # without express or implied warranty.
16 #
17 # U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19 # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21 # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 #
24 # Author: James da Silva, Systems Design and Analysis Group
25 #                          Computer Science Department
26 #                          University of Maryland at College Park
27 #
28
29 #
30 # chg-chs.sh - chs tape changer script
31 #
32
33 prefix=@prefix@
34 exec_prefix=@exec_prefix@
35 sbindir=@sbindir@
36 libexecdir=@libexecdir@
37
38 pname="chg-chs"
39
40 PATH=$sbindir:$libexecdir:/usr/bin:/bin:/usr/sbin:/sbin:/usr/ucb
41 export PATH
42
43 if [ -d "@AMANDA_DBGDIR@" ]; then
44         logfile=@AMANDA_DBGDIR@/changer.debug
45 else
46         logfile=/dev/null
47 fi
48
49 CHS=@CHS@
50
51 if [ -x $sbindir/ammt$SUF ]; then
52         MT=$sbindir/ammt$SUF
53         MTF=-f
54 elif [ -x "@MT@" ]; then
55         MT=@MT@
56         MTF=@MT_FILE_FLAG@
57 else
58         answer="<none> $myname: mt program not found"
59         code=1
60         echo "Exit -> $answer" >> $logfile
61         echo "$answer"
62         exit $code
63 fi
64 echo MT "->" $MT $MTF >> $logfile
65
66 USE_VERSION_SUFFIXES="@USE_VERSION_SUFFIXES@"
67 if test "$USE_VERSION_SUFFIXES" = "yes"; then
68         SUF="-@VERSION@"
69 else
70         SUF=
71 fi
72
73 ourconf=`amgetconf$SUF changerfile`
74 changerdev=`amgetconf$SUF changerdev`
75 if test -n "$changerdev" && test x"$changerdev" != x/dev/null; then
76         CHS="$CHS -f$changerdev"
77 fi
78
79 # read in some config parameters
80
81 if [ \! -f $ourconf ]; then
82         answer="<none> $pname: $ourconf does not exist"
83         code=2
84         echo "Exit -> $answer" >> $logfile
85         echo "$answer"
86         exit $code
87 fi
88
89 firstslot=`awk '$1 == "firstslot" {print $2}' $ourconf 2>/dev/null`
90 if [ "$firstslot" = "" ]; then
91         answer="<none> $pname: firstslot not specified in $ourconf"
92         code=2
93         echo "Exit -> $answer" >> $logfile
94         echo "$answer"
95         exit $code
96 fi
97
98 lastslot=`awk '$1 == "lastslot" {print $2}' $ourconf 2>/dev/null`
99 if [ "$lastslot" = "" ]; then
100         answer="<none> $pname: lastslot not specified in $ourconf"
101         code=2
102         echo "Exit -> $answer" >> $logfile
103         echo "$answer"
104         exit $code
105 fi
106
107 nslots=`expr $lastslot - $firstslot + 1`
108
109 gravity=`awk '$1 == "gravity" {print $2}' $ourconf 2>/dev/null`
110 if [ "$gravity" = "" ]; then
111         answer="<none> $pname: gravity not specified in $ourconf"
112         code=2
113         echo "Exit -> $answer" >> $logfile
114         echo "$answer"
115         exit $code
116 fi
117
118 needeject=`awk '$1 == "needeject" {print $2}' $ourconf 2>/dev/null`
119 if [ "$needeject" = "" ]; then
120         answer="<none> $pname: needeject not specified in $ourconf"
121         code=2
122         echo "Exit -> $answer" >> $logfile
123         echo "$answer"
124         exit $code
125 fi
126
127 multieject=`awk '$1 == "multieject" {print $2}' $ourconf 2>/dev/null`
128 if [ "$multieject" = "" ]; then
129         echo "Note -> multieject not specified in $ourconf" >> $logfile
130         multieject=0
131 fi
132
133 ejectdelay=`awk '$1 == "ejectdelay" {print $2}' $ourconf 2>/dev/null`
134 if [ "$ejectdelay" = "" ]; then
135         echo "Note -> ejectdelay not specified in $ourconf" >> $logfile
136         ejectdelay=0
137 fi
138
139 ourstate=`awk '$1 == "statefile" {print $2}' $ourconf 2>/dev/null`
140 if [ "$ourstate" = "" ]; then
141         answer="<none> $pname: statefile not specified in $ourconf"
142         code=2
143         echo "Exit -> $answer" >> $logfile
144         echo "$answer"
145         exit $code
146 fi
147
148 # read in state: only curslot and curloaded at the present time
149
150 curslot=`awk '$1 == "curslot" {print $2}' $ourstate 2>/dev/null`
151 if [ "$curslot" = "" ]; then
152         curslot=$firstslot
153 fi
154
155 curloaded=`awk '$1 == "curloaded" {print $2}' $ourstate 2>/dev/null`
156 if [ "$curloaded" = "" ]; then
157         curloaded=0
158 fi
159
160
161 # process the command-line
162
163 # control vars to avoid code duplication: not all shells have functions!
164 usage=0
165 checkgravity=0
166 ejectslot=0
167 loadslot=0
168 slotempty=0
169
170 if [ $# -ge 1 ]; then command=$1; else command="-usage"; fi
171
172 case "$command" in
173
174 -info) # return basic information about changer
175
176         backwards=`expr 1 - $gravity`
177         answer="$curslot $nslots $backwards"
178         code=0
179         echo "Exit -> $answer" >> $logfile
180         echo "$answer"
181         exit $code
182         ;;
183
184 -reset) # reset changer
185
186         checkgravity=0
187         loadslot=1
188         newslot=$firstslot
189
190         # XXX put changer-specific reset here, if applicable
191         ;;
192
193 -eject) # eject tape if loaded
194
195         checkgravity=0
196         loadslot=0
197         newslot=$curslot
198         ejectslot=1
199
200         if [ $curloaded -eq 0 ]; then
201                 answer="$curslot $pname: slot already empty"
202                 code=1
203                 echo "Exit -> $answer" >> $logfile
204                 echo "$answer"
205                 exit $code
206         fi
207         ;;
208
209 -slot)  # change to slot
210
211         checkgravity=1
212         loadslot=1
213
214         slotparm=$2
215         case "$slotparm" in
216         [0-9]*) 
217                 newslot=$slotparm
218                 if [ \( $newslot -gt $lastslot \) -o \
219                      \( $newslot -lt $firstslot \) ]; then
220                         answer="$newslot $pname: no slot $newslot: legal range is $firstslot ... $lastslot"
221                         code=1
222                         echo "Exit -> $answer" >> $logfile
223                         echo "$answer"
224                         exit $code
225                 fi
226                 ;;
227         current)
228                 newslot=$curslot
229                 ;;
230         first)
231                 newslot=$firstslot
232                 ;;
233         last)
234                 newslot=$lastslot
235                 ;;
236         next|advance)
237                 newslot=`expr $curslot + 1`
238                 if [ $newslot -gt $lastslot ]; then
239                         newslot=$firstslot
240                 fi
241                 if [ $slotparm = advance ]; then
242                         loadslot=0
243                 fi
244                 ;;
245         prev)
246                 newslot=`expr $curslot - 1`
247                 if [ $newslot -lt $firstslot ]; then
248                         newslot=$lastslot
249                 fi
250                 ;;
251         *)
252                 answer="<none> $pname: bad slot name \"$slotparm\""
253                 code=1
254                 echo "Exit -> $answer" >> $logfile
255                 echo "$answer"
256                 exit $code
257                 ;;
258         esac
259         ;;
260 *)
261         usage=1
262         ;;
263 esac
264
265
266 if [ $usage -eq 1 ]; then
267         answer="<none> usage: $pname {-reset | -slot [<slot-number>|current|next|prev|advance]}"
268         code=2
269         echo "Exit -> $answer" >> $logfile
270         echo "$answer"
271         exit $code
272 fi
273
274
275 # check for legal move
276
277 if [ \( $checkgravity -eq 1 \) -a \( $gravity -ne 0 \) ]; then
278         if [ \( $newslot -lt $curslot \) -o \( "$slotparm" = "prev" \) ]
279         then
280                 answer="$newslot $pname: cannot go backwards in gravity stacker"
281                 code=1
282                 echo "Exit -> $answer" >> $logfile
283                 echo "$answer"
284                 exit $code
285         fi
286 fi
287
288 # get tape device name
289
290 device=`awk '$1 == "slot" && $2 == '$newslot' {print $3}' $ourconf 2>/dev/null`
291 if [ "$device" = "" ]; then
292         answer="$newslot $pname: slot $newslot device not specified in $ourconf"
293         code=2
294         echo "Exit -> $answer" >> $logfile
295         echo "$answer"
296         exit $code
297 fi
298
299 # check if load needs an eject first
300
301 if [ \( $needeject -eq 1 \) -a \( $loadslot -eq 1 \) -a \
302      \( $curloaded -eq 1 \) -a \( $newslot -ne $curslot \) ]; then
303         ejectslot=1
304 fi
305
306
307 if [ $ejectslot -eq 1 ]; then   # eject the tape from the drive
308
309         # XXX put changer-specific load command here, if applicable
310
311         curloaded=0             # unless something goes wrong
312         slotempty=0
313
314         # generically, first check that the device is there
315
316         if [ ! -c $device ]; then
317                 answer="$newslot $pname: $device: not a device file"
318                 code=2
319                 echo "Exit -> $answer" >> $logfile
320                 echo "$answer"
321                 exit $code
322         fi
323
324         # if multiple eject is required, do it now
325         if [ $multieject -eq 1 ]; then
326                 loopslot=$curslot
327                 while [ $loopslot -lt $newslot ]; do
328                         $MT $MTF $device offline >/dev/null 2>&1
329                         if [ $? -ne 0 ]; then
330                                 answer="$newslot $pname: $device: unable to change slot $loopslot"
331                                 code=2
332                                 echo "Exit -> $answer" >> $logfile
333                                 echo "$answer"
334                                 exit $code
335                         fi
336                         loopslot=`/usr/bin/expr $loopslot + 1`
337                 done
338         fi
339   
340         # second, try to unload the device
341         $MT $MTF $device offline >/dev/null 2>&1
342         $CHS deselect -d1 -s$curslot >/dev/null 2>&1
343         if [ $? -ne 0 ]; then
344                 #
345                 # XXX if the changer-specific eject command can distinguish
346                 # betweeen "slot empty" and more serious errors, return 1
347                 # for the first case, 2 for the second case.  Generically,
348                 # we just presume an error signifies an empty slot.
349                 #
350                 #slotempty=1
351                 answer="<none> $pname: tape unload to slot $curslot failed"
352                 code=2
353                 echo "Exit -> $answer" >> $logfile
354                 echo "$answer"
355                 exit $code
356         else
357                 sleep $ejectdelay
358         fi
359 fi
360
361 if [ \( $loadslot -eq 1 \) -a \( \( $curloaded -ne 1 \) -o \( \( $curloaded -eq 1 \) -a \( $newslot -ne $curslot \) \) \) ]; then       # load the tape from the slot
362
363         # XXX put changer-specific load command here, if applicable
364
365         curloaded=1             # unless something goes wrong
366         slotempty=0
367
368         # generically, first check that the device is there
369
370         if [ ! -c $device ]; then
371                 answer="$newslot $pname: $device: not a device file"
372                 code=2
373                 echo "Exit -> $answer" >> $logfile
374                 echo "$answer"
375                 exit $code
376         fi
377
378         $CHS select -s$newslot -d1 >/dev/null 2>&1
379         if [ $? -ne 0 ]; then
380                 answer="<none> $pname: tape load from slot $newslot failed"
381                 code=2
382                 echo "Exit -> $answer" >> $logfile
383                 echo "$answer"
384                 exit $code
385         fi
386         sleep 60
387
388         # second, try to rewind the device
389         $MT $MTF $device rewind >/dev/null 2>&1
390         if [ $? -ne 0 ]; then
391                 #
392                 # XXX if the changer-specific load command can distinguish
393                 # betweeen "slot empty" and more serious errors, return 1
394                 # for the first case, 2 for the second case.  Generically,
395                 # we just presume an error signifies an empty slot.
396                 #
397                 slotempty=1
398                 curloaded=0
399         fi
400 fi
401
402 # update state
403
404 echo "# $pname state cache: DO NOT EDIT!"       >  $ourstate
405 echo curslot $newslot                           >> $ourstate
406 echo curloaded $curloaded                       >> $ourstate
407
408 # return slot info
409
410 if [ $slotempty -eq 1 ]; then
411         answer="<nonw> $pname: $newslot slot is empty"
412         code=1
413         echo "Exit -> $answer" >> $logfile
414         echo "$answer"
415         exit $code
416 fi
417
418 if [ "$command" = -slot -a "$slotparm" = advance ]; then
419         device=/dev/null
420 fi
421
422 answer="$newslot $device"
423 code=0
424 echo "Exit -> $answer" >> $logfile
425 echo "$answer"
426 exit $code