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