X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=restore%2Ftape.c;h=553abbc8e99fef89f0d75fc27bdbd2a612451a3c;hp=50d8a3e1daef9a10bd59c5527651855ca41d0a9a;hb=206f768c7a7a4bca1c4acc3c686d55578c0cb919;hpb=40df6a0e578b56977f18c2a960f3fd30c4c78e60 diff --git a/restore/tape.c b/restore/tape.c index 50d8a3e..553abbc 100644 --- a/restore/tape.c +++ b/restore/tape.c @@ -23,11 +23,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -46,7 +42,7 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.53 2002/01/16 10:29:26 stelian Exp $"; + "$Id: tape.c,v 1.74 2003/03/31 09:42:59 stelian Exp $"; #endif /* not lint */ #include @@ -88,6 +84,10 @@ static const char rcsid[] = #include #endif /* HAVE_BZLIB */ +#ifdef HAVE_LZO +#include +#endif /* HAVE_LZO */ + #include "restore.h" #include "extern.h" #include "pathnames.h" @@ -106,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 */ -#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) static char *comprbuf; /* uncompress work buf */ static size_t comprlen; /* size including prefix */ #endif @@ -116,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; @@ -134,6 +134,8 @@ static int checksum __P((int *)); static void findinode __P((struct s_spcl *)); static void findtapeblksize __P((void)); static int gethead __P((struct s_spcl *)); +static int converthead __P((struct s_spcl *)); +static void converttapebuf __P((struct tapebuf *)); static void readtape __P((char *)); static void setdumpnum __P((void)); static u_int swabi __P((u_int)); @@ -152,8 +154,9 @@ static void xtrmapskip __P((char *, size_t)); static void xtrskip __P((char *, size_t)); static void setmagtapein __P((void)); -#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) 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 *)); @@ -174,6 +177,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. @@ -239,7 +243,7 @@ newtapebuf(long size) tapebufsize = size; } -#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) static void newcomprbuf(int size) { @@ -253,7 +257,7 @@ newcomprbuf(int size) if (comprbuf == NULL) errx(1, "Cannot allocate space for decompress buffer"); } -#endif /* HAVE_ZLIB || HAVE_BZLIB */ +#endif /* HAVE_ZLIB || HAVE_BZLIB || HAVE_LZO */ /* * Verify that the tape drive can be accessed and @@ -264,9 +268,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) { @@ -274,20 +279,37 @@ setup(void) exit(1); } } + + if (Afile) + temptape = Afile; + else + temptape = magtape; + #ifdef RRESTORE - if (host) - mt = rmtopen(magtape, 0); + if (!Afile && host) + mt = rmtopen(temptape, O_RDONLY); 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(); + err(1, "%s", temptape); + if (!Afile) { + volno = 1; + setmagtapein(); + setdumpnum(); + } +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) + readtape_func = readtape_set; +#if defined(HAVE_LZO) + if (lzo_init() != LZO_E_OK) { + msg("internal error - lzo_init failed \n"); + exit(1); + } +#endif +#endif FLUSHTAPEBUF(); findtapeblksize(); if (gethead(&spcl) == FAIL) { @@ -302,11 +324,9 @@ setup(void) if (zflag) { fprintf(stderr, "Dump tape is compressed.\n"); -#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) - newcomprbuf(ntrec); -#else +#if !defined(HAVE_ZLIB) && !defined(HAVE_BZLIB) && !defined(HAVE_LZO) 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; @@ -321,6 +341,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); @@ -345,17 +369,27 @@ 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 */ + dump_ino_t oldmaxino = maxino; + maxino += (spcl.c_count * TP_BSIZE * NBBY) + 1; + resizemaps(oldmaxino, maxino); + + 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)); @@ -364,6 +398,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 @@ -371,6 +409,8 @@ setup(void) */ if (oldinofmt == 0) SETINO(WINO, dumpmap); + readingmaps = 0; + findinode(&spcl); } /* @@ -393,6 +433,8 @@ getvol(long nextvol) if (nextvol == 1) { tapesread = 0; gettingfile = 0; + tpblksread = 0; + blksread = 0; } if (pipein) { if (nextvol != 1) @@ -403,6 +445,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 */ @@ -416,7 +462,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", @@ -450,9 +496,25 @@ 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(); + + /* + * if using an archive file, reset its name so readtape() + * could properly use remote access. + */ + Afile = NULL; + if (Mflag) { snprintf(magtape, MAXPATHLEN, "%s%03ld", magtapeprefix, newvol); magtape[MAXPATHLEN - 1] = '\0'; @@ -467,9 +529,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)) @@ -488,7 +550,7 @@ again: } #ifdef RRESTORE if (host) - mt = rmtopen(magtape, 0); + mt = rmtopen(magtape, O_RDONLY); else #endif mt = OPEN(magtape, O_RDONLY, 0); @@ -501,6 +563,9 @@ again: } gethdr: setmagtapein(); +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) + readtape_func = readtape_set; +#endif volno = newvol; setdumpnum(); FLUSHTAPEBUF(); @@ -533,8 +598,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. @@ -542,11 +605,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) && !defined(HAVE_LZO) + 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 && @@ -638,22 +707,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 < (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; @@ -675,7 +775,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(); @@ -690,16 +789,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 @@ -712,12 +816,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); @@ -738,12 +844,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); @@ -761,32 +869,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 */ } @@ -821,7 +938,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; @@ -873,7 +990,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) { @@ -888,7 +1005,8 @@ loop: if (last_write_was_hole) { FTRUNCATE(ofile, origsize); } - findinode(&spcl); + if (!readingmaps) + findinode(&spcl); gettingfile = 0; } @@ -911,10 +1029,10 @@ 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) + if (LSEEK(ofile, (OFF_T)size, SEEK_CUR) == -1) err(1, "seek error extracting inode %lu, name %s\nlseek", (unsigned long)curfile.ino, curfile.name); } @@ -938,7 +1056,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); @@ -960,7 +1078,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"); @@ -972,7 +1090,7 @@ xtrmapskip(char *buf, size_t size) */ /* ARGSUSED */ void -xtrnull(char *buf, size_t size) +xtrnull(UNUSED(char *buf), UNUSED(size_t size)) { return; @@ -990,7 +1108,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; @@ -1009,7 +1127,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; @@ -1017,14 +1135,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); @@ -1153,7 +1271,7 @@ static char tmpfilename[MAXPATHLEN]; void comparefile(char *name) { - int mode; + unsigned int mode; struct STAT sb; int r; #if !COMPARE_ONTHEFLY @@ -1161,6 +1279,16 @@ comparefile(char *name) struct STAT stemp; #endif + curfile.name = name; + curfile.action = USING; + mode = curfile.dip->di_mode; + + if ((mode & IFMT) == IFSOCK) { + Vprintf(stdout, "skipped socket %s\n", name); + skipfile(); + return; + } + if ((r = LSTAT(name, &sb)) != 0) { warn("%s: does not exist (%d)", name, r); do_compare_error; @@ -1168,10 +1296,6 @@ comparefile(char *name) return; } - curfile.name = name; - curfile.action = USING; - mode = curfile.dip->di_mode; - Vprintf(stdout, "comparing %s (size: %ld, mode: 0%o)\n", name, (long)sb.st_size, mode); @@ -1180,6 +1304,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(); @@ -1239,7 +1367,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, @@ -1303,7 +1431,7 @@ comparefile(char *name) /* NOTREACHED */ } -#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) static void (*readtape_func)(char *) = readtape_set; /* @@ -1336,7 +1464,7 @@ readtape_set(char *buf) readtape(buf); } -#endif /* HAVE_ZLIB || HAVE_BZLIB */ +#endif /* HAVE_ZLIB || HAVE_BZLIB || HAVE_LZO */ /* * This is the original readtape(), it's used for reading uncompressed input. @@ -1344,7 +1472,7 @@ readtape_set(char *buf) * Handle read errors, and end of media. */ static void -#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) readtape_uncompr(char *buf) #else readtape(char *buf) @@ -1366,9 +1494,13 @@ 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) + if (!Afile && host) i = rmtread(&tapebuf[rd], cnt); else #endif @@ -1430,11 +1562,11 @@ getmore: i = ntrec * TP_BSIZE; memset(tapebuf, 0, (size_t)i); #ifdef RRESTORE - if (host) + if (!Afile && host) seek_failed = (rmtseek(i, 1) < 0); else #endif - seek_failed = (LSEEK(mt, i, SEEK_CUR) == (off_t)-1); + seek_failed = (LSEEK(mt, i, SEEK_CUR) == (OFF_T)-1); if (seek_failed) { warn("continuation failed"); @@ -1468,7 +1600,7 @@ getmore: tpblksread++; } -#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) /* * Read a compressed format block from a file or pipe and uncompress it. @@ -1496,8 +1628,9 @@ readtape_comprfile(char *buf) /* read the block prefix */ ret = read_a_block(mt, tapebuf, PREFIXSIZE, &rl); + converttapebuf(tpb); - 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; @@ -1588,6 +1721,7 @@ readtape_comprtape(char *buf) if (ret <= 0) goto readerr; + converttapebuf(tpb); tbufptr = decompress_tapebuf(tpb, rl); if (tbufptr == NULL) { msg_read_error("Tape decompression error while"); @@ -1664,10 +1798,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; @@ -1735,6 +1869,29 @@ decompress_tapebuf(struct tapebuf *tpbin, int readsize) cresult = 0; #endif /* HAVE_BZLIB */ } + if (tpbin->flags == COMPRESS_LZO) { +#ifndef HAVE_LZO + errx(1,"This restore version doesn't support lzo decompression"); +#else + cresult = lzo1x_decompress(tpbin->buf, blocklen, + comprbuf, (lzo_uintp) &worklen,NULL); + output = comprbuf; + switch (cresult) { + case LZO_E_OK: + break; + case LZO_E_ERROR: + case LZO_E_EOF_NOT_FOUND: + reason = "data error"; + break; + default: + reason = "unknown"; + } + if (cresult == LZO_E_OK) + cresult = 1; + else + cresult = 0; +#endif /* HAVE_LZO */ + } } else { output = tpbin->buf; @@ -1780,7 +1937,7 @@ msg_read_error(char *m) break; } } -#endif /* HAVE_ZLIB || HAVE_BZLIB */ +#endif /* HAVE_ZLIB || HAVE_BZLIB || HAVE_LZO */ /* * Read the first block and get the blocksize from it. Test @@ -1798,7 +1955,7 @@ findtapeblksize(void) long i; size_t len; struct tapebuf *tpb = (struct tapebuf *) tapebuf; - struct s_spcl *spclpt = (struct s_spcl *) tapebuf; + struct s_spcl spclpt; for (i = 0; i < ntrec; i++) ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; @@ -1813,6 +1970,17 @@ findtapeblksize(void) if (read_a_block(mt, tapebuf, len, &i) <= 0) errx(1, "Tape read error on first record"); + memcpy(&spclpt, tapebuf, TP_BSIZE); + if (converthead(&spclpt) == FAIL) { + cvtflag++; + if (converthead(&spclpt) == FAIL) { + /* Special case for old compressed tapes with prefix */ + if (magtapein && (i % TP_BSIZE != 0)) + goto oldformat; + errx(1, "Tape is not a dump tape"); + } + fprintf(stderr, "Converting to new file system format.\n"); + } /* * If the input is from a file or a pipe, we read TP_BSIZE * bytes looking for a dump header. If the dump is compressed @@ -1821,14 +1989,14 @@ findtapeblksize(void) * dump is not compressed and does not have a prefix. */ if (!magtapein) { - if (spclpt->c_type == TS_TAPE - && spclpt->c_flags & DR_COMPRESSED) { + if (spclpt.c_type == TS_TAPE + && spclpt.c_flags & DR_COMPRESSED) { /* It's a compressed dump file, read in the */ - /* rest of the block based on spclpt->c_ntrec. */ - if (spclpt->c_ntrec > ntrec) + /* rest of the block based on spclpt.c_ntrec. */ + if (spclpt.c_ntrec > ntrec) errx(1, "Tape blocksize is too large, use " - "\'-b %d\' ", spclpt->c_ntrec); - ntrec = spclpt->c_ntrec; + "\'-b %d\' ", spclpt.c_ntrec); + ntrec = spclpt.c_ntrec; len = (ntrec - 1) * TP_BSIZE; zflag = 1; } @@ -1837,7 +2005,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; @@ -1851,14 +2019,21 @@ findtapeblksize(void) * what we asked for; adjust the value of ntrec and test for * a compressed dump tape. */ - if (i % TP_BSIZE != 0) { +oldformat: /* may be old format compressed dump tape with a prefix */ - spclpt = (struct s_spcl *) tpb->buf; + memcpy(&spclpt, tpb->buf, TP_BSIZE); + cvtflag = 0; + if (converthead(&spclpt) == FAIL) { + cvtflag++; + if (converthead(&spclpt) == FAIL) + errx(1, "Tape is not a dump tape"); + fprintf(stderr, "Converting to new file system format.\n"); + } if (i % TP_BSIZE == PREFIXSIZE && tpb->compressed == 0 - && spclpt->c_type == TS_TAPE - && spclpt->c_flags & DR_COMPRESSED) { + && spclpt.c_type == TS_TAPE + && spclpt.c_flags & DR_COMPRESSED) { zflag = 1; tbufptr = tpb->buf; if (tpb->length > bufsize) @@ -1870,12 +2045,12 @@ findtapeblksize(void) i, TP_BSIZE); } ntrec = i / TP_BSIZE; - if (spclpt->c_type == TS_TAPE) { - if (spclpt->c_flags & DR_COMPRESSED) + if (spclpt.c_type == TS_TAPE) { + if (spclpt.c_flags & DR_COMPRESSED) zflag = 1; - if (spclpt->c_ntrec > ntrec) + if (spclpt.c_ntrec > ntrec) errx(1, "Tape blocksize is too large, use " - "\'-b %d\' ", spclpt->c_ntrec); + "\'-b %d\' ", spclpt.c_ntrec); } numtrec = ntrec; Vprintf(stdout, "Tape block size is %ld\n", ntrec); @@ -1891,7 +2066,7 @@ static int read_a_block(int fd, char *buf, size_t len, long *lengthread) size = len; while (size > 0) { #ifdef RRESTORE - if (host) + if (!Afile && host) i = rmtread(buf, size); else #endif @@ -1915,7 +2090,7 @@ closemt(void) if (mt < 0) return; #ifdef RRESTORE - if (host) + if (!Afile && host) rmtclose(); else #endif @@ -1939,7 +2114,8 @@ setmagtapein(void) { magtapein = ioctl(mt, MTIOCGET, (char *)&mt_stat) == 0; } - Vprintf(stdout,"Input is from %s\n", + Vprintf(stdout,"Input is from a %s %s\n", + host ? "remote" : "local", magtapein ? "tape" : Vflag ? "multi-volume (no tape)" : "file/pipe"); } @@ -1952,6 +2128,13 @@ setmagtapein(void) { */ static int gethead(struct s_spcl *buf) +{ + readtape((char *)buf); + return converthead(buf); +} + +static int +converthead(struct s_spcl *buf) { int32_t i; union { @@ -1982,12 +2165,11 @@ 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; if (!cvtflag) { - readtape((char *)buf); if (buf->c_magic != NFS_MAGIC) { if (swabi(buf->c_magic) != NFS_MAGIC) return (FAIL); @@ -1999,10 +2181,10 @@ gethead(struct s_spcl *buf) if (checksum((int *)buf) == FAIL) return (FAIL); if (Bcvt) - swabst((u_char *)"8i4s31i528bi192b2i", (u_char *)buf); + swabst((u_char *)"8i4s31i528bi192b3i", (u_char *)buf); goto good; } - readtape((char *)(&u_ospcl.s_ospcl)); + memcpy(&u_ospcl.s_ospcl, buf, TP_BSIZE); memset((char *)buf, 0, (long)TP_BSIZE); buf->c_type = u_ospcl.s_ospcl.c_type; buf->c_date = u_ospcl.s_ospcl.c_date; @@ -2018,17 +2200,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); @@ -2039,7 +2221,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; } } @@ -2074,6 +2256,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: @@ -2097,6 +2284,23 @@ good: return(GOOD); } +static void +converttapebuf(struct tapebuf *tpb) +{ + if (Bcvt) { + struct tb { + unsigned int length:28; + unsigned int flags:3; + unsigned int compressed:1; + } tb; + swabst((u_char *)"i", (u_char *)tpb); + memcpy(&tb, tpb, 4); + tpb->length = tb.length; + tpb->flags = tb.flags; + tpb->compressed = tb.compressed; + } +} + /* * Check that a header is where it belongs and predict the next header */ @@ -2228,7 +2432,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; @@ -2381,14 +2585,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; } @@ -2404,16 +2626,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(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; } @@ -2437,10 +2673,32 @@ 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 < ntrec)); +#ifdef DEBUG_QFA + fprintf(stderr, "%ld reads\n", cntloop); + if (cntloop == ntrec) { + fprintf(stderr, "DEBUG: bufsize %d\n", bufsize); + fprintf(stderr, "DEBUG: ntrec %ld\n", ntrec); + } +#endif + findinode(&spcl); + noresyncmesg = 0; +} +#endif /* USE_QFA */ + void RequestVol(long tnum) { FLUSHTAPEBUF(); getvol(tnum); } -#endif /* USE_QFA */