new version from CSRG, via BSDI, with fixes

This commit is contained in:
cgd 1993-12-22 10:31:38 +00:00
parent 6b7fd8ec52
commit 3e75cabcd4
12 changed files with 811 additions and 673 deletions

View File

@ -1,24 +1,16 @@
# from: @(#)Makefile 5.10 (Berkeley) 5/11/90
# $Id: Makefile,v 1.9 1993/11/14 15:36:05 cgd Exp $
# from: @(#)Makefile 5.13 (Berkeley) 3/16/92
# $Id: Makefile,v 1.10 1993/12/22 10:31:38 cgd Exp $
PROG= restore
SRCS= main.c interactive.c restore.c dirs.c symtab.c tape.c utilities.c
ROBJS= main.o interactive.o restore.o dirs.o symtab.o rtape.o utilities.o \
dumprmt.o
MAN8= restore.0 rrestore.0
LINKS= ${BINDIR}/restore ${BINDIR}/rrestore
CFLAGS+=-DRRESTORE
SRCS= main.c interactive.c restore.c dirs.c symtab.c tape.c utilities.c \
dumprmt.c
BINOWN= root
BINGRP= tty
BINMODE=6555
MAN8= restore.0
MLINKS+=restore.8 rrestore.8
.PATH: ${.CURDIR}/../dump
CLEANFILES+=dumprmt.o rtape.o rrestore
all: rrestore
rtape.o: tape.c ${LIBC}
${CC} ${CFLAGS} -c -DRRESTORE ${.CURDIR}/tape.c -o ${.TARGET}
afterinstall:
install ${COPY} ${STRIP} -o root -g ${BINGRP} -m 4755 rrestore \
${DESTDIR}${BINDIR}
.include <bsd.prog.mk>
rrestore: ${LIBCRT0} ${ROBJS} ${LIBC} ${DPADD}
${CC} ${LDFLAGS} ${LDSTATIC} -o ${.TARGET} ${ROBJS} ${LDADD}

View File

@ -1 +1 @@
revision 1.3 intentionally removed
revision 1.4 intentionally removed

102
sbin/restore/extern.h Normal file
View File

@ -0,0 +1,102 @@
/*-
* Copyright (c) 1992 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)extern.h 5.2 (Berkeley) 12/2/92
* $Id: extern.h,v 1.1 1993/12/22 10:31:45 cgd Exp $
*/
struct entry *addentry __P((char *, ino_t, int));
long addfile __P((char *, ino_t, int));
void badentry __P((struct entry *, char *));
void canon __P((char *, char *));
void checkrestore __P((void));
void closemt __P((void));
void createfiles __P((void));
void createleaves __P((char *));
void createlinks __P((void));
long deletefile __P((char *, ino_t, int));
void deleteino __P((ino_t));
ino_t dirlookup __P((char *));
void done __P((int));
void dumpsymtable __P((char *, long));
void err __P((const char *, ...));
void extractdirs __P((int));
int extractfile __P((char *));
void findunreflinks __P((void));
char *flagvalues __P((struct entry *));
void freeentry __P((struct entry *));
void freename __P((char *));
int genliteraldir __P((char *, ino_t));
char *gentempname __P((struct entry *));
void getfile __P((void (*)(char *, long), void (*)(char *, long)));
void getvol __P((long));
void initsymtable __P((char *));
int inodetype __P((ino_t));
int linkit __P((char *, char *, int));
struct entry *lookupino __P((ino_t));
struct entry *lookupname __P((char *));
long listfile __P((char *, ino_t, int));
ino_t lowerbnd __P((ino_t));
void mktempname __P((struct entry *));
void moveentry __P((struct entry *, char *));
void msg __P((const char *, ...));
char *myname __P((struct entry *));
void newnode __P((struct entry *));
void newtapebuf __P((long));
long nodeupdates __P((char *, ino_t, int));
void onintr __P((int));
void panic __P((const char *, ...));
void pathcheck __P((char *));
struct direct *pathsearch __P((const char *));
void printdumpinfo __P((void));
void removeleaf __P((struct entry *));
void removenode __P((struct entry *));
void removeoldleaves __P((void));
void removeoldnodes __P((void));
void renameit __P((char *, char *));
int reply __P((char *));
RST_DIR *rst_opendir __P((char *));
struct direct *rst_readdir __P((RST_DIR *));
void rst_closedir __P((RST_DIR *dirp));
void runcmdshell __P((void));
char *savename __P((char *));
void setdirmodes __P((int));
void setinput __P((char *));
void setup __P((void));
void skipdirs __P((void));
void skipfile __P((void));
void skipmaps __P((void));
void swabst __P((u_char *, u_char *));
void treescan __P((char *, ino_t, long (*)(char *, ino_t, int)));
ino_t upperbnd __P((ino_t));
long verifyfile __P((char *, ino_t, int));
void xtrnull __P((char *, long));

View File

