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