aboutsummaryrefslogtreecommitdiff
path: root/sbin/restore
diff options
context:
space:
mode:
authorDavid Malone <dwmalone@FreeBSD.org>2006-12-05 11:18:51 +0000
committerDavid Malone <dwmalone@FreeBSD.org>2006-12-05 11:18:51 +0000
commitcbc8bb98efc17781454a83b2d5f53042f49a4776 (patch)
tree93515273cbec28074cbc2e6628a45e20d8f8745d /sbin/restore
parent762d365ac610288281abb20ff2959a084b2548dd (diff)
downloadsrc-cbc8bb98efc17781454a83b2d5f53042f49a4776.tar.gz
src-cbc8bb98efc17781454a83b2d5f53042f49a4776.zip
Notes
Diffstat (limited to 'sbin/restore')
-rw-r--r--sbin/restore/main.c7
-rw-r--r--sbin/restore/restore.816
-rw-r--r--sbin/restore/restore.c12
-rw-r--r--sbin/restore/restore.h1
-rw-r--r--sbin/restore/tape.c90
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;
}