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
28 /* NOTE: this driver is *deprecated* and should not be used. See the Device API
29 * in device-src/ for the new implementation.
33 * $Id: output-tape.c,v 1.18 2006/08/22 14:19:39 martinea Exp $
35 * tapeio.c virtual tape interface for normal tape drives.
52 #include "output-tape.h"
55 #include "fileheader.h"
64 =======================================================================
65 ** Here are the ioctl() interface routines, which are #ifdef-ed
66 ** heavily by platform.
67 =======================================================================
70 #if defined(HAVE_BROKEN_FSF) /* { */
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
87 buflen = getconf_readblocksize() * 1024;
88 buffer = alloc(buflen);
91 while((len = tapefd_read(fd, buffer, buflen)) > 0) {}
101 #ifdef WANT_TAPE_UWARE /* { */
103 #include <sys/tape.h>
106 * Rewind a tape to the beginning.
114 return ioctl(fd, T_RWD, &st);
118 * Rewind and unload a tape.
126 return ioctl(fd, T_OFFL, &st);
129 #if !defined(HAVE_BROKEN_FSF)
131 * Forward space the tape device count files.
141 while (--count >= 0) {
142 if ((status = ioctl(fd, T_SFF, &st)) != 0) {
152 * Write some number of end of file marks (a.k.a. tape marks).
162 while (--count >= (off_t)0) {
163 if ((status = ioctl(fd, T_WRFILEM, &st)) != 0) {
172 #ifdef WANT_TAPE_AIX /* { */
174 #include <sys/tape.h>
177 * Rewind a tape to the beginning.
188 return ioctl(fd, STIOCTOP, &st);
192 * Rewind and unload a tape.
203 return ioctl(fd, STIOCTOP, &st);
206 #if !defined(HAVE_BROKEN_FSF)
208 * Forward space the tape device count files.
217 if ((count > (off_t)INT_MAX) || (count < (off_t)INT_MIN)) {
227 st.st_count = (int)count;
229 return ioctl(fd, STIOCTOP, &st);
234 * Write some number of end of file marks (a.k.a. tape marks).
243 if ((count > (off_t)INT_MAX) || (count < (off_t)INT_MIN)) {
253 st.st_count = (int)count;
255 return ioctl(fd, STIOCTOP, &st);
258 #else /* WANT_TAPE_AIX */ /* }{ */
259 #ifdef WANT_TAPE_XENIX /* { */
261 #include <sys/tape.h>
264 * Rewind a tape to the beginning.
272 return ioctl(fd, MT_REWIND, &st);
276 * Rewind and unload a tape.
294 return ioctl(fd, f, &st);
297 #if !defined(HAVE_BROKEN_FSF)
299 * Forward space the tape device count files.
309 while (--count >= 0) {
310 if ((status = ioctl(fd, MT_RFM, &st)) != 0) {
320 * Write some number of end of file marks (a.k.a. tape marks).
331 while (--count >= 0) {
332 if ((status = ioctl(fd, MT_WFM, &st)) != 0) {
340 #else /* ! WANT_TAPE_AIX && !WANT_TAPE_XENIX */ /* }{ */
342 #include <sys/mtio.h>
345 * Rewind a tape to the beginning.
358 * EXB-8200 drive on FreeBSD can fail to rewind, but retrying won't
359 * hurt, and it will usually even work!
361 for(cnt = 10; cnt >= 0; --cnt) {
362 if ((rc = ioctl(fd, MTIOCTOP, &mt)) == 0) {
373 * Rewind and unload a tape.
388 mt.mt_op = syntax error;
394 * EXB-8200 drive on FreeBSD can fail to unload, but retrying won't
395 * hurt, and it will usually even work!
397 for(cnt = 10; cnt >= 0; --cnt) {
398 if ((rc = ioctl(fd, MTIOCTOP, &mt)) == 0) {
408 #if !defined(HAVE_BROKEN_FSF)
410 * Forward space the tape device count files.
419 if ((count > (off_t)INT_MAX) || (count < (off_t)INT_MIN)) {
429 mt.mt_count = (int)count;
431 return ioctl(fd, MTIOCTOP, &mt);
436 * Write some number of end of file marks (a.k.a. tape marks).
438 * write <count> filemarks on the tape.
447 if ((count > (off_t)INT_MAX) || (count < (off_t)INT_MIN)) {
457 mt.mt_count = (int)count;
459 return ioctl(fd, MTIOCTOP, &mt);
462 #endif /* !WANT_TAPE_XENIX */ /* } */
463 #endif /* !WANT_TAPE_AIX */ /* } */
464 #endif /* !WANT_TAPE_UWARE */ /* } */
467 * At this point we have pulled in every conceivable #include file :-),
468 * so now come the more general routines with minimal #ifdef-ing.
471 #ifdef HAVE_LINUX_ZFTAPE_H
473 * is_zftape(filename) checks if filename is a valid ftape device name.
477 const char *filename)
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);
484 #endif /* HAVE_LINUX_ZFTAPE_H */
493 time_t timeout = 200;
496 if ((flags & 3) != O_RDONLY) {
500 ret = open(filename, flags, mask);
502 if ((errno != EAGAIN) && (errno != EBUSY) && (errno != EINTR)) {
504 * Open failed completely: just return
506 g_fprintf(stderr, _("Opening tapedev %s: got error %s.\n"),
507 filename, strerror(errno));
512 * if tape open fails with errno==EAGAIN, EBUSY or EINTR, it
513 * may be worth retrying a few seconds later.
517 /* Open failed: just return */
518 g_fprintf(stderr, _("Opening tapedev %s: not ready.\n"), filename);
526 ret = open(filename, flags, mask);
530 /* Now check that we opened a tape device. */
534 memset(&mt, 0, SIZEOF(mt));
535 if (ioctl(ret, MTIOCGET, &mt) < 0) {
537 g_fprintf(stderr, _("tapedev %s is not a tape device!\n"), filename);
542 if (!GMT_ONLINE(mt.mt_gstat)) {
544 g_fprintf(stderr, _("tapedev %s is offline or has no loaded tape.\n"),
548 #endif /* GMT_ONLINE */
550 #endif /* MTIOCGET */
553 #ifdef HAVE_LINUX_ZFTAPE_H
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>
559 if (is_zftape(filename) == 1) {
563 mt.mt_count = 32 * 1024; /* should be blocksize ??? */
564 ioctl(ret, MTIOCTOP, &mt);
566 #endif /* HAVE_LINUX_ZFTAPE_H */
576 return read(fd, buffer, count);
585 return write(fd, buffer, count);
596 tape_tapefd_resetofs(
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.
604 if (lseek(fd, (off_t)0, SEEK_SET) < 0) {
605 dbprintf(_("tape_tapefd_resetofs: lseek failed: <%s>\n"),
613 struct am_mt_status *stat)
616 int anything_valid = 0;
617 #if defined(MTIOCGET)
621 memset((void *)stat, 0, SIZEOF(*stat));
623 #if defined(MTIOCGET) /* { */
624 res = ioctl(fd,MTIOCGET,&buf);
627 #ifdef MT_ONL /* { */
628 /* IRIX-ish system */
630 stat->online_valid = 1;
631 stat->online = (0 != (buf.mt_dposn & MT_ONL));
633 stat->bot = (0 != (buf.mt_dposn & MT_BOT));
635 stat->eot = (0 != (buf.mt_dposn & MT_EOT));
636 stat->protected_valid = 1;
637 stat->protected = (0 != (buf.mt_dposn & MT_WPROT));
639 #ifdef GMT_ONLINE /* { */
640 /* Linux-ish system */
642 stat->online_valid = 1;
643 stat->online = (0 != GMT_ONLINE(buf.mt_gstat));
645 stat->bot = (0 != GMT_BOT(buf.mt_gstat));
647 stat->eot = (0 != GMT_EOT(buf.mt_gstat));
648 stat->protected_valid = 1;
649 stat->protected = (0 != GMT_WR_PROT(buf.mt_gstat));
651 #ifdef DEV_BOM /* { */
652 /* OSF1-ish system */
654 stat->online_valid = 1;
655 stat->online = (0 == (DEV_OFFLINE & buf.mt_dsreg));
657 stat->bot = (0 != (DEV_BOM & buf.mt_dsreg));
658 stat->protected_valid = 1;
659 stat->protected = (0 != (DEV_WRTLCK & buf.mt_dsreg));
661 /* Solaris, minix, etc. */
663 stat->online_valid = 1;
664 stat->online = 1; /* ioctl fails otherwise */
666 stat->device_status_valid = 1;
667 stat->device_status_size = SIZEOF(buf.mt_dsreg);
668 stat->device_status = (unsigned long)buf.mt_dsreg;
671 stat->error_status_valid = 1;
672 stat->error_status_size = SIZEOF(buf.mt_erreg);
673 stat->error_status = (unsigned long)buf.mt_erreg;
675 #if defined(HAVE_MT_FLAGS) && defined(MTF_SCSI) /* { */
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).
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;
688 stat->blkno_valid = 1;
689 stat->blkno = (long)buf.mt_blkno;
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.
704 if(!anything_valid) {
707 res = fstat(fd, &sbuf);
708 stat->online_valid = 1;
709 stat->online = (char)(res == 0);
720 return stat(filename, buf);
728 return access(filename, mode);
732 tape_tapefd_can_fork(
735 (void)fd; /* Quiet unused parameter warning */