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