|
|
1.1 root 1: static char *sccsid = "@(#)restor.c 4.1 (Berkeley) 10/1/80";
2:
3: #define MAXINO 3000
4: #define BITS 8
5: #define MAXXTR 600
6: #define NCACHE 3
7:
8: #ifndef STANDALONE
9: #include <stdio.h>
10: #include <signal.h>
11: #endif
12: #include <sys/param.h>
13: #include <sys/inode.h>
14: #include <sys/ino.h>
15: #include <sys/fblk.h>
16: #include <sys/filsys.h>
17: #include <sys/dir.h>
18: #include <dumprestor.h>
19:
20: #define MWORD(m,i) (m[(unsigned)(i-1)/MLEN])
21: #define MBIT(i) (1<<((unsigned)(i-1)%MLEN))
22: #define BIS(i,w) (MWORD(w,i) |= MBIT(i))
23: #define BIC(i,w) (MWORD(w,i) &= ~MBIT(i))
24: #define BIT(i,w) (MWORD(w,i) & MBIT(i))
25:
26: struct filsys sblock;
27:
28: int fi;
29: ino_t ino, maxi, curino;
30:
31: int mt;
32: char tapename[] = "/dev/rmt8";
33: char *magtape = tapename;
34: #ifdef STANDALONE
35: char mbuf[50];
36: #endif
37:
38: #ifndef STANDALONE
39: daddr_t seekpt;
40: int df, ofile;
41: char dirfile[] = "rstXXXXXX";
42:
43: struct {
44: ino_t t_ino;
45: daddr_t t_seekpt;
46: } inotab[MAXINO];
47: int ipos;
48:
49: #define ONTAPE 1
50: #define XTRACTD 2
51: #define XINUSE 4
52: struct xtrlist {
53: ino_t x_ino;
54: char x_flags;
55: } xtrlist[MAXXTR];
56:
57: char name[12];
58:
59: char drblock[BSIZE];
60: int bpt;
61: #endif
62:
63: int eflag;
64:
65: int volno = 1;
66:
67: struct dinode tino, dino;
68: daddr_t taddr[NADDR];
69:
70: daddr_t curbno;
71:
72: short dumpmap[MSIZ];
73: short clrimap[MSIZ];
74:
75:
76: int bct = NTREC+1;
77: char tbf[NTREC*BSIZE];
78:
79: struct cache {
80: daddr_t c_bno;
81: int c_time;
82: char c_block[BSIZE];
83: } cache[NCACHE];
84: int curcache;
85:
86: main(argc, argv)
87: char *argv[];
88: {
89: register char *cp;
90: char command;
91: int done();
92:
93: #ifndef STANDALONE
94: mktemp(dirfile);
95: if (argc < 2) {
96: usage:
97: printf("Usage: restor x file file..., restor r filesys, or restor t\n");
98: exit(1);
99: }
100: argv++;
101: argc -= 2;
102: for (cp = *argv++; *cp; cp++) {
103: switch (*cp) {
104: case '-':
105: break;
106: case 'f':
107: magtape = *argv++;
108: argc--;
109: break;
110: case 'r':
111: case 'R':
112: case 't':
113: case 'x':
114: command = *cp;
115: break;
116: default:
117: printf("Bad key character %c\n", *cp);
118: goto usage;
119: }
120: }
121: if (command == 'x') {
122: if (signal(SIGINT, done) == SIG_IGN)
123: signal(SIGINT, SIG_IGN);
124: if (signal(SIGTERM, done) == SIG_IGN)
125: signal(SIGTERM, SIG_IGN);
126:
127: df = creat(dirfile, 0666);
128: if (df < 0) {
129: printf("restor: %s - cannot create directory temporary\n", dirfile);
130: exit(1);
131: }
132: close(df);
133: df = open(dirfile, 2);
134: }
135: doit(command, argc, argv);
136: if (command == 'x')
137: unlink(dirfile);
138: exit(0);
139: #else
140: magtape = "tape";
141: doit('r', 1, 0);
142: #endif
143: }
144:
145: doit(command, argc, argv)
146: char command;
147: int argc;
148: char *argv[];
149: {
150: extern char *ctime();
151: register i, k;
152: ino_t d;
153: #ifndef STANDALONE
154: int xtrfile(), skip();
155: #endif
156: int rstrfile(), rstrskip();
157: struct dinode *ip, *ip1;
158:
159: #ifndef STANDALONE
160: if ((mt = open(magtape, 0)) < 0) {
161: printf("%s: cannot open tape\n", magtape);
162: exit(1);
163: }
164: #else
165: do {
166: printf("Tape? ");
167: gets(mbuf);
168: mt = open(mbuf, 0);
169: } while (mt == -1);
170: magtape = mbuf;
171: #endif
172: switch(command) {
173: #ifndef STANDALONE
174: case 't':
175: if (readhdr(&spcl) == 0) {
176: printf("Tape is not a dump tape\n");
177: exit(1);
178: }
179: printf("Dump date: %s", ctime(&spcl.c_date));
180: printf("Dumped from: %s", ctime(&spcl.c_ddate));
181: return;
182: case 'x':
183: if (readhdr(&spcl) == 0) {
184: printf("Tape is not a dump tape\n");
185: exit(1);
186: }
187: if (checkvol(&spcl, 1) == 0) {
188: printf("Tape is not volume 1 of the dump\n");
189: exit(1);
190: }
191: pass1(); /* This sets the various maps on the way by */
192: i = 0;
193: while (i < MAXXTR-1 && argc--) {
194: if ((d = psearch(*argv)) == 0 || BIT(d, dumpmap) == 0) {
195: printf("%s: not on the tape\n", *argv++);
196: continue;
197: }
198: xtrlist[i].x_ino = d;
199: xtrlist[i].x_flags |= XINUSE;
200: printf("%s: inode %u\n", *argv, d);
201: argv++;
202: i++;
203: }
204: newvol:
205: flsht();
206: close(mt);
207: getvol:
208: printf("Mount desired tape volume: Specify volume #: ");
209: if (gets(tbf) == NULL)
210: return;
211: volno = atoi(tbf);
212: if (volno <= 0) {
213: printf("Volume numbers are positive numerics\n");
214: goto getvol;
215: }
216: mt = open(magtape, 0);
217: if (readhdr(&spcl) == 0) {
218: printf("tape is not dump tape\n");
219: goto newvol;
220: }
221: if (checkvol(&spcl, volno) == 0) {
222: printf("Wrong volume (%d)\n", spcl.c_volume);
223: goto newvol;
224: }
225: rbits:
226: while (gethead(&spcl) == 0)
227: ;
228: if (checktype(&spcl, TS_INODE) == 1) {
229: printf("Can't find inode mask!\n");
230: goto newvol;
231: }
232: if (checktype(&spcl, TS_BITS) == 0)
233: goto rbits;
234: readbits(dumpmap);
235: for (;;) {
236: again:
237: if (ishead(&spcl) == 0)
238: while(gethead(&spcl) == 0)
239: ;
240: if (checktype(&spcl, TS_END) == 1) {
241: printf("end of tape\n");
242: checkdone:
243: return;
244: }
245: if (checktype(&spcl, TS_INODE) == 0) {
246: gethead(&spcl);
247: goto again;
248: }
249: d = spcl.c_inumber;
250: printf("extract file %u\n", d);
251: sprintf(name, "%u", d);
252: if ((ofile = creat(name, 0666)) < 0) {
253: printf("%s: cannot create file\n", name);
254: continue;
255: }
256: chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
257: getfile(ino, xtrfile, skip, spcl.c_dinode.di_size);
258: close(ofile);
259: ;
260: }
261: goto checkdone;
262: #endif
263: case 'r':
264: case 'R':
265: #ifndef STANDALONE
266: if ((fi = open(*argv, 2)) < 0) {
267: printf("%s: cannot open\n", *argv);
268: exit(1);
269: }
270: #else
271: do {
272: char charbuf[50];
273:
274: printf("Disk? ");
275: gets(charbuf);
276: fi = open(charbuf, 2);
277: } while (fi == -1);
278: #endif
279: #ifndef STANDALONE
280: if (command == 'R') {
281: printf("Enter starting volume number: ");
282: if (gets(tbf) == EOF) {
283: volno = 1;
284: printf("\n");
285: }
286: else
287: volno = atoi(tbf);
288: }
289: else
290: #endif
291: volno = 1;
292: printf("Last chance before scribbling on %s. ",
293: #ifdef STANDALONE
294: "disk");
295: #else
296: *argv);
297: #endif
298: while (getchar() != '\n');
299: dread((daddr_t)1, (char *)&sblock, sizeof(sblock));
300: maxi = (sblock.s_isize-2)*INOPB;
301: if (readhdr(&spcl) == 0) {
302: printf("Missing volume record\n");
303: exit(1);
304: }
305: if (checkvol(&spcl, volno) == 0) {
306: printf("Tape is not volume %d\n", volno);
307: exit(1);
308: }
309: gethead(&spcl);
310: for (;;) {
311: ragain:
312: if (ishead(&spcl) == 0) {
313: printf("Missing header block\n");
314: while (gethead(&spcl) == 0)
315: ;
316: eflag++;
317: }
318: if (checktype(&spcl, TS_END) == 1) {
319: printf("End of tape\n");
320: close(mt);
321: dwrite( (daddr_t) 1, (char *) &sblock);
322: return;
323: }
324: if (checktype(&spcl, TS_CLRI) == 1) {
325: readbits(clrimap);
326: for (ino = 1; ino <= maxi; ino++)
327: if (BIT(ino, clrimap) == 0) {
328: getdino(ino, &tino);
329: if (tino.di_mode == 0)
330: continue;
331: itrunc(&tino);
332: clri(&tino);
333: putdino(ino, &tino);
334: }
335: dwrite( (daddr_t) 1, (char *) &sblock);
336: goto ragain;
337: }
338: if (checktype(&spcl, TS_BITS) == 1) {
339: readbits(dumpmap);
340: goto ragain;
341: }
342: if (checktype(&spcl, TS_INODE) == 0) {
343: printf("Unknown header type\n");
344: eflag++;
345: gethead(&spcl);
346: goto ragain;
347: }
348: ino = spcl.c_inumber;
349: if (eflag)
350: printf("Resynced at inode %u\n", ino);
351: eflag = 0;
352: if (ino > maxi) {
353: printf("%u: ilist too small\n", ino);
354: gethead(&spcl);
355: goto ragain;
356: }
357: dino = spcl.c_dinode;
358: getdino(ino, &tino);
359: curbno = 0;
360: itrunc(&tino);
361: clri(&tino);
362: for (i = 0; i < NADDR; i++)
363: taddr[i] = 0;
364: l3tol(taddr, dino.di_addr, 1);
365: getfile(d, rstrfile, rstrskip, dino.di_size);
366: ip = &tino;
367: ltol3(ip->di_addr, taddr, NADDR);
368: ip1 = &dino;
369: ip->di_mode = ip1->di_mode;
370: ip->di_nlink = ip1->di_nlink;
371: ip->di_uid = ip1->di_uid;
372: ip->di_gid = ip1->di_gid;
373: ip->di_size = ip1->di_size;
374: ip->di_atime = ip1->di_atime;
375: ip->di_mtime = ip1->di_mtime;
376: ip->di_ctime = ip1->di_ctime;
377: putdino(ino, &tino);
378: }
379: }
380: }
381:
382: /*
383: * Read the tape, bulding up a directory structure for extraction
384: * by name
385: */
386: #ifndef STANDALONE
387: pass1()
388: {
389: register i;
390: struct dinode *ip;
391: int putdir(), null();
392:
393: while (gethead(&spcl) == 0) {
394: printf("Can't find directory header!\n");
395: }
396: for (;;) {
397: if (checktype(&spcl, TS_BITS) == 1) {
398: readbits(dumpmap);
399: continue;
400: }
401: if (checktype(&spcl, TS_CLRI) == 1) {
402: readbits(clrimap);
403: continue;
404: }
405: if (checktype(&spcl, TS_INODE) == 0) {
406: finish:
407: flsh();
408: close(mt);
409: return;
410: }
411: ip = &spcl.c_dinode;
412: i = ip->di_mode & IFMT;
413: if (i != IFDIR) {
414: goto finish;
415: }
416: inotab[ipos].t_ino = spcl.c_inumber;
417: inotab[ipos++].t_seekpt = seekpt;
418: getfile(spcl.c_inumber, putdir, null, spcl.c_dinode.di_size);
419: putent("\000\000/");
420: }
421: }
422: #endif
423:
424: /*
425: * Do the file extraction, calling the supplied functions
426: * with the blocks
427: */
428: getfile(n, f1, f2, size)
429: ino_t n;
430: int (*f2)(), (*f1)();
431: long size;
432: {
433: register i;
434: struct spcl addrblock;
435: char buf[BSIZE];
436:
437: addrblock = spcl;
438: curino = n;
439: goto start;
440: for (;;) {
441: if (gethead(&addrblock) == 0) {
442: printf("Missing address (header) block\n");
443: goto eloop;
444: }
445: if (checktype(&addrblock, TS_ADDR) == 0) {
446: spcl = addrblock;
447: curino = 0;
448: curino = 0;
449: return;
450: }
451: start:
452: for (i = 0; i < addrblock.c_count; i++) {
453: if (addrblock.c_addr[i]) {
454: readtape(buf);
455: (*f1)(buf, size > BSIZE ? (long) BSIZE : size);
456: }
457: else {
458: clearbuf(buf);
459: (*f2)(buf, size > BSIZE ? (long) BSIZE : size);
460: }
461: if ((size -= BSIZE) <= 0) {
462: eloop:
463: while (gethead(&spcl) == 0)
464: ;
465: if (checktype(&spcl, TS_ADDR) == 1)
466: goto eloop;
467: curino = 0;
468: return;
469: }
470: }
471: }
472: }
473:
474: /*
475: * Do the tape i\/o, dealling with volume changes
476: * etc..
477: */
478: readtape(b)
479: char *b;
480: {
481: register i;
482: struct spcl tmpbuf;
483:
484: if (bct >= NTREC) {
485: for (i = 0; i < NTREC; i++)
486: ((struct spcl *)&tbf[i*BSIZE])->c_magic = 0;
487: bct = 0;
488: if ((i = read(mt, tbf, NTREC*BSIZE)) < 0) {
489: printf("Tape read error: inode %u\n", curino);
490: eflag++;
491: exit(1);
492: }
493: if (i == 0) {
494: bct = NTREC + 1;
495: volno++;
496: loop:
497: flsht();
498: close(mt);
499: printf("Mount volume %d\n", volno);
500: while (getchar() != '\n')
501: ;
502: if ((mt = open(magtape, 0)) == -1) {
503: printf("Cannot open tape!\n");
504: goto loop;
505: }
506: if (readhdr(&tmpbuf) == 0) {
507: printf("Not a dump tape.Try again\n");
508: goto loop;
509: }
510: if (checkvol(&tmpbuf, volno) == 0) {
511: printf("Wrong tape. Try again\n");
512: goto loop;
513: }
514: readtape(b);
515: return;
516: }
517: }
518: copy(&tbf[(bct++*BSIZE)], b, BSIZE);
519: }
520:
521: flsht()
522: {
523: bct = NTREC+1;
524: }
525:
526: copy(f, t, s)
527: register char *f, *t;
528: {
529: register i;
530:
531: i = s;
532: do
533: *t++ = *f++;
534: while (--i);
535: }
536:
537: clearbuf(cp)
538: register char *cp;
539: {
540: register i;
541:
542: i = BSIZE;
543: do
544: *cp++ = 0;
545: while (--i);
546: }
547:
548: /*
549: * Put and get the directory entries from the compressed
550: * directory file
551: */
552: #ifndef STANDALONE
553: putent(cp)
554: char *cp;
555: {
556: register i;
557:
558: for (i = 0; i < sizeof(ino_t); i++)
559: writec(*cp++);
560: for (i = 0; i < DIRSIZ; i++) {
561: writec(*cp);
562: if (*cp++ == 0)
563: return;
564: }
565: return;
566: }
567:
568: getent(bf)
569: register char *bf;
570: {
571: register i;
572:
573: for (i = 0; i < sizeof(ino_t); i++)
574: *bf++ = readc();
575: for (i = 0; i < DIRSIZ; i++)
576: if ((*bf++ = readc()) == 0)
577: return;
578: return;
579: }
580:
581: /*
582: * read/write te directory file
583: */
584: writec(c)
585: char c;
586: {
587: drblock[bpt++] = c;
588: seekpt++;
589: if (bpt >= BSIZE) {
590: bpt = 0;
591: write(df, drblock, BSIZE);
592: }
593: }
594:
595: readc()
596: {
597: if (bpt >= BSIZE) {
598: read(df, drblock, BSIZE);
599: bpt = 0;
600: }
601: return(drblock[bpt++]);
602: }
603:
604: mseek(pt)
605: daddr_t pt;
606: {
607: bpt = BSIZE;
608: lseek(df, pt, 0);
609: }
610:
611: flsh()
612: {
613: write(df, drblock, bpt+1);
614: }
615:
616: /*
617: * search the directory inode ino
618: * looking for entry cp
619: */
620: ino_t
621: search(inum, cp)
622: ino_t inum;
623: char *cp;
624: {
625: register i;
626: struct direct dir;
627:
628: for (i = 0; i < MAXINO; i++)
629: if (inotab[i].t_ino == inum) {
630: goto found;
631: }
632: return(0);
633: found:
634: mseek(inotab[i].t_seekpt);
635: do {
636: getent((char *)&dir);
637: if (direq(dir.d_name, "/"))
638: return(0);
639: } while (direq(dir.d_name, cp) == 0);
640: return(dir.d_ino);
641: }
642:
643: /*
644: * Search the directory tree rooted at inode 2
645: * for the path pointed at by n
646: */
647: psearch(n)
648: char *n;
649: {
650: register char *cp, *cp1;
651: char c;
652:
653: ino = 2;
654: if (*(cp = n) == '/')
655: cp++;
656: next:
657: cp1 = cp + 1;
658: while (*cp1 != '/' && *cp1)
659: cp1++;
660: c = *cp1;
661: *cp1 = 0;
662: ino = search(ino, cp);
663: if (ino == 0) {
664: *cp1 = c;
665: return(0);
666: }
667: *cp1 = c;
668: if (c == '/') {
669: cp = cp1+1;
670: goto next;
671: }
672: return(ino);
673: }
674:
675: direq(s1, s2)
676: register char *s1, *s2;
677: {
678: register i;
679:
680: for (i = 0; i < DIRSIZ; i++)
681: if (*s1++ == *s2) {
682: if (*s2++ == 0)
683: return(1);
684: } else
685: return(0);
686: return(1);
687: }
688: #endif
689:
690: /*
691: * read/write a disk block, be sure to update the buffer
692: * cache if needed.
693: */
694: dwrite(bno, b)
695: daddr_t bno;
696: char *b;
697: {
698: register i;
699:
700: for (i = 0; i < NCACHE; i++) {
701: if (cache[i].c_bno == bno) {
702: copy(b, cache[i].c_block, BSIZE);
703: cache[i].c_time = 0;
704: break;
705: }
706: else
707: cache[i].c_time++;
708: }
709: lseek(fi, bno*BSIZE, 0);
710: if(write(fi, b, BSIZE) != BSIZE) {
711: #ifdef STANDALONE
712: printf("disk write error %D\n", bno);
713: #else
714: fprintf(stderr, "disk write error %ld\n", bno);
715: #endif
716: exit(1);
717: }
718: }
719:
720: dread(bno, buf, cnt)
721: daddr_t bno;
722: char *buf;
723: {
724: register i, j;
725:
726: j = 0;
727: for (i = 0; i < NCACHE; i++) {
728: if (++curcache >= NCACHE)
729: curcache = 0;
730: if (cache[curcache].c_bno == bno) {
731: copy(cache[curcache].c_block, buf, cnt);
732: cache[curcache].c_time = 0;
733: return;
734: }
735: else {
736: cache[curcache].c_time++;
737: if (cache[j].c_time < cache[curcache].c_time)
738: j = curcache;
739: }
740: }
741:
742: lseek(fi, bno*BSIZE, 0);
743: if (read(fi, cache[j].c_block, BSIZE) != BSIZE) {
744: #ifdef STANDALONE
745: printf("read error %D\n", bno);
746: #else
747: printf("read error %ld\n", bno);
748: #endif
749: exit(1);
750: }
751: copy(cache[j].c_block, buf, cnt);
752: cache[j].c_time = 0;
753: cache[j].c_bno = bno;
754: }
755:
756: /*
757: * the inode manpulation routines. Like the system.
758: *
759: * clri zeros the inode
760: */
761: clri(ip)
762: struct dinode *ip;
763: {
764: int i, *p;
765: if (ip->di_mode&IFMT)
766: sblock.s_tinode++;
767: i = sizeof(struct dinode)/sizeof(int);
768: p = (int *)ip;
769: do
770: *p++ = 0;
771: while(--i);
772: }
773:
774: /*
775: * itrunc/tloop/bfree free all of the blocks pointed at by the inode
776: */
777: itrunc(ip)
778: register struct dinode *ip;
779: {
780: register i;
781: daddr_t bn, iaddr[NADDR];
782:
783: if (ip->di_mode == 0)
784: return;
785: i = ip->di_mode & IFMT;
786: if (i != IFDIR && i != IFREG)
787: return;
788: l3tol(iaddr, ip->di_addr, NADDR);
789: for(i=NADDR-1;i>=0;i--) {
790: bn = iaddr[i];
791: if(bn == 0) continue;
792: switch(i) {
793:
794: default:
795: bfree(bn);
796: break;
797:
798: case NADDR-3:
799: tloop(bn, 0, 0);
800: break;
801:
802: case NADDR-2:
803: tloop(bn, 1, 0);
804: break;
805:
806: case NADDR-1:
807: tloop(bn, 1, 1);
808: }
809: }
810: ip->di_size = 0;
811: }
812:
813: tloop(bn, f1, f2)
814: daddr_t bn;
815: int f1, f2;
816: {
817: register i;
818: daddr_t nb;
819: union {
820: char data[BSIZE];
821: daddr_t indir[NINDIR];
822: } ibuf;
823:
824: dread(bn, ibuf.data, BSIZE);
825: for(i=NINDIR-1;i>=0;i--) {
826: nb = ibuf.indir[i];
827: if(nb) {
828: if(f1)
829: tloop(nb, f2, 0);
830: else
831: bfree(nb);
832: }
833: }
834: bfree(bn);
835: }
836:
837: bfree(bn)
838: daddr_t bn;
839: {
840: register i;
841: union {
842: char data[BSIZE];
843: struct fblk frees;
844: } fbun;
845: #define fbuf fbun.frees
846:
847: if(sblock.s_nfree >= NICFREE) {
848: fbuf.df_nfree = sblock.s_nfree;
849: for(i=0;i<NICFREE;i++)
850: fbuf.df_free[i] = sblock.s_free[i];
851: sblock.s_nfree = 0;
852: dwrite(bn, fbun.data);
853: }
854: sblock.s_free[sblock.s_nfree++] = bn;
855: sblock.s_tfree++;
856: }
857:
858: /*
859: * allocate a block off the free list.
860: */
861: daddr_t
862: balloc()
863: {
864: daddr_t bno;
865: register i;
866: static char zeroes[BSIZE];
867: union {
868: char data[BSIZE];
869: struct fblk frees;
870: } fbun;
871: #undef fbuf
872: #define fbuf fbun.frees
873:
874: if(sblock.s_nfree == 0 || (bno=sblock.s_free[--sblock.s_nfree]) == 0) {
875: #ifdef STANDALONE
876: printf("Out of space\n");
877: #else
878: fprintf(stderr, "Out of space.\n");
879: #endif
880: exit(1);
881: }
882: if(sblock.s_nfree == 0) {
883: dread(bno, (char *)&fbuf, BSIZE);
884: sblock.s_nfree = fbuf.df_nfree;
885: for(i=0;i<NICFREE;i++)
886: sblock.s_free[i] = fbuf.df_free[i];
887: }
888: dwrite(bno, zeroes);
889: sblock.s_tfree--;
890: return(bno);
891: }
892:
893: /*
894: * map a block number into a block address, ensuring
895: * all of the correct indirect blocks are around. Allocate
896: * the block requested.
897: */
898: daddr_t
899: bmap(iaddr, bn)
900: daddr_t iaddr[NADDR];
901: daddr_t bn;
902: {
903: register i;
904: int j, sh;
905: daddr_t nb, nnb;
906: daddr_t indir[NINDIR];
907:
908: /*
909: * blocks 0..NADDR-4 are direct blocks
910: */
911: if(bn < NADDR-3) {
912: iaddr[bn] = nb = balloc();
913: return(nb);
914: }
915:
916: /*
917: * addresses NADDR-3, NADDR-2, and NADDR-1
918: * have single, double, triple indirect blocks.
919: * the first step is to determine
920: * how many levels of indirection.
921: */
922: sh = 0;
923: nb = 1;
924: bn -= NADDR-3;
925: for(j=3; j>0; j--) {
926: sh += NSHIFT;
927: nb <<= NSHIFT;
928: if(bn < nb)
929: break;
930: bn -= nb;
931: }
932: if(j == 0) {
933: return((daddr_t)0);
934: }
935:
936: /*
937: * fetch the address from the inode
938: */
939: if((nb = iaddr[NADDR-j]) == 0) {
940: iaddr[NADDR-j] = nb = balloc();
941: }
942:
943: /*
944: * fetch through the indirect blocks
945: */
946: for(; j<=3; j++) {
947: dread(nb, (char *)indir, BSIZE);
948: sh -= NSHIFT;
949: i = (bn>>sh) & NMASK;
950: nnb = indir[i];
951: if(nnb == 0) {
952: nnb = balloc();
953: indir[i] = nnb;
954: dwrite(nb, (char *)indir);
955: }
956: nb = nnb;
957: }
958: return(nb);
959: }
960:
961: /*
962: * read the tape into buf, then return whether or
963: * or not it is a header block.
964: */
965: gethead(buf)
966: struct spcl *buf;
967: {
968: readtape((char *)buf);
969: if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
970: return(0);
971: return(1);
972: }
973:
974: /*
975: * return whether or not the buffer contains a header block
976: */
977: ishead(buf)
978: struct spcl *buf;
979: {
980: if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
981: return(0);
982: return(1);
983: }
984:
985: checktype(b, t)
986: struct spcl *b;
987: int t;
988: {
989: return(b->c_type == t);
990: }
991:
992:
993: checksum(b)
994: int *b;
995: {
996: register i, j;
997:
998: j = BSIZE/sizeof(int);
999: i = 0;
1000: do
1001: i += *b++;
1002: while (--j);
1003: if (i != CHECKSUM) {
1004: printf("Checksum error %o\n", i);
1005: return(0);
1006: }
1007: return(1);
1008: }
1009:
1010: checkvol(b, t)
1011: struct spcl *b;
1012: int t;
1013: {
1014: if (b->c_volume == t)
1015: return(1);
1016: return(0);
1017: }
1018:
1019: readhdr(b)
1020: struct spcl *b;
1021: {
1022: if (gethead(b) == 0)
1023: return(0);
1024: if (checktype(b, TS_TAPE) == 0)
1025: return(0);
1026: return(1);
1027: }
1028:
1029: /*
1030: * The next routines are called during file extraction to
1031: * put the data into the right form and place.
1032: */
1033: #ifndef STANDALONE
1034: xtrfile(b, size)
1035: char *b;
1036: long size;
1037: {
1038: write(ofile, b, (int) size);
1039: }
1040:
1041: null() {;}
1042:
1043: skip()
1044: {
1045: lseek(ofile, (long) BSIZE, 1);
1046: }
1047: #endif
1048:
1049:
1050: rstrfile(b, s)
1051: char *b;
1052: long s;
1053: {
1054: daddr_t d;
1055:
1056: d = bmap(taddr, curbno);
1057: dwrite(d, b);
1058: curbno += 1;
1059: }
1060:
1061: rstrskip(b, s)
1062: char *b;
1063: long s;
1064: {
1065: curbno += 1;
1066: }
1067:
1068: #ifndef STANDALONE
1069: putdir(b)
1070: char *b;
1071: {
1072: register struct direct *dp;
1073: register i;
1074:
1075: for (dp = (struct direct *) b, i = 0; i < BSIZE; dp++, i += sizeof(*dp)) {
1076: if (dp->d_ino == 0)
1077: continue;
1078: putent((char *) dp);
1079: }
1080: }
1081: #endif
1082:
1083: /*
1084: * read/write an inode from the disk
1085: */
1086: getdino(inum, b)
1087: ino_t inum;
1088: struct dinode *b;
1089: {
1090: daddr_t bno;
1091: char buf[BSIZE];
1092:
1093: bno = (ino - 1)/INOPB;
1094: bno += 2;
1095: dread(bno, buf, BSIZE);
1096: copy(&buf[((inum-1)%INOPB)*sizeof(struct dinode)], (char *) b, sizeof(struct dinode));
1097: }
1098:
1099: putdino(inum, b)
1100: ino_t inum;
1101: struct dinode *b;
1102: {
1103: daddr_t bno;
1104: char buf[BSIZE];
1105:
1106: if (b->di_mode&IFMT)
1107: sblock.s_tinode--;
1108: bno = ((ino - 1)/INOPB) + 2;
1109: dread(bno, buf, BSIZE);
1110: copy((char *) b, &buf[((inum-1)%INOPB)*sizeof(struct dinode)], sizeof(struct dinode));
1111: dwrite(bno, buf);
1112: }
1113:
1114: /*
1115: * read a bit mask from the tape into m.
1116: */
1117: readbits(m)
1118: short *m;
1119: {
1120: register i;
1121:
1122: i = spcl.c_count;
1123:
1124: while (i--) {
1125: readtape((char *) m);
1126: m += (BSIZE/(MLEN/BITS));
1127: }
1128: while (gethead(&spcl) == 0)
1129: ;
1130: }
1131:
1132: done()
1133: {
1134: #ifndef STANDALONE
1135: unlink(dirfile);
1136: #endif
1137: exit(0);
1138: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.