BSD 4 release
[unix-history] / usr / src / cmd / dumpdir.c
CommitLineData
31cef89c 1static char *sccsid = "@(#)dumpdir.c 4.2 (Berkeley) 11/15/80";
c1984ed6
BJ
2#define MAXINO 2000
3#define BITS 8
4#define MAXXTR 60
5#define NCACHE 3
6
7#include <stdio.h>
8#include <sys/param.h>
9#include <sys/inode.h>
10#include <sys/ino.h>
11#include <sys/fblk.h>
12#include <sys/filsys.h>
13#include <sys/dir.h>
14#include <dumprestor.h>
15
16#define MWORD(m,i) (m[(unsigned)(i-1)/MLEN])
17#define MBIT(i) (1<<((unsigned)(i-1)%MLEN))
18#define BIS(i,w) (MWORD(w,i) |= MBIT(i))
19#define BIC(i,w) (MWORD(w,i) &= ~MBIT(i))
20#define BIT(i,w) (MWORD(w,i) & MBIT(i))
21
22int mt;
31cef89c 23char tapename[] = "/dev/rmt8";
c1984ed6
BJ
24char *magtape = tapename;
25
26daddr_t seekpt;
27int ofile;
28FILE *df;
29char dirfile[] = "rstXXXXXX";
30
31struct {
32 ino_t t_ino;
33 daddr_t t_seekpt;
34} inotab[MAXINO];
35int ipos;
36
37#define ONTAPE 1
38#define XTRACTD 2
39#define XINUSE 4
40
41short dumpmap[MSIZ];
42short clrimap[MSIZ];
43
44
45int bct = NTREC+1;
46char tbf[NTREC*BSIZE];
47
48char prebuf[BUFSIZ];
49
50int volno;
51
52main(argc, argv)
53char *argv[];
54{
55 extern char *ctime();
56
57 mktemp(dirfile);
58 argv++;
59 if (argc>=3 && *argv[0] == 'f')
60 magtape = *++argv;
61 df = fopen(dirfile, "w");
62 if (df == NULL) {
63 printf("dumpdir: %s - cannot create directory temporary\n", dirfile);
64 exit(1);
65 }
66
67 if ((mt = open(magtape, 0)) < 0) {
68 printf("%s: cannot open tape\n", magtape);
69 exit(1);
70 }
71 if (readhdr(&spcl) == 0) {
72 printf("Tape is not a dump tape\n");
73 exit(1);
74 }
75 printf("Dump date: %s", ctime(&spcl.c_date));
76 printf("Dumped from: %s", ctime(&spcl.c_ddate));
77 if (checkvol(&spcl, 1) == 0) {
78 printf("Tape is not volume 1 of the dump\n");
79 exit(1);
80 }
81 pass1(); /* This sets the various maps on the way by */
82 freopen(dirfile, "r", df);
83 strcpy(prebuf, "/");
84 printem(prebuf, (ino_t) 2);
85 exit(0);
86}
87 i = 0;
88/*
89 * Read the tape, bulding up a directory structure for extraction
90 * by name
91 */
92pass1()
93{
94 register i;
95 struct dinode *ip;
96 int putdir(), null();
97
98 while (gethead(&spcl) == 0) {
99 printf("Can't find directory header!\n");
100 }
101 for (;;) {
102 if (checktype(&spcl, TS_BITS) == 1) {
103 readbits(dumpmap);
104 continue;
105 }
106 if (checktype(&spcl, TS_CLRI) == 1) {
107 readbits(clrimap);
108 continue;
109 }
110 if (checktype(&spcl, TS_INODE) == 0) {
111finish:
112 flsh();
113 close(mt);
114 return;
115 }
116 ip = &spcl.c_dinode;
117 i = ip->di_mode & IFMT;
118 if (i != IFDIR) {
119 goto finish;
120 }
121 inotab[ipos].t_ino = spcl.c_inumber;
122 inotab[ipos++].t_seekpt = seekpt;
123 getfile(spcl.c_inumber, putdir, null, spcl.c_dinode.di_size);
124 putent("\000\000/");
125 }
126}
127
128printem(prefix, inum)
129char *prefix;
130ino_t inum;
131{
132 struct direct dir;
133 register int i;
134
135 for (i = 0; i < MAXINO; i++)
136 if (inotab[i].t_ino == inum) {
137 goto found;
138 }
139 printf("PANIC - can't find directory %d\n", inum);
140 return;
141found:
142 mseek(inotab[i].t_seekpt);
143 for (;;) {
144 getent((char *) &dir);
145 if (direq(dir.d_name, "/"))
146 return;
147 if (search(dir.d_ino) != 0 && direq(dir.d_name, ".") == 0 && direq(dir.d_name, "..") == 0) {
148 int len;
149 FILE *tdf;
150
151 tdf = df;
152 df = fopen(dirfile, "r");
153 len = strlen(prefix);
154 strncat(prefix, dir.d_name, sizeof(dir.d_name));
155 strcat(prefix, "/");
156 printem(prefix, dir.d_ino);
157 prefix[len] = '\0';
158 fclose(df);
159 df = tdf;
160 }
161 else
162 if (BIT(dir.d_ino, dumpmap))
163 printf("%5d %s%-.14s\n", dir.d_ino, prefix, dir.d_name);
164 }
165}
166/*
167 * Do the file extraction, calling the supplied functions
168 * with the blocks
169 */
170getfile(n, f1, f2, size)
171ino_t n;
172int (*f2)(), (*f1)();
173long size;
174{
175 register i;
176 struct spcl addrblock;
177 char buf[BSIZE];
178
179 addrblock = spcl;
180 goto start;
181 for (;;) {
182 if (gethead(&addrblock) == 0) {
183 printf("Missing address (header) block\n");
184 goto eloop;
185 }
186 if (checktype(&addrblock, TS_ADDR) == 0) {
187 spcl = addrblock;
188 return;
189 }
190start:
191 for (i = 0; i < addrblock.c_count; i++) {
192 if (addrblock.c_addr[i]) {
193 readtape(buf);
194 (*f1)(buf, size > BSIZE ? (long) BSIZE : size);
195 }
196 else {
197 clearbuf(buf);
198 (*f2)(buf, size > BSIZE ? (long) BSIZE : size);
199 }
200 if ((size -= BSIZE) <= 0) {
201eloop:
202 while (gethead(&spcl) == 0)
203 ;
204 if (checktype(&spcl, TS_ADDR) == 1)
205 goto eloop;
206 return;
207 }
208 }
209 }
210}
211
212/*
213 * Do the tape i\/o, dealling with volume changes
214 * etc..
215 */
216readtape(b)
217char *b;
218{
219 register i;
220 struct spcl tmpbuf;
221
222 if (bct >= NTREC) {
223 for (i = 0; i < NTREC; i++)
224 ((struct spcl *)&tbf[i*BSIZE])->c_magic = 0;
225 bct = 0;
226 if ((i = read(mt, tbf, NTREC*BSIZE)) < 0) {
227 exit(1);
228 }
229 if (i == 0) {
230 bct = NTREC + 1;
231 volno++;
232loop:
233 flsht();
234 close(mt);
235 printf("Mount volume %d\n", volno);
236 while (getchar() != '\n')
237 ;
238 if ((mt = open(magtape, 0)) == -1) {
239 printf("Cannot open tape!\n");
240 }
241 if (readhdr(&tmpbuf) == 0) {
242 printf("Not a dump tape.Try again\n");
243 goto loop;
244 }
245 if (checkvol(&tmpbuf, volno) == 0) {
246 printf("Wrong tape. Try again\n");
247 goto loop;
248 }
249 readtape(b);
250 return;
251 }
252 }
253 copy(&tbf[(bct++*BSIZE)], b, BSIZE);
254}
255
256flsht()
257{
258 bct = NTREC+1;
259}
260
261copy(f, t, s)
262register char *f, *t;
263{
264 register i;
265
266 i = s;
267 do
268 *t++ = *f++;
269 while (--i);
270}
271
272clearbuf(cp)
273register char *cp;
274{
275 register i;
276
277 i = BSIZE;
278 do
279 *cp++ = 0;
280 while (--i);
281}
282
283/*
284 * Put and get the directory entries from the compressed
285 * directory file
286 */
287putent(cp)
288char *cp;
289{
290 register i;
291
292 for (i = 0; i < sizeof(ino_t); i++)
293 writec(*cp++);
294 for (i = 0; i < DIRSIZ; i++) {
295 writec(*cp);
296 if (*cp++ == 0)
297 return;
298 }
299 return;
300}
301
302getent(bf)
303register char *bf;
304{
305 register i;
306
307 for (i = 0; i < sizeof(ino_t); i++)
308 *bf++ = readc();
309 for (i = 0; i < DIRSIZ; i++)
310 if ((*bf++ = readc()) == 0)
311 return;
312 return;
313}
314
315/*
316 * read/write te directory file
317 */
318writec(c)
319char c;
320{
321 seekpt++;
322 fwrite(&c, 1, 1, df);
323}
324
325readc()
326{
327 char c;
328
329 fread(&c, 1, 1, df);
330 return(c);
331}
332
333mseek(pt)
334daddr_t pt;
335{
336 fseek(df, pt, 0);
337}
338
339flsh()
340{
341 fflush(df);
342}
343
344/*
345 * search the directory inode ino
346 * looking for entry cp
347 */
348search(inum)
349ino_t inum;
350{
351 register low, high, probe;
352
353 low = 0;
354 high = ipos-1;
355
356 while (low != high) {
357 probe = (high - low + 1)/2 + low;
358/*
359printf("low = %d, high = %d, probe = %d, ino = %d, inum = %d\n", low, high, probe, inum, inotab[probe].t_ino);
360*/
361 if (inum >= inotab[probe].t_ino)
362 low = probe;
363 else
364 high = probe - 1;
365 }
366 return(inum == inotab[low].t_ino);
367}
368
369direq(s1, s2)
370register char *s1, *s2;
371{
372 register i;
373
374 for (i = 0; i < DIRSIZ; i++)
375 if (*s1++ == *s2) {
376 if (*s2++ == 0)
377 return(1);
378 } else
379 return(0);
380 return(1);
381}
382
383/*
384 * read the tape into buf, then return whether or
385 * or not it is a header block.
386 */
387gethead(buf)
388struct spcl *buf;
389{
390 readtape((char *)buf);
391 if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
392 return(0);
393 return(1);
394}
395
396/*
397 * return whether or not the buffer contains a header block
398 */
399checktype(b, t)
400struct spcl *b;
401int t;
402{
403 return(b->c_type == t);
404}
405
406
407checksum(b)
408int *b;
409{
410 register i, j;
411
412 j = BSIZE/sizeof(int);
413 i = 0;
414 do
415 i += *b++;
416 while (--j);
417 if (i != CHECKSUM) {
418 printf("Checksum error %o\n", i);
419 return(0);
420 }
421 return(1);
422}
423
424checkvol(b, t)
425struct spcl *b;
426int t;
427{
428 if (b->c_volume == t)
429 return(1);
430 return(0);
431}
432
433readhdr(b)
434struct spcl *b;
435{
436 if (gethead(b) == 0)
437 return(0);
438 if (checktype(b, TS_TAPE) == 0)
439 return(0);
440 return(1);
441}
442
443putdir(b)
444char *b;
445{
446 register struct direct *dp;
447 register i;
448
449 for (dp = (struct direct *) b, i = 0; i < BSIZE; dp++, i += sizeof(*dp)) {
450 if (dp->d_ino == 0)
451 continue;
452 putent((char *) dp);
453 }
454}
455
456/*
457 * read a bit mask from the tape into m.
458 */
459readbits(m)
460short *m;
461{
462 register i;
463
464 i = spcl.c_count;
465
466 while (i--) {
467 readtape((char *) m);
468 m += (BSIZE/(MLEN/BITS));
469 }
470 while (gethead(&spcl) == 0)
471 ;
472}
473
474null() { ; }