#ifndef lint
static const char rcsid[] =
- "$Id: tape.c,v 1.26 2001/03/18 15:35:44 stelian Exp $";
+ "$Id: tape.c,v 1.36 2001/04/27 12:23:23 stelian Exp $";
#endif /* not lint */
#include <config.h>
+#include <errno.h>
+#include <compaterr.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
#include <sys/param.h>
#include <sys/file.h>
#include <sys/mtio.h>
#include <sys/time.h>
#include <time.h>
#include <linux/ext2_fs.h>
+#include <ext2fs/ext2fs.h>
#include <bsdcompat.h>
#else /* __linux__ */
#include <ufs/ufs/dinode.h>
#endif /* __linux__ */
#include <protocols/dumprestore.h>
-#include <errno.h>
-#include <compaterr.h>
-#include <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
#ifdef HAVE_ZLIB
#include <zlib.h>
#endif /* HAVE_ZLIB */
-#ifdef __linux__
-#include <ext2fs/ext2fs.h>
-#endif
-
#include "restore.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
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");
goto again;
}
if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) {
-#ifdef __linux__
fprintf(stderr, "Wrong dump date\n\tgot: %s",
ctime4(&tmpbuf.c_date));
- fprintf(stderr, "\twanted: %s", ctime4(&dumpdate));
-#else
- fprintf(stderr, "Wrong dump date\n\tgot: %s",
- ctime(&tmpbuf.c_date));
fprintf(stderr, "\twanted: %s", ctime(&dumpdate));
-#endif
volno = 0;
haderror = 1;
goto again;
void
printdumpinfo(void)
{
-#ifdef __linux__
fprintf(stdout, "Dump date: %s", ctime4(&spcl.c_date));
fprintf(stdout, "Dumped from: %s",
(spcl.c_ddate == 0) ? "the epoch\n" : ctime4(&spcl.c_ddate));
-#else
- fprintf(stdout, "Dump date: %s", ctime(&spcl.c_date));
- fprintf(stdout, "Dumped from: %s",
- (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&spcl.c_ddate));
-#endif
if (spcl.c_host[0] == '\0')
return;
fprintf(stdout, "Level %d dump of %s on %s:%s\n",
(*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);
+ (*skip)(clearedbuf, size);
+ last_write_was_hole = 1;
+ }
if (last_write_was_hole) {
ftruncate(ofile, origsize);
}
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
}
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 */