xref: /titanic_50/usr/src/cmd/backup/restore/tape.c (revision 294baf98ae09b8aa1fd82c7ab53f8d8299c6d226)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (c) 1983 Regents of the University of California.
37c478bd9Sstevel@tonic-gate  * All rights reserved.  The Berkeley software License Agreement
47c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
57c478bd9Sstevel@tonic-gate  */
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
87c478bd9Sstevel@tonic-gate /*	  All Rights Reserved	*/
97c478bd9Sstevel@tonic-gate 
107c478bd9Sstevel@tonic-gate /*
11*294baf98Sbatschul  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
127c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #include <setjmp.h>
167c478bd9Sstevel@tonic-gate #include "restore.h"
177c478bd9Sstevel@tonic-gate #include <byteorder.h>
187c478bd9Sstevel@tonic-gate #include <rmt.h>
197c478bd9Sstevel@tonic-gate #include <sys/mtio.h>
207c478bd9Sstevel@tonic-gate #include <utime.h>
217c478bd9Sstevel@tonic-gate #include <sys/errno.h>
227c478bd9Sstevel@tonic-gate #include <sys/fdio.h>
237c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>	/* for expdev */
247c478bd9Sstevel@tonic-gate #include <assert.h>
257c478bd9Sstevel@tonic-gate #include <limits.h>
267c478bd9Sstevel@tonic-gate #include <priv_utils.h>
2749f0e518Smarks #include <aclutils.h>
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #define	MAXINO	65535		/* KLUDGE */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #define	MAXTAPES	128
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate static size_t	fssize = MAXBSIZE; /* preferred size of writes to filesystem */
347c478bd9Sstevel@tonic-gate int mt = -1;
357c478bd9Sstevel@tonic-gate static int	continuemap = 0;
367c478bd9Sstevel@tonic-gate char		magtape[BUFSIZ];
377c478bd9Sstevel@tonic-gate int		pipein = 0;
387c478bd9Sstevel@tonic-gate char		*host;		/* used in dumprmt.c */
397c478bd9Sstevel@tonic-gate daddr32_t	rec_position;
407c478bd9Sstevel@tonic-gate static char	*archivefile;	/* used in metamucil.c */
417c478bd9Sstevel@tonic-gate static int	bct;		/* block # index into tape record buffer */
427c478bd9Sstevel@tonic-gate static int	numtrec;	/* # of logical blocks in current tape record */
437c478bd9Sstevel@tonic-gate static char	*tbf = NULL;
447c478bd9Sstevel@tonic-gate static size_t	tbfsize = 0;
457c478bd9Sstevel@tonic-gate static int	recsread;
467c478bd9Sstevel@tonic-gate static union	u_spcl endoftapemark;
477c478bd9Sstevel@tonic-gate static struct	s_spcl dumpinfo;
487c478bd9Sstevel@tonic-gate static long	blksread;	/* # of logical blocks actually read/touched */
497c478bd9Sstevel@tonic-gate static long	tapea;		/* current logical block # on tape */
507c478bd9Sstevel@tonic-gate static uchar_t	tapesread[MAXTAPES];
517c478bd9Sstevel@tonic-gate static jmp_buf	restart;
527c478bd9Sstevel@tonic-gate static int	gettingfile = 0;	/* restart has a valid frame */
537c478bd9Sstevel@tonic-gate static int	ofile;
547c478bd9Sstevel@tonic-gate static char	*map, *beginmap;
557c478bd9Sstevel@tonic-gate static char	*endmap;
567c478bd9Sstevel@tonic-gate static char	lnkbuf[MAXPATHLEN + 2];
577c478bd9Sstevel@tonic-gate static int	pathlen;
587c478bd9Sstevel@tonic-gate static int	inodeinfo;	/* Have starting volume information */
597c478bd9Sstevel@tonic-gate static int	hostinfo;	/* Have dump host information */
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate static int autoload_tape(void);
627c478bd9Sstevel@tonic-gate static void setdumpnum(void);
637c478bd9Sstevel@tonic-gate static void metacheck(struct s_spcl *);
647c478bd9Sstevel@tonic-gate static void xtrmeta(char *, size_t);
657c478bd9Sstevel@tonic-gate static void metaskip(char *, size_t);
667c478bd9Sstevel@tonic-gate static void xtrfile(char *, size_t);
677c478bd9Sstevel@tonic-gate static void xtrskip(char *, size_t);
687c478bd9Sstevel@tonic-gate static void xtrlnkfile(char *, size_t);
697c478bd9Sstevel@tonic-gate static void xtrlnkskip(char *, size_t);
707c478bd9Sstevel@tonic-gate static void xtrmap(char *, size_t);
717c478bd9Sstevel@tonic-gate static void xtrmapskip(char *, size_t);
727c478bd9Sstevel@tonic-gate static void readtape(char *);
737c478bd9Sstevel@tonic-gate static int checkvol(struct s_spcl *, int);
747c478bd9Sstevel@tonic-gate static void accthdr(struct s_spcl *);
757c478bd9Sstevel@tonic-gate static int ishead(struct s_spcl *);
76fe0e7ec4Smaheshvs static int checktype(struct s_spcl *, int);
777c478bd9Sstevel@tonic-gate static void metaset(char *name);
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate /*
807c478bd9Sstevel@tonic-gate  * Set up an input source
817c478bd9Sstevel@tonic-gate  */
827c478bd9Sstevel@tonic-gate void
setinput(char * source,char * archive)83fe0e7ec4Smaheshvs setinput(char *source, char *archive)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	flsht();
877c478bd9Sstevel@tonic-gate 	archivefile = archive;
887c478bd9Sstevel@tonic-gate 	if (bflag == 0) {
897c478bd9Sstevel@tonic-gate 		ntrec = ((CARTRIDGETREC > HIGHDENSITYTREC) ?
907c478bd9Sstevel@tonic-gate 		    (NTREC > CARTRIDGETREC ? NTREC : CARTRIDGETREC) :
917c478bd9Sstevel@tonic-gate 		    (NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC));
927c478bd9Sstevel@tonic-gate 		saved_ntrec = (ntrec * (tp_bsize/DEV_BSIZE));
937c478bd9Sstevel@tonic-gate 	}
947c478bd9Sstevel@tonic-gate 	newtapebuf(ntrec);
957c478bd9Sstevel@tonic-gate 	terminal = stdin;
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 	if (source == NULL) {
987c478bd9Sstevel@tonic-gate 		/* A can't-happen */
997c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1007c478bd9Sstevel@tonic-gate 		    gettext("Internal consistency check failed.\n"));
1017c478bd9Sstevel@tonic-gate 		done(1);
1027c478bd9Sstevel@tonic-gate 	}
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	if (strchr(source, ':')) {
1057c478bd9Sstevel@tonic-gate 		char *tape;
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 		host = source;
1087c478bd9Sstevel@tonic-gate 		tape = strchr(host, ':');
1097c478bd9Sstevel@tonic-gate 		*tape++ = '\0';
1107c478bd9Sstevel@tonic-gate 		if (strlen(tape) > (sizeof (magtape) - 1)) {
1117c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("Tape name too long\n"));
1127c478bd9Sstevel@tonic-gate 			done(1);
1137c478bd9Sstevel@tonic-gate 		}
1147c478bd9Sstevel@tonic-gate 		(void) strcpy(magtape, tape);
1157c478bd9Sstevel@tonic-gate 		if (rmthost(host, ntrec) == 0)
1167c478bd9Sstevel@tonic-gate 			done(1);
1177c478bd9Sstevel@tonic-gate 	} else {
1187c478bd9Sstevel@tonic-gate 		if (strlen(source) > (sizeof (magtape) - 1)) {
1197c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("Tape name too long\n"));
1207c478bd9Sstevel@tonic-gate 			done(1);
1217c478bd9Sstevel@tonic-gate 		}
1227c478bd9Sstevel@tonic-gate 		/* Not remote, no need for privileges */
1237c478bd9Sstevel@tonic-gate 		__priv_relinquish();
1247c478bd9Sstevel@tonic-gate 		host = NULL;
1257c478bd9Sstevel@tonic-gate 		if (strcmp(source, "-") == 0) {
1267c478bd9Sstevel@tonic-gate 			/*
1277c478bd9Sstevel@tonic-gate 			 * Since input is coming from a pipe we must establish
1287c478bd9Sstevel@tonic-gate 			 * our own connection to the terminal.
1297c478bd9Sstevel@tonic-gate 			 */
1307c478bd9Sstevel@tonic-gate 			terminal = fopen("/dev/tty", "r");
1317c478bd9Sstevel@tonic-gate 			if (terminal == NULL) {
1327c478bd9Sstevel@tonic-gate 				int saverr = errno;
1337c478bd9Sstevel@tonic-gate 				char *msg =
1347c478bd9Sstevel@tonic-gate 				    gettext("Cannot open(\"/dev/tty\")");
1357c478bd9Sstevel@tonic-gate 				errno = saverr;
1367c478bd9Sstevel@tonic-gate 				perror(msg);
1377c478bd9Sstevel@tonic-gate 				terminal = fopen("/dev/null", "r");
1387c478bd9Sstevel@tonic-gate 				if (terminal == NULL) {
1397c478bd9Sstevel@tonic-gate 					saverr = errno;
1407c478bd9Sstevel@tonic-gate 					msg = gettext(
1417c478bd9Sstevel@tonic-gate 					    "Cannot open(\"/dev/null\")");
1427c478bd9Sstevel@tonic-gate 					errno = saverr;
1437c478bd9Sstevel@tonic-gate 					perror(msg);
1447c478bd9Sstevel@tonic-gate 					done(1);
1457c478bd9Sstevel@tonic-gate 				}
1467c478bd9Sstevel@tonic-gate 			}
1477c478bd9Sstevel@tonic-gate 			pipein++;
1487c478bd9Sstevel@tonic-gate 			if (archive) {
1497c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
1507c478bd9Sstevel@tonic-gate 	    "Cannot specify an archive file when reading from a pipe\n"));
1517c478bd9Sstevel@tonic-gate 				done(1);
1527c478bd9Sstevel@tonic-gate 			}
1537c478bd9Sstevel@tonic-gate 		}
1547c478bd9Sstevel@tonic-gate 		(void) strcpy(magtape, source);
1557c478bd9Sstevel@tonic-gate 	}
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate void
newtapebuf(size_t size)159fe0e7ec4Smaheshvs newtapebuf(size_t size)
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate 	size_t nsize;
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	nsize = size * tp_bsize;
1647c478bd9Sstevel@tonic-gate 	ntrec = size;
1657c478bd9Sstevel@tonic-gate 	if (nsize <= tbfsize)
1667c478bd9Sstevel@tonic-gate 		return;
1677c478bd9Sstevel@tonic-gate 	if (tbf != NULL)
1687c478bd9Sstevel@tonic-gate 		free(tbf);
1697c478bd9Sstevel@tonic-gate 	tbf = (char *)malloc(nsize);
1707c478bd9Sstevel@tonic-gate 	if (tbf == NULL) {
1717c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1727c478bd9Sstevel@tonic-gate 		    gettext("Cannot allocate space for buffer\n"));
1737c478bd9Sstevel@tonic-gate 		done(1);
1747c478bd9Sstevel@tonic-gate 	}
1757c478bd9Sstevel@tonic-gate 	tbfsize = nsize;
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate /*
1797c478bd9Sstevel@tonic-gate  * Verify that the tape drive can be accessed and
1807c478bd9Sstevel@tonic-gate  * that it actually is a dump tape.
1817c478bd9Sstevel@tonic-gate  */
1827c478bd9Sstevel@tonic-gate void
setup(void)1837c478bd9Sstevel@tonic-gate setup(void)
1847c478bd9Sstevel@tonic-gate {
1857c478bd9Sstevel@tonic-gate 	int i, j;
1867c478bd9Sstevel@tonic-gate 	int32_t *ip;
1877c478bd9Sstevel@tonic-gate 	struct stat stbuf;
1887c478bd9Sstevel@tonic-gate 	size_t mapsize;
1897c478bd9Sstevel@tonic-gate 	char *syment = RESTORESYMTABLE;
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	vprintf(stdout, gettext("Verify volume and initialize maps\n"));
1927c478bd9Sstevel@tonic-gate 	if (archivefile) {
1937c478bd9Sstevel@tonic-gate 		mt = open(archivefile, O_RDONLY|O_LARGEFILE);
1947c478bd9Sstevel@tonic-gate 		if (mt < 0) {
1957c478bd9Sstevel@tonic-gate 			perror(archivefile);
1967c478bd9Sstevel@tonic-gate 			done(1);
1977c478bd9Sstevel@tonic-gate 		}
1987c478bd9Sstevel@tonic-gate 		volno = 0;
1997c478bd9Sstevel@tonic-gate 	} else if (host) {
2007c478bd9Sstevel@tonic-gate 		if ((mt = rmtopen(magtape, O_RDONLY)) < 0) {
2017c478bd9Sstevel@tonic-gate 			perror(magtape);
2027c478bd9Sstevel@tonic-gate 			done(1);
2037c478bd9Sstevel@tonic-gate 		}
2047c478bd9Sstevel@tonic-gate 		volno = 1;
2057c478bd9Sstevel@tonic-gate 	} else {
2067c478bd9Sstevel@tonic-gate 		if (pipein)
2077c478bd9Sstevel@tonic-gate 			mt = 0;
2087c478bd9Sstevel@tonic-gate 		else if ((mt = open(magtape, O_RDONLY|O_LARGEFILE)) < 0) {
2097c478bd9Sstevel@tonic-gate 			perror(magtape);
2107c478bd9Sstevel@tonic-gate 			done(1);
2117c478bd9Sstevel@tonic-gate 		}
2127c478bd9Sstevel@tonic-gate 		volno = 1;
2137c478bd9Sstevel@tonic-gate 	}
2147c478bd9Sstevel@tonic-gate 	setdumpnum();
2157c478bd9Sstevel@tonic-gate 	flsht();
2167c478bd9Sstevel@tonic-gate 	if (!pipein && !bflag)
2177c478bd9Sstevel@tonic-gate 		if (archivefile)
2187c478bd9Sstevel@tonic-gate 			findtapeblksize(ARCHIVE_FILE);
2197c478bd9Sstevel@tonic-gate 		else
2207c478bd9Sstevel@tonic-gate 			findtapeblksize(TAPE_FILE);
2217c478bd9Sstevel@tonic-gate 	if (bflag == 1) {
2227c478bd9Sstevel@tonic-gate 		tape_rec_size = saved_ntrec * DEV_BSIZE;
2237c478bd9Sstevel@tonic-gate 	}
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	/*
2267c478bd9Sstevel@tonic-gate 	 * Get the first header.  If c_magic is NOT NFS_MAGIC or if
2277c478bd9Sstevel@tonic-gate 	 * the checksum is in error, it will fail.  The magic could then
2287c478bd9Sstevel@tonic-gate 	 * be either OFS_MAGIC or MTB_MAGIC.  If OFS_MAGIC, assume we
2297c478bd9Sstevel@tonic-gate 	 * have an old dump, and try to convert it.  If it is MTB_MAGIC, we
2307c478bd9Sstevel@tonic-gate 	 * procees this after.
2317c478bd9Sstevel@tonic-gate 	 */
2327c478bd9Sstevel@tonic-gate 	if ((gethead(&spcl) == FAIL) && (spcl.c_magic != MTB_MAGIC)) {
2337c478bd9Sstevel@tonic-gate 		bct--; /* push back this block */
2347c478bd9Sstevel@tonic-gate 		blksread--;
2357c478bd9Sstevel@tonic-gate 		tapea--;
2367c478bd9Sstevel@tonic-gate 		cvtflag++;
2377c478bd9Sstevel@tonic-gate 		if (gethead(&spcl) == FAIL) {
2387c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
2397c478bd9Sstevel@tonic-gate 			    gettext("Volume is not in dump format\n"));
2407c478bd9Sstevel@tonic-gate 			done(1);
2417c478bd9Sstevel@tonic-gate 		}
2427c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
2437c478bd9Sstevel@tonic-gate 		    gettext("Converting to new file system format.\n"));
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 	/*
2467c478bd9Sstevel@tonic-gate 	 * The above gethead will have failed if the magic is
2477c478bd9Sstevel@tonic-gate 	 * MTB_MAGIC. If that is true, we need to adjust tp_bsize.
2487c478bd9Sstevel@tonic-gate 	 * We have assumed to this time that tp_bsize was 1024, if
2497c478bd9Sstevel@tonic-gate 	 * this is a newer dump, get the real tp_bsize from the header,
2507c478bd9Sstevel@tonic-gate 	 * and recalculate ntrec, numtrec.
2517c478bd9Sstevel@tonic-gate 	 */
2527c478bd9Sstevel@tonic-gate 	if (spcl.c_magic == MTB_MAGIC) {
2537c478bd9Sstevel@tonic-gate 		tp_bsize = spcl.c_tpbsize;
2547c478bd9Sstevel@tonic-gate 		if ((tp_bsize % TP_BSIZE_MIN != 0) ||
2557c478bd9Sstevel@tonic-gate 		    (tp_bsize > TP_BSIZE_MAX)) {
2567c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
2577c478bd9Sstevel@tonic-gate 			    gettext("Volume is not in dump format\n"));
2587c478bd9Sstevel@tonic-gate 			done(1);
2597c478bd9Sstevel@tonic-gate 		}
2607c478bd9Sstevel@tonic-gate 		ntrec = (tape_rec_size/tp_bsize);
2617c478bd9Sstevel@tonic-gate 		numtrec = ntrec;
2627c478bd9Sstevel@tonic-gate 		newtapebuf(ntrec);
2637c478bd9Sstevel@tonic-gate 		bct--; /* push back this block */
2647c478bd9Sstevel@tonic-gate 		blksread--;
2657c478bd9Sstevel@tonic-gate 		tapea--;
2667c478bd9Sstevel@tonic-gate 		/* we have to re-do this in case checksum is wrong */
2677c478bd9Sstevel@tonic-gate 		if (gethead(&spcl) == FAIL) {
2687c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
2697c478bd9Sstevel@tonic-gate 			    gettext("Volume is not in dump format\n"));
2707c478bd9Sstevel@tonic-gate 			done(1);
2717c478bd9Sstevel@tonic-gate 		}
2727c478bd9Sstevel@tonic-gate 	}
2737c478bd9Sstevel@tonic-gate 	if (vflag)
2747c478bd9Sstevel@tonic-gate 		byteorder_banner(byteorder, stdout);
2757c478bd9Sstevel@tonic-gate 	if (pipein) {
2767c478bd9Sstevel@tonic-gate 		endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC :
2777c478bd9Sstevel@tonic-gate 		    ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC);
2787c478bd9Sstevel@tonic-gate 		endoftapemark.s_spcl.c_type = TS_END;
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 		/*
2817c478bd9Sstevel@tonic-gate 		 * include this since the `resync' loop in findinode
2827c478bd9Sstevel@tonic-gate 		 * expects to find a header with the c_date field
2837c478bd9Sstevel@tonic-gate 		 * filled in.
2847c478bd9Sstevel@tonic-gate 		 */
2857c478bd9Sstevel@tonic-gate 		endoftapemark.s_spcl.c_date = spcl.c_date;
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 		ip = (int32_t *)&endoftapemark;
2887c478bd9Sstevel@tonic-gate 		/*LINTED [assertion always true]*/
2897c478bd9Sstevel@tonic-gate 		assert((sizeof (endoftapemark) % sizeof (int32_t)) == 0);
2907c478bd9Sstevel@tonic-gate 		j = sizeof (endoftapemark) / sizeof (int32_t);
2917c478bd9Sstevel@tonic-gate 		i = 0;
2927c478bd9Sstevel@tonic-gate 		do
2937c478bd9Sstevel@tonic-gate 			i += *ip++;
294*294baf98Sbatschul 		while (--j)
295*294baf98Sbatschul 			;
2967c478bd9Sstevel@tonic-gate 		endoftapemark.s_spcl.c_checksum = CHECKSUM - i;
2977c478bd9Sstevel@tonic-gate 	}
2987c478bd9Sstevel@tonic-gate 	if (vflag && command != 't')
2997c478bd9Sstevel@tonic-gate 		printdumpinfo();
3007c478bd9Sstevel@tonic-gate 	dumptime = spcl.c_ddate;
3017c478bd9Sstevel@tonic-gate 	dumpdate = spcl.c_date;
3027c478bd9Sstevel@tonic-gate 	if (stat(".", &stbuf) < 0) {
3037c478bd9Sstevel@tonic-gate 		perror(gettext("cannot stat ."));
3047c478bd9Sstevel@tonic-gate 		done(1);
3057c478bd9Sstevel@tonic-gate 	}
3067c478bd9Sstevel@tonic-gate 	if (stbuf.st_blksize >= tp_bsize && stbuf.st_blksize <= MAXBSIZE) {
3077c478bd9Sstevel@tonic-gate 		/* LINTED: value fits in a size_t */
3087c478bd9Sstevel@tonic-gate 		fssize = stbuf.st_blksize;
309*294baf98Sbatschul 	} else {
310*294baf98Sbatschul 		fssize = MAXBSIZE;
3117c478bd9Sstevel@tonic-gate 	}
312*294baf98Sbatschul 
3137c478bd9Sstevel@tonic-gate 	if (checkvol(&spcl, 1) == FAIL) {
3147c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
3157c478bd9Sstevel@tonic-gate 		    gettext("This is not volume 1 of the dump\n"));
3167c478bd9Sstevel@tonic-gate 		done(1);
3177c478bd9Sstevel@tonic-gate 	}
3187c478bd9Sstevel@tonic-gate 	if (readhdr(&spcl) == FAIL)
3197c478bd9Sstevel@tonic-gate 		panic(gettext("no header after volume mark!\n"));
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	findinode(&spcl);	/* sets curfile, resyncs the tape if need be */
3227c478bd9Sstevel@tonic-gate 	if (checktype(&spcl, TS_CLRI) == FAIL) {
3237c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
3247c478bd9Sstevel@tonic-gate 		    gettext("Cannot find file removal list\n"));
3257c478bd9Sstevel@tonic-gate 		done(1);
3267c478bd9Sstevel@tonic-gate 	}
3277c478bd9Sstevel@tonic-gate 	maxino = (unsigned)((spcl.c_count * tp_bsize * NBBY) + 1);
3287c478bd9Sstevel@tonic-gate 	dprintf(stdout, "maxino = %lu\n", maxino);
3297c478bd9Sstevel@tonic-gate 	/*
3307c478bd9Sstevel@tonic-gate 	 * Allocate space for at least MAXINO inodes to allow us
3317c478bd9Sstevel@tonic-gate 	 * to restore partial dump tapes written before dump was
3327c478bd9Sstevel@tonic-gate 	 * fixed to write out the entire inode map.
3337c478bd9Sstevel@tonic-gate 	 */
3347c478bd9Sstevel@tonic-gate 	if (maxino > ULONG_MAX) {
3357c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
3367c478bd9Sstevel@tonic-gate 		    gettext("file system too large\n"));
3377c478bd9Sstevel@tonic-gate 		done(1);
3387c478bd9Sstevel@tonic-gate 	}
3397c478bd9Sstevel@tonic-gate 	/* LINTED maxino size-checked above */
3407c478bd9Sstevel@tonic-gate 	mapsize = (size_t)d_howmany(maxino > MAXINO ? maxino : MAXINO, NBBY);
3417c478bd9Sstevel@tonic-gate 	beginmap = map = calloc((size_t)1, mapsize);
3427c478bd9Sstevel@tonic-gate 	if (map == (char *)NIL) {
3437c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
3447c478bd9Sstevel@tonic-gate 		    gettext("no memory for file removal list\n"));
3457c478bd9Sstevel@tonic-gate 		done(1);
3467c478bd9Sstevel@tonic-gate 	}
3477c478bd9Sstevel@tonic-gate 	endmap = map + mapsize;
3487c478bd9Sstevel@tonic-gate 	clrimap = map;
3497c478bd9Sstevel@tonic-gate 	curfile.action = USING;
3507c478bd9Sstevel@tonic-gate 	continuemap = 1;
3517c478bd9Sstevel@tonic-gate 	getfile(xtrmap, xtrmapskip);
3527c478bd9Sstevel@tonic-gate 	if (MAXINO > maxino)
3537c478bd9Sstevel@tonic-gate 		maxino = MAXINO;
3547c478bd9Sstevel@tonic-gate 	if (checktype(&spcl, TS_BITS) == FAIL) {
3557c478bd9Sstevel@tonic-gate 		/* if we have TS_CLRI then no TS_BITS then a TS_END */
3567c478bd9Sstevel@tonic-gate 		/* then we have an empty dump file */
357*294baf98Sbatschul 		if (gethead(&spcl) == GOOD &&
358*294baf98Sbatschul 		    checktype(&spcl, TS_END) == GOOD) {
3597c478bd9Sstevel@tonic-gate 			if ((command == 'r') || (command == 'R')) {
3607c478bd9Sstevel@tonic-gate 				initsymtable(syment);
3617c478bd9Sstevel@tonic-gate 				dumpsymtable(syment, volno);
3627c478bd9Sstevel@tonic-gate 			}
3637c478bd9Sstevel@tonic-gate 			done(0);
3647c478bd9Sstevel@tonic-gate 		}
3657c478bd9Sstevel@tonic-gate 		/* otherwise we have an error */
3667c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Cannot find file dump list\n"));
3677c478bd9Sstevel@tonic-gate 		done(1);
3687c478bd9Sstevel@tonic-gate 	}
3697c478bd9Sstevel@tonic-gate 	/* LINTED maxino size-checked above */
3707c478bd9Sstevel@tonic-gate 	mapsize = (size_t)d_howmany(maxino, NBBY);
3717c478bd9Sstevel@tonic-gate 	beginmap = map = calloc((size_t)1, mapsize);
3727c478bd9Sstevel@tonic-gate 	if (map == (char *)NULL) {
3737c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
3747c478bd9Sstevel@tonic-gate 		    gettext("no memory for file dump list\n"));
3757c478bd9Sstevel@tonic-gate 		done(1);
3767c478bd9Sstevel@tonic-gate 	}
3777c478bd9Sstevel@tonic-gate 	endmap = map + mapsize;
3787c478bd9Sstevel@tonic-gate 	dumpmap = map;
3797c478bd9Sstevel@tonic-gate 	curfile.action = USING;
3807c478bd9Sstevel@tonic-gate 	continuemap = 1;
3817c478bd9Sstevel@tonic-gate 	getfile(xtrmap, xtrmapskip);
3827c478bd9Sstevel@tonic-gate 	continuemap = 0;
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate /*
3867c478bd9Sstevel@tonic-gate  * Initialize fssize variable for 'R' command to work.
3877c478bd9Sstevel@tonic-gate  */
3887c478bd9Sstevel@tonic-gate void
setupR(void)3897c478bd9Sstevel@tonic-gate setupR(void)
3907c478bd9Sstevel@tonic-gate {
3917c478bd9Sstevel@tonic-gate 	struct stat stbuf;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	if (stat(".", &stbuf) < 0) {
3947c478bd9Sstevel@tonic-gate 		perror(gettext("cannot stat ."));
3957c478bd9Sstevel@tonic-gate 		done(1);
3967c478bd9Sstevel@tonic-gate 	}
3977c478bd9Sstevel@tonic-gate 	if (stbuf.st_blksize >= tp_bsize && stbuf.st_blksize <= MAXBSIZE) {
3987c478bd9Sstevel@tonic-gate 		/* LINTED: value fits in a size_t */
3997c478bd9Sstevel@tonic-gate 		fssize = stbuf.st_blksize;
400*294baf98Sbatschul 	} else {
401*294baf98Sbatschul 		fssize = MAXBSIZE;
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate /*
4067c478bd9Sstevel@tonic-gate  * Prompt user to load a new dump volume.
4077c478bd9Sstevel@tonic-gate  * "Nextvol" is the next suggested volume to use.
4087c478bd9Sstevel@tonic-gate  * This suggested volume is enforced when doing full
4097c478bd9Sstevel@tonic-gate  * or incremental restores, but can be overrridden by
4107c478bd9Sstevel@tonic-gate  * the user when only extracting a subset of the files.
4117c478bd9Sstevel@tonic-gate  *
4127c478bd9Sstevel@tonic-gate  * first_time is used with archive files and can have 1 of 3 states:
4137c478bd9Sstevel@tonic-gate  *	FT_STATE_1	Tape has not been read yet
4147c478bd9Sstevel@tonic-gate  *	FT_STATE_2	Tape has been read but not positioned past directory
4157c478bd9Sstevel@tonic-gate  *			information
4167c478bd9Sstevel@tonic-gate  *	FT_STATE_3	Tape has been read and is reading file information
4177c478bd9Sstevel@tonic-gate  */
4187c478bd9Sstevel@tonic-gate #define	FT_STATE_1	1
4197c478bd9Sstevel@tonic-gate #define	FT_STATE_2	2
4207c478bd9Sstevel@tonic-gate #define	FT_STATE_3	3
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate void
getvol(int nextvol)423fe0e7ec4Smaheshvs getvol(int nextvol)
4247c478bd9Sstevel@tonic-gate {
4257c478bd9Sstevel@tonic-gate 	int newvol;
4267c478bd9Sstevel@tonic-gate 	long savecnt, savetapea, wantnext;
4277c478bd9Sstevel@tonic-gate 	long i;
4287c478bd9Sstevel@tonic-gate 	union u_spcl tmpspcl;
4297c478bd9Sstevel@tonic-gate #define	tmpbuf tmpspcl.s_spcl
4307c478bd9Sstevel@tonic-gate 	char buf[TP_BSIZE_MAX];
4317c478bd9Sstevel@tonic-gate 	static int first_time = FT_STATE_1;
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	if (tbf == NULL) {
4347c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
4357c478bd9Sstevel@tonic-gate 		    "Internal consistency failure in getvol: tbf is NULL\n"));
4367c478bd9Sstevel@tonic-gate 		done(1);
4377c478bd9Sstevel@tonic-gate 	}
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	if (nextvol == 1) {
4407c478bd9Sstevel@tonic-gate 		for (i = 0;  i < MAXTAPES;  i++)
4417c478bd9Sstevel@tonic-gate 			tapesread[i] = 0;
4427c478bd9Sstevel@tonic-gate 		gettingfile = 0;
4437c478bd9Sstevel@tonic-gate 	}
4447c478bd9Sstevel@tonic-gate 	if (pipein) {
4457c478bd9Sstevel@tonic-gate 		if (nextvol != 1)
4467c478bd9Sstevel@tonic-gate 			panic(gettext("changing volumes on pipe input\n"));
4477c478bd9Sstevel@tonic-gate 		if (volno == 1)
4487c478bd9Sstevel@tonic-gate 			return;
4497c478bd9Sstevel@tonic-gate 		goto gethdr;
4507c478bd9Sstevel@tonic-gate 	}
4517c478bd9Sstevel@tonic-gate 	savecnt = blksread;	/* ignore volume verification tape i/o */
4527c478bd9Sstevel@tonic-gate 	savetapea = tapea;
4537c478bd9Sstevel@tonic-gate again:
4547c478bd9Sstevel@tonic-gate 	if (pipein)
4557c478bd9Sstevel@tonic-gate 		done(1); /* pipes do not get a second chance */
4567c478bd9Sstevel@tonic-gate 	if (command == 'R' || command == 'r' || curfile.action != SKIP) {
4577c478bd9Sstevel@tonic-gate 		wantnext = 1;
4587c478bd9Sstevel@tonic-gate 		newvol = nextvol;
4597c478bd9Sstevel@tonic-gate 	} else {
4607c478bd9Sstevel@tonic-gate 		wantnext = 0;
4617c478bd9Sstevel@tonic-gate 		newvol = 0;
4627c478bd9Sstevel@tonic-gate 	}
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 	if (autoload) {
4657c478bd9Sstevel@tonic-gate 		if ((volno == 1) && (nextvol == 1)) {
4667c478bd9Sstevel@tonic-gate 			tapesread[volno-1]++;
4677c478bd9Sstevel@tonic-gate 			return;
4687c478bd9Sstevel@tonic-gate 		}
4697c478bd9Sstevel@tonic-gate 		if (autoload_tape()) {
4702720c984Svk154806 			wantnext = 1;
4712720c984Svk154806 			newvol = nextvol;
4727c478bd9Sstevel@tonic-gate 			goto gethdr;
4737c478bd9Sstevel@tonic-gate 		}
4747c478bd9Sstevel@tonic-gate 	}
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	while (newvol <= 0) {
4777c478bd9Sstevel@tonic-gate 		int n = 0;
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 		for (i = 0;  i < MAXTAPES;  i++)
4807c478bd9Sstevel@tonic-gate 			if (tapesread[i])
4817c478bd9Sstevel@tonic-gate 				n++;
4827c478bd9Sstevel@tonic-gate 		if (n == 0) {
4837c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s", gettext(
4847c478bd9Sstevel@tonic-gate "You have not read any volumes yet.\n\
4857c478bd9Sstevel@tonic-gate Unless you know which volume your file(s) are on you should start\n\
4867c478bd9Sstevel@tonic-gate with the last volume and work towards the first.\n"));
4877c478bd9Sstevel@tonic-gate 		} else {
4887c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
4897c478bd9Sstevel@tonic-gate 			    gettext("You have read volumes"));
4907c478bd9Sstevel@tonic-gate 			(void) strcpy(tbf, ": ");
4917c478bd9Sstevel@tonic-gate 			for (i = 0; i < MAXTAPES; i++)
4927c478bd9Sstevel@tonic-gate 				if (tapesread[i]) {
4937c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr, "%s%ld",
4947c478bd9Sstevel@tonic-gate 					    tbf, i+1);
4957c478bd9Sstevel@tonic-gate 					(void) strcpy(tbf, ", ");
4967c478bd9Sstevel@tonic-gate 				}
4977c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "\n");
4987c478bd9Sstevel@tonic-gate 		}
4997c478bd9Sstevel@tonic-gate 		do {
5007c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
5017c478bd9Sstevel@tonic-gate 			    gettext("Specify next volume #: "));
5027c478bd9Sstevel@tonic-gate 			(void) fflush(stderr);
5037c478bd9Sstevel@tonic-gate 			/* LINTED tbfsize is limited to a few MB */
5047c478bd9Sstevel@tonic-gate 			(void) fgets(tbf, (int)tbfsize, terminal);
5057c478bd9Sstevel@tonic-gate 		} while (!feof(terminal) && tbf[0] == '\n');
5067c478bd9Sstevel@tonic-gate 		if (feof(terminal))
5077c478bd9Sstevel@tonic-gate 			done(1);
5087c478bd9Sstevel@tonic-gate 		newvol = atoi(tbf);
5097c478bd9Sstevel@tonic-gate 		if (newvol <= 0) {
5107c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
5117c478bd9Sstevel@tonic-gate 			    "Volume numbers are positive numerics\n"));
5127c478bd9Sstevel@tonic-gate 		}
5137c478bd9Sstevel@tonic-gate 		if (newvol > MAXTAPES) {
5147c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
5157c478bd9Sstevel@tonic-gate 			    "This program can only deal with %d volumes\n"),
5167c478bd9Sstevel@tonic-gate 			    MAXTAPES);
5177c478bd9Sstevel@tonic-gate 			newvol = 0;
5187c478bd9Sstevel@tonic-gate 		}
5197c478bd9Sstevel@tonic-gate 	}
5207c478bd9Sstevel@tonic-gate 	if (newvol == volno) {
5217c478bd9Sstevel@tonic-gate 		tapesread[volno-1]++;
5227c478bd9Sstevel@tonic-gate 		return;
5237c478bd9Sstevel@tonic-gate 	}
52433a5e6b2Srm88369 	closemt(ALLOW_OFFLINE);
5257c478bd9Sstevel@tonic-gate 	/*
5267c478bd9Sstevel@tonic-gate 	 * XXX: if we are switching devices, we should probably try
5277c478bd9Sstevel@tonic-gate 	 * the device once without prompting to enable unattended
5287c478bd9Sstevel@tonic-gate 	 * operation.
5297c478bd9Sstevel@tonic-gate 	 */
5307c478bd9Sstevel@tonic-gate 	if (host)
5317c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
5327c478bd9Sstevel@tonic-gate "Mount volume %d\nthen enter volume name on host %s (default: %s) "),
5337c478bd9Sstevel@tonic-gate 		    newvol, host,  magtape);
5347c478bd9Sstevel@tonic-gate 	else
5357c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
5367c478bd9Sstevel@tonic-gate 		    "Mount volume %d\nthen enter volume name (default: %s) "),
5377c478bd9Sstevel@tonic-gate 		    newvol, magtape);
5387c478bd9Sstevel@tonic-gate 	(void) fflush(stderr);
5397c478bd9Sstevel@tonic-gate 	/* LINTED tbfsize is limited to a few MB */
5407c478bd9Sstevel@tonic-gate 	(void) fgets(tbf, (int)tbfsize, terminal);
5417c478bd9Sstevel@tonic-gate 	if (feof(terminal))
5427c478bd9Sstevel@tonic-gate 		done(1);
5437c478bd9Sstevel@tonic-gate 	/*
5447c478bd9Sstevel@tonic-gate 	 * XXX We don't allow rotating among tape hosts, just drives.
5457c478bd9Sstevel@tonic-gate 	 */
5467c478bd9Sstevel@tonic-gate 	if (tbf[0] != '\n') {
5477c478bd9Sstevel@tonic-gate 		(void) strncpy(magtape, tbf, sizeof (magtape));
5487c478bd9Sstevel@tonic-gate 		magtape[sizeof (magtape) - 1] = '\0';
5497c478bd9Sstevel@tonic-gate 		/* LINTED unsigned -> signed conversion ok */
5507c478bd9Sstevel@tonic-gate 		i = (int)strlen(magtape);
5517c478bd9Sstevel@tonic-gate 		if (magtape[i - 1] == '\n')
5527c478bd9Sstevel@tonic-gate 			magtape[i - 1] = '\0';
5537c478bd9Sstevel@tonic-gate 	}
5547c478bd9Sstevel@tonic-gate 	if ((host != NULL && (mt = rmtopen(magtape, O_RDONLY)) == -1) ||
5557c478bd9Sstevel@tonic-gate 	    (host == NULL &&
5567c478bd9Sstevel@tonic-gate 	    (mt = open(magtape, O_RDONLY|O_LARGEFILE)) == -1)) {
5577c478bd9Sstevel@tonic-gate 		int error = errno;
5587c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Cannot open %s: %s\n"),
5597c478bd9Sstevel@tonic-gate 		    magtape, strerror(error));
5607c478bd9Sstevel@tonic-gate 		volno = -1;
5617c478bd9Sstevel@tonic-gate 		goto again;
5627c478bd9Sstevel@tonic-gate 	}
5637c478bd9Sstevel@tonic-gate gethdr:
5647c478bd9Sstevel@tonic-gate 	volno = newvol;
5657c478bd9Sstevel@tonic-gate 	setdumpnum();
5667c478bd9Sstevel@tonic-gate 	flsht();
5677c478bd9Sstevel@tonic-gate 	if (!pipein && !bflag && archivefile && (first_time == FT_STATE_1)) {
5687c478bd9Sstevel@tonic-gate 		first_time = FT_STATE_2;
5697c478bd9Sstevel@tonic-gate 		findtapeblksize(TAPE_FILE);
5707c478bd9Sstevel@tonic-gate 	}
5717c478bd9Sstevel@tonic-gate 	if (readhdr(&tmpbuf) == FAIL) {
5727c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
5737c478bd9Sstevel@tonic-gate 		    gettext("volume is not in dump format\n"));
5747c478bd9Sstevel@tonic-gate 		volno = 0;
5757c478bd9Sstevel@tonic-gate 		goto again;
5767c478bd9Sstevel@tonic-gate 	}
5777c478bd9Sstevel@tonic-gate 	if (checkvol(&tmpbuf, volno) == FAIL) {
5787c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Wrong volume (%d)\n"),
5797c478bd9Sstevel@tonic-gate 		    tmpbuf.c_volume);
5807c478bd9Sstevel@tonic-gate 		volno = 0;
5817c478bd9Sstevel@tonic-gate 		goto again;
5827c478bd9Sstevel@tonic-gate 	}
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	if (((time_t)(tmpbuf.c_date) != dumpdate) ||
5857c478bd9Sstevel@tonic-gate 	    ((time_t)(tmpbuf.c_ddate) != dumptime)) {
5867c478bd9Sstevel@tonic-gate 		char *tmp_ct;
5877c478bd9Sstevel@tonic-gate 		time_t lc_date = (time_t)tmpbuf.c_date;
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 		/*
5907c478bd9Sstevel@tonic-gate 		 * This is used to save the return value from lctime(),
5917c478bd9Sstevel@tonic-gate 		 * since that's volatile across lctime() invocations.
5927c478bd9Sstevel@tonic-gate 		 */
5937c478bd9Sstevel@tonic-gate 		tmp_ct = strdup(lctime(&lc_date));
5947c478bd9Sstevel@tonic-gate 		if (tmp_ct == (char *)0) {
5957c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
5967c478bd9Sstevel@tonic-gate 			    "Cannot allocate space for time string\n"));
5977c478bd9Sstevel@tonic-gate 			done(1);
5987c478bd9Sstevel@tonic-gate 		}
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
6017c478bd9Sstevel@tonic-gate 		    gettext("Wrong dump date\n\tgot: %s\twanted: %s"),
6027c478bd9Sstevel@tonic-gate 		    tmp_ct,  lctime(&dumpdate));
6037c478bd9Sstevel@tonic-gate 		volno = 0;
6047c478bd9Sstevel@tonic-gate 		free(tmp_ct);
6057c478bd9Sstevel@tonic-gate 		goto again;
6067c478bd9Sstevel@tonic-gate 	}
6077c478bd9Sstevel@tonic-gate 	tapesread[volno-1]++;
6087c478bd9Sstevel@tonic-gate 	blksread = savecnt;
6097c478bd9Sstevel@tonic-gate 	tapea = savetapea;
6107c478bd9Sstevel@tonic-gate 	/*
6117c478bd9Sstevel@tonic-gate 	 * If continuing from the previous volume, skip over any
6127c478bd9Sstevel@tonic-gate 	 * blocks read already at the end of the previous volume.
6137c478bd9Sstevel@tonic-gate 	 *
6147c478bd9Sstevel@tonic-gate 	 * If coming to this volume at random, skip to the beginning
6157c478bd9Sstevel@tonic-gate 	 * of the next record.
6167c478bd9Sstevel@tonic-gate 	 */
6177c478bd9Sstevel@tonic-gate 	if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) {
6187c478bd9Sstevel@tonic-gate 		if (!wantnext) {
6197c478bd9Sstevel@tonic-gate 			if (archivefile && first_time == FT_STATE_2) {
6207c478bd9Sstevel@tonic-gate 				first_time = FT_STATE_3;
6217c478bd9Sstevel@tonic-gate 			}
6227c478bd9Sstevel@tonic-gate 			recsread = tmpbuf.c_firstrec;
6237c478bd9Sstevel@tonic-gate 			tapea = tmpbuf.c_tapea;
6247c478bd9Sstevel@tonic-gate 			dprintf(stdout,
6257c478bd9Sstevel@tonic-gate 			    "restore skipping %d records\n",
6267c478bd9Sstevel@tonic-gate 			    tmpbuf.c_count);
6277c478bd9Sstevel@tonic-gate 			for (i = tmpbuf.c_count; i > 0; i--)
6287c478bd9Sstevel@tonic-gate 				readtape(buf);
6297c478bd9Sstevel@tonic-gate 		} else if (tmpbuf.c_firstrec != 0) {
6307c478bd9Sstevel@tonic-gate 			savecnt = blksread;
6317c478bd9Sstevel@tonic-gate 			savetapea = tapea;
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 			if (archivefile && first_time == FT_STATE_2) {
6347c478bd9Sstevel@tonic-gate 				/*
6357c478bd9Sstevel@tonic-gate 				 * subtract 2, 1 for archive file's TS_END
6367c478bd9Sstevel@tonic-gate 				 * and 1 for tape's TS_TAPE
6377c478bd9Sstevel@tonic-gate 				 */
6387c478bd9Sstevel@tonic-gate 				first_time = FT_STATE_3;
6397c478bd9Sstevel@tonic-gate 				i = tapea - tmpbuf.c_tapea - 2;
6407c478bd9Sstevel@tonic-gate 			} else {
6417c478bd9Sstevel@tonic-gate 				i = tapea - tmpbuf.c_tapea;
6427c478bd9Sstevel@tonic-gate 			}
6437c478bd9Sstevel@tonic-gate 			if (i > 0)
6447c478bd9Sstevel@tonic-gate 				dprintf(stdout, gettext(
6457c478bd9Sstevel@tonic-gate 				    "restore skipping %d duplicate records\n"),
6467c478bd9Sstevel@tonic-gate 				    i);
6477c478bd9Sstevel@tonic-gate 			else if (i < 0)
6487c478bd9Sstevel@tonic-gate 				dprintf(stdout, gettext(
6497c478bd9Sstevel@tonic-gate 				    "restore duplicate record botch (%d)\n"),
6507c478bd9Sstevel@tonic-gate 				    i);
6517c478bd9Sstevel@tonic-gate 			while (--i >= 0)
6527c478bd9Sstevel@tonic-gate 				readtape(buf);
6537c478bd9Sstevel@tonic-gate 			blksread = savecnt;
6547c478bd9Sstevel@tonic-gate 			tapea = savetapea + 1; /* <= (void) gethead() below */
6557c478bd9Sstevel@tonic-gate 		}
6567c478bd9Sstevel@tonic-gate 	}
6577c478bd9Sstevel@tonic-gate 	if (curfile.action == USING) {
6587c478bd9Sstevel@tonic-gate 		if (volno == 1)
6597c478bd9Sstevel@tonic-gate 			panic(gettext("active file into volume 1\n"));
6607c478bd9Sstevel@tonic-gate 		return;
6617c478bd9Sstevel@tonic-gate 	}
6627c478bd9Sstevel@tonic-gate 	(void) gethead(&spcl);
6637c478bd9Sstevel@tonic-gate 	findinode(&spcl); /* do we always restart files in full? */
6647c478bd9Sstevel@tonic-gate 	if (gettingfile) { /* i.e. will we lose metadata? */
6657c478bd9Sstevel@tonic-gate 		gettingfile = 0;
6667c478bd9Sstevel@tonic-gate 		longjmp(restart, 1); /* will this set f1 & f2? */
6677c478bd9Sstevel@tonic-gate 	}
6687c478bd9Sstevel@tonic-gate }
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate /*
6717c478bd9Sstevel@tonic-gate  * handle multiple dumps per tape by skipping forward to the
6727c478bd9Sstevel@tonic-gate  * appropriate one.  Note we don't use absolute positioning,
6737c478bd9Sstevel@tonic-gate  * as that may take a very long time.
6747c478bd9Sstevel@tonic-gate  */
6757c478bd9Sstevel@tonic-gate static void
setdumpnum(void)6767c478bd9Sstevel@tonic-gate setdumpnum(void)
6777c478bd9Sstevel@tonic-gate {
6787c478bd9Sstevel@tonic-gate 	struct mtop tcom;
6797c478bd9Sstevel@tonic-gate 	int retval;
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	if (dumpnum == 1 || volno != 1)
6827c478bd9Sstevel@tonic-gate 		return;
6837c478bd9Sstevel@tonic-gate 	if (pipein) {
6847c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
6857c478bd9Sstevel@tonic-gate 		    gettext("Cannot have multiple dumps on pipe input\n"));
6867c478bd9Sstevel@tonic-gate 		done(1);
6877c478bd9Sstevel@tonic-gate 	}
6887c478bd9Sstevel@tonic-gate 	tcom.mt_op = MTFSF;
6897c478bd9Sstevel@tonic-gate 	tcom.mt_count = dumpnum - 1;
6907c478bd9Sstevel@tonic-gate 	if (host)
6917c478bd9Sstevel@tonic-gate 		retval = rmtioctl(MTFSF, dumpnum - 1);
6927c478bd9Sstevel@tonic-gate 	else
6937c478bd9Sstevel@tonic-gate 		retval = ioctl(mt, (int)MTIOCTOP, (char *)&tcom);
6947c478bd9Sstevel@tonic-gate 	if (retval < 0)
6957c478bd9Sstevel@tonic-gate 		perror("ioctl MTFSF");
6967c478bd9Sstevel@tonic-gate }
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate void
printdumpinfo(void)6997c478bd9Sstevel@tonic-gate printdumpinfo(void)
7007c478bd9Sstevel@tonic-gate {
7017c478bd9Sstevel@tonic-gate 	int i;
7027c478bd9Sstevel@tonic-gate 	time_t date;
7037c478bd9Sstevel@tonic-gate 	static char *epoch = NULL;
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 	if (epoch == NULL) {
7067c478bd9Sstevel@tonic-gate 		epoch = strdup(gettext("the epoch\n"));
7077c478bd9Sstevel@tonic-gate 		if (epoch == NULL) {
7087c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("Out of memory\n"));
7097c478bd9Sstevel@tonic-gate 			return;
7107c478bd9Sstevel@tonic-gate 		}
7117c478bd9Sstevel@tonic-gate 	}
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 	date = (time_t)dumpinfo.c_date;
7147c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout,
7157c478bd9Sstevel@tonic-gate 	    gettext("Dump   date: %s"), lctime(&date));
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate 	date = (time_t)dumpinfo.c_ddate;
7187c478bd9Sstevel@tonic-gate 	(void) fprintf(stdout, gettext("Dumped from: %s"),
7197c478bd9Sstevel@tonic-gate 	    (dumpinfo.c_ddate == 0) ? epoch : lctime(&date));
7207c478bd9Sstevel@tonic-gate 	if (hostinfo) {
7217c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout,
7227c478bd9Sstevel@tonic-gate 		    gettext("Level %d dump of %s on %.*s:%s\n"),
7237c478bd9Sstevel@tonic-gate 		    dumpinfo.c_level, dumpinfo.c_filesys,
7247c478bd9Sstevel@tonic-gate 		    sizeof (dumpinfo.c_host), dumpinfo.c_host, dumpinfo.c_dev);
7257c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout,
7267c478bd9Sstevel@tonic-gate 		    gettext("Label: %.*s\n"),
7277c478bd9Sstevel@tonic-gate 		    sizeof (dumpinfo.c_label), dumpinfo.c_label);
7287c478bd9Sstevel@tonic-gate 	}
7297c478bd9Sstevel@tonic-gate 	if (inodeinfo) {
7307c478bd9Sstevel@tonic-gate 		(void) fprintf(stdout,
7317c478bd9Sstevel@tonic-gate 		    gettext("Starting inode numbers by volume:\n"));
7327c478bd9Sstevel@tonic-gate 		for (i = 1; i <= dumpinfo.c_volume; i++)
7337c478bd9Sstevel@tonic-gate 			(void) fprintf(stdout, gettext("\tVolume %d: %6d\n"),
7347c478bd9Sstevel@tonic-gate 			    i, dumpinfo.c_inos[i]);
7357c478bd9Sstevel@tonic-gate 	}
7367c478bd9Sstevel@tonic-gate }
7377c478bd9Sstevel@tonic-gate 
738fe0e7ec4Smaheshvs int
extractfile(char * name)739fe0e7ec4Smaheshvs extractfile(char *name)
7407c478bd9Sstevel@tonic-gate {
7417c478bd9Sstevel@tonic-gate 	static int complained_chown = 0;
7427c478bd9Sstevel@tonic-gate 	static int complained_lchown = 0;
7437c478bd9Sstevel@tonic-gate 	static int complained_chmod = 0;
7447c478bd9Sstevel@tonic-gate 	static int complained_utime = 0;
7457c478bd9Sstevel@tonic-gate 	static int complained_mknod = 0;
7467c478bd9Sstevel@tonic-gate 	mode_t mode;
7477c478bd9Sstevel@tonic-gate 	time_t timep[2];
7487c478bd9Sstevel@tonic-gate 	struct entry *ep;
7497c478bd9Sstevel@tonic-gate 	uid_t uid;
7507c478bd9Sstevel@tonic-gate 	gid_t gid;
7517c478bd9Sstevel@tonic-gate 	char *errmsg;
7527c478bd9Sstevel@tonic-gate 	int result, saverr;
7537c478bd9Sstevel@tonic-gate 	dev_t full_dev;
7547c478bd9Sstevel@tonic-gate 	int dfd;
7557c478bd9Sstevel@tonic-gate 	char *rname;
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate 	curfile.name = name;
7587c478bd9Sstevel@tonic-gate 	curfile.action = USING;
7597c478bd9Sstevel@tonic-gate 	timep[0] = (time_t)curfile.dip->di_atime;
7607c478bd9Sstevel@tonic-gate 	timep[1] = (time_t)curfile.dip->di_mtime;
7617c478bd9Sstevel@tonic-gate 	mode = curfile.dip->di_mode;
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	uid = curfile.dip->di_suid == UID_LONG ?
7647c478bd9Sstevel@tonic-gate 	    curfile.dip->di_uid : (uid_t)curfile.dip->di_suid;
7657c478bd9Sstevel@tonic-gate 	gid = curfile.dip->di_sgid == GID_LONG ?
7667c478bd9Sstevel@tonic-gate 	    curfile.dip->di_gid : (gid_t)curfile.dip->di_sgid;
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 	resolve(name, &dfd, &rname);
7697c478bd9Sstevel@tonic-gate 	if (dfd != AT_FDCWD) {
7707c478bd9Sstevel@tonic-gate 		if (fchdir(dfd) < 0) {
7717c478bd9Sstevel@tonic-gate 			saverr = errno;
7727c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
7737c478bd9Sstevel@tonic-gate 			    "%s: unable to set attribute context: %s\n"),
7747c478bd9Sstevel@tonic-gate 			    rname, strerror(saverr));
7757c478bd9Sstevel@tonic-gate 			skipfile();
7767c478bd9Sstevel@tonic-gate 			(void) close(dfd);
7777c478bd9Sstevel@tonic-gate 			return (FAIL);
7787c478bd9Sstevel@tonic-gate 		}
7797c478bd9Sstevel@tonic-gate 	}
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 	switch (mode & IFMT) {
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 	default:
7847c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("%s: unknown file mode 0%lo\n"),
7857c478bd9Sstevel@tonic-gate 		    rname, (ulong_t)(mode&IFMT));
7867c478bd9Sstevel@tonic-gate 		skipfile();
7877c478bd9Sstevel@tonic-gate 		result = FAIL;
7887c478bd9Sstevel@tonic-gate 		break;
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 	case IFSOCK:
7917c478bd9Sstevel@tonic-gate 		vprintf(stdout, gettext("skipped socket %s\n"), rname);
7927c478bd9Sstevel@tonic-gate 		skipfile();
7937c478bd9Sstevel@tonic-gate 		result = GOOD;
7947c478bd9Sstevel@tonic-gate 		break;
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate 	case IFDIR:
7977c478bd9Sstevel@tonic-gate 		if (mflag) {
7987c478bd9Sstevel@tonic-gate 			ep = lookupname(name);
7997c478bd9Sstevel@tonic-gate 			if (ep == NIL || ep->e_flags & EXTRACT) {
8007c478bd9Sstevel@tonic-gate 				panic(gettext(
8017c478bd9Sstevel@tonic-gate 				    "directory %s was not restored\n"),
8027c478bd9Sstevel@tonic-gate 				    rname);
8037c478bd9Sstevel@tonic-gate 				skipfile();
8047c478bd9Sstevel@tonic-gate 				result = FAIL;
8057c478bd9Sstevel@tonic-gate 				break;
8067c478bd9Sstevel@tonic-gate 			}
8077c478bd9Sstevel@tonic-gate 			skipfile();
8087c478bd9Sstevel@tonic-gate 			result = GOOD;
8097c478bd9Sstevel@tonic-gate 			break;
8107c478bd9Sstevel@tonic-gate 		}
8117c478bd9Sstevel@tonic-gate 		vprintf(stdout, gettext("extract file %s\n"), rname);
8127c478bd9Sstevel@tonic-gate 		result = genliteraldir(rname, curfile.ino);
8137c478bd9Sstevel@tonic-gate 		break;
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate 	case IFLNK:
8167c478bd9Sstevel@tonic-gate 		lnkbuf[0] = '\0';
8177c478bd9Sstevel@tonic-gate 		pathlen = 0;
8187c478bd9Sstevel@tonic-gate 		getfile(xtrlnkfile, xtrlnkskip);
8197c478bd9Sstevel@tonic-gate 		if (pathlen == 0) {
8207c478bd9Sstevel@tonic-gate 			vprintf(stdout, gettext(
8217c478bd9Sstevel@tonic-gate 			    "%s: zero length symbolic link (ignored)\n"),
8227c478bd9Sstevel@tonic-gate 			    rname);
8237c478bd9Sstevel@tonic-gate 			result = GOOD;
8247c478bd9Sstevel@tonic-gate 			break;
8257c478bd9Sstevel@tonic-gate 		}
8267c478bd9Sstevel@tonic-gate 		if ((result = lf_linkit(lnkbuf, rname, SYMLINK)) != GOOD)
8277c478bd9Sstevel@tonic-gate 			break;
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 		/* 1254700: set uid/gid (previously missing)  */
8307c478bd9Sstevel@tonic-gate 		if (lchown(rname, uid, gid) < 0 && !complained_lchown) {
8317c478bd9Sstevel@tonic-gate 			/* Just a warning */
8327c478bd9Sstevel@tonic-gate 			saverr = errno;
8337c478bd9Sstevel@tonic-gate 			errmsg = gettext(
8347c478bd9Sstevel@tonic-gate 			    "Unable to restore ownership of symlink %s: %s\n");
8357c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, errmsg,
8367c478bd9Sstevel@tonic-gate 			    rname, strerror(saverr));
8377c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
8387c478bd9Sstevel@tonic-gate 			    "Additional such failures will be ignored.\n"));
8397c478bd9Sstevel@tonic-gate 			complained_lchown = 1;
8407c478bd9Sstevel@tonic-gate 		}
8417c478bd9Sstevel@tonic-gate 		metaset(rname);
8427c478bd9Sstevel@tonic-gate 		result = GOOD;
8437c478bd9Sstevel@tonic-gate 		break;
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 	case IFCHR:
8467c478bd9Sstevel@tonic-gate 	case IFBLK:
8477c478bd9Sstevel@tonic-gate 	case IFIFO:
8487c478bd9Sstevel@tonic-gate 		vprintf(stdout, gettext("extract special file %s\n"), rname);
8497c478bd9Sstevel@tonic-gate 		/* put device rdev into dev_t expanded format */
8507c478bd9Sstevel@tonic-gate 		/* XXX does this always do the right thing? */
8517c478bd9Sstevel@tonic-gate 		/* XXX does dump do the right thing? */
8527c478bd9Sstevel@tonic-gate 		if (((curfile.dip->di_ordev & 0xFFFF0000) == 0) ||
8537c478bd9Sstevel@tonic-gate 		    ((curfile.dip->di_ordev & 0xFFFF0000) == 0xFFFF0000)) {
8547c478bd9Sstevel@tonic-gate 			full_dev = expdev((unsigned)(curfile.dip->di_ordev));
8557c478bd9Sstevel@tonic-gate 		} else {
8567c478bd9Sstevel@tonic-gate 			/* LINTED sign extension ok */
8577c478bd9Sstevel@tonic-gate 			full_dev = (unsigned)(curfile.dip->di_ordev);
8587c478bd9Sstevel@tonic-gate 		}
8597c478bd9Sstevel@tonic-gate 
860fe0e7ec4Smaheshvs 		if (mknod(rname, mode, full_dev) < 0) {
8617c478bd9Sstevel@tonic-gate 			struct stat64 s[1];
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 			saverr = errno;
8647c478bd9Sstevel@tonic-gate 			if ((stat64(rname, s)) ||
8657c478bd9Sstevel@tonic-gate 			    ((s->st_mode & S_IFMT) != (mode & S_IFMT)) ||
8667c478bd9Sstevel@tonic-gate 			    (s->st_rdev != full_dev)) {
8677c478bd9Sstevel@tonic-gate 				if (saverr != EPERM || !complained_mknod) {
8687c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr, "%s: ", rname);
8697c478bd9Sstevel@tonic-gate 					(void) fflush(stderr);
8707c478bd9Sstevel@tonic-gate 					errno = saverr;
8717c478bd9Sstevel@tonic-gate 					perror(gettext(
8727c478bd9Sstevel@tonic-gate 					    "cannot create special file"));
8737c478bd9Sstevel@tonic-gate 					if (saverr == EPERM) {
8747c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr, gettext(
8757c478bd9Sstevel@tonic-gate 			    "Additional such failures will be ignored.\n"));
8767c478bd9Sstevel@tonic-gate 						complained_mknod = 1;
8777c478bd9Sstevel@tonic-gate 					}
8787c478bd9Sstevel@tonic-gate 				}
8797c478bd9Sstevel@tonic-gate 				skipfile();
8807c478bd9Sstevel@tonic-gate 				result = FAIL;
8817c478bd9Sstevel@tonic-gate 				break;
8827c478bd9Sstevel@tonic-gate 			}
8837c478bd9Sstevel@tonic-gate 		}
8847c478bd9Sstevel@tonic-gate 		if (chown(rname, uid, gid) < 0 && !complained_chown) {
8857c478bd9Sstevel@tonic-gate 			/* Just a warning */
8867c478bd9Sstevel@tonic-gate 			saverr = errno;
8877c478bd9Sstevel@tonic-gate 			errmsg = gettext(
8887c478bd9Sstevel@tonic-gate 			    "Unable to restore ownership of %s: %s\n");
8897c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, errmsg,
8907c478bd9Sstevel@tonic-gate 			    rname, strerror(saverr));
8917c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
8927c478bd9Sstevel@tonic-gate 			    "Additional such failures will be ignored.\n"));
8937c478bd9Sstevel@tonic-gate 			complained_chown = 1;
8947c478bd9Sstevel@tonic-gate 		}
8957c478bd9Sstevel@tonic-gate 		if (chmod(rname, mode) < 0 && !complained_chmod) {
8967c478bd9Sstevel@tonic-gate 			saverr = errno;
8977c478bd9Sstevel@tonic-gate 			errmsg = gettext(
8987c478bd9Sstevel@tonic-gate 			    "Unable to restore permissions on %s: %s\n");
8997c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, errmsg,
9007c478bd9Sstevel@tonic-gate 			    rname, strerror(saverr));
9017c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
9027c478bd9Sstevel@tonic-gate 			    "Additional such failures will be ignored.\n"));
9037c478bd9Sstevel@tonic-gate 			complained_chmod = 1;
9047c478bd9Sstevel@tonic-gate 		}
9057c478bd9Sstevel@tonic-gate 		skipfile();
9067c478bd9Sstevel@tonic-gate 		metaset(rname); /* skipfile() got the metadata, if any */
9077c478bd9Sstevel@tonic-gate 		if (utime(rname, (struct utimbuf *)timep) < 0 &&
9087c478bd9Sstevel@tonic-gate 		    !complained_utime) {
9097c478bd9Sstevel@tonic-gate 			saverr = errno;
9107c478bd9Sstevel@tonic-gate 			errmsg = gettext(
9117c478bd9Sstevel@tonic-gate 			    "Unable to restore times on %s: %s\n");
9127c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, errmsg,
9137c478bd9Sstevel@tonic-gate 			    rname, strerror(saverr));
9147c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
9157c478bd9Sstevel@tonic-gate 			    "Additional such failures will be ignored.\n"));
9167c478bd9Sstevel@tonic-gate 			complained_utime = 1;
9177c478bd9Sstevel@tonic-gate 		}
9187c478bd9Sstevel@tonic-gate 		result = GOOD;
9197c478bd9Sstevel@tonic-gate 		break;
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 	case IFREG:
9227c478bd9Sstevel@tonic-gate 		vprintf(stdout, gettext("extract file %s\n"), rname);
923*294baf98Sbatschul 
924*294baf98Sbatschul 		/*
925*294baf98Sbatschul 		 * perform a restrictive creat(2) initally, we'll
926*294baf98Sbatschul 		 * fchmod(2) according to the archive later after
927*294baf98Sbatschul 		 * we've written the blocks.
928*294baf98Sbatschul 		 */
929*294baf98Sbatschul 		ofile = creat64(rname, 0600);
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 		if (ofile < 0) {
9327c478bd9Sstevel@tonic-gate 			saverr = errno;
9337c478bd9Sstevel@tonic-gate 			errmsg = gettext("cannot create file");
9347c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: ", rname);
9357c478bd9Sstevel@tonic-gate 			(void) fflush(stderr);
9367c478bd9Sstevel@tonic-gate 			errno = saverr;
9377c478bd9Sstevel@tonic-gate 			perror(errmsg);
9387c478bd9Sstevel@tonic-gate 			skipfile();
9397c478bd9Sstevel@tonic-gate 			result = FAIL;
9407c478bd9Sstevel@tonic-gate 			break;
9417c478bd9Sstevel@tonic-gate 		}
9427c478bd9Sstevel@tonic-gate 		if (fchown(ofile, uid, gid) < 0 && !complained_chown) {
9437c478bd9Sstevel@tonic-gate 			/* Just a warning */
9447c478bd9Sstevel@tonic-gate 			saverr = errno;
9457c478bd9Sstevel@tonic-gate 			errmsg = gettext(
9467c478bd9Sstevel@tonic-gate 			    "Unable to restore ownership of %s: %s\n");
9477c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, errmsg,
9487c478bd9Sstevel@tonic-gate 			    rname, strerror(saverr));
9497c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
9507c478bd9Sstevel@tonic-gate 			    "Additional such failures will be ignored.\n"));
9517c478bd9Sstevel@tonic-gate 			complained_chown = 1;
9527c478bd9Sstevel@tonic-gate 		}
953*294baf98Sbatschul 
954*294baf98Sbatschul 		getfile(xtrfile, xtrskip);
955*294baf98Sbatschul 		metaset(rname);
956*294baf98Sbatschul 
957*294baf98Sbatschul 		/*
958*294baf98Sbatschul 		 * the fchmod(2) has to come after getfile() as some POSIX
959*294baf98Sbatschul 		 * implementations clear the S_ISUID and S_ISGID bits of the
960*294baf98Sbatschul 		 * file after every write(2).
961*294baf98Sbatschul 		 */
9627c478bd9Sstevel@tonic-gate 		if (fchmod(ofile, mode) < 0 && !complained_chmod) {
9637c478bd9Sstevel@tonic-gate 			saverr = errno;
9647c478bd9Sstevel@tonic-gate 			errmsg = gettext(
9657c478bd9Sstevel@tonic-gate 			    "Unable to restore permissions on %s: %s\n");
9667c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, errmsg,
9677c478bd9Sstevel@tonic-gate 			    rname, strerror(saverr));
9687c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
9697c478bd9Sstevel@tonic-gate 			    "Additional such failures will be ignored.\n"));
9707c478bd9Sstevel@tonic-gate 			complained_chmod = 1;
9717c478bd9Sstevel@tonic-gate 		}
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 		/*
9747c478bd9Sstevel@tonic-gate 		 * Some errors don't get reported until we close(2), so
9757c478bd9Sstevel@tonic-gate 		 * check for them.
9767c478bd9Sstevel@tonic-gate 		 * XXX unlink the file if an error is reported?
9777c478bd9Sstevel@tonic-gate 		 */
9787c478bd9Sstevel@tonic-gate 		if (close(ofile) < 0) {
9797c478bd9Sstevel@tonic-gate 			saverr = errno;
9807c478bd9Sstevel@tonic-gate 			errmsg = gettext("error closing file");
9817c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: ", rname);
9827c478bd9Sstevel@tonic-gate 			(void) fflush(stderr);
9837c478bd9Sstevel@tonic-gate 			errno = saverr;
9847c478bd9Sstevel@tonic-gate 			perror(errmsg);
9857c478bd9Sstevel@tonic-gate 			result = FAIL;
9867c478bd9Sstevel@tonic-gate 			break;
9877c478bd9Sstevel@tonic-gate 		}
9887c478bd9Sstevel@tonic-gate 		if (utime(rname, (struct utimbuf *)timep) < 0 &&
9897c478bd9Sstevel@tonic-gate 		    !complained_utime) {
9907c478bd9Sstevel@tonic-gate 			saverr = errno;
9917c478bd9Sstevel@tonic-gate 			errmsg = gettext(
9927c478bd9Sstevel@tonic-gate 			    "Unable to restore times on %s: %s\n");
9937c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, errmsg,
9947c478bd9Sstevel@tonic-gate 			    rname, strerror(saverr));
9957c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
9967c478bd9Sstevel@tonic-gate 			    "Additional such failures will be ignored.\n"));
9977c478bd9Sstevel@tonic-gate 			complained_utime = 1;
9987c478bd9Sstevel@tonic-gate 		}
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate 		result = GOOD;
10017c478bd9Sstevel@tonic-gate 		break;
10027c478bd9Sstevel@tonic-gate 	}
10037c478bd9Sstevel@tonic-gate 	if (dfd != AT_FDCWD) {
10047c478bd9Sstevel@tonic-gate 		fchdir(savepwd);
10057c478bd9Sstevel@tonic-gate 		(void) close(dfd);
10067c478bd9Sstevel@tonic-gate 	}
10077c478bd9Sstevel@tonic-gate 	return (result);
10087c478bd9Sstevel@tonic-gate }
10097c478bd9Sstevel@tonic-gate 
10107c478bd9Sstevel@tonic-gate /*
10117c478bd9Sstevel@tonic-gate  * skip over bit maps on the tape
10127c478bd9Sstevel@tonic-gate  */
10137c478bd9Sstevel@tonic-gate void
skipmaps(void)10147c478bd9Sstevel@tonic-gate skipmaps(void)
10157c478bd9Sstevel@tonic-gate {
10167c478bd9Sstevel@tonic-gate 	continuemap = 1;
10177c478bd9Sstevel@tonic-gate 	while (checktype(&spcl, TS_CLRI) == GOOD ||
10187c478bd9Sstevel@tonic-gate 	    checktype(&spcl, TS_BITS) == GOOD)
10197c478bd9Sstevel@tonic-gate 		skipfile();
10207c478bd9Sstevel@tonic-gate 	continuemap = 0;
10217c478bd9Sstevel@tonic-gate }
10227c478bd9Sstevel@tonic-gate 
10237c478bd9Sstevel@tonic-gate /*
10247c478bd9Sstevel@tonic-gate  * skip over a file on the tape
10257c478bd9Sstevel@tonic-gate  */
10267c478bd9Sstevel@tonic-gate void
skipfile(void)10277c478bd9Sstevel@tonic-gate skipfile(void)
10287c478bd9Sstevel@tonic-gate {
10297c478bd9Sstevel@tonic-gate 	curfile.action = SKIP;
10307c478bd9Sstevel@tonic-gate 	getfile(null, null);
10317c478bd9Sstevel@tonic-gate }
10327c478bd9Sstevel@tonic-gate /*
10337c478bd9Sstevel@tonic-gate  * Do the file extraction, calling the supplied functions
10347c478bd9Sstevel@tonic-gate  * with the blocks
10357c478bd9Sstevel@tonic-gate  */
10367c478bd9Sstevel@tonic-gate void
getfile(void (* f1)(),void (* f2)())1037fe0e7ec4Smaheshvs getfile(void (*f1)(), void (*f2)())
10387c478bd9Sstevel@tonic-gate {
10397c478bd9Sstevel@tonic-gate 	int i;
10407c478bd9Sstevel@tonic-gate 	size_t curblk = 0;
10417c478bd9Sstevel@tonic-gate 	offset_t size = (offset_t)spcl.c_dinode.di_size;
10427c478bd9Sstevel@tonic-gate 	static char clearedbuf[MAXBSIZE];
10437c478bd9Sstevel@tonic-gate 	char buf[TP_BSIZE_MAX];
10447c478bd9Sstevel@tonic-gate 	char *bufptr;
10457c478bd9Sstevel@tonic-gate 	char junk[TP_BSIZE_MAX];
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 	assert(MAXBSIZE >= tp_bsize);
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate 	metaset(NULL);	/* flush old metadata */
10507c478bd9Sstevel@tonic-gate 	if (checktype(&spcl, TS_END) == GOOD) {
10517c478bd9Sstevel@tonic-gate 		panic(gettext("ran off end of volume\n"));
10527c478bd9Sstevel@tonic-gate 		return;
10537c478bd9Sstevel@tonic-gate 	}
10547c478bd9Sstevel@tonic-gate 	if (ishead(&spcl) == FAIL) {
10557c478bd9Sstevel@tonic-gate 		panic(gettext("not at beginning of a file\n"));
10567c478bd9Sstevel@tonic-gate 		return;
10577c478bd9Sstevel@tonic-gate 	}
10587c478bd9Sstevel@tonic-gate 	metacheck(&spcl); /* check for metadata in header */
10597c478bd9Sstevel@tonic-gate 	if (!gettingfile && setjmp(restart) != 0) {
10607c478bd9Sstevel@tonic-gate 		gettingfile = 0;	/* paranoia; longjmp'er should do */
10617c478bd9Sstevel@tonic-gate 		return;
10627c478bd9Sstevel@tonic-gate 	}
10637c478bd9Sstevel@tonic-gate 	gettingfile++;
10647c478bd9Sstevel@tonic-gate loop:
10657c478bd9Sstevel@tonic-gate 	if ((spcl.c_dinode.di_mode & IFMT) == IFSHAD) {
10667c478bd9Sstevel@tonic-gate 		f1 = xtrmeta;
10677c478bd9Sstevel@tonic-gate 		f2 = metaskip;
10687c478bd9Sstevel@tonic-gate 	}
10697c478bd9Sstevel@tonic-gate 	for (i = 0, bufptr = buf; i < spcl.c_count; i++) {
10707c478bd9Sstevel@tonic-gate 		if ((i >= TP_NINDIR) || (spcl.c_addr[i])) {
10717c478bd9Sstevel@tonic-gate 			readtape(bufptr);
10727c478bd9Sstevel@tonic-gate 			bufptr += tp_bsize;
10737c478bd9Sstevel@tonic-gate 			curblk++;
10747c478bd9Sstevel@tonic-gate 			if (curblk == (fssize / tp_bsize)) {
10757c478bd9Sstevel@tonic-gate 				(*f1)(buf, size > tp_bsize ?
10767c478bd9Sstevel@tonic-gate 				    (size_t)(fssize) :
10777c478bd9Sstevel@tonic-gate 					/* LINTED size <= tp_bsize */
10787c478bd9Sstevel@tonic-gate 				    (curblk - 1) * tp_bsize + (size_t)size);
10797c478bd9Sstevel@tonic-gate 				curblk = 0;
10807c478bd9Sstevel@tonic-gate 				bufptr = buf;
10817c478bd9Sstevel@tonic-gate 			}
10827c478bd9Sstevel@tonic-gate 		} else {
10837c478bd9Sstevel@tonic-gate 			if (curblk > 0) {
10847c478bd9Sstevel@tonic-gate 				(*f1)(buf, size > tp_bsize ?
10857c478bd9Sstevel@tonic-gate 				    (size_t)(curblk * tp_bsize) :
10867c478bd9Sstevel@tonic-gate 					/* LINTED size <= tp_bsize */
10877c478bd9Sstevel@tonic-gate 				    (curblk - 1) * tp_bsize + (size_t)size);
10887c478bd9Sstevel@tonic-gate 				curblk = 0;
10897c478bd9Sstevel@tonic-gate 				bufptr = buf;
10907c478bd9Sstevel@tonic-gate 			}
10917c478bd9Sstevel@tonic-gate 			(*f2)(clearedbuf, size > tp_bsize ?
10927c478bd9Sstevel@tonic-gate 					/* LINTED size <= tp_bsize */
10937c478bd9Sstevel@tonic-gate 			    (long)tp_bsize : (size_t)size);
10947c478bd9Sstevel@tonic-gate 		}
10957c478bd9Sstevel@tonic-gate 		if ((size -= tp_bsize) <= 0) {
10967c478bd9Sstevel@tonic-gate 			for (i++; i < spcl.c_count; i++)
10977c478bd9Sstevel@tonic-gate 				if ((i >= TP_NINDIR) || (spcl.c_addr[i]))
10987c478bd9Sstevel@tonic-gate 					readtape(junk);
10997c478bd9Sstevel@tonic-gate 			break;
11007c478bd9Sstevel@tonic-gate 		}
11017c478bd9Sstevel@tonic-gate 	}
11027c478bd9Sstevel@tonic-gate 	if (curblk > 0) {
11037c478bd9Sstevel@tonic-gate 		/*
11047c478bd9Sstevel@tonic-gate 		 * Ok to cast size to size_t here. The above for loop reads
11057c478bd9Sstevel@tonic-gate 		 * data into the buffer then writes it to the output file. The
11067c478bd9Sstevel@tonic-gate 		 * call to f1 here is to write out the data that's in the
11077c478bd9Sstevel@tonic-gate 		 * buffer that has not yet been written to the file.
11087c478bd9Sstevel@tonic-gate 		 * This will be less than N-KB of data, since the
11097c478bd9Sstevel@tonic-gate 		 * above loop writes to the file in filesystem-
11107c478bd9Sstevel@tonic-gate 		 * blocksize chunks.
11117c478bd9Sstevel@tonic-gate 		 */
11127c478bd9Sstevel@tonic-gate 		/* LINTED: size fits into a size_t at this point */
11137c478bd9Sstevel@tonic-gate 		(*f1)(buf, (curblk * tp_bsize) + (size_t)size);
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate 		curblk = 0;
11167c478bd9Sstevel@tonic-gate 		bufptr = buf;
11177c478bd9Sstevel@tonic-gate 	}
11187c478bd9Sstevel@tonic-gate 	if ((readhdr(&spcl) == GOOD) && (checktype(&spcl, TS_ADDR) == GOOD)) {
11197c478bd9Sstevel@tonic-gate 		if (continuemap)
11207c478bd9Sstevel@tonic-gate 			size = (offset_t)spcl.c_count * tp_bsize;
11217c478bd9Sstevel@tonic-gate 							/* big bitmap */
11227c478bd9Sstevel@tonic-gate 		else if ((size <= 0) &&
11237c478bd9Sstevel@tonic-gate 		    ((spcl.c_dinode.di_mode & IFMT) == IFSHAD)) {
11247c478bd9Sstevel@tonic-gate 			/* LINTED unsigned to signed conversion ok */
11257c478bd9Sstevel@tonic-gate 			size = spcl.c_dinode.di_size;
11267c478bd9Sstevel@tonic-gate 		}
11277c478bd9Sstevel@tonic-gate 		if (size > 0)
11287c478bd9Sstevel@tonic-gate 			goto loop;
11297c478bd9Sstevel@tonic-gate 	}
11307c478bd9Sstevel@tonic-gate 	if (size > 0)
11317c478bd9Sstevel@tonic-gate 		dprintf(stdout,
11327c478bd9Sstevel@tonic-gate 		    gettext("Missing address (header) block for %s\n"),
11337c478bd9Sstevel@tonic-gate 		    curfile.name);
11347c478bd9Sstevel@tonic-gate 	findinode(&spcl);
11357c478bd9Sstevel@tonic-gate 	gettingfile = 0;
11367c478bd9Sstevel@tonic-gate }
11377c478bd9Sstevel@tonic-gate 
11387c478bd9Sstevel@tonic-gate /*
11397c478bd9Sstevel@tonic-gate  * The next routines are called during file extraction to
11407c478bd9Sstevel@tonic-gate  * put the data into the right form and place.
11417c478bd9Sstevel@tonic-gate  */
11427c478bd9Sstevel@tonic-gate static void
xtrfile(char * buf,size_t size)1143fe0e7ec4Smaheshvs xtrfile(char *buf, size_t size)
11447c478bd9Sstevel@tonic-gate {
11457c478bd9Sstevel@tonic-gate 	if (write(ofile, buf, (size_t)size) == -1) {
11467c478bd9Sstevel@tonic-gate 		int saverr = errno;
11477c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
11487c478bd9Sstevel@tonic-gate 		    gettext("write error extracting inode %d, name %s\n"),
11497c478bd9Sstevel@tonic-gate 		    curfile.ino, curfile.name);
11507c478bd9Sstevel@tonic-gate 		errno = saverr;
11517c478bd9Sstevel@tonic-gate 		perror("write");
11527c478bd9Sstevel@tonic-gate 		done(1);
11537c478bd9Sstevel@tonic-gate 	}
11547c478bd9Sstevel@tonic-gate }
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate /*
11577c478bd9Sstevel@tonic-gate  * Even though size is a size_t, it's seeking to a relative
11587c478bd9Sstevel@tonic-gate  * offset.  Thus, the seek could go beyond 2 GB, so lseek64 is needed.
11597c478bd9Sstevel@tonic-gate  */
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11627c478bd9Sstevel@tonic-gate static void
xtrskip(char * buf,size_t size)1163fe0e7ec4Smaheshvs xtrskip(char *buf, size_t size)
11647c478bd9Sstevel@tonic-gate {
11657c478bd9Sstevel@tonic-gate 	if (lseek64(ofile, (offset_t)size, 1) == -1) {
11667c478bd9Sstevel@tonic-gate 		int saverr = errno;
11677c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
11687c478bd9Sstevel@tonic-gate 		    gettext("seek error extracting inode %d, name %s\n"),
11697c478bd9Sstevel@tonic-gate 		    curfile.ino, curfile.name);
11707c478bd9Sstevel@tonic-gate 		errno = saverr;
11717c478bd9Sstevel@tonic-gate 		perror("lseek64");
11727c478bd9Sstevel@tonic-gate 		done(1);
11737c478bd9Sstevel@tonic-gate 	}
11747c478bd9Sstevel@tonic-gate }
11757c478bd9Sstevel@tonic-gate 
11767c478bd9Sstevel@tonic-gate /* these are local to the next five functions */
11777c478bd9Sstevel@tonic-gate static char *metadata = NULL;
11787c478bd9Sstevel@tonic-gate static size_t metasize = 0;
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate static void
metacheck(struct s_spcl * head)1181fe0e7ec4Smaheshvs metacheck(struct s_spcl *head)
11827c478bd9Sstevel@tonic-gate {
11837c478bd9Sstevel@tonic-gate 	if (! (head->c_flags & DR_HASMETA))
11847c478bd9Sstevel@tonic-gate 		return;
11857c478bd9Sstevel@tonic-gate 	if ((metadata = malloc(metasize = (size_t)sizeof (head->c_shadow)))
11867c478bd9Sstevel@tonic-gate 	    == NULL) {
11877c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
11887c478bd9Sstevel@tonic-gate 		    gettext("Cannot malloc for metadata\n"));
11897c478bd9Sstevel@tonic-gate 		done(1);
11907c478bd9Sstevel@tonic-gate 	}
11917c478bd9Sstevel@tonic-gate 	bcopy(&(head->c_shadow), metadata, metasize);
11927c478bd9Sstevel@tonic-gate }
11937c478bd9Sstevel@tonic-gate 
11947c478bd9Sstevel@tonic-gate static void
xtrmeta(char * buf,size_t size)1195fe0e7ec4Smaheshvs xtrmeta(char *buf, size_t size)
11967c478bd9Sstevel@tonic-gate {
11977c478bd9Sstevel@tonic-gate 	if ((metadata == NULL) && ((spcl.c_dinode.di_mode & IFMT) != IFSHAD))
11987c478bd9Sstevel@tonic-gate 		return;
11997c478bd9Sstevel@tonic-gate 	if ((metadata = realloc(metadata, metasize + size)) == NULL) {
12007c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
12017c478bd9Sstevel@tonic-gate 		    gettext("Cannot malloc for metadata\n"));
12027c478bd9Sstevel@tonic-gate 		done(1);
12037c478bd9Sstevel@tonic-gate 	}
12047c478bd9Sstevel@tonic-gate 	bcopy(buf, metadata + metasize, size);
12057c478bd9Sstevel@tonic-gate 	metasize += size;
12067c478bd9Sstevel@tonic-gate }
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate /* ARGSUSED */
12097c478bd9Sstevel@tonic-gate static void
metaskip(char * buf,size_t size)1210fe0e7ec4Smaheshvs metaskip(char *buf, size_t size)
12117c478bd9Sstevel@tonic-gate {
12127c478bd9Sstevel@tonic-gate 	if (metadata == NULL)
12137c478bd9Sstevel@tonic-gate 		return;
12147c478bd9Sstevel@tonic-gate 	if ((metadata = realloc(metadata, metasize + size)) == NULL) {
12157c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
12167c478bd9Sstevel@tonic-gate 		    gettext("Cannot malloc for metadata\n"));
12177c478bd9Sstevel@tonic-gate 		done(1);
12187c478bd9Sstevel@tonic-gate 	}
12197c478bd9Sstevel@tonic-gate 	bzero(metadata + metasize, size);
12207c478bd9Sstevel@tonic-gate 	metasize += size;
12217c478bd9Sstevel@tonic-gate }
12227c478bd9Sstevel@tonic-gate 
12237c478bd9Sstevel@tonic-gate static void
metaset(char * name)1224fe0e7ec4Smaheshvs metaset(char *name)
12257c478bd9Sstevel@tonic-gate {
12267c478bd9Sstevel@tonic-gate 	if (metadata == NULL)
12277c478bd9Sstevel@tonic-gate 		return;
12287c478bd9Sstevel@tonic-gate 	if (name != NULL)
12297c478bd9Sstevel@tonic-gate 		metaproc(name, metadata, metasize);
12307c478bd9Sstevel@tonic-gate 	(void) free(metadata);
12317c478bd9Sstevel@tonic-gate 	metadata = NULL;
12327c478bd9Sstevel@tonic-gate 	metasize = 0;
12337c478bd9Sstevel@tonic-gate }
12347c478bd9Sstevel@tonic-gate 
12357c478bd9Sstevel@tonic-gate void
metaget(data,size)12367c478bd9Sstevel@tonic-gate metaget(data, size)
12377c478bd9Sstevel@tonic-gate 	char **data;
12387c478bd9Sstevel@tonic-gate 	size_t *size;
12397c478bd9Sstevel@tonic-gate {
12407c478bd9Sstevel@tonic-gate 	*data = metadata;
12417c478bd9Sstevel@tonic-gate 	*size = metasize;
12427c478bd9Sstevel@tonic-gate }
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate static void
fsd_acl(name,aclp,size)12457c478bd9Sstevel@tonic-gate fsd_acl(name, aclp, size)
12467c478bd9Sstevel@tonic-gate 	char *name, *aclp;
12477c478bd9Sstevel@tonic-gate 	unsigned size;
12487c478bd9Sstevel@tonic-gate {
12497c478bd9Sstevel@tonic-gate 	static aclent_t *aclent = NULL;
12507c478bd9Sstevel@tonic-gate 	ufs_acl_t *diskacl;
12517c478bd9Sstevel@tonic-gate 	static int n = 0;
125249f0e518Smarks 	acl_t *set_aclp;
12537c478bd9Sstevel@tonic-gate 	uint_t i;
12547c478bd9Sstevel@tonic-gate 	int saverr, j;
12557c478bd9Sstevel@tonic-gate 
12567c478bd9Sstevel@tonic-gate 	if (aclp == NULL) {
12577c478bd9Sstevel@tonic-gate 		if (aclent != NULL)
12587c478bd9Sstevel@tonic-gate 			free(aclent);
12597c478bd9Sstevel@tonic-gate 		aclent = NULL;
12607c478bd9Sstevel@tonic-gate 		n = 0;
12617c478bd9Sstevel@tonic-gate 		return;
12627c478bd9Sstevel@tonic-gate 	}
12637c478bd9Sstevel@tonic-gate 
12647c478bd9Sstevel@tonic-gate 	/*LINTED [aclp is malloc'd]*/
12657c478bd9Sstevel@tonic-gate 	diskacl = (ufs_acl_t *)aclp;
12667c478bd9Sstevel@tonic-gate 	/* LINTED: result fits in an int */
12677c478bd9Sstevel@tonic-gate 	j = size / sizeof (*diskacl);
12687c478bd9Sstevel@tonic-gate 	normacls(byteorder, diskacl, j);
12697c478bd9Sstevel@tonic-gate 
12707c478bd9Sstevel@tonic-gate 	i = n;
12717c478bd9Sstevel@tonic-gate 	n += j;
12727c478bd9Sstevel@tonic-gate 	aclent = realloc(aclent, n * (size_t)sizeof (*aclent));
12737c478bd9Sstevel@tonic-gate 	if (aclent == NULL) {
12747c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Cannot malloc acl list\n"));
12757c478bd9Sstevel@tonic-gate 		done(1);
12767c478bd9Sstevel@tonic-gate 	}
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 	j = 0;
12797c478bd9Sstevel@tonic-gate 	while (i < n) {
12807c478bd9Sstevel@tonic-gate 		aclent[i].a_type = diskacl[j].acl_tag;
12817c478bd9Sstevel@tonic-gate 		aclent[i].a_id = diskacl[j].acl_who;
12827c478bd9Sstevel@tonic-gate 		aclent[i].a_perm = diskacl[j].acl_perm;
12837c478bd9Sstevel@tonic-gate 		++i;
12847c478bd9Sstevel@tonic-gate 		++j;
12857c478bd9Sstevel@tonic-gate 	}
12867c478bd9Sstevel@tonic-gate 
128749f0e518Smarks 	set_aclp = acl_to_aclp(ACLENT_T, aclent, n);
128849f0e518Smarks 	if (set_aclp == NULL) {
128949f0e518Smarks 		(void) fprintf(stderr, gettext("Cannot build acl_t\n"));
129049f0e518Smarks 		done(1);
129149f0e518Smarks 	}
129249f0e518Smarks 
129349f0e518Smarks 	if (acl_set(name, set_aclp) == -1) {
12947c478bd9Sstevel@tonic-gate 		static int once = 0;
12957c478bd9Sstevel@tonic-gate 
12967c478bd9Sstevel@tonic-gate 		/*
12977c478bd9Sstevel@tonic-gate 		 * Treat some errors from the acl subsystem specially to
12987c478bd9Sstevel@tonic-gate 		 * avoid being too noisy:
12997c478bd9Sstevel@tonic-gate 		 *
13007c478bd9Sstevel@tonic-gate 		 * ENOSYS - ACLs not supported on this file system
13017c478bd9Sstevel@tonic-gate 		 * EPERM  - not the owner or not privileged
13027c478bd9Sstevel@tonic-gate 		 *
13037c478bd9Sstevel@tonic-gate 		 * The following is also supported for backwards compat.
13047c478bd9Sstevel@tonic-gate 		 * since acl(2) used to return the wrong errno:
13057c478bd9Sstevel@tonic-gate 		 *
13067c478bd9Sstevel@tonic-gate 		 * EINVAL - not the owner of the object
13077c478bd9Sstevel@tonic-gate 		 */
13087c478bd9Sstevel@tonic-gate 		if (errno == ENOSYS || errno == EPERM || errno == EINVAL) {
13097c478bd9Sstevel@tonic-gate 			if (once == 0) {
13107c478bd9Sstevel@tonic-gate 				saverr = errno;
13117c478bd9Sstevel@tonic-gate 				++once;
13127c478bd9Sstevel@tonic-gate 				fprintf(stderr,
13137c478bd9Sstevel@tonic-gate 				    gettext("setacl failed: %s\n"),
13147c478bd9Sstevel@tonic-gate 				    strerror(saverr));
13157c478bd9Sstevel@tonic-gate 			}
13167c478bd9Sstevel@tonic-gate 		} else {
13177c478bd9Sstevel@tonic-gate 			saverr = errno;
13187c478bd9Sstevel@tonic-gate 			fprintf(stderr, gettext("setacl on %s failed: %s\n"),
13197c478bd9Sstevel@tonic-gate 			    name, strerror(saverr));
13207c478bd9Sstevel@tonic-gate 		}
13217c478bd9Sstevel@tonic-gate 	}
132249f0e518Smarks 	acl_free(set_aclp);
13237c478bd9Sstevel@tonic-gate }
13247c478bd9Sstevel@tonic-gate 
13257c478bd9Sstevel@tonic-gate static struct fsdtypes {
13267c478bd9Sstevel@tonic-gate 	int type;
13277c478bd9Sstevel@tonic-gate 	void (*function)();
13287c478bd9Sstevel@tonic-gate } fsdtypes[] = {
13297c478bd9Sstevel@tonic-gate 	{FSD_ACL, fsd_acl},
13307c478bd9Sstevel@tonic-gate 	{FSD_DFACL, fsd_acl},
13317c478bd9Sstevel@tonic-gate 	{0, NULL}
13327c478bd9Sstevel@tonic-gate };
13337c478bd9Sstevel@tonic-gate 
13347c478bd9Sstevel@tonic-gate void
metaproc(char * name,char * mdata,size_t msize)1335fe0e7ec4Smaheshvs metaproc(char *name, char *mdata, size_t msize)
13367c478bd9Sstevel@tonic-gate {
13377c478bd9Sstevel@tonic-gate 	struct fsdtypes *fsdtype;
13387c478bd9Sstevel@tonic-gate 	ufs_fsd_t *fsd;
13397c478bd9Sstevel@tonic-gate 	char *c;
13407c478bd9Sstevel@tonic-gate 
13417c478bd9Sstevel@tonic-gate 	/*
13427c478bd9Sstevel@tonic-gate 	 * for the whole shadow inode, dispatch each piece
13437c478bd9Sstevel@tonic-gate 	 * to the appropriate function.
13447c478bd9Sstevel@tonic-gate 	 */
13457c478bd9Sstevel@tonic-gate 	c = mdata;
13467c478bd9Sstevel@tonic-gate 	/* LINTED (c - mdata) fits into a size_t */
13477c478bd9Sstevel@tonic-gate 	while ((size_t)(c - mdata) < msize) {
13487c478bd9Sstevel@tonic-gate 		/*LINTED [mdata is malloc'd]*/
13497c478bd9Sstevel@tonic-gate 		fsd = (ufs_fsd_t *)c;
13507c478bd9Sstevel@tonic-gate 		assert((fsd->fsd_size % 4) == 0);
13517c478bd9Sstevel@tonic-gate 		/* LINTED: lint thinks pointers are signed */
13527c478bd9Sstevel@tonic-gate 		c += FSD_RECSZ(fsd, fsd->fsd_size);
13537c478bd9Sstevel@tonic-gate 		if ((fsd->fsd_type == FSD_FREE) ||
13547c478bd9Sstevel@tonic-gate 		    ((unsigned)(fsd->fsd_size) <= sizeof (ufs_fsd_t)) ||
13557c478bd9Sstevel@tonic-gate 		    (c > (mdata + msize)))
13567c478bd9Sstevel@tonic-gate 			break;
13577c478bd9Sstevel@tonic-gate 		for (fsdtype = fsdtypes; fsdtype->type; fsdtype++)
13587c478bd9Sstevel@tonic-gate 			if (fsdtype->type == fsd->fsd_type)
13597c478bd9Sstevel@tonic-gate 				(*fsdtype->function)(name, fsd->fsd_data,
13607c478bd9Sstevel@tonic-gate 				    (unsigned)(fsd->fsd_size) -
13617c478bd9Sstevel@tonic-gate 				    sizeof (fsd->fsd_type) -
13627c478bd9Sstevel@tonic-gate 				    sizeof (fsd->fsd_size));
13637c478bd9Sstevel@tonic-gate 		/* ^^^ be sure to change if fsd ever changes ^^^ */
13647c478bd9Sstevel@tonic-gate 	}
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 	/* reset the state of all the functions */
13677c478bd9Sstevel@tonic-gate 	for (fsdtype = fsdtypes; fsdtype->type; fsdtype++)
13687c478bd9Sstevel@tonic-gate 		(*fsdtype->function)(NULL, NULL, 0);
13697c478bd9Sstevel@tonic-gate }
13707c478bd9Sstevel@tonic-gate 
13717c478bd9Sstevel@tonic-gate static void
xtrlnkfile(char * buf,size_t size)1372fe0e7ec4Smaheshvs xtrlnkfile(char *buf, size_t size)
13737c478bd9Sstevel@tonic-gate {
13747c478bd9Sstevel@tonic-gate 	/* LINTED: signed/unsigned mix ok */
13757c478bd9Sstevel@tonic-gate 	pathlen += size;
13767c478bd9Sstevel@tonic-gate 	if (pathlen > MAXPATHLEN) {
13777c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
13787c478bd9Sstevel@tonic-gate 		    gettext("symbolic link name: %s->%s%s; too long %d\n"),
13797c478bd9Sstevel@tonic-gate 		    curfile.name, lnkbuf, buf, pathlen);
13807c478bd9Sstevel@tonic-gate 		done(1);
13817c478bd9Sstevel@tonic-gate 	}
13827c478bd9Sstevel@tonic-gate 	buf[size] = '\0';
13837c478bd9Sstevel@tonic-gate 	(void) strcat(lnkbuf, buf);
13847c478bd9Sstevel@tonic-gate 	/* add an extra NULL to make this a legal complex string */
13857c478bd9Sstevel@tonic-gate 	lnkbuf[pathlen+1] = '\0';
13867c478bd9Sstevel@tonic-gate }
13877c478bd9Sstevel@tonic-gate 
13887c478bd9Sstevel@tonic-gate /*ARGSUSED*/
13897c478bd9Sstevel@tonic-gate static void
xtrlnkskip(char * buf,size_t size)1390fe0e7ec4Smaheshvs xtrlnkskip(char *buf, size_t size)
13917c478bd9Sstevel@tonic-gate {
13927c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
13937c478bd9Sstevel@tonic-gate 	    gettext("unallocated block in symbolic link %s\n"),
13947c478bd9Sstevel@tonic-gate 	    curfile.name);
13957c478bd9Sstevel@tonic-gate 	done(1);
13967c478bd9Sstevel@tonic-gate }
13977c478bd9Sstevel@tonic-gate 
13987c478bd9Sstevel@tonic-gate static void
xtrmap(char * buf,size_t size)1399fe0e7ec4Smaheshvs xtrmap(char *buf, size_t size)
14007c478bd9Sstevel@tonic-gate {
14017c478bd9Sstevel@tonic-gate 	if ((map+size) > endmap) {
14027c478bd9Sstevel@tonic-gate 		int64_t mapsize, increment;
14037c478bd9Sstevel@tonic-gate 		int64_t diff;
14047c478bd9Sstevel@tonic-gate 
14057c478bd9Sstevel@tonic-gate 		if (spcl.c_type != TS_ADDR) {
14067c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
14077c478bd9Sstevel@tonic-gate 			    gettext("xtrmap: current record not TS_ADDR\n"));
14087c478bd9Sstevel@tonic-gate 			done(1);
14097c478bd9Sstevel@tonic-gate 		}
14107c478bd9Sstevel@tonic-gate 		if ((spcl.c_count < 0) || (spcl.c_count > TP_NINDIR)) {
14117c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
14127c478bd9Sstevel@tonic-gate 			    gettext("xtrmap: illegal c_count field (%d)\n"),
14137c478bd9Sstevel@tonic-gate 			    spcl.c_count);
14147c478bd9Sstevel@tonic-gate 			done(1);
14157c478bd9Sstevel@tonic-gate 		}
14167c478bd9Sstevel@tonic-gate 
14177c478bd9Sstevel@tonic-gate 		increment = d_howmany(
14187c478bd9Sstevel@tonic-gate 		    ((spcl.c_count * tp_bsize * NBBY) + 1), NBBY);
14197c478bd9Sstevel@tonic-gate 		mapsize = endmap - beginmap + increment;
14207c478bd9Sstevel@tonic-gate 		if (mapsize > UINT_MAX) {
14217c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
14227c478bd9Sstevel@tonic-gate 			    gettext("xtrmap: maximum bitmap size exceeded"));
14237c478bd9Sstevel@tonic-gate 			done(1);
14247c478bd9Sstevel@tonic-gate 		}
14257c478bd9Sstevel@tonic-gate 
14267c478bd9Sstevel@tonic-gate 		diff = map - beginmap;
14277c478bd9Sstevel@tonic-gate 		/* LINTED mapsize checked above */
14287c478bd9Sstevel@tonic-gate 		beginmap = realloc(beginmap, (size_t)mapsize);
14297c478bd9Sstevel@tonic-gate 		if (beginmap == NULL) {
14307c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
14317c478bd9Sstevel@tonic-gate 			    gettext("xtrmap: realloc failed\n"));
14327c478bd9Sstevel@tonic-gate 			done(1);
14337c478bd9Sstevel@tonic-gate 		}
14347c478bd9Sstevel@tonic-gate 		map = beginmap + diff;
14357c478bd9Sstevel@tonic-gate 		endmap = beginmap + mapsize;
14367c478bd9Sstevel@tonic-gate 		/* LINTED endmap - map cannot exceed 32 bits */
14377c478bd9Sstevel@tonic-gate 		bzero(map, (size_t)(endmap - map));
14387c478bd9Sstevel@tonic-gate 		maxino = NBBY * mapsize + 1;
14397c478bd9Sstevel@tonic-gate 	}
14407c478bd9Sstevel@tonic-gate 
14417c478bd9Sstevel@tonic-gate 	bcopy(buf, map, size);
14427c478bd9Sstevel@tonic-gate 	/* LINTED character pointers aren't signed */
14437c478bd9Sstevel@tonic-gate 	map += size;
14447c478bd9Sstevel@tonic-gate }
14457c478bd9Sstevel@tonic-gate 
14467c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14477c478bd9Sstevel@tonic-gate static void
xtrmapskip(char * buf,size_t size)1448fe0e7ec4Smaheshvs xtrmapskip(char *buf, size_t size)
14497c478bd9Sstevel@tonic-gate {
14507c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("hole in map\n"));
14517c478bd9Sstevel@tonic-gate 	done(1);
14527c478bd9Sstevel@tonic-gate }
14537c478bd9Sstevel@tonic-gate 
14547c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14557c478bd9Sstevel@tonic-gate void
null(char * buf,size_t size)1456fe0e7ec4Smaheshvs null(char *buf, size_t size)
14577c478bd9Sstevel@tonic-gate {
14587c478bd9Sstevel@tonic-gate }
14597c478bd9Sstevel@tonic-gate 
14607c478bd9Sstevel@tonic-gate /*
14617c478bd9Sstevel@tonic-gate  * Do the tape i/o, dealing with volume changes
14627c478bd9Sstevel@tonic-gate  * etc..
14637c478bd9Sstevel@tonic-gate  */
14647c478bd9Sstevel@tonic-gate static void
readtape(char * b)1465fe0e7ec4Smaheshvs readtape(char *b)
14667c478bd9Sstevel@tonic-gate {
14677c478bd9Sstevel@tonic-gate 	int i;
14687c478bd9Sstevel@tonic-gate 	int rd, newvol;
14697c478bd9Sstevel@tonic-gate 	int cnt;
14707c478bd9Sstevel@tonic-gate 	struct s_spcl *sp;
14717c478bd9Sstevel@tonic-gate 	int32_t	expected_magic;
14727c478bd9Sstevel@tonic-gate 
14737c478bd9Sstevel@tonic-gate 	if (tbf == NULL) {
14747c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
14757c478bd9Sstevel@tonic-gate 		    "Internal consistency failure in readtape: tbf is NULL\n"));
14767c478bd9Sstevel@tonic-gate 		done(1);
14777c478bd9Sstevel@tonic-gate 	}
14787c478bd9Sstevel@tonic-gate 	expected_magic = ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC);
14797c478bd9Sstevel@tonic-gate 
14807c478bd9Sstevel@tonic-gate top:
14817c478bd9Sstevel@tonic-gate 	if (bct < numtrec) {
14827c478bd9Sstevel@tonic-gate 		/*
14837c478bd9Sstevel@tonic-gate 		 * check for old-dump floppy EOM -- it may appear in
14847c478bd9Sstevel@tonic-gate 		 * the middle of a buffer.  The Dflag used to be used for
14857c478bd9Sstevel@tonic-gate 		 * this, but since it doesn't hurt to always do this we
14867c478bd9Sstevel@tonic-gate 		 * got rid of the Dflag.
14877c478bd9Sstevel@tonic-gate 		 */
14887c478bd9Sstevel@tonic-gate 		/*LINTED [tbf = malloc()]*/
14897c478bd9Sstevel@tonic-gate 		sp = &((union u_spcl *)&tbf[bct*tp_bsize])->s_spcl;
14907c478bd9Sstevel@tonic-gate 		if (sp->c_magic == expected_magic && sp->c_type == TS_EOM &&
14917c478bd9Sstevel@tonic-gate 		    (time_t)(sp->c_date) == dumpdate &&
14927c478bd9Sstevel@tonic-gate 		    (time_t)(sp->c_ddate) == dumptime) {
14937c478bd9Sstevel@tonic-gate 			for (i = 0; i < ntrec; i++)
14947c478bd9Sstevel@tonic-gate 				/*LINTED [tbf = malloc()]*/
14957c478bd9Sstevel@tonic-gate 				((struct s_spcl *)
14967c478bd9Sstevel@tonic-gate 				    &tbf[i*tp_bsize])->c_magic = 0;
14977c478bd9Sstevel@tonic-gate 			bct = 0;
14987c478bd9Sstevel@tonic-gate 			rd = 0;
14997c478bd9Sstevel@tonic-gate 			i = 0;
15007c478bd9Sstevel@tonic-gate 			goto nextvol;
15017c478bd9Sstevel@tonic-gate 		}
15027c478bd9Sstevel@tonic-gate 		bcopy(&tbf[(bct++*tp_bsize)], b, (size_t)tp_bsize);
15037c478bd9Sstevel@tonic-gate 		blksread++;
15047c478bd9Sstevel@tonic-gate 		tapea++;
15057c478bd9Sstevel@tonic-gate 		return;
15067c478bd9Sstevel@tonic-gate 	}
15077c478bd9Sstevel@tonic-gate 	/*LINTED [assertion always true]*/
15087c478bd9Sstevel@tonic-gate 	assert(sizeof (union u_spcl) == TP_BSIZE_MAX);
15097c478bd9Sstevel@tonic-gate 	for (i = 0; i < ntrec; i++)
15107c478bd9Sstevel@tonic-gate 		/*LINTED [tbf = malloc()]*/
15117c478bd9Sstevel@tonic-gate 		((struct s_spcl *)&tbf[i*sizeof (struct s_spcl)])->c_magic = 0;
15127c478bd9Sstevel@tonic-gate 	if (numtrec == 0) {
15137c478bd9Sstevel@tonic-gate 		/* LINTED unsigned/signed assignment ok */
15147c478bd9Sstevel@tonic-gate 		numtrec = ntrec;
15157c478bd9Sstevel@tonic-gate 	}
15167c478bd9Sstevel@tonic-gate 	/* LINTED unsigned/signed assignment ok */
15177c478bd9Sstevel@tonic-gate 	cnt = ntrec*tp_bsize;
15187c478bd9Sstevel@tonic-gate 	rd = 0;
15197c478bd9Sstevel@tonic-gate getmore:
15207c478bd9Sstevel@tonic-gate 	if (host)
15217c478bd9Sstevel@tonic-gate 		i = rmtread(&tbf[rd], cnt);
15227c478bd9Sstevel@tonic-gate 	else
15237c478bd9Sstevel@tonic-gate 		i = read(mt, &tbf[rd], cnt);
15247c478bd9Sstevel@tonic-gate 	/*
15257c478bd9Sstevel@tonic-gate 	 * Check for mid-tape short read error.
15267c478bd9Sstevel@tonic-gate 	 * If found, return rest of buffer.
15277c478bd9Sstevel@tonic-gate 	 */
15287c478bd9Sstevel@tonic-gate 	if (numtrec < ntrec && i != 0) {
15297c478bd9Sstevel@tonic-gate 		/* LINTED unsigned/signed assignment ok */
15307c478bd9Sstevel@tonic-gate 		numtrec = ntrec;
15317c478bd9Sstevel@tonic-gate 		goto top;
15327c478bd9Sstevel@tonic-gate 	}
15337c478bd9Sstevel@tonic-gate 	/*
15347c478bd9Sstevel@tonic-gate 	 * Handle partial block read.
15357c478bd9Sstevel@tonic-gate 	 */
15367c478bd9Sstevel@tonic-gate 	if (i > 0 && i != ntrec*tp_bsize) {
15377c478bd9Sstevel@tonic-gate 		if (pipein) {
15387c478bd9Sstevel@tonic-gate 			rd += i;
15397c478bd9Sstevel@tonic-gate 			cnt -= i;
15407c478bd9Sstevel@tonic-gate 			if (cnt > 0)
15417c478bd9Sstevel@tonic-gate 				goto getmore;
15427c478bd9Sstevel@tonic-gate 			i = rd;
15437c478bd9Sstevel@tonic-gate 		} else {
15447c478bd9Sstevel@tonic-gate 			if (i % tp_bsize != 0)
15457c478bd9Sstevel@tonic-gate 				panic(gettext(
15467c478bd9Sstevel@tonic-gate 				    "partial block read: %d should be %d\n"),
15477c478bd9Sstevel@tonic-gate 				    i, ntrec * tp_bsize);
15487c478bd9Sstevel@tonic-gate 			numtrec = i / tp_bsize;
15497c478bd9Sstevel@tonic-gate 			if (numtrec == 0)
15507c478bd9Sstevel@tonic-gate 				/*
15517c478bd9Sstevel@tonic-gate 				 * it's possible to read only 512 bytes
15527c478bd9Sstevel@tonic-gate 				 * from a QIC device...
15537c478bd9Sstevel@tonic-gate 				 */
15547c478bd9Sstevel@tonic-gate 				i = 0;
15557c478bd9Sstevel@tonic-gate 		}
15567c478bd9Sstevel@tonic-gate 	}
15577c478bd9Sstevel@tonic-gate 	/*
15587c478bd9Sstevel@tonic-gate 	 * Handle read error.
15597c478bd9Sstevel@tonic-gate 	 */
15607c478bd9Sstevel@tonic-gate 	if (i < 0) {
15617c478bd9Sstevel@tonic-gate 		switch (curfile.action) {
15627c478bd9Sstevel@tonic-gate 		default:
15637c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
15647c478bd9Sstevel@tonic-gate 			    "Read error while trying to set up volume\n"));
15657c478bd9Sstevel@tonic-gate 			break;
15667c478bd9Sstevel@tonic-gate 		case UNKNOWN:
15677c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
15687c478bd9Sstevel@tonic-gate 			    "Read error while trying to resynchronize\n"));
15697c478bd9Sstevel@tonic-gate 			break;
15707c478bd9Sstevel@tonic-gate 		case USING:
15717c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
15727c478bd9Sstevel@tonic-gate 			    "Read error while restoring %s\n"),
15737c478bd9Sstevel@tonic-gate 			    curfile.name);
15747c478bd9Sstevel@tonic-gate 			break;
15757c478bd9Sstevel@tonic-gate 		case SKIP:
15767c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
15777c478bd9Sstevel@tonic-gate 			    "Read error while skipping over inode %d\n"),
15787c478bd9Sstevel@tonic-gate 			    curfile.ino);
15797c478bd9Sstevel@tonic-gate 			break;
15807c478bd9Sstevel@tonic-gate 		}
15817c478bd9Sstevel@tonic-gate 		if (!yflag && !reply(gettext("continue")))
15827c478bd9Sstevel@tonic-gate 			done(1);
15837c478bd9Sstevel@tonic-gate 		/* LINTED: unsigned->signed conversion ok */
15847c478bd9Sstevel@tonic-gate 		i = (int)(ntrec*tp_bsize);
15857c478bd9Sstevel@tonic-gate 		bzero(tbf, (size_t)i);
15867c478bd9Sstevel@tonic-gate 		if ((host != 0 && rmtseek(i, 1) < 0) ||
15877c478bd9Sstevel@tonic-gate 		    (host == 0 && (lseek64(mt, (offset_t)i, 1) ==
15887c478bd9Sstevel@tonic-gate 		    (off64_t)-1))) {
15897c478bd9Sstevel@tonic-gate 			perror(gettext("continuation failed"));
15907c478bd9Sstevel@tonic-gate 			done(1);
15917c478bd9Sstevel@tonic-gate 		}
15927c478bd9Sstevel@tonic-gate 	}
15937c478bd9Sstevel@tonic-gate 	/*
15947c478bd9Sstevel@tonic-gate 	 * Handle end of tape.  The Dflag used to be used, but since it doesn't
15957c478bd9Sstevel@tonic-gate 	 * hurt to always check we got rid if it.
15967c478bd9Sstevel@tonic-gate 	 */
15977c478bd9Sstevel@tonic-gate 
15987c478bd9Sstevel@tonic-gate 	/*
15997c478bd9Sstevel@tonic-gate 	 * if the first record in the buffer just read is EOM,
16007c478bd9Sstevel@tonic-gate 	 * change volumes.
16017c478bd9Sstevel@tonic-gate 	 */
16027c478bd9Sstevel@tonic-gate 	/*LINTED [tbf = malloc()]*/
16037c478bd9Sstevel@tonic-gate 	sp = &((union u_spcl *)tbf)->s_spcl;
16047c478bd9Sstevel@tonic-gate 	if (i != 0 && sp->c_magic == expected_magic && sp->c_type == TS_EOM &&
16057c478bd9Sstevel@tonic-gate 	    (time_t)(sp->c_date) == dumpdate &&
16067c478bd9Sstevel@tonic-gate 	    (time_t)(sp->c_ddate) == dumptime) {
16077c478bd9Sstevel@tonic-gate 		i = 0;
16087c478bd9Sstevel@tonic-gate 	}
16097c478bd9Sstevel@tonic-gate nextvol:
16107c478bd9Sstevel@tonic-gate 	if (i == 0) {
16117c478bd9Sstevel@tonic-gate 		if (!pipein) {
16127c478bd9Sstevel@tonic-gate 			newvol = volno + 1;
16137c478bd9Sstevel@tonic-gate 			volno = 0;
16147c478bd9Sstevel@tonic-gate 			numtrec = 0;
16157c478bd9Sstevel@tonic-gate 			getvol(newvol);
16167c478bd9Sstevel@tonic-gate 			readtape(b); /* XXX tail recursion, not goto top? */
16177c478bd9Sstevel@tonic-gate 			return;
16187c478bd9Sstevel@tonic-gate 		}
16197c478bd9Sstevel@tonic-gate 		/* XXX if panic returns, should we round rd up? */
16207c478bd9Sstevel@tonic-gate 		/* XXX if we do, then we should zero the intervening space */
16217c478bd9Sstevel@tonic-gate 		if (rd % tp_bsize != 0)
16227c478bd9Sstevel@tonic-gate 			panic(gettext("partial block read: %d should be %d\n"),
16237c478bd9Sstevel@tonic-gate 			    rd, ntrec * tp_bsize);
16247c478bd9Sstevel@tonic-gate 		bcopy((char *)&endoftapemark, &tbf[rd], (size_t)tp_bsize);
16257c478bd9Sstevel@tonic-gate 	}
16267c478bd9Sstevel@tonic-gate 	bct = 0;
16277c478bd9Sstevel@tonic-gate 	bcopy(&tbf[(bct++*tp_bsize)], b, (size_t)tp_bsize);
16287c478bd9Sstevel@tonic-gate 	blksread++;
16297c478bd9Sstevel@tonic-gate 	recsread++;
16307c478bd9Sstevel@tonic-gate 	tapea++;
16317c478bd9Sstevel@tonic-gate 	rec_position++;
16327c478bd9Sstevel@tonic-gate }
16337c478bd9Sstevel@tonic-gate 
16347c478bd9Sstevel@tonic-gate void
findtapeblksize(int arfile)16357c478bd9Sstevel@tonic-gate findtapeblksize(int arfile)
16367c478bd9Sstevel@tonic-gate {
16377c478bd9Sstevel@tonic-gate 	int	i;
16387c478bd9Sstevel@tonic-gate 
16397c478bd9Sstevel@tonic-gate 	if (tbf == NULL) {
16407c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
16417c478bd9Sstevel@tonic-gate 		    "Internal consistency failure in findtapeblksize: "
16427c478bd9Sstevel@tonic-gate 		    "tbf is NULL\n"));
16437c478bd9Sstevel@tonic-gate 		assert(tbf != NULL);
16447c478bd9Sstevel@tonic-gate 		done(1);
16457c478bd9Sstevel@tonic-gate 	}
16467c478bd9Sstevel@tonic-gate 
16477c478bd9Sstevel@tonic-gate 	for (i = 0; i < ntrec; i++)
16487c478bd9Sstevel@tonic-gate 		/*LINTED [tbf = malloc()]*/
16497c478bd9Sstevel@tonic-gate 		((struct s_spcl *)&tbf[i * tp_bsize])->c_magic = 0;
16507c478bd9Sstevel@tonic-gate 	bct = 0;
16517c478bd9Sstevel@tonic-gate 	if (host && arfile == TAPE_FILE)
16527c478bd9Sstevel@tonic-gate 		tape_rec_size = rmtread(tbf, ntrec * tp_bsize);
16537c478bd9Sstevel@tonic-gate 	else
16547c478bd9Sstevel@tonic-gate 		tape_rec_size = read(mt, tbf, ntrec * tp_bsize);
16557c478bd9Sstevel@tonic-gate 	recsread++;
16567c478bd9Sstevel@tonic-gate 	rec_position++;
16577c478bd9Sstevel@tonic-gate 	if (tape_rec_size == (ssize_t)-1) {
16587c478bd9Sstevel@tonic-gate 		int saverr = errno;
16597c478bd9Sstevel@tonic-gate 		char *errmsg = gettext("Media read error");
16607c478bd9Sstevel@tonic-gate 		errno = saverr;
16617c478bd9Sstevel@tonic-gate 		perror(errmsg);
16627c478bd9Sstevel@tonic-gate 		done(1);
16637c478bd9Sstevel@tonic-gate 	}
16647c478bd9Sstevel@tonic-gate 	if (tape_rec_size % tp_bsize != 0) {
16657c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
16667c478bd9Sstevel@tonic-gate 	    "Record size (%d) is not a multiple of dump block size (%d)\n"),
16677c478bd9Sstevel@tonic-gate 		    tape_rec_size, tp_bsize);
16687c478bd9Sstevel@tonic-gate 		done(1);
16697c478bd9Sstevel@tonic-gate 	}
16707c478bd9Sstevel@tonic-gate 	ntrec = (int)tape_rec_size / tp_bsize;
16717c478bd9Sstevel@tonic-gate 	/* LINTED unsigned/signed assignment ok */
16727c478bd9Sstevel@tonic-gate 	numtrec = ntrec;
16737c478bd9Sstevel@tonic-gate 	vprintf(stdout, gettext("Media block size is %d\n"), ntrec*2);
16747c478bd9Sstevel@tonic-gate }
16757c478bd9Sstevel@tonic-gate 
16767c478bd9Sstevel@tonic-gate void
flsht(void)16777c478bd9Sstevel@tonic-gate flsht(void)
16787c478bd9Sstevel@tonic-gate {
16797c478bd9Sstevel@tonic-gate 	/* LINTED unsigned/signed assignment ok */
16807c478bd9Sstevel@tonic-gate 	bct = ntrec+1;
16817c478bd9Sstevel@tonic-gate }
16827c478bd9Sstevel@tonic-gate 
16837c478bd9Sstevel@tonic-gate void
closemt(int mode)168433a5e6b2Srm88369 closemt(int mode)
16857c478bd9Sstevel@tonic-gate {
168633a5e6b2Srm88369 	/*
168733a5e6b2Srm88369 	 * If mode == FORCE_OFFLINE then we're not done but
168833a5e6b2Srm88369 	 * we need to change tape. So, rewind and unload current
168933a5e6b2Srm88369 	 * tape before loading the new one.
169033a5e6b2Srm88369 	 */
169133a5e6b2Srm88369 
16927c478bd9Sstevel@tonic-gate 	static struct mtop mtop = { MTOFFL, 0 };
16937c478bd9Sstevel@tonic-gate 
16947c478bd9Sstevel@tonic-gate 	if (mt < 0)
16957c478bd9Sstevel@tonic-gate 		return;
169633a5e6b2Srm88369 	if (offline || mode == FORCE_OFFLINE)
16977c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Rewinding tape\n"));
16987c478bd9Sstevel@tonic-gate 	if (host) {
169933a5e6b2Srm88369 		if (offline || mode == FORCE_OFFLINE)
17007c478bd9Sstevel@tonic-gate 			(void) rmtioctl(MTOFFL, 1);
17017c478bd9Sstevel@tonic-gate 		rmtclose();
17027c478bd9Sstevel@tonic-gate 	} else if (pipein) {
17037c478bd9Sstevel@tonic-gate 		char buffy[MAXBSIZE];
17047c478bd9Sstevel@tonic-gate 
17057c478bd9Sstevel@tonic-gate 		while (read(mt, buffy, sizeof (buffy)) > 0) {
17067c478bd9Sstevel@tonic-gate 			continue;
17077c478bd9Sstevel@tonic-gate 			/*LINTED [assertion always true]*/
17087c478bd9Sstevel@tonic-gate 		}
17097c478bd9Sstevel@tonic-gate 		(void) close(mt);
17107c478bd9Sstevel@tonic-gate 	} else {
17117c478bd9Sstevel@tonic-gate 		/*
17127c478bd9Sstevel@tonic-gate 		 * Only way to tell if this is a floppy is to issue an ioctl
17137c478bd9Sstevel@tonic-gate 		 * but why waste one - if the eject fails, tough!
17147c478bd9Sstevel@tonic-gate 		 */
171533a5e6b2Srm88369 		if (offline || mode == FORCE_OFFLINE)
17167c478bd9Sstevel@tonic-gate 			(void) ioctl(mt, MTIOCTOP, &mtop);
17177c478bd9Sstevel@tonic-gate 		(void) ioctl(mt, FDEJECT, 0);
17187c478bd9Sstevel@tonic-gate 		(void) close(mt);
17197c478bd9Sstevel@tonic-gate 	}
17207c478bd9Sstevel@tonic-gate 	mt = -1;
17217c478bd9Sstevel@tonic-gate }
17227c478bd9Sstevel@tonic-gate 
17237c478bd9Sstevel@tonic-gate static int
checkvol(struct s_spcl * b,int t)1724fe0e7ec4Smaheshvs checkvol(struct s_spcl *b, int t)
17257c478bd9Sstevel@tonic-gate {
17267c478bd9Sstevel@tonic-gate 
17277c478bd9Sstevel@tonic-gate 	if (b->c_volume != t)
17287c478bd9Sstevel@tonic-gate 		return (FAIL);
17297c478bd9Sstevel@tonic-gate 	return (GOOD);
17307c478bd9Sstevel@tonic-gate }
17317c478bd9Sstevel@tonic-gate 
1732fe0e7ec4Smaheshvs int
readhdr(struct s_spcl * b)1733fe0e7ec4Smaheshvs readhdr(struct s_spcl *b)
17347c478bd9Sstevel@tonic-gate {
17357c478bd9Sstevel@tonic-gate 
17367c478bd9Sstevel@tonic-gate 	if (gethead(b) == FAIL) {
17377c478bd9Sstevel@tonic-gate 		dprintf(stdout, gettext("readhdr fails at %ld blocks\n"),
17387c478bd9Sstevel@tonic-gate 		    blksread);
17397c478bd9Sstevel@tonic-gate 		return (FAIL);
17407c478bd9Sstevel@tonic-gate 	}
17417c478bd9Sstevel@tonic-gate 	return (GOOD);
17427c478bd9Sstevel@tonic-gate }
17437c478bd9Sstevel@tonic-gate 
17447c478bd9Sstevel@tonic-gate /*
17457c478bd9Sstevel@tonic-gate  * read the tape into buf, then return whether or
17467c478bd9Sstevel@tonic-gate  * or not it is a header block.
17477c478bd9Sstevel@tonic-gate  */
1748fe0e7ec4Smaheshvs int
gethead(struct s_spcl * buf)1749fe0e7ec4Smaheshvs gethead(struct s_spcl *buf)
17507c478bd9Sstevel@tonic-gate {
17517c478bd9Sstevel@tonic-gate 	int i;
17527c478bd9Sstevel@tonic-gate 	union u_ospcl {
17537c478bd9Sstevel@tonic-gate 		char dummy[TP_BSIZE_MIN];
17547c478bd9Sstevel@tonic-gate 		struct	s_ospcl {
17557c478bd9Sstevel@tonic-gate 			int32_t	c_type;
17567c478bd9Sstevel@tonic-gate 			int32_t	c_date;
17577c478bd9Sstevel@tonic-gate 			int32_t	c_ddate;
17587c478bd9Sstevel@tonic-gate 			int32_t	c_volume;
17597c478bd9Sstevel@tonic-gate 			int32_t	c_tapea;
17607c478bd9Sstevel@tonic-gate 			ushort_t c_inumber;
17617c478bd9Sstevel@tonic-gate 			int32_t	c_magic;
17627c478bd9Sstevel@tonic-gate 			int32_t	c_checksum;
17637c478bd9Sstevel@tonic-gate 			struct odinode {
17647c478bd9Sstevel@tonic-gate 				unsigned short odi_mode;
17657c478bd9Sstevel@tonic-gate 				ushort_t odi_nlink;
17667c478bd9Sstevel@tonic-gate 				ushort_t odi_uid;
17677c478bd9Sstevel@tonic-gate 				ushort_t odi_gid;
17687c478bd9Sstevel@tonic-gate 				int32_t	odi_size;
17697c478bd9Sstevel@tonic-gate 				int32_t	odi_rdev;
17707c478bd9Sstevel@tonic-gate 				char	odi_addr[36];
17717c478bd9Sstevel@tonic-gate 				int32_t	odi_atime;
17727c478bd9Sstevel@tonic-gate 				int32_t	odi_mtime;
17737c478bd9Sstevel@tonic-gate 				int32_t	odi_ctime;
17747c478bd9Sstevel@tonic-gate 			} c_dinode;
17757c478bd9Sstevel@tonic-gate 			int32_t	c_count;
17767c478bd9Sstevel@tonic-gate 			char	c_baddr[256];
17777c478bd9Sstevel@tonic-gate 		} s_ospcl;
17787c478bd9Sstevel@tonic-gate 	} u_ospcl;
17797c478bd9Sstevel@tonic-gate 
17807c478bd9Sstevel@tonic-gate 	if (cvtflag) {
17817c478bd9Sstevel@tonic-gate 		readtape((char *)(&u_ospcl.s_ospcl));
17827c478bd9Sstevel@tonic-gate 		bzero((char *)buf, (size_t)TP_BSIZE_MIN);
17837c478bd9Sstevel@tonic-gate 		buf->c_type = u_ospcl.s_ospcl.c_type;
17847c478bd9Sstevel@tonic-gate 		buf->c_date = u_ospcl.s_ospcl.c_date;
17857c478bd9Sstevel@tonic-gate 		buf->c_ddate = u_ospcl.s_ospcl.c_ddate;
17867c478bd9Sstevel@tonic-gate 		buf->c_volume = u_ospcl.s_ospcl.c_volume;
17877c478bd9Sstevel@tonic-gate 		buf->c_tapea = u_ospcl.s_ospcl.c_tapea;
17887c478bd9Sstevel@tonic-gate 		buf->c_inumber = u_ospcl.s_ospcl.c_inumber;
17897c478bd9Sstevel@tonic-gate 		buf->c_checksum = u_ospcl.s_ospcl.c_checksum;
17907c478bd9Sstevel@tonic-gate 		buf->c_magic = u_ospcl.s_ospcl.c_magic;
17917c478bd9Sstevel@tonic-gate 		buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode;
17927c478bd9Sstevel@tonic-gate 		/* LINTED: unsigned/signed combination ok */
17937c478bd9Sstevel@tonic-gate 		buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink;
17947c478bd9Sstevel@tonic-gate 		buf->c_dinode.di_size =
17957c478bd9Sstevel@tonic-gate 		    (unsigned)(u_ospcl.s_ospcl.c_dinode.odi_size);
17967c478bd9Sstevel@tonic-gate 		buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid;
17977c478bd9Sstevel@tonic-gate 		buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid;
17987c478bd9Sstevel@tonic-gate 		buf->c_dinode.di_suid = UID_LONG;
17997c478bd9Sstevel@tonic-gate 		buf->c_dinode.di_sgid = GID_LONG;
18007c478bd9Sstevel@tonic-gate 		buf->c_dinode.di_ordev = u_ospcl.s_ospcl.c_dinode.odi_rdev;
18017c478bd9Sstevel@tonic-gate 		buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime;
18027c478bd9Sstevel@tonic-gate 		buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime;
18037c478bd9Sstevel@tonic-gate 		buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime;
18047c478bd9Sstevel@tonic-gate 		buf->c_count = u_ospcl.s_ospcl.c_count;
18057c478bd9Sstevel@tonic-gate 		bcopy(u_ospcl.s_ospcl.c_baddr, buf->c_addr,
18067c478bd9Sstevel@tonic-gate 		    sizeof (u_ospcl.s_ospcl.c_baddr));
18077c478bd9Sstevel@tonic-gate 
18087c478bd9Sstevel@tonic-gate 		/*CONSTANTCONDITION*/
18097c478bd9Sstevel@tonic-gate 		assert(sizeof (u_ospcl.s_ospcl) < sizeof (union u_spcl));
18107c478bd9Sstevel@tonic-gate 
18117c478bd9Sstevel@tonic-gate 		/* we byte-swap the new spclrec, but checksum the old	*/
18127c478bd9Sstevel@tonic-gate 		/* (see comments in normspcl())				*/
18137c478bd9Sstevel@tonic-gate 		if (normspcl(byteorder, buf,
18147c478bd9Sstevel@tonic-gate 		    (int *)(&u_ospcl.s_ospcl), sizeof (u_ospcl.s_ospcl),
18157c478bd9Sstevel@tonic-gate 		    OFS_MAGIC))
18167c478bd9Sstevel@tonic-gate 			return (FAIL);
18177c478bd9Sstevel@tonic-gate 		buf->c_magic =
18187c478bd9Sstevel@tonic-gate 		    ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC);
18197c478bd9Sstevel@tonic-gate 	} else {
18207c478bd9Sstevel@tonic-gate 		readtape((char *)buf);
18217c478bd9Sstevel@tonic-gate 		if (normspcl(byteorder, buf, (int *)buf, tp_bsize,
18227c478bd9Sstevel@tonic-gate 		    ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC)))
18237c478bd9Sstevel@tonic-gate 			return (FAIL);
18247c478bd9Sstevel@tonic-gate 	}
18257c478bd9Sstevel@tonic-gate 
18267c478bd9Sstevel@tonic-gate 	switch (buf->c_type) {
18277c478bd9Sstevel@tonic-gate 
18287c478bd9Sstevel@tonic-gate 	case TS_CLRI:
18297c478bd9Sstevel@tonic-gate 	case TS_BITS:
18307c478bd9Sstevel@tonic-gate 		/*
18317c478bd9Sstevel@tonic-gate 		 * Have to patch up missing information in bit map headers
18327c478bd9Sstevel@tonic-gate 		 */
18337c478bd9Sstevel@tonic-gate 		buf->c_inumber = 0;
18347c478bd9Sstevel@tonic-gate 		buf->c_dinode.di_size = (offset_t)buf->c_count * tp_bsize;
18357c478bd9Sstevel@tonic-gate 		for (i = 0; i < buf->c_count && i < TP_NINDIR; i++)
18367c478bd9Sstevel@tonic-gate 			buf->c_addr[i] = 1;
18377c478bd9Sstevel@tonic-gate 		break;
18387c478bd9Sstevel@tonic-gate 
18397c478bd9Sstevel@tonic-gate 	case TS_TAPE:
18407c478bd9Sstevel@tonic-gate 	case TS_END:
18417c478bd9Sstevel@tonic-gate 		if (dumpinfo.c_date == 0) {
18427c478bd9Sstevel@tonic-gate 			dumpinfo.c_date = spcl.c_date;
18437c478bd9Sstevel@tonic-gate 			dumpinfo.c_ddate = spcl.c_ddate;
18447c478bd9Sstevel@tonic-gate 		}
18457c478bd9Sstevel@tonic-gate 		if (!hostinfo && spcl.c_host[0] != '\0') {
18467c478bd9Sstevel@tonic-gate 			bcopy(spcl.c_label, dumpinfo.c_label,
18477c478bd9Sstevel@tonic-gate 			    sizeof (spcl.c_label));
18487c478bd9Sstevel@tonic-gate 			bcopy(spcl.c_filesys, dumpinfo.c_filesys,
18497c478bd9Sstevel@tonic-gate 			    sizeof (spcl.c_filesys));
18507c478bd9Sstevel@tonic-gate 			bcopy(spcl.c_dev, dumpinfo.c_dev,
18517c478bd9Sstevel@tonic-gate 			    sizeof (spcl.c_dev));
18527c478bd9Sstevel@tonic-gate 			bcopy(spcl.c_host, dumpinfo.c_host,
18537c478bd9Sstevel@tonic-gate 			    sizeof (spcl.c_host));
18547c478bd9Sstevel@tonic-gate 			dumpinfo.c_level = spcl.c_level;
18557c478bd9Sstevel@tonic-gate 			hostinfo++;
18567c478bd9Sstevel@tonic-gate 			if (c_label != NULL &&
18577c478bd9Sstevel@tonic-gate 			    strncmp(c_label, spcl.c_label,
18587c478bd9Sstevel@tonic-gate 			    sizeof (spcl.c_label))
18597c478bd9Sstevel@tonic-gate 			    != 0) {
18607c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
18617c478bd9Sstevel@tonic-gate 		    "Incorrect tape label.  Expected `%s', got `%.*s'\n"),
18627c478bd9Sstevel@tonic-gate 				    c_label,
18637c478bd9Sstevel@tonic-gate 				    sizeof (spcl.c_label), spcl.c_label);
18647c478bd9Sstevel@tonic-gate 				done(1);
18657c478bd9Sstevel@tonic-gate 			}
18667c478bd9Sstevel@tonic-gate 		}
18677c478bd9Sstevel@tonic-gate 		if (!inodeinfo && (spcl.c_flags & DR_INODEINFO)) {
18687c478bd9Sstevel@tonic-gate 			dumpinfo.c_volume = spcl.c_volume;
18697c478bd9Sstevel@tonic-gate 			bcopy(spcl.c_inos, dumpinfo.c_inos,
18707c478bd9Sstevel@tonic-gate 			    sizeof (spcl.c_inos));
18717c478bd9Sstevel@tonic-gate 			inodeinfo++;
18727c478bd9Sstevel@tonic-gate 		}
18737c478bd9Sstevel@tonic-gate 		buf->c_inumber = 0;
18747c478bd9Sstevel@tonic-gate 		break;
18757c478bd9Sstevel@tonic-gate 
18767c478bd9Sstevel@tonic-gate 	case TS_INODE:
18777c478bd9Sstevel@tonic-gate 	case TS_ADDR:
18787c478bd9Sstevel@tonic-gate 		break;
18797c478bd9Sstevel@tonic-gate 
18807c478bd9Sstevel@tonic-gate 	default:
18817c478bd9Sstevel@tonic-gate 		panic(gettext("%s: unknown inode type %d\n"),
18827c478bd9Sstevel@tonic-gate 		    "gethead", buf->c_type);
18837c478bd9Sstevel@tonic-gate 		return (FAIL);
18847c478bd9Sstevel@tonic-gate 	}
18857c478bd9Sstevel@tonic-gate 	if (dflag)
18867c478bd9Sstevel@tonic-gate 		accthdr(buf);
18877c478bd9Sstevel@tonic-gate 	return (GOOD);
18887c478bd9Sstevel@tonic-gate }
18897c478bd9Sstevel@tonic-gate 
18907c478bd9Sstevel@tonic-gate /*
18917c478bd9Sstevel@tonic-gate  * Check that a header is where it belongs and predict the next header
18927c478bd9Sstevel@tonic-gate  */
18937c478bd9Sstevel@tonic-gate static void
accthdr(struct s_spcl * header)1894fe0e7ec4Smaheshvs accthdr(struct s_spcl *header)
18957c478bd9Sstevel@tonic-gate {
18967c478bd9Sstevel@tonic-gate 	static ino_t previno = (ino_t)(unsigned)-1;
18977c478bd9Sstevel@tonic-gate 	static int prevtype;
18987c478bd9Sstevel@tonic-gate 	static long predict;
18997c478bd9Sstevel@tonic-gate 	int blks, i;
19007c478bd9Sstevel@tonic-gate 
19017c478bd9Sstevel@tonic-gate 	if (header->c_type == TS_TAPE) {
19027c478bd9Sstevel@tonic-gate 		if (header->c_firstrec)
19037c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
19047c478bd9Sstevel@tonic-gate 			    gettext("Volume header begins with record %d"),
19057c478bd9Sstevel@tonic-gate 			    header->c_firstrec);
19067c478bd9Sstevel@tonic-gate 		else
19077c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("Volume header"));
19087c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "\n");
19097c478bd9Sstevel@tonic-gate 		previno = (ino_t)(unsigned)-1;
19107c478bd9Sstevel@tonic-gate 		return;
19117c478bd9Sstevel@tonic-gate 	}
19127c478bd9Sstevel@tonic-gate 	if (previno == (ino_t)(unsigned)-1)
19137c478bd9Sstevel@tonic-gate 		goto newcalc;
19147c478bd9Sstevel@tonic-gate 	switch (prevtype) {
19157c478bd9Sstevel@tonic-gate 	case TS_BITS:
19167c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Dump mask header"));
19177c478bd9Sstevel@tonic-gate 		break;
19187c478bd9Sstevel@tonic-gate 	case TS_CLRI:
19197c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("Remove mask header"));
19207c478bd9Sstevel@tonic-gate 		break;
19217c478bd9Sstevel@tonic-gate 	case TS_INODE:
19227c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
19237c478bd9Sstevel@tonic-gate 		    gettext("File header, ino %d at record %d"),
19247c478bd9Sstevel@tonic-gate 		    previno, rec_position);
19257c478bd9Sstevel@tonic-gate 		break;
19267c478bd9Sstevel@tonic-gate 	case TS_ADDR:
19277c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
19287c478bd9Sstevel@tonic-gate 		    gettext("File continuation header, ino %d"),
19297c478bd9Sstevel@tonic-gate 		    previno);
19307c478bd9Sstevel@tonic-gate 		break;
19317c478bd9Sstevel@tonic-gate 	case TS_END:
19327c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("End of media header"));
19337c478bd9Sstevel@tonic-gate 		break;
19347c478bd9Sstevel@tonic-gate 	}
19357c478bd9Sstevel@tonic-gate 	if (predict != blksread - 1)
19367c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
19377c478bd9Sstevel@tonic-gate 		    gettext("; predicted %ld blocks, got %ld blocks"),
19387c478bd9Sstevel@tonic-gate 		    predict, blksread - 1);
19397c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\n");
19407c478bd9Sstevel@tonic-gate newcalc:
19417c478bd9Sstevel@tonic-gate 	blks = 0;
19427c478bd9Sstevel@tonic-gate 	if (header->c_type != TS_END)
19437c478bd9Sstevel@tonic-gate 		for (i = 0; i < header->c_count; i++)
19447c478bd9Sstevel@tonic-gate 			if ((i >= TP_NINDIR) || (header->c_addr[i] != 0))
19457c478bd9Sstevel@tonic-gate 				blks++;
19467c478bd9Sstevel@tonic-gate 	predict = blks;
19477c478bd9Sstevel@tonic-gate 	blksread = 0;
19487c478bd9Sstevel@tonic-gate 	prevtype = header->c_type;
19497c478bd9Sstevel@tonic-gate 	previno = header->c_inumber;
19507c478bd9Sstevel@tonic-gate }
19517c478bd9Sstevel@tonic-gate 
19527c478bd9Sstevel@tonic-gate /*
19537c478bd9Sstevel@tonic-gate  * Try to determine which volume a file resides on.
19547c478bd9Sstevel@tonic-gate  */
1955fe0e7ec4Smaheshvs int
volnumber(ino_t inum)1956fe0e7ec4Smaheshvs volnumber(ino_t inum)
19577c478bd9Sstevel@tonic-gate {
19587c478bd9Sstevel@tonic-gate 	int i;
19597c478bd9Sstevel@tonic-gate 
19607c478bd9Sstevel@tonic-gate 	if (inodeinfo == 0)
19617c478bd9Sstevel@tonic-gate 		return (0);
19627c478bd9Sstevel@tonic-gate 	for (i = 1; i <= dumpinfo.c_volume; i++)
19637c478bd9Sstevel@tonic-gate 		if (inum < (ino_t)(unsigned)(dumpinfo.c_inos[i]))
19647c478bd9Sstevel@tonic-gate 			break;
19657c478bd9Sstevel@tonic-gate 	return (i - 1);
19667c478bd9Sstevel@tonic-gate }
19677c478bd9Sstevel@tonic-gate 
19687c478bd9Sstevel@tonic-gate /*
19697c478bd9Sstevel@tonic-gate  * Find an inode header.
19707c478bd9Sstevel@tonic-gate  * Note that *header must be stable storage, as curfile will end up with
19717c478bd9Sstevel@tonic-gate  * pointers into it.
19727c478bd9Sstevel@tonic-gate  */
19737c478bd9Sstevel@tonic-gate void
findinode(struct s_spcl * header)1974fe0e7ec4Smaheshvs findinode(struct s_spcl *header)
19757c478bd9Sstevel@tonic-gate {
19767c478bd9Sstevel@tonic-gate 	long skipcnt = 0;
19777c478bd9Sstevel@tonic-gate 	int i;
19787c478bd9Sstevel@tonic-gate 	char buf[TP_BSIZE_MAX];
19797c478bd9Sstevel@tonic-gate 
19807c478bd9Sstevel@tonic-gate 	curfile.name = gettext("<name unknown>");
19817c478bd9Sstevel@tonic-gate 	curfile.action = UNKNOWN;
19827c478bd9Sstevel@tonic-gate 	curfile.dip = (struct dinode *)NULL;
19837c478bd9Sstevel@tonic-gate 	curfile.ino = 0;
19847c478bd9Sstevel@tonic-gate 	curfile.ts = 0;
19857c478bd9Sstevel@tonic-gate 	if (ishead(header) == FAIL) {
19867c478bd9Sstevel@tonic-gate 		skipcnt++;
19877c478bd9Sstevel@tonic-gate 		while (gethead(header) == FAIL ||
19887c478bd9Sstevel@tonic-gate 		    (time_t)(header->c_date) != dumpdate)
19897c478bd9Sstevel@tonic-gate 			skipcnt++;
19907c478bd9Sstevel@tonic-gate 	}
19917c478bd9Sstevel@tonic-gate 	for (;;) {
19927c478bd9Sstevel@tonic-gate 		if (checktype(header, TS_ADDR) == GOOD) {
19937c478bd9Sstevel@tonic-gate 			/*
19947c478bd9Sstevel@tonic-gate 			 * Skip up to the beginning of the next record
19957c478bd9Sstevel@tonic-gate 			 */
19967c478bd9Sstevel@tonic-gate 			for (i = 0; i < header->c_count; i++)
19977c478bd9Sstevel@tonic-gate 				if ((i >= TP_NINDIR) || (header->c_addr[i]))
19987c478bd9Sstevel@tonic-gate 					readtape(buf);
19997c478bd9Sstevel@tonic-gate 			(void) gethead(header);
20007c478bd9Sstevel@tonic-gate 			continue;
20017c478bd9Sstevel@tonic-gate 		}
20027c478bd9Sstevel@tonic-gate 		if (checktype(header, TS_INODE) == GOOD) {
20037c478bd9Sstevel@tonic-gate 			curfile.dip = &header->c_dinode;
20047c478bd9Sstevel@tonic-gate 			if (curfile.dip->di_suid != UID_LONG)
20057c478bd9Sstevel@tonic-gate 				curfile.dip->di_uid = curfile.dip->di_suid;
20067c478bd9Sstevel@tonic-gate 			if (curfile.dip->di_sgid != GID_LONG)
20077c478bd9Sstevel@tonic-gate 				curfile.dip->di_gid = curfile.dip->di_sgid;
20087c478bd9Sstevel@tonic-gate 			curfile.ino = header->c_inumber;
20097c478bd9Sstevel@tonic-gate 			curfile.ts = TS_INODE;
20107c478bd9Sstevel@tonic-gate 			break;
20117c478bd9Sstevel@tonic-gate 		}
20127c478bd9Sstevel@tonic-gate 		if (checktype(header, TS_END) == GOOD) {
20137c478bd9Sstevel@tonic-gate 			curfile.ino = maxino;
20147c478bd9Sstevel@tonic-gate 			curfile.ts = TS_END;
20157c478bd9Sstevel@tonic-gate 			break;
20167c478bd9Sstevel@tonic-gate 		}
20177c478bd9Sstevel@tonic-gate 		if (checktype(header, TS_CLRI) == GOOD) {
20187c478bd9Sstevel@tonic-gate 			curfile.name = gettext("<file removal list>");
20197c478bd9Sstevel@tonic-gate 			curfile.ts = TS_CLRI;
20207c478bd9Sstevel@tonic-gate 			break;
20217c478bd9Sstevel@tonic-gate 		}
20227c478bd9Sstevel@tonic-gate 		if (checktype(header, TS_BITS) == GOOD) {
20237c478bd9Sstevel@tonic-gate 			curfile.name = gettext("<file dump list>");
20247c478bd9Sstevel@tonic-gate 			curfile.ts = TS_BITS;
20257c478bd9Sstevel@tonic-gate 			break;
20267c478bd9Sstevel@tonic-gate 		}
20277c478bd9Sstevel@tonic-gate 		while (gethead(header) == FAIL)
20287c478bd9Sstevel@tonic-gate 			skipcnt++;
20297c478bd9Sstevel@tonic-gate 	}
20307c478bd9Sstevel@tonic-gate 	if (skipcnt > 0)
20317c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
20327c478bd9Sstevel@tonic-gate 		    gettext("resync restore, skipped %d blocks\n"),
20337c478bd9Sstevel@tonic-gate 		    skipcnt);
20347c478bd9Sstevel@tonic-gate }
20357c478bd9Sstevel@tonic-gate 
20367c478bd9Sstevel@tonic-gate /*
20377c478bd9Sstevel@tonic-gate  * return whether or not the buffer contains a header block
20387c478bd9Sstevel@tonic-gate  */
20397c478bd9Sstevel@tonic-gate static int
ishead(struct s_spcl * buf)2040fe0e7ec4Smaheshvs ishead(struct s_spcl *buf)
20417c478bd9Sstevel@tonic-gate {
20427c478bd9Sstevel@tonic-gate 	if (buf->c_magic !=
20437c478bd9Sstevel@tonic-gate 	    ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC))
20447c478bd9Sstevel@tonic-gate 		return (FAIL);
20457c478bd9Sstevel@tonic-gate 	return (GOOD);
20467c478bd9Sstevel@tonic-gate }
20477c478bd9Sstevel@tonic-gate 
2048fe0e7ec4Smaheshvs static int
checktype(struct s_spcl * b,int t)2049fe0e7ec4Smaheshvs checktype(struct s_spcl *b, int t)
20507c478bd9Sstevel@tonic-gate {
20517c478bd9Sstevel@tonic-gate 	if (b->c_type != t)
20527c478bd9Sstevel@tonic-gate 		return (FAIL);
20537c478bd9Sstevel@tonic-gate 	return (GOOD);
20547c478bd9Sstevel@tonic-gate }
20557c478bd9Sstevel@tonic-gate 
20567c478bd9Sstevel@tonic-gate /*
20577c478bd9Sstevel@tonic-gate  * If autoloading is enabled, attempt to do it.  If we succeed,
20587c478bd9Sstevel@tonic-gate  * return non-zero.
20597c478bd9Sstevel@tonic-gate  */
20607c478bd9Sstevel@tonic-gate static int
autoload_tape(void)20617c478bd9Sstevel@tonic-gate autoload_tape(void)
20627c478bd9Sstevel@tonic-gate {
20637c478bd9Sstevel@tonic-gate 	int result = 0;		/* assume failure */
20647c478bd9Sstevel@tonic-gate 	int tries;
20657c478bd9Sstevel@tonic-gate 	int fd;
20667c478bd9Sstevel@tonic-gate 
20677c478bd9Sstevel@tonic-gate 	if (autoload) {
20687c478bd9Sstevel@tonic-gate 		/*
20697c478bd9Sstevel@tonic-gate 		 * Wait for the tape to autoload.  Note that the delay
20707c478bd9Sstevel@tonic-gate 		 * period doesn't take into account however long it takes
20717c478bd9Sstevel@tonic-gate 		 * for the open to fail (measured at 21 seconds for an
20727c478bd9Sstevel@tonic-gate 		 * Exabyte 8200 under 2.7 on an Ultra 2).
20737c478bd9Sstevel@tonic-gate 		 */
207433a5e6b2Srm88369 
207533a5e6b2Srm88369 		/* rewind tape and offline drive before loading new tape */
207633a5e6b2Srm88369 		closemt(FORCE_OFFLINE);
20777c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
20787c478bd9Sstevel@tonic-gate 		    gettext("Attempting to autoload next volume\n"));
20797c478bd9Sstevel@tonic-gate 		for (tries = 0; tries < autoload_tries; tries++) {
20807c478bd9Sstevel@tonic-gate 			if (host) {
20817c478bd9Sstevel@tonic-gate 				if (rmtopen(magtape, O_RDONLY) >= 0) {
20827c478bd9Sstevel@tonic-gate 					rmtclose();
20837c478bd9Sstevel@tonic-gate 					result = 1;
20847c478bd9Sstevel@tonic-gate 					break;
20857c478bd9Sstevel@tonic-gate 				}
20867c478bd9Sstevel@tonic-gate 			} else {
20877c478bd9Sstevel@tonic-gate 				if ((fd = open(magtape, O_RDONLY|O_LARGEFILE,
20887c478bd9Sstevel@tonic-gate 				    0600)) >= 0) {
20897c478bd9Sstevel@tonic-gate 					(void) close(fd);
20907c478bd9Sstevel@tonic-gate 					result = 1;
20917c478bd9Sstevel@tonic-gate 					break;
20927c478bd9Sstevel@tonic-gate 				}
20937c478bd9Sstevel@tonic-gate 			}
20947c478bd9Sstevel@tonic-gate 			(void) sleep(autoload_period);
20957c478bd9Sstevel@tonic-gate 		}
20967c478bd9Sstevel@tonic-gate 		if (result == 0) {
20977c478bd9Sstevel@tonic-gate 			/* Assume caller will deal with manual change-over */
20987c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
20997c478bd9Sstevel@tonic-gate 			    gettext("Autoload timed out\n"));
21007c478bd9Sstevel@tonic-gate 		} else {
21017c478bd9Sstevel@tonic-gate 			if ((host != NULL &&
21027c478bd9Sstevel@tonic-gate 			    (mt = rmtopen(magtape, O_RDONLY)) == -1) ||
21037c478bd9Sstevel@tonic-gate 			    (host == NULL &&
21047c478bd9Sstevel@tonic-gate 			    (mt = open(magtape, O_RDONLY|O_LARGEFILE)) == -1)) {
21057c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
21067c478bd9Sstevel@tonic-gate 				    "Autoload could not re-open tape\n"));
21077c478bd9Sstevel@tonic-gate 				result = 0;
21087c478bd9Sstevel@tonic-gate 			} else {
21097c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
21107c478bd9Sstevel@tonic-gate 				    "Tape loaded\n"));
21117c478bd9Sstevel@tonic-gate 			}
21127c478bd9Sstevel@tonic-gate 		}
21137c478bd9Sstevel@tonic-gate 	}
21147c478bd9Sstevel@tonic-gate 
21157c478bd9Sstevel@tonic-gate 	return (result);
21167c478bd9Sstevel@tonic-gate }
2117