change name embeddet to rmt8
[unix-history] / usr / src / old / 512restor / 512restor.c
CommitLineData
19cc19bb 1static char *sccsid = "@(#)512restor.c 4.2 (Berkeley) %G%";
be684735
BJ
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
37struct 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
52struct 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
67struct filsys sblock;
68
69int fi;
70ino_t ino, maxi, curino;
71
72int mt;
19cc19bb 73char tapename[] = "/dev/rmt8";
be684735
BJ
74char *magtape = tapename;
75#ifdef STANDALONE
76char mbuf[50];
77#endif
78
79#ifndef STANDALONE
80daddr_t seekpt;
81int df, ofile;
82char dirfile[] = "rstXXXXXX";
83
84struct {
85 ino_t t_ino;
86 daddr_t t_seekpt;
87} inotab[MAXINO];
88int ipos;
89
90#define ONTAPE 1
91#define XTRACTD 2
92#define XINUSE 4
93struct xtrlist {
94 ino_t x_ino;
95 char x_flags;
96} xtrlist[MAXXTR];
97
98char name[12];
99
100char drblock[BSIZE];
101int bpt;
102#endif
103
104int eflag;
105
106int volno = 1;
107
108struct dinode tino, dino;
109daddr_t taddr[NADDR];
110
111daddr_t curbno;
112
113short dumpmap[MSIZ];
114short clrimap[MSIZ];
115
116
117int bct = NTREC+1;
118char tbf[NTREC*OBSIZE];
119
120struct cache {
121 daddr_t c_bno;
122 int c_time;
123 char c_block[BSIZE];
124} cache[NCACHE];
125int curcache;
126
127main(argc, argv)
128char *argv[];
129{
130 register char *cp;
131 char command;
132 int done();
133
134#ifndef STANDALONE
135 mktemp(dirfile);
136 if (argc < 2) {
137usage:
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
186doit(command, argc, argv)
187char command;
188int argc;
189char *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 }
245newvol:
246 flsht();
247 close(mt);
248getvol:
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 }
266rbits:
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) {
284again:
285 if (ishead(&spcl) == 0)
286 while(gethead(&spcl) == 0)
287 ;
288 if (checktype(&spcl, TS_END) == 1) {
289 printf("end of tape\n");
290checkdone:
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);
319done:
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 (;;) {
372ragain:
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
448pass1()
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) {
467finish:
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 */
489getfile(n, f1, f2, size)
490ino_t n;
491int (*f2)(), (*f1)();
492long 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 }
512start:
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) {
527eloop:
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 */
543readtape(b, part)
544char *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++;
561loop:
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
586flsht()
587{
588 bct = NTREC+1;
589}
590
591copy(f, t, s)
592register char *f, *t;
593{
594 register i;
595
596 i = s;
597 do
598 *t++ = *f++;
599 while (--i);
600}
601
602clearbuf(cp, part)
603register 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
619putent(cp)
620char *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
634getent(bf)
635register 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 */
650writec(c)
651char c;
652{
653 drblock[bpt++] = c;
654 seekpt++;
655 if (bpt >= BSIZE) {
656 bpt = 0;
657 write(df, drblock, BSIZE);
658 }
659}
660
661readc()
662{
663 if (bpt >= BSIZE) {
664 read(df, drblock, BSIZE);
665 bpt = 0;
666 }
667 return(drblock[bpt++]);
668}
669
670mseek(pt)
671daddr_t pt;
672{
673 bpt = BSIZE;
674 lseek(df, pt, 0);
675}
676
677flsh()
678{
679 write(df, drblock, bpt+1);
680}
681
682/*
683 * search the directory inode ino
684 * looking for entry cp
685 */
686ino_t
687search(inum, cp)
688ino_t inum;
689char *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);
699found:
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 */
713psearch(n)
714char *n;
715{
716 register char *cp, *cp1;
717 char c;
718
719 ino = 2;
720 if (*(cp = n) == '/')
721 cp++;
722next:
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
741direq(s1, s2)
742register 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 */
760dwrite(bno, b)
761daddr_t bno;
762char *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
786dread(bno, buf, cnt)
787daddr_t bno;
788char *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 */
827clri(ip)
828struct 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 */
841itrunc(ip)
842register 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
877tloop(bn, f1, f2)
878daddr_t bn;
879int 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
901bfree(bn)
902daddr_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 */
923daddr_t
924balloc()
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 */
957daddr_t
958bmap(iaddr, bn)
959daddr_t iaddr[NADDR];
960daddr_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 */
1024gethead(buf)
1025struct 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 */
1036ishead(buf)
1037struct spcl *buf;
1038{
1039 if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
1040 return(0);
1041 return(1);
1042}
1043
1044checktype(b, t)
1045struct spcl *b;
1046int t;
1047{
1048 return(b->c_type == t);
1049}
1050
1051
1052checksum(b)
1053int *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
1069checkvol(b, t)
1070struct spcl *b;
1071int t;
1072{
1073 if (b->c_volume == t)
1074 return(1);
1075 return(0);
1076}
1077
1078readhdr(b)
1079struct 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
1093xtrfile(b, size)
1094char *b;
1095long size;
1096{
1097 write(ofile, b, (int) size);
1098}
1099
1100null() {;}
1101
1102skip()
1103{
1104 lseek(ofile, (long) OBSIZE, 1);
1105}
1106#endif
1107
1108
1109rstrfile(b, s)
1110char *b;
1111long s;
1112{
1113 daddr_t d;
1114
1115 d = bmap(taddr, curbno);
1116 dwrite(d, b);
1117 curbno += 1;
1118}
1119
1120rstrskip(b, s)
1121char *b;
1122long s;
1123{
1124 curbno += 1;
1125}
1126
1127#ifndef STANDALONE
1128putdir(b)
1129char *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 */
1145getdino(inum, b)
1146ino_t inum;
1147struct 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
1158putdino(inum, b)
1159ino_t inum;
1160struct 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 */
1174readbits(m)
1175short *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
1189done()
1190{
1191 unlink(dirfile);
1192 exit(0);
1193}