new version from CSRG, via BSDI, with fixes
This commit is contained in:
parent
6b7fd8ec52
commit
3e75cabcd4
@ -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}
|
||||
|
@ -1 +1 @@
|
||||
revision 1.3 intentionally removed
|
||||
revision 1.4 intentionally removed
|
||||
|
102
sbin/restore/extern.h
Normal file
102
sbin/restore/extern.h
Normal 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));
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -1 +1 @@
|
||||
revision 1.2 intentionally removed
|
||||
revision 1.3 intentionally removed
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -1 +1 @@
|
||||
revision 1.2 intentionally removed
|
||||
revision 1.3 intentionally removed
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
revision 1.4 intentionally removed
|
||||
revision 1.5 intentionally removed
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user