@ -32,20 +32,34 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)interactive.c 5.9 (Berkeley) 6/1/90";*/
static char rcsid[] = "$Id: interactive.c,v 1.2 1993/08/01 18:25:21 mycroft Exp $";
/* from: static char sccsid[] = "@(#)interactive.c 5.18 (Berkeley) 12/2/92"; */
static char *rcsid = "$Id: interactive.c,v 1.3 1993/12/22 10:31:47 cgd Exp $";
#endif /* not lint */
#include "restore.h"
#include <protocols/dumprestore.h>
#include <setjmp.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <ufs/fs.h>
#include <ufs/dinode.h>
#include <ufs/dir.h>
#include <protocols/dumprestore.h>
#include <setjmp.h>
#include <glob.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "restore.h"
#include "extern.h"
#define round(a, b) (((a) + (b) - 1) / (b) * (b))
/*
* Things to handle interruptions.
*/
static int runshell;
static jmp_buf reset;
static char *nextarg = NULL;
@ -55,41 +69,61 @@ static char *nextarg = NULL;
struct afile {
ino_t fnum; /* inode number of file */
char *fname; /* file name */
short fflags; /* extraction flags, if any */
char ftype; /* file type, e.g. LEAF or NODE */
short len; /* name length */
char prefix; /* prefix character */
char postfix; /* postfix character */
};
struct arglist {
struct afile *head; /* start of argument list */
struct afile *last; /* end of argument list */
struct afile *base; /* current list arena */
int nent; /* maximum size of list */
char *cmd; /* the current command */
int freeglob; /* glob structure needs to be freed */
int argcnt; /* next globbed argument to return */
glob_t glob; /* globbing information */
char *cmd; /* the current command */
};
extern int fcmp();
extern char *fmtentry();
char *copynext();
static char *copynext __P((char *, char *));
static int fcmp __P((const void *, const void *));
static char *fmtentry __P((struct afile *));
static void formatf __P((struct afile *, int));
static void getcmd __P((char *, char *, char *, 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 printlist __P((char *, char *));
/*
* Read and execute commands from the terminal.
*/
void
runcmdshell()
{
register struct entry *np;
ino_t ino;
static struct arglist alist = { 0, 0, 0, 0, 0 };
struct arglist arglist;
char curdir[MAXPATHLEN];
char name[MAXPATHLEN];
char cmd[BUFSIZ];
arglist.freeglob = 0;
arglist.argcnt = 0;
arglist.glob.gl_flags = GLOB_ALTDIRFUNC;
arglist.glob.gl_opendir = (void *)rst_opendir;
arglist.glob.gl_readdir = (void *)glob_readdir;
arglist.glob.gl_closedir = (void *)rst_closedir;
arglist.glob.gl_lstat = glob_stat;
arglist.glob.gl_stat = glob_stat;
canon("/", curdir);
loop:
if (setjmp(reset) != 0) {
for (; alist.head < alist.last; alist.head++)
freename(alist.head->fname);
if (arglist.freeglob != 0) {
arglist.freeglob = 0;
arglist.argcnt = 0;
globfree(&arglist.glob);
}
nextarg = NULL;
volno = 0;
}
getcmd(curdir, cmd, name, &alist);
runshell = 1;
getcmd(curdir, cmd, name, &arglist);
switch (cmd[0]) {
/*
* Add elements to the extraction list.
@ -126,7 +160,7 @@ loop:
if (strncmp(cmd, "delete", strlen(cmd)) != 0)
goto bad;
np = lookupname(name);
if (np == NIL || (np->e_flags & NEW) == 0) {
if (np == NULL || (np->e_flags & NEW) == 0) {
fprintf(stderr, "%s: not on extraction list\n", name);
break;
}
@ -140,7 +174,7 @@ loop:
goto bad;
createfiles();
createlinks();
setdirmodes();
setdirmodes(0);
if (dflag)
checkrestore();
volno = 0;
@ -177,10 +211,7 @@ loop:
case 'l':
if (strncmp(cmd, "ls", strlen(cmd)) != 0)
goto bad;
ino = dirlookup(name);
if (ino == 0)
break;
printlist(name, ino, curdir);
printlist(name, curdir);
break;
/*
* Print current directory.
@ -224,7 +255,7 @@ loop:
case 's':
if (strncmp(cmd, "setmodes", strlen(cmd)) != 0)
goto bad;
setdirmodes();
setdirmodes(FORCE);
break;
/*
* Print out dump header information.
@ -270,6 +301,7 @@ loop:
* "curdir" is prepended to it. Finally "canon" is called to
* eliminate any embedded ".." components.
*/
static void
getcmd(curdir, cmd, name, ap)
char *curdir, *cmd, *name;
struct arglist *ap;
@ -282,12 +314,8 @@ getcmd(curdir, cmd, name, ap)
/*
* Check to see if still processing arguments.
*/
if (ap->head != ap->last) {
strcpy(name, ap->head->fname);
freename(ap->head->fname);
ap->head++;
return;
}
if (ap->argcnt > 0)
goto retnext;
if (nextarg != NULL)
goto getnext;
/*
@ -328,7 +356,7 @@ getnext:
else
nextarg = cp;
/*
* If it an absolute pathname, canonicalize it and return it.
* If it is an absolute pathname, canonicalize it and return it.
*/
if (rawname[0] == '/') {
canon(rawname, name);
@ -342,17 +370,26 @@ getnext:
(void) strcat(output, rawname);
canon(output, name);
}
expandarg(name, ap);
strcpy(name, ap->head->fname);
freename(ap->head->fname);
ap->head++;
if (glob(name, GLOB_ALTDIRFUNC, NULL, &ap->glob) < 0)
fprintf(stderr, "%s: out of memory\n", ap->cmd);
if (ap->glob.gl_pathc == 0)
return;
ap->freeglob = 1;
ap->argcnt = ap->glob.gl_pathc;
retnext:
strcpy(name, ap->glob.gl_pathv[ap->glob.gl_pathc - ap->argcnt]);
if (--ap->argcnt == 0) {
ap->freeglob = 0;
globfree(&ap->glob);
}
# undef rawname
}
/*
* Strip off the next token of the input.
*/
char *
static char *
copynext(input, output)
char *input, *output;
{
@ -402,11 +439,11 @@ copynext(input, output)
* Canonicalize file names to always start with ``./'' and
* remove any imbedded "." and ".." components.
*/
void
canon(rawname, canonname)
char *rawname, *canonname;
{
register char *cp, *np;
int len;
if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0)
(void) strcpy(canonname, "");
@ -449,412 +486,278 @@ canon(rawname, canonname)
}
}
/*
* globals (file name generation)
*
* "*" in params matches r.e ".*"
* "?" in params matches r.e. "."
* "[...]" in params matches character class
* "[...a-z...]" in params matches a through z.
*/
expandarg(arg, ap)
char *arg;
register struct arglist *ap;
{
static struct afile single;
struct entry *ep;
int size;
ap->head = ap->last = (struct afile *)0;
size = expand(arg, 0, ap);
if (size == 0) {
ep = lookupname(arg);
single.fnum = ep ? ep->e_ino : 0;
single.fname = savename(arg);
ap->head = &single;
ap->last = ap->head + 1;
return;
}
qsort((char *)ap->head, ap->last - ap->head, sizeof *ap->head, fcmp);
}
/*
* Expand a file name
*/
expand(as, rflg, ap)
char *as;
int rflg;
register struct arglist *ap;
{
int count, size;
char dir = 0;
char *rescan = 0;
DIR *dirp;
register char *s, *cs;
int sindex, rindex, lindex;
struct direct *dp;
register char slash;
register char *rs;
register char c;
/*
* check for meta chars
*/
s = cs = as;
slash = 0;
while (*cs != '*' && *cs != '?' && *cs != '[') {
if (*cs++ == 0) {
if (rflg && slash)
break;
else
return (0) ;
} else if (*cs == '/') {
slash++;
}
}
for (;;) {
if (cs == s) {
s = "";
break;
} else if (*--cs == '/') {
*cs = 0;
if (s == cs)
s = "/";
break;
}
}
if ((dirp = rst_opendir(s)) != NULL)
dir++;
count = 0;
if (*cs == 0)
*cs++ = 0200;
if (dir) {
/*
* check for rescan
*/
rs = cs;
do {
if (*rs == '/') {
rescan = rs;
*rs = 0;
}
} while (*rs++);
sindex = ap->last - ap->head;
while ((dp = rst_readdir(dirp)) != NULL && dp->d_ino != 0) {
if (!dflag && BIT(dp->d_ino, dumpmap) == 0)
continue;
if ((*dp->d_name == '.' && *cs != '.'))
continue;
if (gmatch(dp->d_name, cs)) {
if (addg(dp, s, rescan, ap) < 0)
return (-1);
count++;
}
}
if (rescan) {
rindex = sindex;
lindex = ap->last - ap->head;
if (count) {
count = 0;
while (rindex < lindex) {
size = expand(ap->head[rindex].fname,
1, ap);
if (size < 0)
return (size);
count += size;
rindex++;
}
}
bcopy((char *)&ap->head[lindex],
(char *)&ap->head[sindex],
(ap->last - &ap->head[rindex]) * sizeof *ap->head);
ap->last -= lindex - sindex;
*rescan = '/';
}
}
s = as;
while (c = *s)
*s++ = (c&0177 ? c : '/');
return (count);
}
/*
* Check for a name match
*/
gmatch(s, p)
register char *s, *p;
{
register int scc;
char c;
char ok;
int lc;
if (scc = *s++)
if ((scc &= 0177) == 0)
scc = 0200;
switch (c = *p++) {
case '[':
ok = 0;
lc = 077777;
while (c = *p++) {
if (c == ']') {
return (ok ? gmatch(s, p) : 0);
} else if (c == '-') {
if (lc <= scc && scc <= (*p++))
ok++ ;
} else {
if (scc == (lc = (c&0177)))
ok++ ;
}
}
return (0);
default:
if ((c&0177) != scc)
return (0) ;
/* falls through */
case '?':
return (scc ? gmatch(s, p) : 0);
case '*':
if (*p == 0)
return (1) ;
s--;
while (*s) {
if (gmatch(s++, p))
return (1);
}
return (0);
case 0:
return (scc == 0);
}
}
/*
* Construct a matched name.
*/
addg(dp, as1, as3, ap)
struct direct *dp;
char *as1, *as3;
struct arglist *ap;
{
register char *s1, *s2;
register int c;
char buf[BUFSIZ];
s2 = buf;
s1 = as1;
while (c = *s1++) {
if ((c &= 0177) == 0) {
*s2++ = '/';
break;
}
*s2++ = c;
}
s1 = dp->d_name;
while (*s2 = *s1++)
s2++;
if (s1 = as3) {
*s2++ = '/';
while (*s2++ = *++s1)
/* void */;
}
if (mkentry(buf, dp->d_ino, ap) == FAIL)
return (-1);
}
/*
* Do an "ls" style listing of a directory
*/
printlist(name, ino, basename)
static void
printlist(name, basename)
char *name;
ino_t ino;
char *basename;
{
register struct afile *fp;
register struct afile *fp, *list, *listp;
register struct direct *dp;
static struct arglist alist = { 0, 0, 0, 0, "ls" };
struct afile single;
DIR *dirp;
RST_DIR *dirp;
int entries, len;
dp = pathsearch(name);
if (dp == NULL || (!dflag && TSTINO(dp->d_ino, dumpmap) == 0))
return;
if ((dirp = rst_opendir(name)) == NULL) {
single.fnum = ino;
single.fname = savename(name + strlen(basename) + 1);
alist.head = &single;
alist.last = alist.head + 1;
entries = 1;
list = &single;
mkentry(dp, list);
len = strlen(basename) + 1;
if (strlen(name) - len > single.len) {
freename(single.fname);
single.fname = savename(&name[len]);
single.len = strlen(single.fname);
}
} else {
alist.head = (struct afile *)0;
entries = 0;
while (dp = rst_readdir(dirp))
entries++;
rst_closedir(dirp);
list = (struct afile *)malloc(entries * sizeof(struct afile));
if (list == NULL) {
fprintf(stderr, "ls: out of memory\n");
return;
}
if ((dirp = rst_opendir(name)) == NULL)
panic("directory reopen failed\n");
fprintf(stderr, "%s:\n", name);
entries = 0;
listp = list;
while (dp = rst_readdir(dirp)) {
if (dp == NULL || dp->d_ino == 0)
break;
if (!dflag && BIT(dp->d_ino, dumpmap) == 0)
if (!dflag && TSTINO(dp->d_ino, dumpmap) == 0)
continue;
if (vflag == 0 &&
(strcmp(dp->d_name, ".") == 0 ||
strcmp(dp->d_name, "..") == 0))
continue;
if (!mkentry(dp->d_name, dp->d_ino, &alist))
return;
mkentry(dp, listp++);
entries++;
}
rst_closedir(dirp);
if (entries == 0) {
fprintf(stderr, "\n");
free(list);
return;
}
qsort((char *)list, entries, sizeof(struct afile), fcmp);
}
if (alist.head != 0) {
qsort((char *)alist.head, alist.last - alist.head,
sizeof *alist.head, fcmp);
formatf(&alist);
for (fp = alist.head; fp < alist.last; fp++)
formatf(list, entries);
if (dirp != NULL) {
for (fp = listp - 1; fp >= list; fp--)
freename(fp->fname);
}
if (dirp != NULL)
fprintf(stderr, "\n");
free(list);
}
}
/*
* Read the contents of a directory.
*/
mkentry(name, ino, ap)
char *name;
ino_t ino;
register struct arglist *ap;
{
static void
mkentry(dp, fp)
struct direct *dp;
register struct afile *fp;
{
char *cp;
struct entry *np;
int type;
if (ap->base == NULL) {
ap->nent = 20;
ap->base = (struct afile *)calloc((unsigned)ap->nent,
sizeof (struct afile));
if (ap->base == NULL) {
fprintf(stderr, "%s: out of memory\n", ap->cmd);
return (FAIL);
}
fp->fnum = dp->d_ino;
fp->fname = savename(dp->d_name);
for (cp = fp->fname; *cp; cp++)
if (!vflag && (*cp < ' ' || *cp >= 0177))
*cp = '?';
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))
fp->prefix = '*';
else
fp->prefix = ' ';
#ifndef BSD44
type = (np && (np->e_type == NODE)) ? DT_DIR : DT_REG;
#else
type = dp->d_type;
#endif
switch(type) {
default:
fprintf(stderr, "Warning: undefined file type %d\n", type);
/* fall through */
case DT_REG:
fp->postfix = ' ';
break;
case DT_LNK:
fp->postfix = '@';
break;
case DT_FIFO:
case DT_SOCK:
fp->postfix = '=';
break;
case DT_CHR:
case DT_BLK:
fp->postfix = '#';
break;
case DT_UNKNOWN:
case DT_DIR:
if (inodetype(dp->d_ino) == NODE)
fp->postfix = '/';
else
fp->postfix = ' ';
break;
}
if (ap->head == 0)
ap->head = ap->last = ap->base;
fp = ap->last;
fp->fnum = ino;
fp->fname = savename(name);
fp++;
if (fp == ap->head + ap->nent) {
ap->base = (struct afile *)realloc((char *)ap->base,
(unsigned)(2 * ap->nent * sizeof (struct afile)));
if (ap->base == 0) {
fprintf(stderr, "%s: out of memory\n", ap->cmd);
return (FAIL);
}
ap->head = ap->base;
fp = ap->head + ap->nent;
ap->nent *= 2;
}
ap->last = fp;
return (GOOD);
return;
}
/*
* Print out a pretty listing of a directory
*/
formatf(ap)
register struct arglist *ap;
static void
formatf(list, nentry)
register struct afile *list;
int nentry;
{
register struct afile *fp;
struct entry *np;
int width = 0, w, nentry = ap->last - ap->head;
int i, j, len, columns, lines;
char *cp;
register struct afile *fp, *endlist;
int width, bigino, haveprefix, havepostfix;
int i, j, w, precision, columns, lines;
if (ap->head == ap->last)
return;
for (fp = ap->head; fp < ap->last; fp++) {
fp->ftype = inodetype(fp->fnum);
np = lookupino(fp->fnum);
if (np != NIL)
fp->fflags = np->e_flags;
else
fp->fflags = 0;
len = strlen(fmtentry(fp));
if (len > width)
width = len;
width = 0;
haveprefix = 0;
havepostfix = 0;
bigino = ROOTINO;
endlist = &list[nentry];
for (fp = &list[0]; fp < endlist; fp++) {
if (bigino < fp->fnum)
bigino = fp->fnum;
if (width < fp->len)
width = fp->len;
if (fp->prefix != ' ')
haveprefix = 1;
if (fp->postfix != ' ')
havepostfix = 1;
}
width += 2;
columns = 80 / width;
if (haveprefix)
width++;
if (havepostfix)
width++;
if (vflag) {
for (precision = 0, i = bigino; i > 0; i /= 10)
precision++;
width += precision + 1;
}
width++;
columns = 81 / width;
if (columns == 0)
columns = 1;
lines = (nentry + columns - 1) / columns;
for (i = 0; i < lines; i++) {
for (j = 0; j < columns; j++) {
fp = ap->head + j * lines + i;
cp = fmtentry(fp);
fprintf(stderr, "%s", cp);
if (fp + lines >= ap->last) {
fp = &list[j * lines + i];
if (vflag) {
fprintf(stderr, "%*d ", precision, fp->fnum);
fp->len += precision + 1;
}
if (haveprefix) {
putc(fp->prefix, stderr);
fp->len++;
}
fprintf(stderr, "%s", fp->fname);
if (havepostfix) {
putc(fp->postfix, stderr);
fp->len++;
}
if (fp + lines >= endlist) {
fprintf(stderr, "\n");
break;
}
w = strlen(cp);
while (w < width) {
w++;
fprintf(stderr, " ");
}
for (w = fp->len; w < width; w++)
putc(' ', stderr);
}
}
}
/*
* Comparison routine for qsort.
* Skip over directory entries that are not on the tape
*
* First have to get definition of a dirent.
*/
fcmp(f1, f2)
register struct afile *f1, *f2;
{
#undef DIRBLKSIZ
#include <dirent.h>
#undef d_ino
return (strcmp(f1->fname, f2->fname));
struct dirent *
glob_readdir(dirp)
RST_DIR *dirp;
{
struct direct *dp;
static struct dirent adirent;
while ((dp = rst_readdir(dirp)) != NULL) {
if (dp->d_ino == 0)
continue;
if (dflag || TSTINO(dp->d_ino, dumpmap))
break;
}
if (dp == NULL)
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);
return (&adirent);
}
/*
* Format a directory entry.
* Return st_mode information in response to stat or lstat calls
*/
char *
fmtentry(fp)
register struct afile *fp;
static int
glob_stat(name, stp)
const char *name;
struct stat *stp;
{
static char fmtres[BUFSIZ];
static int precision = 0;
int i;
register char *cp, *dp;
register struct direct *dp;
if (!vflag) {
fmtres[0] = '\0';
} else {
if (precision == 0)
for (i = maxino; i > 0; i /= 10)
precision++;
(void) sprintf(fmtres, "%*d ", precision, fp->fnum);
}
dp = &fmtres[strlen(fmtres)];
if (dflag && BIT(fp->fnum, dumpmap) == 0)
*dp++ = '^';
else if ((fp->fflags & NEW) != 0)
*dp++ = '*';
dp = pathsearch(name);
if (dp == NULL || (!dflag && TSTINO(dp->d_ino, dumpmap) == 0))
return (-1);
if (inodetype(dp->d_ino) == NODE)
stp->st_mode = IFDIR;
else
*dp++ = ' ';
for (cp = fp->fname; *cp; cp++)
if (!vflag && (*cp < ' ' || *cp >= 0177))
*dp++ = '?';
else
*dp++ = *cp;
if (fp->ftype == NODE)
*dp++ = '/';
*dp++ = 0;
return (fmtres);
stp->st_mode = IFREG;
return (0);
}
/*
* Comparison routine for qsort.
*/
static int
fcmp(f1, f2)
register const void *f1, *f2;
{
return (strcmp(((struct afile *)f1)->fname,
((struct afile *)f2)->fname));
}
/*
* respond to interrupts
*/
void
onintr()
onintr(signo)
int signo;
{
if (command == 'i')
if (command == 'i' && runshell)
longjmp(reset, 1);
if (reply("restore interrupted, continue") == FAIL)
done(1);

View File

@ -38,32 +38,26 @@ char copyright[] =
#endif /* not lint */
#ifndef lint
/*static char sccsid[] = "from: @(#)main.c 5.8 (Berkeley) 6/1/90";*/
static char rcsid[] = "$Id: main.c,v 1.2 1993/08/01 18:25:18 mycroft Exp $";
/* from: static char sccsid[] = "@(#)main.c 5.11 (Berkeley) 10/16/92"; */
static char *rcsid = "$Id: main.c,v 1.3 1993/12/22 10:31:52 cgd Exp $";
#endif /* not lint */
/*
* Modified to recursively extract all files within a subtree
* (supressed by the h option) and recreate the heirarchical
* structure of that subtree and move extracted files to their
* proper homes (supressed by the m option).
* Includes the s (skip files) option for use with multiple
* dumps on a single tape.
* 8/29/80 by Mike Litzkow
*
* Modified to work on the new file system and to recover from
* tape read errors.
* 1/19/82 by Kirk McKusick
*
* Full incremental restore running entirely in user code and
* interactive tape browser.
* 1/19/83 by Kirk McKusick
*/
#include <sys/param.h>
#include <sys/time.h>
#include "restore.h"
#include <ufs/fs.h>
#include <ufs/dinode.h>
#include <protocols/dumprestore.h>
#include <sys/signal.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pathnames.h"
#include "restore.h"
#include "extern.h"
int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
int hflag = 1, mflag = 1, Nflag = 0;
@ -78,126 +72,99 @@ time_t dumptime;
time_t dumpdate;
FILE *terminal;
static void obsolete __P((int *, char **[]));
static void usage __P((void));
int
main(argc, argv)
int argc;
char *argv[];
{
register char *cp;
int ch;
ino_t ino;
char *inputdev = _PATH_DEFTAPE;
char *symtbl = "./restoresymtable";
char name[MAXPATHLEN];
void onintr();
char *p, name[MAXPATHLEN];
if (argc < 2)
usage();
obsolete(&argc, &argv);
while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tvxy")) != EOF)
switch(ch) {
case 'b':
/* Change default tape blocksize. */
bflag = 1;
ntrec = strtol(optarg, &p, 10);
if (*p)
err("illegal blocksize -- %s", optarg);
if (ntrec <= 0)
err("block size must be greater than 0");
break;
case 'c':
cvtflag = 1;
break;
case 'd':
dflag = 1;
break;
case 'f':
inputdev = optarg;
break;
case 'h':
hflag = 0;
break;
case 'i':
case 'R':
case 'r':
case 't':
case 'x':
if (command != '\0')
err("%c and %c options are mutually exclusive",
ch, command);
command = ch;
break;
case 'm':
mflag = 0;
break;
case 'N':
Nflag = 1;
break;
case 's':
/* Dumpnum (skip to) for multifile dump tapes. */
dumpnum = strtol(optarg, &p, 10);
if (*p)
err("illegal dump number -- %s", optarg);
if (dumpnum <= 0)
err("dump number must be greater than 0");
break;
case 'v':
vflag = 1;
break;
case 'y':
yflag = 1;
break;
default:
usage();
}
argc -= optind;
argv += optind;
if (command == '\0')
err("none of i, R, r, t or x options specified");
if (signal(SIGINT, onintr) == SIG_IGN)
(void) signal(SIGINT, SIG_IGN);
if (signal(SIGTERM, onintr) == SIG_IGN)
(void) signal(SIGTERM, SIG_IGN);
setlinebuf(stderr);
if (argc < 2) {
usage:
fprintf(stderr, "Usage:\n%s%s%s%s%s",
"\trestore tfhsvy [file file ...]\n",
"\trestore xfhmsvy [file file ...]\n",
"\trestore ifhmsvy\n",
"\trestore rfsvy\n",
"\trestore Rfsvy\n");
done(1);
}
argv++;
argc -= 2;
command = '\0';
for (cp = *argv++; *cp; cp++) {
switch (*cp) {
case '-':
break;
case 'c':
cvtflag++;
break;
case 'd':
dflag++;
break;
case 'h':
hflag = 0;
break;
case 'm':
mflag = 0;
break;
case 'N':
Nflag++;
break;
case 'v':
vflag++;
break;
case 'y':
yflag++;
break;
case 'f':
if (argc < 1) {
fprintf(stderr, "missing device specifier\n");
done(1);
}
inputdev = *argv++;
argc--;
break;
case 'b':
/*
* change default tape blocksize
*/
bflag++;
if (argc < 1) {
fprintf(stderr, "missing block size\n");
done(1);
}
ntrec = atoi(*argv++);
if (ntrec <= 0) {
fprintf(stderr, "Block size must be a positive integer\n");
done(1);
}
argc--;
break;
case 's':
/*
* dumpnum (skip to) for multifile dump tapes
*/
if (argc < 1) {
fprintf(stderr, "missing dump number\n");
done(1);
}
dumpnum = atoi(*argv++);
if (dumpnum <= 0) {
fprintf(stderr, "Dump number must be a positive integer\n");
done(1);
}
argc--;
break;
case 't':
case 'R':
case 'r':
case 'x':
case 'i':
if (command != '\0') {
fprintf(stderr,
"%c and %c are mutually exclusive\n",
*cp, command);
goto usage;
}
command = *cp;
break;
default:
fprintf(stderr, "Bad key character %c\n", *cp);
goto usage;
}
}
if (command == '\0') {
fprintf(stderr, "must specify i, t, r, R, or x\n");
goto usage;
}
setinput(inputdev);
if (argc == 0) {
argc = 1;
*--argv = ".";
}
switch (command) {
/*
* Interactive mode.
@ -205,9 +172,9 @@ usage:
case 'i':
setup();
extractdirs(1);
initsymtable((char *)0);
initsymtable(NULL);
runcmdshell();
done(0);
break;
/*
* Incremental restoration of a file system.
*/
@ -237,14 +204,14 @@ usage:
}
createleaves(symtbl);
createlinks();
setdirmodes();
setdirmodes(FORCE);
checkrestore();
if (dflag) {
vprintf(stdout, "Verify the directory structure\n");
treescan(".", ROOTINO, verifyfile);
}
dumpsymtable(symtbl, (long)1);
done(0);
break;
/*
* Resume an incremental file system restoration.
*/
@ -254,10 +221,10 @@ usage:
skipdirs();
createleaves(symtbl);
createlinks();
setdirmodes();
setdirmodes(FORCE);
checkrestore();
dumpsymtable(symtbl, (long)1);
done(0);
break;
/*
* List contents of tape.
*/
@ -272,7 +239,7 @@ usage:
continue;
treescan(name, ino, listfile);
}
done(0);
break;
/*
* Batch extraction of tape contents.
*/
@ -291,9 +258,93 @@ usage:
}
createfiles();
createlinks();
setdirmodes();
setdirmodes(0);
if (dflag)
checkrestore();
done(0);
break;
}
done(0);
/* NOTREACHED */
}
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");
done(1);
}
/*
* obsolete --
* Change set of key letters and ordered arguments into something
* getopt(3) will like.
*/
static void
obsolete(argcp, argvp)
int *argcp;
char **argvp[];
{
int argc, flags;
char *ap, **argv, *flagsp, **nargv, *p;
/* Setup. */
argv = *argvp;
argc = *argcp;
/* Return if no arguments or first argument has leading dash. */
ap = argv[1];
if (argc == 1 || *ap == '-')
return;
/* Allocate space for new arguments. */
if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL ||
(p = flagsp = malloc(strlen(ap) + 2)) == NULL)
err("%s", strerror(errno));
*nargv++ = *argv;
argv += 2;
for (flags = 0; *ap; ++ap) {
switch(*ap) {
case 'b':
case 'f':
case 's':
if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL)
err("%s", strerror(errno));
nargv[0][0] = '-';
nargv[0][1] = *ap;
(void)strcpy(&nargv[0][2], *argv);
if (*argv != NULL)
++argv;
++nargv;
break;
default:
if (!flags) {
*p++ = '-';
flags = 1;
}
*p++ = *ap;
break;
}
}
/* Terminate flags. */
if (flags) {
*p = '\0';
*nargv++ = flagsp;
}
/* Copy remaining arguments. */
while (*nargv++ = *argv++);
}
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif

