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
|
# 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}
|
|
||||||
|
@ -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
|
#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);
|
||||||
|
@ -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
|
||||||
|
@ -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
|
.\" 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
|
||||||
|
@ -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");
|
||||||
|
@ -1 +1 @@
|
|||||||
revision 1.2 intentionally removed
|
revision 1.3 intentionally removed
|
||||||
|
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
revision 1.4 intentionally removed
|
revision 1.5 intentionally removed
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user