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