xref: /csrg-svn/sbin/restore/main.c (revision 4700)
14610Smckusick /* Copyright (c) 1981 Regents of the University of California */
24610Smckusick 
3*4700Smckusic char version[] = "@(#)main.c 1.3 10/31/81";
44610Smckusick 
54610Smckusick /*	Modified to include h option (recursively extract all files within
64610Smckusick  *	a subtree) and m option (recreate the heirarchical structure of
74610Smckusick  *	that subtree and move extracted files to their proper homes).
84610Smckusick  *	8/29/80		by Mike Litzkow
94610Smckusick  *
104610Smckusick  *	Includes the s (skip files) option for use with multiple dumps on
114610Smckusick  *	a single tape.
124610Smckusick  */
134610Smckusick 
144611Smckusic /* static char *sccsid = "@(#)restor.c	4.3 (Berkeley) 6/3/81"; */
154610Smckusick 
164610Smckusick #define MAXINO	3000
174610Smckusick #define BITS	8
184610Smckusick #define NCACHE	3
194610Smckusick #define NSIZE   100
204610Smckusick #define SIZEINC 10
214610Smckusick 
224610Smckusick #ifndef STANDALONE
234610Smckusick #include <stdio.h>
244610Smckusick #include <signal.h>
254610Smckusick #endif
26*4700Smckusic #include "../h/param.h"
27*4700Smckusic #include "../h/inode.h"
28*4700Smckusic #include "../h/fs.h"
29*4700Smckusic #include "../h/buf.h"
30*4700Smckusic #include "../h/dir.h"
31*4700Smckusic #include "../h/user.h"
32*4700Smckusic #include "../h/dumprestor.h"
334610Smckusick 
344610Smckusick #define	MWORD(m,i) (m[(unsigned)(i-1)/MLEN])
354610Smckusick #define	MBIT(i)	(1<<((unsigned)(i-1)%MLEN))
364610Smckusick #define	BIS(i,w)	(MWORD(w,i) |=  MBIT(i))
374610Smckusick #define	BIC(i,w)	(MWORD(w,i) &= ~MBIT(i))
384610Smckusick #define	BIT(i,w)	(MWORD(w,i) & MBIT(i))
394610Smckusick 
404610Smckusick struct  direct	dir;
414610Smckusick 
424610Smckusick int	fi;
43*4700Smckusic ino_t	ino, maxi;
444610Smckusick 
45*4700Smckusic int	mt, i;
46*4700Smckusic int	eflag, hflag, mflag;
474610Smckusick 
48*4700Smckusic char	mounted = 0;
49*4700Smckusic dev_t	dev = 0;
504610Smckusick char	tapename[] = "/dev/rmt8";
514610Smckusick char	*magtape = tapename;
524610Smckusick 
534610Smckusick #ifdef STANDALONE
544610Smckusick char	mbuf[50];
554610Smckusick #endif
564610Smckusick 
574610Smckusick #ifndef STANDALONE
584610Smckusick daddr_t	seekpt;
594610Smckusick int	df, ofile;
604610Smckusick char	dirfile[] = "rstXXXXXX";
614610Smckusick 
624610Smckusick struct {
634610Smckusick 	ino_t	t_ino;
644610Smckusick 	daddr_t	t_seekpt;
654610Smckusick } inotab[MAXINO];
664610Smckusick int	ipos;
674610Smckusick 
684610Smckusick #define ONTAPE	1
694610Smckusick #define XTRACTD	2
704610Smckusick #define XINUSE	4
714610Smckusick struct xtrlist {
724610Smckusick 	ino_t	x_ino;
734610Smckusick 	char	x_flags;
744610Smckusick 	char 	*x_name;
754610Smckusick } *xtrlist;
764610Smckusick 
774610Smckusick char	name[100];
784610Smckusick 
794610Smckusick char	drblock[BSIZE];
804610Smckusick int	bpt, nread, xsize,
814610Smckusick 	init = 1;
824610Smckusick 
834610Smckusick #include <sys/mtio.h>
844610Smckusick struct mtop tcom;
854610Smckusick 
864610Smckusick int dumpnum = 1;
874610Smckusick int	volno = 1;
884610Smckusick 
89*4700Smckusic struct inode *cur_ip;
904610Smckusick 
914610Smckusick short	dumpmap[MSIZ];
924610Smckusick short	clrimap[MSIZ];
93*4700Smckusic char	clearedbuf[BSIZE];
944610Smckusick 
954610Smckusick int bct = NTREC+1;
964610Smckusick char tbf[NTREC*BSIZE];
974610Smckusick 
98*4700Smckusic char **envp;
994610Smckusick 
100*4700Smckusic main(argc, argv, arge)
101*4700Smckusic 	int argc;
102*4700Smckusic 	char *argv[];
103*4700Smckusic 	char **arge;
1044610Smckusick {
1054610Smckusick 	register char *cp;
1064610Smckusick 	char command;
107*4700Smckusic 	int (*signal())();
1084610Smckusick 	int done();
1094610Smckusick 
1104610Smckusick #ifndef STANDALONE
111*4700Smckusic 	envp = arge;
112*4700Smckusic 	mktmp(dirfile);
1134610Smckusick 	if (argc < 2) {
1144610Smckusick usage:
115*4700Smckusic 		fprintf(stderr, "Usage: restor x[s|m|h] file file..., restor r filesys, or restor t\n");
116*4700Smckusic 		done(1);
1174610Smckusick 	}
1184610Smckusick 	argv++;
1194610Smckusick 	argc -= 2;
1204610Smckusick 	for (cp = *argv++; *cp; cp++) {
1214610Smckusick 		switch (*cp) {
1224610Smckusick 		case '-':
1234610Smckusick 			break;
1244610Smckusick 		case 'f':
1254610Smckusick 			magtape = *argv++;
1264610Smckusick 			argc--;
1274610Smckusick 			break;
1284610Smckusick 		/* s dumpnum (skip to) for multifile dump tapes */
1294610Smckusick 		case 's':
1304610Smckusick 			dumpnum = atoi(*argv++);
1314610Smckusick 			if(dumpnum <= 0) {
132*4700Smckusic 				fprintf(stderr, "Dump number must be a positive integer\n");
133*4700Smckusic 				done(1);
1344610Smckusick 			}
1354610Smckusick 			argc--;
1364610Smckusick 			break;
1374610Smckusick 		case 'h':
1384610Smckusick 			hflag++;
1394610Smckusick 			break;
1404610Smckusick 		case 'm':
1414610Smckusick 			mflag++;
1424610Smckusick 			break;
1434610Smckusick 		case 'r':
1444610Smckusick 		case 'R':
1454610Smckusick 		case 't':
1464610Smckusick 		case 'x':
1474610Smckusick 			command = *cp;
1484610Smckusick 			break;
1494610Smckusick 		default:
150*4700Smckusic 			fprintf(stderr, "Bad key character %c\n", *cp);
1514610Smckusick 			goto usage;
1524610Smckusick 		}
1534610Smckusick 	}
1544610Smckusick 	if (command == 'x') {
1554610Smckusick 		if (signal(SIGINT, done) == SIG_IGN)
1564610Smckusick 			signal(SIGINT, SIG_IGN);
1574610Smckusick 		if (signal(SIGTERM, done) == SIG_IGN)
1584610Smckusick 			signal(SIGTERM, SIG_IGN);
1594610Smckusick 
1604610Smckusick 		df = creat(dirfile, 0666);
1614610Smckusick 		if (df < 0) {
162*4700Smckusic 			fprintf(stderr, "restor: %s - cannot create directory temporary\n", dirfile);
163*4700Smckusic 			done(1);
1644610Smckusick 		}
1654610Smckusick 		close(df);
166*4700Smckusic 		xmount(envp);
167*4700Smckusic 		mounted++;
1684610Smckusick 		df = open(dirfile, 2);
1694610Smckusick 	}
1704610Smckusick 	doit(command, argc, argv);
1714610Smckusick 	if (command == 'x')
1724610Smckusick 		unlink(dirfile);
173*4700Smckusic 	done(0);
1744610Smckusick #else
1754610Smckusick 	magtape = "tape";
1764610Smckusick 	doit('r', 1, 0);
1774610Smckusick #endif
1784610Smckusick }
1794610Smckusick 
1804610Smckusick doit(command, argc, argv)
181*4700Smckusic 	char	command;
182*4700Smckusic 	int	argc;
183*4700Smckusic 	char	*argv[];
1844610Smckusick {
1854610Smckusick 	extern char *ctime();
1864610Smckusick 	char *ststore();
1874610Smckusick 	register k;
1884610Smckusick 	ino_t	d;
1894610Smckusick #ifndef STANDALONE
1904611Smckusic 	int	xtrfile(), skip(), null();
1914610Smckusick #endif
1924610Smckusick 	int	rstrfile(), rstrskip();
193*4700Smckusic 	register struct dinode *dp;
194*4700Smckusic 	register struct inode *ip;
195*4700Smckusic 	struct fs *fs;
1964610Smckusick 
1974610Smckusick #ifndef STANDALONE
1984610Smckusick 	getxtrlist();
1994610Smckusick 	if ((mt = open(magtape, 0)) < 0) {
200*4700Smckusic 		fprintf(stderr, "%s: cannot open tape\n", magtape);
201*4700Smckusic 		done(1);
2024610Smckusick 	}
2034610Smckusick 	if(dumpnum != 1) {
2044610Smckusick 		tcom.mt_op = MTFSF;
2054610Smckusick 		tcom.mt_count = dumpnum -1;
2064610Smckusick 		if( ioctl(mt,MTIOCTOP,&tcom) < 0)
2074610Smckusick 			perror("ioctl MTFSF");
2084610Smckusick 	}
2094610Smckusick #else
2104610Smckusick 	do {
211*4700Smckusic 		fprintf(stderr, "Tape? ");
2124610Smckusick 		gets(mbuf);
2134610Smckusick 		mt = open(mbuf, 0);
2144610Smckusick 	} while (mt == -1);
2154610Smckusick 	magtape = mbuf;
216*4700Smckusic 	clearbuf(clearedbuf);
2174610Smckusick #endif
2184610Smckusick 	switch(command) {
2194610Smckusick #ifndef STANDALONE
2204610Smckusick 	case 't':
2214610Smckusick 		if (readhdr(&spcl) == 0) {
222*4700Smckusic 			fprintf(stderr, "Tape is not a dump tape\n");
223*4700Smckusic 			done(1);
2244610Smckusick 		}
225*4700Smckusic 		fprintf(stderr, "Dump   date: %s", ctime(&spcl.c_date));
226*4700Smckusic 		fprintf(stderr, "Dumped from: %s", ctime(&spcl.c_ddate));
2274610Smckusick 		return;
2284610Smckusick 	case 'x':
2294610Smckusick 		if (readhdr(&spcl) == 0) {
230*4700Smckusic 			fprintf(stderr, "Tape is not a dump tape\n");
231*4700Smckusic 			done(1);
2324610Smckusick 		}
2334610Smckusick 		if (checkvol(&spcl, 1) == 0) {
234*4700Smckusic 			fprintf(stderr, "Tape is not volume 1 of the dump\n");
2354610Smckusick 		}
2364610Smckusick 		pass1();  /* This sets the various maps on the way by */
2374610Smckusick 		i = 0;
2384610Smckusick 		while( argc-- ) {
2394610Smckusick 			if(hflag)
2404610Smckusick 				getleaves( *argv++ );
2414610Smckusick 			else {
2424610Smckusick 				if( (d = psearch(*argv)) == 0 ||
2434610Smckusick 							BIT(d,dumpmap) == 0 ) {
244*4700Smckusic 					fprintf(stderr,  "%s: not on tape\n", *argv++ );
2454610Smckusick 					continue;
2464610Smckusick 				}
2474610Smckusick 				xtrlist[i].x_ino = d;
2484610Smckusick 				xtrlist[i].x_flags |= XINUSE;
2494610Smckusick 				if( mflag )
2504610Smckusick 					xtrlist[i].x_name = ststore( *argv );
251*4700Smckusic 				fprintf(stderr,  "%s: inode %u\n", *argv, d );
2524610Smckusick 				argv++;
2534610Smckusick 				if( ++i >= xsize ) getxtrlist();
2544610Smckusick 			}
2554610Smckusick 		}
2564610Smckusick 
2574610Smckusick 
2584610Smckusick 		if(dumpnum > 1)
2594610Smckusick 			tcom.mt_op = MTBSF;
2604610Smckusick 		else	tcom.mt_op = MTREW;
2614610Smckusick 		tcom.mt_count = 1;
2624610Smckusick 
2634610Smckusick newvol:
2644610Smckusick 		flsht();
2654610Smckusick 		ioctl(mt,MTIOCTOP,&tcom);
2664610Smckusick 		if( dumpnum > 1 ) {
2674610Smckusick 			tcom.mt_op = MTFSF;
2684610Smckusick 			tcom.mt_count = 1;
2694610Smckusick 			ioctl(mt,MTIOCTOP,&tcom);
2704610Smckusick 		}
271*4700Smckusic 		lseek(mt, 0, 0);
2724610Smckusick 
2734610Smckusick 
2744610Smckusick getvol:
275*4700Smckusic 		fprintf(stderr, "Mount desired tape volume: Specify volume #: ");
2764610Smckusick 		if (gets(tbf) == NULL)
2774610Smckusick 			return;
2784610Smckusick 		volno = atoi(tbf);
2794610Smckusick 		if (volno <= 0) {
280*4700Smckusic 			fprintf(stderr, "Volume numbers are positive numerics\n");
2814610Smckusick 			goto getvol;
2824610Smckusick 		}
2834610Smckusick 		if (readhdr(&spcl) == 0) {
284*4700Smckusic 			fprintf(stderr, "tape is not dump tape\n");
2854610Smckusick 			goto newvol;
2864610Smckusick 		}
2874610Smckusick 		if (checkvol(&spcl, volno) == 0) {
288*4700Smckusic 			fprintf(stderr, "Wrong volume (%d)\n", spcl.c_volume);
2894610Smckusick 			goto newvol;
2904610Smckusick 		}
2914610Smckusick rbits:
2924610Smckusick 		while (gethead(&spcl) == 0)
2934610Smckusick 			;
2944610Smckusick 		if (checktype(&spcl, TS_INODE) == 1) {
295*4700Smckusic 			fprintf(stderr, "Can't find inode mask!\n");
2964610Smckusick 			goto newvol;
2974610Smckusick 		}
2984610Smckusick 		if (checktype(&spcl, TS_BITS) == 0)
2994610Smckusick 			goto rbits;
3004610Smckusick 		readbits(dumpmap);
3014610Smckusick 		i = 0;
3024610Smckusick 		for (k = 0; xtrlist[k].x_flags; k++) {
3034610Smckusick 			if (BIT(xtrlist[k].x_ino, dumpmap)) {
3044610Smckusick 				xtrlist[k].x_flags |= ONTAPE;
3054610Smckusick 				i++;
3064610Smckusick 			}
3074610Smckusick 		}
3084610Smckusick 		while (i > 0) {
3094610Smckusick again:
3104610Smckusick 			if (ishead(&spcl) == 0)
3114610Smckusick 				while(gethead(&spcl) == 0)
3124610Smckusick 					;
3134610Smckusick 			if (checktype(&spcl, TS_END) == 1) {
314*4700Smckusic 				fprintf(stderr, "end of tape\n");
3154610Smckusick checkdone:
3164610Smckusick 				for (k = 0; xtrlist[k].x_flags; k++)
3174610Smckusick 					if ((xtrlist[k].x_flags&XTRACTD) == 0) {
3184610Smckusick 						/* get next tape */
3194610Smckusick 						tcom.mt_op = MTREW;
3204610Smckusick 
3214610Smckusick 						goto newvol;
3224610Smckusick 					}
3234610Smckusick 				return;
3244610Smckusick 			}
3254610Smckusick 			if (checktype(&spcl, TS_INODE) == 0) {
3264610Smckusick 				gethead(&spcl);
3274610Smckusick 				goto again;
3284610Smckusick 			}
3294610Smckusick 			d = spcl.c_inumber;
3304610Smckusick 			for (k = 0; xtrlist[k].x_flags; k++) {
3314610Smckusick 				if (d == xtrlist[k].x_ino) {
3324610Smckusick 					if( mflag ) {
3334610Smckusick 						sprintf(name, "%s", xtrlist[k].x_name);
334*4700Smckusic 						fprintf(stderr, "extract file %s\n",name);
3354610Smckusick 						checkdir( name );
3364610Smckusick 					}
3374610Smckusick 					else {
338*4700Smckusic 						fprintf(stderr, "extract file %u\n", xtrlist[k].x_ino );
3394610Smckusick 						sprintf(name, "%u", xtrlist[k].x_ino);
3404610Smckusick 					}
341*4700Smckusic 					if ((ofile = xcreat(name, 0666)) < 0) {
342*4700Smckusic 						fprintf(stderr, "%s: cannot create file\n", name);
3434610Smckusick 						i--;
3444610Smckusick 						continue;
3454610Smckusick 					}
346*4700Smckusic 					xchown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
347*4700Smckusic 					getfile(xtrfile, skip, spcl.c_dinode.di_size);
3484610Smckusick 					i--;
3494610Smckusick 					xtrlist[k].x_flags |= XTRACTD;
350*4700Smckusic 					xclose(ofile);
351*4700Smckusic 					goto finished;
3524610Smckusick 				}
3534610Smckusick 			}
354*4700Smckusic 			getfile(null, null, spcl.c_dinode.di_size);
355*4700Smckusic finished:
3564610Smckusick 			;
3574610Smckusick 		}
3584610Smckusick 		goto checkdone;
3594610Smckusick #endif
3604610Smckusick 	case 'r':
3614610Smckusick 	case 'R':
3624610Smckusick #ifndef STANDALONE
363*4700Smckusic 		{
364*4700Smckusic 			char mount[80];
365*4700Smckusic 			char *ptr[2];
366*4700Smckusic 
367*4700Smckusic 			strcpy(mount, "MOUNT=");
368*4700Smckusic 			strcat(mount, *argv);
369*4700Smckusic 			ptr[0] = mount;
370*4700Smckusic 			ptr[1] = 0;
371*4700Smckusic 			xmount(ptr);
372*4700Smckusic 			iput(u.u_cdir); /* release root inode */
373*4700Smckusic 			iput(u.u_rdir); /* release root inode */
374*4700Smckusic 			mounted++;
3754610Smckusick 		}
3764610Smckusick #else
3774610Smckusick 		do {
3784610Smckusick 			char charbuf[50];
3794610Smckusick 
380*4700Smckusic 			fprintf(stderr, "Disk? ");
3814610Smckusick 			gets(charbuf);
3824610Smckusick 			fi = open(charbuf, 2);
3834610Smckusick 		} while (fi == -1);
3844610Smckusick #endif
3854610Smckusick #ifndef STANDALONE
3864610Smckusick 		if (command == 'R') {
387*4700Smckusic 			fprintf(stderr, "Enter starting volume number: ");
3884610Smckusick 			if (gets(tbf) == EOF) {
3894610Smckusick 				volno = 1;
390*4700Smckusic 				fprintf(stderr, "\n");
3914610Smckusick 			}
3924610Smckusick 			else
3934610Smckusick 				volno = atoi(tbf);
3944610Smckusick 		}
3954610Smckusick 		else
3964610Smckusick #endif
3974610Smckusick 			volno = 1;
398*4700Smckusic 		fprintf(stderr, "Last chance before scribbling on %s. ",
3994610Smckusick #ifdef STANDALONE
4004610Smckusick 								"disk");
4014610Smckusick #else
4024610Smckusick 								*argv);
4034610Smckusick #endif
4044610Smckusick 		while (getchar() != '\n');
405*4700Smckusic 		fs = getfs(dev);
406*4700Smckusic 		maxi = fs->fs_ipg * fs->fs_ncg;
4074610Smckusick 		if (readhdr(&spcl) == 0) {
408*4700Smckusic 			fprintf(stderr, "Missing volume record\n");
409*4700Smckusic 			done(1);
4104610Smckusick 		}
4114610Smckusick 		if (checkvol(&spcl, volno) == 0) {
412*4700Smckusic 			fprintf(stderr, "Tape is not volume %d\n", volno);
413*4700Smckusic 			done(1);
4144610Smckusick 		}
4154610Smckusick 		gethead(&spcl);
4164610Smckusick 		for (;;) {
4174610Smckusick ragain:
4184610Smckusick 			if (ishead(&spcl) == 0) {
419*4700Smckusic 				fprintf(stderr, "Missing header block\n");
4204610Smckusick 				while (gethead(&spcl) == 0)
4214610Smckusick 					;
4224610Smckusick 				eflag++;
4234610Smckusick 			}
4244610Smckusick 			if (checktype(&spcl, TS_END) == 1) {
425*4700Smckusic 				fprintf(stderr, "End of tape\n");
4264610Smckusick 				close(mt);
4274610Smckusick 				return;
4284610Smckusick 			}
4294610Smckusick 			if (checktype(&spcl, TS_CLRI) == 1) {
4304610Smckusick 				readbits(clrimap);
4314610Smckusick 				for (ino = 1; ino <= maxi; ino++)
4324610Smckusick 					if (BIT(ino, clrimap) == 0) {
433*4700Smckusic 						if (!iexist(dev, ino))
4344610Smckusick 							continue;
435*4700Smckusic 						ip = iget(dev, ino);
436*4700Smckusic 						if (ip == NULL) {
437*4700Smckusic 							fprintf(stderr, "can't find inode %u\n", ino);
438*4700Smckusic 							done(1);
439*4700Smckusic 						}
440*4700Smckusic 						ip->i_nlink = 0;
441*4700Smckusic 						ip->i_flag |= ICHG;
442*4700Smckusic 						iput(ip);
4434610Smckusick 					}
4444610Smckusick 				goto ragain;
4454610Smckusick 			}
4464610Smckusick 			if (checktype(&spcl, TS_BITS) == 1) {
4474610Smckusick 				readbits(dumpmap);
4484610Smckusick 				goto ragain;
4494610Smckusick 			}
4504610Smckusick 			if (checktype(&spcl, TS_INODE) == 0) {
451*4700Smckusic 				fprintf(stderr, "Unknown header type\n");
4524610Smckusick 				eflag++;
4534610Smckusick 				gethead(&spcl);
4544610Smckusick 				goto ragain;
4554610Smckusick 			}
4564610Smckusick 			ino = spcl.c_inumber;
4574610Smckusick 			if (eflag)
458*4700Smckusic 				fprintf(stderr, "Resynced at inode %u\n", ino);
4594610Smckusick 			eflag = 0;
4604610Smckusick 			if (ino > maxi) {
461*4700Smckusic 				fprintf(stderr, "%u: ilist too small\n", ino);
4624610Smckusick 				gethead(&spcl);
4634610Smckusick 				goto ragain;
4644610Smckusick 			}
465*4700Smckusic 			if (iexist(dev, ino)) {
466*4700Smckusic 				ip = iget(dev, ino);
467*4700Smckusic 				if (ip == NULL) {
468*4700Smckusic 					fprintf(stderr, "can't find inode %u\n",
469*4700Smckusic 						ino);
470*4700Smckusic 					done(1);
471*4700Smckusic 				}
472*4700Smckusic 				ip->i_nlink = 0;
473*4700Smckusic 				ip->i_flag |= ICHG;
474*4700Smckusic 				iput(ip);
475*4700Smckusic 			}
476*4700Smckusic 			dp = &spcl.c_dinode;
477*4700Smckusic 			ip = ialloc(dev, ino, dp->di_mode);
478*4700Smckusic 			if (ip == NULL || ip->i_number != ino) {
479*4700Smckusic 				fprintf(stderr, "can't create inode %u\n", ino);
480*4700Smckusic 				done(1);
481*4700Smckusic 			}
482*4700Smckusic 			ip->i_mode = dp->di_mode;
483*4700Smckusic 			ip->i_nlink = dp->di_nlink;
484*4700Smckusic 			ip->i_uid = dp->di_uid;
485*4700Smckusic 			ip->i_gid = dp->di_gid;
486*4700Smckusic 			ip->i_size = dp->di_size;
487*4700Smckusic 			ip->i_atime = dp->di_atime;
488*4700Smckusic 			ip->i_mtime = dp->di_mtime;
489*4700Smckusic 			ip->i_ctime = dp->di_ctime;
490*4700Smckusic 			cur_ip = ip;
491*4700Smckusic 			u.u_offset = 0;
492*4700Smckusic 			u.u_segflg = 1;
493*4700Smckusic 			getfile(rstrfile, rstrskip, dp->di_size);
494*4700Smckusic 			ip->i_flag |= ICHG;
495*4700Smckusic 			iput(ip);
4964610Smckusick 		}
4974610Smckusick 	}
4984610Smckusick }
4994610Smckusick 
5004610Smckusick /*
5014610Smckusick  * Read the tape, bulding up a directory structure for extraction
5024610Smckusick  * by name
5034610Smckusick  */
5044610Smckusick #ifndef STANDALONE
5054610Smckusick pass1()
5064610Smckusick {
5074610Smckusick 	register i;
5084610Smckusick 	struct dinode *ip;
5094610Smckusick 	int	putdir(), null();
5104610Smckusick 
5114610Smckusick 	while (gethead(&spcl) == 0) {
512*4700Smckusic 		fprintf(stderr, "Can't find directory header!\n");
5134610Smckusick 	}
5144610Smckusick 	for (;;) {
5154610Smckusick 		if (checktype(&spcl, TS_BITS) == 1) {
5164610Smckusick 			readbits(dumpmap);
5174610Smckusick 			continue;
5184610Smckusick 		}
5194610Smckusick 		if (checktype(&spcl, TS_CLRI) == 1) {
5204610Smckusick 			readbits(clrimap);
5214610Smckusick 			continue;
5224610Smckusick 		}
5234610Smckusick 		if (checktype(&spcl, TS_INODE) == 0) {
5244610Smckusick finish:
5254610Smckusick 			flsh();
5264610Smckusick /*
5274610Smckusick 			close(mt);
5284610Smckusick */
5294610Smckusick 			return;
5304610Smckusick 		}
5314610Smckusick 		ip = &spcl.c_dinode;
5324610Smckusick 		i = ip->di_mode & IFMT;
5334610Smckusick 		if (i != IFDIR) {
5344610Smckusick 			goto finish;
5354610Smckusick 		}
5364610Smckusick 		inotab[ipos].t_ino = spcl.c_inumber;
5374610Smckusick 		inotab[ipos++].t_seekpt = seekpt;
538*4700Smckusic 		getfile(putdir, null, spcl.c_dinode.di_size);
5394610Smckusick 		putent("\000\000/");
5404610Smckusick 	}
5414610Smckusick }
5424610Smckusick #endif
5434610Smckusick 
5444610Smckusick /*
5454610Smckusick  * Do the file extraction, calling the supplied functions
5464610Smckusick  * with the blocks
5474610Smckusick  */
548*4700Smckusic getfile(f1, f2, size)
549*4700Smckusic 	int	(*f2)(), (*f1)();
550*4700Smckusic 	long	size;
5514610Smckusick {
5524610Smckusick 	register i;
5534610Smckusick 	struct spcl addrblock;
5544610Smckusick 	char buf[BSIZE];
5554610Smckusick 
5564610Smckusick 	addrblock = spcl;
5574610Smckusick 	for (;;) {
5584610Smckusick 		for (i = 0; i < addrblock.c_count; i++) {
5594610Smckusick 			if (addrblock.c_addr[i]) {
5604610Smckusick 				readtape(buf);
5614610Smckusick 				(*f1)(buf, size > BSIZE ? (long) BSIZE : size);
5624610Smckusick 			}
5634610Smckusick 			else {
564*4700Smckusic 				(*f2)(clearedbuf, size > BSIZE ? (long) BSIZE : size);
5654610Smckusick 			}
5664610Smckusick 			if ((size -= BSIZE) <= 0) {
5674610Smckusick eloop:
5684610Smckusick 				while (gethead(&spcl) == 0)
5694610Smckusick 					;
5704610Smckusick 				if (checktype(&spcl, TS_ADDR) == 1)
5714610Smckusick 					goto eloop;
5724610Smckusick 				return;
5734610Smckusick 			}
5744610Smckusick 		}
575*4700Smckusic 		if (gethead(&addrblock) == 0) {
576*4700Smckusic 			fprintf(stderr, "Missing address (header) block\n");
577*4700Smckusic 			goto eloop;
578*4700Smckusic 		}
579*4700Smckusic 		if (checktype(&addrblock, TS_ADDR) == 0) {
580*4700Smckusic 			spcl = addrblock;
581*4700Smckusic 			return;
582*4700Smckusic 		}
5834610Smckusick 	}
5844610Smckusick }
5854610Smckusick 
5864610Smckusick /*
5874610Smckusick  * Do the tape i\/o, dealling with volume changes
5884610Smckusick  * etc..
5894610Smckusick  */
5904610Smckusick readtape(b)
591*4700Smckusic 	char *b;
5924610Smckusick {
5934610Smckusick 	register i;
5944610Smckusick 	struct spcl tmpbuf;
5954610Smckusick 
5964610Smckusick 	if (bct >= NTREC) {
5974610Smckusick 		for (i = 0; i < NTREC; i++)
5984610Smckusick 			((struct spcl *)&tbf[i*BSIZE])->c_magic = 0;
5994610Smckusick 		bct = 0;
6004610Smckusick 		if ((i = read(mt, tbf, NTREC*BSIZE)) < 0) {
601*4700Smckusic 			perror("Tape read error");
6024610Smckusick 			eflag++;
603*4700Smckusic 			done(1);
6044610Smckusick 		}
6054610Smckusick 		if (i == 0) {
6064610Smckusick 			bct = NTREC + 1;
6074610Smckusick 			volno++;
6084610Smckusick loop:
6094610Smckusick 			flsht();
6104610Smckusick 			close(mt);
611*4700Smckusic 			fprintf(stderr, "Mount volume %d\n", volno);
6124610Smckusick 			while (getchar() != '\n')
6134610Smckusick 				;
6144610Smckusick 			if ((mt = open(magtape, 0)) == -1) {
615*4700Smckusic 				fprintf(stderr, "Cannot open tape!\n");
6164610Smckusick 				goto loop;
6174610Smckusick 			}
6184610Smckusick 			if (readhdr(&tmpbuf) == 0) {
619*4700Smckusic 				fprintf(stderr, "Not a dump tape.Try again\n");
6204610Smckusick 				goto loop;
6214610Smckusick 			}
6224610Smckusick 			if (checkvol(&tmpbuf, volno) == 0) {
623*4700Smckusic 				fprintf(stderr, "Wrong tape. Try again\n");
6244610Smckusick 				goto loop;
6254610Smckusick 			}
6264610Smckusick 			readtape(b);
6274610Smckusick 			return;
6284610Smckusick 		}
6294610Smckusick 	}
6304610Smckusick 	copy(&tbf[(bct++*BSIZE)], b, BSIZE);
6314610Smckusick }
6324610Smckusick 
6334610Smckusick flsht()
6344610Smckusick {
6354610Smckusick 	bct = NTREC+1;
6364610Smckusick }
6374610Smckusick 
6384610Smckusick copy(f, t, s)
639*4700Smckusic 	register char *f, *t;
6404610Smckusick {
6414610Smckusick 	register i;
6424610Smckusick 
6434610Smckusick 	i = s;
6444610Smckusick 	do
6454610Smckusick 		*t++ = *f++;
6464610Smckusick 	while (--i);
6474610Smckusick }
6484610Smckusick 
6494610Smckusick clearbuf(cp)
650*4700Smckusic 	register char *cp;
6514610Smckusick {
6524610Smckusick 	register i;
6534610Smckusick 
6544610Smckusick 	i = BSIZE;
6554610Smckusick 	do
6564610Smckusick 		*cp++ = 0;
6574610Smckusick 	while (--i);
6584610Smckusick }
6594610Smckusick 
6604610Smckusick /*
6614610Smckusick  * Put and get the directory entries from the compressed
6624610Smckusick  * directory file
6634610Smckusick  */
6644610Smckusick #ifndef STANDALONE
6654610Smckusick putent(cp)
666*4700Smckusic 	char	*cp;
6674610Smckusick {
6684610Smckusick 	register i;
6694610Smckusick 
6704610Smckusick 	for (i = 0; i < sizeof(ino_t); i++)
6714610Smckusick 		writec(*cp++);
6724610Smckusick 	for (i = 0; i < DIRSIZ; i++) {
6734610Smckusick 		writec(*cp);
6744610Smckusick 		if (*cp++ == 0)
6754610Smckusick 			return;
6764610Smckusick 	}
6774610Smckusick 	return;
6784610Smckusick }
6794610Smckusick 
6804610Smckusick getent(bf)
681*4700Smckusic 	register char *bf;
6824610Smckusick {
6834610Smckusick 	register i;
6844610Smckusick 
6854610Smckusick 	for (i = 0; i < sizeof(ino_t); i++)
6864610Smckusick 		*bf++ = readc();
6874610Smckusick 	for (i = 0; i < DIRSIZ; i++)
6884610Smckusick 		if ((*bf++ = readc()) == 0)
6894610Smckusick 			return;
6904610Smckusick 	return;
6914610Smckusick }
6924610Smckusick 
6934610Smckusick /*
6944610Smckusick  * read/write te directory file
6954610Smckusick  */
6964610Smckusick writec(c)
697*4700Smckusic 	char c;
6984610Smckusick {
6994610Smckusick 	drblock[bpt++] = c;
7004610Smckusick 	seekpt++;
7014610Smckusick 	if (bpt >= BSIZE) {
7024610Smckusick 		bpt = 0;
7034610Smckusick 		write(df, drblock, BSIZE);
7044610Smckusick 	}
7054610Smckusick }
7064610Smckusick 
7074610Smckusick readc()
7084610Smckusick {
7094610Smckusick 	if (bpt >= BSIZE) {
7104610Smckusick 		nread = read(df, drblock, BSIZE);
7114610Smckusick 		bpt = 0;
7124610Smckusick 	}
7134610Smckusick 	return(drblock[bpt++]);
7144610Smckusick }
7154610Smckusick 
7164610Smckusick mseek(pt)
717*4700Smckusic 	daddr_t pt;
7184610Smckusick {
7194610Smckusick 	bpt = BSIZE;
7204610Smckusick 	lseek(df, pt, 0);
7214610Smckusick }
7224610Smckusick 
7234610Smckusick flsh()
7244610Smckusick {
7254610Smckusick 	write(df, drblock, bpt+1);
7264610Smckusick }
7274610Smckusick 
7284610Smckusick /*
7294610Smckusick  * search the directory inode ino
7304610Smckusick  * looking for entry cp
7314610Smckusick  */
7324610Smckusick ino_t
7334610Smckusick search(inum, cp)
734*4700Smckusic 	ino_t	inum;
735*4700Smckusic 	char	*cp;
7364610Smckusick {
7374610Smckusick 	register i;
7384610Smckusick 
7394610Smckusick 	for (i = 0; i < MAXINO; i++)
7404610Smckusick 		if (inotab[i].t_ino == inum) {
7414610Smckusick 			goto found;
7424610Smckusick 		}
7434610Smckusick 	return(0);
7444610Smckusick found:
7454610Smckusick 	mseek(inotab[i].t_seekpt);
7464610Smckusick 	do {
7474610Smckusick 		getent((char *)&dir);
7484610Smckusick 		if (direq(dir.d_name, "/"))
7494610Smckusick 			return(0);
7504610Smckusick 	} while (direq(dir.d_name, cp) == 0);
7514610Smckusick 	return(dir.d_ino);
7524610Smckusick }
7534610Smckusick 
7544610Smckusick /*
755*4700Smckusic  * Search the directory tree rooted at inode ROOTINO
7564610Smckusick  * for the path pointed at by n
7574610Smckusick  */
7584610Smckusick psearch(n)
759*4700Smckusic 	char	*n;
7604610Smckusick {
7614610Smckusick 	register char *cp, *cp1;
7624610Smckusick 	char c;
7634610Smckusick 
764*4700Smckusic 	ino = ROOTINO;
7654610Smckusick 	if (*(cp = n) == '/')
7664610Smckusick 		cp++;
7674610Smckusick next:
7684610Smckusick 	cp1 = cp + 1;
7694610Smckusick 	while (*cp1 != '/' && *cp1)
7704610Smckusick 		cp1++;
7714610Smckusick 	c = *cp1;
7724610Smckusick 	*cp1 = 0;
7734610Smckusick 	ino = search(ino, cp);
7744610Smckusick 	if (ino == 0) {
7754610Smckusick 		*cp1 = c;
7764610Smckusick 		return(0);
7774610Smckusick 	}
7784610Smckusick 	*cp1 = c;
7794610Smckusick 	if (c == '/') {
7804610Smckusick 		cp = cp1+1;
7814610Smckusick 		goto next;
7824610Smckusick 	}
7834610Smckusick 	return(ino);
7844610Smckusick }
7854610Smckusick 
7864610Smckusick direq(s1, s2)
787*4700Smckusic 	register char *s1, *s2;
7884610Smckusick {
7894610Smckusick 	register i;
7904610Smckusick 
7914610Smckusick 	for (i = 0; i < DIRSIZ; i++)
7924610Smckusick 		if (*s1++ == *s2) {
7934610Smckusick 			if (*s2++ == 0)
7944610Smckusick 				return(1);
7954610Smckusick 		} else
7964610Smckusick 			return(0);
7974610Smckusick 	return(1);
7984610Smckusick }
7994610Smckusick #endif
8004610Smckusick 
8014610Smckusick /*
8024610Smckusick  * read the tape into buf, then return whether or
8034610Smckusick  * or not it is a header block.
8044610Smckusick  */
8054610Smckusick gethead(buf)
806*4700Smckusic 	struct spcl *buf;
8074610Smckusick {
8084610Smckusick 	readtape((char *)buf);
8094610Smckusick 	if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
8104610Smckusick 		return(0);
8114610Smckusick 	return(1);
8124610Smckusick }
8134610Smckusick 
8144610Smckusick /*
8154610Smckusick  * return whether or not the buffer contains a header block
8164610Smckusick  */
8174610Smckusick ishead(buf)
818*4700Smckusic 	struct spcl *buf;
8194610Smckusick {
8204610Smckusick 	if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
8214610Smckusick 		return(0);
8224610Smckusick 	return(1);
8234610Smckusick }
8244610Smckusick 
8254610Smckusick checktype(b, t)
826*4700Smckusic 	struct	spcl *b;
827*4700Smckusic 	int	t;
8284610Smckusick {
8294610Smckusick 	return(b->c_type == t);
8304610Smckusick }
8314610Smckusick 
8324610Smckusick 
8334610Smckusick checksum(b)
834*4700Smckusic 	int *b;
8354610Smckusick {
8364610Smckusick 	register i, j;
8374610Smckusick 
8384610Smckusick 	j = BSIZE/sizeof(int);
8394610Smckusick 	i = 0;
8404610Smckusick 	do
8414610Smckusick 		i += *b++;
8424610Smckusick 	while (--j);
8434610Smckusick 	if (i != CHECKSUM) {
844*4700Smckusic 		fprintf(stderr, "Checksum error %o\n", i);
8454610Smckusick 		return(0);
8464610Smckusick 	}
8474610Smckusick 	return(1);
8484610Smckusick }
8494610Smckusick 
8504610Smckusick checkvol(b, t)
851*4700Smckusic 	struct spcl *b;
852*4700Smckusic 	int t;
8534610Smckusick {
8544610Smckusick 	if (b->c_volume == t)
8554610Smckusick 		return(1);
8564610Smckusick 	return(0);
8574610Smckusick }
8584610Smckusick 
8594610Smckusick readhdr(b)
860*4700Smckusic 	struct	spcl *b;
8614610Smckusick {
8624610Smckusick 	if (gethead(b) == 0)
8634610Smckusick 		return(0);
8644610Smckusick 	if (checktype(b, TS_TAPE) == 0)
8654610Smckusick 		return(0);
8664610Smckusick 	return(1);
8674610Smckusick }
8684610Smckusick 
8694610Smckusick /*
8704610Smckusick  * The next routines are called during file extraction to
8714610Smckusick  * put the data into the right form and place.
8724610Smckusick  */
8734610Smckusick #ifndef STANDALONE
874*4700Smckusic xtrfile(buf, size)
875*4700Smckusic 	char	*buf;
876*4700Smckusic 	long	size;
8774610Smckusick {
878*4700Smckusic 	xwrite(ofile, buf, (int) size);
8794610Smckusick }
8804610Smckusick 
8814610Smckusick null() {;}
8824610Smckusick 
883*4700Smckusic skip(buf, size)
884*4700Smckusic 	char *buf;
885*4700Smckusic 	long size;
8864610Smckusick {
887*4700Smckusic 	xseek(ofile, size, 1);
8884610Smckusick }
8894610Smckusick #endif
8904610Smckusick 
8914610Smckusick 
892*4700Smckusic rstrfile(buf, size)
893*4700Smckusic 	char *buf;
894*4700Smckusic 	long size;
8954610Smckusick {
896*4700Smckusic 	u.u_base = buf;
897*4700Smckusic 	u.u_count = size;
898*4700Smckusic 	writei(cur_ip);
899*4700Smckusic }
9004610Smckusick 
901*4700Smckusic rstrskip(buf, size)
902*4700Smckusic 	char *buf;
903*4700Smckusic 	long size;
904*4700Smckusic {
905*4700Smckusic 	u.u_offset += size;
9064610Smckusick }
9074610Smckusick 
908*4700Smckusic /*
909*4700Smckusic  * tell whether an inode is allocated
910*4700Smckusic  * this is drawn from ialloccg in sys/alloc.c
911*4700Smckusic  */
912*4700Smckusic iexist(dev, ino)
913*4700Smckusic 	dev_t dev;
914*4700Smckusic 	ino_t ino;
9154610Smckusick {
916*4700Smckusic 	register struct fs *fs;
917*4700Smckusic 	register struct cg *cgp;
918*4700Smckusic 	register struct buf *bp;
919*4700Smckusic 	int cg;
920*4700Smckusic 
921*4700Smckusic 	fs = getfs(dev);
922*4700Smckusic 	if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg)
923*4700Smckusic 		return (0);
924*4700Smckusic 	cg = itog(ino, fs);
925*4700Smckusic 	bp = bread(dev, cgtod(cg, fs), BSIZE);
926*4700Smckusic 	if (bp->b_flags & B_ERROR)
927*4700Smckusic 		return(0);
928*4700Smckusic 	cgp = bp->b_un.b_cg;
929*4700Smckusic 	ino %= fs->fs_ipg;
930*4700Smckusic 	if (isclr(cgp->cg_iused, ino)) {
931*4700Smckusic 		brelse(bp);
932*4700Smckusic 		return(0);
933*4700Smckusic 	}
934*4700Smckusic 	brelse(bp);
935*4700Smckusic 	return (1);
9364610Smckusick }
9374610Smckusick 
9384610Smckusick #ifndef STANDALONE
939*4700Smckusic putdir(buf, size)
940*4700Smckusic 	char *buf;
941*4700Smckusic 	int size;
9424610Smckusick {
9434610Smckusick 	register struct direct *dp;
9444610Smckusick 	register i;
9454610Smckusick 
946*4700Smckusic 	for (dp = (struct direct *) buf, i = 0; i < size; dp++, i += sizeof(*dp)) {
9474610Smckusick 		if (dp->d_ino == 0)
9484610Smckusick 			continue;
9494610Smckusick 		putent((char *) dp);
9504610Smckusick 	}
9514610Smckusick }
9524610Smckusick #endif
9534610Smckusick 
9544610Smckusick /*
9554610Smckusick  * read a bit mask from the tape into m.
9564610Smckusick  */
9574610Smckusick readbits(m)
958*4700Smckusic 	short	*m;
9594610Smckusick {
9604610Smckusick 	register i;
9614610Smckusick 
9624610Smckusick 	i = spcl.c_count;
9634610Smckusick 
9644610Smckusick 	while (i--) {
9654610Smckusick 		readtape((char *) m);
9664610Smckusick 		m += (BSIZE/(MLEN/BITS));
9674610Smckusick 	}
9684610Smckusick 	while (gethead(&spcl) == 0)
9694610Smckusick 		;
9704610Smckusick }
9714610Smckusick 
972*4700Smckusic done(exitcode)
973*4700Smckusic 	int exitcode;
9744610Smckusick {
9754610Smckusick #ifndef STANDALONE
9764610Smckusick 	unlink(dirfile);
9774610Smckusick #endif
978*4700Smckusic 	if (mounted)
979*4700Smckusic 		xumount();
980*4700Smckusic 	exit(exitcode);
9814610Smckusick }
9824610Smckusick 
9834610Smckusick stcopy( sourcep, destp, max )
984*4700Smckusic 	char *sourcep, *destp;
985*4700Smckusic 	int max;
9864610Smckusick {
9874610Smckusick 	int i;
9884610Smckusick 	for( i=1; i<=max && (*destp++ = *sourcep++); i++ )
9894610Smckusick 		;
9904610Smckusick 	if( i > max )	return( 0 );
9914610Smckusick 	else		return( 1 );
9924610Smckusick }
9934610Smckusick 
9944610Smckusick append( sourcep, destp, max )
995*4700Smckusic 	char *sourcep, *destp;
996*4700Smckusic 	int max;
9974610Smckusick {
9984610Smckusick 	int i;
9994610Smckusick 	for( i=0; *destp; i++ )
10004610Smckusick 		*destp++;
10014610Smckusick 	if( ++i <= max ) *destp++ = '/';
10024610Smckusick 	while( ++i<=max && (*destp++ = *sourcep++) )
10034610Smckusick 		;
10044610Smckusick 	if( i > max )	return( 0 );
10054610Smckusick 	else		return( 1 );
10064610Smckusick }
10074610Smckusick /*
10084610Smckusick  *	Truncate the rightmost file or directory name from a pathname
10094610Smckusick  */
10104610Smckusick 
10114610Smckusick trunc( cp )
1012*4700Smckusic 	char *cp;
10134610Smckusick {
10144610Smckusick 	char *lstslsh;
10154610Smckusick 	lstslsh = 0;
10164610Smckusick 	while( *cp++ )
10174610Smckusick 		if( *cp == '/' ) lstslsh = cp;
10184610Smckusick 	if( lstslsh == 0 )
10194610Smckusick 		return( 0 );
10204610Smckusick 	else {
10214610Smckusick 		*lstslsh = '\0';
10224610Smckusick 		return( 1 );
10234610Smckusick 	}
10244610Smckusick }
10254610Smckusick getxtrlist() {
10264610Smckusick 	struct xtrlist	*malloc(),
10274610Smckusick 			*realloc();
10284610Smckusick 
10294610Smckusick 	if( init ) {
10304610Smckusick 		init = 0;
10314610Smckusick 		xtrlist = malloc( SIZEINC*sizeof(struct xtrlist) );
10324610Smckusick 		xsize = SIZEINC;
10334610Smckusick 	}
10344610Smckusick 	else {
10354610Smckusick 		xtrlist = realloc( xtrlist, (SIZEINC+xsize) *
10364610Smckusick 						sizeof(struct xtrlist) );
10374610Smckusick 		xsize += SIZEINC;
10384610Smckusick 	}
10394610Smckusick 
10404610Smckusick }
10414610Smckusick 
10424610Smckusick /*
10434610Smckusick  *	Check for access into each directory in the pathname of an extracted
10444610Smckusick  *	file and create such a directory if needed in preparation for moving
10454610Smckusick  *	the file to its proper home.
10464610Smckusick  */
10474610Smckusick checkdir(name)
1048*4700Smckusic 	register char *name;
10494610Smckusick {
10504610Smckusick 	register char *cp;
10514610Smckusick 	int i;
10524610Smckusick 	for (cp = name; *cp; cp++) {
10534610Smckusick 		if (*cp == '/') {
10544610Smckusick 			*cp = '\0';
1055*4700Smckusic 			if (xaccess(name, 01) < 0) {
10564610Smckusick 				register int pid, rp;
10574610Smckusick 
1058*4700Smckusic 				xumount();
10594610Smckusick 				if ((pid = fork()) == 0) {
1060*4700Smckusic 					execl("/bin/xmkdir", "xmkdir", name, 0);
1061*4700Smckusic 					execl("/usr/bin/xmkdir", "xmkdir", name, 0);
1062*4700Smckusic 					execl("./xmkdir", "xmkdir", name, 0);
1063*4700Smckusic 					fprintf(stderr, "xrestor: cannot find xmkdir!\n");
10644610Smckusick 					done(0);
10654610Smckusick 				}
10664610Smckusick 				while ((rp = wait(&i)) >= 0 && rp != pid)
10674610Smckusick 					;
1068*4700Smckusic 				xmount(envp);
1069*4700Smckusic 				xchown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
10704610Smckusick 			}
10714610Smckusick 			*cp = '/';
10724610Smckusick 		}
10734610Smckusick 	}
10744610Smckusick }
10754610Smckusick 
10764610Smckusick /*
10774610Smckusick  *	Store a string in core returning a pointer to it.  Allocate space
10784610Smckusick  *	as needed.
10794610Smckusick  */
10804610Smckusick char *
10814610Smckusick ststore( stringp )
1082*4700Smckusic 	char *stringp;
10834610Smckusick {
10844610Smckusick 	static char *spacep;
10854610Smckusick 	static int spaceleft;
10864610Smckusick 	char *rtnp, *savep;
10874610Smckusick 
10884610Smckusick 	rtnp = spacep;
10894610Smckusick 	savep = stringp;
10904610Smckusick 	while( spaceleft-- && (*spacep++ = *stringp++) );
10914610Smckusick 	if( spaceleft >= 0 )
10924610Smckusick 		return( rtnp );
10934610Smckusick 	else {
10944610Smckusick 		spaceleft = 10 * NSIZE;
10954610Smckusick 		spacep = (char *)malloc( spaceleft );
10964610Smckusick 		return( ststore(savep) );
10974610Smckusick 	}
10984610Smckusick }
10994610Smckusick 
11004610Smckusick /*
11014610Smckusick  *	Recursively find names and inumbers of all files in subtree
11024610Smckusick  *	pname and put them in xtrlist[]
11034610Smckusick  */
11044610Smckusick getleaves( pname )
1105*4700Smckusic 	char *pname;
11064610Smckusick {
11074610Smckusick 	int 	n, 		/* loop counter */
11084610Smckusick 		bptsave, 	/* placeholder for pointer into drblock */
11094610Smckusick 		readsize;	/* nbytes read into drblock at cur level
11104610Smckusick 				   of recursion */
11114610Smckusick 	char 	locname[NSIZE];	/* pname + an entry from drblock */
11124610Smckusick 	daddr_t dptsave, 	/* disk loc where cur drblock came from */
11134610Smckusick 		disk_loc;	/* used to see if getent() causes a phys read */
11144610Smckusick 	ino_t 	d;		/* inode no of pname */
11154610Smckusick 
11164610Smckusick 	stcopy( pname, locname, NSIZE );
11174610Smckusick 	if( (d = psearch(locname)) == 0 || BIT( d, dumpmap) == 0 ) {
1118*4700Smckusic 		fprintf(stderr, "%s: not on the tape\n", locname );
11194610Smckusick 		return;
11204610Smckusick 	}
11214610Smckusick 
11224610Smckusick 	for( n=0; n<MAXINO; n++ ) {
11234610Smckusick 		if( inotab[n].t_ino == d ) {
11244610Smckusick 			/*
11254610Smckusick 			 * locname is a directory name
11264610Smckusick 			 */
11274610Smckusick 				/* phys disk read forced so reset readsize */
11284610Smckusick 			mseek( inotab[n].t_seekpt);
11294610Smckusick 			getent( (char *)&dir );
11304610Smckusick 			readsize = nread;
11314610Smckusick 
11324610Smckusick 				/* "/" signals end of directory */
11334610Smckusick 			while( !direq(dir.d_name,"/") ) {
11344610Smckusick 
11354610Smckusick 				if( direq(dir.d_name,".") ) {
11364610Smckusick 					getent( (char *)&dir );
11374610Smckusick 					continue;
11384610Smckusick 				}
11394610Smckusick 
11404610Smckusick 				if( direq(dir.d_name,"..") ) {
11414610Smckusick 					getent( (char *)&dir );
11424610Smckusick 					continue;
11434610Smckusick 				}
11444610Smckusick 
11454610Smckusick 				if( append(dir.d_name,locname,NSIZE) == 0 ) {
1146*4700Smckusic 					fprintf(stderr, "name exceedes %d char\n",NSIZE);
11474610Smckusick 					continue;
11484610Smckusick 				}
11494610Smckusick 
11504610Smckusick 					/* info for rereading drblock later */
11514610Smckusick 				dptsave = lseek( df, 0L, 1 ) - readsize;
11524610Smckusick 				bptsave = bpt;
11534610Smckusick 
11544610Smckusick 				getleaves( locname );
11554610Smckusick 
11564610Smckusick 					/* reread drblock after recursion rtn */
11574610Smckusick 				lseek( df, dptsave, 0 );
11584610Smckusick 				read( df, drblock, BSIZE );
11594610Smckusick 				bpt = bptsave;
11604610Smckusick 
11614610Smckusick 				if( trunc(locname) == 0 ) {
1162*4700Smckusic 					fprintf(stderr,  "Trouble with name trunc\n" );
11634610Smckusick 					abort();
11644610Smckusick 				}
11654610Smckusick 					/* get next entry from drblock; reset
11664610Smckusick 					 * readsize iff physical disk read */
11674610Smckusick 				disk_loc = lseek( df, 0L, 1 );
11684610Smckusick 				getent( (char *)&dir );
11694610Smckusick 				if( lseek(df,0L,1) != disk_loc )
11704610Smckusick 					readsize = nread;
11714610Smckusick 			}
11724610Smckusick 			return;
11734610Smckusick 		}
11744610Smckusick 	}
11754610Smckusick 	/*
11764610Smckusick 	 * locname is name of a simple file
11774610Smckusick 	 */
11784610Smckusick 	xtrlist[i].x_ino = d;
11794610Smckusick 	xtrlist[i].x_flags |= XINUSE;
11804610Smckusick 	xtrlist[i].x_name = (char *)ststore( locname );
11814610Smckusick 	if( ++i >= xsize ) getxtrlist();
1182*4700Smckusic 	fprintf(stderr,  "%s: inode %u\n", locname, d );
11834610Smckusick 
11844610Smckusick }
11854610Smckusick 
11864610Smckusick 
1187