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