X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=restore%2Ftape.c;h=45d19d22aa8234a12480f424459aeb8e5a513961;hb=401a4d13e4c30d46074531c6c26efefcaf3bbdaf;hp=4bce13d97400c9bf9a1ba34e83cbd00c604b87f2;hpb=0d7af9c5f2cc7d4a97e934692ea8665e09fd5500;p=dump.git diff --git a/restore/tape.c b/restore/tape.c index 4bce13d..45d19d2 100644 --- a/restore/tape.c +++ b/restore/tape.c @@ -2,7 +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 , 1999-2000 + * Stelian Pop - AlcĂ´ve , 2000 */ /* @@ -45,9 +46,10 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.13 2000/03/02 11:34:51 stelian Exp $"; + "$Id: tape.c,v 1.25 2001/02/22 10:57:40 stelian Exp $"; #endif /* not lint */ +#include #include #include #include @@ -55,6 +57,7 @@ static const char rcsid[] = #ifdef __linux__ #include +#include #include #include #else /* __linux__ */ @@ -70,6 +73,10 @@ static const char rcsid[] = #include #include +#ifdef HAVE_ZLIB +#include +#endif /* HAVE_ZLIB */ + #ifdef __linux__ #include #endif @@ -86,6 +93,11 @@ static char magtapeprefix[MAXPATHLEN]; static int blkcnt; static int numtrec; static char *tapebuf; +static char *tbufptr = NULL; /* active tape buffer */ +#ifdef HAVE_ZLIB +static char *comprbuf; /* uncompress work buf */ +static size_t comprlen; +#endif static union u_spcl endoftapemark; static long blksread; /* blocks read since last header */ static long tpblksread = 0; /* TP_BSIZE blocks read */ @@ -113,7 +125,9 @@ static int gethead __P((struct s_spcl *)); static void readtape __P((char *)); static void setdumpnum __P((void)); static u_int swabi __P((u_int)); +#if 0 static u_long swabl __P((u_long)); +#endif static u_char *swab64 __P((u_char *, int)); static u_char *swab32 __P((u_char *, int)); static u_char *swab16 __P((u_char *, int)); @@ -125,6 +139,15 @@ static void xtrmap __P((char *, size_t)); static void xtrmapskip __P((char *, size_t)); static void xtrskip __P((char *, size_t)); +#define COMPARE_ONTHEFLY 1 + +#if COMPARE_ONTHEFLY +static int ifile; /* input file for compare */ +static int cmperror; /* compare error */ +static void xtrcmpfile __P((char *, size_t)); +static void xtrcmpskip __P((char *, size_t)); +#endif + static int readmapflag; /* @@ -188,6 +211,14 @@ newtapebuf(long size) if (tapebuf == NULL) errx(1, "Cannot allocate space for tape buffer"); tapebufsize = size; +#ifdef HAVE_ZLIB + if (comprbuf != NULL) + free(comprbuf); + comprlen = size * TP_BSIZE; + comprbuf = malloc(comprlen); + if (comprbuf == NULL) + errx(1, "Cannot allocate space for uncompress buffer"); +#endif /* HAVE_ZLIB */ } /* @@ -226,6 +257,15 @@ setup(void) errx(1, "Tape is not a dump tape"); fprintf(stderr, "Converting to new file system format.\n"); } + + if (spcl.c_flags & DR_COMPRESSED) { + fprintf(stderr, "Dump tape is compressed.\n"); +#ifdef HAVE_ZLIB + zflag = 1; +#else + errx(1,"This restore version doesn't support decompression"); +#endif /* HAVE_ZLIB */ + } if (pipein) { endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC; endoftapemark.s_spcl.c_type = TS_END; @@ -241,15 +281,11 @@ setup(void) printdumpinfo(); if (filesys[0] == '\0') { char *dirptr; -printf("spcl.c_filesys = %s\n", spcl.c_filesys); strncpy(filesys, spcl.c_filesys, NAMELEN); filesys[NAMELEN - 1] = '\0'; dirptr = strstr(filesys, " (dir"); -printf("dirptr = %s\n", dirptr); if (dirptr != NULL) *dirptr = '\0'; -printf("dirptr = %s\n", dirptr); -printf("filesys = %s\n", filesys); } dumptime = spcl.c_ddate; dumpdate = spcl.c_date; @@ -274,7 +310,7 @@ printf("filesys = %s\n", filesys); Dprintf(stdout, "maxino = %ld\n", (long)maxino); map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); if (map == NULL) - panic("no memory for active inode map\n"); + errx(1, "no memory for active inode map"); usedinomap = map; curfile.action = USING; getfile(xtrmap, xtrmapskip); @@ -282,7 +318,7 @@ printf("filesys = %s\n", filesys); errx(1, "Cannot find file dump list"); map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); if (map == (char *)NULL) - panic("no memory for file dump list\n"); + errx(1, "no memory for file dump list"); dumpmap = map; curfile.action = USING; getfile(xtrmap, xtrmapskip); @@ -354,7 +390,7 @@ again: do { fprintf(stderr, "Specify next volume #: "); (void) fflush(stderr); - (void) fgets(buf, BUFSIZ, terminal); + (void) fgets(buf, TP_BSIZE, terminal); } while (!feof(terminal) && buf[0] == '\n'); if (feof(terminal)) exit(1); @@ -379,7 +415,7 @@ again: fprintf(stderr, "Enter ``none'' if there are no more tapes\n"); fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape); (void) fflush(stderr); - (void) fgets(buf, BUFSIZ, terminal); + (void) fgets(buf, TP_BSIZE, terminal); if (feof(terminal)) exit(1); if (!strcmp(buf, "none\n")) { @@ -541,9 +577,9 @@ printdumpinfo(void) #endif if (spcl.c_host[0] == '\0') return; - fprintf(stderr, "Level %d dump of %s on %s:%s\n", + fprintf(stdout, "Level %d dump of %s on %s:%s\n", spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev); - fprintf(stderr, "Label: %s\n", spcl.c_label); + fprintf(stdout, "Label: %s\n", spcl.c_label); } int @@ -877,6 +913,63 @@ xtrnull(char *buf, size_t size) return; } +#if COMPARE_ONTHEFLY +/* + * Compare the next block of a file. + */ +static void +xtrcmpfile(char *buf, size_t size) +{ + static char cmpbuf[MAXBSIZE]; + + if (cmperror) + return; + + if (read(ifile, cmpbuf, size) != size) { + fprintf(stderr, "%s: size has changed.\n", + curfile.name); + cmperror = 1; + return; + } + + if (memcmp(buf, cmpbuf, size) != 0) { + fprintf(stderr, "%s: tape and disk copies are different\n", + curfile.name); + cmperror = 1; + return; + } +} + +/* + * Skip over a hole in a file. + */ +static void +xtrcmpskip(char *buf, size_t size) +{ + static char cmpbuf[MAXBSIZE]; + int i; + + if (cmperror) + return; + + if (read(ifile, cmpbuf, size) != size) { + fprintf(stderr, "%s: size has changed.\n", + curfile.name); + cmperror = 1; + return; + } + + for (i = 0; i < size; ++i) + if (cmpbuf[i] != '\0') { + fprintf(stderr, "%s: tape and disk copies are different\n", + curfile.name); + cmperror = 1; + return; + } +} +#endif /* COMPARE_ONTHEFLY */ + +#if !COMPARE_ONTHEFLY static int do_cmpfiles(int fd_tape, int fd_disk, long size) { @@ -922,12 +1015,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; } 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; #ifdef COMPARE_FAIL_KEEP_FILE return (0); #else @@ -937,10 +1032,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; } if ((fd_disk = open(diskfile, O_RDONLY)) < 0) { close(fd_tape); panic("Can't open %s: %s\n", diskfile, strerror(errno)); + compare_errors = 1; } if (do_cmpfiles(fd_tape, fd_disk, sbuf_tape.st_size)) { @@ -948,6 +1045,7 @@ cmpfiles(char *tapefile, char *diskfile, struct stat *sbuf_disk) diskfile); close(fd_tape); close(fd_disk); + compare_errors = 1; #ifdef COMPARE_FAIL_KEEP_FILE /* rename the file to live in /tmp */ /* rename `tapefile' to /tmp/ */ @@ -981,19 +1079,26 @@ cmpfiles(char *tapefile, char *diskfile, struct stat *sbuf_disk) return (1); #endif } +#endif /* !COMPARE_ONTHEFLY */ +#if !COMPARE_ONTHEFLY static char tmpfilename[MAXPATHLEN]; +#endif void comparefile(char *name) { - static char *tmpfile = NULL; int mode; - struct stat sb, stemp; + struct stat sb; int r; +#if !COMPARE_ONTHEFLY + static char *tmpfile = NULL; + struct stat stemp; +#endif if ((r = lstat(name, &sb)) != 0) { warn("%s: does not exist (%d)", name, r); + compare_errors = 1; skipfile(); return; } @@ -1008,6 +1113,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; } switch (mode & IFMT) { default: @@ -1029,6 +1135,7 @@ comparefile(char *name) if (!(sb.st_mode & S_IFLNK)) { fprintf(stderr, "%s: is no longer a symbolic link\n", name); + compare_errors = 1; return; } lnkbuf[0] = '\0'; @@ -1038,17 +1145,20 @@ comparefile(char *name) fprintf(stderr, "%s: zero length symbolic link (ignored)\n", name); + compare_errors = 1; return; } if ((lsize = readlink(name, lbuf, MAXPATHLEN)) < 0) { panic("readlink of %s failed: %s", name, strerror(errno)); + compare_errors = 1; } 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; return; } return; @@ -1059,6 +1169,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; skipfile(); return; } @@ -1071,11 +1182,34 @@ comparefile(char *name) (int)curfile.dip->di_rdev & 0xff, ((int)sb.st_rdev >> 8) & 0xff, (int)sb.st_rdev & 0xff); + compare_errors = 1; } skipfile(); return; case IFREG: +#if COMPARE_ONTHEFLY + if ((ifile = open(name, O_RDONLY)) < 0) { + panic("Can't open %s: %s\n", name, strerror(errno)); + skipfile(); + compare_errors = 1; + } + else { + cmperror = 0; + getfile(xtrcmpfile, xtrcmpskip); + if (!cmperror) { + char c; + if (read(ifile, &c, 1) != 0) { + fprintf(stderr, "%s: size has changed.\n", + name); + cmperror = 1; + } + } + if (cmperror) + compare_errors = 1; + close(ifile); + } +#else if (tmpfile == NULL) { /* argument to mktemp() must not be in RO space: */ snprintf(tmpfilename, sizeof(tmpfilename), "%s/restoreCXXXXXX", tmpdir); @@ -1098,6 +1232,7 @@ comparefile(char *name) cmpfiles(tmpfile, name, &sb); unlink(tmpfile); #endif +#endif /* COMPARE_ONTHEFLY */ return; } /* NOTREACHED */ @@ -1112,13 +1247,19 @@ readtape(char *buf) { ssize_t rd, newvol, i; int cnt, seek_failed; +#ifdef HAVE_ZLIB + int cresult; + struct tapebuf* tpb; + unsigned long worklen; +#endif if (blkcnt < numtrec) { - memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], TP_BSIZE); + memmove(buf, &tbufptr[(blkcnt++ * TP_BSIZE)], TP_BSIZE); blksread++; tpblksread++; return; } + tbufptr = tapebuf; for (i = 0; i < ntrec; i++) ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; if (numtrec == 0) @@ -1132,6 +1273,28 @@ getmore: else #endif i = read(mt, &tapebuf[rd], cnt); + +#ifdef HAVE_ZLIB + if (i < 0) + goto readerror; + if (i == 0 && !pipein) + goto endoftape; + + if (zflag && i != ntrec * TP_BSIZE) { + tpb = (struct tapebuf *) tapebuf; + if (i != tpb->clen + sizeof(struct tapebuf)) + errx(1,"tape is not a compressed dump tape"); + worklen = comprlen; + cresult = uncompress(comprbuf, &worklen, tpb->buf, tpb->clen); + if (cresult != Z_OK) + errx(1,"tape is not a compressed dump tape"); + if (worklen != tpb->unclen) + errx(1,"decompression error, length mismatch"); + i = worklen; + tbufptr = comprbuf; + } +#endif /* HAVE_ZLIB */ + /* * Check for mid-tape short read error. * If found, skip rest of buffer and start with the next. @@ -1166,6 +1329,9 @@ getmore: /* * Handle read error. */ +#ifdef HAVE_ZLIB +readerror: +#endif if (i < 0) { fprintf(stderr, "Tape read error while "); switch (curfile.action) { @@ -1194,12 +1360,19 @@ getmore: #endif seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1); - if (seek_failed) - err(1, "continuation failed"); + if (seek_failed) { + warn("continuation failed"); + if (!yflag && !reply("assume end-of-tape and continue")) + exit(1); + i = 0; + } } /* * Handle end of tape. */ +#ifdef HAVE_ZLIB +endoftape: +#endif if (i == 0) { Vprintf(stdout, "End-of-tape encountered\n"); if (!pipein) { @@ -1217,7 +1390,7 @@ getmore: memmove(&tapebuf[rd], &endoftapemark, TP_BSIZE); } blkcnt = 0; - memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], TP_BSIZE); + memmove(buf, &tbufptr[(blkcnt++ * TP_BSIZE)], TP_BSIZE); blksread++; tpblksread++; } @@ -1244,6 +1417,7 @@ findtapeblksize(void) (long)i, TP_BSIZE); ntrec = i / TP_BSIZE; numtrec = ntrec; + tbufptr = tapebuf; Vprintf(stdout, "Tape block size is %ld\n", ntrec); } @@ -1681,9 +1855,11 @@ swabi(u_int x) return (x); } +#if 0 static u_long swabl(u_long x) { swabst((u_char *)"l", (u_char *)&x); return (x); } +#endif