#ifndef lint
static const char rcsid[] =
- "$Id: tape.c,v 1.28 2001/03/20 09:14:58 stelian Exp $";
+ "$Id: tape.c,v 1.37 2001/04/27 15:22:47 stelian Exp $";
#endif /* not lint */
#include <config.h>
+#include <compatlfs.h>
#include <errno.h>
#include <compaterr.h>
#include <setjmp.h>
#include "extern.h"
#include "pathnames.h"
+#ifdef USE_QFA
+int noresyncmesg = 0;
+#endif /* USE_QFA */
static long fssize = MAXBSIZE;
static int mt = -1;
static int pipein = 0;
static char *decompress_tapebuf __P((struct tapebuf *, int));
static void msg_read_error __P((char *));
#endif
-static int read_a_block __P((int, void *, size_t, long *));
+static int read_a_block __P((int, char *, size_t, long *));
#define PREFIXSIZE sizeof(struct tapebuf)
#define COMPARE_ONTHEFLY 1
setup(void)
{
int i, j, *ip;
- struct stat stbuf;
+ struct STAT stbuf;
struct mtget mt_stat;
Vprintf(stdout, "Verify tape and initialize maps\n");
if (pipein)
mt = 0;
else
- mt = open(magtape, O_RDONLY, 0);
+ mt = OPEN(magtape, O_RDONLY, 0);
if (mt < 0)
err(1, "%s", magtape);
volno = 1;
magtapein = rmtioctl(MTNOP, 1) != -1;
else
#endif
- magtapein = ioctl(mt, MTIOCGET, (char *) &mt_stat) == 0;
+ if (ioctl(mt, MTIOCGET, (char *) &mt_stat) == 0) {
+ if (mt_stat.mt_dsreg & 0xffff)
+ magtapein = 1; /* fixed blocksize */
+ else
+ magtapein = 2; /* variable blocksize */
+ }
}
Vprintf(stdout,"Input is from %s\n", magtapein? "tape": "file/pipe");
}
dumptime = spcl.c_ddate;
dumpdate = spcl.c_date;
- if (stat(".", &stbuf) < 0)
+ if (STAT(".", &stbuf) < 0)
err(1, "cannot stat .");
if (stbuf.st_blksize > 0 && stbuf.st_blksize < TP_BSIZE )
fssize = TP_BSIZE;
mt = rmtopen(magtape, 0);
else
#endif
- mt = open(magtape, O_RDONLY, 0);
+ mt = OPEN(magtape, O_RDONLY, 0);
if (mt == -1) {
fprintf(stderr, "Cannot open %s\n", magtape);
}
if (uflag)
(void)unlink(name);
- if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC,
+ if ((ofile = OPEN(name, O_WRONLY | O_CREAT | O_TRUNC,
0666)) < 0) {
warn("%s: cannot create file", name);
skipfile();
(*fill)((char *)buf, (size_t)(curblk * TP_BSIZE) + size);
last_write_was_hole = 0;
}
+ if (size > 0) {
+ fprintf(stderr, "Missing blocks at the end of %s, assuming hole\n", curfile.name);
+ while (size > 0) {
+ size_t skp = size > TP_BSIZE ? TP_BSIZE : size;
+ (*skip)(clearedbuf, skp);
+ size -= skp;
+ }
+ last_write_was_hole = 1;
+ }
if (last_write_was_hole) {
- ftruncate(ofile, origsize);
+ FTRUNCATE(ofile, origsize);
}
findinode(&spcl);
gettingfile = 0;
xtrskip(char *buf, size_t size)
{
- if (lseek(ofile, (off_t)size, SEEK_CUR) == -1)
+ if (LSEEK(ofile, (off_t)size, SEEK_CUR) == -1)
err(1, "seek error extracting inode %lu, name %s\nlseek",
(unsigned long)curfile.ino, curfile.name);
}
#else
void
#endif
-cmpfiles(char *tapefile, char *diskfile, struct stat *sbuf_disk)
+cmpfiles(char *tapefile, char *diskfile, struct STAT *sbuf_disk)
{
- struct stat sbuf_tape;
+ struct STAT sbuf_tape;
int fd_tape, fd_disk;
- if (stat(tapefile, &sbuf_tape) != 0) {
+ if (STAT(tapefile, &sbuf_tape) != 0) {
panic("Can't lstat tmp file %s: %s\n", tapefile,
strerror(errno));
compare_errors = 1;
#endif
}
- if ((fd_tape = open(tapefile, O_RDONLY)) < 0) {
+ if ((fd_tape = OPEN(tapefile, O_RDONLY)) < 0) {
panic("Can't open %s: %s\n", tapefile, strerror(errno));
compare_errors = 1;
}
- if ((fd_disk = open(diskfile, O_RDONLY)) < 0) {
+ if ((fd_disk = OPEN(diskfile, O_RDONLY)) < 0) {
close(fd_tape);
panic("Can't open %s: %s\n", diskfile, strerror(errno));
compare_errors = 1;
comparefile(char *name)
{
int mode;
- struct stat sb;
+ struct STAT sb;
int r;
#if !COMPARE_ONTHEFLY
static char *tmpfile = NULL;
- struct stat stemp;
+ struct STAT stemp;
#endif
- if ((r = lstat(name, &sb)) != 0) {
+ if ((r = LSTAT(name, &sb)) != 0) {
warn("%s: does not exist (%d)", name, r);
compare_errors = 1;
skipfile();
case IFREG:
#if COMPARE_ONTHEFLY
- if ((ifile = open(name, O_RDONLY)) < 0) {
+ if ((ifile = OPEN(name, O_RDONLY)) < 0) {
panic("Can't open %s: %s\n", name, strerror(errno));
skipfile();
compare_errors = 1;
snprintf(tmpfilename, sizeof(tmpfilename), "%s/restoreCXXXXXX", tmpdir);
tmpfile = mktemp(&tmpfilename[0]);
}
- if ((stat(tmpfile, &stemp) == 0) && (unlink(tmpfile) != 0)) {
+ if ((STAT(tmpfile, &stemp) == 0) && (unlink(tmpfile) != 0)) {
panic("cannot delete tmp file %s: %s\n",
tmpfile, strerror(errno));
}
- if ((ofile = creat(tmpfile, 0600)) < 0) {
+ if ((ofile = OPEN(tmpfile, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
panic("cannot create file temp file %s: %s\n",
name, strerror(errno));
}
if (numtrec == 0)
numtrec = ntrec;
cnt = ntrec * TP_BSIZE;
- if (zflag)
- cnt += PREFIXSIZE;
rd = 0;
getmore:
#ifdef RRESTORE
seek_failed = (rmtseek(i, 1) < 0);
else
#endif
- seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1);
+ seek_failed = (LSEEK(mt, i, SEEK_CUR) == (off_t)-1);
if (seek_failed) {
warn("continuation failed");
}
switch (cresult) {
case Z_OK:
- if (worklen != ntrec * TP_BSIZE) {
- /* short block, shouldn't happen, but... */
+ numtrec = worklen / TP_BSIZE;
+ if (worklen % TP_BSIZE != 0)
reason = "length mismatch";
- if (worklen % TP_BSIZE == 0)
- numtrec = worklen / TP_BSIZE;
- }
break;
case Z_MEM_ERROR:
reason = "not enough memory";
* For a pipe or file, read in the first record. For a tape, read
* the first block.
*/
- len = magtapein ? bufsize + PREFIXSIZE: TP_BSIZE;
+ if (magtapein == 1) /* fixed blocksize tape, not compressed */
+ len = ntrec * TP_BSIZE;
+ else if (magtapein == 2)/* variable blocksize tape */
+ len = bufsize + PREFIXSIZE;
+ else /* not mag tape */
+ len = TP_BSIZE;
if (read_a_block(mt, tapebuf, len, &i) <= 0)
errx(1, "Tape read error on first record");
else {
/* read in the rest of the block based on bufsize */
len = bufsize - TP_BSIZE;
- if (read_a_block(mt, tapebuf+TP_BSIZE, len, &i) <= 0
- || i != len)
+ if (read_a_block(mt, tapebuf+TP_BSIZE, len, &i) < 0
+ || (i != len && i % TP_BSIZE != 0))
errx(1,"Error reading dump file header");
tbufptr = tapebuf;
numtrec = ntrec;
}
/*
- * If the input is a tape, we tried to read PREFIXSIZE +
- * ntrec * TP_BSIZE bytes. If it's not a compressed dump tape
- * or the value of ntrec is too large, we have read less than
- * what we asked for; adjust the value of ntrec and test for
- * a compressed dump tape prefix.
+ * If the input is a variable block size tape, we tried to
+ * read PREFIXSIZE + ntrec * TP_BSIZE bytes.
+ * If it's not a compressed dump tape or the value of ntrec is
+ * too large, we have read less than * what we asked for;
+ * adjust the value of ntrec and test for * a compressed dump
+ * tape prefix.
*/
if (i % TP_BSIZE != 0) {
/*
* Read a block of data handling all of the messy details.
*/
-static int read_a_block(int fd, void *buf, size_t len, long *lengthread)
+static int read_a_block(int fd, char *buf, size_t len, long *lengthread)
{
long i = 1, size;
static void
accthdr(struct s_spcl *header)
{
- static ino_t previno = 0x7fffffff;
+ static dump_ino_t previno = 0x7fffffff;
static int prevtype;
static long predict;
long blks, i;
}
} while (header->c_type == TS_ADDR);
if (skipcnt > 0)
- fprintf(stderr, "resync restore, skipped %ld blocks\n",
- skipcnt);
+#ifdef USE_QFA
+ if (!noresyncmesg)
+#endif
+ fprintf(stderr, "resync restore, skipped %ld blocks\n",
+ skipcnt);
skipcnt = 0;
}
return (x);
}
#endif
+
+#ifdef USE_QFA
+/*
+ * get the current position of the tape
+ */
+int
+GetTapePos(long *pos)
+{
+ int err = 0;
+
+ *pos = 0;
+ if (ioctl(mt, MTIOCPOS, pos) == -1) {
+ err = errno;
+ fprintf(stdout, "[%ld] error: %d (getting tapepos: %ld)\n",
+ (unsigned long)getpid(), err, *pos);
+ return err;
+ }
+ return err;
+}
+
+typedef struct mt_pos {
+ short mt_op;
+ int mt_count;
+} MTPosRec, *MTPosPtr;
+
+/*
+ * go to specified position on tape
+ */
+int
+GotoTapePos(long pos)
+{
+ int err = 0;
+ struct mt_pos buf;
+
+ buf.mt_op = MTSEEK;
+ buf.mt_count = pos;
+ if (ioctl(mt, MTIOCTOP, &buf) == -1) {
+ err = errno;
+ fprintf(stdout, "[%ld] error: %d (setting tapepos: %ld)\n",
+ (unsigned long)getpid(), err, pos);
+ return err;
+ }
+ return err;
+}
+
+/*
+ * read next data from tape to re-sync
+ */
+void
+ReReadFromTape(void)
+{
+ FLUSHTAPEBUF();
+ noresyncmesg = 1;
+ if (gethead(&spcl) == FAIL) {
+#ifdef DEBUG_QFA
+ fprintf(stdout, "DEBUG 1 gethead failed\n");
+#endif
+ }
+ findinode(&spcl);
+ noresyncmesg = 0;
+}
+
+void
+RequestVol(long tnum)
+{
+ FLUSHTAPEBUF();
+ getvol(tnum);
+}
+#endif /* USE_QFA */