xref: /csrg-svn/old/512restor/512restor.c (revision 1814)
1*1814Sbill static char *sccsid = "@(#)512restor.c	4.2 (Berkeley) 11/15/80";
2944Sbill #define MAXINO	3000
3944Sbill #define BITS	8
4944Sbill #define MAXXTR	60
5944Sbill #define NCACHE	3
6944Sbill 
7944Sbill #ifndef STANDALONE
8944Sbill #include <stdio.h>
9944Sbill #include <signal.h>
10944Sbill #endif
11944Sbill #include <sys/param.h>
12944Sbill #include <sys/inode.h>
13944Sbill #include <sys/ino.h>
14944Sbill #include <sys/fblk.h>
15944Sbill #include <sys/filsys.h>
16944Sbill #include <sys/dir.h>
17944Sbill 
18944Sbill #define	OBSIZE	512
19944Sbill 
20944Sbill /* from old <ino.h> */
21944Sbill 
22944Sbill #define	OINOPB	8	/* 8 inodes per block */
23944Sbill 
24944Sbill /* old <dumprestor.h> */
25944Sbill #define NTREC   	20
26944Sbill #define MLEN    	16
27944Sbill #define MSIZ    	4096
28944Sbill 
29944Sbill #define TS_TAPE 	1
30944Sbill #define TS_INODE	2
31944Sbill #define TS_BITS 	3
32944Sbill #define TS_ADDR 	4
33944Sbill #define TS_END  	5
34944Sbill #define TS_CLRI 	6
35944Sbill #define MAGIC   	(int)60011
36944Sbill #define CHECKSUM	(int)84446
37944Sbill struct	spcl
38944Sbill {
39944Sbill 	int	c_type;
40944Sbill 	time_t	c_date;
41944Sbill 	time_t	c_ddate;
42944Sbill 	int	c_volume;
43944Sbill 	daddr_t	c_tapea;
44944Sbill 	ino_t	c_inumber;
45944Sbill 	int	c_magic;
46944Sbill 	int	c_checksum;
47944Sbill 	struct	dinode	c_dinode;
48944Sbill 	int	c_count;
49944Sbill 	char	c_addr[OBSIZE];
50944Sbill } spcl;
51944Sbill 
52944Sbill struct	idates
53944Sbill {
54944Sbill 	char	id_name[16];
55944Sbill 	char	id_incno;
56944Sbill 	time_t	id_ddate;
57944Sbill };
58944Sbill 
59944Sbill /* end of old <dumprestor.h> */
60944Sbill 
61944Sbill #define	MWORD(m,i) (m[(unsigned)(i-1)/MLEN])
62944Sbill #define	MBIT(i)	(1<<((unsigned)(i-1)%MLEN))
63944Sbill #define	BIS(i,w)	(MWORD(w,i) |=  MBIT(i))
64944Sbill #define	BIC(i,w)	(MWORD(w,i) &= ~MBIT(i))
65944Sbill #define	BIT(i,w)	(MWORD(w,i) & MBIT(i))
66944Sbill 
67944Sbill struct	filsys	sblock;
68944Sbill 
69944Sbill int	fi;
70944Sbill ino_t	ino, maxi, curino;
71944Sbill 
72944Sbill int	mt;
73*1814Sbill char	tapename[] = "/dev/rmt8";
74944Sbill char	*magtape = tapename;
75944Sbill #ifdef STANDALONE
76944Sbill char	mbuf[50];
77944Sbill #endif
78944Sbill 
79944Sbill #ifndef STANDALONE
80944Sbill daddr_t	seekpt;
81944Sbill int	df, ofile;
82944Sbill char	dirfile[] = "rstXXXXXX";
83944Sbill 
84944Sbill struct {
85944Sbill 	ino_t	t_ino;
86944Sbill 	daddr_t	t_seekpt;
87944Sbill } inotab[MAXINO];
88944Sbill int	ipos;
89944Sbill 
90944Sbill #define ONTAPE	1
91944Sbill #define XTRACTD	2
92944Sbill #define XINUSE	4
93944Sbill struct xtrlist {
94944Sbill 	ino_t	x_ino;
95944Sbill 	char	x_flags;
96944Sbill } xtrlist[MAXXTR];
97944Sbill 
98944Sbill char	name[12];
99944Sbill 
100944Sbill char	drblock[BSIZE];
101944Sbill int	bpt;
102944Sbill #endif
103944Sbill 
104944Sbill int	eflag;
105944Sbill 
106944Sbill int	volno = 1;
107944Sbill 
108944Sbill struct dinode tino, dino;
109944Sbill daddr_t	taddr[NADDR];
110944Sbill 
111944Sbill daddr_t	curbno;
112944Sbill 
113944Sbill short	dumpmap[MSIZ];
114944Sbill short	clrimap[MSIZ];
115944Sbill 
116944Sbill 
117944Sbill int bct = NTREC+1;
118944Sbill char tbf[NTREC*OBSIZE];
119944Sbill 
120944Sbill struct	cache {
121944Sbill 	daddr_t	c_bno;
122944Sbill 	int	c_time;
123944Sbill 	char	c_block[BSIZE];
124944Sbill } cache[NCACHE];
125944Sbill int	curcache;
126944Sbill 
main(argc,argv)127944Sbill main(argc, argv)
128944Sbill char *argv[];
129944Sbill {
130944Sbill 	register char *cp;
131944Sbill 	char command;
132944Sbill 	int done();
133944Sbill 
134944Sbill #ifndef STANDALONE
135944Sbill 	mktemp(dirfile);
136944Sbill 	if (argc < 2) {
137944Sbill usage:
138944Sbill 		printf("Usage: oldrestor x file file..., oldrestor r filesys, or oldrestor t\n");
139944Sbill 		exit(1);
140944Sbill 	}
141944Sbill 	argv++;
142944Sbill 	argc -= 2;
143944Sbill 	for (cp = *argv++; *cp; cp++) {
144944Sbill 		switch (*cp) {
145944Sbill 		case '-':
146944Sbill 			break;
147944Sbill 		case 'f':
148944Sbill 			magtape = *argv++;
149944Sbill 			argc--;
150944Sbill 			break;
151944Sbill 		case 'r':
152944Sbill 		case 'R':
153944Sbill 		case 't':
154944Sbill 		case 'x':
155944Sbill 			command = *cp;
156944Sbill 			break;
157944Sbill 		default:
158944Sbill 			printf("Bad key character %c\n", *cp);
159944Sbill 			goto usage;
160944Sbill 		}
161944Sbill 	}
162944Sbill 	if (command == 'x') {
163944Sbill 		if (signal(SIGINT, done) == SIG_IGN)
164944Sbill 			signal(SIGINT, SIG_IGN);
165944Sbill 		if (signal(SIGTERM, done) == SIG_IGN)
166944Sbill 			signal(SIGTERM, SIG_IGN);
167944Sbill 
168944Sbill 		df = creat(dirfile, 0666);
169944Sbill 		if (df < 0) {
170944Sbill 			printf("restor: %s - cannot create directory temporary\n", dirfile);
171944Sbill 			exit(1);
172944Sbill 		}
173944Sbill 		close(df);
174944Sbill 		df = open(dirfile, 2);
175944Sbill 	}
176944Sbill 	doit(command, argc, argv);
177944Sbill 	if (command == 'x')
178944Sbill 		unlink(dirfile);
179944Sbill 	exit(0);
180944Sbill #else
181944Sbill 	magtape = "tape";
182944Sbill 	doit('r', 1, 0);
183944Sbill #endif
184944Sbill }
185944Sbill 
doit(command,argc,argv)186944Sbill doit(command, argc, argv)
187944Sbill char	command;
188944Sbill int	argc;
189944Sbill char	*argv[];
190944Sbill {
191944Sbill 	extern char *ctime();
192944Sbill 	register i, k;
193944Sbill 	ino_t	d;
194944Sbill #ifndef STANDALONE
195944Sbill 	int	xtrfile(), skip();
196944Sbill #endif
197944Sbill 	int	rstrfile(), rstrskip();
198944Sbill 	struct dinode *ip, *ip1;
199944Sbill 
200944Sbill #ifndef STANDALONE
201944Sbill 	if ((mt = open(magtape, 0)) < 0) {
202944Sbill 		printf("%s: cannot open tape\n", magtape);
203944Sbill 		exit(1);
204944Sbill 	}
205944Sbill #else
206944Sbill 	do {
207944Sbill 		printf("Tape? ");
208944Sbill 		gets(mbuf);
209944Sbill 		mt = open(mbuf, 0);
210944Sbill 	} while (mt == -1);
211944Sbill 	magtape = mbuf;
212944Sbill #endif
213944Sbill 	switch(command) {
214944Sbill #ifndef STANDALONE
215944Sbill 	case 't':
216944Sbill 		if (readhdr(&spcl) == 0) {
217944Sbill 			printf("Tape is not a dump tape\n");
218944Sbill 			exit(1);
219944Sbill 		}
220944Sbill 		printf("Dump   date: %s", ctime(&spcl.c_date));
221944Sbill 		printf("Dumped from: %s", ctime(&spcl.c_ddate));
222944Sbill 		return;
223944Sbill 	case 'x':
224944Sbill 		if (readhdr(&spcl) == 0) {
225944Sbill 			printf("Tape is not a dump tape\n");
226944Sbill 			exit(1);
227944Sbill 		}
228944Sbill 		if (checkvol(&spcl, 1) == 0) {
229944Sbill 			printf("Tape is not volume 1 of the dump\n");
230944Sbill 			exit(1);
231944Sbill 		}
232944Sbill 		pass1();  /* This sets the various maps on the way by */
233944Sbill 		i = 0;
234944Sbill 		while (i < MAXXTR-1 && argc--) {
235944Sbill 			if ((d = psearch(*argv)) == 0 || BIT(d, dumpmap) == 0) {
236944Sbill 				printf("%s: not on the tape\n", *argv++);
237944Sbill 				continue;
238944Sbill 			}
239944Sbill 			xtrlist[i].x_ino = d;
240944Sbill 			xtrlist[i].x_flags |= XINUSE;
241944Sbill 			printf("%s: inode %u\n", *argv, d);
242944Sbill 			argv++;
243944Sbill 			i++;
244944Sbill 		}
245944Sbill newvol:
246944Sbill 		flsht();
247944Sbill 		close(mt);
248944Sbill getvol:
249944Sbill 		printf("Mount desired tape volume: Specify volume #: ");
250944Sbill 		if (gets(tbf) == NULL)
251944Sbill 			return;
252944Sbill 		volno = atoi(tbf);
253944Sbill 		if (volno <= 0) {
254944Sbill 			printf("Volume numbers are positive numerics\n");
255944Sbill 			goto getvol;
256944Sbill 		}
257944Sbill 		mt = open(magtape, 0);
258944Sbill 		if (readhdr(&spcl) == 0) {
259944Sbill 			printf("tape is not dump tape\n");
260944Sbill 			goto newvol;
261944Sbill 		}
262944Sbill 		if (checkvol(&spcl, volno) == 0) {
263944Sbill 			printf("Wrong volume (%d)\n", spcl.c_volume);
264944Sbill 			goto newvol;
265944Sbill 		}
266944Sbill rbits:
267944Sbill 		while (gethead(&spcl) == 0)
268944Sbill 			;
269944Sbill 		if (checktype(&spcl, TS_INODE) == 1) {
270944Sbill 			printf("Can't find inode mask!\n");
271944Sbill 			goto newvol;
272944Sbill 		}
273944Sbill 		if (checktype(&spcl, TS_BITS) == 0)
274944Sbill 			goto rbits;
275944Sbill 		readbits(dumpmap);
276944Sbill 		i = 0;
277944Sbill 		for (k = 0; xtrlist[k].x_flags; k++) {
278944Sbill 			if (BIT(xtrlist[k].x_ino, dumpmap)) {
279944Sbill 				xtrlist[k].x_flags |= ONTAPE;
280944Sbill 				i++;
281944Sbill 			}
282944Sbill 		}
283944Sbill 		while (i > 0) {
284944Sbill again:
285944Sbill 			if (ishead(&spcl) == 0)
286944Sbill 				while(gethead(&spcl) == 0)
287944Sbill 					;
288944Sbill 			if (checktype(&spcl, TS_END) == 1) {
289944Sbill 				printf("end of tape\n");
290944Sbill checkdone:
291944Sbill 				for (k = 0; xtrlist[k].x_flags; k++)
292944Sbill 					if ((xtrlist[k].x_flags&XTRACTD) == 0)
293944Sbill 						goto newvol;
294944Sbill 					return;
295944Sbill 			}
296944Sbill 			if (checktype(&spcl, TS_INODE) == 0) {
297944Sbill 				gethead(&spcl);
298944Sbill 				goto again;
299944Sbill 			}
300944Sbill 			d = spcl.c_inumber;
301944Sbill 			for (k = 0; xtrlist[k].x_flags; k++) {
302944Sbill 				if (d == xtrlist[k].x_ino) {
303944Sbill 					printf("extract file %u\n", xtrlist[k].x_ino);
304944Sbill 					sprintf(name, "%u", xtrlist[k].x_ino);
305944Sbill 					if ((ofile = creat(name, 0666)) < 0) {
306944Sbill 						printf("%s: cannot create file\n", name);
307944Sbill 						i--;
308944Sbill 						continue;
309944Sbill 					}
310944Sbill 					chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
311944Sbill 					getfile(ino, xtrfile, skip, spcl.c_dinode.di_size);
312944Sbill 					i--;
313944Sbill 					xtrlist[k].x_flags |= XTRACTD;
314944Sbill 					close(ofile);
315944Sbill 					goto done;
316944Sbill 				}
317944Sbill 			}
318944Sbill 			gethead(&spcl);
319944Sbill done:
320944Sbill 			;
321944Sbill 		}
322944Sbill 		goto checkdone;
323944Sbill #endif
324944Sbill 	case 'r':
325944Sbill 	case 'R':
326944Sbill #ifndef STANDALONE
327944Sbill 		if ((fi = open(*argv, 2)) < 0) {
328944Sbill 			printf("%s: cannot open\n", *argv);
329944Sbill 			exit(1);
330944Sbill 		}
331944Sbill #else
332944Sbill 		do {
333944Sbill 			char charbuf[50];
334944Sbill 
335944Sbill 			printf("Disk? ");
336944Sbill 			gets(charbuf);
337944Sbill 			fi = open(charbuf, 2);
338944Sbill 		} while (fi == -1);
339944Sbill #endif
340944Sbill #ifndef STANDALONE
341944Sbill 		if (command == 'R') {
342944Sbill 			printf("Enter starting volume number: ");
343944Sbill 			if (gets(tbf) == EOF) {
344944Sbill 				volno = 1;
345944Sbill 				printf("\n");
346944Sbill 			}
347944Sbill 			else
348944Sbill 				volno = atoi(tbf);
349944Sbill 		}
350944Sbill 		else
351944Sbill #endif
352944Sbill 			volno = 1;
353944Sbill 		printf("Last chance before scribbling on %s. ",
354944Sbill #ifdef STANDALONE
355944Sbill 								"disk");
356944Sbill #else
357944Sbill 								*argv);
358944Sbill #endif
359944Sbill 		while (getchar() != '\n');
360944Sbill 		dread((daddr_t)1, (char *)&sblock, sizeof(sblock));
361944Sbill 		maxi = (sblock.s_isize-2)*INOPB;
362944Sbill 		if (readhdr(&spcl) == 0) {
363944Sbill 			printf("Missing volume record\n");
364944Sbill 			exit(1);
365944Sbill 		}
366944Sbill 		if (checkvol(&spcl, volno) == 0) {
367944Sbill 			printf("Tape is not volume %d\n", volno);
368944Sbill 			exit(1);
369944Sbill 		}
370944Sbill 		gethead(&spcl);
371944Sbill 		for (;;) {
372944Sbill ragain:
373944Sbill 			if (ishead(&spcl) == 0) {
374944Sbill 				printf("Missing header block\n");
375944Sbill 				while (gethead(&spcl) == 0)
376944Sbill 					;
377944Sbill 				eflag++;
378944Sbill 			}
379944Sbill 			if (checktype(&spcl, TS_END) == 1) {
380944Sbill 				printf("End of tape\n");
381944Sbill 				close(mt);
382944Sbill 				dwrite( (daddr_t) 1, (char *) &sblock);
383944Sbill 				return;
384944Sbill 			}
385944Sbill 			if (checktype(&spcl, TS_CLRI) == 1) {
386944Sbill 				readbits(clrimap);
387944Sbill 				for (ino = 1; ino <= maxi; ino++)
388944Sbill 					if (BIT(ino, clrimap) == 0) {
389944Sbill 						getdino(ino, &tino);
390944Sbill 						if (tino.di_mode == 0)
391944Sbill 							continue;
392944Sbill 						itrunc(&tino);
393944Sbill 						clri(&tino);
394944Sbill 						putdino(ino, &tino);
395944Sbill 					}
396944Sbill 				dwrite( (daddr_t) 1, (char *) &sblock);
397944Sbill 				goto ragain;
398944Sbill 			}
399944Sbill 			if (checktype(&spcl, TS_BITS) == 1) {
400944Sbill 				readbits(dumpmap);
401944Sbill 				goto ragain;
402944Sbill 			}
403944Sbill 			if (checktype(&spcl, TS_INODE) == 0) {
404944Sbill 				printf("Unknown header type\n");
405944Sbill 				eflag++;
406944Sbill 				gethead(&spcl);
407944Sbill 				goto ragain;
408944Sbill 			}
409944Sbill 			ino = spcl.c_inumber;
410944Sbill 			if (eflag)
411944Sbill 				printf("Resynced at inode %u\n", ino);
412944Sbill 			eflag = 0;
413944Sbill 			if (ino > maxi) {
414944Sbill 				printf("%u: ilist too small\n", ino);
415944Sbill 				gethead(&spcl);
416944Sbill 				goto ragain;
417944Sbill 			}
418944Sbill 			dino = spcl.c_dinode;
419944Sbill 			getdino(ino, &tino);
420944Sbill 			curbno = 0;
421944Sbill 			itrunc(&tino);
422944Sbill 			clri(&tino);
423944Sbill 			for (i = 0; i < NADDR; i++)
424944Sbill 				taddr[i] = 0;
425944Sbill 			l3tol(taddr, dino.di_addr, 1);
426944Sbill 			getfile(d, rstrfile, rstrskip, dino.di_size);
427944Sbill 			ip = &tino;
428944Sbill 			ltol3(ip->di_addr, taddr, NADDR);
429944Sbill 			ip1 = &dino;
430944Sbill 			ip->di_mode = ip1->di_mode;
431944Sbill 			ip->di_nlink = ip1->di_nlink;
432944Sbill 			ip->di_uid = ip1->di_uid;
433944Sbill 			ip->di_gid = ip1->di_gid;
434944Sbill 			ip->di_size = ip1->di_size;
435944Sbill 			ip->di_atime = ip1->di_atime;
436944Sbill 			ip->di_mtime = ip1->di_mtime;
437944Sbill 			ip->di_ctime = ip1->di_ctime;
438944Sbill 			putdino(ino, &tino);
439944Sbill 		}
440944Sbill 	}
441944Sbill }
442944Sbill 
443944Sbill /*
444944Sbill  * Read the tape, bulding up a directory structure for extraction
445944Sbill  * by name
446944Sbill  */
447944Sbill #ifndef STANDALONE
pass1()448944Sbill pass1()
449944Sbill {
450944Sbill 	register i;
451944Sbill 	struct dinode *ip;
452944Sbill 	int	putdir(), null();
453944Sbill 
454944Sbill 	while (gethead(&spcl) == 0) {
455944Sbill 		printf("Can't find directory header!\n");
456944Sbill 	}
457944Sbill 	for (;;) {
458944Sbill 		if (checktype(&spcl, TS_BITS) == 1) {
459944Sbill 			readbits(dumpmap);
460944Sbill 			continue;
461944Sbill 		}
462944Sbill 		if (checktype(&spcl, TS_CLRI) == 1) {
463944Sbill 			readbits(clrimap);
464944Sbill 			continue;
465944Sbill 		}
466944Sbill 		if (checktype(&spcl, TS_INODE) == 0) {
467944Sbill finish:
468944Sbill 			flsh();
469944Sbill 			close(mt);
470944Sbill 			return;
471944Sbill 		}
472944Sbill 		ip = &spcl.c_dinode;
473944Sbill 		i = ip->di_mode & IFMT;
474944Sbill 		if (i != IFDIR) {
475944Sbill 			goto finish;
476944Sbill 		}
477944Sbill 		inotab[ipos].t_ino = spcl.c_inumber;
478944Sbill 		inotab[ipos++].t_seekpt = seekpt;
479944Sbill 		getfile(spcl.c_inumber, putdir, null, spcl.c_dinode.di_size);
480944Sbill 		putent("\000\000/");
481944Sbill 	}
482944Sbill }
483944Sbill #endif
484944Sbill 
485944Sbill /*
486944Sbill  * Do the file extraction, calling the supplied functions
487944Sbill  * with the blocks
488944Sbill  */
getfile(n,f1,f2,size)489944Sbill getfile(n, f1, f2, size)
490944Sbill ino_t	n;
491944Sbill int	(*f2)(), (*f1)();
492944Sbill long	size;
493944Sbill {
494944Sbill 	register i;
495944Sbill 	struct spcl addrblock;
496944Sbill 	char buf[BSIZE];
497944Sbill 
498944Sbill 	addrblock = spcl;
499944Sbill 	curino = n;
500944Sbill 	goto start;
501944Sbill 	for (;;) {
502944Sbill 		if (gethead(&addrblock) == 0) {
503944Sbill 			printf("Missing address (header) block\n");
504944Sbill 			goto eloop;
505944Sbill 		}
506944Sbill 		if (checktype(&addrblock, TS_ADDR) == 0) {
507944Sbill 			spcl = addrblock;
508944Sbill 			curino = 0;
509944Sbill 			curino = 0;
510944Sbill 			return;
511944Sbill 		}
512944Sbill start:
513944Sbill 		for (i = 0; i < addrblock.c_count; i += 2) {
514944Sbill 			if (addrblock.c_addr[i])
515944Sbill 				readtape(buf, 0);
516944Sbill 			else
517944Sbill 				clearbuf(buf, 0);
518944Sbill 			if (size > OBSIZE && addrblock.c_addr[i+1])
519944Sbill 				readtape(buf, 1);
520944Sbill 			else
521944Sbill 				clearbuf(buf, 1);
522944Sbill 			if (addrblock.c_addr[i] || size > OBSIZE && addrblock.c_addr[i + 1])
523944Sbill 				(*f1)(buf, size > BSIZE ? (long) BSIZE : size);
524944Sbill 			else
525944Sbill 				(*f2)(buf, size > BSIZE ? (long) BSIZE : size);
526944Sbill 			if ((size -= BSIZE) <= 0) {
527944Sbill eloop:
528944Sbill 				while (gethead(&spcl) == 0)
529944Sbill 					;
530944Sbill 				if (checktype(&spcl, TS_ADDR) == 1)
531944Sbill 					goto eloop;
532944Sbill 				curino = 0;
533944Sbill 				return;
534944Sbill 			}
535944Sbill 		}
536944Sbill 	}
537944Sbill }
538944Sbill 
539944Sbill /*
540944Sbill  * Do the tape i\/o, dealling with volume changes
541944Sbill  * etc..
542944Sbill  */
readtape(b,part)543944Sbill readtape(b, part)
544944Sbill char *b;
545944Sbill {
546944Sbill 	register i;
547944Sbill 	struct spcl tmpbuf;
548944Sbill 
549944Sbill 	if (bct >= NTREC) {
550944Sbill 		for (i = 0; i < NTREC; i++)
551944Sbill 			((struct spcl *)&tbf[i*OBSIZE])->c_magic = 0;
552944Sbill 		bct = 0;
553944Sbill 		if ((i = read(mt, tbf, NTREC*OBSIZE)) < 0) {
554944Sbill 			printf("Tape read error: inode %u\n", curino);
555944Sbill 			eflag++;
556944Sbill 			exit(1);
557944Sbill 		}
558944Sbill 		if (i == 0) {
559944Sbill 			bct = NTREC + 1;
560944Sbill 			volno++;
561944Sbill loop:
562944Sbill 			flsht();
563944Sbill 			close(mt);
564944Sbill 			printf("Mount volume %d\n", volno);
565944Sbill 			while (getchar() != '\n')
566944Sbill 				;
567944Sbill 			if ((mt = open(magtape, 0)) == -1) {
568944Sbill 				printf("Cannot open tape!\n");
569944Sbill 				goto loop;
570944Sbill 			}
571944Sbill 			if (readhdr(&tmpbuf) == 0) {
572944Sbill 				printf("Not a dump tape.Try again\n");
573944Sbill 				goto loop;
574944Sbill 			}
575944Sbill 			if (checkvol(&tmpbuf, volno) == 0) {
576944Sbill 				printf("Wrong tape. Try again\n");
577944Sbill 				goto loop;
578944Sbill 			}
579944Sbill 			readtape(b, part);
580944Sbill 			return;
581944Sbill 		}
582944Sbill 	}
583944Sbill 	copy(&tbf[(bct++*OBSIZE)], b + part * OBSIZE, OBSIZE);
584944Sbill }
585944Sbill 
flsht()586944Sbill flsht()
587944Sbill {
588944Sbill 	bct = NTREC+1;
589944Sbill }
590944Sbill 
copy(f,t,s)591944Sbill copy(f, t, s)
592944Sbill register char *f, *t;
593944Sbill {
594944Sbill 	register i;
595944Sbill 
596944Sbill 	i = s;
597944Sbill 	do
598944Sbill 		*t++ = *f++;
599944Sbill 	while (--i);
600944Sbill }
601944Sbill 
clearbuf(cp,part)602944Sbill clearbuf(cp, part)
603944Sbill register char *cp;
604944Sbill {
605944Sbill 	register i;
606944Sbill 
607944Sbill 	cp += part * OBSIZE;
608944Sbill 	i = OBSIZE;
609944Sbill 	do
610944Sbill 		*cp++ = 0;
611944Sbill 	while (--i);
612944Sbill }
613944Sbill 
614944Sbill /*
615944Sbill  * Put and get the directory entries from the compressed
616944Sbill  * directory file
617944Sbill  */
618944Sbill #ifndef STANDALONE
putent(cp)619944Sbill putent(cp)
620944Sbill char	*cp;
621944Sbill {
622944Sbill 	register i;
623944Sbill 
624944Sbill 	for (i = 0; i < sizeof(ino_t); i++)
625944Sbill 		writec(*cp++);
626944Sbill 	for (i = 0; i < DIRSIZ; i++) {
627944Sbill 		writec(*cp);
628944Sbill 		if (*cp++ == 0)
629944Sbill 			return;
630944Sbill 	}
631944Sbill 	return;
632944Sbill }
633944Sbill 
getent(bf)634944Sbill getent(bf)
635944Sbill register char *bf;
636944Sbill {
637944Sbill 	register i;
638944Sbill 
639944Sbill 	for (i = 0; i < sizeof(ino_t); i++)
640944Sbill 		*bf++ = readc();
641944Sbill 	for (i = 0; i < DIRSIZ; i++)
642944Sbill 		if ((*bf++ = readc()) == 0)
643944Sbill 			return;
644944Sbill 	return;
645944Sbill }
646944Sbill 
647944Sbill /*
648944Sbill  * read/write te directory file
649944Sbill  */
writec(c)650944Sbill writec(c)
651944Sbill char c;
652944Sbill {
653944Sbill 	drblock[bpt++] = c;
654944Sbill 	seekpt++;
655944Sbill 	if (bpt >= BSIZE) {
656944Sbill 		bpt = 0;
657944Sbill 		write(df, drblock, BSIZE);
658944Sbill 	}
659944Sbill }
660944Sbill 
readc()661944Sbill readc()
662944Sbill {
663944Sbill 	if (bpt >= BSIZE) {
664944Sbill 		read(df, drblock, BSIZE);
665944Sbill 		bpt = 0;
666944Sbill 	}
667944Sbill 	return(drblock[bpt++]);
668944Sbill }
669944Sbill 
mseek(pt)670944Sbill mseek(pt)
671944Sbill daddr_t pt;
672944Sbill {
673944Sbill 	bpt = BSIZE;
674944Sbill 	lseek(df, pt, 0);
675944Sbill }
676944Sbill 
flsh()677944Sbill flsh()
678944Sbill {
679944Sbill 	write(df, drblock, bpt+1);
680944Sbill }
681944Sbill 
682944Sbill /*
683944Sbill  * search the directory inode ino
684944Sbill  * looking for entry cp
685944Sbill  */
686944Sbill ino_t
search(inum,cp)687944Sbill search(inum, cp)
688944Sbill ino_t	inum;
689944Sbill char	*cp;
690944Sbill {
691944Sbill 	register i;
692944Sbill 	struct direct dir;
693944Sbill 
694944Sbill 	for (i = 0; i < MAXINO; i++)
695944Sbill 		if (inotab[i].t_ino == inum) {
696944Sbill 			goto found;
697944Sbill 		}
698944Sbill 	return(0);
699944Sbill found:
700944Sbill 	mseek(inotab[i].t_seekpt);
701944Sbill 	do {
702944Sbill 		getent((char *)&dir);
703944Sbill 		if (direq(dir.d_name, "/"))
704944Sbill 			return(0);
705944Sbill 	} while (direq(dir.d_name, cp) == 0);
706944Sbill 	return(dir.d_ino);
707944Sbill }
708944Sbill 
709944Sbill /*
710944Sbill  * Search the directory tree rooted at inode 2
711944Sbill  * for the path pointed at by n
712944Sbill  */
psearch(n)713944Sbill psearch(n)
714944Sbill char	*n;
715944Sbill {
716944Sbill 	register char *cp, *cp1;
717944Sbill 	char c;
718944Sbill 
719944Sbill 	ino = 2;
720944Sbill 	if (*(cp = n) == '/')
721944Sbill 		cp++;
722944Sbill next:
723944Sbill 	cp1 = cp + 1;
724944Sbill 	while (*cp1 != '/' && *cp1)
725944Sbill 		cp1++;
726944Sbill 	c = *cp1;
727944Sbill 	*cp1 = 0;
728944Sbill 	ino = search(ino, cp);
729944Sbill 	if (ino == 0) {
730944Sbill 		*cp1 = c;
731944Sbill 		return(0);
732944Sbill 	}
733944Sbill 	*cp1 = c;
734944Sbill 	if (c == '/') {
735944Sbill 		cp = cp1+1;
736944Sbill 		goto next;
737944Sbill 	}
738944Sbill 	return(ino);
739944Sbill }
740944Sbill 
direq(s1,s2)741944Sbill direq(s1, s2)
742944Sbill register char *s1, *s2;
743944Sbill {
744944Sbill 	register i;
745944Sbill 
746944Sbill 	for (i = 0; i < DIRSIZ; i++)
747944Sbill 		if (*s1++ == *s2) {
748944Sbill 			if (*s2++ == 0)
749944Sbill 				return(1);
750944Sbill 		} else
751944Sbill 			return(0);
752944Sbill 	return(1);
753944Sbill }
754944Sbill #endif
755944Sbill 
756944Sbill /*
757944Sbill  * read/write a disk block, be sure to update the buffer
758944Sbill  * cache if needed.
759944Sbill  */
dwrite(bno,b)760944Sbill dwrite(bno, b)
761944Sbill daddr_t	bno;
762944Sbill char	*b;
763944Sbill {
764944Sbill 	register i;
765944Sbill 
766944Sbill 	for (i = 0; i < NCACHE; i++) {
767944Sbill 		if (cache[i].c_bno == bno) {
768944Sbill 			copy(b, cache[i].c_block, BSIZE);
769944Sbill 			cache[i].c_time = 0;
770944Sbill 			break;
771944Sbill 		}
772944Sbill 		else
773944Sbill 			cache[i].c_time++;
774944Sbill 	}
775944Sbill 	lseek(fi, bno*BSIZE, 0);
776944Sbill 	if(write(fi, b, BSIZE) != BSIZE) {
777944Sbill #ifdef STANDALONE
778944Sbill 		printf("disk write error %D\n", bno);
779944Sbill #else
780944Sbill 		fprintf(stderr, "disk write error %ld\n", bno);
781944Sbill #endif
782944Sbill 		exit(1);
783944Sbill 	}
784944Sbill }
785944Sbill 
dread(bno,buf,cnt)786944Sbill dread(bno, buf, cnt)
787944Sbill daddr_t bno;
788944Sbill char *buf;
789944Sbill {
790944Sbill 	register i, j;
791944Sbill 
792944Sbill 	j = 0;
793944Sbill 	for (i = 0; i < NCACHE; i++) {
794944Sbill 		if (++curcache >= NCACHE)
795944Sbill 			curcache = 0;
796944Sbill 		if (cache[curcache].c_bno == bno) {
797944Sbill 			copy(cache[curcache].c_block, buf, cnt);
798944Sbill 			cache[curcache].c_time = 0;
799944Sbill 			return;
800944Sbill 		}
801944Sbill 		else {
802944Sbill 			cache[curcache].c_time++;
803944Sbill 			if (cache[j].c_time < cache[curcache].c_time)
804944Sbill 				j = curcache;
805944Sbill 		}
806944Sbill 	}
807944Sbill 
808944Sbill 	lseek(fi, bno*BSIZE, 0);
809944Sbill 	if (read(fi, cache[j].c_block, BSIZE) != BSIZE) {
810944Sbill #ifdef STANDALONE
811944Sbill 		printf("read error %D\n", bno);
812944Sbill #else
813944Sbill 		printf("read error %ld\n", bno);
814944Sbill #endif
815944Sbill 		exit(1);
816944Sbill 	}
817944Sbill 	copy(cache[j].c_block, buf, cnt);
818944Sbill 	cache[j].c_time = 0;
819944Sbill 	cache[j].c_bno = bno;
820944Sbill }
821944Sbill 
822944Sbill /*
823944Sbill  * the inode manpulation routines. Like the system.
824944Sbill  *
825944Sbill  * clri zeros the inode
826944Sbill  */
827944Sbill clri(ip)
828944Sbill struct dinode *ip;
829944Sbill {
830944Sbill 	int i, *p;
831944Sbill 	i = sizeof(struct dinode)/sizeof(int);
832944Sbill 	p = (int *)ip;
833944Sbill 	do
834944Sbill 		*p++ = 0;
835944Sbill 	while(--i);
836944Sbill }
837944Sbill 
838944Sbill /*
839944Sbill  * itrunc/tloop/bfree free all of the blocks pointed at by the inode
840944Sbill  */
itrunc(ip)841944Sbill itrunc(ip)
842944Sbill register struct dinode *ip;
843944Sbill {
844944Sbill 	register i;
845944Sbill 	daddr_t bn, iaddr[NADDR];
846944Sbill 
847944Sbill 	if (ip->di_mode == 0)
848944Sbill 		return;
849944Sbill 	i = ip->di_mode & IFMT;
850944Sbill 	if (i != IFDIR && i != IFREG)
851944Sbill 		return;
852944Sbill 	l3tol(iaddr, ip->di_addr, NADDR);
853944Sbill 	for(i=NADDR-1;i>=0;i--) {
854944Sbill 		bn = iaddr[i];
855944Sbill 		if(bn == 0) continue;
856944Sbill 		switch(i) {
857944Sbill 
858944Sbill 		default:
859944Sbill 			bfree(bn);
860944Sbill 			break;
861944Sbill 
862944Sbill 		case NADDR-3:
863944Sbill 			tloop(bn, 0, 0);
864944Sbill 			break;
865944Sbill 
866944Sbill 		case NADDR-2:
867944Sbill 			tloop(bn, 1, 0);
868944Sbill 			break;
869944Sbill 
870944Sbill 		case NADDR-1:
871944Sbill 			tloop(bn, 1, 1);
872944Sbill 		}
873944Sbill 	}
874944Sbill 	ip->di_size = 0;
875944Sbill }
876944Sbill 
tloop(bn,f1,f2)877944Sbill tloop(bn, f1, f2)
878944Sbill daddr_t	bn;
879944Sbill int	f1, f2;
880944Sbill {
881944Sbill 	register i;
882944Sbill 	daddr_t nb;
883944Sbill 	union {
884944Sbill 		char	data[BSIZE];
885944Sbill 		daddr_t	indir[NINDIR];
886944Sbill 	} ibuf;
887944Sbill 
888944Sbill 	dread(bn, ibuf.data, BSIZE);
889944Sbill 	for(i=NINDIR-1;i>=0;i--) {
890944Sbill 		nb = ibuf.indir[i];
891944Sbill 		if(nb) {
892944Sbill 			if(f1)
893944Sbill 				tloop(nb, f2, 0);
894944Sbill 			else
895944Sbill 				bfree(nb);
896944Sbill 		}
897944Sbill 	}
898944Sbill 	bfree(bn);
899944Sbill }
900944Sbill 
bfree(bn)901944Sbill bfree(bn)
902944Sbill daddr_t	bn;
903944Sbill {
904944Sbill 	register i;
905944Sbill 	union {
906944Sbill 		char	data[BSIZE];
907944Sbill 		struct	fblk frees;
908944Sbill 	} fbuf;
909944Sbill 
910944Sbill 	if(sblock.s_nfree >= NICFREE) {
911944Sbill 		fbuf.df_nfree = sblock.s_nfree;
912944Sbill 		for(i=0;i<NICFREE;i++)
913944Sbill 			fbuf.df_free[i] = sblock.s_free[i];
914944Sbill 		sblock.s_nfree = 0;
915944Sbill 		dwrite(bn, fbuf.data);
916944Sbill 	}
917944Sbill 	sblock.s_free[sblock.s_nfree++] = bn;
918944Sbill }
919944Sbill 
920944Sbill /*
921944Sbill  * allocate a block off the free list.
922944Sbill  */
923944Sbill daddr_t
balloc()924944Sbill balloc()
925944Sbill {
926944Sbill 	daddr_t	bno;
927944Sbill 	register i;
928944Sbill 	static char zeroes[BSIZE];
929944Sbill 	union {
930944Sbill 		char	data[BSIZE];
931944Sbill 		struct	fblk frees;
932944Sbill 	} fbuf;
933944Sbill 
934944Sbill 	if(sblock.s_nfree == 0 || (bno=sblock.s_free[--sblock.s_nfree]) == 0) {
935944Sbill #ifdef STANDALONE
936944Sbill 		printf("Out of space\n");
937944Sbill #else
938944Sbill 		fprintf(stderr, "Out of space.\n");
939944Sbill #endif
940944Sbill 		exit(1);
941944Sbill 	}
942944Sbill 	if(sblock.s_nfree == 0) {
943944Sbill 		dread(bno, fbuf.data, BSIZE);
944944Sbill 		sblock.s_nfree = fbuf.df_nfree;
945944Sbill 		for(i=0;i<NICFREE;i++)
946944Sbill 			sblock.s_free[i] = fbuf.df_free[i];
947944Sbill 	}
948944Sbill 	dwrite(bno, zeroes);
949944Sbill 	return(bno);
950944Sbill }
951944Sbill 
952944Sbill /*
953944Sbill  * map a block number into a block address, ensuring
954944Sbill  * all of the correct indirect blocks are around. Allocate
955944Sbill  * the block requested.
956944Sbill  */
957944Sbill daddr_t
bmap(iaddr,bn)958944Sbill bmap(iaddr, bn)
959944Sbill daddr_t	iaddr[NADDR];
960944Sbill daddr_t	bn;
961944Sbill {
962944Sbill 	register i;
963944Sbill 	int j, sh;
964944Sbill 	daddr_t nb, nnb;
965944Sbill 	daddr_t indir[NINDIR];
966944Sbill 
967944Sbill 	/*
968944Sbill 	 * blocks 0..NADDR-4 are direct blocks
969944Sbill 	 */
970944Sbill 	if(bn < NADDR-3) {
971944Sbill 		iaddr[bn] = nb = balloc();
972944Sbill 		return(nb);
973944Sbill 	}
974944Sbill 
975944Sbill 	/*
976944Sbill 	 * addresses NADDR-3, NADDR-2, and NADDR-1
977944Sbill 	 * have single, double, triple indirect blocks.
978944Sbill 	 * the first step is to determine
979944Sbill 	 * how many levels of indirection.
980944Sbill 	 */
981944Sbill 	sh = 0;
982944Sbill 	nb = 1;
983944Sbill 	bn -= NADDR-3;
984944Sbill 	for(j=3; j>0; j--) {
985944Sbill 		sh += NSHIFT;
986944Sbill 		nb <<= NSHIFT;
987944Sbill 		if(bn < nb)
988944Sbill 			break;
989944Sbill 		bn -= nb;
990944Sbill 	}
991944Sbill 	if(j == 0) {
992944Sbill 		return((daddr_t)0);
993944Sbill 	}
994944Sbill 
995944Sbill 	/*
996944Sbill 	 * fetch the address from the inode
997944Sbill 	 */
998944Sbill 	if((nb = iaddr[NADDR-j]) == 0) {
999944Sbill 		iaddr[NADDR-j] = nb = balloc();
1000944Sbill 	}
1001944Sbill 
1002944Sbill 	/*
1003944Sbill 	 * fetch through the indirect blocks
1004944Sbill 	 */
1005944Sbill 	for(; j<=3; j++) {
1006944Sbill 		dread(nb, (char *)indir, BSIZE);
1007944Sbill 		sh -= NSHIFT;
1008944Sbill 		i = (bn>>sh) & NMASK;
1009944Sbill 		nnb = indir[i];
1010944Sbill 		if(nnb == 0) {
1011944Sbill 			nnb = balloc();
1012944Sbill 			indir[i] = nnb;
1013944Sbill 			dwrite(nb, (char *)indir);
1014944Sbill 		}
1015944Sbill 		nb = nnb;
1016944Sbill 	}
1017944Sbill 	return(nb);
1018944Sbill }
1019944Sbill 
1020944Sbill /*
1021944Sbill  * read the tape into buf, then return whether or
1022944Sbill  * or not it is a header block.
1023944Sbill  */
1024944Sbill gethead(buf)
1025944Sbill struct spcl *buf;
1026944Sbill {
1027944Sbill 	readtape((char *)buf, 0);
1028944Sbill 	if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
1029944Sbill 		return(0);
1030944Sbill 	return(1);
1031944Sbill }
1032944Sbill 
1033944Sbill /*
1034944Sbill  * return whether or not the buffer contains a header block
1035944Sbill  */
1036944Sbill ishead(buf)
1037944Sbill struct spcl *buf;
1038944Sbill {
1039944Sbill 	if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
1040944Sbill 		return(0);
1041944Sbill 	return(1);
1042944Sbill }
1043944Sbill 
1044944Sbill checktype(b, t)
1045944Sbill struct	spcl *b;
1046944Sbill int	t;
1047944Sbill {
1048944Sbill 	return(b->c_type == t);
1049944Sbill }
1050944Sbill 
1051944Sbill 
checksum(b)1052944Sbill checksum(b)
1053944Sbill int *b;
1054944Sbill {
1055944Sbill 	register i, j;
1056944Sbill 
1057944Sbill 	j = OBSIZE/sizeof(int);
1058944Sbill 	i = 0;
1059944Sbill 	do
1060944Sbill 		i += *b++;
1061944Sbill 	while (--j);
1062944Sbill 	if (i != CHECKSUM) {
1063944Sbill 		printf("Checksum error %o\n", i);
1064944Sbill 		return(0);
1065944Sbill 	}
1066944Sbill 	return(1);
1067944Sbill }
1068944Sbill 
1069944Sbill checkvol(b, t)
1070944Sbill struct spcl *b;
1071944Sbill int t;
1072944Sbill {
1073944Sbill 	if (b->c_volume == t)
1074944Sbill 		return(1);
1075944Sbill 	return(0);
1076944Sbill }
1077944Sbill 
1078944Sbill readhdr(b)
1079944Sbill struct	spcl *b;
1080944Sbill {
1081944Sbill 	if (gethead(b) == 0)
1082944Sbill 		return(0);
1083944Sbill 	if (checktype(b, TS_TAPE) == 0)
1084944Sbill 		return(0);
1085944Sbill 	return(1);
1086944Sbill }
1087944Sbill 
1088944Sbill /*
1089944Sbill  * The next routines are called during file extraction to
1090944Sbill  * put the data into the right form and place.
1091944Sbill  */
1092944Sbill #ifndef STANDALONE
xtrfile(b,size)1093944Sbill xtrfile(b, size)
1094944Sbill char	*b;
1095944Sbill long	size;
1096944Sbill {
1097944Sbill 	write(ofile, b, (int) size);
1098944Sbill }
1099944Sbill 
null()1100944Sbill null() {;}
1101944Sbill 
skip()1102944Sbill skip()
1103944Sbill {
1104944Sbill 	lseek(ofile, (long) OBSIZE, 1);
1105944Sbill }
1106944Sbill #endif
1107944Sbill 
1108944Sbill 
rstrfile(b,s)1109944Sbill rstrfile(b, s)
1110944Sbill char *b;
1111944Sbill long s;
1112944Sbill {
1113944Sbill 	daddr_t d;
1114944Sbill 
1115944Sbill 	d = bmap(taddr, curbno);
1116944Sbill 	dwrite(d, b);
1117944Sbill 	curbno += 1;
1118944Sbill }
1119944Sbill 
rstrskip(b,s)1120944Sbill rstrskip(b, s)
1121944Sbill char *b;
1122944Sbill long s;
1123944Sbill {
1124944Sbill 	curbno += 1;
1125944Sbill }
1126944Sbill 
1127944Sbill #ifndef STANDALONE
putdir(b)1128944Sbill putdir(b)
1129944Sbill char *b;
1130944Sbill {
1131944Sbill 	register struct direct *dp;
1132944Sbill 	register i;
1133944Sbill 
1134944Sbill 	for (dp = (struct direct *) b, i = 0; i < BSIZE; dp++, i += sizeof(*dp)) {
1135944Sbill 		if (dp->d_ino == 0)
1136944Sbill 			continue;
1137944Sbill 		putent((char *) dp);
1138944Sbill 	}
1139944Sbill }
1140944Sbill #endif
1141944Sbill 
1142944Sbill /*
1143944Sbill  * read/write an inode from the disk
1144944Sbill  */
getdino(inum,b)1145944Sbill getdino(inum, b)
1146944Sbill ino_t	inum;
1147944Sbill struct	dinode *b;
1148944Sbill {
1149944Sbill 	daddr_t	bno;
1150944Sbill 	char buf[BSIZE];
1151944Sbill 
1152944Sbill 	bno = (ino - 1)/INOPB;
1153944Sbill 	bno += 2;
1154944Sbill 	dread(bno, buf, BSIZE);
1155944Sbill 	copy(&buf[((inum-1)%INOPB)*sizeof(struct dinode)], (char *) b, sizeof(struct dinode));
1156944Sbill }
1157944Sbill 
putdino(inum,b)1158944Sbill putdino(inum, b)
1159944Sbill ino_t	inum;
1160944Sbill struct	dinode *b;
1161944Sbill {
1162944Sbill 	daddr_t bno;
1163944Sbill 	char buf[BSIZE];
1164944Sbill 
1165944Sbill 	bno = ((ino - 1)/INOPB) + 2;
1166944Sbill 	dread(bno, buf, BSIZE);
1167944Sbill 	copy((char *) b, &buf[((inum-1)%INOPB)*sizeof(struct dinode)], sizeof(struct dinode));
1168944Sbill 	dwrite(bno, buf);
1169944Sbill }
1170944Sbill 
1171944Sbill /*
1172944Sbill  * read a bit mask from the tape into m.
1173944Sbill  */
readbits(m)1174944Sbill readbits(m)
1175944Sbill short	*m;
1176944Sbill {
1177944Sbill 	register i;
1178944Sbill 
1179944Sbill 	i = spcl.c_count;
1180944Sbill 
1181944Sbill 	while (i--) {
1182944Sbill 		readtape((char *) m, 0);
1183944Sbill 		m += (OBSIZE/(MLEN/BITS));
1184944Sbill 	}
1185944Sbill 	while (gethead(&spcl) == 0)
1186944Sbill 		;
1187944Sbill }
1188944Sbill 
done()1189944Sbill done()
1190944Sbill {
1191944Sbill 	unlink(dirfile);
1192944Sbill 	exit(0);
1193944Sbill }
1194