Bell 32V development
[unix-history] / usr / src / cmd / dumpdir.c
#define MAXINO 2000
#define BITS 8
#define MAXXTR 60
#define NCACHE 3
#include <stdio.h>
#include <sys/param.h>
#include <sys/inode.h>
#include <sys/ino.h>
#include <sys/fblk.h>
#include <sys/filsys.h>
#include <sys/dir.h>
#include <dumprestor.h>
#define MWORD(m,i) (m[(unsigned)(i-1)/MLEN])
#define MBIT(i) (1<<((unsigned)(i-1)%MLEN))
#define BIS(i,w) (MWORD(w,i) |= MBIT(i))
#define BIC(i,w) (MWORD(w,i) &= ~MBIT(i))
#define BIT(i,w) (MWORD(w,i) & MBIT(i))
int mt;
char tapename[] = "/dev/rmt1";
char *magtape = tapename;
daddr_t seekpt;
int ofile;
FILE *df;
char dirfile[] = "rstXXXXXX";
struct {
ino_t t_ino;
daddr_t t_seekpt;
} inotab[MAXINO];
int ipos;
#define ONTAPE 1
#define XTRACTD 2
#define XINUSE 4
short dumpmap[MSIZ];
short clrimap[MSIZ];
int bct = NTREC+1;
char tbf[NTREC*BSIZE];
char prebuf[512];
int volno;
main(argc, argv)
char *argv[];
{
extern char *ctime();
mktemp(dirfile);
argv++;
if (argc>=3 && *argv[0] == 'f')
magtape = *++argv;
df = fopen(dirfile, "w");
if (df == NULL) {
printf("dumpdir: %s - cannot create directory temporary\n", dirfile);
exit(1);
}
if ((mt = open(magtape, 0)) < 0) {
printf("%s: cannot open tape\n", magtape);
exit(1);
}
if (readhdr(&spcl) == 0) {
printf("Tape is not a dump tape\n");
exit(1);
}
printf("Dump date: %s", ctime(&spcl.c_date));
printf("Dumped from: %s", ctime(&spcl.c_ddate));
if (checkvol(&spcl, 1) == 0) {
printf("Tape is not volume 1 of the dump\n");
exit(1);
}
pass1(); /* This sets the various maps on the way by */
freopen(dirfile, "r", df);
strcpy(prebuf, "/");
printem(prebuf, (ino_t) 2);
exit(0);
}
i = 0;
/*
* Read the tape, bulding up a directory structure for extraction
* by name
*/
pass1()
{
register i;
struct dinode *ip;
int putdir(), null();
while (gethead(&spcl) == 0) {
printf("Can't find directory header!\n");
}
for (;;) {
if (checktype(&spcl, TS_BITS) == 1) {
readbits(dumpmap);
continue;
}
if (checktype(&spcl, TS_CLRI) == 1) {
readbits(clrimap);
continue;
}
if (checktype(&spcl, TS_INODE) == 0) {
finish:
flsh();
close(mt);
return;
}
ip = &spcl.c_dinode;
i = ip->di_mode & IFMT;
if (i != IFDIR) {
goto finish;
}
inotab[ipos].t_ino = spcl.c_inumber;
inotab[ipos++].t_seekpt = seekpt;
getfile(spcl.c_inumber, putdir, null, spcl.c_dinode.di_size);
putent("\000\000/");
}
}
printem(prefix, inum)
char *prefix;
ino_t inum;
{
struct direct dir;
register int i;
for (i = 0; i < MAXINO; i++)
if (inotab[i].t_ino == inum) {
goto found;
}
printf("PANIC - can't find directory %d\n", inum);
return;
found:
mseek(inotab[i].t_seekpt);
for (;;) {
getent((char *) &dir);
if (direq(dir.d_name, "/"))
return;
if (search(dir.d_ino) != 0 && direq(dir.d_name, ".") == 0 && direq(dir.d_name, "..") == 0) {
int len;
FILE *tdf;
tdf = df;
df = fopen(dirfile, "r");
len = strlen(prefix);
strncat(prefix, dir.d_name, sizeof(dir.d_name));
strcat(prefix, "/");
printem(prefix, dir.d_ino);
prefix[len] = '\0';
fclose(df);
df = tdf;
}
else
if (BIT(dir.d_ino, dumpmap))
printf("%5d %s%-.14s\n", dir.d_ino, prefix, dir.d_name);
}
}
/*
* Do the file extraction, calling the supplied functions
* with the blocks
*/
getfile(n, f1, f2, size)
ino_t n;
int (*f2)(), (*f1)();
long size;
{
register i;
struct spcl addrblock;
char buf[BSIZE];
addrblock = spcl;
goto start;
for (;;) {
if (gethead(&addrblock) == 0) {
printf("Missing address (header) block\n");
goto eloop;
}
if (checktype(&addrblock, TS_ADDR) == 0) {
spcl = addrblock;
return;
}
start:
for (i = 0; i < addrblock.c_count; i++) {
if (addrblock.c_addr[i]) {
readtape(buf);
(*f1)(buf, size > BSIZE ? (long) BSIZE : size);
}
else {
clearbuf(buf);
(*f2)(buf, size > BSIZE ? (long) BSIZE : size);
}
if ((size -= BSIZE) <= 0) {
eloop:
while (gethead(&spcl) == 0)
;
if (checktype(&spcl, TS_ADDR) == 1)
goto eloop;
return;
}
}
}
}
/*
* Do the tape i\/o, dealling with volume changes
* etc..
*/
readtape(b)
char *b;
{
register i;
struct spcl tmpbuf;
if (bct >= NTREC) {
for (i = 0; i < NTREC; i++)
((struct spcl *)&tbf[i*BSIZE])->c_magic = 0;
bct = 0;
if ((i = read(mt, tbf, NTREC*BSIZE)) < 0) {
exit(1);
}
if (i == 0) {
bct = NTREC + 1;
volno++;
loop:
flsht();
close(mt);
printf("Mount volume %d\n", volno);
while (getchar() != '\n')
;
if ((mt = open(magtape, 0)) == -1) {
printf("Cannot open tape!\n");
}
if (readhdr(&tmpbuf) == 0) {
printf("Not a dump tape.Try again\n");
goto loop;
}
if (checkvol(&tmpbuf, volno) == 0) {
printf("Wrong tape. Try again\n");
goto loop;
}
readtape(b);
return;
}
}
copy(&tbf[(bct++*BSIZE)], b, BSIZE);
}
flsht()
{
bct = NTREC+1;
}
copy(f, t, s)
register char *f, *t;
{
register i;
i = s;
do
*t++ = *f++;
while (--i);
}
clearbuf(cp)
register char *cp;
{
register i;
i = BSIZE;
do
*cp++ = 0;
while (--i);
}
/*
* Put and get the directory entries from the compressed
* directory file
*/
putent(cp)
char *cp;
{
register i;
for (i = 0; i < sizeof(ino_t); i++)
writec(*cp++);
for (i = 0; i < DIRSIZ; i++) {
writec(*cp);
if (*cp++ == 0)
return;
}
return;
}
getent(bf)
register char *bf;
{
register i;
for (i = 0; i < sizeof(ino_t); i++)
*bf++ = readc();
for (i = 0; i < DIRSIZ; i++)
if ((*bf++ = readc()) == 0)
return;
return;
}
/*
* read/write te directory file
*/
writec(c)
char c;
{
seekpt++;
fwrite(&c, 1, 1, df);
}
readc()
{
char c;
fread(&c, 1, 1, df);
return(c);
}
mseek(pt)
daddr_t pt;
{
fseek(df, pt, 0);
}
flsh()
{
fflush(df);
}
/*
* search the directory inode ino
* looking for entry cp
*/
search(inum)
ino_t inum;
{
register low, high, probe;
low = 0;
high = ipos-1;
while (low != high) {
probe = (high - low + 1)/2 + low;
/*
printf("low = %d, high = %d, probe = %d, ino = %d, inum = %d\n", low, high, probe, inum, inotab[probe].t_ino);
*/
if (inum >= inotab[probe].t_ino)
low = probe;
else
high = probe - 1;
}
return(inum == inotab[low].t_ino);
}
direq(s1, s2)
register char *s1, *s2;
{
register i;
for (i = 0; i < DIRSIZ; i++)
if (*s1++ == *s2) {
if (*s2++ == 0)
return(1);
} else
return(0);
return(1);
}
/*
* read the tape into buf, then return whether or
* or not it is a header block.
*/
gethead(buf)
struct spcl *buf;
{
readtape((char *)buf);
if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
return(0);
return(1);
}
/*
* return whether or not the buffer contains a header block
*/
checktype(b, t)
struct spcl *b;
int t;
{
return(b->c_type == t);
}
checksum(b)
int *b;
{
register i, j;
j = BSIZE/sizeof(int);
i = 0;
do
i += *b++;
while (--j);
if (i != CHECKSUM) {
printf("Checksum error %o\n", i);
return(0);
}
return(1);
}
checkvol(b, t)
struct spcl *b;
int t;
{
if (b->c_volume == t)
return(1);
return(0);
}
readhdr(b)
struct spcl *b;
{
if (gethead(b) == 0)
return(0);
if (checktype(b, TS_TAPE) == 0)
return(0);
return(1);
}
putdir(b)
char *b;
{
register struct direct *dp;
register i;
for (dp = (struct direct *) b, i = 0; i < BSIZE; dp++, i += sizeof(*dp)) {
if (dp->d_ino == 0)
continue;
putent((char *) dp);
}
}
/*
* read a bit mask from the tape into m.
*/
readbits(m)
short *m;
{
register i;
i = spcl.c_count;
while (i--) {
readtape((char *) m);
m += (BSIZE/(MLEN/BITS));
}
while (gethead(&spcl) == 0)
;
}
null() { ; }