c08aa03ab5e20c4070743ea1f1ac767d35f0b585
[debian/amanda] / tape-src / output-tape.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-1998 University of Maryland at College Park
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of U.M. not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  U.M. makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Author: James da Silva, Systems Design and Analysis Group
24  *                         Computer Science Department
25  *                         University of Maryland at College Park
26  */
27
28 /*
29  * $Id: output-tape.c,v 1.14 2006/03/09 20:06:12 johnfranks Exp $
30  *
31  * tapeio.c virtual tape interface for normal tape drives.
32  */
33
34 #ifdef NO_AMANDA
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <string.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <sys/stat.h>
42 #include <sys/wait.h>
43 #else
44 #include "amanda.h"
45 #include "tapeio.h"
46 #endif
47
48 #include "output-tape.h"
49
50 #ifndef NO_AMANDA
51 #include "fileheader.h"
52 #endif
53
54 #ifndef R_OK
55 #define R_OK 4
56 #define W_OK 2
57 #endif
58
59 /*
60 =======================================================================
61 ** Here are the ioctl() interface routines, which are #ifdef-ed
62 ** heavily by platform.
63 =======================================================================
64 */
65
66 #if defined(HAVE_BROKEN_FSF)                                            /* { */
67 /*
68  * tape_tapefd_fsf -- handle systems that have a broken fsf operation
69  * and cannot do an fsf operation unless they are positioned at a tape
70  * mark (or BOT).  Sheesh!  This shows up in amrestore as I/O errors
71  * when skipping.
72  */
73
74 int
75 tape_tapefd_fsf(fd, count)
76     int fd;
77     int count;
78 {
79     size_t buflen;
80     char *buffer = NULL;
81     int len = 0;
82
83     buflen = MAX_TAPE_BLOCK_BYTES;
84     buffer = alloc(buflen);
85
86     while(--count >= 0) {
87         while((len = tapefd_read(fd, buffer, buflen)) > 0) {}
88         if(len < 0) {
89             break;
90         }
91     }
92     amfree(buffer);
93     return len;
94 }
95 #endif                                                                  /* } */
96
97 #ifdef UWARE_TAPEIO                                                     /* { */
98
99 #include <sys/tape.h>
100
101 /*
102  * Rewind a tape to the beginning.
103  */
104 int
105 tape_tapefd_rewind(fd)
106     int fd;
107 {
108     int st;
109
110     return ioctl(fd, T_RWD, &st);
111 }
112
113 /*
114  * Rewind and unload a tape.
115  */
116 int
117 tape_tapefd_unload(fd)
118     int fd;
119 {
120     int st;
121
122     return ioctl(fd, T_OFFL, &st);
123 }
124
125 #if !defined(HAVE_BROKEN_FSF)
126 /*
127  * Forward space the tape device count files.
128  */
129 int tape_tapefd_fsf(fd, count)
130     int fd, count;
131 {
132     int st;
133     int status;
134
135     while (--count >= 0) {
136         if ((status = ioctl(fd, T_SFF, &st)) != 0) {
137             break;
138         }
139     }
140
141     return status;
142 }
143 #endif
144
145 /*
146  * Write some number of end of file marks (a.k.a. tape marks).
147  */
148 int
149 tape_tapefd_weof(fd, count)
150     int fd, count;
151 {
152     int st;
153     int status;
154
155     while (--count >= 0) {
156         if ((status = ioctl(fd, T_WRFILEM, &st)) != 0) {
157             break;
158         }
159     }
160
161     return status;
162 }
163
164 #else                                                                   /* }{ */
165 #ifdef AIX_TAPEIO                                                       /* { */
166
167 #include <sys/tape.h>
168
169 /*
170  * Rewind a tape to the beginning.
171  */
172 int
173 tape_tapefd_rewind(fd)
174     int fd;
175 {
176     struct stop st;
177
178     st.st_op = STREW;
179     st.st_count = 1;
180
181     return ioctl(fd, STIOCTOP, &st);
182 }
183
184 /*
185  * Rewind and unload a tape.
186  */
187 int
188 tape_tapefd_unload(fd)
189     int fd;
190 {
191     struct stop st;
192
193     st.st_op = STOFFL;
194     st.st_count = 1;
195
196     return ioctl(fd, STIOCTOP, &st);
197 }
198
199 #if !defined(HAVE_BROKEN_FSF)
200 /*
201  * Forward space the tape device count files.
202  */
203 int
204 tape_tapefd_fsf(fd, count)
205     int fd, count;
206 {
207     struct stop st;
208
209     st.st_op = STFSF;
210     st.st_count = count;
211
212     return ioctl(fd, STIOCTOP, &st);
213 }
214 #endif
215
216 /*
217  * Write some number of end of file marks (a.k.a. tape marks).
218  */
219 int
220 tape_tapefd_weof(fd, count)
221     int fd, count;
222 {
223     struct stop st;
224
225     st.st_op = STWEOF;
226     st.st_count = count;
227
228     return ioctl(fd, STIOCTOP, &st);
229 }
230
231 #else /* AIX_TAPEIO */                                                  /* }{ */
232 #ifdef XENIX_TAPEIO                                                     /* { */
233
234 #include <sys/tape.h>
235
236 /*
237  * Rewind a tape to the beginning.
238  */
239 int
240 tape_tapefd_rewind(fd)
241     int fd;
242 {
243     int st;
244
245     return ioctl(fd, MT_REWIND, &st);
246 }
247
248 /*
249  * Rewind and unload a tape.
250  */
251 int
252 tape_tapefd_unload(fd)
253     int fd;
254 {
255     int st;
256     int f;
257
258 #ifdef MT_OFFLINE
259     f = MT_OFFLINE;
260 #else
261 #ifdef MT_UNLOAD
262     f = MT_UNLOAD;
263 #else
264     f = syntax error;
265 #endif
266 #endif
267     return ioctl(fd, f, &st);
268 }
269
270 #if !defined(HAVE_BROKEN_FSF)
271 /*
272  * Forward space the tape device count files.
273  */
274 int
275 tape_tapefd_fsf(fd, count)
276     int fd, count;
277 {
278     int st;
279     int status;
280
281     while (--count >= 0) {
282         if ((status = ioctl(fd, MT_RFM, &st)) != 0) {
283             break;
284         }
285     }
286
287     return status;
288 }
289 #endif
290
291 /*
292  * Write some number of end of file marks (a.k.a. tape marks).
293  */
294 int
295 tape_tapefd_weof(fd, count)
296     int fd, count;
297 {
298     int st;
299     int c;
300     int status;
301
302     while (--count >= 0) {
303         if ((status = ioctl(fd, MT_WFM, &st)) != 0) {
304             break;
305         }
306     }
307
308     return status;
309 }
310
311 #else   /* ! AIX_TAPEIO && !XENIX_TAPEIO */                             /* }{ */
312
313 #include <sys/mtio.h>
314
315 /*
316  * Rewind a tape to the beginning.
317  */
318 int
319 tape_tapefd_rewind(fd)
320     int fd;
321 {
322     struct mtop mt;
323     int rc=-1, cnt;
324
325     mt.mt_op = MTREW;
326     mt.mt_count = 1;
327
328     /*
329      * EXB-8200 drive on FreeBSD can fail to rewind, but retrying won't
330      * hurt, and it will usually even work!
331      */
332     for(cnt = 10; cnt >= 0; --cnt) {
333         if ((rc = ioctl(fd, MTIOCTOP, &mt)) == 0) {
334             break;
335         }
336         if (cnt) {
337             sleep(3);
338         }
339     }
340     return rc;
341 }
342
343 /*
344  * Rewind and unload a tape.
345  */
346 int
347 tape_tapefd_unload(fd)
348     int fd;
349 {
350     struct mtop mt;
351     int rc=-1, cnt;
352
353 #ifdef MTUNLOAD
354     mt.mt_op = MTUNLOAD;
355 #else
356 #ifdef MTOFFL
357     mt.mt_op = MTOFFL;
358 #else
359     mt.mt_op = syntax error;
360 #endif
361 #endif
362     mt.mt_count = 1;
363
364     /*
365      * EXB-8200 drive on FreeBSD can fail to unload, but retrying won't
366      * hurt, and it will usually even work!
367      */
368     for(cnt = 10; cnt >= 0; --cnt) {
369         if ((rc = ioctl(fd, MTIOCTOP, &mt)) == 0) {
370             break;
371         }
372         if (cnt) {
373             sleep(3);
374         }
375     }
376     return rc;
377 }
378
379 #if !defined(HAVE_BROKEN_FSF)
380 /*
381  * Forward space the tape device count files.
382  */
383 int
384 tape_tapefd_fsf(fd, count)
385     int fd, count;
386 {
387     struct mtop mt;
388
389     mt.mt_op = MTFSF;
390     mt.mt_count = count;
391
392     return ioctl(fd, MTIOCTOP, &mt);
393 }
394 #endif
395
396 /*
397  * Write some number of end of file marks (a.k.a. tape marks).
398  */
399 int tape_tapefd_weof(fd, count)
400 int fd, count;
401 /*
402  * write <count> filemarks on the tape.
403  */
404 {
405     struct mtop mt;
406
407     mt.mt_op = MTWEOF;
408     mt.mt_count = count;
409
410     return ioctl(fd, MTIOCTOP, &mt);
411 }
412
413 #endif /* !XENIX_TAPEIO */                                              /* } */
414 #endif /* !AIX_TAPEIO */                                                /* } */
415 #endif /* !UWARE_TAPEIO */                                              /* } */
416
417 /*
418  * At this point we have pulled in every conceivable #include file :-),
419  * so now come the more general routines with minimal #ifdef-ing.
420  */
421
422 #ifdef HAVE_LINUX_ZFTAPE_H
423 /*
424  * is_zftape(filename) checks if filename is a valid ftape device name.
425  */
426 int
427 is_zftape(filename)
428     const char *filename;
429 {
430     if (strncmp(filename, "/dev/nftape", 11) == 0) return(1);
431     if (strncmp(filename, "/dev/nqft",    9) == 0) return(1);
432     if (strncmp(filename, "/dev/nrft",    9) == 0) return(1);
433     return(0);
434 }
435 #endif /* HAVE_LINUX_ZFTAPE_H */
436
437 int tape_tape_open(filename, flags, mask)
438     char *filename;
439     int flags;
440     int mask;
441 {
442     int ret = 0, delay = 2, timeout = 200;
443
444     if ((flags & 3) != O_RDONLY) {
445         flags &= ~3;
446         flags |= O_RDWR;
447     }
448     while (1) {
449         ret = open(filename, flags, mask);
450         /* if tape open fails with errno==EAGAIN, EBUSY or EINTR, it
451          * is worth retrying a few seconds later.  */
452         if (ret >= 0 ||
453             (1
454 #ifdef EAGAIN
455              && errno != EAGAIN
456 #endif
457 #ifdef EBUSY
458              && errno != EBUSY
459 #endif
460 #ifdef EINTR
461              && errno != EINTR
462 #endif
463              )) {
464             break;
465         }
466         timeout -= delay;
467         if (timeout <= 0) {
468             break;
469         }
470         if (delay < 16) {
471             delay *= 2;
472         }
473         sleep(delay);
474     }
475 #ifdef HAVE_LINUX_ZFTAPE_H
476     /*
477      * switch the block size for the zftape driver (3.04d)
478      * (its default is 10kb and not 32kb)
479      *        A. Gebhardt <albrecht.gebhardt@uni-klu.ac.at>
480      */
481     if (ret >= 0 && is_zftape(filename) == 1) {
482         struct mtop mt;
483
484         mt.mt_op = MTSETBLK;
485         mt.mt_count = 32 * 1024;                /* should be blocksize ??? */
486         ioctl(ret, MTIOCTOP, &mt);
487     }
488 #endif /* HAVE_LINUX_ZFTAPE_H */
489     return ret;
490 }
491
492 ssize_t tape_tapefd_read(fd, buffer, count)
493     int fd;
494     void *buffer;
495     size_t count;
496 {
497     return read(fd, buffer, count);
498 }
499
500 ssize_t tape_tapefd_write(fd, buffer, count)
501     int fd;
502     const void *buffer;
503     size_t count;
504 {
505     return write(fd, buffer, count);
506 }
507
508 int tape_tapefd_close(fd)
509     int fd;
510 {
511     return close(fd);
512 }
513
514 void tape_tapefd_resetofs(fd)
515     int fd;
516 {
517     /*
518      * this *should* be a no-op on the tape, but resets the kernel's view
519      * of the file offset, preventing it from barfing should we pass the
520      * filesize limit (eg OSes with 2 GB filesize limits) on a long tape.
521      */
522     lseek(fd, (off_t) 0L, SEEK_SET);
523 }
524
525 int
526 tape_tapefd_status(fd, stat)
527     int fd;
528     struct am_mt_status *stat;
529 {
530     int res = 0;
531     int anything_valid = 0;
532 #if defined(MTIOCGET)
533     struct mtget buf;
534 #endif
535
536     memset((void *)stat, 0, sizeof(*stat));
537
538 #if defined(MTIOCGET)                                                   /* { */
539     res = ioctl(fd,MTIOCGET,&buf);
540
541     if (res >= 0) {
542 #ifdef MT_ONL                                                           /* { */
543         /* IRIX-ish system */
544         anything_valid = 1;
545         stat->online_valid = 1;
546         stat->online = (0 != (buf.mt_dposn & MT_ONL));
547         stat->bot_valid = 1;
548         stat->bot = (0 != (buf.mt_dposn & MT_BOT));
549         stat->eot_valid = 1;
550         stat->eot = (0 != (buf.mt_dposn & MT_EOT));
551         stat->protected_valid = 1;
552         stat->protected = (0 != (buf.mt_dposn & MT_WPROT));
553 #else                                                                   /* }{ */
554 #ifdef GMT_ONLINE                                                       /* { */
555         /* Linux-ish system */
556         anything_valid = 1;
557         stat->online_valid = 1;
558         stat->online = (0 != GMT_ONLINE(buf.mt_gstat));
559         stat->bot_valid = 1;
560         stat->bot = (0 != GMT_BOT(buf.mt_gstat));
561         stat->eot_valid = 1;
562         stat->eot = (0 != GMT_EOT(buf.mt_gstat));
563         stat->protected_valid = 1;
564         stat->protected = (0 != GMT_WR_PROT(buf.mt_gstat));
565 #else                                                                   /* }{ */
566 #ifdef DEV_BOM                                                          /* { */
567         /* OSF1-ish system */
568         anything_valid = 1;
569         stat->online_valid = 1;
570         stat->online = (0 == (DEV_OFFLINE & buf.mt_dsreg));
571         stat->bot_valid = 1;
572         stat->bot = (0 != (DEV_BOM & buf.mt_dsreg));
573         stat->protected_valid = 1;
574         stat->protected = (0 != (DEV_WRTLCK & buf.mt_dsreg));
575 #else                                                                   /* }{ */
576         /* Solaris, minix, etc. */
577         anything_valid = 1;
578         stat->online_valid = 1;
579         stat->online = 1;                       /* ioctl fails otherwise */
580 #ifdef HAVE_MT_DSREG
581         stat->device_status_valid = 1;
582         stat->device_status_size = sizeof(buf.mt_dsreg);
583         stat->device_status = (unsigned long)buf.mt_dsreg;
584 #endif
585 #ifdef HAVE_MT_ERREG
586         stat->error_status_valid = 1;
587         stat->error_status_size = sizeof(buf.mt_erreg);
588         stat->error_status = (unsigned long)buf.mt_erreg;
589 #endif
590 #if defined(HAVE_MT_FLAGS) && defined(MTF_SCSI)                 /* { */
591         /* 
592          * On Solaris, the file/block number fields are only valid if
593          * the driver is SCSI.  And in that case, the dsreg value is
594          * not useful (it is a retry count).
595          */
596         if(buf.mt_flags & MTF_SCSI) {
597             stat->device_status_valid = 0;
598 #ifdef HAVE_MT_FILENO
599             stat->fileno_valid = 1;
600             stat->fileno = (long)buf.mt_fileno;
601 #endif
602 #ifdef HAVE_MT_BLKNO
603             stat->blkno_valid = 1;
604             stat->blkno = (long)buf.mt_blkno;
605 #endif
606         }
607 #endif                                                                  /* } */
608 #endif                                                                  /* } */
609 #endif                                                                  /* } */
610 #endif                                                                  /* } */
611     }
612 #endif                                                                  /* } */
613
614     /*
615      * If we did not find any valid information, do a stat on the device
616      * and if that returns successfully, assume it is at least online.
617      */
618     if(!anything_valid) {
619         struct stat sbuf;
620
621         res = fstat(fd, &sbuf);
622         stat->online_valid = 1;
623         stat->online = (res == 0);
624     }
625
626     return res;
627 }
628
629 int tape_tape_stat(filename, buf)
630      char *filename;
631      struct stat *buf;
632 {
633      return stat(filename, buf);
634 }
635
636 int tape_tape_access(filename, mode)
637      char *filename;
638      int mode;
639 {
640      return access(filename, mode);
641 }
642
643 int 
644 tape_tapefd_can_fork(fd)
645     int fd;
646 {
647     return 1;
648 }
649