X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=restore%2Ftape.c;h=1b6b1d9d52578436d8fd6c1cfa6baf712359fe11;hp=d7e8ed635be54041c6872d5512e64eca52d861ea;hb=ff9e45da1a0be7807fb18401ca7e5ee28d0e1007;hpb=6d9ffa3ebaadf8f1709aa4e6a8956fab4abf4f64 diff --git a/restore/tape.c b/restore/tape.c index d7e8ed6..1b6b1d9 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,13 +46,14 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.39 2001/05/26 11:04:46 stelian Exp $"; + "$Id: tape.c,v 1.61 2002/05/06 08:45:41 stelian Exp $"; #endif /* not lint */ #include #include #include #include +#include #include #include #include @@ -67,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__ */ @@ -79,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" @@ -88,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]; @@ -97,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 @@ -107,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; @@ -143,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 *)); @@ -165,6 +175,7 @@ static void xtrcmpskip __P((char *, size_t)); #endif static int readmapflag; +static int readingmaps; /* set to 1 while reading the maps */ /* * Set up an input source. This is called from main.c before setup() is. @@ -230,7 +241,7 @@ newtapebuf(long size) tapebufsize = size; } -#ifdef HAVE_ZLIB +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) static void newcomprbuf(int size) { @@ -244,7 +255,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 @@ -253,24 +264,44 @@ newcomprbuf(int size) void setup(void) { - int i, j, *ip; + int i, j, *ip, bot_code; struct STAT stbuf; + char *temptape; Vprintf(stdout, "Verify tape and initialize maps\n"); + 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) { + msg("Restore aborted by the beginning of tape script\n"); + 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) { @@ -285,11 +316,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; @@ -304,6 +333,10 @@ setup(void) } if (vflag || command == 't' || command == 'C') printdumpinfo(); +#ifdef USE_QFA + if (tapeposflag && spcl.c_date != qfadumpdate) + errx(1, "different QFA/dumpdates detected\n"); +#endif if (filesys[0] == '\0') { char *dirptr; strncpy(filesys, spcl.c_filesys, NAMELEN); @@ -328,17 +361,33 @@ setup(void) Dprintf(stdout, "header read failed at %ld blocks\n", (long)blksread); panic("no header after volume mark!\n"); } + readingmaps = 1; findinode(&spcl); 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", (long)maxino); map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); if (map == NULL) errx(1, "no memory for active inode map"); usedinomap = map; curfile.action = USING; getfile(xtrmap, xtrmapskip); + while (spcl.c_type == TS_ADDR) { + /* Recompute maxino and the map */ + char *oldmap = usedinomap; + dump_ino_t oldmaxino = maxino; + maxino += (spcl.c_count * TP_BSIZE * NBBY) + 1; + map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); + if (map == NULL) + errx(1, "no memory for active inode map"); + usedinomap = map; + memcpy(usedinomap, oldmap, howmany(oldmaxino, NBBY)); + free(oldmap); + + spcl.c_dinode.di_size = spcl.c_count * TP_BSIZE; + getfile(xtrmap, xtrmapskip); + } + Dprintf(stdout, "maxino = %lu\n", (unsigned long)maxino); if (spcl.c_type != TS_BITS) errx(1, "Cannot find file dump list"); map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); @@ -347,6 +396,10 @@ setup(void) dumpmap = map; curfile.action = USING; getfile(xtrmap, xtrmapskip); + while (spcl.c_type == TS_ADDR) { + spcl.c_dinode.di_size = spcl.c_count * TP_BSIZE; + getfile(xtrmap, xtrmapskip); + } /* * If there may be whiteout entries on the tape, pretend that the * whiteout inode exists, so that the whiteout entries can be @@ -354,6 +407,8 @@ setup(void) */ if (oldinofmt == 0) SETINO(WINO, dumpmap); + readingmaps = 0; + findinode(&spcl); } /* @@ -366,15 +421,18 @@ 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; gettingfile = 0; + tpblksread = 0; + blksread = 0; } if (pipein) { if (nextvol != 1) @@ -383,11 +441,16 @@ getvol(long nextvol) return; goto gethdr; } - savecnt = blksread; + saved_blksread = blksread; + saved_tpblksread = tpblksread; +#if defined(USE_QFA) && defined(sunos) + if (createtapeposflag || tapeposflag) + close(fdsmtc); +#endif 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 { @@ -397,7 +460,7 @@ again: while (newvol <= 0) { if (tapesread == 0) { fprintf(stderr, "%s%s%s%s%s", - "You have not read any tapes yet.\n", + "You have not read any volumes yet.\n", "Unless you know which volume your", " file(s) are on you should start\n", "with the last volume and work", @@ -413,12 +476,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, @@ -427,6 +494,15 @@ again: } if (newvol == volno) { tapesread |= 1 << volno; +#if defined(USE_QFA) && defined(sunos) + if (createtapeposflag || tapeposflag) { + if (OpenSMTCmt(magtape) < 0) { + volno = -1; + haderror = 1; + goto again; + } + } +#endif return; } closemt(); @@ -434,11 +510,19 @@ 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"); - fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape); + fprintf(stderr, "Mount volume %ld\n", (long)newvol); + fprintf(stderr, "Enter ``none'' if there are no more volumes\n"); + fprintf(stderr, "otherwise enter volume name (default: %s) ", magtape); (void) fflush(stderr); (void) fgets(buf, TP_BSIZE, terminal); if (feof(terminal)) @@ -448,8 +532,11 @@ again: return; } if (buf[0] != '\n') { + char *pos; (void) strncpy(magtape, buf, sizeof(magtape)); magtape[sizeof(magtape) - 1] = '\0'; + if ((pos = strchr(magtape, '\n'))) + magtape[pos - magtape] = '\0'; } } #ifdef RRESTORE @@ -467,20 +554,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) { @@ -489,10 +584,11 @@ gethdr: fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); volno = 0; haderror = 1; + blksread = saved_blksread; + tpblksread = saved_tpblksread; goto again; } tapesread |= 1 << volno; - blksread = savecnt; /* * If continuing from the previous volume, skip over any * blocks read already at the end of the previous volume. @@ -500,11 +596,17 @@ 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); + tpblksread - 1, (long)tmpbuf.c_firstrec); if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) { if (!wantnext) { - tpblksread = tmpbuf.c_firstrec; + tpblksread = tmpbuf.c_firstrec + 1; for (i = tmpbuf.c_count; i > 0; i--) readtape(buf); } else if (tmpbuf.c_firstrec > 0 && @@ -596,22 +698,53 @@ 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]); + } +} + +#ifdef sunos +struct timeval + time_t tv_sec; /* seconds */ + suseconds_t tv_usec; /* and microseconds */ +}; +#endif + int -extractfile(char *name) +extractfile(struct entry *ep, int doremove) { unsigned int flags; mode_t mode; struct timeval timep[2]; - struct entry *ep; + char *name = myname(ep); + + /* If removal is requested (-r mode) do remove it unless + * we are extracting a metadata only inode */ + if (spcl.c_flags & DR_METAONLY) { + Vprintf(stdout, "file %s is metadata only\n", name); + } + else { + if (doremove) { + removeleaf(ep); + ep->e_flags &= ~REMOVED; + } + } curfile.name = name; curfile.action = USING; -#ifdef __linux__ +#if defined(__linux__) || defined(sunos) timep[0].tv_sec = curfile.dip->di_atime.tv_sec; timep[0].tv_usec = curfile.dip->di_atime.tv_usec; timep[1].tv_sec = curfile.dip->di_mtime.tv_sec; timep[1].tv_usec = curfile.dip->di_mtime.tv_usec; -#else /* __linux__ */ +#else /* __linux__ || sunos */ timep[0].tv_sec = curfile.dip->di_atime; timep[0].tv_usec = curfile.dip->di_atimensec / 1000; timep[1].tv_sec = curfile.dip->di_mtime; @@ -633,7 +766,6 @@ extractfile(char *name) case IFDIR: if (mflag) { - ep = lookupname(name); if (ep == NULL || ep->e_flags & EXTRACT) panic("unextracted directory %s\n", name); skipfile(); @@ -648,16 +780,21 @@ extractfile(char *name) uid_t luid = curfile.dip->di_uid; gid_t lgid = curfile.dip->di_gid; #endif - lnkbuf[0] = '\0'; - pathlen = 0; - getfile(xtrlnkfile, xtrlnkskip); - if (pathlen == 0) { - Vprintf(stdout, - "%s: zero length symbolic link (ignored)\n", name); - return (GOOD); + if (! (spcl.c_flags & DR_METAONLY)) { + lnkbuf[0] = '\0'; + pathlen = 0; + getfile(xtrlnkfile, xtrlnkskip); + if (pathlen == 0) { + Vprintf(stdout, + "%s: zero length symbolic link (ignored)\n", name); + return (GOOD); + } + if (linkit(lnkbuf, name, SYMLINK) == FAIL) + return (FAIL); } - if (linkit(lnkbuf, name, SYMLINK) == FAIL) - return (FAIL); + else + skipfile(); + #ifdef HAVE_LCHOWN (void) lchown(name, luid, lgid); #endif @@ -670,12 +807,14 @@ extractfile(char *name) skipfile(); return (GOOD); } - if (uflag && !Nflag) - (void)unlink(name); - if (mkfifo(name, mode) < 0) { - warn("%s: cannot create fifo", name); - skipfile(); - return (FAIL); + if (! (spcl.c_flags & DR_METAONLY)) { + if (uflag && !Nflag) + (void)unlink(name); + if (mkfifo(name, mode) < 0) { + warn("%s: cannot create fifo", name); + skipfile(); + return (FAIL); + } } (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); (void) chmod(name, mode); @@ -696,12 +835,14 @@ extractfile(char *name) skipfile(); return (GOOD); } - if (uflag) - (void)unlink(name); - if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) { - warn("%s: cannot create special file", name); - skipfile(); - return (FAIL); + if (! (spcl.c_flags & DR_METAONLY)) { + if (uflag) + (void)unlink(name); + if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) { + warn("%s: cannot create special file", name); + skipfile(); + return (FAIL); + } } (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); (void) chmod(name, mode); @@ -719,32 +860,41 @@ extractfile(char *name) return (GOOD); case IFREG: + { + uid_t luid = curfile.dip->di_uid; + gid_t lgid = curfile.dip->di_gid; + Vprintf(stdout, "extract file %s\n", name); if (Nflag) { skipfile(); return (GOOD); } - if (uflag) - (void)unlink(name); - if ((ofile = OPEN(name, O_WRONLY | O_CREAT | O_TRUNC, - 0666)) < 0) { - warn("%s: cannot create file", name); - skipfile(); - return (FAIL); + if (! (spcl.c_flags & DR_METAONLY)) { + if (uflag) + (void)unlink(name); + if ((ofile = OPEN(name, O_WRONLY | O_CREAT | O_TRUNC, + 0666)) < 0) { + warn("%s: cannot create file", name); + skipfile(); + return (FAIL); + } + getfile(xtrfile, xtrskip); + (void) close(ofile); } - (void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid); - (void) fchmod(ofile, mode); + else + skipfile(); + (void) chown(name, luid, lgid); + (void) chmod(name, mode); if (flags) #ifdef __linux__ - (void) setflags(ofile, flags); + (void) fsetflags(name, flags); #else - (void) fchflags(ofile, flags); + (void) chflags(name, flags); #endif - getfile(xtrfile, xtrskip); - (void) close(ofile); utimes(name, timep); return (GOOD); } + } /* NOTREACHED */ } @@ -779,7 +929,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; @@ -831,7 +981,7 @@ loop: curfile.name, (long)blksread); } if (curblk > 0) { - (*fill)((char *)buf, (size_t)(curblk * TP_BSIZE) + size); + (*fill)((char *)buf, (size_t)((curblk * TP_BSIZE) + size)); last_write_was_hole = 0; } if (size > 0) { @@ -846,7 +996,8 @@ loop: if (last_write_was_hole) { FTRUNCATE(ofile, origsize); } - findinode(&spcl); + if (!readingmaps) + findinode(&spcl); gettingfile = 0; } @@ -1038,14 +1189,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 @@ -1055,12 +1206,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)) { @@ -1068,7 +1219,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/ */ @@ -1121,7 +1272,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; } @@ -1136,7 +1287,11 @@ 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; + } + if (spcl.c_flags & DR_METAONLY) { + skipfile(); + return; } switch (mode & IFMT) { default: @@ -1158,7 +1313,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'; @@ -1168,20 +1323,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; @@ -1192,7 +1347,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; } @@ -1205,7 +1360,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; @@ -1215,7 +1370,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; @@ -1229,7 +1384,7 @@ comparefile(char *name) } } if (cmperror) - compare_errors = 1; + do_compare_error; close(ifile); } #else @@ -1261,7 +1416,7 @@ comparefile(char *name) /* NOTREACHED */ } -#ifdef HAVE_ZLIB +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) static void (*readtape_func)(char *) = readtape_set; /* @@ -1294,7 +1449,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. @@ -1302,7 +1457,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) @@ -1324,6 +1479,10 @@ readtape(char *buf) numtrec = ntrec; cnt = ntrec * TP_BSIZE; rd = 0; +#ifdef USE_QFA + if (createtapeposflag) + (void)GetTapePos(&curtapepos); +#endif getmore: #ifdef RRESTORE if (host) @@ -1426,7 +1585,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. @@ -1454,6 +1613,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; @@ -1612,6 +1774,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 */ @@ -1623,41 +1788,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; } @@ -1685,7 +1897,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 @@ -1838,13 +2050,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"); } /* @@ -1885,7 +2099,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; @@ -1921,17 +2135,17 @@ gethead(struct s_spcl *buf) buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid; buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size; buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev; -#ifdef __linux__ +#if defined(__linux__) || defined(sunos) buf->c_dinode.di_atime.tv_sec = u_ospcl.s_ospcl.c_dinode.odi_atime; buf->c_dinode.di_mtime.tv_sec = u_ospcl.s_ospcl.c_dinode.odi_mtime; buf->c_dinode.di_ctime.tv_sec = u_ospcl.s_ospcl.c_dinode.odi_ctime; -#else /* __linux__ */ +#else /* __linux__ || sunos */ buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime; buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime; buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; -#endif /* __linux__ */ +#endif /* __linux__ || sunos */ 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); @@ -1942,7 +2156,7 @@ good: (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt == 0) { qcvt.qval = buf->c_dinode.di_size; if (qcvt.val[0] || qcvt.val[1]) { - printf("Note: Doing Quad swapping\n"); + Vprintf(stdout, "Note: Doing Quad swapping\n"); Qcvt = 1; } } @@ -1977,6 +2191,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: @@ -2131,7 +2350,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; @@ -2284,14 +2503,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; } @@ -2307,16 +2544,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; } @@ -2340,10 +2591,33 @@ ReReadFromTape(void) noresyncmesg = 0; } +void +ReReadInodeFromTape(dump_ino_t theino) +{ + long cntloop = 0; + + FLUSHTAPEBUF(); + noresyncmesg = 1; + do { + cntloop++; + gethead(&spcl); + } while (!(spcl.c_inumber == theino && spcl.c_type == TS_INODE && spcl.c_date == dumpdate) && (cntloop < 32)); +#ifdef DEBUG_QFA + fprintf(stderr, "%ld reads\n", cntloop); + if (cntloop == 32) { + fprintf(stderr, "DEBUG: bufsize %d\n", bufsize); + fprintf(stderr, "DEBUG: ntrec %ld\n", ntrec); + fprintf(stderr, "DEBUG: %ld reads\n", cntloop); + } +#endif + findinode(&spcl); + noresyncmesg = 0; +} +#endif /* USE_QFA */ + void RequestVol(long tnum) { FLUSHTAPEBUF(); getvol(tnum); } -#endif /* USE_QFA */