X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=restore%2Ftape.c;h=76dded78fbef7113e3dc2740378fcc4392e59585;hp=d04866de64d6b70437c95d4e3dc830d2dbfc3d0b;hb=11856e771fadee7ddb9b5a613c91f562bf363da7;hpb=dad15dbdd521ed77fefd0de843f69467d727aade diff --git a/restore/tape.c b/restore/tape.c index d04866d..76dded7 100644 --- a/restore/tape.c +++ b/restore/tape.c @@ -2,8 +2,8 @@ * Ported to Linux's Second Extended File System as part of the * dump and restore backup suit * Remy Card , 1994-1997 - * Stelian Pop , 1999-2000 - * Stelian Pop - Alcôve , 2000 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 */ /* @@ -46,12 +46,14 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.30 2001/03/20 20:39:36 stelian Exp $"; + "$Id: tape.c,v 1.52 2002/01/16 09:32:14 stelian Exp $"; #endif /* not lint */ #include +#include #include #include +#include #include #include #include @@ -66,7 +68,11 @@ static const char rcsid[] = #ifdef __linux__ #include #include +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else #include +#endif #include #include #else /* __linux__ */ @@ -78,13 +84,20 @@ static const char rcsid[] = #include #endif /* HAVE_ZLIB */ +#ifdef HAVE_BZLIB +#include +#endif /* HAVE_BZLIB */ + #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; +int pipein = 0; static int magtapein = 0; /* input is from magtape */ static char magtape[MAXPATHLEN]; static char magtapeprefix[MAXPATHLEN]; @@ -93,7 +106,7 @@ static int numtrec; static char *tapebuf; /* input buffer for read */ static int bufsize; /* buffer size without prefix */ static char *tbufptr = NULL; /* active tape buffer */ -#ifdef HAVE_ZLIB +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) static char *comprbuf; /* uncompress work buf */ static size_t comprlen; /* size including prefix */ #endif @@ -137,9 +150,10 @@ static void xtrlnkskip __P((char *, size_t)); static void xtrmap __P((char *, size_t)); static void xtrmapskip __P((char *, size_t)); static void xtrskip __P((char *, size_t)); +static void setmagtapein __P((void)); -#ifdef HAVE_ZLIB -static void newcomprbuf __P((long)); +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) +static void newcomprbuf __P((int)); static void readtape_set __P((char *)); static void readtape_uncompr __P((char *)); static void readtape_comprfile __P((char *)); @@ -147,7 +161,7 @@ static void readtape_comprtape __P((char *)); 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 @@ -225,20 +239,21 @@ newtapebuf(long size) tapebufsize = size; } -#ifdef HAVE_ZLIB +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) static void -newcomprbuf(long size) +newcomprbuf(int size) { - if (size <= comprlen) + size_t buf_size = (size+1) * TP_BSIZE + sizeof(struct tapebuf); + if (buf_size <= comprlen) return; - comprlen = size + sizeof(struct tapebuf); + comprlen = buf_size; if (comprbuf != NULL) free(comprbuf); comprbuf = malloc(comprlen); if (comprbuf == NULL) errx(1, "Cannot allocate space for decompress buffer"); } -#endif /* HAVE_ZLIB */ +#endif /* HAVE_ZLIB || HAVE_BZLIB */ /* * Verify that the tape drive can be accessed and @@ -247,11 +262,18 @@ newcomprbuf(long size) void setup(void) { - int i, j, *ip; - struct stat stbuf; - struct mtget mt_stat; + int i, j, *ip, bot_code; + struct STAT stbuf; Vprintf(stdout, "Verify tape and initialize maps\n"); + if (bot_script) { + msg("Launching %s\n", bot_script); + bot_code = system_command(bot_script, magtape, 1); + if (bot_code != 0 && bot_code != 1) { + msg("Restore aborted by the beginning of tape script\n"); + exit(1); + } + } #ifdef RRESTORE if (host) mt = rmtopen(magtape, 0); @@ -260,21 +282,11 @@ setup(void) 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; - if (!pipein) { - /* need to know if input is really from a tape */ -#ifdef RRESTORE - if (host) - magtapein = rmtioctl(MTNOP, 1) != -1; - else -#endif - magtapein = ioctl(mt, MTIOCGET, (char *) &mt_stat) == 0; - } - - Vprintf(stdout,"Input is from %s\n", magtapein? "tape": "file/pipe"); + setmagtapein(); setdumpnum(); FLUSHTAPEBUF(); findtapeblksize(); @@ -290,8 +302,8 @@ setup(void) if (zflag) { fprintf(stderr, "Dump tape is compressed.\n"); -#ifdef HAVE_ZLIB - newcomprbuf(bufsize); +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) + newcomprbuf(ntrec); #else errx(1,"This restore version doesn't support decompression"); #endif /* HAVE_ZLIB */ @@ -319,7 +331,7 @@ setup(void) } 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; @@ -371,11 +383,12 @@ setup(void) void getvol(long nextvol) { - long newvol = 0, savecnt = 0, wantnext = 0, i; + long newvol = 0, wantnext = 0, i; + long saved_blksread = 0, saved_tpblksread = 0; union u_spcl tmpspcl; # define tmpbuf tmpspcl.s_spcl char buf[TP_BSIZE]; - int haderror = 0; + int haderror = 0, bot_code = 1; if (nextvol == 1) { tapesread = 0; @@ -388,7 +401,8 @@ getvol(long nextvol) return; goto gethdr; } - savecnt = blksread; + saved_blksread = blksread; + saved_tpblksread = tpblksread; again: if (pipein) exit(1); /* pipes do not get a second chance */ @@ -418,12 +432,16 @@ again: fprintf(stderr, "\n"); } do { - fprintf(stderr, "Specify next volume #: "); + fprintf(stderr, "Specify next volume # (none if no more volumes): "); (void) fflush(stderr); (void) fgets(buf, TP_BSIZE, terminal); } while (!feof(terminal) && buf[0] == '\n'); if (feof(terminal)) exit(1); + if (!strcmp(buf, "none\n")) { + terminateinput(); + return; + } newvol = atoi(buf); if (newvol <= 0) { fprintf(stderr, @@ -439,7 +457,15 @@ again: snprintf(magtape, MAXPATHLEN, "%s%03ld", magtapeprefix, newvol); magtape[MAXPATHLEN - 1] = '\0'; } - if (!Mflag || haderror) { + if (bot_script && !haderror) { + msg("Launching %s\n", bot_script); + bot_code = system_command(bot_script, magtape, newvol); + if (bot_code != 0 && bot_code != 1) { + msg("Restore aborted by the beginning of tape script\n"); + exit(1); + } + } + if (haderror || (bot_code && !Mflag)) { haderror = 0; fprintf(stderr, "Mount tape volume %ld\n", (long)newvol); fprintf(stderr, "Enter ``none'' if there are no more tapes\n"); @@ -453,8 +479,11 @@ again: return; } if (buf[0] != '\n') { - (void) strcpy(magtape, buf); - magtape[strlen(magtape) - 1] = '\0'; + char *pos; + (void) strncpy(magtape, buf, sizeof(magtape)); + magtape[sizeof(magtape) - 1] = '\0'; + if ((pos = strchr(magtape, '\n'))) + magtape[pos - magtape] = '\0'; } } #ifdef RRESTORE @@ -462,7 +491,7 @@ again: 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); @@ -471,20 +500,26 @@ again: goto again; } gethdr: + setmagtapein(); volno = newvol; setdumpnum(); FLUSHTAPEBUF(); + findtapeblksize(); if (gethead(&tmpbuf) == FAIL) { Dprintf(stdout, "header read failed at %ld blocks\n", (long)blksread); fprintf(stderr, "tape is not dump tape\n"); volno = 0; haderror = 1; + blksread = saved_blksread; + tpblksread = saved_tpblksread; goto again; } if (tmpbuf.c_volume != volno) { fprintf(stderr, "Wrong volume (%d)\n", tmpbuf.c_volume); volno = 0; haderror = 1; + blksread = saved_blksread; + tpblksread = saved_tpblksread; goto again; } if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) { @@ -493,10 +528,13 @@ gethdr: fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); volno = 0; haderror = 1; + blksread = saved_blksread; + tpblksread = saved_tpblksread; goto again; } tapesread |= 1 << volno; - blksread = savecnt; + blksread = saved_blksread; + tpblksread = saved_tpblksread; /* * If continuing from the previous volume, skip over any * blocks read already at the end of the previous volume. @@ -730,7 +768,7 @@ extractfile(char *name) } 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(); @@ -838,8 +876,17 @@ loop: (*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; @@ -867,7 +914,7 @@ static void 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); } @@ -1025,22 +1072,22 @@ int #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; + do_compare_error; } if (sbuf_disk->st_size != sbuf_tape.st_size) { fprintf(stderr, "%s: size changed from %ld to %ld.\n", diskfile, (long)sbuf_tape.st_size, (long)sbuf_disk->st_size); - compare_errors = 1; + do_compare_error; #ifdef COMPARE_FAIL_KEEP_FILE return (0); #else @@ -1048,14 +1095,14 @@ cmpfiles(char *tapefile, char *diskfile, struct stat *sbuf_disk) #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; + do_compare_error; } - 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; + do_compare_error; } if (do_cmpfiles(fd_tape, fd_disk, sbuf_tape.st_size)) { @@ -1063,7 +1110,7 @@ cmpfiles(char *tapefile, char *diskfile, struct stat *sbuf_disk) diskfile); close(fd_tape); close(fd_disk); - compare_errors = 1; + do_compare_error; #ifdef COMPARE_FAIL_KEEP_FILE /* rename the file to live in /tmp */ /* rename `tapefile' to /tmp/ */ @@ -1107,16 +1154,16 @@ void 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; + do_compare_error; skipfile(); return; } @@ -1131,7 +1178,7 @@ comparefile(char *name) if (sb.st_mode != mode) { fprintf(stderr, "%s: mode changed from 0%o to 0%o.\n", name, mode & 07777, sb.st_mode & 07777); - compare_errors = 1; + do_compare_error; } switch (mode & IFMT) { default: @@ -1153,7 +1200,7 @@ comparefile(char *name) if (!(sb.st_mode & S_IFLNK)) { fprintf(stderr, "%s: is no longer a symbolic link\n", name); - compare_errors = 1; + do_compare_error; return; } lnkbuf[0] = '\0'; @@ -1163,20 +1210,20 @@ comparefile(char *name) fprintf(stderr, "%s: zero length symbolic link (ignored)\n", name); - compare_errors = 1; + do_compare_error; return; } if ((lsize = readlink(name, lbuf, MAXPATHLEN)) < 0) { panic("readlink of %s failed: %s", name, strerror(errno)); - compare_errors = 1; + do_compare_error; } lbuf[lsize] = 0; if (strcmp(lbuf, lnkbuf) != 0) { fprintf(stderr, "%s: symbolic link changed from %s to %s.\n", name, lnkbuf, lbuf); - compare_errors = 1; + do_compare_error; return; } return; @@ -1187,7 +1234,7 @@ comparefile(char *name) if (!(sb.st_mode & (S_IFCHR|S_IFBLK))) { fprintf(stderr, "%s: no longer a special file\n", name); - compare_errors = 1; + do_compare_error; skipfile(); return; } @@ -1200,17 +1247,17 @@ comparefile(char *name) (int)curfile.dip->di_rdev & 0xff, ((int)sb.st_rdev >> 8) & 0xff, (int)sb.st_rdev & 0xff); - compare_errors = 1; + do_compare_error; } skipfile(); return; 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; + do_compare_error; } else { cmperror = 0; @@ -1224,7 +1271,7 @@ comparefile(char *name) } } if (cmperror) - compare_errors = 1; + do_compare_error; close(ifile); } #else @@ -1233,11 +1280,11 @@ comparefile(char *name) 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 = open(tmpfile, O_WRONLY | O_CREAT | O_TRUNC, 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)); } @@ -1256,7 +1303,7 @@ comparefile(char *name) /* NOTREACHED */ } -#ifdef HAVE_ZLIB +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) static void (*readtape_func)(char *) = readtape_set; /* @@ -1280,6 +1327,7 @@ readtape_set(char *buf) if (!zflag) readtape_func = readtape_uncompr; else { + newcomprbuf(ntrec); if (magtapein) readtape_func = readtape_comprtape; else @@ -1288,7 +1336,7 @@ readtape_set(char *buf) readtape(buf); } -#endif /* HAVE_ZLIB */ +#endif /* HAVE_ZLIB || HAVE_BZLIB */ /* * This is the original readtape(), it's used for reading uncompressed input. @@ -1296,7 +1344,7 @@ readtape_set(char *buf) * Handle read errors, and end of media. */ static void -#ifdef HAVE_ZLIB +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) readtape_uncompr(char *buf) #else readtape(char *buf) @@ -1317,8 +1365,6 @@ readtape(char *buf) if (numtrec == 0) numtrec = ntrec; cnt = ntrec * TP_BSIZE; - if (zflag) - cnt += PREFIXSIZE; rd = 0; getmore: #ifdef RRESTORE @@ -1388,7 +1434,7 @@ getmore: 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"); @@ -1422,7 +1468,7 @@ getmore: tpblksread++; } -#ifdef HAVE_ZLIB +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) /* * Read a compressed format block from a file or pipe and uncompress it. @@ -1450,6 +1496,9 @@ readtape_comprfile(char *buf) /* read the block prefix */ ret = read_a_block(mt, tapebuf, PREFIXSIZE, &rl); + + if (Vflag && (ret == 0 || rl < PREFIXSIZE || tpb->length == 0)) + ret = 0; if (ret <= 0) goto readerr; @@ -1608,6 +1657,9 @@ decompress_tapebuf(struct tapebuf *tpbin, int readsize) /* zflag gets set in setup() from the dump header */ int cresult, blocklen; unsigned long worklen; +#ifdef HAVE_BZLIB + unsigned int worklen2; +#endif char *output = NULL,*reason = NULL, *lengtherr = NULL; /* build a length error message */ @@ -1619,44 +1671,88 @@ decompress_tapebuf(struct tapebuf *tpbin, int readsize) lengtherr = "long"; worklen = comprlen; - cresult = Z_OK; + cresult = 1; if (tpbin->compressed) { /* uncompress whatever we read, if it fails, complain later */ - cresult = uncompress(comprbuf, &worklen, tpbin->buf, blocklen); - output = comprbuf; + if (tpbin->flags == COMPRESS_ZLIB) { +#ifndef HAVE_ZLIB + errx(1,"This restore version doesn't support zlib decompression"); +#else + cresult = uncompress(comprbuf, &worklen, + tpbin->buf, blocklen); + output = comprbuf; + switch (cresult) { + case Z_OK: + break; + case Z_MEM_ERROR: + reason = "not enough memory"; + break; + case Z_BUF_ERROR: + reason = "buffer too small"; + break; + case Z_DATA_ERROR: + reason = "data error"; + break; + default: + reason = "unknown"; + } + if (cresult == Z_OK) + cresult = 1; + else + cresult = 0; +#endif /* HAVE_ZLIB */ + } + if (tpbin->flags == COMPRESS_BZLIB) { +#ifndef HAVE_BZLIB + errx(1,"This restore version doesn't support bzlib decompression"); +#else + worklen2 = worklen; + cresult = BZ2_bzBuffToBuffDecompress( + comprbuf, &worklen2, + tpbin->buf, blocklen, 0, 0); + worklen = worklen2; + output = comprbuf; + switch (cresult) { + case BZ_OK: + break; + case BZ_MEM_ERROR: + reason = "not enough memory"; + break; + case BZ_OUTBUFF_FULL: + reason = "buffer too small"; + break; + case BZ_DATA_ERROR: + case BZ_DATA_ERROR_MAGIC: + case BZ_UNEXPECTED_EOF: + reason = "data error"; + break; + default: + reason = "unknown"; + } + if (cresult == BZ_OK) + cresult = 1; + else + cresult = 0; +#endif /* HAVE_BZLIB */ + } } else { output = tpbin->buf; worklen = blocklen; } - switch (cresult) { - case Z_OK: - if (worklen != ntrec * TP_BSIZE) { - /* short block, shouldn't happen, but... */ - reason = "length mismatch"; - if (worklen % TP_BSIZE == 0) - numtrec = worklen / TP_BSIZE; - } - break; - case Z_MEM_ERROR: - reason = "not enough memory"; - break; - case Z_BUF_ERROR: - reason = "buffer too small"; - break; - case Z_DATA_ERROR: - reason = "data error"; - break; - default: - reason = "unknown"; - } /*switch */ + if (cresult) { + numtrec = worklen / TP_BSIZE; + if (worklen % TP_BSIZE != 0) + reason = "length mismatch"; + } if (reason) { if (lengtherr) fprintf(stderr, "%s compressed block: %d expected: %d\n", lengtherr, readsize, tpbin->length + PREFIXSIZE); fprintf(stderr, "decompression error, block %ld: %s\n", tpblksread+1, reason); - if (cresult != Z_OK) output = NULL; + if (!cresult) + output = NULL; } return output; } @@ -1684,16 +1780,17 @@ msg_read_error(char *m) break; } } -#endif /* HAVE_ZLIB */ +#endif /* HAVE_ZLIB || HAVE_BZLIB */ /* - * Read the first block and set the blocksize from its length. Test - * if the block looks like a compressed dump tape. setup() will make - * the final determination by checking the compressed flag if gethead() + * Read the first block and get the blocksize from it. Test + * for a compressed dump tape/file. setup() will make the final + * determination by checking the compressed flag if gethead() * finds a valid header. The test here is necessary to offset the buffer * by the size of the compressed prefix. zflag is set here so that * readtape_set can set the correct function pointer for readtape(). - * Note that the first block of each tape/file will not be compressed. + * Note that the first block of each tape/file is not compressed + * and does not have a prefix. */ static void findtapeblksize(void) @@ -1701,7 +1798,7 @@ findtapeblksize(void) long i; size_t len; struct tapebuf *tpb = (struct tapebuf *) tapebuf; - struct s_spcl *spclpt = (struct s_spcl *) tpb->buf; + struct s_spcl *spclpt = (struct s_spcl *) tapebuf; for (i = 0; i < ntrec; i++) ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; @@ -1711,61 +1808,57 @@ findtapeblksize(void) * For a pipe or file, read in the first record. For a tape, read * the first block. */ - len = magtapein ? bufsize + PREFIXSIZE: TP_BSIZE; + len = magtapein ? ntrec * TP_BSIZE : TP_BSIZE; if (read_a_block(mt, tapebuf, len, &i) <= 0) errx(1, "Tape read error on first record"); /* * If the input is from a file or a pipe, we read TP_BSIZE - * bytes looking for a compressed dump header, we then - * need to read in the rest of the record, as determined by - * tpb->length or bufsize. The first block of the dump is - * guaranteed to not be compressed so we look at the header. + * bytes looking for a dump header. If the dump is compressed + * we need to read in the rest of the block, as determined + * by c_ntrec in the dump header. The first block of the + * dump is not compressed and does not have a prefix. */ if (!magtapein) { - if (tpb->length % TP_BSIZE == 0 - && tpb->length <= bufsize - && tpb->compressed == 0 - && spclpt->c_type == TS_TAPE + if (spclpt->c_type == TS_TAPE && spclpt->c_flags & DR_COMPRESSED) { - /* Looks like it's a compressed dump block prefix, */ - /* read in the rest of the block based on tpb->length. */ - len = tpb->length - TP_BSIZE + PREFIXSIZE; - if (read_a_block(mt, tapebuf+TP_BSIZE, len, &i) <= 0 - || i != len) - errx(1,"Error reading dump file header"); - tbufptr = tpb->buf; - numtrec = ntrec = tpb->length / TP_BSIZE; + /* It's a compressed dump file, read in the */ + /* rest of the block based on spclpt->c_ntrec. */ + if (spclpt->c_ntrec > ntrec) + errx(1, "Tape blocksize is too large, use " + "\'-b %d\' ", spclpt->c_ntrec); + ntrec = spclpt->c_ntrec; + len = (ntrec - 1) * TP_BSIZE; zflag = 1; } 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) - errx(1,"Error reading dump file header"); - tbufptr = tapebuf; - numtrec = ntrec; } + 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; Vprintf(stdout, "Input block size is %ld\n", ntrec); return; - } + } /* if (!magtapein) */ /* - * 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 tape, we tried to read ntrec * TP_BSIZE bytes. + * If the value of ntrec is too large, we read less than + * what we asked for; adjust the value of ntrec and test for + * a compressed dump tape. */ if (i % TP_BSIZE != 0) { + /* may be old format compressed dump tape with a prefix */ + spclpt = (struct s_spcl *) tpb->buf; if (i % TP_BSIZE == PREFIXSIZE && tpb->compressed == 0 && spclpt->c_type == TS_TAPE && spclpt->c_flags & DR_COMPRESSED) { - zflag = 1; tbufptr = tpb->buf; if (tpb->length > bufsize) @@ -1777,6 +1870,13 @@ findtapeblksize(void) i, TP_BSIZE); } ntrec = i / TP_BSIZE; + if (spclpt->c_type == TS_TAPE) { + if (spclpt->c_flags & DR_COMPRESSED) + zflag = 1; + if (spclpt->c_ntrec > ntrec) + errx(1, "Tape blocksize is too large, use " + "\'-b %d\' ", spclpt->c_ntrec); + } numtrec = ntrec; Vprintf(stdout, "Tape block size is %ld\n", ntrec); } @@ -1784,7 +1884,7 @@ findtapeblksize(void) /* * 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; @@ -1822,6 +1922,28 @@ closemt(void) (void) close(mt); } +static void +setmagtapein(void) { + struct mtget mt_stat; + static int done = 0; + if (done) + return; + done = 1; + if (!pipein) { + /* need to know if input is really from a tape */ +#ifdef RRESTORE + if (host) + magtapein = !lflag; + else +#endif + magtapein = ioctl(mt, MTIOCGET, (char *)&mt_stat) == 0; + } + + Vprintf(stdout,"Input is from %s\n", + magtapein ? "tape" : + Vflag ? "multi-volume (no tape)" : "file/pipe"); +} + /* * Read the next block from the tape. * Check to see if it is one of several vintage headers. @@ -2095,8 +2217,11 @@ findinode(struct s_spcl *header) } } 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; } @@ -2250,3 +2375,72 @@ swabl(u_long x) 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 */