xref: /csrg-svn/sbin/restore/main.c (revision 4610)
1*4610Smckusick /* Copyright (c) 1981 Regents of the University of California */
2*4610Smckusick 
3*4610Smckusick char version[] = "@(#)main.c 1.1 10/25/81";
4*4610Smckusick 
5*4610Smckusick /*	Modified to include h option (recursively extract all files within
6*4610Smckusick  *	a subtree) and m option (recreate the heirarchical structure of
7*4610Smckusick  *	that subtree and move extracted files to their proper homes).
8*4610Smckusick  *	8/29/80		by Mike Litzkow
9*4610Smckusick  *
10*4610Smckusick  *	Includes the s (skip files) option for use with multiple dumps on
11*4610Smckusick  *	a single tape.
12*4610Smckusick  */
13*4610Smckusick 
14*4610Smckusick /* static char *sccsid = "@(#)restor.c	4.1 (Berkeley) 10/1/80"; */
15*4610Smckusick 
16*4610Smckusick #define MAXINO	3000
17*4610Smckusick #define BITS	8
18*4610Smckusick #define NCACHE	3
19*4610Smckusick #define NSIZE   100
20*4610Smckusick #define SIZEINC 10
21*4610Smckusick 
22*4610Smckusick #ifndef STANDALONE
23*4610Smckusick #include <stdio.h>
24*4610Smckusick #include <signal.h>
25*4610Smckusick #endif
26*4610Smckusick #include <sys/param.h>
27*4610Smckusick #include <sys/inode.h>
28*4610Smckusick #include <sys/ino.h>
29*4610Smckusick #include <sys/fblk.h>
30*4610Smckusick #include <sys/filsys.h>
31*4610Smckusick #include <sys/dir.h>
32*4610Smckusick #include <dumprestor.h>
33*4610Smckusick 
34*4610Smckusick #define	MWORD(m,i) (m[(unsigned)(i-1)/MLEN])
35*4610Smckusick #define	MBIT(i)	(1<<((unsigned)(i-1)%MLEN))
36*4610Smckusick #define	BIS(i,w)	(MWORD(w,i) |=  MBIT(i))
37*4610Smckusick #define	BIC(i,w)	(MWORD(w,i) &= ~MBIT(i))
38*4610Smckusick #define	BIT(i,w)	(MWORD(w,i) & MBIT(i))
39*4610Smckusick 
40*4610Smckusick struct	filsys	sblock;
41*4610Smckusick struct  direct	dir;
42*4610Smckusick 
43*4610Smckusick int	fi;
44*4610Smckusick ino_t	ino, maxi, curino;
45*4610Smckusick 
46*4610Smckusick int	mt, hflag, mflag, i;
47*4610Smckusick 
48*4610Smckusick char	tapename[] = "/dev/rmt8";
49*4610Smckusick char	*magtape = tapename;
50*4610Smckusick 
51*4610Smckusick #ifdef STANDALONE
52*4610Smckusick char	mbuf[50];
53*4610Smckusick #endif
54*4610Smckusick 
55*4610Smckusick #ifndef STANDALONE
56*4610Smckusick daddr_t	seekpt;
57*4610Smckusick int	df, ofile;
58*4610Smckusick char	dirfile[] = "rstXXXXXX";
59*4610Smckusick 
60*4610Smckusick struct {
61*4610Smckusick 	ino_t	t_ino;
62*4610Smckusick 	daddr_t	t_seekpt;
63*4610Smckusick } inotab[MAXINO];
64*4610Smckusick int	ipos;
65*4610Smckusick 
66*4610Smckusick #define ONTAPE	1
67*4610Smckusick #define XTRACTD	2
68*4610Smckusick #define XINUSE	4
69*4610Smckusick struct xtrlist {
70*4610Smckusick 	ino_t	x_ino;
71*4610Smckusick 	char	x_flags;
72*4610Smckusick 	char 	*x_name;
73*4610Smckusick } *xtrlist;
74*4610Smckusick 
75*4610Smckusick char	name[100];
76*4610Smckusick 
77*4610Smckusick char	drblock[BSIZE];
78*4610Smckusick int	bpt, nread, xsize,
79*4610Smckusick 	init = 1;
80*4610Smckusick 
81*4610Smckusick 
82*4610Smckusick #include <sys/mtio.h>
83*4610Smckusick struct mtop tcom;
84*4610Smckusick 
85*4610Smckusick 
86*4610Smckusick int dumpnum = 1;
87*4610Smckusick int	volno = 1;
88*4610Smckusick 
89*4610Smckusick 
90*4610Smckusick int	eflag;
91*4610Smckusick 
92*4610Smckusick struct dinode tino, dino;
93*4610Smckusick daddr_t	taddr[NADDR];
94*4610Smckusick 
95*4610Smckusick daddr_t	curbno;
96*4610Smckusick 
97*4610Smckusick short	dumpmap[MSIZ];
98*4610Smckusick short	clrimap[MSIZ];
99*4610Smckusick 
100*4610Smckusick 
101*4610Smckusick int bct = NTREC+1;
102*4610Smckusick char tbf[NTREC*BSIZE];
103*4610Smckusick 
104*4610Smckusick struct	cache {
105*4610Smckusick 	daddr_t	c_bno;
106*4610Smckusick 	int	c_time;
107*4610Smckusick 	char	c_block[BSIZE];
108*4610Smckusick } cache[NCACHE];
109*4610Smckusick int	curcache;
110*4610Smckusick 
111*4610Smckusick main(argc, argv)
112*4610Smckusick char *argv[];
113*4610Smckusick {
114*4610Smckusick 	register char *cp;
115*4610Smckusick 	char command;
116*4610Smckusick 	int done();
117*4610Smckusick 
118*4610Smckusick #ifndef STANDALONE
119*4610Smckusick 	mktemp(dirfile);
120*4610Smckusick 	if (argc < 2) {
121*4610Smckusick usage:
122*4610Smckusick 		printf("Usage: restor x[s|m|h] file file..., restor r filesys, or restor t\n");
123*4610Smckusick 		exit(1);
124*4610Smckusick 	}
125*4610Smckusick 	argv++;
126*4610Smckusick 	argc -= 2;
127*4610Smckusick 	for (cp = *argv++; *cp; cp++) {
128*4610Smckusick 		switch (*cp) {
129*4610Smckusick 		case '-':
130*4610Smckusick 			break;
131*4610Smckusick 		case 'f':
132*4610Smckusick 			magtape = *argv++;
133*4610Smckusick 			argc--;
134*4610Smckusick 			break;
135*4610Smckusick 		/* s dumpnum (skip to) for multifile dump tapes */
136*4610Smckusick 		case 's':
137*4610Smckusick 			dumpnum = atoi(*argv++);
138*4610Smckusick 			if(dumpnum <= 0) {
139*4610Smckusick 				printf("Dump number must be a positive integer\n");
140*4610Smckusick 				exit(1);
141*4610Smckusick 			}
142*4610Smckusick 			argc--;
143*4610Smckusick 			break;
144*4610Smckusick 		case 'h':
145*4610Smckusick 			hflag++;
146*4610Smckusick 			break;
147*4610Smckusick 		case 'm':
148*4610Smckusick 			mflag++;
149*4610Smckusick 			break;
150*4610Smckusick 		case 'r':
151*4610Smckusick 		case 'R':
152*4610Smckusick 		case 't':
153*4610Smckusick 		case 'x':
154*4610Smckusick 			command = *cp;
155*4610Smckusick 			break;
156*4610Smckusick 		default:
157*4610Smckusick 			printf("Bad key character %c\n", *cp);
158*4610Smckusick 			goto usage;
159*4610Smckusick 		}
160*4610Smckusick 	}
161*4610Smckusick 	if (command == 'x') {
162*4610Smckusick 		if (signal(SIGINT, done) == SIG_IGN)
163*4610Smckusick 			signal(SIGINT, SIG_IGN);
164*4610Smckusick 		if (signal(SIGTERM, done) == SIG_IGN)
165*4610Smckusick 			signal(SIGTERM, SIG_IGN);
166*4610Smckusick 
167*4610Smckusick 		df = creat(dirfile, 0666);
168*4610Smckusick 		if (df < 0) {
169*4610Smckusick 			printf("restor: %s - cannot create directory temporary\n", dirfile);
170*4610Smckusick 			exit(1);
171*4610Smckusick 		}
172*4610Smckusick 		close(df);
173*4610Smckusick 		df = open(dirfile, 2);
174*4610Smckusick 	}
175*4610Smckusick 	doit(command, argc, argv);
176*4610Smckusick 	if (command == 'x')
177*4610Smckusick 		unlink(dirfile);
178*4610Smckusick 	exit(0);
179*4610Smckusick #else
180*4610Smckusick 	magtape = "tape";
181*4610Smckusick 	doit('r', 1, 0);
182*4610Smckusick #endif
183*4610Smckusick }
184*4610Smckusick 
185*4610Smckusick doit(command, argc, argv)
186*4610Smckusick char	command;
187*4610Smckusick int	argc;
188*4610Smckusick char	*argv[];
189*4610Smckusick {
190*4610Smckusick 	extern char *ctime();
191*4610Smckusick 	char *ststore();
192*4610Smckusick 	register k;
193*4610Smckusick 	ino_t	d;
194*4610Smckusick #ifndef STANDALONE
195*4610Smckusick 	int	xtrfile(), skip();
196*4610Smckusick #endif
197*4610Smckusick 	int	rstrfile(), rstrskip();
198*4610Smckusick 	struct dinode *ip, *ip1;
199*4610Smckusick 
200*4610Smckusick #ifndef STANDALONE
201*4610Smckusick 	getxtrlist();
202*4610Smckusick 	if ((mt = open(magtape, 0)) < 0) {
203*4610Smckusick 		printf("%s: cannot open tape\n", magtape);
204*4610Smckusick 		exit(1);
205*4610Smckusick 	}
206*4610Smckusick 	if(dumpnum != 1) {
207*4610Smckusick 		tcom.mt_op = MTFSF;
208*4610Smckusick 		tcom.mt_count = dumpnum -1;
209*4610Smckusick 		if( ioctl(mt,MTIOCTOP,&tcom) < 0)
210*4610Smckusick 			perror("ioctl MTFSF");
211*4610Smckusick 	}
212*4610Smckusick #else
213*4610Smckusick 	do {
214*4610Smckusick 		printf("Tape? ");
215*4610Smckusick 		gets(mbuf);
216*4610Smckusick 		mt = open(mbuf, 0);
217*4610Smckusick 	} while (mt == -1);
218*4610Smckusick 	magtape = mbuf;
219*4610Smckusick #endif
220*4610Smckusick 	switch(command) {
221*4610Smckusick #ifndef STANDALONE
222*4610Smckusick 	case 't':
223*4610Smckusick 		if (readhdr(&spcl) == 0) {
224*4610Smckusick 			printf("Tape is not a dump tape\n");
225*4610Smckusick 			exit(1);
226*4610Smckusick 		}
227*4610Smckusick 		printf("Dump   date: %s", ctime(&spcl.c_date));
228*4610Smckusick 		printf("Dumped from: %s", ctime(&spcl.c_ddate));
229*4610Smckusick 		return;
230*4610Smckusick 	case 'x':
231*4610Smckusick 		if (readhdr(&spcl) == 0) {
232*4610Smckusick 			printf("Tape is not a dump tape\n");
233*4610Smckusick 			exit(1);
234*4610Smckusick 		}
235*4610Smckusick 		if (checkvol(&spcl, 1) == 0) {
236*4610Smckusick 			printf("Tape is not volume 1 of the dump\n");
237*4610Smckusick 		}
238*4610Smckusick 		pass1();  /* This sets the various maps on the way by */
239*4610Smckusick 		i = 0;
240*4610Smckusick 		while( argc-- ) {
241*4610Smckusick 			if(hflag)
242*4610Smckusick 				getleaves( *argv++ );
243*4610Smckusick 			else {
244*4610Smckusick 				if( (d = psearch(*argv)) == 0 ||
245*4610Smckusick 							BIT(d,dumpmap) == 0 ) {
246*4610Smckusick 					printf( "%s: not on tape\n", *argv++ );
247*4610Smckusick 					continue;
248*4610Smckusick 				}
249*4610Smckusick 				xtrlist[i].x_ino = d;
250*4610Smckusick 				xtrlist[i].x_flags |= XINUSE;
251*4610Smckusick 				if( mflag )
252*4610Smckusick 					xtrlist[i].x_name = ststore( *argv );
253*4610Smckusick 				printf( "%s: inode %u\n", *argv, d );
254*4610Smckusick 				argv++;
255*4610Smckusick 				if( ++i >= xsize ) getxtrlist();
256*4610Smckusick 			}
257*4610Smckusick 		}
258*4610Smckusick 
259*4610Smckusick 
260*4610Smckusick 		if(dumpnum > 1)
261*4610Smckusick 			tcom.mt_op = MTBSF;
262*4610Smckusick 		else	tcom.mt_op = MTREW;
263*4610Smckusick 		tcom.mt_count = 1;
264*4610Smckusick 
265*4610Smckusick newvol:
266*4610Smckusick 		flsht();
267*4610Smckusick 		ioctl(mt,MTIOCTOP,&tcom);
268*4610Smckusick 		if( dumpnum > 1 ) {
269*4610Smckusick 			tcom.mt_op = MTFSF;
270*4610Smckusick 			tcom.mt_count = 1;
271*4610Smckusick 			ioctl(mt,MTIOCTOP,&tcom);
272*4610Smckusick 		}
273*4610Smckusick 
274*4610Smckusick 
275*4610Smckusick getvol:
276*4610Smckusick 		printf("Mount desired tape volume: Specify volume #: ");
277*4610Smckusick 		if (gets(tbf) == NULL)
278*4610Smckusick 			return;
279*4610Smckusick 		volno = atoi(tbf);
280*4610Smckusick 		if (volno <= 0) {
281*4610Smckusick 			printf("Volume numbers are positive numerics\n");
282*4610Smckusick 			goto getvol;
283*4610Smckusick 		}
284*4610Smckusick 		if (readhdr(&spcl) == 0) {
285*4610Smckusick 			printf("tape is not dump tape\n");
286*4610Smckusick 			goto newvol;
287*4610Smckusick 		}
288*4610Smckusick 		if (checkvol(&spcl, volno) == 0) {
289*4610Smckusick 			printf("Wrong volume (%d)\n", spcl.c_volume);
290*4610Smckusick 			goto newvol;
291*4610Smckusick 		}
292*4610Smckusick rbits:
293*4610Smckusick 		while (gethead(&spcl) == 0)
294*4610Smckusick 			;
295*4610Smckusick 		if (checktype(&spcl, TS_INODE) == 1) {
296*4610Smckusick 			printf("Can't find inode mask!\n");
297*4610Smckusick 			goto newvol;
298*4610Smckusick 		}
299*4610Smckusick 		if (checktype(&spcl, TS_BITS) == 0)
300*4610Smckusick 			goto rbits;
301*4610Smckusick 		readbits(dumpmap);
302*4610Smckusick 		i = 0;
303*4610Smckusick 		for (k = 0; xtrlist[k].x_flags; k++) {
304*4610Smckusick 			if (BIT(xtrlist[k].x_ino, dumpmap)) {
305*4610Smckusick 				xtrlist[k].x_flags |= ONTAPE;
306*4610Smckusick 				i++;
307*4610Smckusick 			}
308*4610Smckusick 		}
309*4610Smckusick 		while (i > 0) {
310*4610Smckusick again:
311*4610Smckusick 			if (ishead(&spcl) == 0)
312*4610Smckusick 				while(gethead(&spcl) == 0)
313*4610Smckusick 					;
314*4610Smckusick 			if (checktype(&spcl, TS_END) == 1) {
315*4610Smckusick 				printf("end of tape\n");
316*4610Smckusick checkdone:
317*4610Smckusick 				for (k = 0; xtrlist[k].x_flags; k++)
318*4610Smckusick 					if ((xtrlist[k].x_flags&XTRACTD) == 0) {
319*4610Smckusick 						/* get next tape */
320*4610Smckusick 						tcom.mt_op = MTREW;
321*4610Smckusick 
322*4610Smckusick 						goto newvol;
323*4610Smckusick 					}
324*4610Smckusick 				return;
325*4610Smckusick 			}
326*4610Smckusick 			if (checktype(&spcl, TS_INODE) == 0) {
327*4610Smckusick 				gethead(&spcl);
328*4610Smckusick 				goto again;
329*4610Smckusick 			}
330*4610Smckusick 			d = spcl.c_inumber;
331*4610Smckusick 			for (k = 0; xtrlist[k].x_flags; k++) {
332*4610Smckusick 				if (d == xtrlist[k].x_ino) {
333*4610Smckusick 					if( mflag ) {
334*4610Smckusick 						sprintf(name, "%s", xtrlist[k].x_name);
335*4610Smckusick 						printf("extract file %s\n",name);
336*4610Smckusick 						checkdir( name );
337*4610Smckusick 					}
338*4610Smckusick 					else {
339*4610Smckusick 						printf("extract file %u\n", xtrlist[k].x_ino );
340*4610Smckusick 						sprintf(name, "%u", xtrlist[k].x_ino);
341*4610Smckusick 					}
342*4610Smckusick 					if ((ofile = creat(name, 0666)) < 0) {
343*4610Smckusick 						printf("%s: cannot create file\n", name);
344*4610Smckusick 						i--;
345*4610Smckusick 						continue;
346*4610Smckusick 					}
347*4610Smckusick 					chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
348*4610Smckusick 					getfile(ino, xtrfile, skip, spcl.c_dinode.di_size);
349*4610Smckusick 					i--;
350*4610Smckusick 					xtrlist[k].x_flags |= XTRACTD;
351*4610Smckusick 					close(ofile);
352*4610Smckusick 					goto done;
353*4610Smckusick 				}
354*4610Smckusick 			}
355*4610Smckusick 			gethead(&spcl);
356*4610Smckusick done:
357*4610Smckusick 			;
358*4610Smckusick 		}
359*4610Smckusick 		goto checkdone;
360*4610Smckusick #endif
361*4610Smckusick 	case 'r':
362*4610Smckusick 	case 'R':
363*4610Smckusick #ifndef STANDALONE
364*4610Smckusick 		if ((fi = open(*argv, 2)) < 0) {
365*4610Smckusick 			printf("%s: cannot open\n", *argv);
366*4610Smckusick 			exit(1);
367*4610Smckusick 		}
368*4610Smckusick #else
369*4610Smckusick 		do {
370*4610Smckusick 			char charbuf[50];
371*4610Smckusick 
372*4610Smckusick 			printf("Disk? ");
373*4610Smckusick 			gets(charbuf);
374*4610Smckusick 			fi = open(charbuf, 2);
375*4610Smckusick 		} while (fi == -1);
376*4610Smckusick #endif
377*4610Smckusick #ifndef STANDALONE
378*4610Smckusick 		if (command == 'R') {
379*4610Smckusick 			printf("Enter starting volume number: ");
380*4610Smckusick 			if (gets(tbf) == EOF) {
381*4610Smckusick 				volno = 1;
382*4610Smckusick 				printf("\n");
383*4610Smckusick 			}
384*4610Smckusick 			else
385*4610Smckusick 				volno = atoi(tbf);
386*4610Smckusick 		}
387*4610Smckusick 		else
388*4610Smckusick #endif
389*4610Smckusick 			volno = 1;
390*4610Smckusick 		printf("Last chance before scribbling on %s. ",
391*4610Smckusick #ifdef STANDALONE
392*4610Smckusick 								"disk");
393*4610Smckusick #else
394*4610Smckusick 								*argv);
395*4610Smckusick #endif
396*4610Smckusick 		while (getchar() != '\n');
397*4610Smckusick 		dread((daddr_t)1, (char *)&sblock, sizeof(sblock));
398*4610Smckusick 		maxi = (sblock.s_isize-2)*INOPB;
399*4610Smckusick 		if (readhdr(&spcl) == 0) {
400*4610Smckusick 			printf("Missing volume record\n");
401*4610Smckusick 			exit(1);
402*4610Smckusick 		}
403*4610Smckusick 		if (checkvol(&spcl, volno) == 0) {
404*4610Smckusick 			printf("Tape is not volume %d\n", volno);
405*4610Smckusick 			exit(1);
406*4610Smckusick 		}
407*4610Smckusick 		gethead(&spcl);
408*4610Smckusick 		for (;;) {
409*4610Smckusick ragain:
410*4610Smckusick 			if (ishead(&spcl) == 0) {
411*4610Smckusick 				printf("Missing header block\n");
412*4610Smckusick 				while (gethead(&spcl) == 0)
413*4610Smckusick 					;
414*4610Smckusick 				eflag++;
415*4610Smckusick 			}
416*4610Smckusick 			if (checktype(&spcl, TS_END) == 1) {
417*4610Smckusick 				printf("End of tape\n");
418*4610Smckusick 				close(mt);
419*4610Smckusick 				dwrite( (daddr_t) 1, (char *) &sblock);
420*4610Smckusick 				return;
421*4610Smckusick 			}
422*4610Smckusick 			if (checktype(&spcl, TS_CLRI) == 1) {
423*4610Smckusick 				readbits(clrimap);
424*4610Smckusick 				for (ino = 1; ino <= maxi; ino++)
425*4610Smckusick 					if (BIT(ino, clrimap) == 0) {
426*4610Smckusick 						getdino(ino, &tino);
427*4610Smckusick 						if (tino.di_mode == 0)
428*4610Smckusick 							continue;
429*4610Smckusick 						itrunc(&tino);
430*4610Smckusick 						clri(&tino);
431*4610Smckusick 						putdino(ino, &tino);
432*4610Smckusick 					}
433*4610Smckusick 				dwrite( (daddr_t) 1, (char *) &sblock);
434*4610Smckusick 				goto ragain;
435*4610Smckusick 			}
436*4610Smckusick 			if (checktype(&spcl, TS_BITS) == 1) {
437*4610Smckusick 				readbits(dumpmap);
438*4610Smckusick 				goto ragain;
439*4610Smckusick 			}
440*4610Smckusick 			if (checktype(&spcl, TS_INODE) == 0) {
441*4610Smckusick 				printf("Unknown header type\n");
442*4610Smckusick 				eflag++;
443*4610Smckusick 				gethead(&spcl);
444*4610Smckusick 				goto ragain;
445*4610Smckusick 			}
446*4610Smckusick 			ino = spcl.c_inumber;
447*4610Smckusick 			if (eflag)
448*4610Smckusick 				printf("Resynced at inode %u\n", ino);
449*4610Smckusick 			eflag = 0;
450*4610Smckusick 			if (ino > maxi) {
451*4610Smckusick 				printf("%u: ilist too small\n", ino);
452*4610Smckusick 				gethead(&spcl);
453*4610Smckusick 				goto ragain;
454*4610Smckusick 			}
455*4610Smckusick 			dino = spcl.c_dinode;
456*4610Smckusick 			getdino(ino, &tino);
457*4610Smckusick 			curbno = 0;
458*4610Smckusick 			itrunc(&tino);
459*4610Smckusick 			clri(&tino);
460*4610Smckusick 			for (i = 0; i < NADDR; i++)
461*4610Smckusick 				taddr[i] = 0;
462*4610Smckusick 			l3tol(taddr, dino.di_addr, 1);
463*4610Smckusick 			getfile(d, rstrfile, rstrskip, dino.di_size);
464*4610Smckusick 			ip = &tino;
465*4610Smckusick 			ltol3(ip->di_addr, taddr, NADDR);
466*4610Smckusick 			ip1 = &dino;
467*4610Smckusick 			ip->di_mode = ip1->di_mode;
468*4610Smckusick 			ip->di_nlink = ip1->di_nlink;
469*4610Smckusick 			ip->di_uid = ip1->di_uid;
470*4610Smckusick 			ip->di_gid = ip1->di_gid;
471*4610Smckusick 			ip->di_size = ip1->di_size;
472*4610Smckusick 			ip->di_atime = ip1->di_atime;
473*4610Smckusick 			ip->di_mtime = ip1->di_mtime;
474*4610Smckusick 			ip->di_ctime = ip1->di_ctime;
475*4610Smckusick 			putdino(ino, &tino);
476*4610Smckusick 		}
477*4610Smckusick 	}
478*4610Smckusick }
479*4610Smckusick 
480*4610Smckusick /*
481*4610Smckusick  * Read the tape, bulding up a directory structure for extraction
482*4610Smckusick  * by name
483*4610Smckusick  */
484*4610Smckusick #ifndef STANDALONE
485*4610Smckusick pass1()
486*4610Smckusick {
487*4610Smckusick 	register i;
488*4610Smckusick 	struct dinode *ip;
489*4610Smckusick 	int	putdir(), null();
490*4610Smckusick 
491*4610Smckusick 	while (gethead(&spcl) == 0) {
492*4610Smckusick 		printf("Can't find directory header!\n");
493*4610Smckusick 	}
494*4610Smckusick 	for (;;) {
495*4610Smckusick 		if (checktype(&spcl, TS_BITS) == 1) {
496*4610Smckusick 			readbits(dumpmap);
497*4610Smckusick 			continue;
498*4610Smckusick 		}
499*4610Smckusick 		if (checktype(&spcl, TS_CLRI) == 1) {
500*4610Smckusick 			readbits(clrimap);
501*4610Smckusick 			continue;
502*4610Smckusick 		}
503*4610Smckusick 		if (checktype(&spcl, TS_INODE) == 0) {
504*4610Smckusick finish:
505*4610Smckusick 			flsh();
506*4610Smckusick /*
507*4610Smckusick 			close(mt);
508*4610Smckusick */
509*4610Smckusick 			return;
510*4610Smckusick 		}
511*4610Smckusick 		ip = &spcl.c_dinode;
512*4610Smckusick 		i = ip->di_mode & IFMT;
513*4610Smckusick 		if (i != IFDIR) {
514*4610Smckusick 			goto finish;
515*4610Smckusick 		}
516*4610Smckusick 		inotab[ipos].t_ino = spcl.c_inumber;
517*4610Smckusick 		inotab[ipos++].t_seekpt = seekpt;
518*4610Smckusick 		getfile(spcl.c_inumber, putdir, null, spcl.c_dinode.di_size);
519*4610Smckusick 		putent("\000\000/");
520*4610Smckusick 	}
521*4610Smckusick }
522*4610Smckusick #endif
523*4610Smckusick 
524*4610Smckusick /*
525*4610Smckusick  * Do the file extraction, calling the supplied functions
526*4610Smckusick  * with the blocks
527*4610Smckusick  */
528*4610Smckusick getfile(n, f1, f2, size)
529*4610Smckusick ino_t	n;
530*4610Smckusick int	(*f2)(), (*f1)();
531*4610Smckusick long	size;
532*4610Smckusick {
533*4610Smckusick 	register i;
534*4610Smckusick 	struct spcl addrblock;
535*4610Smckusick 	char buf[BSIZE];
536*4610Smckusick 
537*4610Smckusick 	addrblock = spcl;
538*4610Smckusick 	curino = n;
539*4610Smckusick 	goto start;
540*4610Smckusick 	for (;;) {
541*4610Smckusick 		if (gethead(&addrblock) == 0) {
542*4610Smckusick 			printf("Missing address (header) block\n");
543*4610Smckusick 			goto eloop;
544*4610Smckusick 		}
545*4610Smckusick 		if (checktype(&addrblock, TS_ADDR) == 0) {
546*4610Smckusick 			spcl = addrblock;
547*4610Smckusick 			curino = 0;
548*4610Smckusick 			curino = 0;
549*4610Smckusick 			return;
550*4610Smckusick 		}
551*4610Smckusick start:
552*4610Smckusick 		for (i = 0; i < addrblock.c_count; i++) {
553*4610Smckusick 			if (addrblock.c_addr[i]) {
554*4610Smckusick 				readtape(buf);
555*4610Smckusick 				(*f1)(buf, size > BSIZE ? (long) BSIZE : size);
556*4610Smckusick 			}
557*4610Smckusick 			else {
558*4610Smckusick 				clearbuf(buf);
559*4610Smckusick 				(*f2)(buf, size > BSIZE ? (long) BSIZE : size);
560*4610Smckusick 			}
561*4610Smckusick 			if ((size -= BSIZE) <= 0) {
562*4610Smckusick eloop:
563*4610Smckusick 				while (gethead(&spcl) == 0)
564*4610Smckusick 					;
565*4610Smckusick 				if (checktype(&spcl, TS_ADDR) == 1)
566*4610Smckusick 					goto eloop;
567*4610Smckusick 				curino = 0;
568*4610Smckusick 				return;
569*4610Smckusick 			}
570*4610Smckusick 		}
571*4610Smckusick 	}
572*4610Smckusick }
573*4610Smckusick 
574*4610Smckusick /*
575*4610Smckusick  * Do the tape i\/o, dealling with volume changes
576*4610Smckusick  * etc..
577*4610Smckusick  */
578*4610Smckusick readtape(b)
579*4610Smckusick char *b;
580*4610Smckusick {
581*4610Smckusick 	register i;
582*4610Smckusick 	struct spcl tmpbuf;
583*4610Smckusick 
584*4610Smckusick 	if (bct >= NTREC) {
585*4610Smckusick 		for (i = 0; i < NTREC; i++)
586*4610Smckusick 			((struct spcl *)&tbf[i*BSIZE])->c_magic = 0;
587*4610Smckusick 		bct = 0;
588*4610Smckusick 		if ((i = read(mt, tbf, NTREC*BSIZE)) < 0) {
589*4610Smckusick 			printf("Tape read error: inode %u\n", curino);
590*4610Smckusick 			eflag++;
591*4610Smckusick 			exit(1);
592*4610Smckusick 		}
593*4610Smckusick 		if (i == 0) {
594*4610Smckusick 			bct = NTREC + 1;
595*4610Smckusick 			volno++;
596*4610Smckusick loop:
597*4610Smckusick 			flsht();
598*4610Smckusick 			close(mt);
599*4610Smckusick 			printf("Mount volume %d\n", volno);
600*4610Smckusick 			while (getchar() != '\n')
601*4610Smckusick 				;
602*4610Smckusick 			if ((mt = open(magtape, 0)) == -1) {
603*4610Smckusick 				printf("Cannot open tape!\n");
604*4610Smckusick 				goto loop;
605*4610Smckusick 			}
606*4610Smckusick 			if (readhdr(&tmpbuf) == 0) {
607*4610Smckusick 				printf("Not a dump tape.Try again\n");
608*4610Smckusick 				goto loop;
609*4610Smckusick 			}
610*4610Smckusick 			if (checkvol(&tmpbuf, volno) == 0) {
611*4610Smckusick 				printf("Wrong tape. Try again\n");
612*4610Smckusick 				goto loop;
613*4610Smckusick 			}
614*4610Smckusick 			readtape(b);
615*4610Smckusick 			return;
616*4610Smckusick 		}
617*4610Smckusick 	}
618*4610Smckusick 	copy(&tbf[(bct++*BSIZE)], b, BSIZE);
619*4610Smckusick }
620*4610Smckusick 
621*4610Smckusick flsht()
622*4610Smckusick {
623*4610Smckusick 	bct = NTREC+1;
624*4610Smckusick }
625*4610Smckusick 
626*4610Smckusick copy(f, t, s)
627*4610Smckusick register char *f, *t;
628*4610Smckusick {
629*4610Smckusick 	register i;
630*4610Smckusick 
631*4610Smckusick 	i = s;
632*4610Smckusick 	do
633*4610Smckusick 		*t++ = *f++;
634*4610Smckusick 	while (--i);
635*4610Smckusick }
636*4610Smckusick 
637*4610Smckusick clearbuf(cp)
638*4610Smckusick register char *cp;
639*4610Smckusick {
640*4610Smckusick 	register i;
641*4610Smckusick 
642*4610Smckusick 	i = BSIZE;
643*4610Smckusick 	do
644*4610Smckusick 		*cp++ = 0;
645*4610Smckusick 	while (--i);
646*4610Smckusick }
647*4610Smckusick 
648*4610Smckusick /*
649*4610Smckusick  * Put and get the directory entries from the compressed
650*4610Smckusick  * directory file
651*4610Smckusick  */
652*4610Smckusick #ifndef STANDALONE
653*4610Smckusick putent(cp)
654*4610Smckusick char	*cp;
655*4610Smckusick {
656*4610Smckusick 	register i;
657*4610Smckusick 
658*4610Smckusick 	for (i = 0; i < sizeof(ino_t); i++)
659*4610Smckusick 		writec(*cp++);
660*4610Smckusick 	for (i = 0; i < DIRSIZ; i++) {
661*4610Smckusick 		writec(*cp);
662*4610Smckusick 		if (*cp++ == 0)
663*4610Smckusick 			return;
664*4610Smckusick 	}
665*4610Smckusick 	return;
666*4610Smckusick }
667*4610Smckusick 
668*4610Smckusick getent(bf)
669*4610Smckusick register char *bf;
670*4610Smckusick {
671*4610Smckusick 	register i;
672*4610Smckusick 
673*4610Smckusick 	for (i = 0; i < sizeof(ino_t); i++)
674*4610Smckusick 		*bf++ = readc();
675*4610Smckusick 	for (i = 0; i < DIRSIZ; i++)
676*4610Smckusick 		if ((*bf++ = readc()) == 0)
677*4610Smckusick 			return;
678*4610Smckusick 	return;
679*4610Smckusick }
680*4610Smckusick 
681*4610Smckusick /*
682*4610Smckusick  * read/write te directory file
683*4610Smckusick  */
684*4610Smckusick writec(c)
685*4610Smckusick char c;
686*4610Smckusick {
687*4610Smckusick 	drblock[bpt++] = c;
688*4610Smckusick 	seekpt++;
689*4610Smckusick 	if (bpt >= BSIZE) {
690*4610Smckusick 		bpt = 0;
691*4610Smckusick 		write(df, drblock, BSIZE);
692*4610Smckusick 	}
693*4610Smckusick }
694*4610Smckusick 
695*4610Smckusick readc()
696*4610Smckusick {
697*4610Smckusick 	if (bpt >= BSIZE) {
698*4610Smckusick 		nread = read(df, drblock, BSIZE);
699*4610Smckusick 		bpt = 0;
700*4610Smckusick 	}
701*4610Smckusick 	return(drblock[bpt++]);
702*4610Smckusick }
703*4610Smckusick 
704*4610Smckusick mseek(pt)
705*4610Smckusick daddr_t pt;
706*4610Smckusick {
707*4610Smckusick 	bpt = BSIZE;
708*4610Smckusick 	lseek(df, pt, 0);
709*4610Smckusick }
710*4610Smckusick 
711*4610Smckusick flsh()
712*4610Smckusick {
713*4610Smckusick 	write(df, drblock, bpt+1);
714*4610Smckusick }
715*4610Smckusick 
716*4610Smckusick /*
717*4610Smckusick  * search the directory inode ino
718*4610Smckusick  * looking for entry cp
719*4610Smckusick  */
720*4610Smckusick ino_t
721*4610Smckusick search(inum, cp)
722*4610Smckusick ino_t	inum;
723*4610Smckusick char	*cp;
724*4610Smckusick {
725*4610Smckusick 	register i;
726*4610Smckusick 
727*4610Smckusick 	for (i = 0; i < MAXINO; i++)
728*4610Smckusick 		if (inotab[i].t_ino == inum) {
729*4610Smckusick 			goto found;
730*4610Smckusick 		}
731*4610Smckusick 	return(0);
732*4610Smckusick found:
733*4610Smckusick 	mseek(inotab[i].t_seekpt);
734*4610Smckusick 	do {
735*4610Smckusick 		getent((char *)&dir);
736*4610Smckusick 		if (direq(dir.d_name, "/"))
737*4610Smckusick 			return(0);
738*4610Smckusick 	} while (direq(dir.d_name, cp) == 0);
739*4610Smckusick 	return(dir.d_ino);
740*4610Smckusick }
741*4610Smckusick 
742*4610Smckusick /*
743*4610Smckusick  * Search the directory tree rooted at inode 2
744*4610Smckusick  * for the path pointed at by n
745*4610Smckusick  */
746*4610Smckusick psearch(n)
747*4610Smckusick char	*n;
748*4610Smckusick {
749*4610Smckusick 	register char *cp, *cp1;
750*4610Smckusick 	char c;
751*4610Smckusick 
752*4610Smckusick 	ino = 2;
753*4610Smckusick 	if (*(cp = n) == '/')
754*4610Smckusick 		cp++;
755*4610Smckusick next:
756*4610Smckusick 	cp1 = cp + 1;
757*4610Smckusick 	while (*cp1 != '/' && *cp1)
758*4610Smckusick 		cp1++;
759*4610Smckusick 	c = *cp1;
760*4610Smckusick 	*cp1 = 0;
761*4610Smckusick 	ino = search(ino, cp);
762*4610Smckusick 	if (ino == 0) {
763*4610Smckusick 		*cp1 = c;
764*4610Smckusick 		return(0);
765*4610Smckusick 	}
766*4610Smckusick 	*cp1 = c;
767*4610Smckusick 	if (c == '/') {
768*4610Smckusick 		cp = cp1+1;
769*4610Smckusick 		goto next;
770*4610Smckusick 	}
771*4610Smckusick 	return(ino);
772*4610Smckusick }
773*4610Smckusick 
774*4610Smckusick direq(s1, s2)
775*4610Smckusick register char *s1, *s2;
776*4610Smckusick {
777*4610Smckusick 	register i;
778*4610Smckusick 
779*4610Smckusick 	for (i = 0; i < DIRSIZ; i++)
780*4610Smckusick 		if (*s1++ == *s2) {
781*4610Smckusick 			if (*s2++ == 0)
782*4610Smckusick 				return(1);
783*4610Smckusick 		} else
784*4610Smckusick 			return(0);
785*4610Smckusick 	return(1);
786*4610Smckusick }
787*4610Smckusick #endif
788*4610Smckusick 
789*4610Smckusick /*
790*4610Smckusick  * read/write a disk block, be sure to update the buffer
791*4610Smckusick  * cache if needed.
792*4610Smckusick  */
793*4610Smckusick dwrite(bno, b)
794*4610Smckusick daddr_t	bno;
795*4610Smckusick char	*b;
796*4610Smckusick {
797*4610Smckusick 	register i;
798*4610Smckusick 
799*4610Smckusick 	for (i = 0; i < NCACHE; i++) {
800*4610Smckusick 		if (cache[i].c_bno == bno) {
801*4610Smckusick 			copy(b, cache[i].c_block, BSIZE);
802*4610Smckusick 			cache[i].c_time = 0;
803*4610Smckusick 			break;
804*4610Smckusick 		}
805*4610Smckusick 		else
806*4610Smckusick 			cache[i].c_time++;
807*4610Smckusick 	}
808*4610Smckusick 	lseek(fi, bno*BSIZE, 0);
809*4610Smckusick 	if(write(fi, b, BSIZE) != BSIZE) {
810*4610Smckusick #ifdef STANDALONE
811*4610Smckusick 		printf("disk write error %D\n", bno);
812*4610Smckusick #else
813*4610Smckusick 		fprintf(stderr, "disk write error %ld\n", bno);
814*4610Smckusick #endif
815*4610Smckusick 		exit(1);
816*4610Smckusick 	}
817*4610Smckusick }
818*4610Smckusick 
819*4610Smckusick dread(bno, buf, cnt)
820*4610Smckusick daddr_t bno;
821*4610Smckusick char *buf;
822*4610Smckusick {
823*4610Smckusick 	register i, j;
824*4610Smckusick 
825*4610Smckusick 	j = 0;
826*4610Smckusick 	for (i = 0; i < NCACHE; i++) {
827*4610Smckusick 		if (++curcache >= NCACHE)
828*4610Smckusick 			curcache = 0;
829*4610Smckusick 		if (cache[curcache].c_bno == bno) {
830*4610Smckusick 			copy(cache[curcache].c_block, buf, cnt);
831*4610Smckusick 			cache[curcache].c_time = 0;
832*4610Smckusick 			return;
833*4610Smckusick 		}
834*4610Smckusick 		else {
835*4610Smckusick 			cache[curcache].c_time++;
836*4610Smckusick 			if (cache[j].c_time < cache[curcache].c_time)
837*4610Smckusick 				j = curcache;
838*4610Smckusick 		}
839*4610Smckusick 	}
840*4610Smckusick 
841*4610Smckusick 	lseek(fi, bno*BSIZE, 0);
842*4610Smckusick 	if (read(fi, cache[j].c_block, BSIZE) != BSIZE) {
843*4610Smckusick #ifdef STANDALONE
844*4610Smckusick 		printf("read error %D\n", bno);
845*4610Smckusick #else
846*4610Smckusick 		printf("read error %ld\n", bno);
847*4610Smckusick #endif
848*4610Smckusick 		exit(1);
849*4610Smckusick 	}
850*4610Smckusick 	copy(cache[j].c_block, buf, cnt);
851*4610Smckusick 	cache[j].c_time = 0;
852*4610Smckusick 	cache[j].c_bno = bno;
853*4610Smckusick }
854*4610Smckusick 
855*4610Smckusick /*
856*4610Smckusick  * the inode manpulation routines. Like the system.
857*4610Smckusick  *
858*4610Smckusick  * clri zeros the inode
859*4610Smckusick  */
860*4610Smckusick clri(ip)
861*4610Smckusick struct dinode *ip;
862*4610Smckusick {
863*4610Smckusick 	int i, *p;
864*4610Smckusick 	if (ip->di_mode&IFMT)
865*4610Smckusick 		sblock.s_tinode++;
866*4610Smckusick 	i = sizeof(struct dinode)/sizeof(int);
867*4610Smckusick 	p = (int *)ip;
868*4610Smckusick 	do
869*4610Smckusick 		*p++ = 0;
870*4610Smckusick 	while(--i);
871*4610Smckusick }
872*4610Smckusick 
873*4610Smckusick /*
874*4610Smckusick  * itrunc/tloop/bfree free all of the blocks pointed at by the inode
875*4610Smckusick  */
876*4610Smckusick itrunc(ip)
877*4610Smckusick register struct dinode *ip;
878*4610Smckusick {
879*4610Smckusick 	register i;
880*4610Smckusick 	daddr_t bn, iaddr[NADDR];
881*4610Smckusick 
882*4610Smckusick 	if (ip->di_mode == 0)
883*4610Smckusick 		return;
884*4610Smckusick 	i = ip->di_mode & IFMT;
885*4610Smckusick 	if (i != IFDIR && i != IFREG)
886*4610Smckusick 		return;
887*4610Smckusick 	l3tol(iaddr, ip->di_addr, NADDR);
888*4610Smckusick 	for(i=NADDR-1;i>=0;i--) {
889*4610Smckusick 		bn = iaddr[i];
890*4610Smckusick 		if(bn == 0) continue;
891*4610Smckusick 		switch(i) {
892*4610Smckusick 
893*4610Smckusick 		default:
894*4610Smckusick 			bfree(bn);
895*4610Smckusick 			break;
896*4610Smckusick 
897*4610Smckusick 		case NADDR-3:
898*4610Smckusick 			tloop(bn, 0, 0);
899*4610Smckusick 			break;
900*4610Smckusick 
901*4610Smckusick 		case NADDR-2:
902*4610Smckusick 			tloop(bn, 1, 0);
903*4610Smckusick 			break;
904*4610Smckusick 
905*4610Smckusick 		case NADDR-1:
906*4610Smckusick 			tloop(bn, 1, 1);
907*4610Smckusick 		}
908*4610Smckusick 	}
909*4610Smckusick 	ip->di_size = 0;
910*4610Smckusick }
911*4610Smckusick 
912*4610Smckusick tloop(bn, f1, f2)
913*4610Smckusick daddr_t	bn;
914*4610Smckusick int	f1, f2;
915*4610Smckusick {
916*4610Smckusick 	register i;
917*4610Smckusick 	daddr_t nb;
918*4610Smckusick 	union {
919*4610Smckusick 		char	data[BSIZE];
920*4610Smckusick 		daddr_t	indir[NINDIR];
921*4610Smckusick 	} ibuf;
922*4610Smckusick 
923*4610Smckusick 	dread(bn, ibuf.data, BSIZE);
924*4610Smckusick 	for(i=NINDIR-1;i>=0;i--) {
925*4610Smckusick 		nb = ibuf.indir[i];
926*4610Smckusick 		if(nb) {
927*4610Smckusick 			if(f1)
928*4610Smckusick 				tloop(nb, f2, 0);
929*4610Smckusick 			else
930*4610Smckusick 				bfree(nb);
931*4610Smckusick 		}
932*4610Smckusick 	}
933*4610Smckusick 	bfree(bn);
934*4610Smckusick }
935*4610Smckusick 
936*4610Smckusick bfree(bn)
937*4610Smckusick daddr_t	bn;
938*4610Smckusick {
939*4610Smckusick 	register i;
940*4610Smckusick 	union {
941*4610Smckusick 		char	data[BSIZE];
942*4610Smckusick 		struct	fblk frees;
943*4610Smckusick 	} fbun;
944*4610Smckusick #define	fbuf fbun.frees
945*4610Smckusick 
946*4610Smckusick 	if(sblock.s_nfree >= NICFREE) {
947*4610Smckusick 		fbuf.df_nfree = sblock.s_nfree;
948*4610Smckusick 		for(i=0;i<NICFREE;i++)
949*4610Smckusick 			fbuf.df_free[i] = sblock.s_free[i];
950*4610Smckusick 		sblock.s_nfree = 0;
951*4610Smckusick 		dwrite(bn, fbun.data);
952*4610Smckusick 	}
953*4610Smckusick 	sblock.s_free[sblock.s_nfree++] = bn;
954*4610Smckusick 	sblock.s_tfree++;
955*4610Smckusick }
956*4610Smckusick 
957*4610Smckusick /*
958*4610Smckusick  * allocate a block off the free list.
959*4610Smckusick  */
960*4610Smckusick daddr_t
961*4610Smckusick balloc()
962*4610Smckusick {
963*4610Smckusick 	daddr_t	bno;
964*4610Smckusick 	register i;
965*4610Smckusick 	static char zeroes[BSIZE];
966*4610Smckusick 	union {
967*4610Smckusick 		char	data[BSIZE];
968*4610Smckusick 		struct	fblk frees;
969*4610Smckusick 	} fbun;
970*4610Smckusick #undef		fbuf
971*4610Smckusick #define		fbuf fbun.frees
972*4610Smckusick 
973*4610Smckusick 	if(sblock.s_nfree == 0 || (bno=sblock.s_free[--sblock.s_nfree]) == 0) {
974*4610Smckusick #ifdef STANDALONE
975*4610Smckusick 		printf("Out of space\n");
976*4610Smckusick #else
977*4610Smckusick 		fprintf(stderr, "Out of space.\n");
978*4610Smckusick #endif
979*4610Smckusick 		exit(1);
980*4610Smckusick 	}
981*4610Smckusick 	if(sblock.s_nfree == 0) {
982*4610Smckusick 		dread(bno, (char * )&fbuf, BSIZE);
983*4610Smckusick 		sblock.s_nfree = fbuf.df_nfree;
984*4610Smckusick 		for(i=0;i<NICFREE;i++)
985*4610Smckusick 			sblock.s_free[i] = fbuf.df_free[i];
986*4610Smckusick 	}
987*4610Smckusick 	dwrite(bno, zeroes);
988*4610Smckusick 	sblock.s_tfree--;
989*4610Smckusick 	return(bno);
990*4610Smckusick }
991*4610Smckusick 
992*4610Smckusick /*
993*4610Smckusick  * map a block number into a block address, ensuring
994*4610Smckusick  * all of the correct indirect blocks are around. Allocate
995*4610Smckusick  * the block requested.
996*4610Smckusick  */
997*4610Smckusick daddr_t
998*4610Smckusick bmap(iaddr, bn)
999*4610Smckusick daddr_t	iaddr[NADDR];
1000*4610Smckusick daddr_t	bn;
1001*4610Smckusick {
1002*4610Smckusick 	register i;
1003*4610Smckusick 	int j, sh;
1004*4610Smckusick 	daddr_t nb, nnb;
1005*4610Smckusick 	daddr_t indir[NINDIR];
1006*4610Smckusick 
1007*4610Smckusick 	/*
1008*4610Smckusick 	 * blocks 0..NADDR-4 are direct blocks
1009*4610Smckusick 	 */
1010*4610Smckusick 	if(bn < NADDR-3) {
1011*4610Smckusick 		iaddr[bn] = nb = balloc();
1012*4610Smckusick 		return(nb);
1013*4610Smckusick 	}
1014*4610Smckusick 
1015*4610Smckusick 	/*
1016*4610Smckusick 	 * addresses NADDR-3, NADDR-2, and NADDR-1
1017*4610Smckusick 	 * have single, double, triple indirect blocks.
1018*4610Smckusick 	 * the first step is to determine
1019*4610Smckusick 	 * how many levels of indirection.
1020*4610Smckusick 	 */
1021*4610Smckusick 	sh = 0;
1022*4610Smckusick 	nb = 1;
1023*4610Smckusick 	bn -= NADDR-3;
1024*4610Smckusick 	for(j=3; j>0; j--) {
1025*4610Smckusick 		sh += NSHIFT;
1026*4610Smckusick 		nb <<= NSHIFT;
1027*4610Smckusick 		if(bn < nb)
1028*4610Smckusick 			break;
1029*4610Smckusick 		bn -= nb;
1030*4610Smckusick 	}
1031*4610Smckusick 	if(j == 0) {
1032*4610Smckusick 		return((daddr_t)0);
1033*4610Smckusick 	}
1034*4610Smckusick 
1035*4610Smckusick 	/*
1036*4610Smckusick 	 * fetch the address from the inode
1037*4610Smckusick 	 */
1038*4610Smckusick 	if((nb = iaddr[NADDR-j]) == 0) {
1039*4610Smckusick 		iaddr[NADDR-j] = nb = balloc();
1040*4610Smckusick 	}
1041*4610Smckusick 
1042*4610Smckusick 	/*
1043*4610Smckusick 	 * fetch through the indirect blocks
1044*4610Smckusick 	 */
1045*4610Smckusick 	for(; j<=3; j++) {
1046*4610Smckusick 		dread(nb, (char *)indir, BSIZE);
1047*4610Smckusick 		sh -= NSHIFT;
1048*4610Smckusick 		i = (bn>>sh) & NMASK;
1049*4610Smckusick 		nnb = indir[i];
1050*4610Smckusick 		if(nnb == 0) {
1051*4610Smckusick 			nnb = balloc();
1052*4610Smckusick 			indir[i] = nnb;
1053*4610Smckusick 			dwrite(nb, (char *)indir);
1054*4610Smckusick 		}
1055*4610Smckusick 		nb = nnb;
1056*4610Smckusick 	}
1057*4610Smckusick 	return(nb);
1058*4610Smckusick }
1059*4610Smckusick 
1060*4610Smckusick /*
1061*4610Smckusick  * read the tape into buf, then return whether or
1062*4610Smckusick  * or not it is a header block.
1063*4610Smckusick  */
1064*4610Smckusick gethead(buf)
1065*4610Smckusick struct spcl *buf;
1066*4610Smckusick {
1067*4610Smckusick 	readtape((char *)buf);
1068*4610Smckusick 	if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
1069*4610Smckusick 		return(0);
1070*4610Smckusick 	return(1);
1071*4610Smckusick }
1072*4610Smckusick 
1073*4610Smckusick /*
1074*4610Smckusick  * return whether or not the buffer contains a header block
1075*4610Smckusick  */
1076*4610Smckusick ishead(buf)
1077*4610Smckusick struct spcl *buf;
1078*4610Smckusick {
1079*4610Smckusick 	if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
1080*4610Smckusick 		return(0);
1081*4610Smckusick 	return(1);
1082*4610Smckusick }
1083*4610Smckusick 
1084*4610Smckusick checktype(b, t)
1085*4610Smckusick struct	spcl *b;
1086*4610Smckusick int	t;
1087*4610Smckusick {
1088*4610Smckusick 	return(b->c_type == t);
1089*4610Smckusick }
1090*4610Smckusick 
1091*4610Smckusick 
1092*4610Smckusick checksum(b)
1093*4610Smckusick int *b;
1094*4610Smckusick {
1095*4610Smckusick 	register i, j;
1096*4610Smckusick 
1097*4610Smckusick 	j = BSIZE/sizeof(int);
1098*4610Smckusick 	i = 0;
1099*4610Smckusick 	do
1100*4610Smckusick 		i += *b++;
1101*4610Smckusick 	while (--j);
1102*4610Smckusick 	if (i != CHECKSUM) {
1103*4610Smckusick 		printf("Checksum error %o\n", i);
1104*4610Smckusick 		return(0);
1105*4610Smckusick 	}
1106*4610Smckusick 	return(1);
1107*4610Smckusick }
1108*4610Smckusick 
1109*4610Smckusick checkvol(b, t)
1110*4610Smckusick struct spcl *b;
1111*4610Smckusick int t;
1112*4610Smckusick {
1113*4610Smckusick 	if (b->c_volume == t)
1114*4610Smckusick 		return(1);
1115*4610Smckusick 	return(0);
1116*4610Smckusick }
1117*4610Smckusick 
1118*4610Smckusick readhdr(b)
1119*4610Smckusick struct	spcl *b;
1120*4610Smckusick {
1121*4610Smckusick 	if (gethead(b) == 0)
1122*4610Smckusick 		return(0);
1123*4610Smckusick 	if (checktype(b, TS_TAPE) == 0)
1124*4610Smckusick 		return(0);
1125*4610Smckusick 	return(1);
1126*4610Smckusick }
1127*4610Smckusick 
1128*4610Smckusick /*
1129*4610Smckusick  * The next routines are called during file extraction to
1130*4610Smckusick  * put the data into the right form and place.
1131*4610Smckusick  */
1132*4610Smckusick #ifndef STANDALONE
1133*4610Smckusick xtrfile(b, size)
1134*4610Smckusick char	*b;
1135*4610Smckusick long	size;
1136*4610Smckusick {
1137*4610Smckusick 	write(ofile, b, (int) size);
1138*4610Smckusick }
1139*4610Smckusick 
1140*4610Smckusick null() {;}
1141*4610Smckusick 
1142*4610Smckusick skip()
1143*4610Smckusick {
1144*4610Smckusick 	lseek(ofile, (long) BSIZE, 1);
1145*4610Smckusick }
1146*4610Smckusick #endif
1147*4610Smckusick 
1148*4610Smckusick 
1149*4610Smckusick rstrfile(b, s)
1150*4610Smckusick char *b;
1151*4610Smckusick long s;
1152*4610Smckusick {
1153*4610Smckusick 	daddr_t d;
1154*4610Smckusick 
1155*4610Smckusick 	d = bmap(taddr, curbno);
1156*4610Smckusick 	dwrite(d, b);
1157*4610Smckusick 	curbno += 1;
1158*4610Smckusick }
1159*4610Smckusick 
1160*4610Smckusick rstrskip(b, s)
1161*4610Smckusick char *b;
1162*4610Smckusick long s;
1163*4610Smckusick {
1164*4610Smckusick 	curbno += 1;
1165*4610Smckusick }
1166*4610Smckusick 
1167*4610Smckusick #ifndef STANDALONE
1168*4610Smckusick putdir(b)
1169*4610Smckusick char *b;
1170*4610Smckusick {
1171*4610Smckusick 	register struct direct *dp;
1172*4610Smckusick 	register i;
1173*4610Smckusick 
1174*4610Smckusick 	for (dp = (struct direct *) b, i = 0; i < BSIZE; dp++, i += sizeof(*dp)) {
1175*4610Smckusick 		if (dp->d_ino == 0)
1176*4610Smckusick 			continue;
1177*4610Smckusick 		putent((char *) dp);
1178*4610Smckusick 	}
1179*4610Smckusick }
1180*4610Smckusick #endif
1181*4610Smckusick 
1182*4610Smckusick /*
1183*4610Smckusick  * read/write an inode from the disk
1184*4610Smckusick  */
1185*4610Smckusick getdino(inum, b)
1186*4610Smckusick ino_t	inum;
1187*4610Smckusick struct	dinode *b;
1188*4610Smckusick {
1189*4610Smckusick 	daddr_t	bno;
1190*4610Smckusick 	char buf[BSIZE];
1191*4610Smckusick 
1192*4610Smckusick 	bno = (ino - 1)/INOPB;
1193*4610Smckusick 	bno += 2;
1194*4610Smckusick 	dread(bno, buf, BSIZE);
1195*4610Smckusick 	copy(&buf[((inum-1)%INOPB)*sizeof(struct dinode)], (char *) b, sizeof(struct dinode));
1196*4610Smckusick }
1197*4610Smckusick 
1198*4610Smckusick putdino(inum, b)
1199*4610Smckusick ino_t	inum;
1200*4610Smckusick struct	dinode *b;
1201*4610Smckusick {
1202*4610Smckusick 	daddr_t bno;
1203*4610Smckusick 	char buf[BSIZE];
1204*4610Smckusick 	if (b->di_mode&IFMT)
1205*4610Smckusick 		sblock.s_tinode--;
1206*4610Smckusick 
1207*4610Smckusick 	bno = ((ino - 1)/INOPB) + 2;
1208*4610Smckusick 	dread(bno, buf, BSIZE);
1209*4610Smckusick 	copy((char *) b, &buf[((inum-1)%INOPB)*sizeof(struct dinode)], sizeof(struct dinode));
1210*4610Smckusick 	dwrite(bno, buf);
1211*4610Smckusick }
1212*4610Smckusick 
1213*4610Smckusick /*
1214*4610Smckusick  * read a bit mask from the tape into m.
1215*4610Smckusick  */
1216*4610Smckusick readbits(m)
1217*4610Smckusick short	*m;
1218*4610Smckusick {
1219*4610Smckusick 	register i;
1220*4610Smckusick 
1221*4610Smckusick 	i = spcl.c_count;
1222*4610Smckusick 
1223*4610Smckusick 	while (i--) {
1224*4610Smckusick 		readtape((char *) m);
1225*4610Smckusick 		m += (BSIZE/(MLEN/BITS));
1226*4610Smckusick 	}
1227*4610Smckusick 	while (gethead(&spcl) == 0)
1228*4610Smckusick 		;
1229*4610Smckusick }
1230*4610Smckusick 
1231*4610Smckusick done()
1232*4610Smckusick {
1233*4610Smckusick #ifndef STANDALONE
1234*4610Smckusick 	unlink(dirfile);
1235*4610Smckusick #endif
1236*4610Smckusick 	exit(0);
1237*4610Smckusick }
1238*4610Smckusick 
1239*4610Smckusick stcopy( sourcep, destp, max )
1240*4610Smckusick char *sourcep, *destp;
1241*4610Smckusick int max;
1242*4610Smckusick {
1243*4610Smckusick 	int i;
1244*4610Smckusick 	for( i=1; i<=max && (*destp++ = *sourcep++); i++ )
1245*4610Smckusick 		;
1246*4610Smckusick 	if( i > max )	return( 0 );
1247*4610Smckusick 	else		return( 1 );
1248*4610Smckusick }
1249*4610Smckusick 
1250*4610Smckusick append( sourcep, destp, max )
1251*4610Smckusick char *sourcep, *destp;
1252*4610Smckusick int max;
1253*4610Smckusick {
1254*4610Smckusick 	int i;
1255*4610Smckusick 	for( i=0; *destp; i++ )
1256*4610Smckusick 		*destp++;
1257*4610Smckusick 	if( ++i <= max ) *destp++ = '/';
1258*4610Smckusick 	while( ++i<=max && (*destp++ = *sourcep++) )
1259*4610Smckusick 		;
1260*4610Smckusick 	if( i > max )	return( 0 );
1261*4610Smckusick 	else		return( 1 );
1262*4610Smckusick }
1263*4610Smckusick /*
1264*4610Smckusick  *	Truncate the rightmost file or directory name from a pathname
1265*4610Smckusick  */
1266*4610Smckusick 
1267*4610Smckusick trunc( cp )
1268*4610Smckusick char *cp;
1269*4610Smckusick {
1270*4610Smckusick 	char *lstslsh;
1271*4610Smckusick 	lstslsh = 0;
1272*4610Smckusick 	while( *cp++ )
1273*4610Smckusick 		if( *cp == '/' ) lstslsh = cp;
1274*4610Smckusick 	if( lstslsh == 0 )
1275*4610Smckusick 		return( 0 );
1276*4610Smckusick 	else {
1277*4610Smckusick 		*lstslsh = '\0';
1278*4610Smckusick 		return( 1 );
1279*4610Smckusick 	}
1280*4610Smckusick }
1281*4610Smckusick getxtrlist() {
1282*4610Smckusick 	struct xtrlist	*malloc(),
1283*4610Smckusick 			*realloc();
1284*4610Smckusick 
1285*4610Smckusick 	if( init ) {
1286*4610Smckusick 		init = 0;
1287*4610Smckusick 		xtrlist = malloc( SIZEINC*sizeof(struct xtrlist) );
1288*4610Smckusick 		xsize = SIZEINC;
1289*4610Smckusick 	}
1290*4610Smckusick 	else {
1291*4610Smckusick 		xtrlist = realloc( xtrlist, (SIZEINC+xsize) *
1292*4610Smckusick 						sizeof(struct xtrlist) );
1293*4610Smckusick 		xsize += SIZEINC;
1294*4610Smckusick 	}
1295*4610Smckusick 
1296*4610Smckusick }
1297*4610Smckusick 
1298*4610Smckusick /*
1299*4610Smckusick  *	Check for access into each directory in the pathname of an extracted
1300*4610Smckusick  *	file and create such a directory if needed in preparation for moving
1301*4610Smckusick  *	the file to its proper home.
1302*4610Smckusick  */
1303*4610Smckusick checkdir(name)
1304*4610Smckusick register char *name;
1305*4610Smckusick {
1306*4610Smckusick 	register char *cp;
1307*4610Smckusick 	int i;
1308*4610Smckusick 	for (cp = name; *cp; cp++) {
1309*4610Smckusick 		if (*cp == '/') {
1310*4610Smckusick 			*cp = '\0';
1311*4610Smckusick 			if (access(name, 01) < 0) {
1312*4610Smckusick 				register int pid, rp;
1313*4610Smckusick 
1314*4610Smckusick 				if ((pid = fork()) == 0) {
1315*4610Smckusick 					execl("/bin/mkdir", "mkdir", name, 0);
1316*4610Smckusick 					execl("/usr/bin/mkdir", "mkdir", name, 0);
1317*4610Smckusick 					fprintf(stderr, "tar: cannot find mkdir!\n");
1318*4610Smckusick 					done(0);
1319*4610Smckusick 				}
1320*4610Smckusick 				while ((rp = wait(&i)) >= 0 && rp != pid)
1321*4610Smckusick 					;
1322*4610Smckusick 				chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
1323*4610Smckusick 			}
1324*4610Smckusick 			*cp = '/';
1325*4610Smckusick 		}
1326*4610Smckusick 	}
1327*4610Smckusick }
1328*4610Smckusick 
1329*4610Smckusick /*
1330*4610Smckusick  *	Store a string in core returning a pointer to it.  Allocate space
1331*4610Smckusick  *	as needed.
1332*4610Smckusick  */
1333*4610Smckusick char *
1334*4610Smckusick ststore( stringp )
1335*4610Smckusick char *stringp;
1336*4610Smckusick {
1337*4610Smckusick 	static char *spacep;
1338*4610Smckusick 	static int spaceleft;
1339*4610Smckusick 	char *rtnp, *savep;
1340*4610Smckusick 
1341*4610Smckusick 	rtnp = spacep;
1342*4610Smckusick 	savep = stringp;
1343*4610Smckusick 	while( spaceleft-- && (*spacep++ = *stringp++) );
1344*4610Smckusick 	if( spaceleft >= 0 )
1345*4610Smckusick 		return( rtnp );
1346*4610Smckusick 	else {
1347*4610Smckusick 		spaceleft = 10 * NSIZE;
1348*4610Smckusick 		spacep = (char *)malloc( spaceleft );
1349*4610Smckusick 		return( ststore(savep) );
1350*4610Smckusick 	}
1351*4610Smckusick }
1352*4610Smckusick 
1353*4610Smckusick /*
1354*4610Smckusick  *	Recursively find names and inumbers of all files in subtree
1355*4610Smckusick  *	pname and put them in xtrlist[]
1356*4610Smckusick  */
1357*4610Smckusick getleaves( pname )
1358*4610Smckusick char *pname;
1359*4610Smckusick {
1360*4610Smckusick 	int 	n, 		/* loop counter */
1361*4610Smckusick 		bptsave, 	/* placeholder for pointer into drblock */
1362*4610Smckusick 		readsize;	/* nbytes read into drblock at cur level
1363*4610Smckusick 				   of recursion */
1364*4610Smckusick 	char 	locname[NSIZE];	/* pname + an entry from drblock */
1365*4610Smckusick 	daddr_t dptsave, 	/* disk loc where cur drblock came from */
1366*4610Smckusick 		disk_loc;	/* used to see if getent() causes a phys read */
1367*4610Smckusick 	ino_t 	d;		/* inode no of pname */
1368*4610Smckusick 
1369*4610Smckusick 	stcopy( pname, locname, NSIZE );
1370*4610Smckusick 	if( (d = psearch(locname)) == 0 || BIT( d, dumpmap) == 0 ) {
1371*4610Smckusick 		printf("%s: not on the tape\n", locname );
1372*4610Smckusick 		return;
1373*4610Smckusick 	}
1374*4610Smckusick 
1375*4610Smckusick 	for( n=0; n<MAXINO; n++ ) {
1376*4610Smckusick 		if( inotab[n].t_ino == d ) {
1377*4610Smckusick 			/*
1378*4610Smckusick 			 * locname is a directory name
1379*4610Smckusick 			 */
1380*4610Smckusick 				/* phys disk read forced so reset readsize */
1381*4610Smckusick 			mseek( inotab[n].t_seekpt);
1382*4610Smckusick 			getent( (char *)&dir );
1383*4610Smckusick 			readsize = nread;
1384*4610Smckusick 
1385*4610Smckusick 				/* "/" signals end of directory */
1386*4610Smckusick 			while( !direq(dir.d_name,"/") ) {
1387*4610Smckusick 
1388*4610Smckusick 				if( direq(dir.d_name,".") ) {
1389*4610Smckusick 					getent( (char *)&dir );
1390*4610Smckusick 					continue;
1391*4610Smckusick 				}
1392*4610Smckusick 
1393*4610Smckusick 				if( direq(dir.d_name,"..") ) {
1394*4610Smckusick 					getent( (char *)&dir );
1395*4610Smckusick 					continue;
1396*4610Smckusick 				}
1397*4610Smckusick 
1398*4610Smckusick 				if( append(dir.d_name,locname,NSIZE) == 0 ) {
1399*4610Smckusick 					printf("name exceedes %d char\n",NSIZE);
1400*4610Smckusick 					continue;
1401*4610Smckusick 				}
1402*4610Smckusick 
1403*4610Smckusick 					/* info for rereading drblock later */
1404*4610Smckusick 				dptsave = lseek( df, 0L, 1 ) - readsize;
1405*4610Smckusick 				bptsave = bpt;
1406*4610Smckusick 
1407*4610Smckusick 				getleaves( locname );
1408*4610Smckusick 
1409*4610Smckusick 					/* reread drblock after recursion rtn */
1410*4610Smckusick 				lseek( df, dptsave, 0 );
1411*4610Smckusick 				read( df, drblock, BSIZE );
1412*4610Smckusick 				bpt = bptsave;
1413*4610Smckusick 
1414*4610Smckusick 				if( trunc(locname) == 0 ) {
1415*4610Smckusick 					printf( "Trouble with name trunc\n" );
1416*4610Smckusick 					abort();
1417*4610Smckusick 				}
1418*4610Smckusick 					/* get next entry from drblock; reset
1419*4610Smckusick 					 * readsize iff physical disk read */
1420*4610Smckusick 				disk_loc = lseek( df, 0L, 1 );
1421*4610Smckusick 				getent( (char *)&dir );
1422*4610Smckusick 				if( lseek(df,0L,1) != disk_loc )
1423*4610Smckusick 					readsize = nread;
1424*4610Smckusick 			}
1425*4610Smckusick 			return;
1426*4610Smckusick 		}
1427*4610Smckusick 	}
1428*4610Smckusick 	/*
1429*4610Smckusick 	 * locname is name of a simple file
1430*4610Smckusick 	 */
1431*4610Smckusick 	xtrlist[i].x_ino = d;
1432*4610Smckusick 	xtrlist[i].x_flags |= XINUSE;
1433*4610Smckusick 	xtrlist[i].x_name = (char *)ststore( locname );
1434*4610Smckusick 	if( ++i >= xsize ) getxtrlist();
1435*4610Smckusick 	printf( "%s: inode %u\n", locname, d );
1436*4610Smckusick 
1437*4610Smckusick }
1438*4610Smckusick 
1439*4610Smckusick 
1440