xref: /csrg-svn/sbin/restore/main.c (revision 4843)
14610Smckusick /* Copyright (c) 1981 Regents of the University of California */
24610Smckusick 
3*4843Smckusic char version[] = "@(#)main.c 1.6 11/10/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 SIZEINC 10
204610Smckusick 
214610Smckusick #ifndef STANDALONE
224610Smckusick #include <stdio.h>
234610Smckusick #include <signal.h>
244610Smckusick #endif
254700Smckusic #include "../h/param.h"
264700Smckusic #include "../h/inode.h"
274700Smckusic #include "../h/fs.h"
284700Smckusic #include "../h/buf.h"
294700Smckusic #include "../h/dir.h"
304700Smckusic #include "../h/user.h"
314700Smckusic #include "../h/dumprestor.h"
324610Smckusick 
334610Smckusick #define	MWORD(m,i) (m[(unsigned)(i-1)/MLEN])
344610Smckusick #define	MBIT(i)	(1<<((unsigned)(i-1)%MLEN))
354610Smckusick #define	BIS(i,w)	(MWORD(w,i) |=  MBIT(i))
364610Smckusick #define	BIC(i,w)	(MWORD(w,i) &= ~MBIT(i))
374610Smckusick #define	BIT(i,w)	(MWORD(w,i) & MBIT(i))
384610Smckusick 
394700Smckusic ino_t	ino, maxi;
404610Smckusick 
414776Smckusic int	mt;
424776Smckusic 
43*4843Smckusic int	eflag = 0, hflag = 0, mflag = 0;
444610Smckusick 
454700Smckusic char	mounted = 0;
464700Smckusic dev_t	dev = 0;
474610Smckusick char	tapename[] = "/dev/rmt8";
484610Smckusick char	*magtape = tapename;
494610Smckusick 
504610Smckusick #ifdef STANDALONE
514610Smckusick char	mbuf[50];
524610Smckusick #endif
534610Smckusick 
544610Smckusick daddr_t	seekpt;
554837Smckusic FILE	*df;
564837Smckusic int	ofile;
574610Smckusick char	dirfile[] = "rstXXXXXX";
584610Smckusick 
594837Smckusic #define INOHASH(val) (val % MAXINO)
604837Smckusic struct inotab {
614837Smckusic 	struct inotab *t_next;
624610Smckusick 	ino_t	t_ino;
634610Smckusick 	daddr_t	t_seekpt;
644837Smckusic } *inotab[MAXINO];
654610Smckusick 
664837Smckusic #define XISDIR	1
674610Smckusick #define XTRACTD	2
684610Smckusick #define XINUSE	4
694837Smckusic #define XLINKED	8
704610Smckusick struct xtrlist {
714837Smckusic 	struct xtrlist	*x_next;
724837Smckusic 	struct xtrlist	*x_linkedto;
73*4843Smckusic 	time_t		x_timep[2];
744837Smckusic 	ino_t		x_ino;
754837Smckusic 	char		x_flags;
76*4843Smckusic 	char 		x_name[1];
77*4843Smckusic 	/* actually longer */
784837Smckusic } *xtrlist[MAXINO];
794776Smckusic int xtrcnt = 0;
804610Smckusick 
814610Smckusick #include <sys/mtio.h>
824610Smckusick struct mtop tcom;
834610Smckusick 
844610Smckusick int dumpnum = 1;
854610Smckusick int	volno = 1;
864610Smckusick 
874700Smckusic struct inode *cur_ip;
884610Smckusick 
894610Smckusick short	dumpmap[MSIZ];
904610Smckusick short	clrimap[MSIZ];
914700Smckusic char	clearedbuf[BSIZE];
924610Smckusick 
934776Smckusic int curblk = 0;
944776Smckusic 
954610Smckusick int bct = NTREC+1;
964776Smckusic char tbf[NTREC*TP_BSIZE];
974610Smckusick 
984837Smckusic extern char *ctime();
99*4843Smckusic ino_t search();
1004700Smckusic char **envp;
1014610Smckusick 
1024700Smckusic main(argc, argv, arge)
1034700Smckusic 	int argc;
1044700Smckusic 	char *argv[];
1054700Smckusic 	char **arge;
1064610Smckusick {
1074610Smckusick 	register char *cp;
1084610Smckusick 	char command;
1094700Smckusic 	int (*signal())();
1104610Smckusick 	int done();
1114610Smckusick 
112*4843Smckusic 	if (signal(SIGINT, done) == SIG_IGN)
113*4843Smckusic 		signal(SIGINT, SIG_IGN);
114*4843Smckusic 	if (signal(SIGTERM, done) == SIG_IGN)
115*4843Smckusic 		signal(SIGTERM, SIG_IGN);
1164610Smckusick #ifndef STANDALONE
1174700Smckusic 	envp = arge;
1184700Smckusic 	mktmp(dirfile);
1194610Smckusick 	if (argc < 2) {
1204610Smckusick usage:
1214837Smckusic 		fprintf(stderr, "Usage: restor x[s|m|h|v] file file..., restor r|R filesys, or restor t\n");
1224700Smckusic 		done(1);
1234610Smckusick 	}
1244610Smckusick 	argv++;
1254610Smckusick 	argc -= 2;
1264610Smckusick 	for (cp = *argv++; *cp; cp++) {
1274610Smckusick 		switch (*cp) {
1284610Smckusick 		case '-':
1294610Smckusick 			break;
1304610Smckusick 		case 'f':
1314610Smckusick 			magtape = *argv++;
1324610Smckusick 			argc--;
1334610Smckusick 			break;
1344610Smckusick 		/* s dumpnum (skip to) for multifile dump tapes */
1354610Smckusick 		case 's':
1364610Smckusick 			dumpnum = atoi(*argv++);
1374610Smckusick 			if(dumpnum <= 0) {
1384700Smckusic 				fprintf(stderr, "Dump number must be a positive integer\n");
1394700Smckusic 				done(1);
1404610Smckusick 			}
1414610Smckusick 			argc--;
1424610Smckusick 			break;
1434610Smckusick 		case 'h':
1444610Smckusick 			hflag++;
1454610Smckusick 			break;
1464610Smckusick 		case 'm':
1474610Smckusick 			mflag++;
1484610Smckusick 			break;
1494610Smckusick 		case 'r':
1504610Smckusick 		case 'R':
1514610Smckusick 		case 't':
1524610Smckusick 		case 'x':
1534610Smckusick 			command = *cp;
1544610Smckusick 			break;
1554610Smckusick 		default:
1564700Smckusic 			fprintf(stderr, "Bad key character %c\n", *cp);
1574610Smckusick 			goto usage;
1584610Smckusick 		}
1594610Smckusick 	}
1604610Smckusick 	if (command == 'x') {
1614837Smckusic 		df = fopen(dirfile, "w");
1624837Smckusic 		if (df == 0) {
1634700Smckusic 			fprintf(stderr, "restor: %s - cannot create directory temporary\n", dirfile);
1644700Smckusic 			done(1);
1654610Smckusick 		}
1664700Smckusic 		xmount(envp);
1674700Smckusic 		mounted++;
1684610Smckusick 	}
1694610Smckusick 	doit(command, argc, argv);
1704700Smckusic 	done(0);
1714610Smckusick #else
1724610Smckusick 	magtape = "tape";
1734610Smckusick 	doit('r', 1, 0);
1744610Smckusick #endif
1754610Smckusick }
1764610Smckusick 
1774610Smckusick doit(command, argc, argv)
1784700Smckusic 	char	command;
1794700Smckusic 	int	argc;
1804700Smckusic 	char	*argv[];
1814610Smckusick {
1824610Smckusick #ifndef STANDALONE
1834610Smckusick 	if ((mt = open(magtape, 0)) < 0) {
1844700Smckusic 		fprintf(stderr, "%s: cannot open tape\n", magtape);
1854700Smckusic 		done(1);
1864610Smckusick 	}
187*4843Smckusic 	if (dumpnum != 1) {
1884610Smckusick 		tcom.mt_op = MTFSF;
1894610Smckusick 		tcom.mt_count = dumpnum -1;
190*4843Smckusic 		if (ioctl(mt,MTIOCTOP,&tcom) < 0)
1914610Smckusick 			perror("ioctl MTFSF");
1924610Smckusick 	}
1934610Smckusick #else
1944610Smckusick 	do {
1954700Smckusic 		fprintf(stderr, "Tape? ");
1964610Smckusick 		gets(mbuf);
1974610Smckusick 		mt = open(mbuf, 0);
1984610Smckusick 	} while (mt == -1);
1994610Smckusick 	magtape = mbuf;
2004700Smckusic 	clearbuf(clearedbuf);
2014610Smckusick #endif
2024610Smckusick 	switch(command) {
2034610Smckusick #ifndef STANDALONE
2044610Smckusick 	case 't':
2054610Smckusick 		if (readhdr(&spcl) == 0) {
2064700Smckusic 			fprintf(stderr, "Tape is not a dump tape\n");
2074700Smckusic 			done(1);
2084610Smckusick 		}
209*4843Smckusic 		fprintf(stdout, "Dump   date: %s", ctime(&spcl.c_date));
210*4843Smckusic 		fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate));
2114610Smckusick 		return;
2124610Smckusick 	case 'x':
2134837Smckusic 		extractfiles(argc, argv);
2144837Smckusic 		return;
2154837Smckusic 	case 'r':
2164837Smckusic 	case 'R':
2174837Smckusic 		restorfiles(command, argv);
2184837Smckusic 		return;
2194837Smckusic 	}
2204837Smckusic #endif
2214837Smckusic }
2224837Smckusic 
2234837Smckusic #ifndef STANDALONE
2244837Smckusic extractfiles(argc, argv)
2254837Smckusic 	int argc;
2264837Smckusic 	char **argv;
2274837Smckusic {
228*4843Smckusic 	char	*ststore();
2294837Smckusic 	register struct xtrlist *xp;
2304837Smckusic 	struct xtrlist **xpp;
2314837Smckusic 	ino_t	d;
2324837Smckusic 	int	xtrfile(), skip(), null();
233*4843Smckusic 	int	mode;
234*4843Smckusic 	char	name[BUFSIZ + 1];
2354837Smckusic 
2364837Smckusic 	if (readhdr(&spcl) == 0) {
2374837Smckusic 		fprintf(stderr, "Tape is not a dump tape\n");
2384837Smckusic 		done(1);
2394837Smckusic 	}
2404837Smckusic 	if (checkvol(&spcl, 1) == 0) {
2414837Smckusic 		fprintf(stderr, "Tape is not volume 1 of the dump\n");
2424837Smckusic 	}
2434837Smckusic 	pass1();  /* This sets the various maps on the way by */
244*4843Smckusic 	while (argc--) {
2454837Smckusic 		if ((d = psearch(*argv)) == 0 || BIT(d,dumpmap) == 0) {
246*4843Smckusic 			fprintf(stdout, "%s: not on tape\n", *argv++);
2474837Smckusic 			continue;
2484610Smckusick 		}
249*4843Smckusic 		if (mflag)
250*4843Smckusic 			checkdir(*argv);
2514837Smckusic 		if(hflag)
2524837Smckusic 			getleaves(d, *argv++);
253*4843Smckusic 		else
254*4843Smckusic 			allocxtr(d, *argv++, XINUSE);
2554837Smckusic 	}
2564610Smckusick 
2574610Smckusick 
2584837Smckusic 	if(dumpnum > 1)
2594837Smckusic 		tcom.mt_op = MTBSF;
2604837Smckusic 	else	tcom.mt_op = MTREW;
2614837Smckusic 	tcom.mt_count = 1;
2624610Smckusick 
2634610Smckusick newvol:
2644837Smckusic 	flsht();
2654837Smckusic 	ioctl(mt,MTIOCTOP,&tcom);
266*4843Smckusic 	if (dumpnum > 1) {
2674837Smckusic 		tcom.mt_op = MTFSF;
2684837Smckusic 		tcom.mt_count = 1;
2694610Smckusick 		ioctl(mt,MTIOCTOP,&tcom);
2704837Smckusic 	}
2714837Smckusic 	lseek(mt, (long)0, 0);
2724610Smckusick 
2734610Smckusick 
2744610Smckusick getvol:
2754837Smckusic 	fprintf(stderr, "Mount desired tape volume: Specify volume #: ");
2764837Smckusic 	if (gets(tbf) == NULL)
2774837Smckusic 		return;
2784837Smckusic 	volno = atoi(tbf);
2794837Smckusic 	if (volno <= 0) {
2804837Smckusic 		fprintf(stderr, "Volume numbers are positive numerics\n");
2814837Smckusic 		goto getvol;
2824837Smckusic 	}
2834837Smckusic 	if (readhdr(&spcl) == 0) {
2844837Smckusic 		fprintf(stderr, "tape is not dump tape\n");
2854837Smckusic 		goto newvol;
2864837Smckusic 	}
2874837Smckusic 	if (checkvol(&spcl, volno) == 0) {
2884837Smckusic 		fprintf(stderr, "Wrong volume (%d)\n", spcl.c_volume);
2894837Smckusic 		goto newvol;
2904837Smckusic 	}
2914610Smckusick rbits:
2924837Smckusic 	while (gethead(&spcl) == 0)
2934837Smckusic 		;
2944837Smckusic 	if (checktype(&spcl, TS_INODE) == 1) {
2954837Smckusic 		fprintf(stderr, "Can't find inode mask!\n");
2964837Smckusic 		goto newvol;
2974837Smckusic 	}
2984837Smckusic 	if (checktype(&spcl, TS_BITS) == 0)
2994837Smckusic 		goto rbits;
3004837Smckusic 	readbits(dumpmap);
3014837Smckusic 	while (xtrcnt > 0) {
3024837Smckusic again:
3034837Smckusic 		if (ishead(&spcl) == 0)
3044837Smckusic 			while(gethead(&spcl) == 0)
3054837Smckusic 				;
3064837Smckusic 		if (checktype(&spcl, TS_END) == 1) {
3074837Smckusic 			fprintf(stderr, "end of tape\n");
3084837Smckusic 			break;
3094610Smckusick 		}
3104837Smckusic 		if (checktype(&spcl, TS_INODE) == 0) {
3114837Smckusic 			gethead(&spcl);
3124837Smckusic 			goto again;
3134610Smckusick 		}
3144837Smckusic 		d = spcl.c_inumber;
3154837Smckusic 		for (xp = xtrlist[INOHASH(d)]; xp; xp = xp->x_next) {
3164837Smckusic 			if (d != xp->x_ino)
3174837Smckusic 				continue;
3184837Smckusic 			if (xp->x_flags & XLINKED)
3194837Smckusic 				continue;
3204837Smckusic 			xp->x_timep[0] = spcl.c_dinode.di_atime;
3214837Smckusic 			xp->x_timep[1] = spcl.c_dinode.di_mtime;
3224837Smckusic 			mode = spcl.c_dinode.di_mode;
3234837Smckusic 			if (mflag)
324*4843Smckusic 				strcpy(name, xp->x_name);
3254837Smckusic 			else
3264837Smckusic 				sprintf(name, "%u", xp->x_ino);
3274837Smckusic 			switch (mode & IFMT) {
3284837Smckusic 			default:
329*4843Smckusic 				fprintf(stderr, "%s: unknown file type\n", name);
3304837Smckusic 				xp->x_flags |= XTRACTD;
3314837Smckusic 				xtrcnt--;
3324837Smckusic 				goto skipfile;
3334837Smckusic 			case IFCHR:
3344837Smckusic 			case IFBLK:
335*4843Smckusic 				fprintf(stdout, "extract special file %s\n", name);
3364837Smckusic 				if (xmknod(name, mode, spcl.c_dinode.di_rdev)) {
3374837Smckusic 					fprintf(stderr, "%s: cannot create special file\n", name);
3384837Smckusic 					xp->x_flags |= XTRACTD;
3394837Smckusic 					xtrcnt--;
3404837Smckusic 					goto skipfile;
3414776Smckusic 				}
3424837Smckusic 				getfile(null, null, spcl.c_dinode.di_size);
3434837Smckusic 				break;
3444837Smckusic 			case IFDIR:
3454837Smckusic 				if (mflag) {
346*4843Smckusic 					fprintf(stdout, "extract directory %s\n", name);
3474837Smckusic 					strncat(name, "/.", BUFSIZ);
348*4843Smckusic 					checkdir(name);
349*4843Smckusic 					xchown(xp->x_name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
3504837Smckusic 					getfile(null, null, spcl.c_dinode.di_size);
3514837Smckusic 					break;
3524610Smckusick 				}
3534837Smckusic 				/* else fall through */
3544837Smckusic 			case IFREG:
355*4843Smckusic 				fprintf(stdout, "extract file %s\n", name);
3564837Smckusic 				if ((ofile = xcreat(name, 0666)) < 0) {
3574837Smckusic 					fprintf(stderr, "%s: cannot create file\n", name);
3584837Smckusic 					xp->x_flags |= XTRACTD;
3594837Smckusic 					xtrcnt--;
3604837Smckusic 					goto skipfile;
3614837Smckusic 				}
3624837Smckusic 				xchown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
3634837Smckusic 				getfile(xtrfile, skip, spcl.c_dinode.di_size);
3644837Smckusic 				xclose(ofile);
3654837Smckusic 				break;
3664610Smckusick 			}
3674837Smckusic 			xchmod(name, mode);
3684837Smckusic 			xutime(name, xp->x_timep);
3694837Smckusic 			xp->x_flags |= XTRACTD;
3704837Smckusic 			xtrcnt--;
3714837Smckusic 			goto finished;
3724837Smckusic 		}
3734837Smckusic skipfile:
3744837Smckusic 		getfile(null, null, spcl.c_dinode.di_size);
3754700Smckusic finished:
3764837Smckusic 		;
3774837Smckusic 	}
3784837Smckusic 	if (xtrcnt == 0 && !mflag)
3794837Smckusic 		return;
3804837Smckusic 	for (xpp = xtrlist; xpp < &xtrlist[MAXINO]; xpp++) {
3814837Smckusic 		for (xp = *xpp; xp; xp = xp->x_next) {
3824837Smckusic 			if (mflag && (xp->x_flags & XISDIR))
3834837Smckusic 				xutime(xp->x_name, xp->x_timep);
3844837Smckusic 			if (xp->x_flags & XTRACTD)
3854837Smckusic 				continue;
3864837Smckusic 			if ((xp->x_flags & XLINKED) == 0) {
3874837Smckusic 				fprintf(stderr, "cannot find file %s\n",
3884837Smckusic 					xp->x_name);
3894837Smckusic 				continue;
3904837Smckusic 			}
391*4843Smckusic 			if (!mflag)
392*4843Smckusic 				continue;
393*4843Smckusic 			fprintf(stdout, "link %s to %s\n",
394*4843Smckusic 				xp->x_linkedto->x_name, xp->x_name);
395*4843Smckusic 			if (xlink(xp->x_linkedto->x_name, xp->x_name) < 0)
396*4843Smckusic 				fprintf(stderr, "link %s to %s failed\n",
3974837Smckusic 					xp->x_linkedto->x_name, xp->x_name);
3984610Smckusick 		}
3994837Smckusic 	}
4004837Smckusic }
4014610Smckusick #endif
4024837Smckusic 
4034837Smckusic restorfiles(command, argv)
4044837Smckusic 	char command;
4054837Smckusic 	char **argv;
4064837Smckusic {
4074837Smckusic 	int	rstrfile(), rstrskip();
4084837Smckusic 	register struct dinode *dp;
4094837Smckusic 	register struct inode *ip;
4104837Smckusic 	struct fs *fs;
4114837Smckusic 	int mode;
4124837Smckusic 	char mount[BUFSIZ + 1];
4134837Smckusic 	char *ptr[2];
4144837Smckusic 
4154610Smckusick #ifndef STANDALONE
4164837Smckusic 	mount[0] = '\0';
4174837Smckusic 	strcpy(mount, "MOUNT=");
4184837Smckusic 	strncat(mount, *argv, BUFSIZ);
4194837Smckusic 	ptr[0] = mount;
4204837Smckusic 	ptr[1] = 0;
4214837Smckusic 	xmount(ptr);
4224837Smckusic 	iput(u.u_cdir); /* release root inode */
4234837Smckusic 	iput(u.u_rdir); /* release root inode */
4244837Smckusic 	mounted++;
4254610Smckusick #else
4264837Smckusic 	do {
4274837Smckusic 		fprintf(stderr, "Disk? ");
4284837Smckusic 		gets(mount);
4294837Smckusic 		fi = open(mount, 2);
4304837Smckusic 	} while (fi == -1);
4314610Smckusick #endif
4324610Smckusick #ifndef STANDALONE
4334837Smckusic 	if (command == 'R') {
4344837Smckusic 		fprintf(stderr, "Enter starting volume number: ");
4354837Smckusic 		if (gets(tbf) == EOF) {
4364837Smckusic 			volno = 1;
4374837Smckusic 			fprintf(stderr, "\n");
4384610Smckusick 		}
4394610Smckusick 		else
4404837Smckusic 			volno = atoi(tbf);
4414837Smckusic 	}
4424837Smckusic 	else
4434610Smckusick #endif
4444837Smckusic 		volno = 1;
4454837Smckusic 	fprintf(stderr, "Last chance before scribbling on %s. ",
4464610Smckusick #ifdef STANDALONE
4474837Smckusic 							"disk");
4484610Smckusick #else
4494837Smckusic 							*argv);
4504610Smckusick #endif
4514837Smckusic 	while (getchar() != '\n');
4524837Smckusic 	fs = getfs(dev);
4534837Smckusic 	maxi = fs->fs_ipg * fs->fs_ncg;
4544837Smckusic 	if (readhdr(&spcl) == 0) {
4554837Smckusic 		fprintf(stderr, "Missing volume record\n");
4564837Smckusic 		done(1);
4574837Smckusic 	}
4584837Smckusic 	if (checkvol(&spcl, volno) == 0) {
4594837Smckusic 		fprintf(stderr, "Tape is not volume %d\n", volno);
4604837Smckusic 		done(1);
4614837Smckusic 	}
4624837Smckusic 	gethead(&spcl);
4634837Smckusic 	for (;;) {
4644837Smckusic ragain:
4654837Smckusic 		if (ishead(&spcl) == 0) {
4664837Smckusic 			fprintf(stderr, "Missing header block\n");
4674837Smckusic 			while (gethead(&spcl) == 0)
4684837Smckusic 				;
4694837Smckusic 			eflag++;
4704610Smckusick 		}
4714837Smckusic 		if (checktype(&spcl, TS_END) == 1) {
4724837Smckusic 			fprintf(stderr, "End of tape\n");
4734837Smckusic 			close(mt);
4744837Smckusic 			return;
4754610Smckusick 		}
4764837Smckusic 		if (checktype(&spcl, TS_CLRI) == 1) {
4774837Smckusic 			readbits(clrimap);
4784837Smckusic 			for (ino = 1; ino <= maxi; ino++)
4794837Smckusic 				if (BIT(ino, clrimap) == 0) {
4804837Smckusic 					if (!iexist(dev, ino))
4814837Smckusic 						continue;
4824837Smckusic 					ip = iget(dev, ino);
4834837Smckusic 					if (ip == NULL) {
4844837Smckusic 						fprintf(stderr, "can't find inode %u\n", ino);
4854837Smckusic 						done(1);
4864610Smckusick 					}
4874837Smckusic 					ip->i_nlink = 0;
4884837Smckusic 					ip->i_flag |= ICHG;
4894837Smckusic 					iput(ip);
4904700Smckusic 				}
4914837Smckusic 			goto ragain;
4924837Smckusic 		}
4934837Smckusic 		if (checktype(&spcl, TS_BITS) == 1) {
4944837Smckusic 			readbits(dumpmap);
4954837Smckusic 			goto ragain;
4964837Smckusic 		}
4974837Smckusic 		if (checktype(&spcl, TS_INODE) == 0) {
4984837Smckusic 			fprintf(stderr, "Unknown header type\n");
4994837Smckusic 			eflag++;
5004837Smckusic 			gethead(&spcl);
5014837Smckusic 			goto ragain;
5024837Smckusic 		}
5034837Smckusic 		ino = spcl.c_inumber;
5044837Smckusic 		if (eflag)
5054837Smckusic 			fprintf(stderr, "Resynced at inode %u\n", ino);
5064837Smckusic 		eflag = 0;
5074837Smckusic 		if (ino > maxi) {
5084837Smckusic 			fprintf(stderr, "%u: ilist too small\n", ino);
5094837Smckusic 			gethead(&spcl);
5104837Smckusic 			goto ragain;
5114837Smckusic 		}
5124837Smckusic 		if (iexist(dev, ino)) {
5134837Smckusic 			ip = iget(dev, ino);
5144837Smckusic 			if (ip == NULL) {
5154837Smckusic 				fprintf(stderr, "can't find inode %u\n",
5164837Smckusic 					ino);
5174700Smckusic 				done(1);
5184700Smckusic 			}
5194837Smckusic 			ip->i_nlink = 0;
5204700Smckusic 			ip->i_flag |= ICHG;
5214700Smckusic 			iput(ip);
5224610Smckusick 		}
5234837Smckusic 		dp = &spcl.c_dinode;
5244837Smckusic 		ip = ialloc(dev, ino, dp->di_mode);
5254837Smckusic 		if (ip == NULL || ip->i_number != ino) {
5264837Smckusic 			fprintf(stderr, "can't create inode %u\n", ino);
5274837Smckusic 			done(1);
5284837Smckusic 		}
5294837Smckusic 		ip->i_mode = mode = dp->di_mode;
5304837Smckusic 		ip->i_nlink = dp->di_nlink;
5314837Smckusic 		ip->i_uid = dp->di_uid;
5324837Smckusic 		ip->i_gid = dp->di_gid;
5334837Smckusic 		ip->i_atime = dp->di_atime;
5344837Smckusic 		ip->i_mtime = dp->di_mtime;
5354837Smckusic 		ip->i_ctime = dp->di_ctime;
5364837Smckusic 		if ((ip->i_mode & IFMT) == IFCHR ||
5374837Smckusic 		    (ip->i_mode & IFMT) == IFBLK)
5384837Smckusic 			ip->i_rdev = dp->di_rdev;
5394837Smckusic 		ip->i_size = 0;
5404837Smckusic 		cur_ip = ip;
5414837Smckusic 		u.u_offset = 0;
5424837Smckusic 		u.u_segflg = 1;
5434837Smckusic 		getfile(rstrfile, rstrskip, dp->di_size);
5444837Smckusic 		ip->i_mode = mode;
5454837Smckusic 		ip->i_flag &= ~(IUPD|IACC);
5464837Smckusic 		ip->i_flag |= ICHG;
5474837Smckusic 		iput(ip);
5484610Smckusick 	}
5494610Smckusick }
5504610Smckusick 
5514610Smckusick /*
5524610Smckusick  * Read the tape, bulding up a directory structure for extraction
5534610Smckusick  * by name
5544610Smckusick  */
5554610Smckusick #ifndef STANDALONE
5564610Smckusick pass1()
5574610Smckusick {
5584776Smckusic 	register int i;
5594837Smckusic 	register struct dinode *ip;
5604837Smckusic 	struct direct nulldir;
5614610Smckusick 	int	putdir(), null();
5624610Smckusick 
5634837Smckusic 	nulldir.d_ino = 0;
5644837Smckusic 	strncpy(nulldir.d_name, "/", DIRSIZ);
5654610Smckusick 	while (gethead(&spcl) == 0) {
5664700Smckusic 		fprintf(stderr, "Can't find directory header!\n");
5674610Smckusick 	}
5684610Smckusick 	for (;;) {
5694610Smckusick 		if (checktype(&spcl, TS_BITS) == 1) {
5704610Smckusick 			readbits(dumpmap);
5714610Smckusick 			continue;
5724610Smckusick 		}
5734610Smckusick 		if (checktype(&spcl, TS_CLRI) == 1) {
5744610Smckusick 			readbits(clrimap);
5754610Smckusick 			continue;
5764610Smckusick 		}
5774610Smckusick 		if (checktype(&spcl, TS_INODE) == 0) {
5784610Smckusick finish:
5794610Smckusick /*
5804610Smckusick 			close(mt);
5814610Smckusick */
5824837Smckusic 			freopen(dirfile, "r", df);
5834610Smckusick 			return;
5844610Smckusick 		}
5854610Smckusick 		ip = &spcl.c_dinode;
5864610Smckusick 		i = ip->di_mode & IFMT;
5874610Smckusick 		if (i != IFDIR) {
5884610Smckusick 			goto finish;
5894610Smckusick 		}
590*4843Smckusic 		allocinotab(spcl.c_inumber, seekpt);
5914700Smckusic 		getfile(putdir, null, spcl.c_dinode.di_size);
5924837Smckusic 		putent(&nulldir);
5934610Smckusick 	}
5944610Smckusick }
5954610Smckusick #endif
5964610Smckusick 
5974610Smckusick /*
598*4843Smckusic  * Put the directory entries in the directory file
599*4843Smckusic  */
600*4843Smckusic #ifndef STANDALONE
601*4843Smckusic putdir(buf, size)
602*4843Smckusic 	char *buf;
603*4843Smckusic 	int size;
604*4843Smckusic {
605*4843Smckusic 	register struct direct *dp;
606*4843Smckusic 	register int i;
607*4843Smckusic 
608*4843Smckusic 	for (dp = (struct direct *)buf, i = 0; i < size; dp++, i += sizeof(*dp))
609*4843Smckusic 		if (dp->d_ino != 0)
610*4843Smckusic 			putent(dp);
611*4843Smckusic }
612*4843Smckusic 
613*4843Smckusic putent(dp)
614*4843Smckusic 	struct direct *dp;
615*4843Smckusic {
616*4843Smckusic 	fwrite(dp, 1, sizeof(struct direct), df);
617*4843Smckusic 	seekpt = ftell(df);
618*4843Smckusic }
619*4843Smckusic 
620*4843Smckusic /*
621*4843Smckusic  *	Recursively find names and inumbers of all files in subtree
622*4843Smckusic  *	pname and put them in xtrlist[]
623*4843Smckusic  */
624*4843Smckusic getleaves(ino, pname)
625*4843Smckusic 	ino_t ino;
626*4843Smckusic 	char *pname;
627*4843Smckusic {
628*4843Smckusic 	register struct inotab *itp;
629*4843Smckusic 	int namelen;
630*4843Smckusic 	daddr_t	bpt;
631*4843Smckusic 	struct direct dir;
632*4843Smckusic 	char 	locname[BUFSIZ + 1];
633*4843Smckusic 
634*4843Smckusic 	if (BIT(ino, dumpmap) == 0) {
635*4843Smckusic 		fprintf(stdout, "%s: not on the tape\n", pname);
636*4843Smckusic 		return;
637*4843Smckusic 	}
638*4843Smckusic 	for (itp = inotab[INOHASH(ino)]; itp; itp = itp->t_next) {
639*4843Smckusic 		if (itp->t_ino != ino)
640*4843Smckusic 			continue;
641*4843Smckusic 		/*
642*4843Smckusic 		 * pname is a directory name
643*4843Smckusic 		 */
644*4843Smckusic 		allocxtr(ino, pname, XISDIR);
645*4843Smckusic 		/*
646*4843Smckusic 		 * begin search through the directory
647*4843Smckusic 		 * skipping over "." and ".."
648*4843Smckusic 		 */
649*4843Smckusic 		strncpy(locname, pname, BUFSIZ);
650*4843Smckusic 		strncat(locname, "/", BUFSIZ);
651*4843Smckusic 		namelen = strlen(locname);
652*4843Smckusic 		fseek(df, itp->t_seekpt, 0);
653*4843Smckusic 		fread(&dir, 1, sizeof(struct direct), df);
654*4843Smckusic 		fread(&dir, 1, sizeof(struct direct), df);
655*4843Smckusic 		fread(&dir, 1, sizeof(struct direct), df);
656*4843Smckusic 		bpt = ftell(df);
657*4843Smckusic 		/*
658*4843Smckusic 		 * "/" signals end of directory
659*4843Smckusic 		 */
660*4843Smckusic 		while (strncmp(dir.d_name, "/", DIRSIZ)) {
661*4843Smckusic 			locname[namelen] = '\0';
662*4843Smckusic 			strncat(locname, dir.d_name, DIRSIZ);
663*4843Smckusic 			if (strlen(locname) >= BUFSIZ) {
664*4843Smckusic 				fprintf(stderr, "%s: name exceedes %d char\n",
665*4843Smckusic 					locname, BUFSIZ);
666*4843Smckusic 				continue;
667*4843Smckusic 			}
668*4843Smckusic 			getleaves(dir.d_ino, locname);
669*4843Smckusic 			fseek(df, bpt, 0);
670*4843Smckusic 			fread(&dir, 1, sizeof(struct direct), df);
671*4843Smckusic 			bpt = ftell(df);
672*4843Smckusic 		}
673*4843Smckusic 		return;
674*4843Smckusic 	}
675*4843Smckusic 	/*
676*4843Smckusic 	 * locname is name of a simple file
677*4843Smckusic 	 */
678*4843Smckusic 	allocxtr(ino, pname, XINUSE);
679*4843Smckusic }
680*4843Smckusic 
681*4843Smckusic /*
682*4843Smckusic  * Search the directory tree rooted at inode ROOTINO
683*4843Smckusic  * for the path pointed at by n
684*4843Smckusic  */
685*4843Smckusic psearch(n)
686*4843Smckusic 	char	*n;
687*4843Smckusic {
688*4843Smckusic 	register char *cp, *cp1;
689*4843Smckusic 	char c;
690*4843Smckusic 
691*4843Smckusic 	ino = ROOTINO;
692*4843Smckusic 	if (*(cp = n) == '/')
693*4843Smckusic 		cp++;
694*4843Smckusic next:
695*4843Smckusic 	cp1 = cp + 1;
696*4843Smckusic 	while (*cp1 != '/' && *cp1)
697*4843Smckusic 		cp1++;
698*4843Smckusic 	c = *cp1;
699*4843Smckusic 	*cp1 = 0;
700*4843Smckusic 	ino = search(ino, cp);
701*4843Smckusic 	if (ino == 0) {
702*4843Smckusic 		*cp1 = c;
703*4843Smckusic 		return(0);
704*4843Smckusic 	}
705*4843Smckusic 	*cp1 = c;
706*4843Smckusic 	if (c == '/') {
707*4843Smckusic 		cp = cp1+1;
708*4843Smckusic 		goto next;
709*4843Smckusic 	}
710*4843Smckusic 	return(ino);
711*4843Smckusic }
712*4843Smckusic 
713*4843Smckusic /*
714*4843Smckusic  * search the directory inode ino
715*4843Smckusic  * looking for entry cp
716*4843Smckusic  */
717*4843Smckusic ino_t
718*4843Smckusic search(inum, cp)
719*4843Smckusic 	ino_t	inum;
720*4843Smckusic 	char	*cp;
721*4843Smckusic {
722*4843Smckusic 	struct direct dir;
723*4843Smckusic 	register struct inotab *itp;
724*4843Smckusic 
725*4843Smckusic 	for (itp = inotab[INOHASH(inum)]; itp; itp = itp->t_next)
726*4843Smckusic 		if (itp->t_ino == inum)
727*4843Smckusic 			goto found;
728*4843Smckusic 	return(0);
729*4843Smckusic found:
730*4843Smckusic 	fseek(df, itp->t_seekpt, 0);
731*4843Smckusic 	do {
732*4843Smckusic 		fread(&dir, 1, sizeof(struct direct), df);
733*4843Smckusic 		if (!strncmp(dir.d_name, "/", DIRSIZ))
734*4843Smckusic 			return(0);
735*4843Smckusic 	} while (strncmp(dir.d_name, cp, DIRSIZ));
736*4843Smckusic 	return(dir.d_ino);
737*4843Smckusic }
738*4843Smckusic #endif
739*4843Smckusic 
740*4843Smckusic /*
7414610Smckusick  * Do the file extraction, calling the supplied functions
7424610Smckusick  * with the blocks
7434610Smckusick  */
7444700Smckusic getfile(f1, f2, size)
7454700Smckusic 	int	(*f2)(), (*f1)();
7464700Smckusic 	long	size;
7474610Smckusick {
7484776Smckusic 	register int i;
7494776Smckusic 	char buf[BLKING * FRAG][TP_BSIZE];
7504837Smckusic 	union u_spcl addrblk;
7514837Smckusic #	define addrblock addrblk.s_spcl
7524610Smckusick 
7534837Smckusic 	addrblock = spcl;
7544610Smckusick 	for (;;) {
7554837Smckusic 		for (i = 0; i < addrblock.c_count; i++) {
7564837Smckusic 			if (addrblock.c_addr[i]) {
7574776Smckusic 				readtape(&buf[curblk++][0]);
7584776Smckusic 				if (curblk == BLKING * FRAG) {
7594776Smckusic 					(*f1)(buf, size > TP_BSIZE ?
7604776Smckusic 					     (long) (BLKING * FRAG * TP_BSIZE) :
7614776Smckusic 					     (curblk - 1) * TP_BSIZE + size);
7624776Smckusic 					curblk = 0;
7634776Smckusic 				}
7644610Smckusick 			}
7654610Smckusick 			else {
7664776Smckusic 				if (curblk > 0) {
7674776Smckusic 					(*f1)(buf, size > TP_BSIZE ?
7684776Smckusic 					     (long) (curblk * TP_BSIZE) :
7694776Smckusic 					     (curblk - 1) * TP_BSIZE + size);
7704776Smckusic 					curblk = 0;
7714776Smckusic 				}
7724776Smckusic 				(*f2)(clearedbuf, size > TP_BSIZE ? (long) TP_BSIZE : size);
7734610Smckusick 			}
7744776Smckusic 			if ((size -= TP_BSIZE) <= 0) {
7754610Smckusick eloop:
7764610Smckusick 				while (gethead(&spcl) == 0)
7774610Smckusick 					;
7784610Smckusick 				if (checktype(&spcl, TS_ADDR) == 1)
7794610Smckusick 					goto eloop;
7804776Smckusic 				goto out;
7814610Smckusick 			}
7824610Smckusick 		}
7834837Smckusic 		if (gethead(&addrblock) == 0) {
7844776Smckusic 			fprintf(stderr, "Missing address (header) block, ino%u\n", ino);
7854700Smckusic 			goto eloop;
7864700Smckusic 		}
7874837Smckusic 		if (checktype(&addrblock, TS_ADDR) == 0) {
7884837Smckusic 			spcl = addrblock;
7894776Smckusic 			goto out;
7904700Smckusic 		}
7914610Smckusick 	}
7924776Smckusic out:
7934776Smckusic 	if (curblk > 0) {
7944776Smckusic 		(*f1)(buf, (curblk * TP_BSIZE) + size);
7954776Smckusic 		curblk = 0;
7964776Smckusic 	}
7974610Smckusick }
7984610Smckusick 
7994610Smckusick /*
800*4843Smckusic  * The next routines are called during file extraction to
801*4843Smckusic  * put the data into the right form and place.
802*4843Smckusic  */
803*4843Smckusic #ifndef STANDALONE
804*4843Smckusic xtrfile(buf, size)
805*4843Smckusic 	char	*buf;
806*4843Smckusic 	long	size;
807*4843Smckusic {
808*4843Smckusic 	if (xwrite(ofile, buf, (int) size) == -1) {
809*4843Smckusic 		perror("extract write:");
810*4843Smckusic 		done(1);
811*4843Smckusic 	}
812*4843Smckusic }
813*4843Smckusic 
814*4843Smckusic skip(buf, size)
815*4843Smckusic 	char *buf;
816*4843Smckusic 	long size;
817*4843Smckusic {
818*4843Smckusic 	if (xseek(ofile, size, 1) == -1) {
819*4843Smckusic 		perror("extract seek:");
820*4843Smckusic 		done(1);
821*4843Smckusic 	}
822*4843Smckusic }
823*4843Smckusic #endif
824*4843Smckusic 
825*4843Smckusic 
826*4843Smckusic rstrfile(buf, size)
827*4843Smckusic 	char *buf;
828*4843Smckusic 	long size;
829*4843Smckusic {
830*4843Smckusic 	u.u_base = buf;
831*4843Smckusic 	u.u_count = size;
832*4843Smckusic 	writei(cur_ip);
833*4843Smckusic 	if (u.u_error) {
834*4843Smckusic 		perror("restor write:");
835*4843Smckusic 		done(1);
836*4843Smckusic 	}
837*4843Smckusic }
838*4843Smckusic 
839*4843Smckusic rstrskip(buf, size)
840*4843Smckusic 	char *buf;
841*4843Smckusic 	long size;
842*4843Smckusic {
843*4843Smckusic 	u.u_offset += size;
844*4843Smckusic }
845*4843Smckusic 
846*4843Smckusic null() {;}
847*4843Smckusic 
848*4843Smckusic /*
8494776Smckusic  * Do the tape i/o, dealing with volume changes
8504610Smckusick  * etc..
8514610Smckusick  */
8524610Smckusick readtape(b)
8534700Smckusic 	char *b;
8544610Smckusick {
8554776Smckusic 	register int i;
8564837Smckusic 	struct s_spcl tmpbuf;
8574610Smckusick 
8584610Smckusick 	if (bct >= NTREC) {
8594610Smckusick 		for (i = 0; i < NTREC; i++)
8604776Smckusic 			((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0;
8614610Smckusick 		bct = 0;
8624776Smckusic 		if ((i = read(mt, tbf, NTREC*TP_BSIZE)) < 0) {
8634700Smckusic 			perror("Tape read error");
8644610Smckusick 			eflag++;
8654700Smckusic 			done(1);
8664610Smckusick 		}
8674610Smckusick 		if (i == 0) {
8684610Smckusick 			bct = NTREC + 1;
8694610Smckusick 			volno++;
8704610Smckusick loop:
8714610Smckusick 			flsht();
8724610Smckusick 			close(mt);
8734700Smckusic 			fprintf(stderr, "Mount volume %d\n", volno);
8744610Smckusick 			while (getchar() != '\n')
8754610Smckusick 				;
8764610Smckusick 			if ((mt = open(magtape, 0)) == -1) {
8774700Smckusic 				fprintf(stderr, "Cannot open tape!\n");
8784610Smckusick 				goto loop;
8794610Smckusick 			}
8804610Smckusick 			if (readhdr(&tmpbuf) == 0) {
8814700Smckusic 				fprintf(stderr, "Not a dump tape.Try again\n");
8824610Smckusick 				goto loop;
8834610Smckusick 			}
8844610Smckusick 			if (checkvol(&tmpbuf, volno) == 0) {
8854700Smckusic 				fprintf(stderr, "Wrong tape. Try again\n");
8864610Smckusick 				goto loop;
8874610Smckusick 			}
8884610Smckusick 			readtape(b);
8894610Smckusick 			return;
8904610Smckusick 		}
8914610Smckusick 	}
8924776Smckusic 	copy(&tbf[(bct++*TP_BSIZE)], b, TP_BSIZE);
8934610Smckusick }
8944610Smckusick 
8954610Smckusick flsht()
8964610Smckusick {
8974610Smckusick 	bct = NTREC+1;
8984610Smckusick }
8994610Smckusick 
9004610Smckusick copy(f, t, s)
9014700Smckusic 	register char *f, *t;
9024610Smckusick {
9034776Smckusic 	register int i;
9044610Smckusick 
9054610Smckusick 	i = s;
9064610Smckusick 	do
9074610Smckusick 		*t++ = *f++;
9084610Smckusick 	while (--i);
9094610Smckusick }
9104610Smckusick 
911*4843Smckusic checkvol(b, t)
912*4843Smckusic 	struct s_spcl *b;
913*4843Smckusic 	int t;
9144610Smckusick {
915*4843Smckusic 	if (b->c_volume == t)
916*4843Smckusic 		return(1);
9174610Smckusick 	return(0);
9184610Smckusick }
9194610Smckusick 
920*4843Smckusic readhdr(b)
921*4843Smckusic 	struct s_spcl *b;
9224610Smckusick {
923*4843Smckusic 	if (gethead(b) == 0)
9244610Smckusick 		return(0);
925*4843Smckusic 	if (checktype(b, TS_TAPE) == 0)
926*4843Smckusic 		return(0);
927*4843Smckusic 	return(1);
9284610Smckusick }
9294610Smckusick 
9304610Smckusick /*
9314610Smckusick  * read the tape into buf, then return whether or
9324610Smckusick  * or not it is a header block.
9334610Smckusick  */
9344610Smckusick gethead(buf)
9354837Smckusic 	struct s_spcl *buf;
9364610Smckusick {
9374610Smckusick 	readtape((char *)buf);
9384837Smckusic 	if (buf->c_magic != MAGIC || checksum((int *)buf) == 0)
9394610Smckusick 		return(0);
9404610Smckusick 	return(1);
9414610Smckusick }
9424610Smckusick 
9434610Smckusick /*
9444610Smckusick  * return whether or not the buffer contains a header block
9454610Smckusick  */
9464610Smckusick ishead(buf)
9474837Smckusic 	struct s_spcl *buf;
9484610Smckusick {
9494837Smckusic 	if (buf->c_magic != MAGIC || checksum((int *)buf) == 0)
9504610Smckusick 		return(0);
9514610Smckusick 	return(1);
9524610Smckusick }
9534610Smckusick 
9544610Smckusick checktype(b, t)
9554837Smckusic 	struct s_spcl *b;
9564700Smckusic 	int	t;
9574610Smckusick {
9584837Smckusic 	return(b->c_type == t);
9594610Smckusick }
9604610Smckusick 
9614610Smckusick 
9624610Smckusick checksum(b)
9634700Smckusic 	int *b;
9644610Smckusick {
9654776Smckusic 	register int i, j;
9664610Smckusick 
9674776Smckusic 	j = sizeof(union u_spcl) / sizeof(int);
9684610Smckusick 	i = 0;
9694610Smckusick 	do
9704610Smckusick 		i += *b++;
9714610Smckusick 	while (--j);
9724610Smckusick 	if (i != CHECKSUM) {
9734776Smckusic 		fprintf(stderr, "Checksum error %o, ino %u\n", i, ino);
9744610Smckusick 		return(0);
9754610Smckusick 	}
9764610Smckusick 	return(1);
9774610Smckusick }
9784610Smckusick 
9794610Smckusick /*
9804700Smckusic  * tell whether an inode is allocated
9814700Smckusic  * this is drawn from ialloccg in sys/alloc.c
9824700Smckusic  */
9834700Smckusic iexist(dev, ino)
9844700Smckusic 	dev_t dev;
9854700Smckusic 	ino_t ino;
9864610Smckusick {
9874700Smckusic 	register struct fs *fs;
9884700Smckusic 	register struct cg *cgp;
9894700Smckusic 	register struct buf *bp;
9904700Smckusic 	int cg;
9914700Smckusic 
9924700Smckusic 	fs = getfs(dev);
9934700Smckusic 	if ((unsigned)ino >= fs->fs_ipg*fs->fs_ncg)
9944700Smckusic 		return (0);
9954700Smckusic 	cg = itog(ino, fs);
9964700Smckusic 	bp = bread(dev, cgtod(cg, fs), BSIZE);
9974700Smckusic 	if (bp->b_flags & B_ERROR)
9984700Smckusic 		return(0);
9994700Smckusic 	cgp = bp->b_un.b_cg;
10004700Smckusic 	ino %= fs->fs_ipg;
10014700Smckusic 	if (isclr(cgp->cg_iused, ino)) {
10024700Smckusic 		brelse(bp);
10034700Smckusic 		return(0);
10044700Smckusic 	}
10054700Smckusic 	brelse(bp);
10064700Smckusic 	return (1);
10074610Smckusick }
10084610Smckusick 
10094610Smckusick /*
10104610Smckusick  * read a bit mask from the tape into m.
10114610Smckusick  */
10124610Smckusick readbits(m)
10134700Smckusic 	short	*m;
10144610Smckusick {
10154776Smckusic 	register int i;
10164610Smckusick 
10174610Smckusick 	i = spcl.c_count;
10184610Smckusick 
10194610Smckusick 	while (i--) {
10204610Smckusick 		readtape((char *) m);
10214776Smckusic 		m += (TP_BSIZE/(MLEN/BITS));
10224610Smckusick 	}
10234610Smckusick 	while (gethead(&spcl) == 0)
10244610Smckusick 		;
10254610Smckusick }
10264610Smckusick 
10274700Smckusic done(exitcode)
10284700Smckusic 	int exitcode;
10294610Smckusick {
10304610Smckusick #ifndef STANDALONE
10314610Smckusick 	unlink(dirfile);
10324610Smckusick #endif
10334700Smckusic 	if (mounted)
10344700Smckusic 		xumount();
10354700Smckusic 	exit(exitcode);
10364610Smckusick }
10374610Smckusick 
1038*4843Smckusic allocinotab(ino, seekpt)
10394837Smckusic 	ino_t ino;
1040*4843Smckusic 	daddr_t seekpt;
10414610Smckusick {
10424837Smckusic 	register struct inotab	*itp;
10434776Smckusic 
10444837Smckusic 	itp = (struct inotab *)calloc(1, sizeof(struct inotab));
10454837Smckusic 	itp->t_next = inotab[INOHASH(ino)];
10464837Smckusic 	inotab[INOHASH(ino)] = itp;
10474837Smckusic 	itp->t_ino = ino;
1048*4843Smckusic 	itp->t_seekpt = seekpt;
10494610Smckusick }
10504610Smckusick 
1051*4843Smckusic allocxtr(ino, name, flags)
10524837Smckusic 	ino_t ino;
1053*4843Smckusic 	char *name;
1054*4843Smckusic 	char flags;
10554610Smckusick {
1056*4843Smckusic 	register struct xtrlist	*xp, *pxp;
10574776Smckusic 
1058*4843Smckusic 	xp = (struct xtrlist *)calloc(1, sizeof(struct xtrlist) + strlen(name));
10594837Smckusic 	xp->x_next = xtrlist[INOHASH(ino)];
10604837Smckusic 	xtrlist[INOHASH(ino)] = xp;
10614837Smckusic 	xp->x_ino = ino;
1062*4843Smckusic 	strcpy(xp->x_name, name);
10634837Smckusic 	xtrcnt++;
1064*4843Smckusic 	xp->x_flags = flags;
1065*4843Smckusic 	for (pxp = xp->x_next; pxp; pxp = pxp->x_next)
1066*4843Smckusic 		if (pxp->x_ino == ino && (pxp->x_flags & XLINKED) == 0) {
1067*4843Smckusic 			xp->x_flags |= XLINKED;
1068*4843Smckusic 			xp->x_linkedto = pxp;
1069*4843Smckusic 			xtrcnt--;
1070*4843Smckusic 			break;
1071*4843Smckusic 		}
1072*4843Smckusic 	if (xp->x_flags & XLINKED)
1073*4843Smckusic 		fprintf(stdout, "%s: linked to %s\n", xp->x_name, pxp->x_name);
1074*4843Smckusic 	else if (xp->x_flags & XISDIR)
1075*4843Smckusic 		fprintf(stdout, "%s: directory inode %u\n", xp->x_name, ino);
1076*4843Smckusic 	else
1077*4843Smckusic 		fprintf(stdout, "%s: inode %u\n", xp->x_name, ino);
10784610Smckusick }
10794610Smckusick 
10804610Smckusick /*
10814610Smckusick  *	Check for access into each directory in the pathname of an extracted
10824610Smckusick  *	file and create such a directory if needed in preparation for moving
10834610Smckusick  *	the file to its proper home.
10844610Smckusick  */
10854610Smckusick checkdir(name)
10864700Smckusic 	register char *name;
10874610Smckusick {
10884610Smckusick 	register char *cp;
10894610Smckusick 	int i;
10904776Smckusic 
10914610Smckusick 	for (cp = name; *cp; cp++) {
10924610Smckusick 		if (*cp == '/') {
10934610Smckusick 			*cp = '\0';
10944700Smckusic 			if (xaccess(name, 01) < 0) {
10954610Smckusick 				register int pid, rp;
10964610Smckusick 
10974700Smckusic 				xumount();
10984610Smckusick 				if ((pid = fork()) == 0) {
10994700Smckusic 					execl("/bin/xmkdir", "xmkdir", name, 0);
11004700Smckusic 					execl("/usr/bin/xmkdir", "xmkdir", name, 0);
11014700Smckusic 					execl("./xmkdir", "xmkdir", name, 0);
11024700Smckusic 					fprintf(stderr, "xrestor: cannot find xmkdir!\n");
11034610Smckusick 					done(0);
11044610Smckusick 				}
11054610Smckusick 				while ((rp = wait(&i)) >= 0 && rp != pid)
11064610Smckusick 					;
11074700Smckusic 				xmount(envp);
11084610Smckusick 			}
11094610Smckusick 			*cp = '/';
11104610Smckusick 		}
11114610Smckusick 	}
11124610Smckusick }
1113