diff options
author | David Malone <dwmalone@FreeBSD.org> | 2006-12-05 11:18:51 +0000 |
---|---|---|
committer | David Malone <dwmalone@FreeBSD.org> | 2006-12-05 11:18:51 +0000 |
commit | cbc8bb98efc17781454a83b2d5f53042f49a4776 (patch) | |
tree | 93515273cbec28074cbc2e6628a45e20d8f8745d /sbin/restore | |
parent | 762d365ac610288281abb20ff2959a084b2548dd (diff) | |
download | src-cbc8bb98efc17781454a83b2d5f53042f49a4776.tar.gz src-cbc8bb98efc17781454a83b2d5f53042f49a4776.zip |
Notes
Diffstat (limited to 'sbin/restore')
-rw-r--r-- | sbin/restore/main.c | 7 | ||||
-rw-r--r-- | sbin/restore/restore.8 | 16 | ||||
-rw-r--r-- | sbin/restore/restore.c | 12 | ||||
-rw-r--r-- | sbin/restore/restore.h | 1 | ||||
-rw-r--r-- | sbin/restore/tape.c | 90 |
5 files changed, 104 insertions, 22 deletions
diff --git a/sbin/restore/main.c b/sbin/restore/main.c index 63fb4efd347d..91f4a83c7296 100644 --- a/sbin/restore/main.c +++ b/sbin/restore/main.c @@ -60,7 +60,7 @@ __FBSDID("$FreeBSD$"); #include "restore.h" #include "extern.h" -int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0; +int bflag = 0, cvtflag = 0, dflag = 0, Dflag = 0, vflag = 0, yflag = 0; int hflag = 1, mflag = 1, Nflag = 0; int uflag = 0; int pipecmd = 0; @@ -97,7 +97,7 @@ main(int argc, char *argv[]) inputdev = NULL; obsolete(&argc, &argv); - while ((ch = getopt(argc, argv, "b:df:himNP:Rrs:tuvxy")) != -1) + while ((ch = getopt(argc, argv, "b:dDf:himNP:Rrs:tuvxy")) != -1) switch(ch) { case 'b': /* Change default tape blocksize. */ @@ -111,6 +111,9 @@ main(int argc, char *argv[]) case 'd': dflag = 1; break; + case 'D': + Dflag = 1; + break; case 'f': if (pipecmd) errx(1, diff --git a/sbin/restore/restore.8 b/sbin/restore/restore.8 index 9db0d67870da..cf6a364693b0 100644 --- a/sbin/restore/restore.8 +++ b/sbin/restore/restore.8 @@ -38,32 +38,32 @@ .Sh SYNOPSIS .Nm .Fl i -.Op Fl dhmNuvy +.Op Fl dDhmNuvy .Op Fl b Ar blocksize .Op Fl f Ar file | Fl P Ar pipecommand .Op Fl s Ar fileno .Nm .Fl R -.Op Fl dNuvy +.Op Fl dDNuvy .Op Fl b Ar blocksize .Op Fl f Ar file | Fl P Ar pipecommand .Op Fl s Ar fileno .Nm .Fl r -.Op Fl dNuvy +.Op Fl dDNuvy .Op Fl b Ar blocksize .Op Fl f Ar file | Fl P Ar pipecommand .Op Fl s Ar fileno .Nm .Fl t -.Op Fl dhNuvy +.Op Fl dDhNuvy .Op Fl b Ar blocksize .Op Fl f Ar file | Fl P Ar pipecommand .Op Fl s Ar fileno .Op Ar .Nm .Fl x -.Op Fl dhmNuvy +.Op Fl dDhmNuvy .Op Fl b Ar blocksize .Op Fl f Ar file | Fl P Ar pipecommand .Op Fl s Ar fileno @@ -278,6 +278,12 @@ option is not specified, tries to determine the media block size dynamically. .It Fl d Sends verbose debugging output to the standard error. +.It Fl D +This puts +.Nm +into degraded mode, +causing restore to operate less efficiently +but to try harder to read corrupted backups. .It Fl f Ar file Read the backup from .Ar file ; diff --git a/sbin/restore/restore.c b/sbin/restore/restore.c index 046c0d27afc2..e494cdb69a7d 100644 --- a/sbin/restore/restore.c +++ b/sbin/restore/restore.c @@ -687,6 +687,17 @@ createfiles(void) */ if (first > last) return; + if (Dflag) { + if (curfile.ino == maxino) + return; + if((ep = lookupino(curfile.ino)) != NULL && + (ep->e_flags & (NEW|EXTRACT))) { + goto justgetit; + } else { + skipfile(); + continue; + } + } /* * Reject any volumes with inodes greater than the last * one needed, so that we can quickly skip backwards to @@ -749,6 +760,7 @@ createfiles(void) ep = lookupino(next); if (ep == NULL) panic("corrupted symbol table\n"); +justgetit: (void) extractfile(myname(ep)); ep->e_flags &= ~NEW; if (volno != curvol) diff --git a/sbin/restore/restore.h b/sbin/restore/restore.h index 04048dc5de19..43e4db5acb5d 100644 --- a/sbin/restore/restore.h +++ b/sbin/restore/restore.h @@ -40,6 +40,7 @@ */ extern int bflag; /* set input block size */ extern int dflag; /* print out debugging info */ +extern int Dflag; /* degraded mode - try hard to get stuff back */ extern int hflag; /* restore heirarchies */ extern int mflag; /* restore by name instead of inode number */ extern int Nflag; /* do not write the disk */ diff --git a/sbin/restore/tape.c b/sbin/restore/tape.c index 83f5ec879909..eb9802f07535 100644 --- a/sbin/restore/tape.c +++ b/sbin/restore/tape.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include <limits.h> #include <paths.h> #include <setjmp.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -74,6 +75,7 @@ static int blkcnt; static int numtrec; static char *tapebuf; static union u_spcl endoftapemark; +static long byteslide = 0; static long blksread; /* blocks read since last header */ static int64_t tapeaddr = 0; /* current TP_BSIZE tape record */ static long tapesread; @@ -170,12 +172,13 @@ newtapebuf(long size) if (size <= tapebufsize) return; if (tapebuf != NULL) - free(tapebuf); - tapebuf = malloc(size * TP_BSIZE); + free(tapebuf - TP_BSIZE); + tapebuf = malloc((size+1) * TP_BSIZE); if (tapebuf == NULL) { fprintf(stderr, "Cannot allocate space for tape buffer\n"); done(1); } + tapebuf += TP_BSIZE; tapebufsize = size; } @@ -733,6 +736,15 @@ getfile(void (*fill)(char *, long), void (*skip)(char *, long)) gettingfile++; loop: for (i = 0; i < spcl.c_count; i++) { + if (!readmapflag && i > TP_NINDIR) { + if (Dflag) { + fprintf(stderr, "spcl.c_count = %jd\n", + (intmax_t)spcl.c_count); + break; + } else + panic("spcl.c_count = %jd\n", + (intmax_t)spcl.c_count); + } if (readmapflag || spcl.c_addr[i]) { readtape(&buf[curblk++][0]); if (curblk == fssize / TP_BSIZE) { @@ -751,9 +763,20 @@ loop: TP_BSIZE : size)); } if ((size -= TP_BSIZE) <= 0) { - for (i++; i < spcl.c_count; i++) + for (i++; i < spcl.c_count; i++) { + if (!readmapflag && i > TP_NINDIR) { + if (Dflag) { + fprintf(stderr, + "spcl.c_count = %jd\n", + (intmax_t)spcl.c_count); + break; + } else + panic("spcl.c_count = %jd\n", + (intmax_t)spcl.c_count); + } if (readmapflag || spcl.c_addr[i]) readtape(junk); + } break; } } @@ -872,15 +895,19 @@ xtrnull(char *buf, long size) static void readtape(char *buf) { - long rd, newvol, i; + long rd, newvol, i, oldnumtrec; int cnt, seek_failed; - if (blkcnt < numtrec) { - memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE); + if (blkcnt + (byteslide > 0) < numtrec) { + memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE) + byteslide], (long)TP_BSIZE); blksread++; tapeaddr++; return; } + if (numtrec > 0) + memmove(&tapebuf[-TP_BSIZE], + &tapebuf[(numtrec-1) * TP_BSIZE], (long)TP_BSIZE); + oldnumtrec = numtrec; for (i = 0; i < ntrec; i++) ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; if (numtrec == 0) @@ -981,8 +1008,12 @@ getmore: terminateinput(); memmove(&tapebuf[rd], &endoftapemark, (long)TP_BSIZE); } - blkcnt = 0; - memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE); + if (oldnumtrec == 0) + blkcnt = 0; + else + blkcnt -= oldnumtrec; + memmove(buf, + &tapebuf[(blkcnt++ * TP_BSIZE) + byteslide], (long)TP_BSIZE); blksread++; tapeaddr++; } @@ -1069,6 +1100,8 @@ gethead(struct s_spcl *buf) } if (checksum((int *)buf) == FAIL) return (FAIL); + if (_time64_to_time(buf->c_date) != dumpdate) + fprintf(stderr, "Header with wrong dumpdate.\n"); if (Bcvt) { swabst((u_char *)"8l4s1q8l2q17l", (u_char *)buf); swabst((u_char *)"l",(u_char *) &buf->c_level); @@ -1225,8 +1258,17 @@ findinode(struct s_spcl *header) if (header->c_addr[i]) readtape(buf); while (gethead(header) == FAIL || - _time64_to_time(header->c_date) != dumpdate) + _time64_to_time(header->c_date) != dumpdate) { skipcnt++; + if (Dflag) { + byteslide++; + if (byteslide < TP_BSIZE) { + blkcnt--; + blksread--; + } else + byteslide = 0; + } + } break; case TS_INODE: @@ -1263,18 +1305,36 @@ findinode(struct s_spcl *header) break; case TS_TAPE: - panic("unexpected tape header\n"); - /* NOTREACHED */ + if (Dflag) + fprintf(stderr, "unexpected tape header\n"); + else + panic("unexpected tape header\n"); default: - panic("unknown tape header type %d\n", spcl.c_type); - /* NOTREACHED */ + if (Dflag) + fprintf(stderr, "unknown tape header type %d\n", + spcl.c_type); + else + panic("unknown tape header type %d\n", + spcl.c_type); + while (gethead(header) == FAIL || + _time64_to_time(header->c_date) != dumpdate) { + skipcnt++; + if (Dflag) { + byteslide++; + if (byteslide < TP_BSIZE) { + blkcnt--; + blksread--; + } else + byteslide = 0; + } + } } } while (htype == TS_ADDR); if (skipcnt > 0) - fprintf(stderr, "resync restore, skipped %ld blocks\n", - skipcnt); + fprintf(stderr, "resync restore, skipped %ld %s\n", + skipcnt, Dflag ? "bytes" : "blocks"); skipcnt = 0; } |