X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=restore%2Ftape.c;h=3c9085bfece3e55b61c8493e4c63ef815343190a;hp=360cb1786aac25cb02a8862577826262fe28408a;hb=5d2a3d246d400d45dfd4c49ddb588c69fb60873d;hpb=fec671d14f580b0264f24b71735a728b467baf21 diff --git a/restore/tape.c b/restore/tape.c index 360cb17..3c9085b 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,7 +46,7 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.43 2001/07/18 13:46:17 stelian Exp $"; + "$Id: tape.c,v 1.56 2002/01/25 15:09:00 stelian Exp $"; #endif /* not lint */ #include @@ -84,6 +84,10 @@ static const char rcsid[] = #include #endif /* HAVE_ZLIB */ +#ifdef HAVE_BZLIB +#include +#endif /* HAVE_BZLIB */ + #include "restore.h" #include "extern.h" #include "pathnames.h" @@ -93,7 +97,7 @@ 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]; @@ -102,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 @@ -112,7 +116,7 @@ static long tpblksread = 0; /* TP_BSIZE blocks read */ static long tapesread; static sigjmp_buf restart; static int gettingfile = 0; /* restart has a valid frame */ -static char *host = NULL; +char *host = NULL; static int ofile; static char *map; @@ -148,8 +152,9 @@ static void xtrmapskip __P((char *, size_t)); static void xtrskip __P((char *, size_t)); static void setmagtapein __P((void)); -#ifdef HAVE_ZLIB +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) static void newcomprbuf __P((int)); +static void (*readtape_func) __P((char *)); static void readtape_set __P((char *)); static void readtape_uncompr __P((char *)); static void readtape_comprfile __P((char *)); @@ -235,7 +240,7 @@ newtapebuf(long size) tapebufsize = size; } -#ifdef HAVE_ZLIB +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) static void newcomprbuf(int size) { @@ -249,7 +254,7 @@ newcomprbuf(int size) 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 @@ -260,9 +265,10 @@ setup(void) { int i, j, *ip, bot_code; struct STAT stbuf; + char *temptape; Vprintf(stdout, "Verify tape and initialize maps\n"); - if (bot_script) { + if (Afile == NULL && bot_script) { msg("Launching %s\n", bot_script); bot_code = system_command(bot_script, magtape, 1); if (bot_code != 0 && bot_code != 1) { @@ -270,20 +276,31 @@ setup(void) exit(1); } } + + if (Afile) + temptape = Afile; + else + temptape = magtape; + #ifdef RRESTORE if (host) - mt = rmtopen(magtape, 0); + mt = rmtopen(temptape, 0); else #endif if (pipein) mt = 0; else - mt = OPEN(magtape, O_RDONLY, 0); + mt = OPEN(temptape, O_RDONLY, 0); if (mt < 0) err(1, "%s", magtape); - volno = 1; - setmagtapein(); - setdumpnum(); + if (!Afile) { + volno = 1; + setmagtapein(); + setdumpnum(); + } +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) + readtape_func = readtape_set; +#endif FLUSHTAPEBUF(); findtapeblksize(); if (gethead(&spcl) == FAIL) { @@ -298,11 +315,9 @@ setup(void) if (zflag) { fprintf(stderr, "Dump tape is compressed.\n"); -#ifdef HAVE_ZLIB - newcomprbuf(ntrec); -#else +#if !defined(HAVE_ZLIB) && !defined(HAVE_BZLIB) errx(1,"This restore version doesn't support decompression"); -#endif /* HAVE_ZLIB */ +#endif /* !HAVE_ZLIB && !HAVE_BZLIB */ } if (pipein) { endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC; @@ -379,7 +394,8 @@ 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]; @@ -396,11 +412,12 @@ 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 */ - if (command == 'R' || command == 'r' || curfile.action != SKIP) { + if (aflag || curfile.action != SKIP) { newvol = nextvol; wantnext = 1; } else { @@ -426,12 +443,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, @@ -491,20 +512,28 @@ again: } gethdr: setmagtapein(); +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) + readtape_func = readtape_set; +#endif 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) { @@ -513,10 +542,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. @@ -524,6 +556,12 @@ gethdr: * If coming to this volume at random, skip to the beginning * of the next record. */ + if (zflag) { + fprintf(stderr, "Dump tape is compressed.\n"); +#if !defined(HAVE_ZLIB) && !defined(HAVE_BZLIB) + errx(1,"This restore version doesn't support decompression"); +#endif /* !HAVE_ZLIB && !HAVE_BZLIB */ + } Dprintf(stdout, "read %ld recs, tape starts with %ld\n", tpblksread, (long)tmpbuf.c_firstrec); if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) { @@ -620,6 +658,18 @@ printdumpinfo(void) fprintf(stdout, "Label: %s\n", spcl.c_label); } +void +printvolinfo(void) +{ + int i; + + if (volinfo[1] == ROOTINO) { + printf("Starting inode numbers by volume:\n"); + for (i = 1; i < TP_NINOS && volinfo[i] != 0; ++i) + printf("\tVolume %d: %lu\n", i, (unsigned long)volinfo[i]); + } +} + int extractfile(char *name) { @@ -803,7 +853,7 @@ skipfile(void) void getfile(void (*fill) __P((char *, size_t)), void (*skip) __P((char *, size_t))) { - register int i; + int i; volatile int curblk = 0; volatile quad_t size = spcl.c_dinode.di_size; volatile int last_write_was_hole = 0; @@ -1062,14 +1112,14 @@ cmpfiles(char *tapefile, char *diskfile, struct STAT *sbuf_disk) 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 @@ -1079,12 +1129,12 @@ cmpfiles(char *tapefile, char *diskfile, struct STAT *sbuf_disk) 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) { 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)) { @@ -1092,7 +1142,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/ */ @@ -1145,7 +1195,7 @@ comparefile(char *name) if ((r = LSTAT(name, &sb)) != 0) { warn("%s: does not exist (%d)", name, r); - compare_errors = 1; + do_compare_error; skipfile(); return; } @@ -1160,7 +1210,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: @@ -1182,7 +1232,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'; @@ -1192,20 +1242,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; @@ -1216,7 +1266,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; } @@ -1229,7 +1279,7 @@ 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; @@ -1239,7 +1289,7 @@ comparefile(char *name) 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; @@ -1253,7 +1303,7 @@ comparefile(char *name) } } if (cmperror) - compare_errors = 1; + do_compare_error; close(ifile); } #else @@ -1285,7 +1335,7 @@ comparefile(char *name) /* NOTREACHED */ } -#ifdef HAVE_ZLIB +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) static void (*readtape_func)(char *) = readtape_set; /* @@ -1318,7 +1368,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. @@ -1326,7 +1376,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) @@ -1450,7 +1500,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. @@ -1478,6 +1528,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; @@ -1636,6 +1689,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 */ @@ -1647,41 +1703,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: - numtrec = worklen / TP_BSIZE; - if (worklen % TP_BSIZE != 0) - reason = "length mismatch"; - 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; } @@ -1709,7 +1812,7 @@ msg_read_error(char *m) break; } } -#endif /* HAVE_ZLIB */ +#endif /* HAVE_ZLIB || HAVE_BZLIB */ /* * Read the first block and get the blocksize from it. Test @@ -1862,13 +1965,15 @@ setmagtapein(void) { /* need to know if input is really from a tape */ #ifdef RRESTORE if (host) - magtapein = rmtioctl(MTNOP, 1) != -1; + magtapein = !lflag; else #endif magtapein = ioctl(mt, MTIOCGET, (char *)&mt_stat) == 0; } - Vprintf(stdout,"Input is from %s\n", magtapein? "tape": "file/pipe"); + Vprintf(stdout,"Input is from %s\n", + magtapein ? "tape" : + Vflag ? "multi-volume (no tape)" : "file/pipe"); } /* @@ -1909,7 +2014,7 @@ gethead(struct s_spcl *buf) int32_t odi_ctime; } c_dinode; int32_t c_count; - char c_addr[256]; + char c_fill[256]; } s_ospcl; } u_ospcl; @@ -1955,7 +2060,7 @@ gethead(struct s_spcl *buf) buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; #endif /* __linux__ */ buf->c_count = u_ospcl.s_ospcl.c_count; - memmove(buf->c_addr, u_ospcl.s_ospcl.c_addr, (long)256); + memmove(buf->c_addr, u_ospcl.s_ospcl.c_fill, (long)256); if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC || checksum((int *)(&u_ospcl.s_ospcl)) == FAIL) return(FAIL); @@ -2001,6 +2106,11 @@ good: /* fall through */ case TS_END: buf->c_inumber = 0; + if (buf->c_flags & DR_INODEINFO) { + memcpy(volinfo, buf->c_inos, TP_NINOS * sizeof(dump_ino_t)); + if (Bcvt) + swabst((u_char *)"128i", (u_char *)volinfo); + } break; case TS_INODE: @@ -2155,7 +2265,7 @@ findinode(struct s_spcl *header) static int checksum(int *buf) { - register int i, j; + int i, j; j = sizeof(union u_spcl) / sizeof(int); i = 0; @@ -2308,14 +2418,32 @@ swabl(u_long x) * get the current position of the tape */ int -GetTapePos(long *pos) +GetTapePos(long long *pos) { int err = 0; - *pos = 0; - if (ioctl(mt, MTIOCPOS, pos) == -1) { +#ifdef RDUMP + if (host) { + *pos = (long long) rmtseek(0, SEEK_CUR); + err = *pos < 0; + } + else +#endif + { + if (magtapein) { + long mtpos; + *pos = 0; + err = (ioctl(mt, MTIOCPOS, &mtpos) < 0); + *pos = (long long)mtpos; + } + else { + *pos = LSEEK(mt, 0, SEEK_CUR); + err = (*pos < 0); + } + } + if (err) { err = errno; - fprintf(stdout, "[%ld] error: %d (getting tapepos: %ld)\n", + fprintf(stdout, "[%ld] error: %d (getting tapepos: %lld)\n", (unsigned long)getpid(), err, *pos); return err; } @@ -2331,16 +2459,30 @@ typedef struct mt_pos { * go to specified position on tape */ int -GotoTapePos(long pos) +GotoTapePos(long long pos) { int err = 0; - struct mt_pos buf; - buf.mt_op = MTSEEK; - buf.mt_count = pos; - if (ioctl(mt, MTIOCTOP, &buf) == -1) { +#ifdef RDUMP + if (host) + err = (rmtseek((long)pos, SEEK_SET) < 0); + else +#endif + { + if (magtapein) { + struct mt_pos buf; + buf.mt_op = MTSEEK; + buf.mt_count = (int) pos; + err = (ioctl(mt, MTIOCTOP, &buf) < 0); + } + else { + pos = LSEEK(mt, pos, SEEK_SET); + err = (pos < 0); + } + } + if (err) { err = errno; - fprintf(stdout, "[%ld] error: %d (setting tapepos: %ld)\n", + fprintf(stdout, "[%ld] error: %d (setting tapepos: %lld)\n", (unsigned long)getpid(), err, pos); return err; } @@ -2363,6 +2505,7 @@ ReReadFromTape(void) findinode(&spcl); noresyncmesg = 0; } +#endif /* USE_QFA */ void RequestVol(long tnum) @@ -2370,4 +2513,3 @@ RequestVol(long tnum) FLUSHTAPEBUF(); getvol(tnum); } -#endif /* USE_QFA */