View File

@ -1 +1 @@
revision 1.2 intentionally removed
revision 1.3 intentionally removed

View File

@ -29,10 +29,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)restore.8 6.10 (Berkeley) 7/23/91
.\" $Id: restore.8,v 1.3 1993/10/05 00:12:10 jtc Exp $
.\" from: @(#)restore.8 6.11 (Berkeley) 8/28/91
.\" $Id: restore.8,v 1.4 1993/12/22 10:31:59 cgd Exp $
.\"
.Dd July 23, 1991
.Dd August 28, 1991
.Dt RESTORE 8
.Os BSD 4
.Sh NAME
@ -53,9 +53,10 @@ Single files and
directory subtrees may be restored from full or partial
backups.
.Nm Restore
cannot work across a network, to do this, see the companion
command
.Xr rrestore .
works across a network;
to do this see the
.Fl f
flag described below.
The actions
of
.Nm restore
@ -247,6 +248,11 @@ The next argument to
is used as the name of the archive instead
of
.Pa /dev/rmt? .
If the name of the file is of the form
.Dq 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
@ -377,11 +383,11 @@ owner, mode, and time stamps for directories.
information passed between incremental restores.
.El
.Sh SEE ALSO
.Xr rrestore 8 ,
.Xr dump 8 ,
.Xr newfs 8 ,
.Xr mount 8 ,
.Xr mkfs 8
.Xr mkfs 8 ,
.Xr rmt 8
.Sh BUGS
.Nm Restore
can get confused when doing incremental restores from

