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 # from: @(#)Makefile 5.13 (Berkeley) 3/16/92
# $Id: Makefile,v 1.9 1993/11/14 15:36:05 cgd Exp $ # $Id: Makefile,v 1.10 1993/12/22 10:31:38 cgd Exp $
PROG= restore PROG= restore
SRCS= main.c interactive.c restore.c dirs.c symtab.c tape.c utilities.c LINKS= ${BINDIR}/restore ${BINDIR}/rrestore
ROBJS= main.o interactive.o restore.o dirs.o symtab.o rtape.o utilities.o \ CFLAGS+=-DRRESTORE
dumprmt.o SRCS= main.c interactive.c restore.c dirs.c symtab.c tape.c utilities.c \
MAN8= restore.0 rrestore.0 dumprmt.c
BINOWN= root
BINGRP= tty
BINMODE=6555
MAN8= restore.0
MLINKS+=restore.8 rrestore.8
.PATH: ${.CURDIR}/../dump .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> .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 #ifndef lint
/*static char sccsid[] = "from: @(#)interactive.c 5.9 (Berkeley) 6/1/90";*/ /* from: static char sccsid[] = "@(#)interactive.c 5.18 (Berkeley) 12/2/92"; */
static char rcsid[] = "$Id: interactive.c,v 1.2 1993/08/01 18:25:21 mycroft Exp $"; static char *rcsid = "$Id: interactive.c,v 1.3 1993/12/22 10:31:47 cgd Exp $";
#endif /* not lint */ #endif /* not lint */
#include "restore.h" #include <sys/param.h>
#include <protocols/dumprestore.h> #include <sys/time.h>
#include <setjmp.h> #include <sys/stat.h>
#include <ufs/fs.h>
#include <ufs/dinode.h>
#include <ufs/dir.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)) #define round(a, b) (((a) + (b) - 1) / (b) * (b))
/* /*
* Things to handle interruptions. * Things to handle interruptions.
*/ */
static int runshell;
static jmp_buf reset; static jmp_buf reset;
static char *nextarg = NULL; static char *nextarg = NULL;
@ -55,41 +69,61 @@ static char *nextarg = NULL;
struct afile { struct afile {
ino_t fnum; /* inode number of file */ ino_t fnum; /* inode number of file */
char *fname; /* file name */ char *fname; /* file name */
short fflags; /* extraction flags, if any */ short len; /* name length */
char ftype; /* file type, e.g. LEAF or NODE */ char prefix; /* prefix character */
char postfix; /* postfix character */
}; };
struct arglist { struct arglist {
struct afile *head; /* start of argument list */ int freeglob; /* glob structure needs to be freed */
struct afile *last; /* end of argument list */ int argcnt; /* next globbed argument to return */
struct afile *base; /* current list arena */ glob_t glob; /* globbing information */
int nent; /* maximum size of list */ char *cmd; /* the current command */
char *cmd; /* the current command */
}; };
extern int fcmp();
extern char *fmtentry(); static char *copynext __P((char *, char *));
char *copynext(); 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. * Read and execute commands from the terminal.
*/ */
void
runcmdshell() runcmdshell()
{ {
register struct entry *np; register struct entry *np;
ino_t ino; ino_t ino;
static struct arglist alist = { 0, 0, 0, 0, 0 }; struct arglist arglist;
char curdir[MAXPATHLEN]; char curdir[MAXPATHLEN];
char name[MAXPATHLEN]; char name[MAXPATHLEN];
char cmd[BUFSIZ]; 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); canon("/", curdir);
loop: loop:
if (setjmp(reset) != 0) { if (setjmp(reset) != 0) {
for (; alist.head < alist.last; alist.head++) if (arglist.freeglob != 0) {
freename(alist.head->fname); arglist.freeglob = 0;
arglist.argcnt = 0;
globfree(&arglist.glob);
}
nextarg = NULL; nextarg = NULL;
volno = 0; volno = 0;
} }
getcmd(curdir, cmd, name, &alist); runshell = 1;
getcmd(curdir, cmd, name, &arglist);
switch (cmd[0]) { switch (cmd[0]) {
/* /*
* Add elements to the extraction list. * Add elements to the extraction list.
@ -126,7 +160,7 @@ loop:
if (strncmp(cmd, "delete", strlen(cmd)) != 0) if (strncmp(cmd, "delete", strlen(cmd)) != 0)
goto bad; goto bad;
np = lookupname(name); 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); fprintf(stderr, "%s: not on extraction list\n", name);
break; break;
} }
@ -140,7 +174,7 @@ loop:
goto bad; goto bad;
createfiles(); createfiles();
createlinks(); createlinks();
setdirmodes(); setdirmodes(0);
if (dflag) if (dflag)
checkrestore(); checkrestore();
volno = 0; volno = 0;
@ -177,10 +211,7 @@ loop:
case 'l': case 'l':
if (strncmp(cmd, "ls", strlen(cmd)) != 0) if (strncmp(cmd, "ls", strlen(cmd)) != 0)
goto bad; goto bad;
ino = dirlookup(name); printlist(name, curdir);
if (ino == 0)
break;
printlist(name, ino, curdir);
break; break;
/* /*
* Print current directory. * Print current directory.
@ -224,7 +255,7 @@ loop:
case 's': case 's':
if (strncmp(cmd, "setmodes", strlen(cmd)) != 0) if (strncmp(cmd, "setmodes", strlen(cmd)) != 0)
goto bad; goto bad;
setdirmodes(); setdirmodes(FORCE);
break; break;
/* /*
* Print out dump header information. * Print out dump header information.
@ -270,6 +301,7 @@ loop:
* "curdir" is prepended to it. Finally "canon" is called to * "curdir" is prepended to it. Finally "canon" is called to
* eliminate any embedded ".." components. * eliminate any embedded ".." components.
*/ */
static void
getcmd(curdir, cmd, name, ap) getcmd(curdir, cmd, name, ap)
char *curdir, *cmd, *name; char *curdir, *cmd, *name;
struct arglist *ap; struct arglist *ap;
@ -282,12 +314,8 @@ getcmd(curdir, cmd, name, ap)
/* /*
* Check to see if still processing arguments. * Check to see if still processing arguments.
*/ */
if (ap->head != ap->last) { if (ap->argcnt > 0)
strcpy(name, ap->head->fname); goto retnext;
freename(ap->head->fname);
ap->head++;
return;
}
if (nextarg != NULL) if (nextarg != NULL)
goto getnext; goto getnext;
/* /*
@ -328,7 +356,7 @@ getnext:
else else
nextarg = cp; 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] == '/') { if (rawname[0] == '/') {
canon(rawname, name); canon(rawname, name);
@ -342,17 +370,26 @@ getnext:
(void) strcat(output, rawname); (void) strcat(output, rawname);
canon(output, name); canon(output, name);
} }
expandarg(name, ap); if (glob(name, GLOB_ALTDIRFUNC, NULL, &ap->glob) < 0)
strcpy(name, ap->head->fname); fprintf(stderr, "%s: out of memory\n", ap->cmd);
freename(ap->head->fname); if (ap->glob.gl_pathc == 0)
ap->head++; 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 # undef rawname
} }
/* /*
* Strip off the next token of the input. * Strip off the next token of the input.
*/ */
char * static char *
copynext(input, output) copynext(input, output)
char *input, *output; char *input, *output;
{ {
@ -402,11 +439,11 @@ copynext(input, output)
* Canonicalize file names to always start with ``./'' and * Canonicalize file names to always start with ``./'' and
* remove any imbedded "." and ".." components. * remove any imbedded "." and ".." components.
*/ */
void
canon(rawname, canonname) canon(rawname, canonname)
char *rawname, *canonname; char *rawname, *canonname;
{ {
register char *cp, *np; register char *cp, *np;
int len;
if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0) if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0)
(void) strcpy(canonname, ""); (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 * Do an "ls" style listing of a directory
*/ */
printlist(name, ino, basename) static void
printlist(name, basename)
char *name; char *name;
ino_t ino;
char *basename; char *basename;
{ {
register struct afile *fp; register struct afile *fp, *list, *listp;
register struct direct *dp; register struct direct *dp;
static struct arglist alist = { 0, 0, 0, 0, "ls" };
struct afile single; 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) { if ((dirp = rst_opendir(name)) == NULL) {
single.fnum = ino; entries = 1;
single.fname = savename(name + strlen(basename) + 1); list = &single;
alist.head = &single; mkentry(dp, list);
alist.last = alist.head + 1; len = strlen(basename) + 1;
if (strlen(name) - len > single.len) {
freename(single.fname);
single.fname = savename(&name[len]);
single.len = strlen(single.fname);
}
} else { } 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); fprintf(stderr, "%s:\n", name);
entries = 0;
listp = list;
while (dp = rst_readdir(dirp)) { while (dp = rst_readdir(dirp)) {
if (dp == NULL || dp->d_ino == 0) if (dp == NULL || dp->d_ino == 0)
break; break;
if (!dflag && BIT(dp->d_ino, dumpmap) == 0) if (!dflag && TSTINO(dp->d_ino, dumpmap) == 0)
continue; continue;
if (vflag == 0 && if (vflag == 0 &&
(strcmp(dp->d_name, ".") == 0 || (strcmp(dp->d_name, ".") == 0 ||
strcmp(dp->d_name, "..") == 0)) strcmp(dp->d_name, "..") == 0))
continue; continue;
if (!mkentry(dp->d_name, dp->d_ino, &alist)) mkentry(dp, listp++);
return; 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) { formatf(list, entries);
qsort((char *)alist.head, alist.last - alist.head, if (dirp != NULL) {
sizeof *alist.head, fcmp); for (fp = listp - 1; fp >= list; fp--)
formatf(&alist);
for (fp = alist.head; fp < alist.last; fp++)
freename(fp->fname); freename(fp->fname);
}
if (dirp != NULL)
fprintf(stderr, "\n"); fprintf(stderr, "\n");
free(list);
}
} }
/* /*
* Read the contents of a directory. * Read the contents of a directory.
*/ */
mkentry(name, ino, ap) static void
char *name; mkentry(dp, fp)
ino_t ino; struct direct *dp;
register struct arglist *ap;
{
register struct afile *fp; register struct afile *fp;
{
char *cp;
struct entry *np;
int type;
if (ap->base == NULL) { fp->fnum = dp->d_ino;
ap->nent = 20; fp->fname = savename(dp->d_name);
ap->base = (struct afile *)calloc((unsigned)ap->nent, for (cp = fp->fname; *cp; cp++)
sizeof (struct afile)); if (!vflag && (*cp < ' ' || *cp >= 0177))
if (ap->base == NULL) { *cp = '?';
fprintf(stderr, "%s: out of memory\n", ap->cmd); fp->len = cp - fp->fname;
return (FAIL); 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; return;
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);
} }
/* /*
* Print out a pretty listing of a directory * Print out a pretty listing of a directory
*/ */
formatf(ap) static void
register struct arglist *ap; formatf(list, nentry)
register struct afile *list;
int nentry;
{ {
register struct afile *fp; register struct afile *fp, *endlist;
struct entry *np; int width, bigino, haveprefix, havepostfix;
int width = 0, w, nentry = ap->last - ap->head; int i, j, w, precision, columns, lines;
int i, j, len, columns, lines;
char *cp;
if (ap->head == ap->last) width = 0;
return; haveprefix = 0;
for (fp = ap->head; fp < ap->last; fp++) { havepostfix = 0;
fp->ftype = inodetype(fp->fnum); bigino = ROOTINO;
np = lookupino(fp->fnum); endlist = &list[nentry];
if (np != NIL) for (fp = &list[0]; fp < endlist; fp++) {
fp->fflags = np->e_flags; if (bigino < fp->fnum)
else bigino = fp->fnum;
fp->fflags = 0; if (width < fp->len)
len = strlen(fmtentry(fp)); width = fp->len;
if (len > width) if (fp->prefix != ' ')
width = len; haveprefix = 1;
if (fp->postfix != ' ')
havepostfix = 1;
} }
width += 2; if (haveprefix)
columns = 80 / width; 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) if (columns == 0)
columns = 1; columns = 1;
lines = (nentry + columns - 1) / columns; lines = (nentry + columns - 1) / columns;
for (i = 0; i < lines; i++) { for (i = 0; i < lines; i++) {
for (j = 0; j < columns; j++) { for (j = 0; j < columns; j++) {
fp = ap->head + j * lines + i; fp = &list[j * lines + i];
cp = fmtentry(fp); if (vflag) {
fprintf(stderr, "%s", cp); fprintf(stderr, "%*d ", precision, fp->fnum);
if (fp + lines >= ap->last) { 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"); fprintf(stderr, "\n");
break; break;
} }
w = strlen(cp); for (w = fp->len; w < width; w++)
while (w < width) { putc(' ', stderr);
w++;
fprintf(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) #undef DIRBLKSIZ
register struct afile *f1, *f2; #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 * static int
fmtentry(fp) glob_stat(name, stp)
register struct afile *fp; const char *name;
struct stat *stp;
{ {
static char fmtres[BUFSIZ]; register struct direct *dp;
static int precision = 0;
int i;
register char *cp, *dp;
if (!vflag) { dp = pathsearch(name);
fmtres[0] = '\0'; if (dp == NULL || (!dflag && TSTINO(dp->d_ino, dumpmap) == 0))
} else { return (-1);
if (precision == 0) if (inodetype(dp->d_ino) == NODE)
for (i = maxino; i > 0; i /= 10) stp->st_mode = IFDIR;
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++ = '*';
else else
*dp++ = ' '; stp->st_mode = IFREG;
for (cp = fp->fname; *cp; cp++) return (0);
if (!vflag && (*cp < ' ' || *cp >= 0177)) }
*dp++ = '?';
else /*
*dp++ = *cp; * Comparison routine for qsort.
if (fp->ftype == NODE) */
*dp++ = '/'; static int
*dp++ = 0; fcmp(f1, f2)
return (fmtres); register const void *f1, *f2;
{
return (strcmp(((struct afile *)f1)->fname,
((struct afile *)f2)->fname));
} }
/* /*
* respond to interrupts * respond to interrupts
*/ */
void void
onintr() onintr(signo)
int signo;
{ {
if (command == 'i') if (command == 'i' && runshell)
longjmp(reset, 1); longjmp(reset, 1);
if (reply("restore interrupted, continue") == FAIL) if (reply("restore interrupted, continue") == FAIL)
done(1); done(1);

View File

@ -38,32 +38,26 @@ char copyright[] =
#endif /* not lint */ #endif /* not lint */
#ifndef lint #ifndef lint
/*static char sccsid[] = "from: @(#)main.c 5.8 (Berkeley) 6/1/90";*/ /* from: static char sccsid[] = "@(#)main.c 5.11 (Berkeley) 10/16/92"; */
static char rcsid[] = "$Id: main.c,v 1.2 1993/08/01 18:25:18 mycroft Exp $"; static char *rcsid = "$Id: main.c,v 1.3 1993/12/22 10:31:52 cgd Exp $";
#endif /* not lint */ #endif /* not lint */
/* #include <sys/param.h>
* Modified to recursively extract all files within a subtree #include <sys/time.h>
* (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 "restore.h" #include <ufs/fs.h>
#include <ufs/dinode.h>
#include <protocols/dumprestore.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 "pathnames.h"
#include "restore.h"
#include "extern.h"
int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0; int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
int hflag = 1, mflag = 1, Nflag = 0; int hflag = 1, mflag = 1, Nflag = 0;
@ -78,126 +72,99 @@ time_t dumptime;
time_t dumpdate; time_t dumpdate;
FILE *terminal; FILE *terminal;
static void obsolete __P((int *, char **[]));
static void usage __P((void));
int
main(argc, argv) main(argc, argv)
int argc; int argc;
char *argv[]; char *argv[];
{ {
register char *cp; int ch;
ino_t ino; ino_t ino;
char *inputdev = _PATH_DEFTAPE; char *inputdev = _PATH_DEFTAPE;
char *symtbl = "./restoresymtable"; char *symtbl = "./restoresymtable";
char name[MAXPATHLEN]; char *p, name[MAXPATHLEN];
void onintr();
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) if (signal(SIGINT, onintr) == SIG_IGN)
(void) signal(SIGINT, SIG_IGN); (void) signal(SIGINT, SIG_IGN);
if (signal(SIGTERM, onintr) == SIG_IGN) if (signal(SIGTERM, onintr) == SIG_IGN)
(void) signal(SIGTERM, SIG_IGN); (void) signal(SIGTERM, SIG_IGN);
setlinebuf(stderr); 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); setinput(inputdev);
if (argc == 0) { if (argc == 0) {
argc = 1; argc = 1;
*--argv = "."; *--argv = ".";
} }
switch (command) { switch (command) {
/* /*
* Interactive mode. * Interactive mode.
@ -205,9 +172,9 @@ usage:
case 'i': case 'i':
setup(); setup();
extractdirs(1); extractdirs(1);
initsymtable((char *)0); initsymtable(NULL);
runcmdshell(); runcmdshell();
done(0); break;
/* /*
* Incremental restoration of a file system. * Incremental restoration of a file system.
*/ */
@ -237,14 +204,14 @@ usage:
} }
createleaves(symtbl); createleaves(symtbl);
createlinks(); createlinks();
setdirmodes(); setdirmodes(FORCE);
checkrestore(); checkrestore();
if (dflag) { if (dflag) {
vprintf(stdout, "Verify the directory structure\n"); vprintf(stdout, "Verify the directory structure\n");
treescan(".", ROOTINO, verifyfile); treescan(".", ROOTINO, verifyfile);
} }
dumpsymtable(symtbl, (long)1); dumpsymtable(symtbl, (long)1);
done(0); break;
/* /*
* Resume an incremental file system restoration. * Resume an incremental file system restoration.
*/ */
@ -254,10 +221,10 @@ usage:
skipdirs(); skipdirs();
createleaves(symtbl); createleaves(symtbl);
createlinks(); createlinks();
setdirmodes(); setdirmodes(FORCE);
checkrestore(); checkrestore();
dumpsymtable(symtbl, (long)1); dumpsymtable(symtbl, (long)1);
done(0); break;
/* /*
* List contents of tape. * List contents of tape.
*/ */
@ -272,7 +239,7 @@ usage:
continue; continue;
treescan(name, ino, listfile); treescan(name, ino, listfile);
} }
done(0); break;
/* /*
* Batch extraction of tape contents. * Batch extraction of tape contents.
*/ */
@ -291,9 +258,93 @@ usage:
} }
createfiles(); createfiles();
createlinks(); createlinks();
setdirmodes(); setdirmodes(0);
if (dflag) if (dflag)
checkrestore(); 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 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.\" from: @(#)restore.8 6.10 (Berkeley) 7/23/91 .\" from: @(#)restore.8 6.11 (Berkeley) 8/28/91
.\" $Id: restore.8,v 1.3 1993/10/05 00:12:10 jtc Exp $ .\" $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 .Dt RESTORE 8
.Os BSD 4 .Os BSD 4
.Sh NAME .Sh NAME
@ -53,9 +53,10 @@ Single files and
directory subtrees may be restored from full or partial directory subtrees may be restored from full or partial
backups. backups.
.Nm Restore .Nm Restore
cannot work across a network, to do this, see the companion works across a network;
command to do this see the
.Xr rrestore . .Fl f
flag described below.
The actions The actions
of of
.Nm restore .Nm restore
@ -247,6 +248,11 @@ The next argument to
is used as the name of the archive instead is used as the name of the archive instead
of of
.Pa /dev/rmt? . .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 If the name of the file is
.Ql Fl , .Ql Fl ,
.Nm restore .Nm restore
@ -377,11 +383,11 @@ owner, mode, and time stamps for directories.
information passed between incremental restores. information passed between incremental restores.
.El .El
.Sh SEE ALSO .Sh SEE ALSO
.Xr rrestore 8 ,
.Xr dump 8 , .Xr dump 8 ,
.Xr newfs 8 , .Xr newfs 8 ,
.Xr mount 8 , .Xr mount 8 ,
.Xr mkfs 8 .Xr mkfs 8 ,
.Xr rmt 8
.Sh BUGS .Sh BUGS
.Nm Restore .Nm Restore
can get confused when doing incremental restores from can get confused when doing incremental restores from

View File

@ -32,11 +32,24 @@
*/ */
#ifndef lint #ifndef lint
/*static char sccsid[] = "from: @(#)restore.c 5.7 (Berkeley) 6/1/90";*/ /* from: static char sccsid[] = "@(#)restore.c 5.11 (Berkeley) 10/16/92"; */
static char rcsid[] = "$Id: restore.c,v 1.2 1993/08/01 18:25:16 mycroft Exp $"; static char *rcsid = "$Id: restore.c,v 1.3 1993/12/22 10:32:04 cgd Exp $";
#endif /* not lint */ #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 "restore.h"
#include "extern.h"
static char *keyval __P((int));
/* /*
* This implements the 't' option. * This implements the 't' option.
@ -50,9 +63,8 @@ listfile(name, ino, type)
{ {
long descend = hflag ? GOOD : FAIL; long descend = hflag ? GOOD : FAIL;
if (BIT(ino, dumpmap) == 0) { if (TSTINO(ino, dumpmap) == 0)
return (descend); return (descend);
}
vprintf(stdout, "%s", type == LEAF ? "leaf" : "dir "); vprintf(stdout, "%s", type == LEAF ? "leaf" : "dir ");
fprintf(stdout, "%10d\t%s\n", ino, name); fprintf(stdout, "%10d\t%s\n", ino, name);
return (descend); return (descend);
@ -72,7 +84,7 @@ addfile(name, ino, type)
long descend = hflag ? GOOD : FAIL; long descend = hflag ? GOOD : FAIL;
char buf[100]; char buf[100];
if (BIT(ino, dumpmap) == 0) { if (TSTINO(ino, dumpmap) == 0) {
dprintf(stdout, "%s: not on the tape\n", name); dprintf(stdout, "%s: not on the tape\n", name);
return (descend); return (descend);
} }
@ -85,7 +97,7 @@ addfile(name, ino, type)
} }
} }
ep = lookupino(ino); ep = lookupino(ino);
if (ep != NIL) { if (ep != NULL) {
if (strcmp(name, myname(ep)) == 0) { if (strcmp(name, myname(ep)) == 0) {
ep->e_flags |= NEW; ep->e_flags |= NEW;
return (descend); return (descend);
@ -113,11 +125,10 @@ deletefile(name, ino, type)
long descend = hflag ? GOOD : FAIL; long descend = hflag ? GOOD : FAIL;
struct entry *ep; struct entry *ep;
if (BIT(ino, dumpmap) == 0) { if (TSTINO(ino, dumpmap) == 0)
return (descend); return (descend);
}
ep = lookupino(ino); ep = lookupino(ino);
if (ep != NIL) if (ep != NULL)
ep->e_flags &= ~NEW; ep->e_flags &= ~NEW;
return (descend); return (descend);
} }
@ -141,6 +152,7 @@ static struct entry *removelist;
* Remove unneeded leaves from the old tree. * Remove unneeded leaves from the old tree.
* Remove directories from the lookup chains. * Remove directories from the lookup chains.
*/ */
void
removeoldleaves() removeoldleaves()
{ {
register struct entry *ep; register struct entry *ep;
@ -149,11 +161,11 @@ removeoldleaves()
vprintf(stdout, "Mark entries to be removed.\n"); vprintf(stdout, "Mark entries to be removed.\n");
for (i = ROOTINO + 1; i < maxino; i++) { for (i = ROOTINO + 1; i < maxino; i++) {
ep = lookupino(i); ep = lookupino(i);
if (ep == NIL) if (ep == NULL)
continue; continue;
if (BIT(i, clrimap)) if (TSTINO(i, clrimap))
continue; continue;
for ( ; ep != NIL; ep = ep->e_links) { for ( ; ep != NULL; ep = ep->e_links) {
dprintf(stdout, "%s: REMOVE\n", myname(ep)); dprintf(stdout, "%s: REMOVE\n", myname(ep));
if (ep->e_type == LEAF) { if (ep->e_type == LEAF) {
removeleaf(ep); removeleaf(ep);
@ -192,7 +204,6 @@ nodeupdates(name, ino, type)
# define INOFND 0x2 /* inode already exists */ # define INOFND 0x2 /* inode already exists */
# define NAMEFND 0x4 /* name already exists */ # define NAMEFND 0x4 /* name already exists */
# define MODECHG 0x8 /* mode of inode changed */ # define MODECHG 0x8 /* mode of inode changed */
extern char *keyval();
/* /*
* This routine is called once for each element in the * 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. * Check to see if the file is on the tape.
*/ */
if (BIT(ino, dumpmap)) if (TSTINO(ino, dumpmap))
key |= ONTAPE; key |= ONTAPE;
/* /*
* Check to see if the name exists, and if the name is a link. * Check to see if the name exists, and if the name is a link.
*/ */
np = lookupname(name); np = lookupname(name);
if (np != NIL) { if (np != NULL) {
key |= NAMEFND; key |= NAMEFND;
ip = lookupino(np->e_ino); ip = lookupino(np->e_ino);
if (ip == NULL) if (ip == NULL)
@ -221,9 +232,9 @@ nodeupdates(name, ino, type)
* corresponds to the name (if one was found). * corresponds to the name (if one was found).
*/ */
ip = lookupino(ino); ip = lookupino(ino);
if (ip != NIL) { if (ip != NULL) {
key |= INOFND; 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) { if (ep == np) {
ip = ep; ip = ep;
break; break;
@ -252,7 +263,7 @@ nodeupdates(name, ino, type)
myname(np)); myname(np));
mktempname(np); mktempname(np);
} }
np = NIL; np = NULL;
key &= ~NAMEFND; key &= ~NAMEFND;
} }
if ((key & ONTAPE) && if ((key & ONTAPE) &&
@ -354,9 +365,22 @@ nodeupdates(name, ino, type)
break; 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: 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) if (type == LEAF && lookuptype != LINK)
np->e_flags |= EXTRACT; np->e_flags |= EXTRACT;
np->e_flags |= KEEP; 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 * for it, we discard the name knowing that it will be on the
* next incremental tape. * next incremental tape.
*/ */
case NIL: case NULL:
fprintf(stderr, "%s: (inode %d) not found on tape\n", fprintf(stderr, "%s: (inode %d) not found on tape\n",
name, ino); name, ino);
break; break;
@ -450,7 +474,7 @@ nodeupdates(name, ino, type)
/* /*
* Calculate the active flags in a key. * Calculate the active flags in a key.
*/ */
char * static char *
keyval(key) keyval(key)
int key; int key;
{ {
@ -472,6 +496,7 @@ keyval(key)
/* /*
* Find unreferenced link names. * Find unreferenced link names.
*/ */
void
findunreflinks() findunreflinks()
{ {
register struct entry *ep, *np; register struct entry *ep, *np;
@ -480,9 +505,9 @@ findunreflinks()
vprintf(stdout, "Find unreferenced names.\n"); vprintf(stdout, "Find unreferenced names.\n");
for (i = ROOTINO; i < maxino; i++) { for (i = ROOTINO; i < maxino; i++) {
ep = lookupino(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; 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) { if (np->e_flags == 0) {
dprintf(stdout, dprintf(stdout,
"%s: remove unreferenced name\n", "%s: remove unreferenced name\n",
@ -495,8 +520,8 @@ findunreflinks()
/* /*
* Any leaves remaining in removed directories is unreferenced. * Any leaves remaining in removed directories is unreferenced.
*/ */
for (ep = removelist; ep != NIL; ep = ep->e_next) { for (ep = removelist; ep != NULL; ep = ep->e_next) {
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_type == LEAF) { if (np->e_type == LEAF) {
if (np->e_flags != 0) if (np->e_flags != 0)
badentry(np, "unreferenced with flags"); badentry(np, "unreferenced with flags");
@ -519,6 +544,7 @@ findunreflinks()
* topologically sorted, the deletion could be done in * topologically sorted, the deletion could be done in
* time O(N). * time O(N).
*/ */
void
removeoldnodes() removeoldnodes()
{ {
register struct entry *ep, **prev; register struct entry *ep, **prev;
@ -528,8 +554,8 @@ removeoldnodes()
do { do {
change = 0; change = 0;
prev = &removelist; prev = &removelist;
for (ep = removelist; ep != NIL; ep = *prev) { for (ep = removelist; ep != NULL; ep = *prev) {
if (ep->e_entries != NIL) { if (ep->e_entries != NULL) {
prev = &ep->e_next; prev = &ep->e_next;
continue; continue;
} }
@ -539,7 +565,7 @@ removeoldnodes()
change++; change++;
} }
} while (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"); badentry(ep, "cannot remove, non-empty");
} }
@ -547,6 +573,7 @@ removeoldnodes()
* This is the routine used to extract files for the 'r' command. * This is the routine used to extract files for the 'r' command.
* Extract new leaves. * Extract new leaves.
*/ */
void
createleaves(symtabfile) createleaves(symtabfile)
char *symtabfile; char *symtabfile;
{ {
@ -573,7 +600,7 @@ createleaves(symtabfile)
*/ */
while (first < curfile.ino) { while (first < curfile.ino) {
ep = lookupino(first); ep = lookupino(first);
if (ep == NIL) if (ep == NULL)
panic("%d: bad first\n", first); panic("%d: bad first\n", first);
fprintf(stderr, "%s: not found on tape\n", myname(ep)); fprintf(stderr, "%s: not found on tape\n", myname(ep));
ep->e_flags &= ~(NEW|EXTRACT); ep->e_flags &= ~(NEW|EXTRACT);
@ -593,7 +620,7 @@ createleaves(symtabfile)
goto next; goto next;
} }
ep = lookupino(curfile.ino); ep = lookupino(curfile.ino);
if (ep == NIL) if (ep == NULL)
panic("unknown file on tape\n"); panic("unknown file on tape\n");
if ((ep->e_flags & (NEW|EXTRACT)) == 0) if ((ep->e_flags & (NEW|EXTRACT)) == 0)
badentry(ep, "unexpected file on tape"); 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. * This is the routine used to extract files for the 'x' and 'i' commands.
* Efficiently extract a subset of the files on a tape. * Efficiently extract a subset of the files on a tape.
*/ */
void
createfiles() createfiles()
{ {
register ino_t first, next, last; register ino_t first, next, last;
@ -688,7 +716,7 @@ createfiles()
*/ */
while (next < curfile.ino) { while (next < curfile.ino) {
ep = lookupino(next); ep = lookupino(next);
if (ep == NIL) if (ep == NULL)
panic("corrupted symbol table\n"); panic("corrupted symbol table\n");
fprintf(stderr, "%s: not found on tape\n", myname(ep)); fprintf(stderr, "%s: not found on tape\n", myname(ep));
ep->e_flags &= ~NEW; ep->e_flags &= ~NEW;
@ -700,7 +728,7 @@ createfiles()
*/ */
if (next == curfile.ino && next <= last) { if (next == curfile.ino && next <= last) {
ep = lookupino(next); ep = lookupino(next);
if (ep == NIL) if (ep == NULL)
panic("corrupted symbol table\n"); panic("corrupted symbol table\n");
(void) extractfile(myname(ep)); (void) extractfile(myname(ep));
ep->e_flags &= ~NEW; ep->e_flags &= ~NEW;
@ -713,6 +741,7 @@ createfiles()
/* /*
* Add links. * Add links.
*/ */
void
createlinks() createlinks()
{ {
register struct entry *np, *ep; register struct entry *np, *ep;
@ -722,9 +751,9 @@ createlinks()
vprintf(stdout, "Add links\n"); vprintf(stdout, "Add links\n");
for (i = ROOTINO; i < maxino; i++) { for (i = ROOTINO; i < maxino; i++) {
ep = lookupino(i); ep = lookupino(i);
if (ep == NIL) if (ep == NULL)
continue; 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) if ((np->e_flags & NEW) == 0)
continue; continue;
(void) strcpy(name, myname(ep)); (void) strcpy(name, myname(ep));
@ -743,6 +772,7 @@ createlinks()
* We do this to insure that all the requested work was done, and * We do this to insure that all the requested work was done, and
* that no temporary names remain. * that no temporary names remain.
*/ */
void
checkrestore() checkrestore()
{ {
register struct entry *ep; register struct entry *ep;
@ -750,7 +780,7 @@ checkrestore()
vprintf(stdout, "Check the symbol table.\n"); vprintf(stdout, "Check the symbol table.\n");
for (i = ROOTINO; i < maxino; i++) { 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; ep->e_flags &= ~KEEP;
if (ep->e_type == NODE) if (ep->e_type == NODE)
ep->e_flags &= ~(NEW|EXISTED); ep->e_flags &= ~(NEW|EXISTED);
@ -774,17 +804,17 @@ verifyfile(name, ino, type)
long descend = GOOD; long descend = GOOD;
ep = lookupname(name); ep = lookupname(name);
if (ep == NIL) { if (ep == NULL) {
fprintf(stderr, "Warning: missing name %s\n", name); fprintf(stderr, "Warning: missing name %s\n", name);
return (FAIL); return (FAIL);
} }
np = lookupino(ino); np = lookupino(ino);
if (np != ep) if (np != ep)
descend = FAIL; descend = FAIL;
for ( ; np != NIL; np = np->e_links) for ( ; np != NULL; np = np->e_links)
if (np == ep) if (np == ep)
break; break;
if (np == NIL) if (np == NULL)
panic("missing inumber %d\n", ino); panic("missing inumber %d\n", ino);
if (ep->e_type == LEAF && type != LEAF) if (ep->e_type == LEAF && type != LEAF)
badentry(ep, "type should be 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 #ifndef lint
/*static char sccsid[] = "from: @(#)symtab.c 5.5 (Berkeley) 6/1/90";*/ /* from: static char sccsid[] = "@(#)symtab.c 5.7 (Berkeley) 10/16/92"; */
static char rcsid[] = "$Id: symtab.c,v 1.2 1993/08/01 18:25:14 mycroft Exp $"; static char *rcsid = "$Id: symtab.c,v 1.3 1993/12/22 10:32:10 cgd Exp $";
#endif /* not lint */ #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". * are needed, by calling "myname".
*/ */
#include "restore.h" #include <sys/param.h>
#include <sys/stat.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. * 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 struct entry **entry;
static long entrytblsize; 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 * Look up an entry by inode number
*/ */
@ -70,16 +86,17 @@ lookupino(inum)
register struct entry *ep; register struct entry *ep;
if (inum < ROOTINO || inum >= maxino) if (inum < ROOTINO || inum >= maxino)
return (NIL); return (NULL);
for (ep = entry[inum % entrytblsize]; ep != NIL; ep = ep->e_next) for (ep = entry[inum % entrytblsize]; ep != NULL; ep = ep->e_next)
if (ep->e_ino == inum) if (ep->e_ino == inum)
return (ep); return (ep);
return (NIL); return (NULL);
} }
/* /*
* Add an entry into the entry table * Add an entry into the entry table
*/ */
static void
addino(inum, np) addino(inum, np)
ino_t inum; ino_t inum;
struct entry *np; struct entry *np;
@ -93,7 +110,7 @@ addino(inum, np)
np->e_next = *epp; np->e_next = *epp;
*epp = np; *epp = np;
if (dflag) 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) if (np->e_ino == inum)
badentry(np, "duplicate inum"); badentry(np, "duplicate inum");
} }
@ -101,6 +118,7 @@ addino(inum, np)
/* /*
* Delete an entry from the entry table * Delete an entry from the entry table
*/ */
void
deleteino(inum) deleteino(inum)
ino_t inum; ino_t inum;
{ {
@ -110,7 +128,7 @@ deleteino(inum)
if (inum < ROOTINO || inum >= maxino) if (inum < ROOTINO || inum >= maxino)
panic("deleteino: out of range %d\n", inum); panic("deleteino: out of range %d\n", inum);
prev = &entry[inum % entrytblsize]; 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) { if (next->e_ino == inum) {
next->e_ino = 0; next->e_ino = 0;
*prev = next->e_next; *prev = next->e_next;
@ -133,25 +151,25 @@ lookupname(name)
char buf[MAXPATHLEN]; char buf[MAXPATHLEN];
cp = name; 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'; ) for (np = buf; *cp != '/' && *cp != '\0'; )
*np++ = *cp++; *np++ = *cp++;
*np = '\0'; *np = '\0';
for ( ; ep != NIL; ep = ep->e_sibling) for ( ; ep != NULL; ep = ep->e_sibling)
if (strcmp(ep->e_name, buf) == 0) if (strcmp(ep->e_name, buf) == 0)
break; break;
if (ep == NIL) if (ep == NULL)
break; break;
if (*cp++ == '\0') if (*cp++ == '\0')
return (ep); return (ep);
} }
return (NIL); return (NULL);
} }
/* /*
* Look up the parent of a pathname * Look up the parent of a pathname
*/ */
struct entry * static struct entry *
lookupparent(name) lookupparent(name)
char *name; char *name;
{ {
@ -160,12 +178,12 @@ lookupparent(name)
tailindex = rindex(name, '/'); tailindex = rindex(name, '/');
if (tailindex == 0) if (tailindex == 0)
return (NIL); return (NULL);
*tailindex = '\0'; *tailindex = '\0';
ep = lookupname(name); ep = lookupname(name);
*tailindex = '/'; *tailindex = '/';
if (ep == NIL) if (ep == NULL)
return (NIL); return (NULL);
if (ep->e_type != NODE) if (ep->e_type != NODE)
panic("%s is not a directory\n", name); panic("%s is not a directory\n", name);
return (ep); return (ep);
@ -197,7 +215,7 @@ myname(ep)
* Unused symbol table entries are linked together on a freelist * Unused symbol table entries are linked together on a freelist
* headed by the following pointer. * headed by the following pointer.
*/ */
static struct entry *freelist = NIL; static struct entry *freelist = NULL;
/* /*
* add an entry to the symbol table * add an entry to the symbol table
@ -210,19 +228,19 @@ addentry(name, inum, type)
{ {
register struct entry *np, *ep; register struct entry *np, *ep;
if (freelist != NIL) { if (freelist != NULL) {
np = freelist; np = freelist;
freelist = np->e_next; freelist = np->e_next;
bzero((char *)np, (long)sizeof(struct entry)); bzero((char *)np, (long)sizeof(struct entry));
} else { } else {
np = (struct entry *)calloc(1, sizeof(struct entry)); np = (struct entry *)calloc(1, sizeof(struct entry));
if (np == NIL) if (np == NULL)
panic("no memory to extend symbol table\n"); panic("no memory to extend symbol table\n");
} }
np->e_type = type & ~LINK; np->e_type = type & ~LINK;
ep = lookupparent(name); ep = lookupparent(name);
if (ep == NIL) { if (ep == NULL) {
if (inum != ROOTINO || lookupino(ROOTINO) != NIL) if (inum != ROOTINO || lookupino(ROOTINO) != NULL)
panic("bad name to addentry %s\n", name); panic("bad name to addentry %s\n", name);
np->e_name = savename(name); np->e_name = savename(name);
np->e_namlen = strlen(name); np->e_namlen = strlen(name);
@ -237,13 +255,13 @@ addentry(name, inum, type)
ep->e_entries = np; ep->e_entries = np;
if (type & LINK) { if (type & LINK) {
ep = lookupino(inum); ep = lookupino(inum);
if (ep == NIL) if (ep == NULL)
panic("link to non-existant name\n"); panic("link to non-existant name\n");
np->e_ino = inum; np->e_ino = inum;
np->e_links = ep->e_links; np->e_links = ep->e_links;
ep->e_links = np; ep->e_links = np;
} else if (inum != 0) { } else if (inum != 0) {
if (lookupino(inum) != NIL) if (lookupino(inum) != NULL)
panic("duplicate entry\n"); panic("duplicate entry\n");
addino(inum, np); addino(inum, np);
} }
@ -253,6 +271,7 @@ addentry(name, inum, type)
/* /*
* delete an entry from the symbol table * delete an entry from the symbol table
*/ */
void
freeentry(ep) freeentry(ep)
register struct entry *ep; register struct entry *ep;
{ {
@ -262,28 +281,28 @@ freeentry(ep)
if (ep->e_flags != REMOVED) if (ep->e_flags != REMOVED)
badentry(ep, "not marked REMOVED"); badentry(ep, "not marked REMOVED");
if (ep->e_type == NODE) { if (ep->e_type == NODE) {
if (ep->e_links != NIL) if (ep->e_links != NULL)
badentry(ep, "freeing referenced directory"); badentry(ep, "freeing referenced directory");
if (ep->e_entries != NIL) if (ep->e_entries != NULL)
badentry(ep, "freeing non-empty directory"); badentry(ep, "freeing non-empty directory");
} }
if (ep->e_ino != 0) { if (ep->e_ino != 0) {
np = lookupino(ep->e_ino); np = lookupino(ep->e_ino);
if (np == NIL) if (np == NULL)
badentry(ep, "lookupino failed"); badentry(ep, "lookupino failed");
if (np == ep) { if (np == ep) {
inum = ep->e_ino; inum = ep->e_ino;
deleteino(inum); deleteino(inum);
if (ep->e_links != NIL) if (ep->e_links != NULL)
addino(inum, ep->e_links); addino(inum, ep->e_links);
} else { } else {
for (; np != NIL; np = np->e_links) { for (; np != NULL; np = np->e_links) {
if (np->e_links == ep) { if (np->e_links == ep) {
np->e_links = ep->e_links; np->e_links = ep->e_links;
break; break;
} }
} }
if (np == NIL) if (np == NULL)
badentry(ep, "link not found"); badentry(ep, "link not found");
} }
} }
@ -296,6 +315,7 @@ freeentry(ep)
/* /*
* Relocate an entry in the tree structure * Relocate an entry in the tree structure
*/ */
void
moveentry(ep, newname) moveentry(ep, newname)
register struct entry *ep; register struct entry *ep;
char *newname; char *newname;
@ -304,7 +324,7 @@ moveentry(ep, newname)
char *cp; char *cp;
np = lookupparent(newname); np = lookupparent(newname);
if (np == NIL) if (np == NULL)
badentry(ep, "cannot move ROOT"); badentry(ep, "cannot move ROOT");
if (np != ep->e_parent) { if (np != ep->e_parent) {
removeentry(ep); removeentry(ep);
@ -325,6 +345,7 @@ moveentry(ep, newname)
/* /*
* Remove an entry in the tree structure * Remove an entry in the tree structure
*/ */
static void
removeentry(ep) removeentry(ep)
register struct entry *ep; register struct entry *ep;
{ {
@ -334,13 +355,13 @@ removeentry(ep)
if (np->e_entries == ep) { if (np->e_entries == ep) {
np->e_entries = ep->e_sibling; np->e_entries = ep->e_sibling;
} else { } 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) { if (np->e_sibling == ep) {
np->e_sibling = ep->e_sibling; np->e_sibling = ep->e_sibling;
break; break;
} }
} }
if (np == NIL) if (np == NULL)
badentry(ep, "cannot find entry in parent list"); badentry(ep, "cannot find entry in parent list");
} }
} }
@ -364,7 +385,7 @@ struct strhdr {
#define STRTBLINCR (sizeof(struct strhdr)) #define STRTBLINCR (sizeof(struct strhdr))
#define allocsize(size) (((size) + 1 + STRTBLINCR - 1) & ~(STRTBLINCR - 1)) #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 * 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 * Free space for a name. The resulting entry is linked onto the
* appropriate free list. * appropriate free list.
*/ */
void
freename(name) freename(name)
char *name; char *name;
{ {
@ -425,6 +447,7 @@ struct symtableheader {
/* /*
* dump a snapshot of the symbol table * dump a snapshot of the symbol table
*/ */
void
dumpsymtable(filename, checkpt) dumpsymtable(filename, checkpt)
char *filename; char *filename;
long checkpt; long checkpt;
@ -440,7 +463,7 @@ dumpsymtable(filename, checkpt)
if (Nflag) if (Nflag)
return; return;
if ((fd = fopen(filename, "w")) == NULL) { 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", panic("cannot create save file %s for symbol table\n",
filename); filename);
} }
@ -450,7 +473,7 @@ dumpsymtable(filename, checkpt)
* Write out the string entries * Write out the string entries
*/ */
for (i = ROOTINO; i < maxino; i++) { 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++; ep->e_index = mynum++;
(void) fwrite(ep->e_name, sizeof(char), (void) fwrite(ep->e_name, sizeof(char),
(int)allocsize(ep->e_namlen), fd); (int)allocsize(ep->e_namlen), fd);
@ -462,22 +485,22 @@ dumpsymtable(filename, checkpt)
tep = &temp; tep = &temp;
stroff = 0; stroff = 0;
for (i = ROOTINO; i < maxino; i++) { 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, bcopy((char *)ep, (char *)tep,
(long)sizeof(struct entry)); (long)sizeof(struct entry));
tep->e_name = (char *)stroff; tep->e_name = (char *)stroff;
stroff += allocsize(ep->e_namlen); stroff += allocsize(ep->e_namlen);
tep->e_parent = (struct entry *)ep->e_parent->e_index; tep->e_parent = (struct entry *)ep->e_parent->e_index;
if (ep->e_links != NIL) if (ep->e_links != NULL)
tep->e_links = tep->e_links =
(struct entry *)ep->e_links->e_index; (struct entry *)ep->e_links->e_index;
if (ep->e_sibling != NIL) if (ep->e_sibling != NULL)
tep->e_sibling = tep->e_sibling =
(struct entry *)ep->e_sibling->e_index; (struct entry *)ep->e_sibling->e_index;
if (ep->e_entries != NIL) if (ep->e_entries != NULL)
tep->e_entries = tep->e_entries =
(struct entry *)ep->e_entries->e_index; (struct entry *)ep->e_entries->e_index;
if (ep->e_next != NIL) if (ep->e_next != NULL)
tep->e_next = tep->e_next =
(struct entry *)ep->e_next->e_index; (struct entry *)ep->e_next->e_index;
(void) fwrite((char *)tep, sizeof(struct entry), 1, fd); (void) fwrite((char *)tep, sizeof(struct entry), 1, fd);
@ -487,8 +510,8 @@ dumpsymtable(filename, checkpt)
* Convert entry pointers to indexes, and output * Convert entry pointers to indexes, and output
*/ */
for (i = 0; i < entrytblsize; i++) { for (i = 0; i < entrytblsize; i++) {
if (entry[i] == NIL) if (entry[i] == NULL)
tentry = NIL; tentry = NULL;
else else
tentry = (struct entry *)entry[i]->e_index; tentry = (struct entry *)entry[i]->e_index;
(void) fwrite((char *)&tentry, sizeof(struct entry *), 1, fd); (void) fwrite((char *)&tentry, sizeof(struct entry *), 1, fd);
@ -502,7 +525,7 @@ dumpsymtable(filename, checkpt)
hdr.ntrec = ntrec; hdr.ntrec = ntrec;
(void) fwrite((char *)&hdr, sizeof(struct symtableheader), 1, fd); (void) fwrite((char *)&hdr, sizeof(struct symtableheader), 1, fd);
if (ferror(fd)) { if (ferror(fd)) {
perror("fwrite"); fprintf(stderr, "fwrite: %s\n", strerror(errno));
panic("output error to file %s writing symbol table\n", panic("output error to file %s writing symbol table\n",
filename); filename);
} }
@ -512,6 +535,7 @@ dumpsymtable(filename, checkpt)
/* /*
* Initialize a symbol table from a file * Initialize a symbol table from a file
*/ */
void
initsymtable(filename) initsymtable(filename)
char *filename; char *filename;
{ {
@ -529,18 +553,18 @@ initsymtable(filename)
entrytblsize = maxino / HASHFACTOR; entrytblsize = maxino / HASHFACTOR;
entry = (struct entry **) entry = (struct entry **)
calloc((unsigned)entrytblsize, sizeof(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"); panic("no memory for entry table\n");
ep = addentry(".", ROOTINO, NODE); ep = addentry(".", ROOTINO, NODE);
ep->e_flags |= NEW; ep->e_flags |= NEW;
return; return;
} }
if ((fd = open(filename, 0)) < 0) { if ((fd = open(filename, O_RDONLY, 0)) < 0) {
perror("open"); fprintf(stderr, "open: %s\n", strerror(errno));
panic("cannot open symbol table file %s\n", filename); panic("cannot open symbol table file %s\n", filename);
} }
if (fstat(fd, &stbuf) < 0) { if (fstat(fd, &stbuf) < 0) {
perror("stat"); fprintf(stderr, "stat: %s\n", strerror(errno));
panic("cannot stat symbol table file %s\n", filename); panic("cannot stat symbol table file %s\n", filename);
} }
tblsize = stbuf.st_size - sizeof(struct symtableheader); tblsize = stbuf.st_size - sizeof(struct symtableheader);
@ -549,7 +573,7 @@ initsymtable(filename)
panic("cannot allocate space for symbol table\n"); panic("cannot allocate space for symbol table\n");
if (read(fd, base, (int)tblsize) < 0 || if (read(fd, base, (int)tblsize) < 0 ||
read(fd, (char *)&hdr, sizeof(struct symtableheader)) < 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); panic("cannot read symbol table file %s\n", filename);
} }
switch (command) { switch (command) {
@ -588,20 +612,20 @@ initsymtable(filename)
baseep = (struct entry *)(base + hdr.stringsize - sizeof(struct entry)); baseep = (struct entry *)(base + hdr.stringsize - sizeof(struct entry));
lep = (struct entry *)entry; lep = (struct entry *)entry;
for (i = 0; i < entrytblsize; i++) { for (i = 0; i < entrytblsize; i++) {
if (entry[i] == NIL) if (entry[i] == NULL)
continue; continue;
entry[i] = &baseep[(long)entry[i]]; entry[i] = &baseep[(long)entry[i]];
} }
for (ep = &baseep[1]; ep < lep; ep++) { for (ep = &baseep[1]; ep < lep; ep++) {
ep->e_name = base + (long)ep->e_name; ep->e_name = base + (long)ep->e_name;
ep->e_parent = &baseep[(long)ep->e_parent]; 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]; 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]; 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]; 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]; 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 #ifndef lint
/*static char sccsid[] = "from: @(#)utilities.c 5.6 (Berkeley) 6/1/90";*/ /* from: static char sccsid[] = "@(#)utilities.c 5.10 (Berkeley) 12/2/92"; */
static char rcsid[] = "$Id: utilities.c,v 1.2 1993/08/01 18:25:08 mycroft Exp $"; static char *rcsid = "$Id: utilities.c,v 1.3 1993/12/22 10:32:18 cgd Exp $";
#endif /* not lint */ #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 "restore.h"
#include "extern.h"
/* /*
* Insure that all the components of a pathname exist. * Insure that all the components of a pathname exist.
*/ */
void
pathcheck(name) pathcheck(name)
char *name; char *name;
{ {
@ -56,8 +71,8 @@ pathcheck(name)
continue; continue;
*cp = '\0'; *cp = '\0';
ep = lookupname(name); ep = lookupname(name);
if (ep == NIL) { if (ep == NULL) {
ep = addentry(name, psearch(name), NODE); ep = addentry(name, pathsearch(name)->d_ino, NODE);
newnode(ep); newnode(ep);
} }
ep->e_flags |= NEW|KEEP; ep->e_flags |= NEW|KEEP;
@ -68,6 +83,7 @@ pathcheck(name)
/* /*
* Change a name to a unique temporary name. * Change a name to a unique temporary name.
*/ */
void
mktempname(ep) mktempname(ep)
register struct entry *ep; register struct entry *ep;
{ {
@ -94,9 +110,10 @@ gentempname(ep)
struct entry *np; struct entry *np;
long i = 0; 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++; i++;
if (np == NIL) if (np == NULL)
badentry(ep, "not on ino list"); badentry(ep, "not on ino list");
(void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino); (void) sprintf(name, "%s%d%d", TMPHDR, i, ep->e_ino);
return (name); return (name);
@ -105,13 +122,13 @@ gentempname(ep)
/* /*
* Rename a file or directory. * Rename a file or directory.
*/ */
void
renameit(from, to) renameit(from, to)
char *from, *to; char *from, *to;
{ {
if (!Nflag && rename(from, to) < 0) { if (!Nflag && rename(from, to) < 0) {
fprintf(stderr, "Warning: cannot rename %s to %s", from, to); fprintf(stderr, "warning: cannot rename %s to %s: %s\n",
(void) fflush(stderr); from, to, strerror(errno));
perror("");
return; return;
} }
vprintf(stdout, "rename %s to %s\n", from, to); vprintf(stdout, "rename %s to %s\n", from, to);
@ -120,6 +137,7 @@ renameit(from, to)
/* /*
* Create a new node (directory). * Create a new node (directory).
*/ */
void
newnode(np) newnode(np)
struct entry *np; struct entry *np;
{ {
@ -130,9 +148,7 @@ newnode(np)
cp = myname(np); cp = myname(np);
if (!Nflag && mkdir(cp, 0777) < 0) { if (!Nflag && mkdir(cp, 0777) < 0) {
np->e_flags |= EXISTED; np->e_flags |= EXISTED;
fprintf(stderr, "Warning: "); fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
(void) fflush(stderr);
perror(cp);
return; return;
} }
vprintf(stdout, "Make node %s\n", cp); vprintf(stdout, "Make node %s\n", cp);
@ -141,6 +157,7 @@ newnode(np)
/* /*
* Remove an old node (directory). * Remove an old node (directory).
*/ */
void
removenode(ep) removenode(ep)
register struct entry *ep; register struct entry *ep;
{ {
@ -148,15 +165,13 @@ removenode(ep)
if (ep->e_type != NODE) if (ep->e_type != NODE)
badentry(ep, "removenode: not a node"); badentry(ep, "removenode: not a node");
if (ep->e_entries != NIL) if (ep->e_entries != NULL)
badentry(ep, "removenode: non-empty directory"); badentry(ep, "removenode: non-empty directory");
ep->e_flags |= REMOVED; ep->e_flags |= REMOVED;
ep->e_flags &= ~TMPNAME; ep->e_flags &= ~TMPNAME;
cp = myname(ep); cp = myname(ep);
if (!Nflag && rmdir(cp) < 0) { if (!Nflag && rmdir(cp) < 0) {
fprintf(stderr, "Warning: "); fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
(void) fflush(stderr);
perror(cp);
return; return;
} }
vprintf(stdout, "Remove node %s\n", cp); vprintf(stdout, "Remove node %s\n", cp);
@ -165,6 +180,7 @@ removenode(ep)
/* /*
* Remove a leaf. * Remove a leaf.
*/ */
void
removeleaf(ep) removeleaf(ep)
register struct entry *ep; register struct entry *ep;
{ {
@ -176,9 +192,7 @@ removeleaf(ep)
ep->e_flags &= ~TMPNAME; ep->e_flags &= ~TMPNAME;
cp = myname(ep); cp = myname(ep);
if (!Nflag && unlink(cp) < 0) { if (!Nflag && unlink(cp) < 0) {
fprintf(stderr, "Warning: "); fprintf(stderr, "warning: %s: %s\n", cp, strerror(errno));
(void) fflush(stderr);
perror(cp);
return; return;
} }
vprintf(stdout, "Remove leaf %s\n", cp); vprintf(stdout, "Remove leaf %s\n", cp);
@ -187,6 +201,7 @@ removeleaf(ep)
/* /*
* Create a link. * Create a link.
*/ */
int
linkit(existing, new, type) linkit(existing, new, type)
char *existing, *new; char *existing, *new;
int type; int type;
@ -195,19 +210,15 @@ linkit(existing, new, type)
if (type == SYMLINK) { if (type == SYMLINK) {
if (!Nflag && symlink(existing, new) < 0) { if (!Nflag && symlink(existing, new) < 0) {
fprintf(stderr, fprintf(stderr,
"Warning: cannot create symbolic link %s->%s: ", "warning: cannot create symbolic link %s->%s: %s\n",
new, existing); new, existing, strerror(errno));
(void) fflush(stderr);
perror("");
return (FAIL); return (FAIL);
} }
} else if (type == HARDLINK) { } else if (type == HARDLINK) {
if (!Nflag && link(existing, new) < 0) { if (!Nflag && link(existing, new) < 0) {
fprintf(stderr, fprintf(stderr,
"Warning: cannot create hard link %s->%s: ", "warning: cannot create hard link %s->%s: %s\n",
new, existing); new, existing, strerror(errno));
(void) fflush(stderr);
perror("");
return (FAIL); return (FAIL);
} }
} else { } else {
@ -230,7 +241,7 @@ lowerbnd(start)
for ( ; start < maxino; start++) { for ( ; start < maxino; start++) {
ep = lookupino(start); ep = lookupino(start);
if (ep == NIL || ep->e_type == NODE) if (ep == NULL || ep->e_type == NODE)
continue; continue;
if (ep->e_flags & (NEW|EXTRACT)) if (ep->e_flags & (NEW|EXTRACT))
return (start); return (start);
@ -249,7 +260,7 @@ upperbnd(start)
for ( ; start > ROOTINO; start--) { for ( ; start > ROOTINO; start--) {
ep = lookupino(start); ep = lookupino(start);
if (ep == NIL || ep->e_type == NODE) if (ep == NULL || ep->e_type == NODE)
continue; continue;
if (ep->e_flags & (NEW|EXTRACT)) if (ep->e_flags & (NEW|EXTRACT))
return (start); return (start);
@ -260,6 +271,7 @@ upperbnd(start)
/* /*
* report on a badly formed entry * report on a badly formed entry
*/ */
void
badentry(ep, msg) badentry(ep, msg)
register struct entry *ep; register struct entry *ep;
char *msg; char *msg;
@ -268,14 +280,15 @@ badentry(ep, msg)
fprintf(stderr, "bad entry: %s\n", msg); fprintf(stderr, "bad entry: %s\n", msg);
fprintf(stderr, "name: %s\n", myname(ep)); fprintf(stderr, "name: %s\n", myname(ep));
fprintf(stderr, "parent name %s\n", myname(ep->e_parent)); 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)); 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)); 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)); fprintf(stderr, "next link name: %s\n", myname(ep->e_links));
if (ep->e_next != NIL) if (ep->e_next != NULL)
fprintf(stderr, "next hashchain name: %s\n", myname(ep->e_next)); fprintf(stderr,
"next hashchain name: %s\n", myname(ep->e_next));
fprintf(stderr, "entry type: %s\n", fprintf(stderr, "entry type: %s\n",
ep->e_type == NODE ? "NODE" : "LEAF"); ep->e_type == NODE ? "NODE" : "LEAF");
fprintf(stderr, "inode number: %ld\n", ep->e_ino); fprintf(stderr, "inode number: %ld\n", ep->e_ino);
@ -317,8 +330,8 @@ dirlookup(name)
{ {
ino_t ino; ino_t ino;
ino = psearch(name); ino = pathsearch(name)->d_ino;
if (ino == 0 || BIT(ino, dumpmap) == 0) if (ino == 0 || TSTINO(ino, dumpmap) == 0)
fprintf(stderr, "%s is not on tape\n", name); fprintf(stderr, "%s is not on tape\n", name);
return (ino); return (ino);
} }
@ -326,6 +339,7 @@ dirlookup(name)
/* /*
* Elicit a reply. * Elicit a reply.
*/ */
int
reply(question) reply(question)
char *question; char *question;
{ {
@ -347,13 +361,29 @@ reply(question)
/* /*
* handle unexpected inconsistencies * handle unexpected inconsistencies
*/ */
/* VARARGS1 */ #if __STDC__
panic(msg, d1, d2) #include <stdarg.h>
char *msg; #else
long d1, d2; #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) if (yflag)
return; return;
if (reply("abort") == GOOD) { if (reply("abort") == GOOD) {