Imported Upstream version 2.5.1
[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.18 2006/08/22 14:19:39 martinea 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(
76     int fd,
77     off_t 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(
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(
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
130 tape_tapefd_fsf(
131     int fd,
132     off_t count)
133 {
134     int st;
135     int status;
136
137     while (--count >= 0) {
138         if ((status = ioctl(fd, T_SFF, &st)) != 0) {
139             break;
140         }
141     }
142
143     return status;
144 }
145 #endif
146
147 /*
148  * Write some number of end of file marks (a.k.a. tape marks).
149  */
150 int
151 tape_tapefd_weof(
152     int fd,
153     off_t count)
154 {
155     int st;
156     int status;
157
158     while (--count >= (off_t)0) {
159         if ((status = ioctl(fd, T_WRFILEM, &st)) != 0) {
160             break;
161         }
162     }
163
164     return status;
165 }
166
167 #else                                                                   /* }{ */
168 #ifdef AIX_TAPEIO                                                       /* { */
169
170 #include <sys/tape.h>
171
172 /*
173  * Rewind a tape to the beginning.
174  */
175 int
176 tape_tapefd_rewind(
177     int fd)
178 {
179     struct stop st;
180
181     st.st_op = STREW;
182     st.st_count = 1;
183
184     return ioctl(fd, STIOCTOP, &st);
185 }
186
187 /*
188  * Rewind and unload a tape.
189  */
190 int
191 tape_tapefd_unload(
192     int fd)
193 {
194     struct stop st;
195
196     st.st_op = STOFFL;
197     st.st_count = 1;
198
199     return ioctl(fd, STIOCTOP, &st);
200 }
201
202 #if !defined(HAVE_BROKEN_FSF)
203 /*
204  * Forward space the tape device count files.
205  */
206 int
207 tape_tapefd_fsf(
208     int fd,
209     off_t count)
210 {
211     struct stop st;
212
213     if ((count > (off_t)INT_MAX) || (count < (off_t)INT_MIN)) {
214 #ifdef EOVERFLOW
215             errno = EOVERFLOW;
216 #else
217             errno = EINVAL;
218 #endif
219         return -1;
220     }
221
222     st.st_op = STFSF;
223     st.st_count = (int)count;
224
225     return ioctl(fd, STIOCTOP, &st);
226 }
227 #endif
228
229 /*
230  * Write some number of end of file marks (a.k.a. tape marks).
231  */
232 int
233 tape_tapefd_weof(
234     int fd,
235     off_t count)
236 {
237     struct stop st;
238
239     if ((count > (off_t)INT_MAX) || (count < (off_t)INT_MIN)) {
240 #ifdef EOVERFLOW
241             errno = EOVERFLOW;
242 #else
243             errno = EINVAL;
244 #endif
245         return -1;
246     }
247
248     st.st_op = STWEOF;
249     st.st_count = (int)count;
250
251     return ioctl(fd, STIOCTOP, &st);
252 }
253
254 #else /* AIX_TAPEIO */                                                  /* }{ */
255 #ifdef XENIX_TAPEIO                                                     /* { */
256
257 #include <sys/tape.h>
258
259 /*
260  * Rewind a tape to the beginning.
261  */
262 int
263 tape_tapefd_rewind(
264     int fd)
265 {
266     int st;
267
268     return ioctl(fd, MT_REWIND, &st);
269 }
270
271 /*
272  * Rewind and unload a tape.
273  */
274 int
275 tape_tapefd_unload(
276     int fd)
277 {
278     int st;
279     int f;
280
281 #ifdef MT_OFFLINE
282     f = MT_OFFLINE;
283 #else
284 #ifdef MT_UNLOAD
285     f = MT_UNLOAD;
286 #else
287     f = syntax error;
288 #endif
289 #endif
290     return ioctl(fd, f, &st);
291 }
292
293 #if !defined(HAVE_BROKEN_FSF)
294 /*
295  * Forward space the tape device count files.
296  */
297 int
298 tape_tapefd_fsf(
299     int fd,
300     off_t count)
301 {
302     int st;
303     int status;
304
305     while (--count >= 0) {
306         if ((status = ioctl(fd, MT_RFM, &st)) != 0) {
307             break;
308         }
309     }
310
311     return status;
312 }
313 #endif
314
315 /*
316  * Write some number of end of file marks (a.k.a. tape marks).
317  */
318 int
319 tape_tapefd_weof(
320     int fd,
321     off_t count)
322 {
323     int st;
324     int c;
325     int status;
326
327     while (--count >= 0) {
328         if ((status = ioctl(fd, MT_WFM, &st)) != 0) {
329             break;
330         }
331     }
332
333     return status;
334 }
335
336 #else   /* ! AIX_TAPEIO && !XENIX_TAPEIO */                             /* }{ */
337
338 #include <sys/mtio.h>
339
340 /*
341  * Rewind a tape to the beginning.
342  */
343 int
344 tape_tapefd_rewind(
345     int fd)
346 {
347     struct mtop mt;
348     int rc=-1, cnt;
349
350     mt.mt_op = MTREW;
351     mt.mt_count = 1;
352
353     /*
354      * EXB-8200 drive on FreeBSD can fail to rewind, but retrying won't
355      * hurt, and it will usually even work!
356      */
357     for(cnt = 10; cnt >= 0; --cnt) {
358         if ((rc = ioctl(fd, MTIOCTOP, &mt)) == 0) {
359             break;
360         }
361         if (cnt) {
362             sleep(3);
363         }
364     }
365     return rc;
366 }
367
368 /*
369  * Rewind and unload a tape.
370  */
371 int
372 tape_tapefd_unload(
373     int fd)
374 {
375     struct mtop mt;
376     int rc=-1, cnt;
377
378 #ifdef MTUNLOAD
379     mt.mt_op = MTUNLOAD;
380 #else
381 #ifdef MTOFFL
382     mt.mt_op = MTOFFL;
383 #else
384     mt.mt_op = syntax error;
385 #endif
386 #endif
387     mt.mt_count = 1;
388
389     /*
390      * EXB-8200 drive on FreeBSD can fail to unload, but retrying won't
391      * hurt, and it will usually even work!
392      */
393     for(cnt = 10; cnt >= 0; --cnt) {
394         if ((rc = ioctl(fd, MTIOCTOP, &mt)) == 0) {
395             break;
396         }
397         if (cnt) {
398             sleep(3);
399         }
400     }
401     return rc;
402 }
403
404 #if !defined(HAVE_BROKEN_FSF)
405 /*
406  * Forward space the tape device count files.
407  */
408 int
409 tape_tapefd_fsf(
410     int fd,
411     off_t count)
412 {
413     struct mtop mt;
414
415     if ((count > (off_t)INT_MAX) || (count < (off_t)INT_MIN)) {
416 #ifdef EOVERFLOW
417             errno = EOVERFLOW;
418 #else
419             errno = EINVAL;
420 #endif
421         return -1;
422     }
423
424     mt.mt_op = MTFSF;
425     mt.mt_count = (int)count;
426
427     return ioctl(fd, MTIOCTOP, &mt);
428 }
429 #endif
430
431 /*
432  * Write some number of end of file marks (a.k.a. tape marks).
433  *
434  * write <count> filemarks on the tape.
435  */
436 int
437 tape_tapefd_weof(
438     int fd,
439     off_t count)
440 {
441     struct mtop mt;
442
443     if ((count > (off_t)INT_MAX) || (count < (off_t)INT_MIN)) {
444 #ifdef EOVERFLOW
445             errno = EOVERFLOW;
446 #else
447             errno = EINVAL;
448 #endif
449         return -1;
450     }
451
452     mt.mt_op = MTWEOF;
453     mt.mt_count = (int)count;
454
455     return ioctl(fd, MTIOCTOP, &mt);
456 }
457
458 #endif /* !XENIX_TAPEIO */                                              /* } */
459 #endif /* !AIX_TAPEIO */                                                /* } */
460 #endif /* !UWARE_TAPEIO */                                              /* } */
461
462 /*
463  * At this point we have pulled in every conceivable #include file :-),
464  * so now come the more general routines with minimal #ifdef-ing.
465  */
466
467 #ifdef HAVE_LINUX_ZFTAPE_H
468 /*
469  * is_zftape(filename) checks if filename is a valid ftape device name.
470  */
471 int
472 is_zftape(
473     const char *filename)
474 {
475     if (strncmp(filename, "/dev/nftape", 11) == 0) return(1);
476     if (strncmp(filename, "/dev/nqft",    9) == 0) return(1);
477     if (strncmp(filename, "/dev/nrft",    9) == 0) return(1);
478     return(0);
479 }
480 #endif /* HAVE_LINUX_ZFTAPE_H */
481
482 int
483 tape_tape_open(
484     char *filename,
485     int flags,
486     mode_t mask)
487 {
488     int ret;
489     time_t timeout = 200;
490     unsigned delay = 2;
491
492     if ((flags & 3) != O_RDONLY) {
493         flags &= ~3;
494         flags |= O_RDWR;
495     }
496     ret = open(filename, flags, mask);
497     while (ret < 0) {
498         if ((errno != EAGAIN) && (errno != EBUSY) && (errno != EINTR)) {
499             /*
500              * Open failed completely: just return
501              */
502             fprintf(stderr, "Opening tapedev %s: got error %s.\n",
503                         filename, strerror(errno));
504             return -1;
505         }
506
507         /*
508          * if tape open fails with errno==EAGAIN, EBUSY or EINTR, it
509          * may be worth retrying a few seconds later.
510          */
511         timeout -= delay;
512         if (timeout <= 0) {
513             /* Open failed: just return */
514             fprintf(stderr, "Opening tapedev %s: not ready.\n", filename);
515             return -1;
516         }
517
518         if (delay < 16)
519             delay *= 2;
520
521         sleep(delay);
522         ret = open(filename, flags, mask);
523     }
524
525 #ifdef MTIOCGET
526     /* Now check that we opened a tape device. */
527     {
528         struct mtget mt;
529
530         memset(&mt, 0, SIZEOF(mt));
531         if (ioctl(ret, MTIOCGET, &mt) < 0) {
532             close(ret);
533             fprintf(stderr, "tapedev %s is not a tape device!\n", filename);
534             return -1;
535         }
536
537 #ifdef GMT_ONLINE
538         if (!GMT_ONLINE(mt.mt_gstat)) {
539             close(ret);
540             fprintf(stderr, "tapedev %s is offline or has no loaded tape.\n",
541                     filename);
542             return -1;
543         }
544 #endif /* GMT_ONLINE */
545     }
546 #endif /* MTIOCGET */
547
548
549 #ifdef HAVE_LINUX_ZFTAPE_H
550     /*
551      * switch the block size for the zftape driver (3.04d)
552      * (its default is 10kb and not 32kb)
553      *        A. Gebhardt <albrecht.gebhardt@uni-klu.ac.at>
554      */
555     if (is_zftape(filename) == 1) {
556         struct mtop mt;
557
558         mt.mt_op = MTSETBLK;
559         mt.mt_count = 32 * 1024;                /* should be blocksize ??? */
560         ioctl(ret, MTIOCTOP, &mt);
561     }
562 #endif /* HAVE_LINUX_ZFTAPE_H */
563     return ret;
564 }
565
566 ssize_t
567 tape_tapefd_read(
568     int fd,
569     void *buffer,
570     size_t count)
571 {
572     return read(fd, buffer, count);
573 }
574
575 ssize_t
576 tape_tapefd_write(
577     int fd,
578     const void *buffer,
579     size_t count)
580 {
581     return write(fd, buffer, count);
582 }
583
584 int
585 tape_tapefd_close(
586     int fd)
587 {
588     return close(fd);
589
590
591 void
592 tape_tapefd_resetofs(
593     int fd)
594 {
595     /*
596      * this *should* be a no-op on the tape, but resets the kernel's view
597      * of the file offset, preventing it from barfing should we pass the
598      * filesize limit (eg OSes with 2 GB filesize limits) on a long tape.
599      */
600     if (lseek(fd, (off_t)0, SEEK_SET) < 0) {
601         dbprintf(("tape_tapefd_resetofs: lseek failed: <%s>\n",
602                   strerror(errno)));
603     }
604 }
605
606 int
607 tape_tapefd_status(
608     int fd,
609     struct am_mt_status *stat)
610 {
611     int res;
612     int anything_valid = 0;
613 #if defined(MTIOCGET)
614     struct mtget buf;
615 #endif
616
617     memset((void *)stat, 0, SIZEOF(*stat));
618
619 #if defined(MTIOCGET)                                                   /* { */
620     res = ioctl(fd,MTIOCGET,&buf);
621     if (res >= 0) {
622         /*@ignore@*/
623 #ifdef MT_ONL                                                           /* { */
624         /* IRIX-ish system */
625         anything_valid = 1;
626         stat->online_valid = 1;
627         stat->online = (0 != (buf.mt_dposn & MT_ONL));
628         stat->bot_valid = 1;
629         stat->bot = (0 != (buf.mt_dposn & MT_BOT));
630         stat->eot_valid = 1;
631         stat->eot = (0 != (buf.mt_dposn & MT_EOT));
632         stat->protected_valid = 1;
633         stat->protected = (0 != (buf.mt_dposn & MT_WPROT));
634 #else                                                                   /* }{ */
635 #ifdef GMT_ONLINE                                                       /* { */
636         /* Linux-ish system */
637         anything_valid = 1;
638         stat->online_valid = 1;
639         stat->online = (0 != GMT_ONLINE(buf.mt_gstat));
640         stat->bot_valid = 1;
641         stat->bot = (0 != GMT_BOT(buf.mt_gstat));
642         stat->eot_valid = 1;
643         stat->eot = (0 != GMT_EOT(buf.mt_gstat));
644         stat->protected_valid = 1;
645         stat->protected = (0 != GMT_WR_PROT(buf.mt_gstat));
646 #else                                                                   /* }{ */
647 #ifdef DEV_BOM                                                          /* { */
648         /* OSF1-ish system */
649         anything_valid = 1;
650         stat->online_valid = 1;
651         stat->online = (0 == (DEV_OFFLINE & buf.mt_dsreg));
652         stat->bot_valid = 1;
653         stat->bot = (0 != (DEV_BOM & buf.mt_dsreg));
654         stat->protected_valid = 1;
655         stat->protected = (0 != (DEV_WRTLCK & buf.mt_dsreg));
656 #else                                                                   /* }{ */
657         /* Solaris, minix, etc. */
658         anything_valid = 1;
659         stat->online_valid = 1;
660         stat->online = 1;                       /* ioctl fails otherwise */
661 #ifdef HAVE_MT_DSREG
662         stat->device_status_valid = 1;
663         stat->device_status_size = SIZEOF(buf.mt_dsreg);
664         stat->device_status = (unsigned long)buf.mt_dsreg;
665 #endif
666 #ifdef HAVE_MT_ERREG
667         stat->error_status_valid = 1;
668         stat->error_status_size = SIZEOF(buf.mt_erreg);
669         stat->error_status = (unsigned long)buf.mt_erreg;
670 #endif
671 #if defined(HAVE_MT_FLAGS) && defined(MTF_SCSI)                 /* { */
672         /* 
673          * On Solaris, the file/block number fields are only valid if
674          * the driver is SCSI.  And in that case, the dsreg value is
675          * not useful (it is a retry count).
676          */
677         if(buf.mt_flags & MTF_SCSI) {
678             stat->device_status_valid = 0;
679 #ifdef HAVE_MT_FILENO
680             stat->fileno_valid = 1;
681             stat->fileno = (long)buf.mt_fileno;
682 #endif
683 #ifdef HAVE_MT_BLKNO
684             stat->blkno_valid = 1;
685             stat->blkno = (long)buf.mt_blkno;
686 #endif
687         }
688 #endif                                                                  /* } */
689 #endif                                                                  /* } */
690 #endif                                                                  /* } */
691 #endif                                                                  /* } */
692         /*@end@*/
693     }
694 #endif                                                                  /* } */
695
696     /*
697      * If we did not find any valid information, do a stat on the device
698      * and if that returns successfully, assume it is at least online.
699      */
700     if(!anything_valid) {
701         struct stat sbuf;
702
703         res = fstat(fd, &sbuf);
704         stat->online_valid = 1;
705         stat->online = (char)(res == 0);
706     }
707
708     return res;
709 }
710
711 int
712 tape_tape_stat(
713      char *filename,
714      struct stat *buf)
715 {
716      return stat(filename, buf);
717 }
718
719 int
720 tape_tape_access(
721      char *filename,
722      int mode)
723 {
724      return access(filename, mode);
725 }
726
727 int 
728 tape_tapefd_can_fork(
729     int fd)
730 {
731     (void)fd;   /* Quiet unused parameter warning */
732
733     return 1;
734 }
735