2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998 University of Maryland at College Park
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.
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.
23 * Author: James da Silva, Systems Design and Analysis Group
24 * Computer Science Department
25 * University of Maryland at College Park
29 * $Id: output-tape.c,v 1.1.2.6.2.7 2003/03/06 21:44:21 martinea Exp $
31 * tapeio.c virtual tape interface for normal tape drives.
48 #include "output-tape.h"
51 #include "fileheader.h"
60 =======================================================================
61 ** Here are the ioctl() interface routines, which are #ifdef-ed
62 ** heavily by platform.
63 =======================================================================
66 #if defined(HAVE_BROKEN_FSF) /* { */
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
75 tape_tapefd_fsf(fd, count)
83 buflen = MAX_TAPE_BLOCK_BYTES;
84 buffer = alloc(buflen);
87 while((len = tapefd_read(fd, buffer, buflen)) > 0) {}
97 #ifdef UWARE_TAPEIO /* { */
102 * Rewind a tape to the beginning.
105 tape_tapefd_rewind(fd)
110 return ioctl(fd, T_RWD, &st);
114 * Rewind and unload a tape.
117 tape_tapefd_unload(fd)
122 return ioctl(fd, T_OFFL, &st);
125 #if !defined(HAVE_BROKEN_FSF)
127 * Forward space the tape device count files.
129 int tape_tapefd_fsf(fd, count)
135 while (--count >= 0) {
136 if ((status = ioctl(fd, T_SFF, &st)) != 0) {
146 * Write some number of end of file marks (a.k.a. tape marks).
149 tape_tapefd_weof(fd, count)
155 while (--count >= 0) {
156 if ((status = ioctl(fd, T_WRFILEM, &st)) != 0) {
165 #ifdef AIX_TAPEIO /* { */
167 #include <sys/tape.h>
170 * Rewind a tape to the beginning.
173 tape_tapefd_rewind(fd)
181 return ioctl(fd, STIOCTOP, &st);
185 * Rewind and unload a tape.
188 tape_tapefd_unload(fd)
196 return ioctl(fd, STIOCTOP, &st);
199 #if !defined(HAVE_BROKEN_FSF)
201 * Forward space the tape device count files.
204 tape_tapefd_fsf(fd, count)
212 return ioctl(fd, STIOCTOP, &st);
217 * Write some number of end of file marks (a.k.a. tape marks).
220 tape_tapefd_weof(fd, count)
228 return ioctl(fd, STIOCTOP, &st);
231 #else /* AIX_TAPEIO */ /* }{ */
232 #ifdef XENIX_TAPEIO /* { */
234 #include <sys/tape.h>
237 * Rewind a tape to the beginning.
240 tape_tapefd_rewind(fd)
245 return ioctl(fd, MT_REWIND, &st);
249 * Rewind and unload a tape.
252 tape_tapefd_unload(fd)
267 return ioctl(fd, f, &st);
270 #if !defined(HAVE_BROKEN_FSF)
272 * Forward space the tape device count files.
275 tape_tapefd_fsf(fd, count)
281 while (--count >= 0) {
282 if ((status = ioctl(fd, MT_RFM, &st)) != 0) {
292 * Write some number of end of file marks (a.k.a. tape marks).
295 tape_tapefd_weof(fd, count)
302 while (--count >= 0) {
303 if ((status = ioctl(fd, MT_WFM, &st)) != 0) {
311 #else /* ! AIX_TAPEIO && !XENIX_TAPEIO */ /* }{ */
313 #include <sys/mtio.h>
316 * Rewind a tape to the beginning.
319 tape_tapefd_rewind(fd)
329 * EXB-8200 drive on FreeBSD can fail to rewind, but retrying won't
330 * hurt, and it will usually even work!
332 for(cnt = 10; cnt >= 0; --cnt) {
333 if ((rc = ioctl(fd, MTIOCTOP, &mt)) == 0) {
344 * Rewind and unload a tape.
347 tape_tapefd_unload(fd)
359 mt.mt_op = syntax error;
365 * EXB-8200 drive on FreeBSD can fail to unload, but retrying won't
366 * hurt, and it will usually even work!
368 for(cnt = 10; cnt >= 0; --cnt) {
369 if ((rc = ioctl(fd, MTIOCTOP, &mt)) == 0) {
379 #if !defined(HAVE_BROKEN_FSF)
381 * Forward space the tape device count files.
384 tape_tapefd_fsf(fd, count)
392 return ioctl(fd, MTIOCTOP, &mt);
397 * Write some number of end of file marks (a.k.a. tape marks).
399 int tape_tapefd_weof(fd, count)
402 * write <count> filemarks on the tape.
410 return ioctl(fd, MTIOCTOP, &mt);
413 #endif /* !XENIX_TAPEIO */ /* } */
414 #endif /* !AIX_TAPEIO */ /* } */
415 #endif /* !UWARE_TAPEIO */ /* } */
418 * At this point we have pulled in every conceivable #include file :-),
419 * so now come the more general routines with minimal #ifdef-ing.
422 #ifdef HAVE_LINUX_ZFTAPE_H
424 * is_zftape(filename) checks if filename is a valid ftape device name.
428 const char *filename;
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);
435 #endif /* HAVE_LINUX_ZFTAPE_H */
437 int tape_tape_open(filename, flags, mask)
442 int ret = 0, delay = 2, timeout = 200;
444 if ((flags & 3) != O_RDONLY) {
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. */
475 #ifdef HAVE_LINUX_ZFTAPE_H
477 * switch the block size for the zftape driver (3.04d)
478 * (its default is 10kb and not TAPE_BLOCK_BYTES=32kb)
479 * A. Gebhardt <albrecht.gebhardt@uni-klu.ac.at>
481 if (ret >= 0 && is_zftape(filename) == 1) {
485 mt.mt_count = 32 * 1024; /* wrong? tape blocksize??? */
486 ioctl(ret, MTIOCTOP, &mt);
488 #endif /* HAVE_LINUX_ZFTAPE_H */
492 ssize_t tape_tapefd_read(fd, buffer, count)
497 return read(fd, buffer, count);
500 ssize_t tape_tapefd_write(fd, buffer, count)
505 return write(fd, buffer, count);
508 int tape_tapefd_close(fd)
514 void tape_tapefd_resetofs(fd)
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.
522 lseek(fd, (off_t) 0L, SEEK_SET);
526 tape_tapefd_status(fd, stat)
528 struct am_mt_status *stat;
531 int anything_valid = 0;
532 #if defined(MTIOCGET)
536 memset((void *)stat, 0, sizeof(*stat));
538 #if defined(MTIOCGET) /* { */
539 res = ioctl(fd,MTIOCGET,&buf);
542 #ifdef MT_ONL /* { */
543 /* IRIX-ish system */
545 stat->online_valid = 1;
546 stat->online = (0 != (buf.mt_dposn & MT_ONL));
548 stat->bot = (0 != (buf.mt_dposn & MT_BOT));
550 stat->eot = (0 != (buf.mt_dposn & MT_EOT));
551 stat->protected_valid = 1;
552 stat->protected = (0 != (buf.mt_dposn & MT_WPROT));
554 #ifdef GMT_ONLINE /* { */
555 /* Linux-ish system */
557 stat->online_valid = 1;
558 stat->online = (0 != GMT_ONLINE(buf.mt_gstat));
560 stat->bot = (0 != GMT_BOT(buf.mt_gstat));
562 stat->eot = (0 != GMT_EOT(buf.mt_gstat));
563 stat->protected_valid = 1;
564 stat->protected = (0 != GMT_WR_PROT(buf.mt_gstat));
566 #ifdef DEV_BOM /* { */
567 /* OSF1-ish system */
569 stat->online_valid = 1;
570 stat->online = (0 == (DEV_OFFLINE & buf.mt_dsreg));
572 stat->bot = (0 != (DEV_BOM & buf.mt_dsreg));
573 stat->protected_valid = 1;
574 stat->protected = (0 != (DEV_WRTLCK & buf.mt_dsreg));
576 /* Solaris, minix, etc. */
578 stat->online_valid = 1;
579 stat->online = 1; /* ioctl fails otherwise */
581 stat->device_status_valid = 1;
582 stat->device_status_size = sizeof(buf.mt_dsreg);
583 stat->device_status = (unsigned long)buf.mt_dsreg;
586 stat->error_status_valid = 1;
587 stat->error_status_size = sizeof(buf.mt_erreg);
588 stat->error_status = (unsigned long)buf.mt_erreg;
590 #if defined(HAVE_MT_FLAGS) && defined(MTF_SCSI) /* { */
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).
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;
603 stat->blkno_valid = 1;
604 stat->blkno = (long)buf.mt_blkno;
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.
618 if(!anything_valid && res == 0) {
621 res = fstat(fd, &sbuf);
623 stat->online_valid = 1;
624 stat->online = (res == 0);
630 int tape_tape_stat(filename, buf)
634 return stat(filename, buf);
637 int tape_tape_access(filename, mode)
641 return access(filename, mode);
645 tape_tapefd_can_fork(fd)