Home | History | Annotate | Download | only in restore
      1 /*
      2  * Copyright (c) 1983 Regents of the University of California.
      3  * All rights reserved.  The Berkeley software License Agreement
      4  * specifies the terms and conditions for redistribution.
      5  */
      6 
      7 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
      8 /*	  All Rights Reserved	*/
      9 
     10 /*
     11  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     12  * Use is subject to license terms.
     13  */
     14 
     15 #include <setjmp.h>
     16 #include "restore.h"
     17 #include <byteorder.h>
     18 #include <rmt.h>
     19 #include <sys/mtio.h>
     20 #include <utime.h>
     21 #include <sys/errno.h>
     22 #include <sys/fdio.h>
     23 #include <sys/sysmacros.h>	/* for expdev */
     24 #include <assert.h>
     25 #include <limits.h>
     26 #include <priv_utils.h>
     27 #include <aclutils.h>
     28 
     29 #define	MAXINO	65535		/* KLUDGE */
     30 
     31 #define	MAXTAPES	128
     32 
     33 static size_t	fssize = MAXBSIZE; /* preferred size of writes to filesystem */
     34 int mt = -1;
     35 static int	continuemap = 0;
     36 char		magtape[BUFSIZ];
     37 int		pipein = 0;
     38 char		*host;		/* used in dumprmt.c */
     39 daddr32_t	rec_position;
     40 static char	*archivefile;	/* used in metamucil.c */
     41 static int	bct;		/* block # index into tape record buffer */
     42 static int	numtrec;	/* # of logical blocks in current tape record */
     43 static char	*tbf = NULL;
     44 static size_t	tbfsize = 0;
     45 static int	recsread;
     46 static union	u_spcl endoftapemark;
     47 static struct	s_spcl dumpinfo;
     48 static long	blksread;	/* # of logical blocks actually read/touched */
     49 static long	tapea;		/* current logical block # on tape */
     50 static uchar_t	tapesread[MAXTAPES];
     51 static jmp_buf	restart;
     52 static int	gettingfile = 0;	/* restart has a valid frame */
     53 static int	ofile;
     54 static char	*map, *beginmap;
     55 static char	*endmap;
     56 static char	lnkbuf[MAXPATHLEN + 2];
     57 static int	pathlen;
     58 static int	inodeinfo;	/* Have starting volume information */
     59 static int	hostinfo;	/* Have dump host information */
     60 
     61 static int autoload_tape(void);
     62 static void setdumpnum(void);
     63 static void metacheck(struct s_spcl *);
     64 static void xtrmeta(char *, size_t);
     65 static void metaskip(char *, size_t);
     66 static void xtrfile(char *, size_t);
     67 static void xtrskip(char *, size_t);
     68 static void xtrlnkfile(char *, size_t);
     69 static void xtrlnkskip(char *, size_t);
     70 static void xtrmap(char *, size_t);
     71 static void xtrmapskip(char *, size_t);
     72 static void readtape(char *);
     73 static int checkvol(struct s_spcl *, int);
     74 static void accthdr(struct s_spcl *);
     75 static int ishead(struct s_spcl *);
     76 static int checktype(struct s_spcl *, int);
     77 static void metaset(char *name);
     78 
     79 /*
     80  * Set up an input source
     81  */
     82 void
     83 setinput(char *source, char *archive)
     84 {
     85 
     86 	flsht();
     87 	archivefile = archive;
     88 	if (bflag == 0) {
     89 		ntrec = ((CARTRIDGETREC > HIGHDENSITYTREC) ?
     90 		    (NTREC > CARTRIDGETREC ? NTREC : CARTRIDGETREC) :
     91 		    (NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC));
     92 		saved_ntrec = (ntrec * (tp_bsize/DEV_BSIZE));
     93 	}
     94 	newtapebuf(ntrec);
     95 	terminal = stdin;
     96 
     97 	if (source == NULL) {
     98 		/* A can't-happen */
     99 		(void) fprintf(stderr,
    100 		    gettext("Internal consistency check failed.\n"));
    101 		done(1);
    102 	}
    103 
    104 	if (strchr(source, ':')) {
    105 		char *tape;
    106 
    107 		host = source;
    108 		tape = strchr(host, ':');
    109 		*tape++ = '\0';
    110 		if (strlen(tape) > (sizeof (magtape) - 1)) {
    111 			(void) fprintf(stderr, gettext("Tape name too long\n"));
    112 			done(1);
    113 		}
    114 		(void) strcpy(magtape, tape);
    115 		if (rmthost(host, ntrec) == 0)
    116 			done(1);
    117 	} else {
    118 		if (strlen(source) > (sizeof (magtape) - 1)) {
    119 			(void) fprintf(stderr, gettext("Tape name too long\n"));
    120 			done(1);
    121 		}
    122 		/* Not remote, no need for privileges */
    123 		__priv_relinquish();
    124 		host = NULL;
    125 		if (strcmp(source, "-") == 0) {
    126 			/*
    127 			 * Since input is coming from a pipe we must establish
    128 			 * our own connection to the terminal.
    129 			 */
    130 			terminal = fopen("/dev/tty", "r");
    131 			if (terminal == NULL) {
    132 				int saverr = errno;
    133 				char *msg =
    134 				    gettext("Cannot open(\"/dev/tty\")");
    135 				errno = saverr;
    136 				perror(msg);
    137 				terminal = fopen("/dev/null", "r");
    138 				if (terminal == NULL) {
    139 					saverr = errno;
    140 					msg = gettext(
    141 					    "Cannot open(\"/dev/null\")");
    142 					errno = saverr;
    143 					perror(msg);
    144 					done(1);
    145 				}
    146 			}
    147 			pipein++;
    148 			if (archive) {
    149 				(void) fprintf(stderr, gettext(
    150 	    "Cannot specify an archive file when reading from a pipe\n"));
    151 				done(1);
    152 			}
    153 		}
    154 		(void) strcpy(magtape, source);
    155 	}
    156 }
    157 
    158 void
    159 newtapebuf(size_t size)
    160 {
    161 	size_t nsize;
    162 
    163 	nsize = size * tp_bsize;
    164 	ntrec = size;
    165 	if (nsize <= tbfsize)
    166 		return;
    167 	if (tbf != NULL)
    168 		free(tbf);
    169 	tbf = (char *)malloc(nsize);
    170 	if (tbf == NULL) {
    171 		(void) fprintf(stderr,
    172 		    gettext("Cannot allocate space for buffer\n"));
    173 		done(1);
    174 	}
    175 	tbfsize = nsize;
    176 }
    177 
    178 /*
    179  * Verify that the tape drive can be accessed and
    180  * that it actually is a dump tape.
    181  */
    182 void
    183 setup(void)
    184 {
    185 	int i, j;
    186 	int32_t *ip;
    187 	struct stat stbuf;
    188 	size_t mapsize;
    189 	char *syment = RESTORESYMTABLE;
    190 
    191 	vprintf(stdout, gettext("Verify volume and initialize maps\n"));
    192 	if (archivefile) {
    193 		mt = open(archivefile, O_RDONLY|O_LARGEFILE);
    194 		if (mt < 0) {
    195 			perror(archivefile);
    196 			done(1);
    197 		}
    198 		volno = 0;
    199 	} else if (host) {
    200 		if ((mt = rmtopen(magtape, O_RDONLY)) < 0) {
    201 			perror(magtape);
    202 			done(1);
    203 		}
    204 		volno = 1;
    205 	} else {
    206 		if (pipein)
    207 			mt = 0;
    208 		else if ((mt = open(magtape, O_RDONLY|O_LARGEFILE)) < 0) {
    209 			perror(magtape);
    210 			done(1);
    211 		}
    212 		volno = 1;
    213 	}
    214 	setdumpnum();
    215 	flsht();
    216 	if (!pipein && !bflag)
    217 		if (archivefile)
    218 			findtapeblksize(ARCHIVE_FILE);
    219 		else
    220 			findtapeblksize(TAPE_FILE);
    221 	if (bflag == 1) {
    222 		tape_rec_size = saved_ntrec * DEV_BSIZE;
    223 	}
    224 
    225 	/*
    226 	 * Get the first header.  If c_magic is NOT NFS_MAGIC or if
    227 	 * the checksum is in error, it will fail.  The magic could then
    228 	 * be either OFS_MAGIC or MTB_MAGIC.  If OFS_MAGIC, assume we
    229 	 * have an old dump, and try to convert it.  If it is MTB_MAGIC, we
    230 	 * procees this after.
    231 	 */
    232 	if ((gethead(&spcl) == FAIL) && (spcl.c_magic != MTB_MAGIC)) {
    233 		bct--; /* push back this block */
    234 		blksread--;
    235 		tapea--;
    236 		cvtflag++;
    237 		if (gethead(&spcl) == FAIL) {
    238 			(void) fprintf(stderr,
    239 			    gettext("Volume is not in dump format\n"));
    240 			done(1);
    241 		}
    242 		(void) fprintf(stderr,
    243 		    gettext("Converting to new file system format.\n"));
    244 	}
    245 	/*
    246 	 * The above gethead will have failed if the magic is
    247 	 * MTB_MAGIC. If that is true, we need to adjust tp_bsize.
    248 	 * We have assumed to this time that tp_bsize was 1024, if
    249 	 * this is a newer dump, get the real tp_bsize from the header,
    250 	 * and recalculate ntrec, numtrec.
    251 	 */
    252 	if (spcl.c_magic == MTB_MAGIC) {
    253 		tp_bsize = spcl.c_tpbsize;
    254 		if ((tp_bsize % TP_BSIZE_MIN != 0) ||
    255 		    (tp_bsize > TP_BSIZE_MAX)) {
    256 			(void) fprintf(stderr,
    257 			    gettext("Volume is not in dump format\n"));
    258 			done(1);
    259 		}
    260 		ntrec = (tape_rec_size/tp_bsize);
    261 		numtrec = ntrec;
    262 		newtapebuf(ntrec);
    263 		bct--; /* push back this block */
    264 		blksread--;
    265 		tapea--;
    266 		/* we have to re-do this in case checksum is wrong */
    267 		if (gethead(&spcl) == FAIL) {
    268 			(void) fprintf(stderr,
    269 			    gettext("Volume is not in dump format\n"));
    270 			done(1);
    271 		}
    272 	}
    273 	if (vflag)
    274 		byteorder_banner(byteorder, stdout);
    275 	if (pipein) {
    276 		endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC :
    277 		    ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC);
    278 		endoftapemark.s_spcl.c_type = TS_END;
    279 
    280 		/*
    281 		 * include this since the `resync' loop in findinode
    282 		 * expects to find a header with the c_date field
    283 		 * filled in.
    284 		 */
    285 		endoftapemark.s_spcl.c_date = spcl.c_date;
    286 
    287 		ip = (int32_t *)&endoftapemark;
    288 		/*LINTED [assertion always true]*/
    289 		assert((sizeof (endoftapemark) % sizeof (int32_t)) == 0);
    290 		j = sizeof (endoftapemark) / sizeof (int32_t);
    291 		i = 0;
    292 		do
    293 			i += *ip++;
    294 		while (--j)
    295 			;
    296 		endoftapemark.s_spcl.c_checksum = CHECKSUM - i;
    297 	}
    298 	if (vflag && command != 't')
    299 		printdumpinfo();
    300 	dumptime = spcl.c_ddate;
    301 	dumpdate = spcl.c_date;
    302 	if (stat(".", &stbuf) < 0) {
    303 		perror(gettext("cannot stat ."));
    304 		done(1);
    305 	}
    306 	if (stbuf.st_blksize >= tp_bsize && stbuf.st_blksize <= MAXBSIZE) {
    307 		/* LINTED: value fits in a size_t */
    308 		fssize = stbuf.st_blksize;
    309 	} else {
    310 		fssize = MAXBSIZE;
    311 	}
    312 
    313 	if (checkvol(&spcl, 1) == FAIL) {
    314 		(void) fprintf(stderr,
    315 		    gettext("This is not volume 1 of the dump\n"));
    316 		done(1);
    317 	}
    318 	if (readhdr(&spcl) == FAIL)
    319 		panic(gettext("no header after volume mark!\n"));
    320 
    321 	findinode(&spcl);	/* sets curfile, resyncs the tape if need be */
    322 	if (checktype(&spcl, TS_CLRI) == FAIL) {
    323 		(void) fprintf(stderr,
    324 		    gettext("Cannot find file removal list\n"));
    325 		done(1);
    326 	}
    327 	maxino = (unsigned)((spcl.c_count * tp_bsize * NBBY) + 1);
    328 	dprintf(stdout, "maxino = %lu\n", maxino);
    329 	/*
    330 	 * Allocate space for at least MAXINO inodes to allow us
    331 	 * to restore partial dump tapes written before dump was
    332 	 * fixed to write out the entire inode map.
    333 	 */
    334 	if (maxino > ULONG_MAX) {
    335 		(void) fprintf(stderr,
    336 		    gettext("file system too large\n"));
    337 		done(1);
    338 	}
    339 	/* LINTED maxino size-checked above */
    340 	mapsize = (size_t)d_howmany(maxino > MAXINO ? maxino : MAXINO, NBBY);
    341 	beginmap = map = calloc((size_t)1, mapsize);
    342 	if (map == (char *)NIL) {
    343 		(void) fprintf(stderr,
    344 		    gettext("no memory for file removal list\n"));
    345 		done(1);
    346 	}
    347 	endmap = map + mapsize;
    348 	clrimap = map;
    349 	curfile.action = USING;
    350 	continuemap = 1;
    351 	getfile(xtrmap, xtrmapskip);
    352 	if (MAXINO > maxino)
    353 		maxino = MAXINO;
    354 	if (checktype(&spcl, TS_BITS) == FAIL) {
    355 		/* if we have TS_CLRI then no TS_BITS then a TS_END */
    356 		/* then we have an empty dump file */
    357 		if (gethead(&spcl) == GOOD &&
    358 		    checktype(&spcl, TS_END) == GOOD) {
    359 			if ((command == 'r') || (command == 'R')) {
    360 				initsymtable(syment);
    361 				dumpsymtable(syment, volno);
    362 			}
    363 			done(0);
    364 		}
    365 		/* otherwise we have an error */
    366 		(void) fprintf(stderr, gettext("Cannot find file dump list\n"));
    367 		done(1);
    368 	}
    369 	/* LINTED maxino size-checked above */
    370 	mapsize = (size_t)d_howmany(maxino, NBBY);
    371 	beginmap = map = calloc((size_t)1, mapsize);
    372 	if (map == (char *)NULL) {
    373 		(void) fprintf(stderr,
    374 		    gettext("no memory for file dump list\n"));
    375 		done(1);
    376 	}
    377 	endmap = map + mapsize;
    378 	dumpmap = map;
    379 	curfile.action = USING;
    380 	continuemap = 1;
    381 	getfile(xtrmap, xtrmapskip);
    382 	continuemap = 0;
    383 }
    384 
    385 /*
    386  * Initialize fssize variable for 'R' command to work.
    387  */
    388 void
    389 setupR(void)
    390 {
    391 	struct stat stbuf;
    392 
    393 	if (stat(".", &stbuf) < 0) {
    394 		perror(gettext("cannot stat ."));
    395 		done(1);
    396 	}
    397 	if (stbuf.st_blksize >= tp_bsize && stbuf.st_blksize <= MAXBSIZE) {
    398 		/* LINTED: value fits in a size_t */
    399 		fssize = stbuf.st_blksize;
    400 	} else {
    401 		fssize = MAXBSIZE;
    402 	}
    403 }
    404 
    405 /*
    406  * Prompt user to load a new dump volume.
    407  * "Nextvol" is the next suggested volume to use.
    408  * This suggested volume is enforced when doing full
    409  * or incremental restores, but can be overrridden by
    410  * the user when only extracting a subset of the files.
    411  *
    412  * first_time is used with archive files and can have 1 of 3 states:
    413  *	FT_STATE_1	Tape has not been read yet
    414  *	FT_STATE_2	Tape has been read but not positioned past directory
    415  *			information
    416  *	FT_STATE_3	Tape has been read and is reading file information
    417  */
    418 #define	FT_STATE_1	1
    419 #define	FT_STATE_2	2
    420 #define	FT_STATE_3	3
    421 
    422 void
    423 getvol(int nextvol)
    424 {
    425 	int newvol;
    426 	long savecnt, savetapea, wantnext;
    427 	long i;
    428 	union u_spcl tmpspcl;
    429 #define	tmpbuf tmpspcl.s_spcl
    430 	char buf[TP_BSIZE_MAX];
    431 	static int first_time = FT_STATE_1;
    432 
    433 	if (tbf == NULL) {
    434 		(void) fprintf(stderr, gettext(
    435 		    "Internal consistency failure in getvol: tbf is NULL\n"));
    436 		done(1);
    437 	}
    438 
    439 	if (nextvol == 1) {
    440 		for (i = 0;  i < MAXTAPES;  i++)
    441 			tapesread[i] = 0;
    442 		gettingfile = 0;
    443 	}
    444 	if (pipein) {
    445 		if (nextvol != 1)
    446 			panic(gettext("changing volumes on pipe input\n"));
    447 		if (volno == 1)
    448 			return;
    449 		goto gethdr;
    450 	}
    451 	savecnt = blksread;	/* ignore volume verification tape i/o */
    452 	savetapea = tapea;
    453 again:
    454 	if (pipein)
    455 		done(1); /* pipes do not get a second chance */
    456 	if (command == 'R' || command == 'r' || curfile.action != SKIP) {
    457 		wantnext = 1;
    458 		newvol = nextvol;
    459 	} else {
    460 		wantnext = 0;
    461 		newvol = 0;
    462 	}
    463 
    464 	if (autoload) {
    465 		if ((volno == 1) && (nextvol == 1)) {
    466 			tapesread[volno-1]++;
    467 			return;
    468 		}
    469 		if (autoload_tape()) {
    470 			wantnext = 1;
    471 			newvol = nextvol;
    472 			goto gethdr;
    473 		}
    474 	}
    475 
    476 	while (newvol <= 0) {
    477 		int n = 0;
    478 
    479 		for (i = 0;  i < MAXTAPES;  i++)
    480 			if (tapesread[i])
    481 				n++;
    482 		if (n == 0) {
    483 			(void) fprintf(stderr, "%s", gettext(
    484 "You have not read any volumes yet.\n\
    485 Unless you know which volume your file(s) are on you should start\n\
    486 with the last volume and work towards the first.\n"));
    487 		} else {
    488 			(void) fprintf(stderr,
    489 			    gettext("You have read volumes"));
    490 			(void) strcpy(tbf, ": ");
    491 			for (i = 0; i < MAXTAPES; i++)
    492 				if (tapesread[i]) {
    493 					(void) fprintf(stderr, "%s%ld",
    494 					    tbf, i+1);
    495 					(void) strcpy(tbf, ", ");
    496 				}
    497 			(void) fprintf(stderr, "\n");
    498 		}
    499 		do {
    500 			(void) fprintf(stderr,
    501 			    gettext("Specify next volume #: "));
    502 			(void) fflush(stderr);
    503 			/* LINTED tbfsize is limited to a few MB */
    504 			(void) fgets(tbf, (int)tbfsize, terminal);
    505 		} while (!feof(terminal) && tbf[0] == '\n');
    506 		if (feof(terminal))
    507 			done(1);
    508 		newvol = atoi(tbf);
    509 		if (newvol <= 0) {
    510 			(void) fprintf(stderr, gettext(
    511 			    "Volume numbers are positive numerics\n"));
    512 		}
    513 		if (newvol > MAXTAPES) {
    514 			(void) fprintf(stderr, gettext(
    515 			    "This program can only deal with %d volumes\n"),
    516 			    MAXTAPES);
    517 			newvol = 0;
    518 		}
    519 	}
    520 	if (newvol == volno) {
    521 		tapesread[volno-1]++;
    522 		return;
    523 	}
    524 	closemt(ALLOW_OFFLINE);
    525 	/*
    526 	 * XXX: if we are switching devices, we should probably try
    527 	 * the device once without prompting to enable unattended
    528 	 * operation.
    529 	 */
    530 	if (host)
    531 		(void) fprintf(stderr, gettext(
    532 "Mount volume %d\nthen enter volume name on host %s (default: %s) "),
    533 		    newvol, host,  magtape);
    534 	else
    535 		(void) fprintf(stderr, gettext(
    536 		    "Mount volume %d\nthen enter volume name (default: %s) "),
    537 		    newvol, magtape);
    538 	(void) fflush(stderr);
    539 	/* LINTED tbfsize is limited to a few MB */
    540 	(void) fgets(tbf, (int)tbfsize, terminal);
    541 	if (feof(terminal))
    542 		done(1);
    543 	/*
    544 	 * XXX We don't allow rotating among tape hosts, just drives.
    545 	 */
    546 	if (tbf[0] != '\n') {
    547 		(void) strncpy(magtape, tbf, sizeof (magtape));
    548 		magtape[sizeof (magtape) - 1] = '\0';
    549 		/* LINTED unsigned -> signed conversion ok */
    550 		i = (int)strlen(magtape);
    551 		if (magtape[i - 1] == '\n')
    552 			magtape[i - 1] = '\0';
    553 	}
    554 	if ((host != NULL && (mt = rmtopen(magtape, O_RDONLY)) == -1) ||
    555 	    (host == NULL &&
    556 	    (mt = open(magtape, O_RDONLY|O_LARGEFILE)) == -1)) {
    557 		int error = errno;
    558 		(void) fprintf(stderr, gettext("Cannot open %s: %s\n"),
    559 		    magtape, strerror(error));
    560 		volno = -1;
    561 		goto again;
    562 	}
    563 gethdr:
    564 	volno = newvol;
    565 	setdumpnum();
    566 	flsht();
    567 	if (!pipein && !bflag && archivefile && (first_time == FT_STATE_1)) {
    568 		first_time = FT_STATE_2;
    569 		findtapeblksize(TAPE_FILE);
    570 	}
    571 	if (readhdr(&tmpbuf) == FAIL) {
    572 		(void) fprintf(stderr,
    573 		    gettext("volume is not in dump format\n"));
    574 		volno = 0;
    575 		goto again;
    576 	}
    577 	if (checkvol(&tmpbuf, volno) == FAIL) {
    578 		(void) fprintf(stderr, gettext("Wrong volume (%d)\n"),
    579 		    tmpbuf.c_volume);
    580 		volno = 0;
    581 		goto again;
    582 	}
    583 
    584 	if (((time_t)(tmpbuf.c_date) != dumpdate) ||
    585 	    ((time_t)(tmpbuf.c_ddate) != dumptime)) {
    586 		char *tmp_ct;
    587 		time_t lc_date = (time_t)tmpbuf.c_date;
    588 
    589 		/*
    590 		 * This is used to save the return value from lctime(),
    591 		 * since that's volatile across lctime() invocations.
    592 		 */
    593 		tmp_ct = strdup(lctime(&lc_date));
    594 		if (tmp_ct == (char *)0) {
    595 			(void) fprintf(stderr, gettext(
    596 			    "Cannot allocate space for time string\n"));
    597 			done(1);
    598 		}
    599 
    600 		(void) fprintf(stderr,
    601 		    gettext("Wrong dump date\n\tgot: %s\twanted: %s"),
    602 		    tmp_ct,  lctime(&dumpdate));
    603 		volno = 0;
    604 		free(tmp_ct);
    605 		goto again;
    606 	}
    607 	tapesread[volno-1]++;
    608 	blksread = savecnt;
    609 	tapea = savetapea;
    610 	/*
    611 	 * If continuing from the previous volume, skip over any
    612 	 * blocks read already at the end of the previous volume.
    613 	 *
    614 	 * If coming to this volume at random, skip to the beginning
    615 	 * of the next record.
    616 	 */
    617 	if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) {
    618 		if (!wantnext) {
    619 			if (archivefile && first_time == FT_STATE_2) {
    620 				first_time = FT_STATE_3;
    621 			}
    622 			recsread = tmpbuf.c_firstrec;
    623 			tapea = tmpbuf.c_tapea;
    624 			dprintf(stdout,
    625 			    "restore skipping %d records\n",
    626 			    tmpbuf.c_count);
    627 			for (i = tmpbuf.c_count; i > 0; i--)
    628 				readtape(buf);
    629 		} else if (tmpbuf.c_firstrec != 0) {
    630 			savecnt = blksread;
    631 			savetapea = tapea;
    632 
    633 			if (archivefile && first_time == FT_STATE_2) {
    634 				/*
    635 				 * subtract 2, 1 for archive file's TS_END
    636 				 * and 1 for tape's TS_TAPE
    637 				 */
    638 				first_time = FT_STATE_3;
    639 				i = tapea - tmpbuf.c_tapea - 2;
    640 			} else {
    641 				i = tapea - tmpbuf.c_tapea;
    642 			}
    643 			if (i > 0)
    644 				dprintf(stdout, gettext(
    645 				    "restore skipping %d duplicate records\n"),
    646 				    i);
    647 			else if (i < 0)
    648 				dprintf(stdout, gettext(
    649 				    "restore duplicate record botch (%d)\n"),
    650 				    i);
    651 			while (--i >= 0)
    652 				readtape(buf);
    653 			blksread = savecnt;
    654 			tapea = savetapea + 1; /* <= (void) gethead() below */
    655 		}
    656 	}
    657 	if (curfile.action == USING) {
    658 		if (volno == 1)
    659 			panic(gettext("active file into volume 1\n"));
    660 		return;
    661 	}
    662 	(void) gethead(&spcl);
    663 	findinode(&spcl); /* do we always restart files in full? */
    664 	if (gettingfile) { /* i.e. will we lose metadata? */
    665 		gettingfile = 0;
    666 		longjmp(restart, 1); /* will this set f1 & f2? */
    667 	}
    668 }
    669 
    670 /*
    671  * handle multiple dumps per tape by skipping forward to the
    672  * appropriate one.  Note we don't use absolute positioning,
    673  * as that may take a very long time.
    674  */
    675 static void
    676 setdumpnum(void)
    677 {
    678 	struct mtop tcom;
    679 	int retval;
    680 
    681 	if (dumpnum == 1 || volno != 1)
    682 		return;
    683 	if (pipein) {
    684 		(void) fprintf(stderr,
    685 		    gettext("Cannot have multiple dumps on pipe input\n"));
    686 		done(1);
    687 	}
    688 	tcom.mt_op = MTFSF;
    689 	tcom.mt_count = dumpnum - 1;
    690 	if (host)
    691 		retval = rmtioctl(MTFSF, dumpnum - 1);
    692 	else
    693 		retval = ioctl(mt, (int)MTIOCTOP, (char *)&tcom);
    694 	if (retval < 0)
    695 		perror("ioctl MTFSF");
    696 }
    697 
    698 void
    699 printdumpinfo(void)
    700 {
    701 	int i;
    702 	time_t date;
    703 	static char *epoch = NULL;
    704 
    705 	if (epoch == NULL) {
    706 		epoch = strdup(gettext("the epoch\n"));
    707 		if (epoch == NULL) {
    708 			(void) fprintf(stderr, gettext("Out of memory\n"));
    709 			return;
    710 		}
    711 	}
    712 
    713 	date = (time_t)dumpinfo.c_date;
    714 	(void) fprintf(stdout,
    715 	    gettext("Dump   date: %s"), lctime(&date));
    716 
    717 	date = (time_t)dumpinfo.c_ddate;
    718 	(void) fprintf(stdout, gettext("Dumped from: %s"),
    719 	    (dumpinfo.c_ddate == 0) ? epoch : lctime(&date));
    720 	if (hostinfo) {
    721 		(void) fprintf(stdout,
    722 		    gettext("Level %d dump of %s on %.*s:%s\n"),
    723 		    dumpinfo.c_level, dumpinfo.c_filesys,
    724 		    sizeof (dumpinfo.c_host), dumpinfo.c_host, dumpinfo.c_dev);
    725 		(void) fprintf(stdout,
    726 		    gettext("Label: %.*s\n"),
    727 		    sizeof (dumpinfo.c_label), dumpinfo.c_label);
    728 	}
    729 	if (inodeinfo) {
    730 		(void) fprintf(stdout,
    731 		    gettext("Starting inode numbers by volume:\n"));
    732 		for (i = 1; i <= dumpinfo.c_volume; i++)
    733 			(void) fprintf(stdout, gettext("\tVolume %d: %6d\n"),
    734 			    i, dumpinfo.c_inos[i]);
    735 	}
    736 }
    737 
    738 int
    739 extractfile(char *name)
    740 {
    741 	static int complained_chown = 0;
    742 	static int complained_lchown = 0;
    743 	static int complained_chmod = 0;
    744 	static int complained_utime = 0;
    745 	static int complained_mknod = 0;
    746 	mode_t mode;
    747 	time_t timep[2];
    748 	struct entry *ep;
    749 	uid_t uid;
    750 	gid_t gid;
    751 	char *errmsg;
    752 	int result, saverr;
    753 	dev_t full_dev;
    754 	int dfd;
    755 	char *rname;
    756 
    757 	curfile.name = name;
    758 	curfile.action = USING;
    759 	timep[0] = (time_t)curfile.dip->di_atime;
    760 	timep[1] = (time_t)curfile.dip->di_mtime;
    761 	mode = curfile.dip->di_mode;
    762 
    763 	uid = curfile.dip->di_suid == UID_LONG ?
    764 	    curfile.dip->di_uid : (uid_t)curfile.dip->di_suid;
    765 	gid = curfile.dip->di_sgid == GID_LONG ?
    766 	    curfile.dip->di_gid : (gid_t)curfile.dip->di_sgid;
    767 
    768 	resolve(name, &dfd, &rname);
    769 	if (dfd != AT_FDCWD) {
    770 		if (fchdir(dfd) < 0) {
    771 			saverr = errno;
    772 			(void) fprintf(stderr, gettext(
    773 			    "%s: unable to set attribute context: %s\n"),
    774 			    rname, strerror(saverr));
    775 			skipfile();
    776 			(void) close(dfd);
    777 			return (FAIL);
    778 		}
    779 	}
    780 
    781 	switch (mode & IFMT) {
    782 
    783 	default:
    784 		(void) fprintf(stderr, gettext("%s: unknown file mode 0%lo\n"),
    785 		    rname, (ulong_t)(mode&IFMT));
    786 		skipfile();
    787 		result = FAIL;
    788 		break;
    789 
    790 	case IFSOCK:
    791 		vprintf(stdout, gettext("skipped socket %s\n"), rname);
    792 		skipfile();
    793 		result = GOOD;
    794 		break;
    795 
    796 	case IFDIR:
    797 		if (mflag) {
    798 			ep = lookupname(name);
    799 			if (ep == NIL || ep->e_flags & EXTRACT) {
    800 				panic(gettext(
    801 				    "directory %s was not restored\n"),
    802 				    rname);
    803 				skipfile();
    804 				result = FAIL;
    805 				break;
    806 			}
    807 			skipfile();
    808 			result = GOOD;
    809 			break;
    810 		}
    811 		vprintf(stdout, gettext("extract file %s\n"), rname);
    812 		result = genliteraldir(rname, curfile.ino);
    813 		break;
    814 
    815 	case IFLNK:
    816 		lnkbuf[0] = '\0';
    817 		pathlen = 0;
    818 		getfile(xtrlnkfile, xtrlnkskip);
    819 		if (pathlen == 0) {
    820 			vprintf(stdout, gettext(
    821 			    "%s: zero length symbolic link (ignored)\n"),
    822 			    rname);
    823 			result = GOOD;
    824 			break;
    825 		}
    826 		if ((result = lf_linkit(lnkbuf, rname, SYMLINK)) != GOOD)
    827 			break;
    828 
    829 		/* 1254700: set uid/gid (previously missing)  */
    830 		if (lchown(rname, uid, gid) < 0 && !complained_lchown) {
    831 			/* Just a warning */
    832 			saverr = errno;
    833 			errmsg = gettext(
    834 			    "Unable to restore ownership of symlink %s: %s\n");
    835 			(void) fprintf(stderr, errmsg,
    836 			    rname, strerror(saverr));
    837 			(void) fprintf(stderr, gettext(
    838 			    "Additional such failures will be ignored.\n"));
    839 			complained_lchown = 1;
    840 		}
    841 		metaset(rname);
    842 		result = GOOD;
    843 		break;
    844 
    845 	case IFCHR:
    846 	case IFBLK:
    847 	case IFIFO:
    848 		vprintf(stdout, gettext("extract special file %s\n"), rname);
    849 		/* put device rdev into dev_t expanded format */
    850 		/* XXX does this always do the right thing? */
    851 		/* XXX does dump do the right thing? */
    852 		if (((curfile.dip->di_ordev & 0xFFFF0000) == 0) ||
    853 		    ((curfile.dip->di_ordev & 0xFFFF0000) == 0xFFFF0000)) {
    854 			full_dev = expdev((unsigned)(curfile.dip->di_ordev));
    855 		} else {
    856 			/* LINTED sign extension ok */
    857 			full_dev = (unsigned)(curfile.dip->di_ordev);
    858 		}
    859 
    860 		if (mknod(rname, mode, full_dev) < 0) {
    861 			struct stat64 s[1];
    862 
    863 			saverr = errno;
    864 			if ((stat64(rname, s)) ||
    865 			    ((s->st_mode & S_IFMT) != (mode & S_IFMT)) ||
    866 			    (s->st_rdev != full_dev)) {
    867 				if (saverr != EPERM || !complained_mknod) {
    868 					(void) fprintf(stderr, "%s: ", rname);
    869 					(void) fflush(stderr);
    870 					errno = saverr;
    871 					perror(gettext(
    872 					    "cannot create special file"));
    873 					if (saverr == EPERM) {
    874 						(void) fprintf(stderr, gettext(
    875 			    "Additional such failures will be ignored.\n"));
    876 						complained_mknod = 1;
    877 					}
    878 				}
    879 				skipfile();
    880 				result = FAIL;
    881 				break;
    882 			}
    883 		}
    884 		if (chown(rname, uid, gid) < 0 && !complained_chown) {
    885 			/* Just a warning */
    886 			saverr = errno;
    887 			errmsg = gettext(
    888 			    "Unable to restore ownership of %s: %s\n");
    889 			(void) fprintf(stderr, errmsg,
    890 			    rname, strerror(saverr));
    891 			(void) fprintf(stderr, gettext(
    892 			    "Additional such failures will be ignored.\n"));
    893 			complained_chown = 1;
    894 		}
    895 		if (chmod(rname, mode) < 0 && !complained_chmod) {
    896 			saverr = errno;
    897 			errmsg = gettext(
    898 			    "Unable to restore permissions on %s: %s\n");
    899 			(void) fprintf(stderr, errmsg,
    900 			    rname, strerror(saverr));
    901 			(void) fprintf(stderr, gettext(
    902 			    "Additional such failures will be ignored.\n"));
    903 			complained_chmod = 1;
    904 		}
    905 		skipfile();
    906 		metaset(rname); /* skipfile() got the metadata, if any */
    907 		if (utime(rname, (struct utimbuf *)timep) < 0 &&
    908 		    !complained_utime) {
    909 			saverr = errno;
    910 			errmsg = gettext(
    911 			    "Unable to restore times on %s: %s\n");
    912 			(void) fprintf(stderr, errmsg,
    913 			    rname, strerror(saverr));
    914 			(void) fprintf(stderr, gettext(
    915 			    "Additional such failures will be ignored.\n"));
    916 			complained_utime = 1;
    917 		}
    918 		result = GOOD;
    919 		break;
    920 
    921 	case IFREG:
    922 		vprintf(stdout, gettext("extract file %s\n"), rname);
    923 
    924 		/*
    925 		 * perform a restrictive creat(2) initally, we'll
    926 		 * fchmod(2) according to the archive later after
    927 		 * we've written the blocks.
    928 		 */
    929 		ofile = creat64(rname, 0600);
    930 
    931 		if (ofile < 0) {
    932 			saverr = errno;
    933 			errmsg = gettext("cannot create file");
    934 			(void) fprintf(stderr, "%s: ", rname);
    935 			(void) fflush(stderr);
    936 			errno = saverr;
    937 			perror(errmsg);
    938 			skipfile();
    939 			result = FAIL;
    940 			break;
    941 		}
    942 		if (fchown(ofile, uid, gid) < 0 && !complained_chown) {
    943 			/* Just a warning */
    944 			saverr = errno;
    945 			errmsg = gettext(
    946 			    "Unable to restore ownership of %s: %s\n");
    947 			(void) fprintf(stderr, errmsg,
    948 			    rname, strerror(saverr));
    949 			(void) fprintf(stderr, gettext(
    950 			    "Additional such failures will be ignored.\n"));
    951 			complained_chown = 1;
    952 		}
    953 
    954 		getfile(xtrfile, xtrskip);
    955 		metaset(rname);
    956 
    957 		/*
    958 		 * the fchmod(2) has to come after getfile() as some POSIX
    959 		 * implementations clear the S_ISUID and S_ISGID bits of the
    960 		 * file after every write(2).
    961 		 */
    962 		if (fchmod(ofile, mode) < 0 && !complained_chmod) {
    963 			saverr = errno;
    964 			errmsg = gettext(
    965 			    "Unable to restore permissions on %s: %s\n");
    966 			(void) fprintf(stderr, errmsg,
    967 			    rname, strerror(saverr));
    968 			(void) fprintf(stderr, gettext(
    969 			    "Additional such failures will be ignored.\n"));
    970 			complained_chmod = 1;
    971 		}
    972 
    973 		/*
    974 		 * Some errors don't get reported until we close(2), so
    975 		 * check for them.
    976 		 * XXX unlink the file if an error is reported?
    977 		 */
    978 		if (close(ofile) < 0) {
    979 			saverr = errno;
    980 			errmsg = gettext("error closing file");
    981 			(void) fprintf(stderr, "%s: ", rname);
    982 			(void) fflush(stderr);
    983 			errno = saverr;
    984 			perror(errmsg);
    985 			result = FAIL;
    986 			break;
    987 		}
    988 		if (utime(rname, (struct utimbuf *)timep) < 0 &&
    989 		    !complained_utime) {
    990 			saverr = errno;
    991 			errmsg = gettext(
    992 			    "Unable to restore times on %s: %s\n");
    993 			(void) fprintf(stderr, errmsg,
    994 			    rname, strerror(saverr));
    995 			(void) fprintf(stderr, gettext(
    996 			    "Additional such failures will be ignored.\n"));
    997 			complained_utime = 1;
    998 		}
    999 
   1000 		result = GOOD;
   1001 		break;
   1002 	}
   1003 	if (dfd != AT_FDCWD) {
   1004 		fchdir(savepwd);
   1005 		(void) close(dfd);
   1006 	}
   1007 	return (result);
   1008 }
   1009 
   1010 /*
   1011  * skip over bit maps on the tape
   1012  */
   1013 void
   1014 skipmaps(void)
   1015 {
   1016 	continuemap = 1;
   1017 	while (checktype(&spcl, TS_CLRI) == GOOD ||
   1018 	    checktype(&spcl, TS_BITS) == GOOD)
   1019 		skipfile();
   1020 	continuemap = 0;
   1021 }
   1022 
   1023 /*
   1024  * skip over a file on the tape
   1025  */
   1026 void
   1027 skipfile(void)
   1028 {
   1029 	curfile.action = SKIP;
   1030 	getfile(null, null);
   1031 }
   1032 /*
   1033  * Do the file extraction, calling the supplied functions
   1034  * with the blocks
   1035  */
   1036 void
   1037 getfile(void (*f1)(), void (*f2)())
   1038 {
   1039 	int i;
   1040 	size_t curblk = 0;
   1041 	offset_t size = (offset_t)spcl.c_dinode.di_size;
   1042 	static char clearedbuf[MAXBSIZE];
   1043 	char buf[TP_BSIZE_MAX];
   1044 	char *bufptr;
   1045 	char junk[TP_BSIZE_MAX];
   1046 
   1047 	assert(MAXBSIZE >= tp_bsize);
   1048 
   1049 	metaset(NULL);	/* flush old metadata */
   1050 	if (checktype(&spcl, TS_END) == GOOD) {
   1051 		panic(gettext("ran off end of volume\n"));
   1052 		return;
   1053 	}
   1054 	if (ishead(&spcl) == FAIL) {
   1055 		panic(gettext("not at beginning of a file\n"));
   1056 		return;
   1057 	}
   1058 	metacheck(&spcl); /* check for metadata in header */
   1059 	if (!gettingfile && setjmp(restart) != 0) {
   1060 		gettingfile = 0;	/* paranoia; longjmp'er should do */
   1061 		return;
   1062 	}
   1063 	gettingfile++;
   1064 loop:
   1065 	if ((spcl.c_dinode.di_mode & IFMT) == IFSHAD) {
   1066 		f1 = xtrmeta;
   1067 		f2 = metaskip;
   1068 	}
   1069 	for (i = 0, bufptr = buf; i < spcl.c_count; i++) {
   1070 		if ((i >= TP_NINDIR) || (spcl.c_addr[i])) {
   1071 			readtape(bufptr);
   1072 			bufptr += tp_bsize;
   1073 			curblk++;
   1074 			if (curblk == (fssize / tp_bsize)) {
   1075 				(*f1)(buf, size > tp_bsize ?
   1076 				    (size_t)(fssize) :
   1077 					/* LINTED size <= tp_bsize */
   1078 				    (curblk - 1) * tp_bsize + (size_t)size);
   1079 				curblk = 0;
   1080 				bufptr = buf;
   1081 			}
   1082 		} else {
   1083 			if (curblk > 0) {
   1084 				(*f1)(buf, size > tp_bsize ?
   1085 				    (size_t)(curblk * tp_bsize) :
   1086 					/* LINTED size <= tp_bsize */
   1087 				    (curblk - 1) * tp_bsize + (size_t)size);
   1088 				curblk = 0;
   1089 				bufptr = buf;
   1090 			}
   1091 			(*f2)(clearedbuf, size > tp_bsize ?
   1092 					/* LINTED size <= tp_bsize */
   1093 			    (long)tp_bsize : (size_t)size);
   1094 		}
   1095 		if ((size -= tp_bsize) <= 0) {
   1096 			for (i++; i < spcl.c_count; i++)
   1097 				if ((i >= TP_NINDIR) || (spcl.c_addr[i]))
   1098 					readtape(junk);
   1099 			break;
   1100 		}
   1101 	}
   1102 	if (curblk > 0) {
   1103 		/*
   1104 		 * Ok to cast size to size_t here. The above for loop reads
   1105 		 * data into the buffer then writes it to the output file. The
   1106 		 * call to f1 here is to write out the data that's in the
   1107 		 * buffer that has not yet been written to the file.
   1108 		 * This will be less than N-KB of data, since the
   1109 		 * above loop writes to the file in filesystem-
   1110 		 * blocksize chunks.
   1111 		 */
   1112 		/* LINTED: size fits into a size_t at this point */
   1113 		(*f1)(buf, (curblk * tp_bsize) + (size_t)size);
   1114 
   1115 		curblk = 0;
   1116 		bufptr = buf;
   1117 	}
   1118 	if ((readhdr(&spcl) == GOOD) && (checktype(&spcl, TS_ADDR) == GOOD)) {
   1119 		if (continuemap)
   1120 			size = (offset_t)spcl.c_count * tp_bsize;
   1121 							/* big bitmap */
   1122 		else if ((size <= 0) &&
   1123 		    ((spcl.c_dinode.di_mode & IFMT) == IFSHAD)) {
   1124 			/* LINTED unsigned to signed conversion ok */
   1125 			size = spcl.c_dinode.di_size;
   1126 		}
   1127 		if (size > 0)
   1128 			goto loop;
   1129 	}
   1130 	if (size > 0)
   1131 		dprintf(stdout,
   1132 		    gettext("Missing address (header) block for %s\n"),
   1133 		    curfile.name);
   1134 	findinode(&spcl);
   1135 	gettingfile = 0;
   1136 }
   1137 
   1138 /*
   1139  * The next routines are called during file extraction to
   1140  * put the data into the right form and place.
   1141  */
   1142 static void
   1143 xtrfile(char *buf, size_t size)
   1144 {
   1145 	if (write(ofile, buf, (size_t)size) == -1) {
   1146 		int saverr = errno;
   1147 		(void) fprintf(stderr,
   1148 		    gettext("write error extracting inode %d, name %s\n"),
   1149 		    curfile.ino, curfile.name);
   1150 		errno = saverr;
   1151 		perror("write");
   1152 		done(1);
   1153 	}
   1154 }
   1155 
   1156 /*
   1157  * Even though size is a size_t, it's seeking to a relative
   1158  * offset.  Thus, the seek could go beyond 2 GB, so lseek64 is needed.
   1159  */
   1160 
   1161 /*ARGSUSED*/
   1162 static void
   1163 xtrskip(char *buf, size_t size)
   1164 {
   1165 	if (lseek64(ofile, (offset_t)size, 1) == -1) {
   1166 		int saverr = errno;
   1167 		(void) fprintf(stderr,
   1168 		    gettext("seek error extracting inode %d, name %s\n"),
   1169 		    curfile.ino, curfile.name);
   1170 		errno = saverr;
   1171 		perror("lseek64");
   1172 		done(1);
   1173 	}
   1174 }
   1175 
   1176 /* these are local to the next five functions */
   1177 static char *metadata = NULL;
   1178 static size_t metasize = 0;
   1179 
   1180 static void
   1181 metacheck(struct s_spcl *head)
   1182 {
   1183 	if (! (head->c_flags & DR_HASMETA))
   1184 		return;
   1185 	if ((metadata = malloc(metasize = (size_t)sizeof (head->c_shadow)))
   1186 	    == NULL) {
   1187 		(void) fprintf(stderr,
   1188 		    gettext("Cannot malloc for metadata\n"));
   1189 		done(1);
   1190 	}
   1191 	bcopy(&(head->c_shadow), metadata, metasize);
   1192 }
   1193 
   1194 static void
   1195 xtrmeta(char *buf, size_t size)
   1196 {
   1197 	if ((metadata == NULL) && ((spcl.c_dinode.di_mode & IFMT) != IFSHAD))
   1198 		return;
   1199 	if ((metadata = realloc(metadata, metasize + size)) == NULL) {
   1200 		(void) fprintf(stderr,
   1201 		    gettext("Cannot malloc for metadata\n"));
   1202 		done(1);
   1203 	}
   1204 	bcopy(buf, metadata + metasize, size);
   1205 	metasize += size;
   1206 }
   1207 
   1208 /* ARGSUSED */
   1209 static void
   1210 metaskip(char *buf, size_t size)
   1211 {
   1212 	if (metadata == NULL)
   1213 		return;
   1214 	if ((metadata = realloc(metadata, metasize + size)) == NULL) {
   1215 		(void) fprintf(stderr,
   1216 		    gettext("Cannot malloc for metadata\n"));
   1217 		done(1);
   1218 	}
   1219 	bzero(metadata + metasize, size);
   1220 	metasize += size;
   1221 }
   1222 
   1223 static void
   1224 metaset(char *name)
   1225 {
   1226 	if (metadata == NULL)
   1227 		return;
   1228 	if (name != NULL)
   1229 		metaproc(name, metadata, metasize);
   1230 	(void) free(metadata);
   1231 	metadata = NULL;
   1232 	metasize = 0;
   1233 }
   1234 
   1235 void
   1236 metaget(data, size)
   1237 	char **data;
   1238 	size_t *size;
   1239 {
   1240 	*data = metadata;
   1241 	*size = metasize;
   1242 }
   1243 
   1244 static void
   1245 fsd_acl(name, aclp, size)
   1246 	char *name, *aclp;
   1247 	unsigned size;
   1248 {
   1249 	static aclent_t *aclent = NULL;
   1250 	ufs_acl_t *diskacl;
   1251 	static int n = 0;
   1252 	acl_t *set_aclp;
   1253 	uint_t i;
   1254 	int saverr, j;
   1255 
   1256 	if (aclp == NULL) {
   1257 		if (aclent != NULL)
   1258 			free(aclent);
   1259 		aclent = NULL;
   1260 		n = 0;
   1261 		return;
   1262 	}
   1263 
   1264 	/*LINTED [aclp is malloc'd]*/
   1265 	diskacl = (ufs_acl_t *)aclp;
   1266 	/* LINTED: result fits in an int */
   1267 	j = size / sizeof (*diskacl);
   1268 	normacls(byteorder, diskacl, j);
   1269 
   1270 	i = n;
   1271 	n += j;
   1272 	aclent = realloc(aclent, n * (size_t)sizeof (*aclent));
   1273 	if (aclent == NULL) {
   1274 		(void) fprintf(stderr, gettext("Cannot malloc acl list\n"));
   1275 		done(1);
   1276 	}
   1277 
   1278 	j = 0;
   1279 	while (i < n) {
   1280 		aclent[i].a_type = diskacl[j].acl_tag;
   1281 		aclent[i].a_id = diskacl[j].acl_who;
   1282 		aclent[i].a_perm = diskacl[j].acl_perm;
   1283 		++i;
   1284 		++j;
   1285 	}
   1286 
   1287 	set_aclp = acl_to_aclp(ACLENT_T, aclent, n);
   1288 	if (set_aclp == NULL) {
   1289 		(void) fprintf(stderr, gettext("Cannot build acl_t\n"));
   1290 		done(1);
   1291 	}
   1292 
   1293 	if (acl_set(name, set_aclp) == -1) {
   1294 		static int once = 0;
   1295 
   1296 		/*
   1297 		 * Treat some errors from the acl subsystem specially to
   1298 		 * avoid being too noisy:
   1299 		 *
   1300 		 * ENOSYS - ACLs not supported on this file system
   1301 		 * EPERM  - not the owner or not privileged
   1302 		 *
   1303 		 * The following is also supported for backwards compat.
   1304 		 * since acl(2) used to return the wrong errno:
   1305 		 *
   1306 		 * EINVAL - not the owner of the object
   1307 		 */
   1308 		if (errno == ENOSYS || errno == EPERM || errno == EINVAL) {
   1309 			if (once == 0) {
   1310 				saverr = errno;
   1311 				++once;
   1312 				fprintf(stderr,
   1313 				    gettext("setacl failed: %s\n"),
   1314 				    strerror(saverr));
   1315 			}
   1316 		} else {
   1317 			saverr = errno;
   1318 			fprintf(stderr, gettext("setacl on %s failed: %s\n"),
   1319 			    name, strerror(saverr));
   1320 		}
   1321 	}
   1322 	acl_free(set_aclp);
   1323 }
   1324 
   1325 static struct fsdtypes {
   1326 	int type;
   1327 	void (*function)();
   1328 } fsdtypes[] = {
   1329 	{FSD_ACL, fsd_acl},
   1330 	{FSD_DFACL, fsd_acl},
   1331 	{0, NULL}
   1332 };
   1333 
   1334 void
   1335 metaproc(char *name, char *mdata, size_t msize)
   1336 {
   1337 	struct fsdtypes *fsdtype;
   1338 	ufs_fsd_t *fsd;
   1339 	char *c;
   1340 
   1341 	/*
   1342 	 * for the whole shadow inode, dispatch each piece
   1343 	 * to the appropriate function.
   1344 	 */
   1345 	c = mdata;
   1346 	/* LINTED (c - mdata) fits into a size_t */
   1347 	while ((size_t)(c - mdata) < msize) {
   1348 		/*LINTED [mdata is malloc'd]*/
   1349 		fsd = (ufs_fsd_t *)c;
   1350 		assert((fsd->fsd_size % 4) == 0);
   1351 		/* LINTED: lint thinks pointers are signed */
   1352 		c += FSD_RECSZ(fsd, fsd->fsd_size);
   1353 		if ((fsd->fsd_type == FSD_FREE) ||
   1354 		    ((unsigned)(fsd->fsd_size) <= sizeof (ufs_fsd_t)) ||
   1355 		    (c > (mdata + msize)))
   1356 			break;
   1357 		for (fsdtype = fsdtypes; fsdtype->type; fsdtype++)
   1358 			if (fsdtype->type == fsd->fsd_type)
   1359 				(*fsdtype->function)(name, fsd->fsd_data,
   1360 				    (unsigned)(fsd->fsd_size) -
   1361 				    sizeof (fsd->fsd_type) -
   1362 				    sizeof (fsd->fsd_size));
   1363 		/* ^^^ be sure to change if fsd ever changes ^^^ */
   1364 	}
   1365 
   1366 	/* reset the state of all the functions */
   1367 	for (fsdtype = fsdtypes; fsdtype->type; fsdtype++)
   1368 		(*fsdtype->function)(NULL, NULL, 0);
   1369 }
   1370 
   1371 static void
   1372 xtrlnkfile(char *buf, size_t size)
   1373 {
   1374 	/* LINTED: signed/unsigned mix ok */
   1375 	pathlen += size;
   1376 	if (pathlen > MAXPATHLEN) {
   1377 		(void) fprintf(stderr,
   1378 		    gettext("symbolic link name: %s->%s%s; too long %d\n"),
   1379 		    curfile.name, lnkbuf, buf, pathlen);
   1380 		done(1);
   1381 	}
   1382 	buf[size] = '\0';
   1383 	(void) strcat(lnkbuf, buf);
   1384 	/* add an extra NULL to make this a legal complex string */
   1385 	lnkbuf[pathlen+1] = '\0';
   1386 }
   1387 
   1388 /*ARGSUSED*/
   1389 static void
   1390 xtrlnkskip(char *buf, size_t size)
   1391 {
   1392 	(void) fprintf(stderr,
   1393 	    gettext("unallocated block in symbolic link %s\n"),
   1394 	    curfile.name);
   1395 	done(1);
   1396 }
   1397 
   1398 static void
   1399 xtrmap(char *buf, size_t size)
   1400 {
   1401 	if ((map+size) > endmap) {
   1402 		int64_t mapsize, increment;
   1403 		int64_t diff;
   1404 
   1405 		if (spcl.c_type != TS_ADDR) {
   1406 			(void) fprintf(stderr,
   1407 			    gettext("xtrmap: current record not TS_ADDR\n"));
   1408 			done(1);
   1409 		}
   1410 		if ((spcl.c_count < 0) || (spcl.c_count > TP_NINDIR)) {
   1411 			(void) fprintf(stderr,
   1412 			    gettext("xtrmap: illegal c_count field (%d)\n"),
   1413 			    spcl.c_count);
   1414 			done(1);
   1415 		}
   1416 
   1417 		increment = d_howmany(
   1418 		    ((spcl.c_count * tp_bsize * NBBY) + 1), NBBY);
   1419 		mapsize = endmap - beginmap + increment;
   1420 		if (mapsize > UINT_MAX) {
   1421 			(void) fprintf(stderr,
   1422 			    gettext("xtrmap: maximum bitmap size exceeded"));
   1423 			done(1);
   1424 		}
   1425 
   1426 		diff = map - beginmap;
   1427 		/* LINTED mapsize checked above */
   1428 		beginmap = realloc(beginmap, (size_t)mapsize);
   1429 		if (beginmap == NULL) {
   1430 			(void) fprintf(stderr,
   1431 			    gettext("xtrmap: realloc failed\n"));
   1432 			done(1);
   1433 		}
   1434 		map = beginmap + diff;
   1435 		endmap = beginmap + mapsize;
   1436 		/* LINTED endmap - map cannot exceed 32 bits */
   1437 		bzero(map, (size_t)(endmap - map));
   1438 		maxino = NBBY * mapsize + 1;
   1439 	}
   1440 
   1441 	bcopy(buf, map, size);
   1442 	/* LINTED character pointers aren't signed */
   1443 	map += size;
   1444 }
   1445 
   1446 /*ARGSUSED*/
   1447 static void
   1448 xtrmapskip(char *buf, size_t size)
   1449 {
   1450 	(void) fprintf(stderr, gettext("hole in map\n"));
   1451 	done(1);
   1452 }
   1453 
   1454 /*ARGSUSED*/
   1455 void
   1456 null(char *buf, size_t size)
   1457 {
   1458 }
   1459 
   1460 /*
   1461  * Do the tape i/o, dealing with volume changes
   1462  * etc..
   1463  */
   1464 static void
   1465 readtape(char *b)
   1466 {
   1467 	int i;
   1468 	int rd, newvol;
   1469 	int cnt;
   1470 	struct s_spcl *sp;
   1471 	int32_t	expected_magic;
   1472 
   1473 	if (tbf == NULL) {
   1474 		(void) fprintf(stderr, gettext(
   1475 		    "Internal consistency failure in readtape: tbf is NULL\n"));
   1476 		done(1);
   1477 	}
   1478 	expected_magic = ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC);
   1479 
   1480 top:
   1481 	if (bct < numtrec) {
   1482 		/*
   1483 		 * check for old-dump floppy EOM -- it may appear in
   1484 		 * the middle of a buffer.  The Dflag used to be used for
   1485 		 * this, but since it doesn't hurt to always do this we
   1486 		 * got rid of the Dflag.
   1487 		 */
   1488 		/*LINTED [tbf = malloc()]*/
   1489 		sp = &((union u_spcl *)&tbf[bct*tp_bsize])->s_spcl;
   1490 		if (sp->c_magic == expected_magic && sp->c_type == TS_EOM &&
   1491 		    (time_t)(sp->c_date) == dumpdate &&
   1492 		    (time_t)(sp->c_ddate) == dumptime) {
   1493 			for (i = 0; i < ntrec; i++)
   1494 				/*LINTED [tbf = malloc()]*/
   1495 				((struct s_spcl *)
   1496 				    &tbf[i*tp_bsize])->c_magic = 0;
   1497 			bct = 0;
   1498 			rd = 0;
   1499 			i = 0;
   1500 			goto nextvol;
   1501 		}
   1502 		bcopy(&tbf[(bct++*tp_bsize)], b, (size_t)tp_bsize);
   1503 		blksread++;
   1504 		tapea++;
   1505 		return;
   1506 	}
   1507 	/*LINTED [assertion always true]*/
   1508 	assert(sizeof (union u_spcl) == TP_BSIZE_MAX);
   1509 	for (i = 0; i < ntrec; i++)
   1510 		/*LINTED [tbf = malloc()]*/
   1511 		((struct s_spcl *)&tbf[i*sizeof (struct s_spcl)])->c_magic = 0;
   1512 	if (numtrec == 0) {
   1513 		/* LINTED unsigned/signed assignment ok */
   1514 		numtrec = ntrec;
   1515 	}
   1516 	/* LINTED unsigned/signed assignment ok */
   1517 	cnt = ntrec*tp_bsize;
   1518 	rd = 0;
   1519 getmore:
   1520 	if (host)
   1521 		i = rmtread(&tbf[rd], cnt);
   1522 	else
   1523 		i = read(mt, &tbf[rd], cnt);
   1524 	/*
   1525 	 * Check for mid-tape short read error.
   1526 	 * If found, return rest of buffer.
   1527 	 */
   1528 	if (numtrec < ntrec && i != 0) {
   1529 		/* LINTED unsigned/signed assignment ok */
   1530 		numtrec = ntrec;
   1531 		goto top;
   1532 	}
   1533 	/*
   1534 	 * Handle partial block read.
   1535 	 */
   1536 	if (i > 0 && i != ntrec*tp_bsize) {
   1537 		if (pipein) {
   1538 			rd += i;
   1539 			cnt -= i;
   1540 			if (cnt > 0)
   1541 				goto getmore;
   1542 			i = rd;
   1543 		} else {
   1544 			if (i % tp_bsize != 0)
   1545 				panic(gettext(
   1546 				    "partial block read: %d should be %d\n"),
   1547 				    i, ntrec * tp_bsize);
   1548 			numtrec = i / tp_bsize;
   1549 			if (numtrec == 0)
   1550 				/*
   1551 				 * it's possible to read only 512 bytes
   1552 				 * from a QIC device...
   1553 				 */
   1554 				i = 0;
   1555 		}
   1556 	}
   1557 	/*
   1558 	 * Handle read error.
   1559 	 */
   1560 	if (i < 0) {
   1561 		switch (curfile.action) {
   1562 		default:
   1563 			(void) fprintf(stderr, gettext(
   1564 			    "Read error while trying to set up volume\n"));
   1565 			break;
   1566 		case UNKNOWN:
   1567 			(void) fprintf(stderr, gettext(
   1568 			    "Read error while trying to resynchronize\n"));
   1569 			break;
   1570 		case USING:
   1571 			(void) fprintf(stderr, gettext(
   1572 			    "Read error while restoring %s\n"),
   1573 			    curfile.name);
   1574 			break;
   1575 		case SKIP:
   1576 			(void) fprintf(stderr, gettext(
   1577 			    "Read error while skipping over inode %d\n"),
   1578 			    curfile.ino);
   1579 			break;
   1580 		}
   1581 		if (!yflag && !reply(gettext("continue")))
   1582 			done(1);
   1583 		/* LINTED: unsigned->signed conversion ok */
   1584 		i = (int)(ntrec*tp_bsize);
   1585 		bzero(tbf, (size_t)i);
   1586 		if ((host != 0 && rmtseek(i, 1) < 0) ||
   1587 		    (host == 0 && (lseek64(mt, (offset_t)i, 1) ==
   1588 		    (off64_t)-1))) {
   1589 			perror(gettext("continuation failed"));
   1590 			done(1);
   1591 		}
   1592 	}
   1593 	/*
   1594 	 * Handle end of tape.  The Dflag used to be used, but since it doesn't
   1595 	 * hurt to always check we got rid if it.
   1596 	 */
   1597 
   1598 	/*
   1599 	 * if the first record in the buffer just read is EOM,
   1600 	 * change volumes.
   1601 	 */
   1602 	/*LINTED [tbf = malloc()]*/
   1603 	sp = &((union u_spcl *)tbf)->s_spcl;
   1604 	if (i != 0 && sp->c_magic == expected_magic && sp->c_type == TS_EOM &&
   1605 	    (time_t)(sp->c_date) == dumpdate &&
   1606 	    (time_t)(sp->c_ddate) == dumptime) {
   1607 		i = 0;
   1608 	}
   1609 nextvol:
   1610 	if (i == 0) {
   1611 		if (!pipein) {
   1612 			newvol = volno + 1;
   1613 			volno = 0;
   1614 			numtrec = 0;
   1615 			getvol(newvol);
   1616 			readtape(b); /* XXX tail recursion, not goto top? */
   1617 			return;
   1618 		}
   1619 		/* XXX if panic returns, should we round rd up? */
   1620 		/* XXX if we do, then we should zero the intervening space */
   1621 		if (rd % tp_bsize != 0)
   1622 			panic(gettext("partial block read: %d should be %d\n"),
   1623 			    rd, ntrec * tp_bsize);
   1624 		bcopy((char *)&endoftapemark, &tbf[rd], (size_t)tp_bsize);
   1625 	}
   1626 	bct = 0;
   1627 	bcopy(&tbf[(bct++*tp_bsize)], b, (size_t)tp_bsize);
   1628 	blksread++;
   1629 	recsread++;
   1630 	tapea++;
   1631 	rec_position++;
   1632 }
   1633 
   1634 void
   1635 findtapeblksize(int arfile)
   1636 {
   1637 	int	i;
   1638 
   1639 	if (tbf == NULL) {
   1640 		(void) fprintf(stderr, gettext(
   1641 		    "Internal consistency failure in findtapeblksize: "
   1642 		    "tbf is NULL\n"));
   1643 		assert(tbf != NULL);
   1644 		done(1);
   1645 	}
   1646 
   1647 	for (i = 0; i < ntrec; i++)
   1648 		/*LINTED [tbf = malloc()]*/
   1649 		((struct s_spcl *)&tbf[i * tp_bsize])->c_magic = 0;
   1650 	bct = 0;
   1651 	if (host && arfile == TAPE_FILE)
   1652 		tape_rec_size = rmtread(tbf, ntrec * tp_bsize);
   1653 	else
   1654 		tape_rec_size = read(mt, tbf, ntrec * tp_bsize);
   1655 	recsread++;
   1656 	rec_position++;
   1657 	if (tape_rec_size == (ssize_t)-1) {
   1658 		int saverr = errno;
   1659 		char *errmsg = gettext("Media read error");
   1660 		errno = saverr;
   1661 		perror(errmsg);
   1662 		done(1);
   1663 	}
   1664 	if (tape_rec_size % tp_bsize != 0) {
   1665 		(void) fprintf(stderr, gettext(
   1666 	    "Record size (%d) is not a multiple of dump block size (%d)\n"),
   1667 		    tape_rec_size, tp_bsize);
   1668 		done(1);
   1669 	}
   1670 	ntrec = (int)tape_rec_size / tp_bsize;
   1671 	/* LINTED unsigned/signed assignment ok */
   1672 	numtrec = ntrec;
   1673 	vprintf(stdout, gettext("Media block size is %d\n"), ntrec*2);
   1674 }
   1675 
   1676 void
   1677 flsht(void)
   1678 {
   1679 	/* LINTED unsigned/signed assignment ok */
   1680 	bct = ntrec+1;
   1681 }
   1682 
   1683 void
   1684 closemt(int mode)
   1685 {
   1686 	/*
   1687 	 * If mode == FORCE_OFFLINE then we're not done but
   1688 	 * we need to change tape. So, rewind and unload current
   1689 	 * tape before loading the new one.
   1690 	 */
   1691 
   1692 	static struct mtop mtop = { MTOFFL, 0 };
   1693 
   1694 	if (mt < 0)
   1695 		return;
   1696 	if (offline || mode == FORCE_OFFLINE)
   1697 		(void) fprintf(stderr, gettext("Rewinding tape\n"));
   1698 	if (host) {
   1699 		if (offline || mode == FORCE_OFFLINE)
   1700 			(void) rmtioctl(MTOFFL, 1);
   1701 		rmtclose();
   1702 	} else if (pipein) {
   1703 		char buffy[MAXBSIZE];
   1704 
   1705 		while (read(mt, buffy, sizeof (buffy)) > 0) {
   1706 			continue;
   1707 			/*LINTED [assertion always true]*/
   1708 		}
   1709 		(void) close(mt);
   1710 	} else {
   1711 		/*
   1712 		 * Only way to tell if this is a floppy is to issue an ioctl
   1713 		 * but why waste one - if the eject fails, tough!
   1714 		 */
   1715 		if (offline || mode == FORCE_OFFLINE)
   1716 			(void) ioctl(mt, MTIOCTOP, &mtop);
   1717 		(void) ioctl(mt, FDEJECT, 0);
   1718 		(void) close(mt);
   1719 	}
   1720 	mt = -1;
   1721 }
   1722 
   1723 static int
   1724 checkvol(struct s_spcl *b, int t)
   1725 {
   1726 
   1727 	if (b->c_volume != t)
   1728 		return (FAIL);
   1729 	return (GOOD);
   1730 }
   1731 
   1732 int
   1733 readhdr(struct s_spcl *b)
   1734 {
   1735 
   1736 	if (gethead(b) == FAIL) {
   1737 		dprintf(stdout, gettext("readhdr fails at %ld blocks\n"),
   1738 		    blksread);
   1739 		return (FAIL);
   1740 	}
   1741 	return (GOOD);
   1742 }
   1743 
   1744 /*
   1745  * read the tape into buf, then return whether or
   1746  * or not it is a header block.
   1747  */
   1748 int
   1749 gethead(struct s_spcl *buf)
   1750 {
   1751 	int i;
   1752 	union u_ospcl {
   1753 		char dummy[TP_BSIZE_MIN];
   1754 		struct	s_ospcl {
   1755 			int32_t	c_type;
   1756 			int32_t	c_date;
   1757 			int32_t	c_ddate;
   1758 			int32_t	c_volume;
   1759 			int32_t	c_tapea;
   1760 			ushort_t c_inumber;
   1761 			int32_t	c_magic;
   1762 			int32_t	c_checksum;
   1763 			struct odinode {
   1764 				unsigned short odi_mode;
   1765 				ushort_t odi_nlink;
   1766 				ushort_t odi_uid;
   1767 				ushort_t odi_gid;
   1768 				int32_t	odi_size;
   1769 				int32_t	odi_rdev;
   1770 				char	odi_addr[36];
   1771 				int32_t	odi_atime;
   1772 				int32_t	odi_mtime;
   1773 				int32_t	odi_ctime;
   1774 			} c_dinode;
   1775 			int32_t	c_count;
   1776 			char	c_baddr[256];
   1777 		} s_ospcl;
   1778 	} u_ospcl;
   1779 
   1780 	if (cvtflag) {
   1781 		readtape((char *)(&u_ospcl.s_ospcl));
   1782 		bzero((char *)buf, (size_t)TP_BSIZE_MIN);
   1783 		buf->c_type = u_ospcl.s_ospcl.c_type;
   1784 		buf->c_date = u_ospcl.s_ospcl.c_date;
   1785 		buf->c_ddate = u_ospcl.s_ospcl.c_ddate;
   1786 		buf->c_volume = u_ospcl.s_ospcl.c_volume;
   1787 		buf->c_tapea = u_ospcl.s_ospcl.c_tapea;
   1788 		buf->c_inumber = u_ospcl.s_ospcl.c_inumber;
   1789 		buf->c_checksum = u_ospcl.s_ospcl.c_checksum;
   1790 		buf->c_magic = u_ospcl.s_ospcl.c_magic;
   1791 		buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode;
   1792 		/* LINTED: unsigned/signed combination ok */
   1793 		buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink;
   1794 		buf->c_dinode.di_size =
   1795 		    (unsigned)(u_ospcl.s_ospcl.c_dinode.odi_size);
   1796 		buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid;
   1797 		buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid;
   1798 		buf->c_dinode.di_suid = UID_LONG;
   1799 		buf->c_dinode.di_sgid = GID_LONG;
   1800 		buf->c_dinode.di_ordev = u_ospcl.s_ospcl.c_dinode.odi_rdev;
   1801 		buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime;
   1802 		buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime;
   1803 		buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime;
   1804 		buf->c_count = u_ospcl.s_ospcl.c_count;
   1805 		bcopy(u_ospcl.s_ospcl.c_baddr, buf->c_addr,
   1806 		    sizeof (u_ospcl.s_ospcl.c_baddr));
   1807 
   1808 		/*CONSTANTCONDITION*/
   1809 		assert(sizeof (u_ospcl.s_ospcl) < sizeof (union u_spcl));
   1810 
   1811 		/* we byte-swap the new spclrec, but checksum the old	*/
   1812 		/* (see comments in normspcl())				*/
   1813 		if (normspcl(byteorder, buf,
   1814 		    (int *)(&u_ospcl.s_ospcl), sizeof (u_ospcl.s_ospcl),
   1815 		    OFS_MAGIC))
   1816 			return (FAIL);
   1817 		buf->c_magic =
   1818 		    ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC);
   1819 	} else {
   1820 		readtape((char *)buf);
   1821 		if (normspcl(byteorder, buf, (int *)buf, tp_bsize,
   1822 		    ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC)))
   1823 			return (FAIL);
   1824 	}
   1825 
   1826 	switch (buf->c_type) {
   1827 
   1828 	case TS_CLRI:
   1829 	case TS_BITS:
   1830 		/*
   1831 		 * Have to patch up missing information in bit map headers
   1832 		 */
   1833 		buf->c_inumber = 0;
   1834 		buf->c_dinode.di_size = (offset_t)buf->c_count * tp_bsize;
   1835 		for (i = 0; i < buf->c_count && i < TP_NINDIR; i++)
   1836 			buf->c_addr[i] = 1;
   1837 		break;
   1838 
   1839 	case TS_TAPE:
   1840 	case TS_END:
   1841 		if (dumpinfo.c_date == 0) {
   1842 			dumpinfo.c_date = spcl.c_date;
   1843 			dumpinfo.c_ddate = spcl.c_ddate;
   1844 		}
   1845 		if (!hostinfo && spcl.c_host[0] != '\0') {
   1846 			bcopy(spcl.c_label, dumpinfo.c_label,
   1847 			    sizeof (spcl.c_label));
   1848 			bcopy(spcl.c_filesys, dumpinfo.c_filesys,
   1849 			    sizeof (spcl.c_filesys));
   1850 			bcopy(spcl.c_dev, dumpinfo.c_dev,
   1851 			    sizeof (spcl.c_dev));
   1852 			bcopy(spcl.c_host, dumpinfo.c_host,
   1853 			    sizeof (spcl.c_host));
   1854 			dumpinfo.c_level = spcl.c_level;
   1855 			hostinfo++;
   1856 			if (c_label != NULL &&
   1857 			    strncmp(c_label, spcl.c_label,
   1858 			    sizeof (spcl.c_label))
   1859 			    != 0) {
   1860 				(void) fprintf(stderr, gettext(
   1861 		    "Incorrect tape label.  Expected `%s', got `%.*s'\n"),
   1862 				    c_label,
   1863 				    sizeof (spcl.c_label), spcl.c_label);
   1864 				done(1);
   1865 			}
   1866 		}
   1867 		if (!inodeinfo && (spcl.c_flags & DR_INODEINFO)) {
   1868 			dumpinfo.c_volume = spcl.c_volume;
   1869 			bcopy(spcl.c_inos, dumpinfo.c_inos,
   1870 			    sizeof (spcl.c_inos));
   1871 			inodeinfo++;
   1872 		}
   1873 		buf->c_inumber = 0;
   1874 		break;
   1875 
   1876 	case TS_INODE:
   1877 	case TS_ADDR:
   1878 		break;
   1879 
   1880 	default:
   1881 		panic(gettext("%s: unknown inode type %d\n"),
   1882 		    "gethead", buf->c_type);
   1883 		return (FAIL);
   1884 	}
   1885 	if (dflag)
   1886 		accthdr(buf);
   1887 	return (GOOD);
   1888 }
   1889 
   1890 /*
   1891  * Check that a header is where it belongs and predict the next header
   1892  */
   1893 static void
   1894 accthdr(struct s_spcl *header)
   1895 {
   1896 	static ino_t previno = (ino_t)(unsigned)-1;
   1897 	static int prevtype;
   1898 	static long predict;
   1899 	int blks, i;
   1900 
   1901 	if (header->c_type == TS_TAPE) {
   1902 		if (header->c_firstrec)
   1903 			(void) fprintf(stderr,
   1904 			    gettext("Volume header begins with record %d"),
   1905 			    header->c_firstrec);
   1906 		else
   1907 			(void) fprintf(stderr, gettext("Volume header"));
   1908 		(void) fprintf(stderr, "\n");
   1909 		previno = (ino_t)(unsigned)-1;
   1910 		return;
   1911 	}
   1912 	if (previno == (ino_t)(unsigned)-1)
   1913 		goto newcalc;
   1914 	switch (prevtype) {
   1915 	case TS_BITS:
   1916 		(void) fprintf(stderr, gettext("Dump mask header"));
   1917 		break;
   1918 	case TS_CLRI:
   1919 		(void) fprintf(stderr, gettext("Remove mask header"));
   1920 		break;
   1921 	case TS_INODE:
   1922 		(void) fprintf(stderr,
   1923 		    gettext("File header, ino %d at record %d"),
   1924 		    previno, rec_position);
   1925 		break;
   1926 	case TS_ADDR:
   1927 		(void) fprintf(stderr,
   1928 		    gettext("File continuation header, ino %d"),
   1929 		    previno);
   1930 		break;
   1931 	case TS_END:
   1932 		(void) fprintf(stderr, gettext("End of media header"));
   1933 		break;
   1934 	}
   1935 	if (predict != blksread - 1)
   1936 		(void) fprintf(stderr,
   1937 		    gettext("; predicted %ld blocks, got %ld blocks"),
   1938 		    predict, blksread - 1);
   1939 	(void) fprintf(stderr, "\n");
   1940 newcalc:
   1941 	blks = 0;
   1942 	if (header->c_type != TS_END)
   1943 		for (i = 0; i < header->c_count; i++)
   1944 			if ((i >= TP_NINDIR) || (header->c_addr[i] != 0))
   1945 				blks++;
   1946 	predict = blks;
   1947 	blksread = 0;
   1948 	prevtype = header->c_type;
   1949 	previno = header->c_inumber;
   1950 }
   1951 
   1952 /*
   1953  * Try to determine which volume a file resides on.
   1954  */
   1955 int
   1956 volnumber(ino_t inum)
   1957 {
   1958 	int i;
   1959 
   1960 	if (inodeinfo == 0)
   1961 		return (0);
   1962 	for (i = 1; i <= dumpinfo.c_volume; i++)
   1963 		if (inum < (ino_t)(unsigned)(dumpinfo.c_inos[i]))
   1964 			break;
   1965 	return (i - 1);
   1966 }
   1967 
   1968 /*
   1969  * Find an inode header.
   1970  * Note that *header must be stable storage, as curfile will end up with
   1971  * pointers into it.
   1972  */
   1973 void
   1974 findinode(struct s_spcl *header)
   1975 {
   1976 	long skipcnt = 0;
   1977 	int i;
   1978 	char buf[TP_BSIZE_MAX];
   1979 
   1980 	curfile.name = gettext("<name unknown>");
   1981 	curfile.action = UNKNOWN;
   1982 	curfile.dip = (struct dinode *)NULL;
   1983 	curfile.ino = 0;
   1984 	curfile.ts = 0;
   1985 	if (ishead(header) == FAIL) {
   1986 		skipcnt++;
   1987 		while (gethead(header) == FAIL ||
   1988 		    (time_t)(header->c_date) != dumpdate)
   1989 			skipcnt++;
   1990 	}
   1991 	for (;;) {
   1992 		if (checktype(header, TS_ADDR) == GOOD) {
   1993 			/*
   1994 			 * Skip up to the beginning of the next record
   1995 			 */
   1996 			for (i = 0; i < header->c_count; i++)
   1997 				if ((i >= TP_NINDIR) || (header->c_addr[i]))
   1998 					readtape(buf);
   1999 			(void) gethead(header);
   2000 			continue;
   2001 		}
   2002 		if (checktype(header, TS_INODE) == GOOD) {
   2003 			curfile.dip = &header->c_dinode;
   2004 			if (curfile.dip->di_suid != UID_LONG)
   2005 				curfile.dip->di_uid = curfile.dip->di_suid;
   2006 			if (curfile.dip->di_sgid != GID_LONG)
   2007 				curfile.dip->di_gid = curfile.dip->di_sgid;
   2008 			curfile.ino = header->c_inumber;
   2009 			curfile.ts = TS_INODE;
   2010 			break;
   2011 		}
   2012 		if (checktype(header, TS_END) == GOOD) {
   2013 			curfile.ino = maxino;
   2014 			curfile.ts = TS_END;
   2015 			break;
   2016 		}
   2017 		if (checktype(header, TS_CLRI) == GOOD) {
   2018 			curfile.name = gettext("<file removal list>");
   2019 			curfile.ts = TS_CLRI;
   2020 			break;
   2021 		}
   2022 		if (checktype(header, TS_BITS) == GOOD) {
   2023 			curfile.name = gettext("<file dump list>");
   2024 			curfile.ts = TS_BITS;
   2025 			break;
   2026 		}
   2027 		while (gethead(header) == FAIL)
   2028 			skipcnt++;
   2029 	}
   2030 	if (skipcnt > 0)
   2031 		(void) fprintf(stderr,
   2032 		    gettext("resync restore, skipped %d blocks\n"),
   2033 		    skipcnt);
   2034 }
   2035 
   2036 /*
   2037  * return whether or not the buffer contains a header block
   2038  */
   2039 static int
   2040 ishead(struct s_spcl *buf)
   2041 {
   2042 	if (buf->c_magic !=
   2043 	    ((tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC))
   2044 		return (FAIL);
   2045 	return (GOOD);
   2046 }
   2047 
   2048 static int
   2049 checktype(struct s_spcl *b, int t)
   2050 {
   2051 	if (b->c_type != t)
   2052 		return (FAIL);
   2053 	return (GOOD);
   2054 }
   2055 
   2056 /*
   2057  * If autoloading is enabled, attempt to do it.  If we succeed,
   2058  * return non-zero.
   2059  */
   2060 static int
   2061 autoload_tape(void)
   2062 {
   2063 	int result = 0;		/* assume failure */
   2064 	int tries;
   2065 	int fd;
   2066 
   2067 	if (autoload) {
   2068 		/*
   2069 		 * Wait for the tape to autoload.  Note that the delay
   2070 		 * period doesn't take into account however long it takes
   2071 		 * for the open to fail (measured at 21 seconds for an
   2072 		 * Exabyte 8200 under 2.7 on an Ultra 2).
   2073 		 */
   2074 
   2075 		/* rewind tape and offline drive before loading new tape */
   2076 		closemt(FORCE_OFFLINE);
   2077 		(void) fprintf(stderr,
   2078 		    gettext("Attempting to autoload next volume\n"));
   2079 		for (tries = 0; tries < autoload_tries; tries++) {
   2080 			if (host) {
   2081 				if (rmtopen(magtape, O_RDONLY) >= 0) {
   2082 					rmtclose();
   2083 					result = 1;
   2084 					break;
   2085 				}
   2086 			} else {
   2087 				if ((fd = open(magtape, O_RDONLY|O_LARGEFILE,
   2088 				    0600)) >= 0) {
   2089 					(void) close(fd);
   2090 					result = 1;
   2091 					break;
   2092 				}
   2093 			}
   2094 			(void) sleep(autoload_period);
   2095 		}
   2096 		if (result == 0) {
   2097 			/* Assume caller will deal with manual change-over */
   2098 			(void) fprintf(stderr,
   2099 			    gettext("Autoload timed out\n"));
   2100 		} else {
   2101 			if ((host != NULL &&
   2102 			    (mt = rmtopen(magtape, O_RDONLY)) == -1) ||
   2103 			    (host == NULL &&
   2104 			    (mt = open(magtape, O_RDONLY|O_LARGEFILE)) == -1)) {
   2105 				(void) fprintf(stderr, gettext(
   2106 				    "Autoload could not re-open tape\n"));
   2107 				result = 0;
   2108 			} else {
   2109 				(void) fprintf(stderr, gettext(
   2110 				    "Tape loaded\n"));
   2111 			}
   2112 		}
   2113 	}
   2114 
   2115 	return (result);
   2116 }
   2117