diff --git a/Makefile b/Makefile
index 65f4a43..3159cc2 100644
--- a/Makefile
+++ b/Makefile
@@ -34,13 +34,14 @@ MODE=4755
BINDIR=/usr/bin
MANSEC=1
MANDIR=/usr/share/man/man$(MANSEC)
-DISTFILES=README vmsbackup.1 Makefile vmsbackup.c match.c NEWS build.com dclmain.c getoptmain.c vmsbackup.cld vmsbackup.h sysdep.h
+DISTFILES=README vmsbackup.1 Makefile vmsbackup.c match.c NEWS build.com dclmain.c getoptmain.c vmsbackup.cld vmsbackup.h sysdep.h tapeio.c
-vmsbackup: vmsbackup.o match.o getoptmain.o hexdump.o
+vmsbackup: vmsbackup.o match.o getoptmain.o hexdump.o tapeio.o
vmsbackup.o : vmsbackup.c
match.o : match.c
getoptmain.o : getoptmain.c
+tapeio.o : tapeio.c
install:
install -m $(MODE) -o $(OWNER) -s vmsbackup $(BINDIR)
diff --git a/tapeio.c b/tapeio.c
new file mode 100644
index 0000000..44b5775
--- /dev/null
+++ b/tapeio.c
@@ -0,0 +1,676 @@
+/*
+ Routines to do magtape I/O to local tapes, remote tapes, and tape image
+ files.
+
+ Copyright 1998, 1999 John Wilson and Eric Smith
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as published
+ by the Free Software Foundation. Note that permission is not granted
+ to redistribute this program under the terms of any other version of the
+ General Public License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+ 08/10/93 JMBW IBM mainframe TCP socket stuff (was using many files).
+ 07/08/94 JMBW Local magtape code.
+ 03/13/95 JMBW Converted to separate routines.
+ 07/19/98 JMBW Added support for "rmt" remote tape protocol.
+ 11/16/98 ELS Provide struct for per-instance variables.
+ 02/06/98 ELS Reorganization, and added skiprec and skipfile.
+*/
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include /* for lseek() SEEK_SET, SEEK_END under Linux */
+#include
+
+#ifdef _AIX /* maybe this will be enough to make it compile on AIX */
+#include
+#define MTWEOF STWEOF
+#define MTREW STREW
+#define MTFSR STFSR
+#define MTFSF STFSF
+#define MTBSR STRSR
+#define MTIOCTOP STIOCTOP
+/* not sure about these two (SCSI only): */
+#define MTSETBLK STSETBLK
+#define MTSETDENSITY STSETDENSITY
+#define mtop stop
+#elif __APPLE__
+#define MTWEOF 0
+#define MTREW 0
+#define MTFSR 0
+#define MTFSF 0
+#define MTBSR 0
+#define MTIOCTOP 0
+#define MTSETBLK 0
+#define MTSETDENSITY 0
+struct mtop { int mt_op; int mt_count; };
+#else
+#include
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#define MTSETBLK MTSETBSIZ
+#define MTSETDENSITY MTSETDNSTY
+#endif
+#endif
+
+#include "tapeio.h"
+
+
+#define TT_UNK 0
+#define TT_TAPE 1 /* honest to god tape drive */
+#define TT_IMAGE 2 /* file containing image of a tape */
+#define TT_RMT 3 /* rmt tape server */
+
+
+struct mtape_t
+{
+ int tape_type;
+ int tapefd; /* tape drive, file, or socket file descriptor */
+ int seek_ok;
+ int flags;
+
+ unsigned long bpi; /* tape density (for tape length msg) */
+ int waccess; /* NZ => tape opened for write access access */
+ unsigned long count; /* count of frames written to tape */
+
+ char netbuf[80]; /* buffer for net commands and responses */
+};
+
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/* default tape drive device name */
+#define TAPE "/dev/nst0"
+/* default tape density */
+#define BPI 1600
+
+
+/* magtape commands */
+static struct mtop mt_weof={ MTWEOF, 1 }; /* operation, count */
+static struct mtop mt_rew={ MTREW, 1 };
+static struct mtop mt_fsr={ MTFSR, 1 };
+static struct mtop mt_fsf={ MTFSF, 1 };
+static struct mtop mt_bsr={ MTBSR, 1 };
+/* SCSI only: */
+static struct mtop mt_setblk={ MTSETBLK, 0 }; /* blockize = 0 (variable) */
+static struct mtop mt_setden={ MTSETDENSITY, 0x02 }; /* density = 1600 */
+
+
+#define FAIL(msg) do { fprintf (stderr, msg); goto fail; } while (0)
+
+
+/* do a write and check the return status, punt on error */
+static void dowrite (int handle, void *buf, int len)
+{
+ if (write (handle, buf, len) != len)
+ {
+ perror ("?Error on write");
+ exit (1);
+ }
+}
+
+
+/* do a read and keep trying until we get all bytes */
+static void doread (int handle, void *buf, int len)
+{
+ int n;
+ while(len)
+ {
+ if ((n = read (handle, buf, len)) < 0)
+ {
+ perror("?Error on read");
+ exit (1);
+ }
+ if (n == 0)
+ {
+ fprintf (stderr, "?Unexpected end of file\n");
+ exit (1);
+ }
+ buf += n;
+ len -= n;
+ }
+}
+
+
+/* get response from "rmt" server */
+static int response (tape_handle_t mtape)
+{
+ char c, rc;
+ int n;
+
+ doread (mtape->tapefd, &rc, 1); /* get success/error code */
+ if (rc != 'A' && rc != 'E')
+ { /* must be Acknowledge or Error */
+ fprintf (stderr, "?Invalid rmt response code: %c\n",rc);
+ exit (1);
+ }
+
+ /* get numeric value (returned by both A and E responses) */
+ for (n=0;;)
+ {
+ doread (mtape->tapefd, &c, 1); /* get next digit */
+ if (c < '0' || c > '9')
+ break; /* not a digit */
+ n = n * 10 + (c - '0'); /* add new digit in */
+ /* ideally would check for overflow */
+ }
+ if (c != '\n')
+ { /* first non-digit char must be */
+ fprintf (stderr, "?Invalid rmt response terminator: %3.3o\n",
+ ((int) c) & 0377);
+ exit (1);
+ }
+ if (rc == 'A')
+ return (n); /* success, return value >=0 */
+ /* (unless overflowed) */
+ do
+ doread (mtape->tapefd, &c, 1);
+ while (c != '\n'); /* ignore until next LF */
+ errno = n; /* set error number */
+ return (-1);
+}
+
+
+/* send ioctl() command to local or remote tape drive */
+static int doioctl (tape_handle_t mtape, struct mtop *op)
+{
+ int len;
+
+ if (mtape->tape_type == TT_TAPE)
+ return (ioctl (mtape->tapefd, MTIOCTOP, op));
+ else
+ { /* "rmt" tape server */
+ /* form cmd (better hope remote MT_OP values are the same) */
+ len = sprintf (mtape->netbuf, "I%d\n%d\n", op->mt_op, op->mt_count);
+ dowrite (mtape->tapefd, mtape->netbuf, len);
+ return (response (mtape));
+ }
+}
+
+
+/* open the tape drive (or whatever) */
+/* "create" =1 to create if file, "writable" =1 to open with write access */
+tape_handle_t opentape (char *name, int create, int writable)
+{
+ char *p, *user, *port;
+ int len;
+ char *host = NULL;
+
+ tape_handle_t mtape = NULL;
+
+ mtape = (tape_handle_t) calloc (1, sizeof (struct mtape_t));
+ if (! mtape)
+ FAIL ("?can't allocate mtape struct\n");
+
+ mtape->bpi = BPI;
+
+ mtape->waccess = writable; /* remember if we're writing */
+ mtape->count = 0; /* nothing transferred yet */
+
+ /* get tape filename */
+ if (name == NULL)
+ name = getenv("TAPE"); /* get from environment */
+ if (name == NULL)
+ name = TAPE; /* or use our default */
+
+ /* just a file if no colon in filename */
+ if ((p = index (name, ':')) == NULL)
+ {
+ /* there's probably a better way to handle this, in case a file is really
+ a link to a tape drive -- handler index or something? */
+ if (strncmp (name, "/dev/", 5) == 0)
+ {
+ /* assume tape if starts with /dev/ */
+ mtape->tape_type = TT_TAPE;
+ mtape->tapefd = open (name, (writable ? O_RDWR : O_RDONLY), 0);
+ }
+ else
+ { /* otherwise file */
+ mtape->tape_type = TT_IMAGE;
+ if (strcmp (name, "-") ==0 )
+ { /* stdin/stdout */
+ if (writable)
+ mtape->tapefd=1;
+ else
+ mtape->tapefd=0;
+ }
+ else
+ {
+ if (create)
+ mtape->tapefd = open (name, O_CREAT | O_TRUNC |
+ O_WRONLY | O_BINARY, 0644);
+ else
+ {
+ mtape->tapefd = open (name, (writable ? O_RDWR : O_RDONLY) |
+ O_BINARY, 0);
+ mtape->seek_ok = 1;
+ }
+ }
+ }
+ if (mtape->tapefd < 0)
+ FAIL ("?can't open device or file\n");
+ }
+ else
+ { /* "rmt" tape server on remote host */
+ mtape->tape_type = TT_RMT;
+ /* split filename around ':' */
+ len = p-name;
+ port = p+1;
+
+ /* can't necessarily modify tape[] so copy it first */
+ if ((host = malloc (len + 1)) == NULL)
+ FAIL ("?can't allocate string for hostname\n");
+ strncpy (host, name, len); /* copy hostname */
+ host [len] = 0; /* tack on null */
+
+ /* connect to "rexec" server */
+ if ((p = index (host, '@')) == NULL)
+ {
+ p = host; /* no @, point at hostname */
+ user = NULL;
+ }
+ else
+ {
+ *p++ = '\0'; /* shoot out @, point at host name */
+ user = (*p != '\0') ? host : NULL; /* keep non-null user */
+ }
+#if !defined(__APPLE__) && !defined(__OpenBSD__)
+ if ((mtape->tapefd = rexec (&p, htons (512), user, NULL, "/etc/rmt",
+ (int *) NULL)) < 0)
+ FAIL ("?Connection failed\n");
+#endif
+
+ /* build rmt "open device" command */
+ if ((1 + strlen (port) + 1 + 1 + 1 + 1) > sizeof (mtape->netbuf))
+ FAIL ("?Device name too long\n");
+ len = sprintf (mtape->netbuf, "O%s\n%d\n", port, writable ? O_RDWR : O_RDONLY);
+ dowrite (mtape->tapefd, mtape->netbuf, len);
+ if (response (mtape) < 0)
+ FAIL ("?Error opening tape drive");
+ }
+
+ /* SCSI setup for local/remote tape drive */
+ if ((mtape->tape_type == TT_TAPE) ||
+ (mtape->tape_type == TT_RMT))
+ {
+ /* (ignore errors in case not SCSI) */
+ /* set variable record length mode */
+ doioctl (mtape, & mt_setblk);
+ /* set density to 1600 */
+ doioctl (mtape, & mt_setden);
+ }
+
+ if (host)
+ free (host);
+
+ return (mtape);
+
+ fail:
+ if (mtape)
+ {
+ if (host)
+ free (host);
+ free (mtape);
+ }
+ return (NULL);
+}
+
+
+/* close the tape drive */
+void closetape (tape_handle_t mtape)
+{
+ if (mtape->waccess)
+ { /* opened for create/append */
+ tapemark (mtape); /* add one more tape mark */
+ /* (should have one already) */
+ }
+ if (mtape->tape_type == TT_RMT)
+ {
+ dowrite (mtape->tapefd, "C\n", 2);
+ if (response (mtape) < 0)
+ {
+ perror("?Error closing remote tape");
+ exit(1);
+ }
+ }
+ if (close (mtape->tapefd) < 0)
+ {
+ perror("?Error closing tape");
+ exit(1);
+ }
+ free (mtape);
+}
+
+
+/* rewind tape */
+void posnbot (tape_handle_t mtape)
+{
+ if (mtape->tape_type == TT_IMAGE)
+ { /* image file */
+ if (lseek (mtape->tapefd, 0L, SEEK_SET) < 0)
+ {
+ perror("?Seek failed");
+ exit(1);
+ }
+ }
+ else
+ { /* local/remote tape drive */
+ if (doioctl (mtape, & mt_rew) < 0)
+ {
+ perror("?Rewind failed");
+ exit(1);
+ }
+ }
+}
+
+
+/* position tape at EOT (between the two tape marks) */
+void posneot (tape_handle_t mtape)
+{
+ if (mtape->tape_type == TT_IMAGE)
+ { /* image file */
+ if (lseek (mtape->tapefd, -4L, SEEK_END) < 0)
+ {
+ perror("?Seek failed");
+ exit(1);
+ }
+ }
+ else
+ { /* local/remote tape drive */
+ doioctl (mtape, & mt_bsr); /* in case already at LEOT */
+ while (1)
+ {
+ /* space forward a file */
+ if (doioctl (mtape, & mt_fsf) < 0)
+ {
+ perror("?Error spacing to EOT");
+ exit(1);
+ }
+ /* space one record more to see if double EOF */
+ if (doioctl (mtape, & mt_fsr) < 0)
+ break;
+/* might want to check errno to make sure it's the right error */
+ }
+#if 1
+ /* "man mtio" doesn't say whether MTFSR actually moves past */
+ /* the tape mark, let's assume it does */
+ if (doioctl (mtape, & mt_bsr) < 0)
+ { /* get between them */
+ perror("?Error backspacing at EOT");
+ exit(1);
+ }
+#endif
+ }
+}
+
+
+/* read a tape record, return actual length (0=tape mark) */
+int getrec (tape_handle_t mtape, void *buf, int len)
+{
+ unsigned char byte [4]; /* 32 bits for length field(s) */
+ unsigned long l; /* at least 32 bits */
+ int i;
+
+ if (mtape->tape_type == TT_IMAGE)
+ { /* image file */
+ doread (mtape->tapefd, byte, 4); /* get record length */
+ l=((unsigned long)byte[3]<<24L)|((unsigned long)byte[2]<<16L)|
+ ((unsigned long)byte[1]<<8L)|(unsigned long)byte[0];
+ /* compose into longword */
+ if (l > len)
+ goto toolong; /* don't read if too long for buf */
+ if (l != 0)
+ { /* get data unless tape mark */
+ char x;
+ doread (mtape->tapefd, buf, l); /* read data */
+ if ((l & 1) != 0 && (mtape->flags & TF_SIMH) != 0)
+ doread (mtape->tapefd, &x, 1);
+ doread (mtape->tapefd, byte, 4); /* get trailing record length */
+ if((((unsigned long)byte[3]<<24L)|
+ ((unsigned long)byte[2]<<16L)|
+ ((unsigned long)byte[1]<<8)|
+ (unsigned long)byte[0])!=l)
+ { /* should match */
+ fprintf (stderr,"?Corrupt tape image\n");
+ exit(1);
+ }
+ }
+ }
+ else if (mtape->tape_type == TT_RMT)
+ { /* rmt tape server */
+ len = sprintf (mtape->netbuf, "R%d\n", len);
+ dowrite (mtape->tapefd, mtape->netbuf, len);
+ if ((i = response (mtape)) < 0)
+ {
+ perror("?Error reading tape");
+ exit(1);
+ }
+ l = i;
+ if (l)
+ doread (mtape->tapefd, buf, l);
+ }
+ else
+ { /* local tape drive */
+ if ((i = read (mtape->tapefd, buf, len)) < 0)
+ {
+ perror("?Error reading tape");
+ exit(1);
+ }
+ l = i;
+ }
+ return(l);
+
+ toolong:
+ fprintf(stderr,"?%ld byte tape record too long for %d byte buffer\n",
+ l,len);
+ exit(1);
+}
+
+
+/* write a tape record */
+void putrec (tape_handle_t mtape, void *buf, int len)
+{
+ unsigned char l [4];
+
+ if (mtape->tape_type == TT_IMAGE)
+ { /* image file */
+ l [0] = len & 0377; /* PDP-11 byte order */
+ l [1] = (len >> 8) &0377;
+ l [2] = 0; /* our recs are always < 64 KB */
+ l [3] = 0;
+ dowrite (mtape->tapefd, l, 4); /* write longword length */
+ dowrite (mtape->tapefd, buf, len); /* write data */
+ dowrite (mtape->tapefd, l, 4); /* write length again */
+ }
+ else if (mtape->tape_type == TT_RMT)
+ { /* rmt tape */
+ int n;
+ n = sprintf (mtape->netbuf, "W%d\n", len);
+ dowrite (mtape->tapefd, mtape->netbuf, n);
+ dowrite (mtape->tapefd, buf, len);
+ }
+ else
+ dowrite (mtape->tapefd, buf, len); /* just write the data if tape */
+
+ mtape->count += len + (mtape->bpi * 3 /5); /* add to byte count
+ (+0.6" tape gap) */
+}
+
+
+/* write a tape mark */
+void tapemark (tape_handle_t mtape)
+{
+ static char zero [4] = { 0, 0, 0, 0 };
+
+ if (mtape->tape_type == TT_IMAGE)
+ { /* image file */
+ dowrite (mtape->tapefd, zero, 4); /* write longword length */
+ }
+ else
+ { /* local/remote tape drive */
+ if (doioctl (mtape, & mt_weof) < 0)
+ {
+ perror ("?Failed writing tape mark");
+ exit (1);
+ }
+ }
+ mtape->count += 3 * mtape->bpi; /* 3" of tape */
+}
+
+
+/* skip records (negative for reverse) */
+void skiprec (tape_handle_t mtape, int count)
+{
+ unsigned char byte [4]; /* 32 bits for length field(s) */
+ unsigned long l; /* at least 32 bits */
+
+ if (mtape->tape_type != TT_IMAGE)
+ {
+ fprintf (stderr, "?Record skip only implemented for image files");
+ exit (1);
+ }
+
+ if (count < 0)
+ {
+ fprintf (stderr, "?Record skip reverse not yet implemented");
+ exit (1);
+ }
+
+ while (count--)
+ {
+ doread (mtape->tapefd, byte, 4); /* get record length */
+
+ /* compose into longword */
+ l=((unsigned long)byte[3]<<24L)|((unsigned long)byte[2]<<16L)|
+ ((unsigned long)byte[1]<<8L)|(unsigned long)byte[0];
+
+ if (l == 0) /* hit tape mark? */
+ return; /* note that we've effectively skipped over the tape mark */
+
+ /* skip record */
+ if (lseek (mtape->tapefd, l, SEEK_CUR) < 0)
+ {
+ perror ("?Seek failed");
+ exit (1);
+ }
+
+ doread (mtape->tapefd, byte, 4); /* get trailing record length */
+ if((((unsigned long)byte[3]<<24L)|
+ ((unsigned long)byte[2]<<16L)|
+ ((unsigned long)byte[1]<<8)|
+ (unsigned long)byte[0])!=l)
+ { /* should match */
+ fprintf (stderr,"?Corrupt tape image\n");
+ exit(1);
+ }
+ }
+}
+
+
+/* skip forward to the next file mark, and leave the tape positioned
+ after the mark */
+static void skip_to_mark (tape_handle_t mtape)
+{
+ unsigned char byte [4]; /* 32 bits for length field(s) */
+ unsigned long l; /* at least 32 bits */
+
+ static char scratch_buf [4096];
+
+ if (mtape->tape_type != TT_IMAGE)
+ {
+ fprintf (stderr, "?Record skip only implemented for image files");
+ exit (1);
+ }
+
+ for (;;)
+ {
+ doread (mtape->tapefd, byte, 4); /* get record length */
+
+ /* compose into longword */
+ l=((unsigned long)byte[3]<<24L)|((unsigned long)byte[2]<<16L)|
+ ((unsigned long)byte[1]<<8L)|(unsigned long)byte[0];
+
+ if (l == 0) /* hit tape mark? */
+ return; /* note that we've effectively skipped over the tape mark */
+
+ /* skip record */
+ if (mtape->seek_ok)
+ {
+ if (lseek (mtape->tapefd, l, SEEK_CUR) < 0)
+ {
+ perror ("?Seek failed");
+ exit (1);
+ }
+ }
+ else
+ {
+ int len, len2;
+ len = l;
+ while (len > 0)
+ {
+ len2 = len;
+ if (len2 > sizeof (scratch_buf))
+ len2 = sizeof (scratch_buf);
+ doread (mtape->tapefd, scratch_buf, len2); /* read data */
+ len -= len2;
+ }
+ }
+
+ doread (mtape->tapefd, byte, 4); /* get trailing record length */
+ if((((unsigned long)byte[3]<<24L)|
+ ((unsigned long)byte[2]<<16L)|
+ ((unsigned long)byte[1]<<8)|
+ (unsigned long)byte[0])!=l)
+ { /* should match */
+ fprintf (stderr,"?Corrupt tape image\n");
+ exit(1);
+ }
+ }
+}
+
+
+/* skip files (negative for reverse) */
+void skipfile (tape_handle_t mtape, int count)
+{
+ if (mtape->tape_type != TT_IMAGE)
+ {
+ fprintf (stderr, "?File skip only implemented for image files");
+ exit (1);
+ }
+
+ if (count < 0)
+ {
+ fprintf (stderr, "?File skip reverse not yet implemented");
+ exit (1);
+ }
+
+ while (count--)
+ {
+ skip_to_mark (mtape);
+ }
+}
+
+/* set tape flags */
+void tapeflags (tape_handle_t mtape, int flags)
+{
+ mtape->flags = flags;
+}
diff --git a/tapeio.h b/tapeio.h
new file mode 100644
index 0000000..762ce94
--- /dev/null
+++ b/tapeio.h
@@ -0,0 +1,59 @@
+/*
+ Routines to do magtape I/O to local tapes, remote tapes, and tape image
+ files.
+
+ Copyright 1998, 1999 John Wilson and Eric Smith
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as published
+ by the Free Software Foundation. Note that permission is not granted
+ to redistribute this program under the terms of any other version of the
+ General Public License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+
+typedef struct mtape_t *tape_handle_t; /* opaque type */
+
+
+/* tape flags */
+#define TF_DEFAULT 0x000
+#define TF_SIMH 0x001
+
+
+/* open a tape drive */
+tape_handle_t opentape (char *name, int create, int writable);
+
+/* close a tape drive */
+void closetape (tape_handle_t h);
+
+/* rewind tape */
+void posnbot (tape_handle_t h);
+
+/* position tape at EOT (between the two tape marks) */
+void posneot (tape_handle_t h);
+
+/* read a tape record, return actual length (0=tape mark) */
+int getrec (tape_handle_t h, void *buf, int len);
+
+/* write a tape record */
+void putrec (tape_handle_t h, void *buf, int len);
+
+/* write a tape mark */
+void tapemark (tape_handle_t h);
+
+/* skip records (negative for reverse) */
+void skiprec (tape_handle_t h, int count);
+
+/* skip files (negative for reverse) */
+void skipfile (tape_handle_t h, int count);
+
+/* set tape flags */
+void tapeflags (tape_handle_t h, int flags);
diff --git a/vmsbackup.c b/vmsbackup.c
index cdc7b63..277a177 100644
--- a/vmsbackup.c
+++ b/vmsbackup.c
@@ -72,6 +72,7 @@ int mkdir (char *path, int mode);
#include "vmsbackup.h"
#include "match.h"
#include "sysdep.h"
+#include "tapeio.h"
#ifdef DEBUG
#include "hexdump.h"
@@ -261,7 +262,7 @@ unsigned long nblocks;
FILE *lf;
#endif
-int fd; /* tape file descriptor */
+tape_handle_t fd; /* tape file descriptor */
/* Command line stuff. */
@@ -1226,7 +1227,7 @@ int rdhead(void)
printf("rdhead\n");
#endif
/* read the tape label - 4 records of 80 bytes */
- while ((i = read(fd, label, LABEL_SIZE)) != 0) {
+ while ((i = getrec(fd, label, LABEL_SIZE)) != 0) {
if (i != LABEL_SIZE) {
fprintf(stderr, "Snark: bad label record\n");
exit(EXIT_FAILURE);
@@ -1265,7 +1266,7 @@ void rdtail(void)
int i;
char name[80];
/* read the tape label - 4 records of 80 bytes */
- while ((i = read(fd, label, LABEL_SIZE)) != 0) {
+ while ((i = getrec(fd, label, LABEL_SIZE)) != 0) {
if (i != LABEL_SIZE) {
fprintf(stderr, "Snark: bad label record\n");
exit(EXIT_FAILURE);
@@ -1303,27 +1304,14 @@ void vmsbackup(void)
#endif
/* open the tape file */
- fd = open(tapefile, O_RDONLY);
- if (fd < 0) {
+ fd = opentape(tapefile, 0, 0);
+ if (fd == NULL) {
perror(tapefile);
exit(EXIT_FAILURE);
}
-#if HAVE_MT_IOCTLS
- /* rewind the tape */
- op.mt_op = MTREW;
- op.mt_count = 1;
- i = ioctl(fd, MTIOCTOP, &op);
- if (i < 0) {
- if (errno == EINVAL || errno == ENOTTY) {
- ondisk = 1;
- } else {
- perror(tapefile);
- exit(EXIT_FAILURE);
- }
- }
-#else
- ondisk = 1;
-#endif
+ ondisk = 0;
+
+ posnbot(fd);
#ifdef DEBUG
if (debugflag) {
@@ -1361,21 +1349,11 @@ void vmsbackup(void)
fprintf(stderr, "-s not supported for disk savesets\n");
exit(EXIT_FAILURE);
}
-#if HAVE_MT_IOCTLS
- op.mt_op = MTFSF;
- op.mt_count = 1;
- i = ioctl(fd, MTIOCTOP, &op);
- if (i < 0) {
- perror(tapefile);
- exit(EXIT_FAILURE);
- }
-#else
- abort ();
-#endif
+ skipfile(fd, 1);
i = 0;
}
else
- i = read(fd, block, blocksize);
+ i = getrec(fd, block, blocksize);
#ifdef DEBUG
if (debugflag) {
printf("Read %d of %d bytes, now at 0x%lx\n", i, blocksize, lseek(fd, 0, SEEK_CUR));
@@ -1417,7 +1395,7 @@ void vmsbackup(void)
}
/* close the tape */
- close(fd);
+ closetape(fd);
#ifdef NEWD
/* close debug file */