X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=restore%2Ftape.c;h=45d19d22aa8234a12480f424459aeb8e5a513961;hb=401a4d13e4c30d46074531c6c26efefcaf3bbdaf;hp=754da610152cb9732c855c854209486f4466c3ff;hpb=08ebf8d7df645851cb5597fd7f755551655c5aa8;p=dump.git diff --git a/restore/tape.c b/restore/tape.c index 754da61..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 + * Stelian Pop , 1999-2000 + * Stelian Pop - AlcĂ´ve , 2000 */ /* @@ -45,9 +46,10 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.7 1999/11/05 22:02:19 tiniou 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 @@ -81,10 +88,16 @@ static const char rcsid[] = static long fssize = MAXBSIZE; static int mt = -1; static int pipein = 0; -static char *magtape; +static char magtape[MAXPATHLEN]; +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 */ @@ -112,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)); @@ -124,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; /* @@ -163,9 +187,14 @@ setinput(char *source) pipein++; } setuid(getuid()); /* no longer need or want root privileges */ - magtape = strdup(source); - if (magtape == NULL) - errx(1, "Cannot allocate space for magtape buffer"); + if (Mflag) { + strncpy(magtapeprefix, source, MAXPATHLEN); + magtapeprefix[MAXPATHLEN-1] = '\0'; + snprintf(magtape, MAXPATHLEN, "%s%03d", source, 1); + } + else + strncpy(magtape, source, MAXPATHLEN); + magtape[MAXPATHLEN - 1] = '\0'; } void @@ -182,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 */ } /* @@ -220,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; @@ -233,8 +279,13 @@ setup(void) } if (vflag || command == 't' || command == 'C') printdumpinfo(); - if (filesys == NULL) { - filesys = spcl.c_filesys; + if (filesys[0] == '\0') { + char *dirptr; + strncpy(filesys, spcl.c_filesys, NAMELEN); + filesys[NAMELEN - 1] = '\0'; + dirptr = strstr(filesys, " (dir"); + if (dirptr != NULL) + *dirptr = '\0'; } dumptime = spcl.c_ddate; dumpdate = spcl.c_date; @@ -256,10 +307,10 @@ setup(void) if (spcl.c_type != TS_CLRI) errx(1, "Cannot find file removal list"); maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1; - Dprintf(stdout, "maxino = %ld\n", maxino); + 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); @@ -267,7 +318,7 @@ setup(void) 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); @@ -294,6 +345,7 @@ getvol(long nextvol) union u_spcl tmpspcl; # define tmpbuf tmpspcl.s_spcl char buf[TP_BSIZE]; + int haderror = 0; if (nextvol == 1) { tapesread = 0; @@ -338,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); @@ -353,20 +405,27 @@ again: return; } closemt(); - fprintf(stderr, "Mount tape volume %ld\n", (long)newvol); - 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); - if (feof(terminal)) - exit(1); - if (!strcmp(buf, "none\n")) { - terminateinput(); - return; + if (Mflag) { + snprintf(magtape, MAXPATHLEN, "%s%03ld", magtapeprefix, newvol); + magtape[MAXPATHLEN - 1] = '\0'; } - if (buf[0] != '\n') { - (void) strcpy(magtape, buf); - magtape[strlen(magtape) - 1] = '\0'; + if (!Mflag || haderror) { + haderror = 0; + fprintf(stderr, "Mount tape volume %ld\n", (long)newvol); + 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, TP_BSIZE, terminal); + if (feof(terminal)) + exit(1); + if (!strcmp(buf, "none\n")) { + terminateinput(); + return; + } + if (buf[0] != '\n') { + (void) strcpy(magtape, buf); + magtape[strlen(magtape) - 1] = '\0'; + } } #ifdef RRESTORE if (host) @@ -378,6 +437,7 @@ again: if (mt == -1) { fprintf(stderr, "Cannot open %s\n", magtape); volno = -1; + haderror = 1; goto again; } gethdr: @@ -388,11 +448,13 @@ gethdr: Dprintf(stdout, "header read failed at %ld blocks\n", (long)blksread); fprintf(stderr, "tape is not dump tape\n"); volno = 0; + haderror = 1; goto again; } if (tmpbuf.c_volume != volno) { fprintf(stderr, "Wrong volume (%d)\n", tmpbuf.c_volume); volno = 0; + haderror = 1; goto again; } if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) { @@ -406,6 +468,7 @@ gethdr: fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); #endif volno = 0; + haderror = 1; goto again; } tapesread |= 1 << volno; @@ -514,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 @@ -566,9 +629,11 @@ extractfile(char *name) return (genliteraldir(name, curfile.ino)); case IFLNK: - { uid_t luid = curfile.dip->di_uid; + { +#ifdef HAVE_LCHOWN + uid_t luid = curfile.dip->di_uid; gid_t lgid = curfile.dip->di_gid; - +#endif lnkbuf[0] = '\0'; pathlen = 0; getfile(xtrlnkfile, xtrlnkskip); @@ -848,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) { @@ -893,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 @@ -908,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)) { @@ -919,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/ */ @@ -952,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; } @@ -979,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: @@ -1000,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'; @@ -1009,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; @@ -1030,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; } @@ -1042,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); @@ -1069,6 +1232,7 @@ comparefile(char *name) cmpfiles(tmpfile, name, &sb); unlink(tmpfile); #endif +#endif /* COMPARE_ONTHEFLY */ return; } /* NOTREACHED */ @@ -1083,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) @@ -1103,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. @@ -1137,6 +1329,9 @@ getmore: /* * Handle read error. */ +#ifdef HAVE_ZLIB +readerror: +#endif if (i < 0) { fprintf(stderr, "Tape read error while "); switch (curfile.action) { @@ -1165,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) { @@ -1188,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++; } @@ -1215,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); } @@ -1419,7 +1622,7 @@ accthdr(struct s_spcl *header) fprintf(stderr, "File header, ino %lu", (unsigned long)previno); break; case TS_ADDR: - fprintf(stderr, "File continuation header, ino %ld", previno); + fprintf(stderr, "File continuation header, ino %ld", (long)previno); break; case TS_END: fprintf(stderr, "End of tape header"); @@ -1652,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