Merge from Lite2

- cleanups,
 - whiteout support
 - bug fixes (chflags missing on a few file types etc)
The dump/restore folks would want to have a closer look at this, the
change is pretty big.
This commit is contained in:
Peter Wemm 1997-03-11 12:55:19 +00:00
parent 08966bd5fd
commit d87d79aefe
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=23685
8 changed files with 416 additions and 283 deletions

View File

@ -37,7 +37,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)dirs.c 8.2 (Berkeley) 1/21/94";
static char sccsid[] = "@(#)dirs.c 8.7 (Berkeley) 5/1/95";
#endif /* not lint */
#include <sys/param.h>
@ -45,9 +45,9 @@ static char sccsid[] = "@(#)dirs.c 8.2 (Berkeley) 1/21/94";
#include <sys/stat.h>
#include <sys/time.h>
#include <ufs/ffs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include <protocols/dumprestore.h>
#include <errno.h>
@ -81,9 +81,10 @@ static struct inotab *inotab[HASHSIZE];
struct modeinfo {
ino_t ino;
struct timeval timep[2];
short mode;
short uid;
short gid;
mode_t mode;
uid_t uid;
gid_t gid;
int flags;
};
/*
@ -272,7 +273,7 @@ treescan(pname, ino, todo)
/*
* a zero inode signals end of directory
*/
while (dp != NULL && dp->d_ino != 0) {
while (dp != NULL) {
locname[namelen] = '\0';
if (namelen + dp->d_namlen >= sizeof(locname)) {
fprintf(stderr, "%s%s: name exceeds %d char\n",
@ -285,8 +286,6 @@ treescan(pname, ino, todo)
dp = rst_readdir(dirp);
bpt = rst_telldir(dirp);
}
if (dp == NULL)
fprintf(stderr, "corrupted directory: %s.\n", locname);
}
/*
@ -334,7 +333,7 @@ searchdir(inum, name)
len = strlen(name);
do {
dp = rst_readdir(dirp);
if (dp == NULL || dp->d_ino == 0)
if (dp == NULL)
return (NULL);
} while (dp->d_namlen != len || strncmp(dp->d_name, name, len) != 0);
return (dp);
@ -367,12 +366,13 @@ putdir(buf, size)
if (Bcvt)
swabst((u_char *)"ls", (u_char *) dp);
if (oldinofmt && dp->d_ino != 0) {
#if BYTE_ORDER == BIG_ENDIAN
if (Bcvt)
#else
if (!Bcvt)
#endif
dp->d_namlen = dp->d_type;
# if BYTE_ORDER == BIG_ENDIAN
if (Bcvt)
dp->d_namlen = dp->d_type;
# else
if (!Bcvt)
dp->d_namlen = dp->d_type;
# endif
dp->d_type = DT_UNKNOWN;
}
i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1));
@ -425,7 +425,7 @@ putent(dp)
(void) fwrite(dirbuf, 1, DIRBLKSIZ, df);
dirloc = 0;
}
bcopy((char *)dp, dirbuf + dirloc, (long)dp->d_reclen);
memmove(dirbuf + dirloc, dp, (long)dp->d_reclen);
prev = dirloc;
dirloc += dp->d_reclen;
}
@ -448,7 +448,7 @@ dcvt(odp, ndp)
register struct direct *ndp;
{
bzero((char *)ndp, (long)(sizeof *ndp));
memset(ndp, 0, (long)(sizeof *ndp));
ndp->d_ino = odp->d_ino;
ndp->d_type = DT_UNKNOWN;
(void) strncpy(ndp->d_name, odp->d_name, ODIRSIZ);
@ -510,8 +510,8 @@ rst_readdir(dirp)
return (NULL);
}
dirp->dd_loc += dp->d_reclen;
if (dp->d_ino == 0 && strcmp(dp->d_name, "/") != 0)
continue;
if (dp->d_ino == 0 && strcmp(dp->d_name, "/") == 0)
return (NULL);
if (dp->d_ino >= maxino) {
dprintf(stderr, "corrupted directory: bad inum %d\n",
dp->d_ino);
@ -636,6 +636,7 @@ setdirmodes(flags)
cp = myname(ep);
(void) chown(cp, node.uid, node.gid);
(void) chmod(cp, node.mode);
(void) chflags(cp, node.flags);
utimes(cp, node.timep);
ep->e_flags &= ~NEW;
}
@ -728,11 +729,12 @@ allocinotab(ino, dip, seekpt)
if (mf == NULL)
return (itp);
node.ino = ino;
node.timep[0].tv_sec = dip->di_atime.tv_sec;
node.timep[0].tv_usec = dip->di_atime.tv_nsec / 1000;
node.timep[1].tv_sec = dip->di_mtime.tv_sec;
node.timep[1].tv_usec = dip->di_mtime.tv_nsec / 1000;
node.timep[0].tv_sec = dip->di_atime;
node.timep[0].tv_usec = dip->di_atimensec / 1000;
node.timep[1].tv_sec = dip->di_mtime;
node.timep[1].tv_usec = dip->di_mtimensec / 1000;
node.mode = dip->di_mode;
node.flags = dip->di_flags;
node.uid = dip->di_uid;
node.gid = dip->di_gid;
(void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf);

View File

@ -32,16 +32,16 @@
*/
#ifndef lint
static char sccsid[] = "@(#)interactive.c 8.1 (Berkeley) 6/5/93";
static char sccsid[] = "@(#)interactive.c 8.5 (Berkeley) 5/1/95";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <ufs/ffs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include <protocols/dumprestore.h>
#include <setjmp.h>
@ -85,7 +85,7 @@ static void formatf __P((struct afile *, int));
static void getcmd __P((char *, char *, char *, int, struct arglist *));
struct dirent *glob_readdir __P((RST_DIR *dirp));
static int glob_stat __P((const char *, struct stat *));
static void mkentry __P((struct direct *, struct afile *));
static void mkentry __P((char *, struct direct *, struct afile *));
static void printlist __P((char *, char *));
/*
@ -503,15 +503,17 @@ printlist(name, basename)
register struct direct *dp;
struct afile single;
RST_DIR *dirp;
int entries, len;
int entries, len, namelen;
char locname[MAXPATHLEN + 1];
dp = pathsearch(name);
if (dp == NULL || (!dflag && TSTINO(dp->d_ino, dumpmap) == 0))
if (dp == NULL || (!dflag && TSTINO(dp->d_ino, dumpmap) == 0) ||
(!vflag && dp->d_ino == WINO))
return;
if ((dirp = rst_opendir(name)) == NULL) {
entries = 1;
list = &single;
mkentry(dp, list);
mkentry(name, dp, list);
len = strlen(basename) + 1;
if (strlen(name) - len > single.len) {
freename(single.fname);
@ -533,17 +535,28 @@ printlist(name, basename)
fprintf(stderr, "%s:\n", name);
entries = 0;
listp = list;
(void) strncpy(locname, name, MAXPATHLEN);
(void) strncat(locname, "/", MAXPATHLEN);
namelen = strlen(locname);
while (dp = rst_readdir(dirp)) {
if (dp == NULL || dp->d_ino == 0)
if (dp == NULL)
break;
if (!dflag && TSTINO(dp->d_ino, dumpmap) == 0)
continue;
if (vflag == 0 &&
(strcmp(dp->d_name, ".") == 0 ||
if (!vflag && (dp->d_ino == WINO ||
strcmp(dp->d_name, ".") == 0 ||
strcmp(dp->d_name, "..") == 0))
continue;
mkentry(dp, listp++);
entries++;
locname[namelen] = '\0';
if (namelen + dp->d_namlen >= MAXPATHLEN) {
fprintf(stderr, "%s%s: name exceeds %d char\n",
locname, dp->d_name, MAXPATHLEN);
} else {
(void) strncat(locname, dp->d_name,
(int)dp->d_namlen);
mkentry(locname, dp, listp++);
entries++;
}
}
rst_closedir(dirp);
if (entries == 0) {
@ -566,7 +579,8 @@ printlist(name, basename)
* Read the contents of a directory.
*/
static void
mkentry(dp, fp)
mkentry(name, dp, fp)
char *name;
struct direct *dp;
register struct afile *fp;
{
@ -581,7 +595,7 @@ mkentry(dp, fp)
fp->len = cp - fp->fname;
if (dflag && TSTINO(fp->fnum, dumpmap) == 0)
fp->prefix = '^';
else if ((np = lookupino(fp->fnum)) != NULL && (np->e_flags & NEW))
else if ((np = lookupname(name)) != NULL && (np->e_flags & NEW))
fp->prefix = '*';
else
fp->prefix = ' ';
@ -609,6 +623,10 @@ mkentry(dp, fp)
fp->postfix = '#';
break;
case DT_WHT:
fp->postfix = '%';
break;
case DT_UNKNOWN:
case DT_DIR:
if (inodetype(dp->d_ino) == NODE)
@ -704,7 +722,7 @@ glob_readdir(dirp)
static struct dirent adirent;
while ((dp = rst_readdir(dirp)) != NULL) {
if (dp->d_ino == 0)
if (!vflag && dp->d_ino == WINO)
continue;
if (dflag || TSTINO(dp->d_ino, dumpmap))
break;
@ -713,7 +731,7 @@ glob_readdir(dirp)
return (NULL);
adirent.d_fileno = dp->d_ino;
adirent.d_namlen = dp->d_namlen;
bcopy(dp->d_name, adirent.d_name, dp->d_namlen + 1);
memmove(adirent.d_name, dp->d_name, dp->d_namlen + 1);
return (&adirent);
}
@ -728,7 +746,8 @@ glob_stat(name, stp)
register struct direct *dp;
dp = pathsearch(name);
if (dp == NULL || (!dflag && TSTINO(dp->d_ino, dumpmap) == 0))
if (dp == NULL || (!dflag && TSTINO(dp->d_ino, dumpmap) == 0) ||
(!vflag && dp->d_ino == WINO))
return (-1);
if (inodetype(dp->d_ino) == NODE)
stp->st_mode = IFDIR;

View File

@ -38,14 +38,14 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 1/7/94";
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/4/95";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/ffs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <protocols/dumprestore.h>
#include <err.h>
@ -54,6 +54,7 @@ static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 1/7/94";
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "pathnames.h"
#include "restore.h"
@ -66,7 +67,7 @@ long dumpnum = 1;
long volno = 0;
long ntrec;
char *dumpmap;
char *clrimap;
char *usedinomap;
ino_t maxino;
time_t dumptime;
time_t dumpdate;
@ -276,12 +277,12 @@ main(argc, argv)
static void
usage()
{
(void)fprintf(stderr, "usage:\t%s%s%s%s%s",
"restore tfhsvy [file ...]\n",
"\trestore xfhmsvy [file ...]\n",
"\trestore ifhmsvy\n",
"\trestore rfsvy\n",
"\trestore Rfsvy\n");
(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n",
"restore -i [-chmvy] [-b blocksize] [-f file] [-s fileno]",
"restore -r [-cvy] [-b blocksize] [-f file] [-s fileno]",
"restore -R [-cvy] [-b blocksize] [-f file] [-s fileno]",
"restore -x [-chmvy] [-b blocksize] [-f file] [-s fileno] [file ...]",
"restore -t [-chvy] [-b blocksize] [-f file] [-s fileno] [file ...]");
done(1);
}
@ -316,19 +317,20 @@ obsolete(argcp, argvp)
argv += 2, argc -= 2;
for (flags = 0; *ap; ++ap) {
switch(*ap) {
switch (*ap) {
case 'b':
case 'f':
case 's':
if (argc < 1)
usage();
if (*argv == NULL) {
warnx("option requires an argument -- %c", *ap);
usage();
}
if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
err(1, NULL);
nargv[0][0] = '-';
nargv[0][1] = *ap;
(void)strcpy(&nargv[0][2], *argv);
if (*argv != NULL)
++argv;
++argv;
++nargv;
break;
default:
@ -349,4 +351,7 @@ obsolete(argcp, argvp)
/* Copy remaining arguments. */
while (*nargv++ = *argv++);
/* Update argument count. */
*argcp = nargv - *argvp - 1;
}

View File

@ -29,10 +29,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)restore.8 8.2 (Berkeley) 12/11/93
.\" $Id$
.\" "
.Dd December 11, 1993
.\" @(#)restore.8 8.4 (Berkeley) 5/1/95
.\" $Id: restore.8,v 1.9 1997/02/22 14:33:08 peter Exp $
.\"
.Dd May 1, 1995
.Dt RESTORE 8
.Os BSD 4
.Sh NAME
@ -40,8 +40,43 @@
.Nd "restore files or file systems from backups made with dump"
.Sh SYNOPSIS
.Nm restore
.Ar key
.Op Ar name Ar ...
.Fl i
.Op Fl chmvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
.Op Fl s Ar fileno
.Nm restore
.Fl R
.Op Fl cvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
.Op Fl s Ar fileno
.Nm restore
.Fl r
.Op Fl cvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
.Op Fl s Ar fileno
.Nm restore
.Fl t
.Op Fl chvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
.Op Fl s Ar fileno
.Op file ...
.Nm restore
.Fl x
.Op Fl chmvy
.Op Fl b Ar blocksize
.Op Fl f Ar file
.Op Fl s Ar fileno
.Op file ...
.Pp
.in -\\n(iSu
(The
.Bx 4.3
option syntax is implemented for backward compatibility, but
is not documented here.)
.Sh DESCRIPTION
The
.Nm restore
@ -57,42 +92,109 @@ works across a network;
to do this see the
.Fl f
flag described below.
The actions
of
.Nm restore
are controlled by the given
.Cm key ,
which
is a string of characters containing
at most one function letter and possibly
one or more function modifiers.
Other arguments to the command are file or directory
names specifying the files that are to be restored.
Unless the
.Cm h
key is specified (see below),
.Fl h
flag is specified (see below),
the appearance of a directory name refers to
the files and (recursively) subdirectories of that directory.
.Pp
The function portion of
the key is specified by one of the following letters:
Exactly one of the following flags is required:
.Bl -tag -width Ds
.It Cm r
.It Fl i
This mode allows interactive restoration of files from a dump.
After reading in the directory information from the dump,
.Nm restore
provides a shell like interface that allows the user to move
around the directory tree selecting files to be extracted.
The available commands are given below;
for those commands that require an argument,
the default is the current directory.
.Bl -tag -width Fl
.It Ic add Op Ar arg
The current directory or specified argument is added to the list of
files to be extracted.
If a directory is specified, then it and all its descendents are
added to the extraction list
(unless the
.Fl h
flag is specified on the command line).
Files that are on the extraction list are prepended with a ``*''
when they are listed by
.Ic ls .
.It Ic \&cd Ar arg
Change the current working directory to the specified argument.
.It Ic delete Op Ar arg
The current directory or specified argument is deleted from the list of
files to be extracted.
If a directory is specified, then it and all its descendents are
deleted from the extraction list
(unless the
.Fl h
flag is specified on the command line).
The most expedient way to extract most of the files from a directory
is to add the directory to the extraction list and then delete
those files that are not needed.
.It Ic extract
All the files that are on the extraction list are extracted
from the dump.
.Nm Restore
will ask which volume the user wishes to mount.
The fastest way to extract a few files is to
start with the last volume, and work towards the first volume.
.It Ic help
List a summary of the available commands.
.It Ic \&ls Op Ar arg
List the current or specified directory.
Entries that are directories are appended with a ``/''.
Entries that have been marked for extraction are prepended with a ``*''.
If the verbose
flag is set the inode number of each entry is also listed.
.It Ic pwd
Print the full pathname of the current working directory.
.It Ic quit
Restore immediately exits,
even if the extraction list is not empty.
.It Ic setmodes
All the directories that have been added to the extraction list
have their owner, modes, and times set;
nothing is extracted from the dump.
This is useful for cleaning up after a restore has been prematurely aborted.
.It Ic verbose
The sense of the
.Fl v
flag is toggled.
When set, the verbose flag causes the
.Ic ls
command to list the inode numbers of all entries.
It also causes
.Nm restore
to print out information about each file as it is extracted.
.El
.It Fl R
.Nm Restore
requests a particular tape of a multi volume set on which to restart
a full restore
(see the
.Fl r
flag below).
This is useful if the restore has been interrupted.
.It Fl r
Restore (rebuild a file system).
The target file system should be made pristine with
.Xr newfs 8 ,
mounted and the
user
mounted and the user
.Xr cd Ns 'd
into the pristine file system
before starting the restoration of the initial level 0 backup. If the
level 0 restores successfully, the
.Cm r
key may be used to restore
.Fl r
flag may be used to restore
any necessary incremental backups on top of the level 0.
The
.Cm r
key precludes an interactive file extraction and can be
.Fl r
flag precludes an interactive file extraction and can be
detrimental to one's health if not used carefully (not to mention
the disk). An example:
.Bd -literal -offset indent
@ -119,21 +221,29 @@ and
.Xr dump 8 ,
may be used to modify file system parameters
such as size or block size.
.It Cm R
.Nm Restore
requests a particular tape of a multi volume set on which to restart
a full restore
(see the
.Cm r
key above).
This is useful if the restore has been interrupted.
.It Cm x
.It Fl t
The names of the specified files are listed if they occur
on the backup.
If no file argument is given,
then the root directory is listed,
which results in the entire content of the
backup being listed,
unless the
.Fl h
flag has been specified.
Note that the
.Fl t
flag replaces the function of the old
.Xr dumpdir 8
program.
.ne 1i
.It Fl x
The named files are read from the given media.
If a named file matches a directory whose contents
are on the backup
and the
.Cm h
key is not specified,
.Fl h
flag is not specified,
the directory is recursively extracted.
The owner, modification time,
and mode are restored (if possible).
@ -142,170 +252,81 @@ then the root directory is extracted,
which results in the entire content of the
backup being extracted,
unless the
.Cm h
key has been specified.
.It Cm t
The names of the specified files are listed if they occur
on the backup.
If no file argument is given,
then the root directory is listed,
which results in the entire content of the
backup being listed,
unless the
.Cm h
key has been specified.
Note that the
.Cm t
key replaces the function of the old
.Xr dumpdir 8
program.
.It Cm i
This mode allows interactive restoration of files from a dump.
After reading in the directory information from the dump,
.Nm restore
provides a shell like interface that allows the user to move
around the directory tree selecting files to be extracted.
The available commands are given below;
for those commands that require an argument,
the default is the current directory.
.Bl -tag -width Fl
.It Ic add Op Ar arg
The current directory or specified argument is added to the list of
files to be extracted.
If a directory is specified, then it and all its descendents are
added to the extraction list
(unless the
.Cm h
key is specified on the command line).
Files that are on the extraction list are prepended with a ``*''
when they are listed by
.Ic ls .
.It Ic \&cd Ar arg
Change the current working directory to the specified argument.
.It Ic delete Op Ar arg
The current directory or specified argument is deleted from the list of
files to be extracted.
If a directory is specified, then it and all its descendents are
deleted from the extraction list
(unless the
.Cm h
key is specified on the command line).
The most expedient way to extract most of the files from a directory
is to add the directory to the extraction list and then delete
those files that are not needed.
.It Ic extract
All the files that are on the extraction list are extracted
from the dump.
.Nm Restore
will ask which volume the user wishes to mount.
The fastest way to extract a few files is to
start with the last volume, and work towards the first volume.
.It Ic help
List a summary of the available commands.
.It Ic \&ls Op Ar arg
List the current or specified directory.
Entries that are directories are appended with a ``/''.
Entries that have been marked for extraction are prepended with a ``*''.
If the verbose key is set the inode number of each entry is also listed.
.It Ic pwd
Print the full pathname of the current working directory.
.It Ic quit
Restore immediately exits,
even if the extraction list is not empty.
.It Ic setmodes
All the directories that have been added to the extraction list
have their owner, modes, and times set;
nothing is extracted from the dump.
This is useful for cleaning up after a restore has been prematurely aborted.
.It Ic verbose
The sense of the
.Cm v
key is toggled.
When set, the verbose key causes the
.Ic ls
command to list the inode numbers of all entries.
It also causes
.Nm restore
to print out information about each file as it is extracted.
.El
.Fl h
flag has been specified.
.El
.Pp
The following characters may be used in addition to the letter
that selects the function desired.
The following additional options may be specified:
.Bl -tag -width Ds
.It Cm b
The next argument to
.Nm restore
is used as the block size of the media (in kilobytes).
.It Fl b Ar blocksize
The number of kilobytes per dump record.
If the
.Fl b
option is not specified,
.Nm restore
tries to determine the media block size dynamically.
.It Cm f
The next argument to
.It Fl c
Normally,
.Nm restore
is used as the name of the archive instead
of
.Pa /dev/rst0 .
will try to determine dynamically whether the dump was made from an
old (pre-4.4) or new format file sytem. The
.Fl c
flag disables this check, and only allows reading a dump in the old
format.
.It Fl f Ar file
Read the backup from
.Ar file ;
.Ar file
may be a special device file
like
.Pa /dev/rmt12
(a tape drive),
.Pa /dev/rsd1c
(a disk drive),
an ordinary file,
or
.Ql Fl
(the standard input).
If the name of the file is of the form
.Dq host:file ,
or
.Dq user@host:file ,
.Nm restore
reads from the named file on the remote host using
.Xr rmt 8 .
If the name of the file is
.Ql Fl ,
.Nm restore
reads from standard input.
Thus,
.Xr dump 8
and
.Nm restore
can be used in a pipeline to dump and restore a file system
with the command
.Bd -literal -offset indent
dump 0f - /usr | (cd /mnt; restore xf -)
.Ed
.Pp
.It Cm h
.Nm Restore
extracts the actual directory,
.It Fl h
Extract the actual directory,
rather than the files that it references.
This prevents hierarchical restoration of complete subtrees
from the dump.
.It Cm m
.Nm Restore
will extract by inode numbers rather than by file name.
.It Fl m
Extract by inode numbers rather than by file name.
This is useful if only a few files are being extracted,
and one wants to avoid regenerating the complete pathname
to the file.
.It Cm s
The next argument to
.Nm restore
is a number which
selects the file on a multi-file dump tape. File numbering
starts at 1.
.It Cm v
.It Fl s Ar fileno
Read from the specified
.Ar fileno
on a multi-file tape.
File numbering starts at 1.
.It Fl v
Normally
.Nm restore
does its work silently.
The
.Cm v
.Fl v
(verbose)
key causes it to type the name of each file it treats
flag causes it to type the name of each file it treats
preceded by its file type.
.It Cm y
.Nm Restore
will not ask whether it should abort the restore if it gets an error.
It will always try to skip over the bad block(s) and continue as
best it can.
.It Fl y
Do not ask the user whether to abort the restore in the event of an error.
Always try to skip over the bad block(s) and continue.
.El
.Sh DIAGNOSTICS
Complaints about bad key characters.
.Pp
Complaints if it gets a read error.
If
.Cm y
.Fl y
has been specified, or the user responds
.Ql y ,
.Nm restore
@ -315,10 +336,10 @@ If a backup was made using more than one tape volume,
.Nm restore
will notify the user when it is time to mount the next volume.
If the
.Cm x
.Fl x
or
.Cm i
key has been specified,
.Fl i
flag has been specified,
.Nm restore
will also ask which volume the user wishes to mount.
The fastest way to extract a few files is to
@ -391,7 +412,7 @@ information passed between incremental restores.
.Sh BUGS
.Nm Restore
can get confused when doing incremental restores from
dump that were made on active file systems.
dumps that were made on active file systems.
.Pp
A level zero dump must be done after a full restore.
Because restore runs in user code,

View File

@ -32,7 +32,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)restore.c 8.1 (Berkeley) 6/5/93";
static char sccsid[] = "@(#)restore.c 8.3 (Berkeley) 9/13/94";
#endif /* not lint */
#include <sys/types.h>
@ -85,6 +85,8 @@ addfile(name, ino, type)
dprintf(stdout, "%s: not on the tape\n", name);
return (descend);
}
if (ino == WINO && command == 'i' && !vflag)
return (descend);
if (!mflag) {
(void) sprintf(buf, "./%u", ino);
name = buf;
@ -124,9 +126,13 @@ deletefile(name, ino, type)
if (TSTINO(ino, dumpmap) == 0)
return (descend);
ep = lookupino(ino);
if (ep != NULL)
ep = lookupname(name);
if (ep != NULL) {
ep->e_flags &= ~NEW;
ep->e_flags |= REMOVED;
if (ep->e_type != NODE)
freeentry(ep);
}
return (descend);
}
@ -146,21 +152,38 @@ deletefile(name, ino, type)
static struct entry *removelist;
/*
* Remove invalid whiteouts from the old tree.
* Remove unneeded leaves from the old tree.
* Remove directories from the lookup chains.
*/
void
removeoldleaves()
{
register struct entry *ep;
register ino_t i;
register struct entry *ep, *nextep;
register ino_t i, mydirino;
vprintf(stdout, "Mark entries to be removed.\n");
if (ep = lookupino(WINO)) {
vprintf(stdout, "Delete whiteouts\n");
for ( ; ep != NULL; ep = nextep) {
nextep = ep->e_links;
mydirino = ep->e_parent->e_ino;
/*
* We remove all whiteouts that are in directories
* that have been removed or that have been dumped.
*/
if (TSTINO(mydirino, usedinomap) &&
!TSTINO(mydirino, dumpmap))
continue;
delwhiteout(ep);
freeentry(ep);
}
}
for (i = ROOTINO + 1; i < maxino; i++) {
ep = lookupino(i);
if (ep == NULL)
continue;
if (TSTINO(i, clrimap))
if (TSTINO(i, usedinomap))
continue;
for ( ; ep != NULL; ep = ep->e_links) {
dprintf(stdout, "%s: REMOVE\n", myname(ep));
@ -745,6 +768,15 @@ createlinks()
register ino_t i;
char name[BUFSIZ];
if (ep = lookupino(WINO)) {
vprintf(stdout, "Add whiteouts\n");
for ( ; ep != NULL; ep = ep->e_links) {
if ((ep->e_flags & NEW) == 0)
continue;
(void) addwhiteout(myname(ep));
ep->e_flags &= ~NEW;
}
}
vprintf(stdout, "Add links\n");
for (i = ROOTINO; i < maxino; i++) {
ep = lookupino(i);
@ -776,7 +808,7 @@ checkrestore()
register ino_t i;
vprintf(stdout, "Check the symbol table.\n");
for (i = ROOTINO; i < maxino; i++) {
for (i = WINO; i < maxino; i++) {
for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
ep->e_flags &= ~KEEP;
if (ep->e_type == NODE)

View File

@ -32,7 +32,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)symtab.c 8.1 (Berkeley) 6/5/93";
static char sccsid[] = "@(#)symtab.c 8.3 (Berkeley) 4/28/95";
#endif /* not lint */
/*
@ -83,7 +83,7 @@ lookupino(inum)
{
register struct entry *ep;
if (inum < ROOTINO || inum >= maxino)
if (inum < WINO || inum >= maxino)
return (NULL);
for (ep = entry[inum % entrytblsize]; ep != NULL; ep = ep->e_next)
if (ep->e_ino == inum)
@ -101,7 +101,7 @@ addino(inum, np)
{
struct entry **epp;
if (inum < ROOTINO || inum >= maxino)
if (inum < WINO || inum >= maxino)
panic("addino: out of range %d\n", inum);
epp = &entry[inum % entrytblsize];
np->e_ino = inum;
@ -123,7 +123,7 @@ deleteino(inum)
register struct entry *next;
struct entry **prev;
if (inum < ROOTINO || inum >= maxino)
if (inum < WINO || inum >= maxino)
panic("deleteino: out of range %d\n", inum);
prev = &entry[inum % entrytblsize];
for (next = *prev; next != NULL; next = next->e_next) {
@ -177,7 +177,7 @@ lookupparent(name)
struct entry *ep;
char *tailindex;
tailindex = rindex(name, '/');
tailindex = strrchr(name, '/');
if (tailindex == NULL)
return (NULL);
*tailindex = '\0';
@ -202,7 +202,7 @@ myname(ep)
for (cp = &namebuf[MAXPATHLEN - 2]; cp > &namebuf[ep->e_namlen]; ) {
cp -= ep->e_namlen;
bcopy(ep->e_name, cp, (long)ep->e_namlen);
memmove(cp, ep->e_name, (long)ep->e_namlen);
if (ep == lookupino(ROOTINO))
return (cp);
*(--cp) = '/';
@ -232,7 +232,7 @@ addentry(name, inum, type)
if (freelist != NULL) {
np = freelist;
freelist = np->e_next;
bzero((char *)np, (long)sizeof(struct entry));
memset(np, 0, (long)sizeof(struct entry));
} else {
np = (struct entry *)calloc(1, sizeof(struct entry));
if (np == NULL)
@ -249,7 +249,7 @@ addentry(name, inum, type)
addino(ROOTINO, np);
return (np);
}
np->e_name = savename(rindex(name, '/') + 1);
np->e_name = savename(strrchr(name, '/') + 1);
np->e_namlen = strlen(np->e_name);
np->e_parent = ep;
np->e_sibling = ep->e_entries;
@ -333,7 +333,7 @@ moveentry(ep, newname)
ep->e_sibling = np->e_entries;
np->e_entries = ep;
}
cp = rindex(newname, '/') + 1;
cp = strrchr(newname, '/') + 1;
freename(ep->e_name);
ep->e_name = savename(cp);
ep->e_namlen = strlen(cp);
@ -473,7 +473,7 @@ dumpsymtable(filename, checkpt)
* Assign indicies to each entry
* Write out the string entries
*/
for (i = ROOTINO; i < maxino; i++) {
for (i = WINO; i <= maxino; i++) {
for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
ep->e_index = mynum++;
(void) fwrite(ep->e_name, sizeof(char),
@ -485,10 +485,9 @@ dumpsymtable(filename, checkpt)
*/
tep = &temp;
stroff = 0;
for (i = ROOTINO; i < maxino; i++) {
for (i = WINO; i <= maxino; i++) {
for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
bcopy((char *)ep, (char *)tep,
(long)sizeof(struct entry));
memmove(tep, ep, (long)sizeof(struct entry));
tep->e_name = (char *)stroff;
stroff += allocsize(ep->e_namlen);
tep->e_parent = (struct entry *)ep->e_parent->e_index;

View File

@ -37,7 +37,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)tape.c 8.3 (Berkeley) 4/1/94";
static char sccsid[] = "@(#)tape.c 8.9 (Berkeley) 5/1/95";
#endif /* not lint */
#include <sys/param.h>
@ -119,9 +119,9 @@ setinput(source)
terminal = stdin;
#ifdef RRESTORE
if (index(source, ':')) {
if (strchr(source, ':')) {
host = source;
source = index(host, ':');
source = strchr(host, ':');
*source++ = '\0';
if (rmthost(host) == 0)
done(1);
@ -254,8 +254,8 @@ setup()
dprintf(stdout, "maxino = %d\n", maxino);
map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
if (map == NULL)
panic("no memory for file removal list\n");
clrimap = map;
panic("no memory for active inode map\n");
usedinomap = map;
curfile.action = USING;
getfile(xtrmap, xtrmapskip);
if (spcl.c_type != TS_BITS) {
@ -268,6 +268,13 @@ setup()
dumpmap = map;
curfile.action = USING;
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
* extracted.
*/
if (oldinofmt == 0)
SETINO(WINO, dumpmap);
}
/*
@ -504,17 +511,19 @@ int
extractfile(name)
char *name;
{
int mode;
int flags;
mode_t mode;
struct timeval timep[2];
struct entry *ep;
curfile.name = name;
curfile.action = USING;
timep[0].tv_sec = curfile.dip->di_atime.tv_sec;
timep[0].tv_usec = curfile.dip->di_atime.tv_nsec / 1000;
timep[1].tv_sec = curfile.dip->di_mtime.tv_sec;
timep[1].tv_usec = curfile.dip->di_mtime.tv_nsec / 1000;
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;
timep[1].tv_usec = curfile.dip->di_mtimensec / 1000;
mode = curfile.dip->di_mode;
flags = curfile.dip->di_flags;
switch (mode & IFMT) {
default:
@ -550,14 +559,20 @@ extractfile(name)
return (linkit(lnkbuf, name, SYMLINK));
case IFIFO:
vprintf(stdout, "extract fifo %s\n", name);
if (Nflag) {
skipfile();
return (GOOD);
}
if (mkfifo(name, mode) < 0) {
fprintf(stderr, "%s: cannot create FIFO: %s\n",
name, strerror(errno));
fprintf(stderr, "%s: cannot create fifo: %s\n",
name, strerror(errno));
skipfile();
return (FAIL);
}
(void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
(void) chmod(name, mode);
(void) chflags(name, flags);
skipfile();
utimes(name, timep);
return (GOOD);
@ -577,6 +592,7 @@ extractfile(name)
}
(void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
(void) chmod(name, mode);
(void) chflags(name, flags);
skipfile();
utimes(name, timep);
return (GOOD);
@ -596,6 +612,7 @@ extractfile(name)
}
(void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid);
(void) fchmod(ofile, mode);
(void) fchflags(ofile, flags);
getfile(xtrfile, xtrskip);
(void) close(ofile);
utimes(name, timep);
@ -639,7 +656,7 @@ getfile(fill, skip)
{
register int i;
int curblk = 0;
long size = spcl.c_dinode.di_size;
quad_t size = spcl.c_dinode.di_size;
static char clearedbuf[MAXBSIZE];
char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
char junk[TP_BSIZE];
@ -656,20 +673,19 @@ getfile(fill, skip)
if (spcl.c_addr[i]) {
readtape(&buf[curblk++][0]);
if (curblk == fssize / TP_BSIZE) {
(*fill)((char *)buf, size > TP_BSIZE ?
(long) (fssize) :
(curblk - 1) * TP_BSIZE + size);
(*fill)((char *)buf, (long)(size > TP_BSIZE ?
fssize : (curblk - 1) * TP_BSIZE + size));
curblk = 0;
}
} else {
if (curblk > 0) {
(*fill)((char *)buf, size > TP_BSIZE ?
(long) (curblk * TP_BSIZE) :
(curblk - 1) * TP_BSIZE + size);
(*fill)((char *)buf, (long)(size > TP_BSIZE ?
curblk * TP_BSIZE :
(curblk - 1) * TP_BSIZE + size));
curblk = 0;
}
(*skip)(clearedbuf, size > TP_BSIZE ?
(long) TP_BSIZE : size);
(*skip)(clearedbuf, (long)(size > TP_BSIZE ?
TP_BSIZE : size));
}
if ((size -= TP_BSIZE) <= 0) {
for (i++; i < spcl.c_count; i++)
@ -686,7 +702,7 @@ getfile(fill, skip)
curfile.name, blksread);
}
if (curblk > 0)
(*fill)((char *)buf, (curblk * TP_BSIZE) + size);
(*fill)((char *)buf, (long)((curblk * TP_BSIZE) + size));
findinode(&spcl);
gettingfile = 0;
}
@ -770,7 +786,7 @@ xtrmap(buf, size)
long size;
{
bcopy(buf, map, size);
memmove(map, buf, size);
map += size;
}
@ -813,7 +829,7 @@ readtape(buf)
int cnt, seek_failed;
if (blkcnt < numtrec) {
bcopy(&tapebuf[(blkcnt++ * TP_BSIZE)], buf, (long)TP_BSIZE);
memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE);
blksread++;
tpblksread++;
return;
@ -885,7 +901,7 @@ readtape(buf)
if (!yflag && !reply("continue"))
done(1);
i = ntrec * TP_BSIZE;
bzero(tapebuf, i);
memset(tapebuf, 0, i);
#ifdef RRESTORE
if (host)
seek_failed = (rmtseek(i, 1) < 0);
@ -916,10 +932,10 @@ readtape(buf)
panic("partial block read: %d should be %d\n",
rd, ntrec * TP_BSIZE);
terminateinput();
bcopy((char *)&endoftapemark, &tapebuf[rd], (long)TP_BSIZE);
memmove(&tapebuf[rd], &endoftapemark, (long)TP_BSIZE);
}
blkcnt = 0;
bcopy(&tapebuf[(blkcnt++ * TP_BSIZE)], buf, (long)TP_BSIZE);
memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE);
blksread++;
tpblksread++;
}
@ -1030,7 +1046,7 @@ gethead(buf)
goto good;
}
readtape((char *)(&u_ospcl.s_ospcl));
bzero((char *)buf, (long)TP_BSIZE);
memset(buf, 0, (long)TP_BSIZE);
buf->c_type = u_ospcl.s_ospcl.c_type;
buf->c_date = u_ospcl.s_ospcl.c_date;
buf->c_ddate = u_ospcl.s_ospcl.c_ddate;
@ -1045,11 +1061,11 @@ gethead(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;
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;
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;
buf->c_count = u_ospcl.s_ospcl.c_count;
bcopy(u_ospcl.s_ospcl.c_addr, buf->c_addr, (long)256);
memmove(buf->c_addr, u_ospcl.s_ospcl.c_addr, (long)256);
if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC ||
checksum((int *)(&u_ospcl.s_ospcl)) == FAIL)
return(FAIL);
@ -1140,10 +1156,10 @@ accthdr(header)
goto newcalc;
switch (prevtype) {
case TS_BITS:
fprintf(stderr, "Dump mask header");
fprintf(stderr, "Dumped inodes map header");
break;
case TS_CLRI:
fprintf(stderr, "Remove mask header");
fprintf(stderr, "Used inodes map header");
break;
case TS_INODE:
fprintf(stderr, "File header, ino %d", previno);

View File

@ -32,7 +32,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)utilities.c 8.2 (Berkeley) 3/25/94";
static char sccsid[] = "@(#)utilities.c 8.5 (Berkeley) 4/28/95";
#endif /* not lint */
#include <sys/param.h>
@ -61,7 +61,7 @@ pathcheck(name)
struct entry *ep;
char *start;
start = index(name, '/');
start = strchr(name, '/');
if (start == 0)
return;
for (cp = start; *cp != '\0'; cp++) {
@ -229,6 +229,45 @@ linkit(existing, new, type)
return (GOOD);
}
/*
* Create a whiteout.
*/
int
addwhiteout(name)
char *name;
{
if (!Nflag && mknod(name, S_IFWHT, 0) < 0) {
fprintf(stderr, "warning: cannot create whiteout %s: %s\n",
name, strerror(errno));
return (FAIL);
}
vprintf(stdout, "Create whiteout %s\n", name);
return (GOOD);
}
/*
* Delete a whiteout.
*/
void
delwhiteout(ep)
register struct entry *ep;
{
char *name;
if (ep->e_type != LEAF)
badentry(ep, "delwhiteout: not a leaf");
ep->e_flags |= REMOVED;
ep->e_flags &= ~TMPNAME;
name = myname(ep);
if (!Nflag && undelete(name) < 0) {
fprintf(stderr, "warning: cannot delete whiteout %s: %s\n",
name, strerror(errno));
return;
}
vprintf(stdout, "Delete whiteout %s\n", name);
}
/*
* find lowest number file (above "start") that needs to be extracted
*/