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.18 2006/08/22 14:19:39 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
83 buflen = getconf_readblocksize() * 1024;
84 buffer = alloc(buflen);
87 while((len = tapefd_read(fd, buffer, buflen)) > 0) {}
97 #ifdef UWARE_TAPEIO /* { */
102 * Rewind a tape to the beginning.
110 return ioctl(fd, T_RWD, &st);
114 * Rewind and unload a tape.
122 return ioctl(fd, T_OFFL, &st);
125 #if !defined(HAVE_BROKEN_FSF)
127 * Forward space the tape device count files.
137 while (--count >= 0) {
138 if ((status = ioctl(fd, T_SFF, &st)) != 0) {
148 * Write some number of end of file marks (a.k.a. tape marks).
158 while (--count >= (off_t)0) {
159 if ((status = ioctl(fd, T_WRFILEM, &st)) != 0) {
168 #ifdef AIX_TAPEIO /* { */
170 #include <sys/tape.h>
173 * Rewind a tape to the beginning.
184 return ioctl(fd, STIOCTOP, &st);
188 * Rewind and unload a tape.
199 return ioctl(fd, STIOCTOP, &st);
202 #if !defined(HAVE_BROKEN_FSF)
204 * Forward space the tape device count files.
213 if ((count > (off_t)INT_MAX) || (count < (off_t)INT_MIN)) {
223 st.st_count = (int)count;
225 return ioctl(fd, STIOCTOP, &st);
230 * Write some number of end of file marks (a.k.a. tape marks).
239 if ((count > (off_t)INT_MAX) || (count < (off_t)INT_MIN)) {
249 st.st_count = (int)count;
251 return ioctl(fd, STIOCTOP, &st);
254 #else /* AIX_TAPEIO */ /* }{ */
255 #ifdef XENIX_TAPEIO /* { */
257 #include <sys/tape.h>
260 * Rewind a tape to the beginning.
268 return ioctl(fd, MT_REWIND, &st);
272 * Rewind and unload a tape.
290 return ioctl(fd, f, &st);
293 #if !defined(HAVE_BROKEN_FSF)
295 * Forward space the tape device count files.
305 while (--count >= 0) {
306 if ((status = ioctl(fd, MT_RFM, &st)) != 0) {
316 * Write some number of end of file marks (a.k.a. tape marks).
327 while (--count >= 0) {
328 if ((status = ioctl(fd, MT_WFM, &st)) != 0) {
336 #else /* ! AIX_TAPEIO && !XENIX_TAPEIO */ /* }{ */
338 #include <sys/mtio.h>
341 * Rewind a tape to the beginning.
354 * EXB-8200 drive on FreeBSD can fail to rewind, but retrying won't
355 * hurt, and it will usually even work!
357 for(cnt = 10; cnt >= 0; --cnt) {
358 if ((rc = ioctl(fd, MTIOCTOP, &mt)) == 0) {
369 * Rewind and unload a tape.
384 mt.mt_op = syntax error;
390 * EXB-8200 drive on FreeBSD can fail to unload, but retrying won't
391 * hurt, and it will usually even work!
393 for(cnt = 10; cnt >= 0; --cnt) {
394 if ((rc = ioctl(fd, MTIOCTOP, &mt)) == 0) {
404 #if !defined(HAVE_BROKEN_FSF)
406 * Forward space the tape device count files.
415 if ((count > (off_t)INT_MAX) || (count < (off_t)INT_MIN)) {
425 mt.mt_count = (int)count;
427 return ioctl(fd, MTIOCTOP, &mt);
432 * Write some number of end of file marks (a.k.a. tape marks).
434 * write <count> filemarks on the tape.
443 if ((count > (off_t)INT_MAX) || (count < (off_t)INT_MIN)) {
453 mt.mt_count = (int)count;
455 return ioctl(fd, MTIOCTOP, &mt);
458 #endif /* !XENIX_TAPEIO */ /* } */
459 #endif /* !AIX_TAPEIO */ /* } */
460 #endif /* !UWARE_TAPEIO */ /* } */
463 * At this point we have pulled in every conceivable #include file :-),
464 * so now come the more general routines with minimal #ifdef-ing.
467 #ifdef HAVE_LINUX_ZFTAPE_H
469 * is_zftape(filename) checks if filename is a valid ftape device name.
473 const char *filename)
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);
480 #endif /* HAVE_LINUX_ZFTAPE_H */
489 time_t timeout = 200;
492 if ((flags & 3) != O_RDONLY) {
496 ret = open(filename, flags, mask);
498 if ((errno != EAGAIN) && (errno != EBUSY) && (errno != EINTR)) {
500 * Open failed completely: just return
502 fprintf(stderr, "Opening tapedev %s: got error %s.\n",
503 filename, strerror(errno));
508 * if tape open fails with errno==EAGAIN, EBUSY or EINTR, it
509 * may be worth retrying a few seconds later.
513 /* Open failed: just return */
514 fprintf(stderr, "Opening tapedev %s: not ready.\n", filename);
522 ret = open(filename, flags, mask);
526 /* Now check that we opened a tape device. */
530 memset(&mt, 0, SIZEOF(mt));
531 if (ioctl(ret, MTIOCGET, &mt) < 0) {
533 fprintf(stderr, "tapedev %s is not a tape device!\n", filename);
538 if (!GMT_ONLINE(mt.mt_gstat)) {
540 fprintf(stderr, "tapedev %s is offline or has no loaded tape.\n",
544 #endif /* GMT_ONLINE */
546 #endif /* MTIOCGET */
549 #ifdef HAVE_LINUX_ZFTAPE_H
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>
555 if (is_zftape(filename) == 1) {
559 mt.mt_count = 32 * 1024; /* should be blocksize ??? */
560 ioctl(ret, MTIOCTOP, &mt);
562 #endif /* HAVE_LINUX_ZFTAPE_H */
572 return read(fd, buffer, count);
581 return write(fd, buffer, count);
592 tape_tapefd_resetofs(
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.
600 if (lseek(fd, (off_t)0, SEEK_SET) < 0) {
601 dbprintf(("tape_tapefd_resetofs: lseek failed: <%s>\n",
609 struct am_mt_status *stat)
612 int anything_valid = 0;
613 #if defined(MTIOCGET)
617 memset((void *)stat, 0, SIZEOF(*stat));
619 #if defined(MTIOCGET) /* { */
620 res = ioctl(fd,MTIOCGET,&buf);
623 #ifdef MT_ONL /* { */
624 /* IRIX-ish system */
626 stat->online_valid = 1;
627 stat->online = (0 != (buf.mt_dposn & MT_ONL));
629 stat->bot = (0 != (buf.mt_dposn & MT_BOT));
631 stat->eot = (0 != (buf.mt_dposn & MT_EOT));
632 stat->protected_valid = 1;
633 stat->protected = (0 != (buf.mt_dposn & MT_WPROT));
635 #ifdef GMT_ONLINE /* { */
636 /* Linux-ish system */
638 stat->online_valid = 1;
639 stat->online = (0 != GMT_ONLINE(buf.mt_gstat));
641 stat->bot = (0 != GMT_BOT(buf.mt_gstat));
643 stat->eot = (0 != GMT_EOT(buf.mt_gstat));
644 stat->protected_valid = 1;
645 stat->protected = (0 != GMT_WR_PROT(buf.mt_gstat));
647 #ifdef DEV_BOM /* { */
648 /* OSF1-ish system */
650 stat->online_valid = 1;
651 stat->online = (0 == (DEV_OFFLINE & buf.mt_dsreg));
653 stat->bot = (0 != (DEV_BOM & buf.mt_dsreg));
654 stat->protected_valid = 1;
655 stat->protected = (0 != (DEV_WRTLCK & buf.mt_dsreg));
657 /* Solaris, minix, etc. */
659 stat->online_valid = 1;
660 stat->online = 1; /* ioctl fails otherwise */
662 stat->device_status_valid = 1;
663 stat->device_status_size = SIZEOF(buf.mt_dsreg);
664 stat->device_status = (unsigned long)buf.mt_dsreg;
667 stat->error_status_valid = 1;
668 stat->error_status_size = SIZEOF(buf.mt_erreg);
669 stat->error_status = (unsigned long)buf.mt_erreg;
671 #if defined(HAVE_MT_FLAGS) && defined(MTF_SCSI) /* { */
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).
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;
684 stat->blkno_valid = 1;
685 stat->blkno = (long)buf.mt_blkno;
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.
700 if(!anything_valid) {
703 res = fstat(fd, &sbuf);
704 stat->online_valid = 1;
705 stat->online = (char)(res == 0);
716 return stat(filename, buf);
724 return access(filename, mode);
728 tape_tapefd_can_fork(
731 (void)fd; /* Quiet unused parameter warning */