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:
parent
08966bd5fd
commit
d87d79aefe
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=23685
@ -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);
|
||||
@ -369,10 +368,11 @@ putdir(buf, size)
|
||||
if (oldinofmt && dp->d_ino != 0) {
|
||||
# if BYTE_ORDER == BIG_ENDIAN
|
||||
if (Bcvt)
|
||||
dp->d_namlen = dp->d_type;
|
||||
# else
|
||||
if (!Bcvt)
|
||||
#endif
|
||||
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);
|
||||
|
@ -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,18 +535,29 @@ 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++);
|
||||
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) {
|
||||
fprintf(stderr, "\n");
|
||||
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
@ -320,14 +321,15 @@ obsolete(argcp, argvp)
|
||||
case 'b':
|
||||
case 'f':
|
||||
case 's':
|
||||
if (argc < 1)
|
||||
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;
|
||||
++nargv;
|
||||
break;
|
||||
@ -349,4 +351,7 @@ obsolete(argcp, argvp)
|
||||
|
||||
/* Copy remaining arguments. */
|
||||
while (*nargv++ = *argv++);
|
||||
|
||||
/* Update argument count. */
|
||||
*argcp = nargv - *argvp - 1;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
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);
|
||||
|
@ -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
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user