X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=restore%2Ftape.c;h=3195ab53b4746893ca50f62ef3e085980bd3db60;hp=94ceab46fdfa9a706cac851acb3108936dd05fcf;hb=ba3af39e8b08027d3338b5533bddc86a9c803a74;hpb=78daec31fcd3deeb9a1fe0129521abc9959a51bb diff --git a/restore/tape.c b/restore/tape.c index 94ceab4..3195ab5 100644 --- a/restore/tape.c +++ b/restore/tape.c @@ -46,7 +46,7 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.57 2002/01/31 10:25:55 stelian Exp $"; + "$Id: tape.c,v 1.64 2002/07/29 12:00:34 stelian Exp $"; #endif /* not lint */ #include @@ -175,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. @@ -284,7 +285,7 @@ setup(void) #ifdef RRESTORE if (host) - mt = rmtopen(temptape, 0); + mt = rmtopen(temptape, O_RDONLY); else #endif if (pipein) @@ -332,6 +333,10 @@ setup(void) } if (vflag || command == 't' || command == 'C') printdumpinfo(); +#ifdef USE_QFA + if (tapeposflag && (unsigned long)spcl.c_date != qfadumpdate) + errx(1, "different QFA/dumpdates detected\n"); +#endif if (filesys[0] == '\0') { char *dirptr; strncpy(filesys, spcl.c_filesys, NAMELEN); @@ -356,18 +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); - findinode(&spcl); + 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)); @@ -376,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 @@ -383,6 +407,7 @@ setup(void) */ if (oldinofmt == 0) SETINO(WINO, dumpmap); + readingmaps = 0; findinode(&spcl); } @@ -406,6 +431,8 @@ getvol(long nextvol) if (nextvol == 1) { tapesread = 0; gettingfile = 0; + tpblksread = 0; + blksread = 0; } if (pipein) { if (nextvol != 1) @@ -416,6 +443,10 @@ getvol(long nextvol) } 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 */ @@ -429,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", @@ -463,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(); @@ -480,9 +520,9 @@ again: } 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)) @@ -501,7 +541,7 @@ again: } #ifdef RRESTORE if (host) - mt = rmtopen(magtape, 0); + mt = rmtopen(magtape, O_RDONLY); else #endif mt = OPEN(magtape, O_RDONLY, 0); @@ -549,8 +589,6 @@ gethdr: goto again; } tapesread |= 1 << volno; - 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. @@ -565,10 +603,10 @@ gethdr: #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 && @@ -667,27 +705,46 @@ printvolinfo(void) if (volinfo[1] == ROOTINO) { printf("Starting inode numbers by volume:\n"); - for (i = 1; i < TP_NINOS && volinfo[i] != 0; ++i) + for (i = 1; i < (int)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; @@ -709,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(); @@ -724,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 @@ -746,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); @@ -772,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); @@ -795,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 */ } @@ -907,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) { @@ -922,7 +996,8 @@ loop: if (last_write_was_hole) { FTRUNCATE(ofile, origsize); } - findinode(&spcl); + if (!readingmaps) + findinode(&spcl); gettingfile = 0; } @@ -945,7 +1020,7 @@ xtrfile(char *buf, size_t size) */ /* ARGSUSED */ static void -xtrskip(char *buf, size_t size) +xtrskip(UNUSED(char *buf), size_t size) { if (LSEEK(ofile, (off_t)size, SEEK_CUR) == -1) @@ -972,7 +1047,7 @@ xtrlnkfile(char *buf, size_t size) */ /* ARGSUSED */ static void -xtrlnkskip(char *buf, size_t size) +xtrlnkskip(UNUSED(char *buf), UNUSED(size_t size)) { errx(1, "unallocated block in symbolic link %s", curfile.name); @@ -994,7 +1069,7 @@ xtrmap(char *buf, size_t size) */ /* ARGSUSED */ static void -xtrmapskip(char *buf, size_t size) +xtrmapskip(UNUSED(char *buf), size_t size) { panic("hole in map\n"); @@ -1006,7 +1081,7 @@ xtrmapskip(char *buf, size_t size) */ /* ARGSUSED */ void -xtrnull(char *buf, size_t size) +xtrnull(UNUSED(char *buf), UNUSED(size_t size)) { return; @@ -1024,7 +1099,7 @@ xtrcmpfile(char *buf, size_t size) if (cmperror) return; - if (read(ifile, cmpbuf, size) != size) { + if (read(ifile, cmpbuf, size) != (ssize_t)size) { fprintf(stderr, "%s: size has changed.\n", curfile.name); cmperror = 1; @@ -1043,7 +1118,7 @@ xtrcmpfile(char *buf, size_t size) * Skip over a hole in a file. */ static void -xtrcmpskip(char *buf, size_t size) +xtrcmpskip(UNUSED(char *buf), size_t size) { static char cmpbuf[MAXBSIZE]; int i; @@ -1051,14 +1126,14 @@ xtrcmpskip(char *buf, size_t size) if (cmperror) return; - if (read(ifile, cmpbuf, size) != size) { + if (read(ifile, cmpbuf, size) != (ssize_t)size) { fprintf(stderr, "%s: size has changed.\n", curfile.name); cmperror = 1; return; } - for (i = 0; i < size; ++i) + for (i = 0; i < (int)size; ++i) if (cmpbuf[i] != '\0') { fprintf(stderr, "%s: tape and disk copies are different\n", curfile.name); @@ -1187,7 +1262,7 @@ static char tmpfilename[MAXPATHLEN]; void comparefile(char *name) { - int mode; + unsigned int mode; struct STAT sb; int r; #if !COMPARE_ONTHEFLY @@ -1214,6 +1289,10 @@ comparefile(char *name) name, mode & 07777, sb.st_mode & 07777); do_compare_error; } + if (spcl.c_flags & DR_METAONLY) { + skipfile(); + return; + } switch (mode & IFMT) { default: skipfile(); @@ -1273,7 +1352,7 @@ comparefile(char *name) return; } - if (sb.st_rdev != (int)curfile.dip->di_rdev) { + if (sb.st_rdev != (dev_t)curfile.dip->di_rdev) { fprintf(stderr, "%s: device changed from %d,%d to %d,%d.\n", name, @@ -1400,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) @@ -1531,7 +1614,7 @@ 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)) + if (Vflag && (ret == 0 || rl < (int)PREFIXSIZE || tpb->length == 0)) ret = 0; if (ret <= 0) goto readerr; @@ -1698,10 +1781,10 @@ decompress_tapebuf(struct tapebuf *tpbin, int readsize) /* build a length error message */ blocklen = tpbin->length; - if (readsize < blocklen + PREFIXSIZE) + if (readsize < blocklen + (int)PREFIXSIZE) lengtherr = "short"; else - if (readsize > blocklen + PREFIXSIZE) + if (readsize > blocklen + (int)PREFIXSIZE) lengtherr = "long"; worklen = comprlen; @@ -1871,7 +1954,7 @@ findtapeblksize(void) len = bufsize - TP_BSIZE; } if (read_a_block(mt, tapebuf+TP_BSIZE, len, &i) < 0 - || (i != len && i % TP_BSIZE != 0)) + || (i != (long)len && i % TP_BSIZE != 0)) errx(1,"Error reading dump file header"); tbufptr = tapebuf; numtrec = ntrec; @@ -2052,15 +2135,15 @@ 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_fill, (long)256); if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC || @@ -2073,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; } } @@ -2507,6 +2590,29 @@ ReReadFromTape(void) findinode(&spcl); 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