View File

@ -32,11 +32,24 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)restore.c 5.7 (Berkeley) 6/1/90";*/
static char rcsid[] = "$Id: restore.c,v 1.2 1993/08/01 18:25:16 mycroft Exp $";
/* from: static char sccsid[] = "@(#)restore.c 5.11 (Berkeley) 10/16/92"; */
static char *rcsid = "$Id: restore.c,v 1.3 1993/12/22 10:32:04 cgd Exp $";
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <stdio.h>
#include <string.h>
#include "restore.h"
#include "extern.h"
static char *keyval __P((int));
/*
* This implements the 't' option.
@ -50,9 +63,8 @@ listfile(name, ino, type)
{
long descend = hflag ? GOOD : FAIL;
if (BIT(ino, dumpmap) == 0) {
if (TSTINO(ino, dumpmap) == 0)
return (descend);
}
vprintf(stdout, "%s", type == LEAF ? "leaf" : "dir ");
fprintf(stdout, "%10d\t%s\n", ino, name);
return (descend);
@ -72,7 +84,7 @@ addfile(name, ino, type)
long descend = hflag ? GOOD : FAIL;
char buf[100];
if (BIT(ino, dumpmap) == 0) {
if (TSTINO(ino, dumpmap) == 0) {
dprintf(stdout, "%s: not on the tape\n", name);
return (descend);
}
@ -85,7 +97,7 @@ addfile(name, ino, type)
}
}
ep = lookupino(ino);
if (ep != NIL) {
if (ep != NULL) {
if (strcmp(name, myname(ep)) == 0) {
ep->e_flags |= NEW;
return (descend);
@ -113,11 +125,10 @@ deletefile(name, ino, type)
long descend = hflag ? GOOD : FAIL;
struct entry *ep;
if (BIT(ino, dumpmap) == 0) {
if (TSTINO(ino, dumpmap) == 0)
return (descend);
}
ep = lookupino(ino);
if (ep != NIL)
if (ep != NULL)
ep->e_flags &= ~NEW;
return (descend);
}
@ -141,6 +152,7 @@ static struct entry *removelist;
* Remove unneeded leaves from the old tree.
* Remove directories from the lookup chains.
*/
void
removeoldleaves()
{
register struct entry *ep;
@ -149,11 +161,11 @@ removeoldleaves()
vprintf(stdout, "Mark entries to be removed.\n");
for (i = ROOTINO + 1; i < maxino; i++) {
ep = lookupino(i);
if (ep == NIL)
if (ep == NULL)
continue;
if (BIT(i, clrimap))
if (TSTINO(i, clrimap))
continue;
for ( ; ep != NIL; ep = ep->e_links) {
for ( ; ep != NULL; ep = ep->e_links) {
dprintf(stdout, "%s: REMOVE\n", myname(ep));
if (ep->e_type == LEAF) {
removeleaf(ep);
@ -192,7 +204,6 @@ nodeupdates(name, ino, type)
# define INOFND 0x2 /* inode already exists */
# define NAMEFND 0x4 /* name already exists */
# define MODECHG 0x8 /* mode of inode changed */
extern char *keyval();
/*
* This routine is called once for each element in the
@ -202,13 +213,13 @@ nodeupdates(name, ino, type)
*
* Check to see if the file is on the tape.
*/
if (BIT(ino, dumpmap))
if (TSTINO(ino, dumpmap))
key |= ONTAPE;
/*
* Check to see if the name exists, and if the name is a link.
*/
np = lookupname(name);
if (np != NIL) {
if (np != NULL) {
key |= NAMEFND;
ip = lookupino(np->e_ino);
if (ip == NULL)
@ -221,9 +232,9 @@ nodeupdates(name, ino, type)
* corresponds to the name (if one was found).
*/
ip = lookupino(ino);
if (ip != NIL) {
if (ip != NULL) {
key |= INOFND;
for (ep = ip->e_links; ep != NIL; ep = ep->e_links) {
for (ep = ip->e_links; ep != NULL; ep = ep->e_links) {
if (ep == np) {
ip = ep;
break;
@ -252,7 +263,7 @@ nodeupdates(name, ino, type)
myname(np));
mktempname(np);
}
np = NIL;
np = NULL;
key &= ~NAMEFND;
}
if ((key & ONTAPE) &&
@ -354,9 +365,22 @@ nodeupdates(name, ino, type)
break;
/*
* A previously known file which is to be updated.
* A previously known file which is to be updated. If it is a link,
* then all names referring to the previous file must be removed
* so that the subset of them that remain can be recreated.
*/
case ONTAPE|INOFND|NAMEFND:
if (lookuptype == LINK) {
removeleaf(np);
freeentry(np);
ep = addentry(name, ino, type|LINK);
if (type == NODE)
newnode(ep);
ep->e_flags |= NEW|KEEP;
dprintf(stdout, "[%s] %s: %s|LINK\n", keyval(key), name,
flagvalues(ep));
break;
}
if (type == LEAF && lookuptype != LINK)
np->e_flags |= EXTRACT;
np->e_flags |= KEEP;
@ -419,7 +443,7 @@ nodeupdates(name, ino, type)
* for it, we discard the name knowing that it will be on the
* next incremental tape.
*/
case NIL:
case NULL:
fprintf(stderr, "%s: (inode %d) not found on tape\n",
name, ino);
break;
@ -450,7 +474,7 @@ nodeupdates(name, ino, type)
/*
* Calculate the active flags in a key.
*/
char *
static char *
keyval(key)
int key;
{
@ -472,6 +496,7 @@ keyval(key)
/*
* Find unreferenced link names.
*/
void
findunreflinks()
{
register struct entry *ep, *np;
@ -480,9 +505,9 @@ findunreflinks()
vprintf(stdout, "Find unreferenced names.\n");
for (i = ROOTINO; i < maxino; i++) {
ep = lookupino(i);
if (ep == NIL || ep->e_type == LEAF || BIT(i, dumpmap) == 0)
if (ep == NULL || ep->e_type == LEAF || TSTINO(i, dumpmap) == 0)
continue;
for (np = ep->e_entries; np != NIL; np = np->e_sibling) {
for (np = ep->e_entries; np != NULL; np = np->e_sibling) {
if (np->e_flags == 0) {
dprintf(stdout,
"%s: remove unreferenced name\n",
@ -495,8 +520,8 @@ findunreflinks()
/*
* Any leaves remaining in removed directories is unreferenced.
*/
for (ep = removelist; ep != NIL; ep = ep->e_next) {
for (np = ep->e_entries; np != NIL; np = np->e_sibling) {
for (ep = removelist; ep != NULL; ep = ep->e_next) {
for (np = ep->e_entries; np != NULL; np = np->e_sibling) {
if (np->e_type == LEAF) {
if (np->e_flags != 0)
badentry(np, "unreferenced with flags");
@ -519,6 +544,7 @@ findunreflinks()
* topologically sorted, the deletion could be done in
* time O(N).
*/
void
removeoldnodes()
{
register struct entry *ep, **prev;
@ -528,8 +554,8 @@ removeoldnodes()
do {
change = 0;
prev = &removelist;
for (ep = removelist; ep != NIL; ep = *prev) {
if (ep->e_entries != NIL) {
for (ep = removelist; ep != NULL; ep = *prev) {
if (ep->e_entries != NULL) {
prev = &ep->e_next;
continue;
}
@ -539,7 +565,7 @@ removeoldnodes()
change++;
}
} while (change);
for (ep = removelist; ep != NIL; ep = ep->e_next)
for (ep = removelist; ep != NULL; ep = ep->e_next)
badentry(ep, "cannot remove, non-empty");
}
@ -547,6 +573,7 @@ removeoldnodes()
* This is the routine used to extract files for the 'r' command.
* Extract new leaves.
*/
void
createleaves(symtabfile)
char *symtabfile;
{
@ -573,7 +600,7 @@ createleaves(symtabfile)
*/
while (first < curfile.ino) {
ep = lookupino(first);
if (ep == NIL)
if (ep == NULL)
panic("%d: bad first\n", first);
fprintf(stderr, "%s: not found on tape\n", myname(ep));
ep->e_flags &= ~(NEW|EXTRACT);
@ -593,7 +620,7 @@ createleaves(symtabfile)
goto next;
}
ep = lookupino(curfile.ino);
if (ep == NIL)
if (ep == NULL)
panic("unknown file on tape\n");
if ((ep->e_flags & (NEW|EXTRACT)) == 0)
badentry(ep, "unexpected file on tape");
@ -626,6 +653,7 @@ createleaves(symtabfile)
* This is the routine used to extract files for the 'x' and 'i' commands.
* Efficiently extract a subset of the files on a tape.
*/
void
createfiles()
{
register ino_t first, next, last;
@ -688,7 +716,7 @@ createfiles()
*/
while (next < curfile.ino) {
ep = lookupino(next);
if (ep == NIL)
if (ep == NULL)
panic("corrupted symbol table\n");
fprintf(stderr, "%s: not found on tape\n", myname(ep));
ep->e_flags &= ~NEW;
@ -700,7 +728,7 @@ createfiles()
*/
if (next == curfile.ino && next <= last) {
ep = lookupino(next);
if (ep == NIL)
if (ep == NULL)
panic("corrupted symbol table\n");
(void) extractfile(myname(ep));
ep->e_flags &= ~NEW;
@ -713,6 +741,7 @@ createfiles()
/*
* Add links.
*/
void
createlinks()
{
register struct entry *np, *ep;
@ -722,9 +751,9 @@ createlinks()
vprintf(stdout, "Add links\n");
for (i = ROOTINO; i < maxino; i++) {
ep = lookupino(i);
if (ep == NIL)
if (ep == NULL)
continue;
for (np = ep->e_links; np != NIL; np = np->e_links) {
for (np = ep->e_links; np != NULL; np = np->e_links) {
if ((np->e_flags & NEW) == 0)
continue;
(void) strcpy(name, myname(ep));
@ -743,6 +772,7 @@ createlinks()
* We do this to insure that all the requested work was done, and
* that no temporary names remain.
*/
void
checkrestore()
{
register struct entry *ep;
@ -750,7 +780,7 @@ checkrestore()
vprintf(stdout, "Check the symbol table.\n");
for (i = ROOTINO; i < maxino; i++) {
for (ep = lookupino(i); ep != NIL; ep = ep->e_links) {
for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
ep->e_flags &= ~KEEP;
if (ep->e_type == NODE)
ep->e_flags &= ~(NEW|EXISTED);
@ -774,17 +804,17 @@ verifyfile(name, ino, type)
long descend = GOOD;
ep = lookupname(name);
if (ep == NIL) {
if (ep == NULL) {
fprintf(stderr, "Warning: missing name %s\n", name);
return (FAIL);
}
np = lookupino(ino);
if (np != ep)
descend = FAIL;
for ( ; np != NIL; np = np->e_links)
for ( ; np != NULL; np = np->e_links)
if (np == ep)
break;
if (np == NIL)
if (np == NULL)
panic("missing inumber %d\n", ino);
if (ep->e_type == LEAF && type != LEAF)
badentry(ep, "type should be LEAF");

View File

@ -1 +1 @@
revision 1.2 intentionally removed
revision 1.3 intentionally removed

View File

@ -32,8 +32,8 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)symtab.c 5.5 (Berkeley) 6/1/90";*/
static char rcsid[] = "$Id: symtab.c,v 1.2 1993/08/01 18:25:14 mycroft Exp $";
/* from: static char sccsid[] = "@(#)symtab.c 5.7 (Berkeley) 10/16/92"; */
static char *rcsid = "$Id: symtab.c,v 1.3 1993/12/22 10:32:10 cgd Exp $";
#endif /* not lint */
/*
@ -45,9 +45,21 @@ static char rcsid[] = "$Id: symtab.c,v 1.2 1993/08/01 18:25:14 mycroft Exp $";
* are needed, by calling "myname".
*/
#include "restore.h"
#include <sys/param.h>
#include <sys/stat.h>
#include <ufs/dir.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "restore.h"
#include "extern.h"
/*
* The following variables define the inode symbol table.
@ -60,6 +72,10 @@ static char rcsid[] = "$Id: symtab.c,v 1.2 1993/08/01 18:25:14 mycroft Exp $";
static struct entry **entry;
static long entrytblsize;
static void addino __P((ino_t, struct entry *));
static struct entry *lookupparent __P((char *));
static void removeentry __P((struct entry *));
/*
* Look up an entry by inode number
*/
@ -70,16 +86,17 @@ lookupino(inum)
register struct entry *ep;
if (inum < ROOTINO || inum >= maxino)
return (NIL);
for (ep = entry[inum % entrytblsize]; ep != NIL; ep = ep->e_next)
return (NULL);
for (ep = entry[inum % entrytblsize]; ep != NULL; ep = ep->e_next)
if (ep->e_ino == inum)
return (ep);
return (NIL);
return (NULL);
}
/*
* Add an entry into the entry table
*/
static void
addino(inum, np)
ino_t inum;
struct entry *np;
@ -93,7 +110,7 @@ addino(inum, np)
np->e_next = *epp;
*epp = np;
if (dflag)
for (np = np->e_next; np != NIL; np = np->e_next)
for (np = np->e_next; np != NULL; np = np->e_next)
if (np->e_ino == inum)
badentry(np, "duplicate inum");
}
@ -101,6 +118,7 @@ addino(inum, np)
/*
* Delete an entry from the entry table
*/
void
deleteino(inum)
ino_t inum;
{
@ -110,7 +128,7 @@ deleteino(inum)
if (inum < ROOTINO || inum >= maxino)
panic("deleteino: out of range %d\n", inum);
prev = &entry[inum % entrytblsize];
for (next = *prev; next != NIL; next = next->e_next) {
for (next = *prev; next != NULL; next = next->e_next) {
if (next->e_ino == inum) {
next->e_ino = 0;
*prev = next->e_next;
@ -133,25 +151,25 @@ lookupname(name)
char buf[MAXPATHLEN];
cp = name;
for (ep = lookupino(ROOTINO); ep != NIL; ep = ep->e_entries) {
for (ep = lookupino(ROOTINO); ep != NULL; ep = ep->e_entries) {
for (np = buf; *cp != '/' && *cp != '\0'; )
*np++ = *cp++;
*np = '\0';
for ( ; ep != NIL; ep = ep->e_sibling)
for ( ; ep != NULL; ep = ep->e_sibling)
if (strcmp(ep->e_name, buf) == 0)
break;
if (ep == NIL)
if (ep == NULL)
break;
if (*cp++ == '\0')
return (ep);
}
return (NIL);
return (NULL);
}
/*
* Look up the parent of a pathname
*/
struct entry *
static struct entry *
lookupparent(name)
char *name;
{
@ -160,12 +178,12 @@ lookupparent(name)
tailindex = rindex(name, '/');
if (tailindex == 0)
return (NIL);
return (NULL);
*tailindex = '\0';
ep = lookupname(name);
*tailindex = '/';
if (ep == NIL)
return (NIL);
if (ep == NULL)
return (NULL);
if (ep->e_type != NODE)
panic("%s is not a directory\n", name);
return (ep);
@ -197,7 +215,7 @@ myname(ep)
* Unused symbol table entries are linked together on a freelist
* headed by the following pointer.
*/
static struct entry *freelist = NIL;
static struct entry *freelist = NULL;
/*
* add an entry to the symbol table
@ -210,19 +228,19 @@ addentry(name, inum, type)
{
register struct entry *np, *ep;
if (freelist != NIL) {
if (freelist != NULL) {
np = freelist;
freelist = np->e_next;
bzero((char *)np, (long)sizeof(struct entry));
} else {
np = (struct entry *)calloc(1, sizeof(struct entry));
if (np == NIL)
if (np == NULL)
panic("no memory to extend symbol table\n");
}
np->e_type = type & ~LINK;
ep = lookupparent(name);
if (ep == NIL) {
if (inum != ROOTINO || lookupino(ROOTINO) != NIL)
if (ep == NULL) {
if (inum != ROOTINO || lookupino(ROOTINO) != NULL)
panic("bad name to addentry %s\n", name);
np->e_name = savename(name);
np->e_namlen = strlen(name);
@ -237,13 +255,13 @@ addentry(name, inum, type)
ep->e_entries = np;
if (type & LINK) {
ep = lookupino(inum);
if (ep == NIL)
if (ep == NULL)
panic("link to non-existant name\n");
np->e_ino = inum;
np->e_links = ep->e_links;
ep->e_links = np;
} else if (inum != 0) {
if (lookupino(inum) != NIL)
if (lookupino(inum) != NULL)
panic("duplicate entry\n");
addino(inum, np);
}
@ -253,6 +271,7 @@ addentry(name, inum, type)
/*
* delete an entry from the symbol table
*/
void
freeentry(ep)
register struct entry *ep;
{
@ -262,28 +281,28 @@ freeentry(ep)
if (ep->e_flags != REMOVED)
badentry(ep, "not marked REMOVED");
if (ep->e_type == NODE) {
if (ep->e_links != NIL)
if (ep->e_links != NULL)
badentry(ep, "freeing referenced directory");
if (ep->e_entries != NIL)
if (ep->e_entries != NULL)
badentry(ep, "freeing non-empty directory");
}
if (ep->e_ino != 0) {
np = lookupino(ep->e_ino);
if (np == NIL)
if (np == NULL)
badentry(ep, "lookupino failed");
if (np == ep) {
inum = ep->e_ino;
deleteino(inum);
if (ep->e_links != NIL)
if (ep->e_links != NULL)
addino(inum, ep->e_links);
} else {
for (; np != NIL; np = np->e_links) {
for (; np != NULL; np = np->e_links) {
if (np->e_links == ep) {
np->e_links = ep->e_links;
break;
}
}
if (np == NIL)
if (np == NULL)
badentry(ep, "link not found");
}
}
@ -296,6 +315,7 @@ freeentry(ep)
/*
* Relocate an entry in the tree structure
*/
void
moveentry(ep, newname)
register struct entry *ep;
char *newname;
@ -304,7 +324,7 @@ moveentry(ep, newname)
char *cp;
np = lookupparent(newname);
if (np == NIL)
if (np == NULL)
badentry(ep, "cannot move ROOT");
if (np != ep->e_parent) {
removeentry(ep);
@ -325,6 +345,7 @@ moveentry(ep, newname)
/*
* Remove an entry in the tree structure
*/
static void
removeentry(ep)
register struct entry *ep;
{
@ -334,13 +355,13 @@ removeentry(ep)
if (np->e_entries == ep) {
np->e_entries = ep->e_sibling;
} else {
for (np = np->e_entries; np != NIL; np = np->e_sibling) {
for (np = np->e_entries; np != NULL; np = np->e_sibling) {
if (np->e_sibling == ep) {
np->e_sibling = ep->e_sibling;
break;
}
}
if (np == NIL)
if (np == NULL)
badentry(ep, "cannot find entry in parent list");
}
}
@ -364,7 +385,7 @@ struct strhdr {
#define STRTBLINCR (sizeof(struct strhdr))
#define allocsize(size) (((size) + 1 + STRTBLINCR - 1) & ~(STRTBLINCR - 1))
static struct strhdr strtblhdr[allocsize(MAXNAMLEN) / STRTBLINCR];
static struct strhdr strtblhdr[allocsize(NAME_MAX) / STRTBLINCR];
/*
* Allocate space for a name. It first looks to see if it already
@ -398,6 +419,7 @@ savename(name)
* Free space for a name. The resulting entry is linked onto the
* appropriate free list.
*/
void
freename(name)
char *name;
{
@ -425,6 +447,7 @@ struct symtableheader {
/*
* dump a snapshot of the symbol table
*/
void
dumpsymtable(filename, checkpt)
char *filename;
long checkpt;
@ -440,7 +463,7 @@ dumpsymtable(filename, checkpt)
if (Nflag)
return;
if ((fd = fopen(filename, "w")) == NULL) {
perror("fopen");
fprintf(stderr, "fopen: %s\n", strerror(errno));
panic("cannot create save file %s for symbol table\n",
filename);
}
@ -450,7 +473,7 @@ dumpsymtable(filename, checkpt)
* Write out the string entries
*/
for (i = ROOTINO; i < maxino; i++) {
for (ep = lookupino(i); ep != NIL; ep = ep->e_links) {
for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
ep->e_index = mynum++;
(void) fwrite(ep->e_name, sizeof(char),
(int)allocsize(ep->e_namlen), fd);
@ -462,22 +485,22 @@ dumpsymtable(filename, checkpt)
tep = &temp;
stroff = 0;
for (i = ROOTINO; i < maxino; i++) {
for (ep = lookupino(i); ep != NIL; ep = ep->e_links) {
for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
bcopy((char *)ep, (char *)tep,
(long)sizeof(struct entry));
tep->e_name = (char *)stroff;
stroff += allocsize(ep->e_namlen);
tep->e_parent = (struct entry *)ep->e_parent->e_index;
if (ep->e_links != NIL)
if (ep->e_links != NULL)
tep->e_links =
(struct entry *)ep->e_links->e_index;
if (ep->e_sibling != NIL)
if (ep->e_sibling != NULL)
tep->e_sibling =
(struct entry *)ep->e_sibling->e_index;
if (ep->e_entries != NIL)
if (ep->e_entries != NULL)
tep->e_entries =
(struct entry *)ep->e_entries->e_index;
if (ep->e_next != NIL)
if (ep->e_next != NULL)
tep->e_next =
(struct entry *)ep->e_next->e_index;
(void) fwrite((char *)tep, sizeof(struct entry), 1, fd);
@ -487,8 +510,8 @@ dumpsymtable(filename, checkpt)
* Convert entry pointers to indexes, and output
*/
for (i = 0; i < entrytblsize; i++) {
if (entry[i] == NIL)
tentry = NIL;
if (entry[i] == NULL)
tentry = NULL;
else
tentry = (struct entry *)entry[i]->e_index;
(void) fwrite((char *)&tentry, sizeof(struct entry *), 1, fd);
@ -502,7 +525,7 @@ dumpsymtable(filename, checkpt)
hdr.ntrec = ntrec;
(void) fwrite((char *)&hdr, sizeof(struct symtableheader), 1, fd);
if (ferror(fd)) {
perror("fwrite");
fprintf(stderr, "fwrite: %s\n", strerror(errno));
panic("output error to file %s writing symbol table\n",
filename);
}
@ -512,6 +535,7 @@ dumpsymtable(filename, checkpt)
/*
* Initialize a symbol table from a file
*/
void
initsymtable(filename)
char *filename;
{
@ -529,18 +553,18 @@ initsymtable(filename)
entrytblsize = maxino / HASHFACTOR;
entry = (struct entry **)
calloc((unsigned)entrytblsize, sizeof(struct entry *));
if (entry == (struct entry **)NIL)
if (entry == (struct entry **)NULL)
panic("no memory for entry table\n");
ep = addentry(".", ROOTINO, NODE);
ep->e_flags |= NEW;
return;
}
if ((fd = open(filename, 0)) < 0) {
perror("open");
if ((fd = open(filename, O_RDONLY, 0)) < 0) {
fprintf(stderr, "open: %s\n", strerror(errno));
panic("cannot open symbol table file %s\n", filename);
}
if (fstat(fd, &stbuf) < 0) {
perror("stat");
fprintf(stderr, "stat: %s\n", strerror(errno));
panic("cannot stat symbol table file %s\n", filename);
}
tblsize = stbuf.st_size - sizeof(struct symtableheader);
@ -549,7 +573,7 @@ initsymtable(filename)
panic("cannot allocate space for symbol table\n");
if (read(fd, base, (int)tblsize) < 0 ||
read(fd, (char *)&hdr, sizeof(struct symtableheader)) < 0) {
perror("read");
fprintf(stderr, "read: %s\n", strerror(errno));
panic("cannot read symbol table file %s\n", filename);
}
switch (command) {
@ -588,20 +612,20 @@ initsymtable(filename)
baseep = (struct entry *)(base + hdr.stringsize - sizeof(struct entry));
lep = (struct entry *)entry;
for (i = 0; i < entrytblsize; i++) {
if (entry[i] == NIL)
if (entry[i] == NULL)
continue;
entry[i] = &baseep[(long)entry[i]];
}
for (ep = &baseep[1]; ep < lep; ep++) {
ep->e_name = base + (long)ep->e_name;
ep->e_parent = &baseep[(long)ep->e_parent];
if (ep->e_sibling != NIL)
if (ep->e_sibling != NULL)
ep->e_sibling = &baseep[(long)ep->e_sibling];
if (ep->e_links != NIL)
if (ep->e_links != NULL)
ep->e_links = &baseep[(long)ep->e_links];
if (ep->e_entries != NIL)
if (ep->e_entries != NULL)
ep->e_entries = &baseep[(long)ep->e_entries];
if (ep->e_next != NIL)
if (ep->e_next != NULL)
ep->e_next = &baseep[(long)ep->e_next];
}
}

View File

@ -1 +1 @@
revision 1.4 intentionally removed
revision 1.5 intentionally removed

View File

@ -32,15 +32,30 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)utilities.c 5.6 (Berkeley) 6/1/90";*/
static char rcsid[] = "$Id: utilities.c,v 1.2 1993/08/01 18:25:08 mycroft Exp $";
/* from: static char sccsid[] = "@(#)utilities.c 5.10 (Berkeley) 12/2/92"; */
static char *rcsid = "$Id: utilities.c,v 1.3 1993/12/22 10:32:18 cgd Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <ufs/dinode.h>
#include <ufs/dir.h>
#include <ufs/fs.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "restore.h"
#include "extern.h"
/*
* Insure that all the components of a pathname exist.
*/
void
pathcheck(name)
char *name;
{
@ -56,8 +71,8 @@ pathcheck(name)
continue;
*cp = '\0';
ep = lookupname(name);
if (ep == NIL) {
ep = addentry(name, psearch(name), NODE);
if (ep == NULL) {
ep = addentry(name, pathsearch(name)->d_ino, NODE);
newnode(ep);
}
ep->e_flags |= NEW|KEEP;
@ -68,6 +83,7 @@ pathcheck(name)
/*
* Change a name to a unique temporary name.
*/
void
mktempname(ep)
register struct entry *ep;
{
@ -94,9 +110,10 @@ gentempname(ep)
struct entry *np;
long i = 0;
for (np = lookupino(ep->e_ino); np != NIL && np != ep; np = np->e_links)
for (np = lookupino(ep->e_ino);
np != NULL && np != ep; np = np->e_links)
i++;
if (np == NIL)
if (np == NULL)
badentry(ep, "not on ino list");
(void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino);
return (name);
@ -105,13 +122,13 @@ gentempname(ep)
/*
* Rename a file or directory.
*/
void
renameit(from, to)
char *from, *to;
{
if (!Nflag && rename(from, to) < 0) {
fprintf(stderr, "Warning: cannot rename %s to %s", from, to);
(void) fflush(stderr);
perror("");
fprintf(stderr, "warning: cannot rename %s to %s: %s\n",
from, to, strerror(errno));
return;
}
vprintf(stdout, "rename %s to %s\n", from, to);
@ -120,6 +137,7 @@ renameit(from, to)
/*
* Create a new node (directory).
*/
void
newnode(np)
struct entry *np;
{
@ -130,9 +148,7 @@ newnode(np)
cp = myname(np);
if (!Nflag && mkdir(cp, 0777) < 0) {
np->e_flags |= EXISTED;
fprintf(stderr, "Warning: ");
(void) fflush(stderr);
perror(cp);
fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
return;
}
vprintf(stdout, "Make node %s\n", cp);
@ -141,6 +157,7 @@ newnode(np)
/*
* Remove an old node (directory).
*/
void
removenode(ep)
register struct entry *ep;
{
@ -148,15 +165,13 @@ removenode(ep)
if (ep->e_type != NODE)
badentry(ep, "removenode: not a node");
if (ep->e_entries != NIL)
if (ep->e_entries != NULL)
badentry(ep, "removenode: non-empty directory");
ep->e_flags |= REMOVED;
ep->e_flags &= ~TMPNAME;
cp = myname(ep);
if (!Nflag && rmdir(cp) < 0) {
fprintf(stderr, "Warning: ");
(void) fflush(stderr);
perror(cp);
fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
return;
}
vprintf(stdout, "Remove node %s\n", cp);
@ -165,6 +180,7 @@ removenode(ep)
/*
* Remove a leaf.
*/
void
removeleaf(ep)
register struct entry *ep;
{
@ -176,9 +192,7 @@ removeleaf(ep)
ep->e_flags &= ~TMPNAME;
cp = myname(ep);
if (!Nflag && unlink(cp) < 0) {
fprintf(stderr, "Warning: ");
(void) fflush(stderr);
perror(cp);
fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
return;
}
vprintf(stdout, "Remove leaf %s\n", cp);
@ -187,6 +201,7 @@ removeleaf(ep)
/*
* Create a link.
*/
int
linkit(existing, new, type)
char *existing, *new;
int type;
@ -195,19 +210,15 @@ linkit(existing, new, type)
if (type == SYMLINK) {
if (!Nflag && symlink(existing, new) < 0) {
fprintf(stderr,
"Warning: cannot create symbolic link %s->%s: ",
new, existing);
(void) fflush(stderr);
perror("");
"warning: cannot create symbolic link %s->%s: %s\n",
new, existing, strerror(errno));
return (FAIL);
}
} else if (type == HARDLINK) {
if (!Nflag && link(existing, new) < 0) {
fprintf(stderr,
"Warning: cannot create hard link %s->%s: ",
new, existing);
(void) fflush(stderr);
perror("");
"warning: cannot create hard link %s->%s: %s\n",
new, existing, strerror(errno));
return (FAIL);
}
} else {
@ -230,7 +241,7 @@ lowerbnd(start)
for ( ; start < maxino; start++) {
ep = lookupino(start);
if (ep == NIL || ep->e_type == NODE)
if (ep == NULL || ep->e_type == NODE)
continue;
if (ep->e_flags & (NEW|EXTRACT))
return (start);
@ -249,7 +260,7 @@ upperbnd(start)
for ( ; start > ROOTINO; start--) {
ep = lookupino(start);
if (ep == NIL || ep->e_type == NODE)
if (ep == NULL || ep->e_type == NODE)
continue;
if (ep->e_flags & (NEW|EXTRACT))
return (start);
@ -260,6 +271,7 @@ upperbnd(start)
/*
* report on a badly formed entry
*/
void
badentry(ep, msg)
register struct entry *ep;
char *msg;
@ -268,14 +280,15 @@ badentry(ep, msg)
fprintf(stderr, "bad entry: %s\n", msg);
fprintf(stderr, "name: %s\n", myname(ep));
fprintf(stderr, "parent name %s\n", myname(ep->e_parent));
if (ep->e_sibling != NIL)
if (ep->e_sibling != NULL)
fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling));
if (ep->e_entries != NIL)
if (ep->e_entries != NULL)
fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries));
if (ep->e_links != NIL)
if (ep->e_links != NULL)
fprintf(stderr, "next link name: %s\n", myname(ep->e_links));
if (ep->e_next != NIL)
fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next));
if (ep->e_next != NULL)
fprintf(stderr,
"next hashchain name: %s\n", myname(ep->e_next));
fprintf(stderr, "entry type: %s\n",
ep->e_type == NODE ? "NODE" : "LEAF");
fprintf(stderr, "inode number: %ld\n", ep->e_ino);
@ -317,8 +330,8 @@ dirlookup(name)
{
ino_t ino;
ino = psearch(name);
if (ino == 0 || BIT(ino, dumpmap) == 0)
ino = pathsearch(name)->d_ino;
if (ino == 0 || TSTINO(ino, dumpmap) == 0)
fprintf(stderr, "%s is not on tape\n", name);
return (ino);
}
@ -326,6 +339,7 @@ dirlookup(name)
/*
* Elicit a reply.
*/
int
reply(question)
char *question;
{
@ -347,13 +361,29 @@ reply(question)
/*
* handle unexpected inconsistencies
*/
/* VARARGS1 */
panic(msg, d1, d2)
char *msg;
long d1, d2;
{
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
fprintf(stderr, msg, d1, d2);
void
#if __STDC__
panic(const char *fmt, ...)
#else
panic(fmt, va_alist)
char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
vfprintf(stderr, fmt, ap);
if (yflag)
return;
if (reply("abort") == GOOD) {