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