#define DUMPDIR #define MAXINO 3000 #define BITS 8 #define MAXXTR 60 #define NCACHE 3 #include #include #include #include #include #include #include #include #include #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 *magtape; 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; int eflag; ino_t curino; main(argc, argv) char *argv[]; { extern char *ctime(); if ((magtape = getenv("TAPE")) == NULL) magtape = DEFTAPE; 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) { perror(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); } /* * 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); } } flsht() { bct = NTREC+1; } copy(f, t, s) register char *f, *t; { #ifdef vax bcopy(f, t, s); #else register i; i = s; do *t++ = *f++; while (--i); #endif } clearbuf(cp) register char *cp; { #ifdef vax bzero(cp, BSIZE); #else register i; i = BSIZE; do *cp++ = 0; while (--i); #endif } /* * Put and get the directory entries from the compressed * directory file */ putent(cp) register 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); } /* * return whether or not the buffer contains a header block */ checktype(b, t) struct spcl *b; int t; { return(b->c_type == t); } 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); if (eflag) exit(1); m += (BSIZE/(MLEN/BITS)); } while (gethead(&spcl) == 0) ; } null() { ; }