1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
27/*	  All Rights Reserved	*/
28
29/*
30 * Portions of this source code were derived from Berkeley 4.3 BSD
31 * under license from the Regents of the University of California.
32 */
33
34#include "dump.h"
35#include <rmt.h>
36#include <setjmp.h>
37#include <sys/fdio.h>
38#include <sys/mkdev.h>
39#include <assert.h>
40#include <limits.h>
41
42#define	SLEEPMS		50
43
44static uint_t writesize;	/* size of malloc()ed buffer for tape */
45static ino_t inos[TP_NINOS];	/* starting inodes on each tape */
46
47/*
48 * The req structure is used to pass commands from the parent
49 * process through the pipes to the slave processes.  It comes
50 * in two flavors, depending on which mode dump is operating under:
51 * an inode request (on-line mode) and a disk block request ("old" mode).
52 */
53/*
54 * The inode request structure is used during on-line mode.
55 * The master passes inode numbers and starting offsets to
56 * the slaves.  The tape writer passes out the current inode,
57 * offset, and number of tape records written after completing a volume.
58 */
59struct ireq {
60	ino_t	inumber;	/* inode number to open/dump */
61	long	igen;		/* inode generation number */
62	off_t	offset;		/* starting offset in inode */
63	int	count;		/* count for 1st spclrec */
64};
65/*
66 * The block request structure is used in off-line mode to pass
67 * commands to dump disk blocks from the parent process through
68 * the pipes to the slave processes.
69 */
70struct breq {
71	diskaddr_t dblk;		/* disk address to read */
72	size_t	size;		/* number of bytes to read from disk */
73	ulong_t	spclrec[1];	/* actually longer */
74};
75
76struct req {
77	short	aflag;		/* write data to archive process as well */
78	short	tflag;		/* begin new tape */
79	union	reqdata {
80		struct ireq ino;	/* used for on-line mode */
81		struct breq blks;	/* used for off-line mode */
82	} data;
83};
84
85#define	ir_inumber	data.ino.inumber
86#define	ir_igen		data.ino.igen
87#define	ir_offset	data.ino.offset
88#define	ir_count	data.ino.count
89
90#define	br_dblk		data.blks.dblk
91#define	br_size		data.blks.size
92#define	br_spcl		data.blks.spclrec
93
94static int reqsiz = 0;	/* alloctape will initialize */
95
96#define	SLAVES 3
97struct slaves {
98	int	sl_slavefd;	/* pipe from master to slave */
99	pid_t	sl_slavepid;	/* slave pid; used by killall() */
100	ino_t	sl_inos;	/* inos, if this record starts tape */
101	int	sl_offset;	/* logical blocks written for object */
102	int	sl_count;	/* logical blocks left in spclrec */
103	int	sl_tapea;	/* header number, if starting tape */
104	int	sl_firstrec;	/* number of first block on tape */
105	int	sl_state;	/* dump output state */
106	struct	req *sl_req;	/* instruction packet to slave */
107};
108static struct slaves slaves[SLAVES];	/* one per slave */
109static struct slaves *slp;	/* pointer to current slave */
110static struct slaves chkpt;	/* checkpointed data */
111
112struct bdesc {
113	char	*b_data;	/* pointer to buffer data */
114	int	b_flags;	/* flags (see below) */
115};
116
117/*
118 * The following variables are in shared memory, and must be
119 * explicitly checkpointed and/or reset.
120 */
121static caddr_t shared;		/* pointer to block of shared memory */
122static struct bdesc *bufp;	/* buffer descriptors */
123static struct bdesc **current;	/* output buffer to fill */
124static int *tapea;		/* logical record count */
125
126#ifdef INSTRUMENT
127static int	*readmissp;	/* number of times writer was idle */
128static int	*idle;		/* number of times slaves were idle */
129#endif	/* INSTRUMENT */
130
131/*
132 * Buffer flags
133 */
134#define	BUF_EMPTY	0x0	/* nothing in buffer */
135#define	BUF_FULL	0x1	/* data in buffer */
136#define	BUF_SPCLREC	0x2	/* contains special record */
137#define	BUF_ARCHIVE	0x4	/* dump to archive */
138
139static int recsout;		/* number of req's sent to slaves */
140static int totalrecsout;	/* total number of req's sent to slaves */
141static int rotor;		/* next slave to be instructed */
142static pid_t master;		/* pid of master, for sending error signals */
143static int writer = -1;		/* fd of tape writer */
144static pid_t writepid;		/* pid of tape writer */
145static int arch;		/* fd of output archiver */
146static pid_t archivepid;	/* pid of output archiver */
147static int archivefd;		/* fd of archive file (proper) */
148static offset_t lf_archoffset;	/* checkpointed offset into archive file */
149
150int caught;			/* caught signal -- imported by mapfile() */
151
152#ifdef DEBUG
153extern	int xflag;
154#endif
155
156#ifdef __STDC__
157static void cmdwrterr(void);
158static void cmdrderr(void);
159static void freetape(void);
160static void bufclear(void);
161static pid_t setuparchive(void);
162static pid_t setupwriter(void);
163static void nextslave(void);
164static void tperror(int);
165static void rollforward(int);
166static void nap(int);
167static void alrm(int);
168static void just_rewind(void);
169static void killall(void);
170static void proceed(int);
171static void die(int);
172static void enslave(void);
173static void wait_our_turn(void);
174static void dumpoffline(int, pid_t, int);
175static void onxfsz(int);
176static void dowrite(int);
177static void checkpoint(struct bdesc *, int);
178static ssize_t atomic(int (*)(), int, char *, int);
179#else
180static void cmdwrterr();
181static void cmdrderr();
182static void freetape();
183static void bufclear();
184static pid_t setuparchive();
185static pid_t setupwriter();
186static void nextslave();
187static void tperror();
188static void rollforward();
189static void nap();
190static void alrm();
191static void just_rewind();
192static void killall();
193static void proceed();
194static void die();
195static void enslave();
196static void wait_our_turn();
197static void dumpoffline();
198static void onxfsz();
199static void dowrite();
200static void checkpoint();
201static ssize_t atomic();
202#endif
203
204static size_t tapesize;
205
206/*
207 * Allocate buffers and shared memory variables.  Tape buffers are
208 * allocated on page boundaries for tape write() efficiency.
209 */
210void
211#ifdef __STDC__
212#else
213#endif
214alloctape(void)
215{
216	struct slaves *slavep;
217	ulong_t pgoff = (unsigned)(getpagesize() - 1); /* 2**n - 1 */
218	int	mapfd;
219	char	*obuf;
220	int	saverr;
221	int	i, j;
222
223	writesize = ntrec * tp_bsize;
224	if (!printsize)
225		msg(gettext("Writing %d Kilobyte records\n"),
226			writesize / TP_BSIZE_MIN);
227
228	/*
229	 * set up shared memory seg for here and child
230	 */
231	mapfd = open("/dev/zero", O_RDWR);
232	if (mapfd == -1) {
233		saverr = errno;
234		msg(gettext("Cannot open `%s': %s\n"),
235			"/dev/zero", strerror(saverr));
236		dumpabort();
237		/*NOTREACHED*/
238	}
239	/*
240	 * Allocate space such that buffers are page-aligned and
241	 * pointers are aligned on 4-byte boundaries (for SPARC).
242	 * This code assumes that (NBUF * writesize) is a multiple
243	 * of the page size and that pages are aligned on 4-byte
244	 * boundaries.  Space is allocated as follows:
245	 *
246	 *    (NBUF * writesize) for the actual buffers
247	 *    (pagesize - 1) for padding so the buffers are page-aligned
248	 *    (NBUF * ntrec * sizeof (struct bdesc)) for each buffer
249	 *    (n * sizeof (int)) for [n] debugging variables/pointers
250	 *    (n * sizeof (int)) for [n] miscellaneous variables/pointers
251	 */
252	tapesize =
253	    (NBUF * writesize)				/* output buffers */
254		/* LINTED: pgoff fits into a size_t */
255	    + (size_t)pgoff				/* page alignment */
256							/* buffer descriptors */
257	    + (((size_t)sizeof (struct bdesc)) * NBUF * ntrec)
258#ifdef INSTRUMENT
259	    + (2 * (size_t)sizeof (int *))		/* instrumentation */
260#endif
261							/* shared variables */
262	    + (size_t)sizeof (struct bdesc **)
263	    + (size_t)sizeof (int *)
264	    + (3 * (size_t)sizeof (time_t));
265
266	shared = mmap((char *)0, tapesize, PROT_READ|PROT_WRITE,
267	    MAP_SHARED, mapfd, (off_t)0);
268	if (shared == (caddr_t)-1) {
269		saverr = errno;
270		msg(gettext("Cannot memory map output buffers: %s\n"),
271		    strerror(saverr));
272		dumpabort();
273		/*NOTREACHED*/
274	}
275	(void) close(mapfd);
276
277	/*
278	 * Buffers and buffer headers
279	 */
280	obuf = (char *)(((ulong_t)shared + pgoff) & ~pgoff);
281	/* LINTED obuf and writesize are aligned */
282	bufp = (struct bdesc *)(obuf + NBUF*writesize);
283	/*
284	 * Shared memory variables
285	 */
286	current = (struct bdesc **)&bufp[NBUF*ntrec];
287	tapea = (int *)(current + 1);
288	/* LINTED pointer alignment ok */
289	telapsed = (time_t *)(tapea + 1);
290	tstart_writing = telapsed + 1;
291	tschedule = tstart_writing + 1;
292#ifdef INSTRUMENT
293	/*
294	 * Debugging and instrumentation variables
295	 */
296	readmissp = (int *)(tschedule + 1);
297	idle = readmissp + 1;
298#endif
299	for (i = 0, j = 0; i < NBUF * ntrec; i++, j += tp_bsize) {
300		bufp[i].b_data = &obuf[j];
301	}
302
303	reqsiz = sizeof (struct req) + tp_bsize - sizeof (long);
304	for (slavep = slaves; slavep < &slaves[SLAVES]; slavep++)
305		slavep->sl_req = (struct req *)xmalloc(reqsiz);
306
307	chkpt.sl_offset = 0;		/* start at offset 0 */
308	chkpt.sl_count = 0;
309	chkpt.sl_inos = UFSROOTINO;	/* in root inode */
310	chkpt.sl_firstrec = 1;
311	chkpt.sl_tapea = 0;
312}
313
314static void
315#ifdef __STDC__
316freetape(void)
317#else
318freetape()
319#endif
320{
321	if (shared == NULL)
322		return;
323	(void) timeclock((time_t)0);
324	(void) munmap(shared, tapesize);
325	shared = NULL;
326}
327
328/*
329 * Reset tape state variables -- called
330 * before a pass to dump active files.
331 */
332void
333#ifdef __STDC__
334reset(void)
335#else
336reset()
337#endif
338{
339	bufclear();
340
341#ifdef INSTRUMENT
342	(*readmissp) = 0;
343	(*idle) = 0;
344#endif
345
346	spcl.c_flags = 0;
347	spcl.c_volume = 0;
348	tapeno = 0;
349
350	chkpt.sl_offset = 0;		/* start at offset 0 */
351	chkpt.sl_count = 0;
352	chkpt.sl_inos = UFSROOTINO;	/* in root inode */
353	chkpt.sl_firstrec = 1;
354	chkpt.sl_tapea = 0;
355}
356
357static void
358#ifdef __STDC__
359bufclear(void)
360#else
361bufclear()
362#endif
363{
364	struct bdesc *bp;
365	int i;
366
367	for (i = 0, bp = bufp; i < NBUF * ntrec; i++, bp++)
368		bp->b_flags = BUF_EMPTY;
369	if ((caddr_t)current < shared ||
370	    (caddr_t)current > (shared + tapesize)) {
371		msg(gettext(
372	    "bufclear: current pointer out of range of shared memory\n"));
373		dumpabort();
374		/*NOTREACHED*/
375	}
376	if ((*current != NULL) &&
377	    (*current < &bufp[0] || *current > &bufp[NBUF*ntrec])) {
378		/* ANSI string catenation, to shut cstyle up */
379		msg(gettext("bufclear: current buffer pointer (0x%x) "
380			"out of range of buffer\naddresses (0x%x - 0x%x)\n"),
381		    *current, &bufp[0], &bufp[NBUF*ntrec]);
382		dumpabort();
383		/*NOTREACHED*/
384	}
385	*current = bufp;
386}
387
388/*
389 * Start a process to collect information describing the dump.
390 * This data takes two forms:
391 *    the bitmap and directory information being written to
392 *	the front of the tape (the "archive" file)
393 *    information describing each directory and inode (to
394 *	be included in the database tmp file)
395 * Write the data to the files as it is received so huge file
396 * systems don't cause dump to consume large amounts of memory.
397 */
398static pid_t
399setuparchive(void)
400{
401	struct slaves *slavep;
402	int cmd[2];
403	pid_t pid;
404	ssize_t size;
405	char *data;
406	char *errmsg;
407	int flags, saverr;
408	int punt = 0;
409
410	/*
411	 * Both the archive and database tmp files are
412	 * checkpointed by taking their current offsets
413	 * (sizes) after completing each volume.  Restoring
414	 * from a checkpoint involves truncating to the
415	 * checkpointed size.
416	 */
417	if (archive && !doingactive) {
418		/* It's allowed/expected to exist, so can't use O_EXCL */
419		archivefd = safe_file_open(archivefile, O_WRONLY, 0600);
420		if (archivefd < 0) {
421			saverr = errno;
422			msg(gettext("Cannot open archive file `%s': %s\n"),
423			    archivefile, strerror(saverr));
424			dumpabort();
425			/*NOTREACHED*/
426		}
427
428		archive_opened = 1;
429
430		if (lseek64(archivefd, lf_archoffset, 0) < 0) {
431			saverr = errno;
432			msg(gettext(
433				    "Cannot position archive file `%s' : %s\n"),
434			    archivefile, strerror(saverr));
435			dumpabort();
436			/*NOTREACHED*/
437		}
438		if (ftruncate64(archivefd, lf_archoffset) < 0) {
439			saverr = errno;
440			msg(gettext(
441				    "Cannot truncate archive file `%s' : %s\n"),
442			    archivefile, strerror(saverr));
443			dumpabort();
444			/*NOTREACHED*/
445		}
446	}
447
448	if (pipe(cmd) < 0) {
449		saverr = errno;
450		msg(gettext("%s: %s error: %s\n"),
451		    "setuparchive", "pipe", strerror(saverr));
452		return (0);
453	}
454	sighold(SIGINT);
455	if ((pid = fork()) < 0) {
456		saverr = errno;
457		msg(gettext("%s: %s error: %s\n"),
458		    "setuparchive", "fork", strerror(saverr));
459		return (0);
460	}
461	if (pid > 0) {
462		sigrelse(SIGINT);
463		/* parent process */
464		(void) close(cmd[0]);
465		arch = cmd[1];
466		return (pid);
467	}
468	/*
469	 * child process
470	 */
471	(void) signal(SIGINT, SIG_IGN);		/* master handles this */
472#ifdef TDEBUG
473	(void) sleep(4);	/* allow time for parent's message to get out */
474	/* XGETTEXT:  #ifdef TDEBUG only */
475	msg(gettext("Archiver has pid = %ld\n"), (long)getpid());
476#endif
477	freeino();	/* release unneeded resources */
478	freetape();
479	for (slavep = &slaves[0]; slavep < &slaves[SLAVES]; slavep++) {
480		if (slavep->sl_slavefd != -1) {
481			(void) close(slavep->sl_slavefd);
482			slavep->sl_slavefd = -1;
483		}
484	}
485	(void) close(to);
486	(void) close(fi);
487	to = fi = -1;
488	(void) close(cmd[1]);
489	data = xmalloc(tp_bsize);
490	for (;;) {
491		size = atomic((int(*)())read, cmd[0], (char *)&flags,
492		    sizeof (flags));
493		if ((unsigned)size != sizeof (flags))
494			break;
495		size = atomic((int(*)())read, cmd[0], data, tp_bsize);
496		if (size == tp_bsize) {
497			if (archive && flags & BUF_ARCHIVE && !punt &&
498			    (size = write(archivefd, data, tp_bsize))
499			    != tp_bsize) {
500				struct stat64 stats;
501
502				if (size != -1) {
503					errmsg = strdup(gettext(
504					    "Output truncated"));
505					if (errmsg == NULL)
506						errmsg = "";
507				} else {
508					errmsg = strerror(errno);
509				}
510
511				if (fstat64(archivefd, &stats) < 0)
512				    stats.st_size = -1;
513
514				/* cast to keep lint&printf happy */
515				msg(gettext(
516		    "Cannot write archive file `%s' at offset %lld: %s\n"),
517				    archivefile, (longlong_t)stats.st_size,
518				    errmsg);
519				msg(gettext(
520		    "Archive file will be deleted, dump will continue\n"));
521				punt++;
522				if ((size != -1) && (*errmsg != '\0')) {
523					free(errmsg);
524				}
525			}
526		} else {
527			break;
528		}
529	}
530	(void) close(cmd[0]);
531	if (archive) {
532		(void) close(archivefd);
533		archivefd = -1;
534	}
535	if (punt) {
536		(void) unlink(archivefile);
537		Exit(X_ABORT);
538	}
539	Exit(X_FINOK);
540	/* NOTREACHED */
541	return (0);
542}
543
544/*
545 * Start a process to read the output buffers and write the data
546 * to the output device.
547 */
548static pid_t
549setupwriter(void)
550{
551	struct slaves *slavep;
552	int cmd[2];
553	pid_t pid;
554	int saverr;
555
556	caught = 0;
557	if (pipe(cmd) < 0) {
558		saverr = errno;
559		msg(gettext("%s: %s error: %s\n"),
560			"setupwriter", "pipe", strerror(saverr));
561		return (0);
562	}
563	sighold(SIGINT);
564	if ((pid = fork()) < 0) {
565		saverr = errno;
566		msg(gettext("%s: %s error: %s\n"),
567			"setupwriter", "fork", strerror(saverr));
568		return (0);
569	}
570	if (pid > 0) {
571		/*
572		 * Parent process
573		 */
574		sigrelse(SIGINT);
575		(void) close(cmd[0]);
576		writer = cmd[1];
577		return (pid);
578	}
579	/*
580	 * Child (writer) process
581	 */
582	(void) signal(SIGINT, SIG_IGN);		/* master handles this */
583#ifdef TDEBUG
584	(void) sleep(4);	/* allow time for parent's message to get out */
585	/* XGETTEXT:  #ifdef TDEBUG only */
586	msg(gettext("Writer has pid = %ld\n"), (long)getpid());
587#endif
588	child_chdir();
589	freeino();	/* release unneeded resources */
590	for (slavep = &slaves[0]; slavep < &slaves[SLAVES]; slavep++) {
591		if (slavep->sl_slavefd != -1) {
592			(void) close(slavep->sl_slavefd);
593			slavep->sl_slavefd = -1;
594		}
595	}
596	(void) close(fi);
597	fi = -1;
598	(void) close(cmd[1]);
599	dowrite(cmd[0]);
600	if (arch >= 0) {
601		(void) close(arch);
602		arch = -1;
603	}
604	(void) close(cmd[0]);
605	Exit(X_FINOK);
606	/* NOTREACHED */
607	return (0);
608}
609
610void
611#ifdef __STDC__
612spclrec(void)
613#else
614spclrec()
615#endif
616{
617	int s, i;
618	int32_t *ip;
619	int flags = BUF_SPCLREC;
620
621	if ((BIT(ino, shamap)) && (spcl.c_type == TS_INODE)) {
622		spcl.c_type = TS_ADDR;
623		/* LINTED: result fits in a short */
624		spcl.c_dinode.di_mode &= ~S_IFMT;
625		/* LINTED: result fits in a short */
626		spcl.c_dinode.di_mode |= IFSHAD;
627	}
628
629	/*
630	 * Only TS_INODEs should have short metadata, if this
631	 * isn't such a spclrec, clear the metadata flag and
632	 * the c_shadow contents.
633	 */
634	if (!(spcl.c_type == TS_INODE && (spcl.c_flags & DR_HASMETA))) {
635		spcl.c_flags &= ~DR_HASMETA;
636		bcopy(c_shadow_save, &(spcl.c_shadow),
637		    sizeof (spcl.c_shadow));
638	}
639
640	if (spcl.c_type == TS_END) {
641		spcl.c_count = 1;
642		spcl.c_flags |= DR_INODEINFO;
643		bcopy((char *)inos, (char *)spcl.c_inos, sizeof (inos));
644	} else if (spcl.c_type == TS_TAPE) {
645		spcl.c_flags |= DR_NEWHEADER;
646		if (doingactive)
647			spcl.c_flags |= DR_REDUMP;
648	} else if (spcl.c_type != TS_INODE)
649		flags = BUF_SPCLREC;
650	spcl.c_tapea = *tapea;
651	/* LINTED for now, max inode # is 2**31 (ufs max size is 4TB) */
652	spcl.c_inumber = (ino32_t)ino;
653	spcl.c_magic = (tp_bsize == TP_BSIZE_MIN) ? NFS_MAGIC : MTB_MAGIC;
654	spcl.c_checksum = 0;
655	ip = (int32_t *)&spcl;
656	s = CHECKSUM;
657	assert((tp_bsize % sizeof (*ip)) == 0);
658	i = tp_bsize / sizeof (*ip);
659	assert((i%8) == 0);
660	i /= 8;
661	do {
662		s -= *ip++; s -= *ip++; s -= *ip++; s -= *ip++;
663		s -= *ip++; s -= *ip++; s -= *ip++; s -= *ip++;
664	} while (--i > 0);
665	spcl.c_checksum = s;
666	taprec((uchar_t *)&spcl, flags, sizeof (spcl));
667	if (spcl.c_type == TS_END)
668		spcl.c_flags &= ~DR_INODEINFO;
669	else if (spcl.c_type == TS_TAPE)
670		spcl.c_flags &= ~(DR_NEWHEADER|DR_REDUMP|DR_TRUEINC);
671}
672
673/*
674 * Fill appropriate buffer
675 */
676void
677taprec(uchar_t *dp, int flags, int size)
678{
679	if (size > tp_bsize) {
680		msg(gettext(
681		    "taprec: Unexpected buffer size, expected %d, got %d.\n"),
682		    tp_bsize, size);
683		dumpabort();
684		/*NOTREACHED*/
685	}
686
687	while ((*current)->b_flags & BUF_FULL)
688		nap(10);
689
690	bcopy(dp, (*current)->b_data, (size_t)size);
691	if (size < tp_bsize) {
692		bzero((*current)->b_data + size, tp_bsize - size);
693	}
694
695	if (dumptoarchive)
696		flags |= BUF_ARCHIVE;
697
698	/* no locking as we assume only one reader and one writer active */
699	(*current)->b_flags = (flags | BUF_FULL);
700	if (++*current >= &bufp[NBUF*ntrec])
701		(*current) = &bufp[0];
702	(*tapea)++;
703}
704
705void
706dmpblk(daddr32_t blkno, size_t size, off_t offset)
707{
708	diskaddr_t dblkno;
709
710	assert((offset >> DEV_BSHIFT) <= INT32_MAX);
711	dblkno = fsbtodb(sblock, blkno) + (offset >> DEV_BSHIFT);
712	size = (size + DEV_BSIZE-1) & ~(DEV_BSIZE-1);
713	slp->sl_req->br_dblk = dblkno;
714	slp->sl_req->br_size = size;
715	if (dumptoarchive) {
716		/* LINTED: result fits in a short */
717		slp->sl_req->aflag |= BUF_ARCHIVE;
718	}
719	toslave((void(*)())0, ino);
720}
721
722/*ARGSUSED*/
723static void
724tperror(int sig)
725{
726	char buf[3000];
727
728	if (pipeout) {
729		msg(gettext("Write error on %s\n"), tape);
730		msg(gettext("Cannot recover\n"));
731		dumpabort();
732		/* NOTREACHED */
733	}
734	if (!doingverify) {
735		broadcast(gettext("WRITE ERROR!\n"));
736		(void) snprintf(buf, sizeof (buf),
737		    gettext("Do you want to restart?: (\"yes\" or \"no\") "));
738		if (!query(buf)) {
739			dumpabort();
740			/*NOTREACHED*/
741		}
742		if (tapeout && (isrewind(to) || offline)) {
743			/* ANSI string catenation, to shut cstyle up */
744			msg(gettext("This tape will rewind.  After "
745				    "it is rewound,\nreplace the faulty tape "
746				    "with a new one;\nthis dump volume will "
747				    "be rewritten.\n"));
748		}
749	} else {
750		broadcast(gettext("TAPE VERIFICATION ERROR!\n"));
751		(void) snprintf(buf, sizeof (buf), gettext(
752		    "Do you want to rewrite?: (\"yes\" or \"no\") "));
753		if (!query(buf)) {
754			dumpabort();
755			/*NOTREACHED*/
756		}
757		msg(gettext(
758			"This tape will be rewritten and then verified\n"));
759	}
760	killall();
761	trewind();
762	Exit(X_REWRITE);
763}
764
765/*
766 * Called by master from pass() to send a request to dump files/blocks
767 * to one of the slaves.  Slaves return whether the file was active
768 * when it was being dumped.  The tape writer process sends checkpoint
769 * info when it completes a volume.
770 */
771void
772toslave(void (*fn)(), ino_t inumber)
773{
774	int	wasactive;
775
776	if (recsout >= SLAVES) {
777		if ((unsigned)atomic((int(*)())read, slp->sl_slavefd,
778		    (char *)&wasactive, sizeof (wasactive)) !=
779		    sizeof (wasactive)) {
780			cmdrderr();
781			dumpabort();
782			/*NOTREACHED*/
783		}
784		if (wasactive) {
785			active++;
786			msg(gettext(
787		"The file at inode `%lu' was active and will be recopied\n"),
788				slp->sl_req->ir_inumber);
789			/* LINTED: 32-bit to 8-bit assignment ok */
790			BIS(slp->sl_req->ir_inumber, activemap);
791		}
792	}
793	slp->sl_req->aflag = 0;
794	if (dumptoarchive) {
795		/* LINTED: result fits in a short */
796		slp->sl_req->aflag |= BUF_ARCHIVE;
797	}
798	if (fn)
799		(*fn)(inumber);
800
801	if (atomic((int(*)())write, slp->sl_slavefd, (char *)slp->sl_req,
802	    reqsiz) != reqsiz) {
803		cmdwrterr();
804		dumpabort();
805		/*NOTREACHED*/
806	}
807	++recsout;
808	nextslave();
809}
810
811void
812dospcl(ino_t inumber)
813{
814	/* LINTED for now, max inode # is 2**31 (ufs max size is 1TB) */
815	spcl.c_inumber = (ino32_t)inumber;
816	slp->sl_req->br_dblk = 0;
817	bcopy((char *)&spcl, (char *)slp->sl_req->br_spcl, tp_bsize);
818}
819
820static void
821#ifdef __STDC__
822nextslave(void)
823#else
824nextslave()
825#endif
826{
827	if (++rotor >= SLAVES) {
828		rotor = 0;
829	}
830	slp = &slaves[rotor];
831}
832
833void
834#ifdef __STDC__
835flushcmds(void)
836#else
837flushcmds()
838#endif
839{
840	int i;
841	int wasactive;
842
843	/*
844	 * Retrieve all slave status
845	 */
846	if (recsout < SLAVES) {
847		slp = slaves;
848		rotor = 0;
849	}
850	for (i = 0; i < (recsout < SLAVES ? recsout : SLAVES); i++) {
851		if ((unsigned)atomic((int(*)())read, slp->sl_slavefd,
852		    (char *)&wasactive, sizeof (wasactive)) !=
853		    sizeof (wasactive)) {
854			cmdrderr();
855			dumpabort();
856			/*NOTREACHED*/
857		}
858		if (wasactive) {
859			active++;
860			msg(gettext(
861			    "inode %d was active and will be recopied\n"),
862				slp->sl_req->ir_inumber);
863			/* LINTED: 32-bit to 8-bit assignment ok */
864			BIS(slp->sl_req->ir_inumber, activemap);
865		}
866		nextslave();
867	}
868}
869
870void
871#ifdef __STDC__
872flusht(void)
873#else
874flusht()
875#endif
876{
877	sigset_t block_set, oset;	/* hold SIGUSR1 and atomically sleep */
878
879	(void) sigemptyset(&block_set);
880	(void) sigaddset(&block_set, SIGUSR1);
881	(void) sigprocmask(SIG_BLOCK, &block_set, &oset);
882	(void) kill(writepid, SIGUSR1);	/* tell writer to flush */
883	(void) sigpause(SIGUSR1);	/* wait for SIGUSR1 from writer */
884	/*NOTREACHED*/
885}
886
887jmp_buf	checkpoint_buf;
888
889/*
890 * Roll forward to the next volume after receiving
891 * an EOT signal from writer.  Get checkpoint data
892 * from writer and return if done, otherwise fork
893 * a new process and jump back to main state loop
894 * to begin the next volume.  Installed as the master's
895 * signal handler for SIGUSR1.
896 */
897/*ARGSUSED*/
898static void
899rollforward(int sig)
900{
901	int status;
902	(void) sighold(SIGUSR1);
903
904	/*
905	 * Writer sends us checkpoint information after
906	 * each volume.  A returned state of DS_DONE with no
907	 * unwritten (left-over) records differentiates a
908	 * clean flush from one in which EOT was encountered.
909	 */
910	if ((unsigned)atomic((int(*)())read, writer, (char *)&chkpt,
911	    sizeof (struct slaves)) != sizeof (struct slaves)) {
912		cmdrderr();
913		dumpabort();
914		/*NOTREACHED*/
915	}
916	if (atomic((int(*)())read, writer, (char *)&spcl,
917	    TP_BSIZE_MIN) != TP_BSIZE_MIN) {
918		cmdrderr();
919		dumpabort();
920		/*NOTREACHED*/
921	}
922	ino = chkpt.sl_inos - 1;
923	pos = chkpt.sl_offset;
924	leftover = chkpt.sl_count;
925	dumpstate = chkpt.sl_state;
926	blockswritten = ++chkpt.sl_tapea;
927
928	if (dumpstate == DS_DONE) {
929		if (archivepid) {
930			/*
931			 * If archiving (either archive or
932			 * database), signal the archiver
933			 * to finish up.  This must happen
934			 * before the writer exits in order
935			 * to avoid a race.
936			 */
937			(void) kill(archivepid, SIGUSR1);
938		}
939		(void) signal(SIGUSR1, SIG_IGN);
940		(void) sigrelse(SIGUSR1);
941		(void) kill(writepid, SIGUSR1);	/* tell writer to exit */
942
943		lf_archoffset = 0LL;
944		longjmp(checkpoint_buf, 1);
945		/*NOTREACHED*/
946	}
947
948	if (leftover) {
949		(void) memmove(spcl.c_addr,
950		    &spcl.c_addr[spcl.c_count-leftover], leftover);
951		bzero(&spcl.c_addr[leftover], TP_NINDIR-leftover);
952	}
953	if (writepid) {
954		(void) kill(writepid, SIGUSR1);	/* tell writer to exit */
955		(void) close(writer);
956		writer = -1;
957	}
958	if (archivepid) {
959		(void) waitpid(archivepid, &status, 0);	/* wait for archiver */
960#ifdef TDEBUG
961
962		/* XGETTEXT:  #ifdef TDEBUG only */
963		msg(gettext("Archiver %ld returns with status %d\n"),
964		    (long)archivepid, status);
965#endif
966		archivepid = 0;
967	}
968	/*
969	 * Checkpoint archive file
970	 */
971	if (!doingverify && archive) {
972		lf_archoffset = lseek64(archivefd, (off64_t)0, 2);
973		if (lf_archoffset < 0) {
974			int saverr = errno;
975			msg(gettext("Cannot position archive file `%s': %s\n"),
976				archivefile, strerror(saverr));
977			dumpabort();
978			/*NOTREACHED*/
979		}
980		(void) close(archivefd);
981		archivefd = -1;
982	}
983	resetino(ino);
984
985	if (dumpstate == DS_START) {
986		msg(gettext(
987			"Tape too short: changing volumes and restarting\n"));
988		reset();
989	}
990
991	if (!pipeout) {
992		if (verify && !doingverify)
993			trewind();
994		else {
995			close_rewind();
996			changevol();
997		}
998	}
999
1000	(void) sigrelse(SIGUSR1);
1001	otape(0);
1002	longjmp(checkpoint_buf, 1);
1003	/*NOTREACHED*/
1004}
1005
1006static void
1007nap(int ms)
1008{
1009	struct timeval tv;
1010
1011	tv.tv_sec = ms / 1000;
1012	tv.tv_usec = (ms - tv.tv_sec * 1000) * 1000;
1013	(void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv);
1014}
1015
1016static jmp_buf alrm_buf;
1017
1018/*ARGSUSED*/
1019static void
1020alrm(int sig)
1021{
1022	longjmp(alrm_buf, 1);
1023	/*NOTREACHED*/
1024}
1025
1026void
1027#ifdef __STDC__
1028nextdevice(void)
1029#else
1030nextdevice()
1031#endif
1032{
1033	char	*cp;
1034
1035	if (host != NULL)	/* we set the host only once in ufsdump */
1036		return;
1037
1038	host = NULL;
1039	if (strchr(tape, ':')) {
1040		if (diskette) {
1041			msg(gettext("Cannot do remote dump to diskette\n"));
1042			Exit(X_ABORT);
1043		}
1044		host = tape;
1045		tape = strchr(host, ':');
1046		*tape++ = 0;
1047		cp = strchr(host, '@');	/* user@host? */
1048		if (cp != (char *)0)
1049			cp++;
1050		else
1051			cp = host;
1052	} else
1053		cp = spcl.c_host;
1054	/*
1055	 * dumpdev is provided for use in prompts and is of
1056	 * the form:
1057	 *	hostname:device
1058	 * sdumpdev is of the form:
1059	 *	hostname:device
1060	 * for remote devices, and simply:
1061	 *	device
1062	 * for local devices.
1063	 */
1064	if (dumpdev != (char *)NULL) {
1065		/* LINTED: dumpdev is not NULL */
1066		free(dumpdev);
1067	}
1068	/*LINTED [cast to smaller integer]*/
1069	dumpdev = xmalloc((size_t)((sizeof (spcl.c_host) + strlen(tape) + 2)));
1070	/* LINTED unsigned -> signed cast ok */
1071	(void) sprintf(dumpdev, "%.*s:%s", (int)sizeof (spcl.c_host), cp, tape);
1072	if (cp == spcl.c_host)
1073		sdumpdev = strchr(dumpdev, ':') + 1;
1074	else
1075		sdumpdev = dumpdev;
1076}
1077
1078/*
1079 * Gross hack due to misfeature of mt tape driver that causes
1080 * the device to rewind if we generate any signals.  Guess
1081 * whether tape is rewind device or not -- for local devices
1082 * we can just look at the minor number.  For rmt devices,
1083 * make an educated guess.
1084 */
1085int
1086isrewind(int f)
1087{
1088	struct stat64 sbuf;
1089	char    *c;
1090	int	unit;
1091	int	rewind;
1092
1093	if (host) {
1094		c = strrchr(tape, '/');
1095		if (c == NULL)
1096			c = tape;
1097		else
1098			c++;
1099		/*
1100		 * If the last component begins or ends with an 'n', it is
1101		 * assumed to be a non-rewind device.
1102		 */
1103		if (c[0] == 'n' || c[strlen(c)-1] == 'n')
1104			rewind = 0;
1105		else if ((strstr(tape, "mt") || strstr(tape, "st")) &&
1106		    sscanf(tape, "%*[a-zA-Z/]%d", &unit) == 1 &&
1107		    (unit & MT_NOREWIND))
1108			rewind = 0;
1109		else
1110			rewind = 1;
1111	} else {
1112		if (fstat64(f, &sbuf) < 0) {
1113			msg(gettext(
1114			    "Cannot obtain status of output device `%s'\n"),
1115				tape);
1116			dumpabort();
1117			/*NOTREACHED*/
1118		}
1119		rewind = minor(sbuf.st_rdev) & MT_NOREWIND ? 0 : 1;
1120	}
1121	return (rewind);
1122}
1123
1124static void
1125#ifdef __STDC__
1126just_rewind(void)
1127#else
1128just_rewind()
1129#endif
1130{
1131	struct slaves *slavep;
1132	char *rewinding = gettext("Tape rewinding\n");
1133
1134	for (slavep = &slaves[0]; slavep < &slaves[SLAVES]; slavep++) {
1135		if (slavep->sl_slavepid > 0)	/* signal normal exit */
1136			(void) kill(slavep->sl_slavepid, SIGTERM);
1137		if (slavep->sl_slavefd >= 0) {
1138			(void) close(slavep->sl_slavefd);
1139			slavep->sl_slavefd = -1;
1140		}
1141	}
1142
1143	/* wait for any signals from slaves */
1144	while (waitpid(0, (int *)0, 0) >= 0)
1145		/*LINTED [empty body]*/
1146		continue;
1147
1148	if (pipeout)
1149		return;
1150
1151	if (doingverify) {
1152		/*
1153		 * Space to the end of the tape.
1154		 * Backup first in case we already read the EOF.
1155		 */
1156		if (host) {
1157			(void) rmtioctl(MTBSR, 1);
1158			if (rmtioctl(MTEOM, 1) < 0)
1159				(void) rmtioctl(MTFSF, 1);
1160		} else {
1161			static struct mtop bsr = { MTBSR, 1 };
1162			static struct mtop eom = { MTEOM, 1 };
1163			static struct mtop fsf = { MTFSF, 1 };
1164
1165			(void) ioctl(to, MTIOCTOP, &bsr);
1166			if (ioctl(to, MTIOCTOP, &eom) < 0)
1167				(void) ioctl(to, MTIOCTOP, &fsf);
1168		}
1169	}
1170
1171	/*
1172	 * Guess whether the tape is rewinding so we can tell
1173	 * the operator if it's going to take a long time.
1174	 */
1175	if (tapeout && isrewind(to)) {
1176		/* tape is probably rewinding */
1177		msg(rewinding);
1178	}
1179}
1180
1181void
1182#ifdef __STDC__
1183trewind(void)
1184#else
1185trewind()
1186#endif
1187{
1188	(void) timeclock((time_t)0);
1189	if (offline && (!verify || doingverify)) {
1190		close_rewind();
1191	} else {
1192		just_rewind();
1193		if (host)
1194			rmtclose();
1195		else {
1196			(void) close(to);
1197			to = -1;
1198		}
1199	}
1200}
1201
1202void
1203#ifdef __STDC__
1204close_rewind(void)
1205#else
1206close_rewind()
1207#endif
1208{
1209	char *rewinding = gettext("Tape rewinding\n");
1210
1211	(void) timeclock((time_t)0);
1212	just_rewind();
1213	/*
1214	 * The check in just_rewind won't catch the case in
1215	 * which the current volume is being taken off-line
1216	 * and is not mounted on a no-rewind device (and is
1217	 * not the last volume, which is not taken off-line).
1218	 */
1219	if (tapeout && !isrewind(to) && offline) {
1220		/* tape is probably rewinding */
1221		msg(rewinding);
1222	}
1223	if (host) {
1224		if (offline || autoload)
1225			(void) rmtioctl(MTOFFL, 0);
1226		rmtclose();
1227	} else {
1228		if (offline || autoload) {
1229			static struct mtop offl = { MTOFFL, 0 };
1230
1231			(void) ioctl(to, MTIOCTOP, &offl);
1232			if (diskette)
1233				(void) ioctl(to, FDEJECT, 0);
1234		}
1235		(void) close(to);
1236		to = -1;
1237	}
1238}
1239
1240void
1241#ifdef __STDC__
1242changevol(void)
1243#else
1244changevol()
1245#endif
1246{
1247	char buf1[3000], buf2[3000];
1248	char volname[LBLSIZE+1];
1249
1250	/*CONSTANTCONDITION*/
1251	assert(sizeof (spcl.c_label) < sizeof (volname));
1252
1253	filenum = 1;
1254	nextdevice();
1255	(void) strcpy(spcl.c_label, tlabel);
1256	if (host) {
1257		char	*rhost = host;
1258		char	*cp = strchr(host, '@');
1259		if (cp == (char *)0)
1260			cp = host;
1261		else
1262			cp++;
1263
1264		if (rmthost(rhost, ntrec) == 0) {
1265			msg(gettext("Cannot connect to tape host `%s'\n"), cp);
1266			dumpabort();
1267			/*NOTREACHED*/
1268		}
1269		if (rhost != host)
1270			free(rhost);
1271	}
1272
1273	/*
1274	 * Make volume switching as automatic as possible
1275	 * while avoiding overwriting volumes.  We will
1276	 * switch automatically under the following condition:
1277	 *    1) The user specified autoloading from the
1278	 *	command line.
1279	 * At one time, we (in the guise of hsmdump) had the
1280	 * concept of a sequence of devices to rotate through,
1281	 * but that's never been a ufsdump feature.
1282	 */
1283	if (autoload) {
1284		int tries;
1285
1286		/*
1287		 * Stop the clock for throughput calculations.
1288		 */
1289		if ((telapsed != NULL) && (tstart_writing != NULL)) {
1290			*telapsed += time((time_t *)NULL) - *tstart_writing;
1291		}
1292
1293		(void) snprintf(volname, sizeof (volname), "#%d", tapeno+1);
1294		(void) snprintf(buf1, sizeof (buf1), gettext(
1295		    "Mounting volume %s on %s\n"), volname, dumpdev);
1296		msg(buf1);
1297		broadcast(buf1);
1298
1299		/*
1300		 * Wait for the tape to autoload.  Note that the delay
1301		 * period doesn't take into account however long it takes
1302		 * for the open to fail (measured at 21 seconds for an
1303		 * Exabyte 8200 under 2.7 on an Ultra 2).
1304		 */
1305		for (tries = 0; tries < autoload_tries; tries++) {
1306			if (host) {
1307				if (rmtopen(tape, O_RDONLY) >= 0) {
1308					rmtclose();
1309					return;
1310				}
1311			} else {
1312				int f, m;
1313
1314				m = (access(tape, F_OK) == 0) ? 0 : O_CREAT;
1315				if ((f = doingverify ?
1316				    safe_device_open(tape, O_RDONLY, 0600) :
1317				    safe_device_open(tape, O_RDONLY|m, 0600))
1318				    >= 0) {
1319					(void) close(f);
1320					return;
1321				}
1322			}
1323			(void) sleep(autoload_period);
1324		}
1325		/*
1326		 * Autoload timed out, ask the operator to do it.
1327		 * Note that query() will update *telapsed, and we
1328		 * shouldn't charge for the autoload time.  So, since
1329		 * we updated *telapsed ourselves above, we just set
1330		 * tstart_writing to the current time, and query()
1331		 * will end up making a null-effect change.  This,
1332		 * of course, assumes that our caller will be resetting
1333		 * *tstart_writing.  This is currently the case.
1334		 * If tstart_writing is NULL (should never happen),
1335		 * we're ok, since time(2) will accept a NULL pointer.
1336		 */
1337		(void) time(tstart_writing);
1338	}
1339
1340	if (strncmp(spcl.c_label, "none", 5)) {
1341		(void) strncpy(volname, spcl.c_label, sizeof (spcl.c_label));
1342		volname[sizeof (spcl.c_label)] = '\0';
1343	} else
1344		(void) snprintf(volname, sizeof (volname), "#%d", tapeno+1);
1345
1346	timeest(1, spcl.c_tapea);
1347	(void) snprintf(buf1, sizeof (buf1), gettext(
1348	    "Change Volumes: Mount volume `%s' on `%s'\n"), volname, dumpdev);
1349	msg(buf1);
1350	broadcast(gettext("CHANGE VOLUMES!\7\7\n"));
1351	(void) snprintf(buf1, sizeof (buf1), gettext(
1352	    "Is the new volume (%s) mounted on `%s' and ready to go?: %s"),
1353	    volname, dumpdev, gettext("(\"yes\" or \"no\") "));
1354	while (!query(buf1)) {
1355		(void) snprintf(buf2, sizeof (buf2), gettext(
1356		    "Do you want to abort dump?: (\"yes\" or \"no\") "));
1357		if (query(buf2)) {
1358			dumpabort();
1359			/*NOTREACHED*/
1360		}
1361	}
1362}
1363
1364/*
1365 *	We implement taking and restoring checkpoints on the tape level.
1366 *	When each tape is opened, a new process is created by forking; this
1367 *	saves all of the necessary context in the parent.  The child
1368 *	continues the dump; the parent waits around, saving the context.
1369 *	If the child returns X_REWRITE, then it had problems writing that tape;
1370 *	this causes the parent to fork again, duplicating the context, and
1371 *	everything continues as if nothing had happened.
1372 */
1373
1374void
1375otape(int top)
1376{
1377	static struct mtget mt;
1378	char buf[3000];
1379	pid_t parentpid;
1380	pid_t childpid;
1381	pid_t waitproc;
1382	int status;
1383	struct sigvec sv, osv;
1384
1385	sv.sv_flags = SA_RESTART;
1386	(void) sigemptyset(&sv.sa_mask);
1387	sv.sv_handler = SIG_IGN;
1388	(void) sigvec(SIGINT, &sv, (struct sigvec *)0);
1389
1390	parentpid = getpid();
1391
1392	if (verify) {
1393		if (doingverify)
1394			doingverify = 0;
1395		else
1396			Exit(X_VERIFY);
1397	}
1398restore_check_point:
1399
1400	sv.sv_handler = interrupt;
1401	(void) sigvec(SIGINT, &sv, (struct sigvec *)0);
1402	(void) fflush(stderr);
1403	/*
1404	 *	All signals are inherited...
1405	 */
1406	sighold(SIGINT);
1407	childpid = fork();
1408	if (childpid < 0) {
1409		msg(gettext(
1410		    "Context-saving fork failed in parent %ld\n"),
1411			(long)parentpid);
1412		Exit(X_ABORT);
1413	}
1414	if (childpid != 0) {
1415		/*
1416		 *	PARENT:
1417		 *	save the context by waiting
1418		 *	until the child doing all of the work returns.
1419		 *	let the child catch user interrupts
1420		 */
1421		sv.sv_handler = SIG_IGN;
1422		(void) sigvec(SIGINT, &sv, (struct sigvec *)0);
1423		sigrelse(SIGINT);
1424#ifdef TDEBUG
1425
1426		/* XGETTEXT:  #ifdef TDEBUG only */
1427		msg(gettext(
1428		    "Volume: %d; parent process: %ld child process %ld\n"),
1429			tapeno+1, (long)parentpid, (long)childpid);
1430#endif /* TDEBUG */
1431		for (;;) {
1432			waitproc = waitpid(0, &status, 0);
1433			if (waitproc == childpid)
1434				break;
1435			msg(gettext(
1436	"Parent %ld waiting for child %ld had another child %ld return\n"),
1437			    (long)parentpid, (long)childpid, (long)waitproc);
1438		}
1439		if (WIFSIGNALED(status)) {
1440			msg(gettext("Process %ld killed by signal %d: %s\n"),
1441			    (long)childpid, WTERMSIG(status),
1442			    strsignal(WTERMSIG(status)));
1443			status = X_ABORT;
1444		} else
1445			status = WEXITSTATUS(status);
1446#ifdef TDEBUG
1447		switch (status) {
1448		case X_FINOK:
1449			/* XGETTEXT:  #ifdef TDEBUG only */
1450			msg(gettext(
1451			    "Child %ld finishes X_FINOK\n"), (long)childpid);
1452			break;
1453		case X_ABORT:
1454			/* XGETTEXT:  #ifdef TDEBUG only */
1455			msg(gettext(
1456			    "Child %ld finishes X_ABORT\n"), (long)childpid);
1457			break;
1458		case X_REWRITE:
1459			/* XGETTEXT:  #ifdef TDEBUG only */
1460			msg(gettext(
1461			    "Child %ld finishes X_REWRITE\n"), (long)childpid);
1462			break;
1463		case X_RESTART:
1464			/* XGETTEXT:  #ifdef TDEBUG only */
1465			msg(gettext(
1466			    "Child %ld finishes X_RESTART\n"), (long)childpid);
1467			break;
1468		case X_VERIFY:
1469			/* XGETTEXT:  #ifdef TDEBUG only */
1470			msg(gettext(
1471			    "Child %ld finishes X_VERIFY\n"), (long)childpid);
1472			break;
1473		default:
1474			/* XGETTEXT:  #ifdef TDEBUG only */
1475			msg(gettext("Child %ld finishes unknown %d\n"),
1476			    (long)childpid, status);
1477			break;
1478		}
1479#endif /* TDEBUG */
1480		switch (status) {
1481		case X_FINOK:
1482			/* wait for children */
1483			while (waitpid(0, (int *)0, 0) >= 0)
1484				/*LINTED [empty body]*/
1485				continue;
1486			Exit(X_FINOK);
1487			/*NOTREACHED*/
1488		case X_ABORT:
1489			Exit(X_ABORT);
1490			/*NOTREACHED*/
1491		case X_VERIFY:
1492			doingverify++;
1493			goto restore_check_point;
1494			/*NOTREACHED*/
1495		case X_REWRITE:
1496			doingverify = 0;
1497			changevol();
1498			goto restore_check_point;
1499			/* NOTREACHED */
1500		case X_RESTART:
1501			doingverify = 0;
1502			if (!top) {
1503				Exit(X_RESTART);
1504			}
1505			if (!offline)
1506				autoload = 0;
1507			changevol();
1508			sv.sv_handler = interrupt;
1509			(void) sigvec(SIGINT, &sv, (struct sigvec *)0);
1510			return;
1511			/* NOTREACHED */
1512		default:
1513			msg(gettext("Bad return code from dump: %d\n"), status);
1514			Exit(X_ABORT);
1515			/*NOTREACHED*/
1516		}
1517		/*NOTREACHED*/
1518	} else {	/* we are the child; just continue */
1519		child_chdir();
1520		sigrelse(SIGINT);
1521#ifdef TDEBUG
1522		(void) sleep(4); /* time for parent's message to get out */
1523		/* XGETTEXT:  #ifdef TDEBUG only */
1524		msg(gettext(
1525		    "Child on Volume %d has parent %ld, my pid = %ld\n"),
1526			tapeno+1, (long)parentpid, (long)getpid());
1527#endif
1528		(void) snprintf(buf, sizeof (buf), gettext(
1529"Cannot open `%s'.  Do you want to retry the open?: (\"yes\" or \"no\") "),
1530		    dumpdev);
1531		if (doingverify) {
1532			/* 1 for stdout */
1533			while ((to = host ? rmtopen(tape, O_RDONLY) :
1534			    pipeout ? 1 :
1535			    safe_device_open(tape, O_RDONLY, 0600)) < 0) {
1536				perror(tape);
1537				if (autoload) {
1538					if (!query_once(buf, 1)) {
1539						dumpabort();
1540						/*NOTREACHED*/
1541					}
1542				} else {
1543					if (!query(buf)) {
1544						dumpabort();
1545						/*NOTREACHED*/
1546					}
1547				}
1548			}
1549
1550			/*
1551			 * If we're using the non-rewinding tape device,
1552			 * the tape will be left positioned after the
1553			 * EOF mark.  We need to back up to the beginning
1554			 * of this tape file (cross two tape marks in the
1555			 * reverse direction and one in the forward
1556			 * direction) before the verify pass.
1557			 */
1558			if (host) {
1559				if (rmtioctl(MTBSF, 2) >= 0)
1560					(void) rmtioctl(MTFSF, 1);
1561				else
1562					(void) rmtioctl(MTNBSF, 1);
1563			} else {
1564				static struct mtop bsf = { MTBSF, 2 };
1565				static struct mtop fsf = { MTFSF, 1 };
1566				static struct mtop nbsf = { MTNBSF, 1 };
1567
1568				if (ioctl(to, MTIOCTOP, &bsf) >= 0)
1569					(void) ioctl(to, MTIOCTOP, &fsf);
1570				else
1571					(void) ioctl(to, MTIOCTOP, &nbsf);
1572			}
1573		} else {
1574			/*
1575			 * XXX Add logic to test for "tape" being a
1576			 * XXX device or a non-existent file.
1577			 * Current behaviour is that it must exist,
1578			 * and we over-write whatever's there.
1579			 * This can be bad if tape == "/etc/passwd".
1580			 */
1581			if (!pipeout && doposition && (tapeno == 0)) {
1582				positiontape(buf);
1583				if (setjmp(alrm_buf)) {
1584					/*
1585					 * The tape is rewinding;
1586					 * we're screwed.
1587					 */
1588				    msg(gettext(
1589			    "Cannot position tape using rewind device!\n"));
1590				    dumpabort();
1591				    /*NOTREACHED*/
1592				} else {
1593					sv.sv_handler = alrm;
1594					(void) sigvec(SIGALRM, &sv, &osv);
1595					(void) alarm(15);
1596				}
1597				while ((to = host ? rmtopen(tape, O_WRONLY) :
1598				    safe_device_open(tape, O_WRONLY, 0600)) < 0)
1599					(void) sleep(10);
1600				(void) alarm(0);
1601				(void) sigvec(SIGALRM, &osv,
1602				    (struct sigvec *)0);
1603			} else {
1604				int m;
1605				m = (access(tape, F_OK) == 0) ? 0 : O_CREAT;
1606				/*
1607				 * Only verify the tape label if label
1608				 * verification is on and we are at BOT
1609				 */
1610				if (pipeout)
1611					to = 1;
1612				else while ((to = host ?
1613				    rmtopen(tape, O_WRONLY) :
1614				    safe_device_open(tape, O_WRONLY|m, 0600))
1615				    < 0)
1616					if (!query_once(buf, 1)) {
1617						dumpabort();
1618						/*NOTREACHED*/
1619					}
1620			}
1621		}
1622		if (!pipeout) {
1623			tapeout = host ? rmtstatus(&mt) >= 0 :
1624			    ioctl(to, MTIOCGET, &mt) >= 0;	/* set state */
1625			/*
1626			 * Make sure the tape is positioned
1627			 * where it is supposed to be
1628			 */
1629			if (tapeout && (tapeno > 0) &&
1630			    (mt.mt_fileno != (filenum-1))) {
1631				(void) snprintf(buf, sizeof (buf), gettext(
1632				    "Warning - tape positioning error!\n\
1633\t%s current file %ld, should be %ld\n"),
1634				    tape, mt.mt_fileno+1, filenum);
1635				msg(buf);
1636				dumpailing();
1637			}
1638		}
1639		tapeno++;		/* current tape sequence */
1640		if (tapeno < TP_NINOS)
1641			inos[tapeno] = chkpt.sl_inos;
1642		spcl.c_firstrec = chkpt.sl_firstrec;
1643		spcl.c_tapea = (*tapea) = chkpt.sl_tapea;
1644		spcl.c_volume++;
1645
1646		enslave();	/* Share tape buffers with slaves */
1647
1648#ifdef DEBUG
1649		if (xflag) {
1650			/* XGETTEXT:  #ifdef DEBUG only */
1651			msg(gettext("Checkpoint state:\n"));
1652			msg("    blockswritten %u\n", blockswritten);
1653			msg("    ino %u\n", ino);
1654			msg("    pos %u\n", pos);
1655			msg("    left %u\n", leftover);
1656			msg("    tapea %u\n", (*tapea));
1657			msg("    state %d\n", dumpstate);
1658		}
1659#endif
1660		spcl.c_type = TS_TAPE;
1661		spcl.c_tpbsize = tp_bsize;
1662		if (leftover == 0) {
1663			spcl.c_count = 0;
1664			spclrec();
1665			newtape = 0;
1666		} else
1667			newtape++;	/* new volume indication */
1668		if (doingverify) {
1669			msg(gettext("Starting verify pass\n"));
1670		} else if (tapeno > 1) {
1671			msg(gettext(
1672			    "Volume %d begins with blocks from inode %lu\n"),
1673				tapeno, chkpt.sl_inos);
1674		}
1675		(void) timeclock((time_t)1);
1676		(void) time(tstart_writing);
1677		timeest(0, spcl.c_tapea);
1678	}
1679}
1680
1681void
1682#ifdef __STDC__
1683dumpabort(void)
1684#else
1685dumpabort()
1686#endif
1687{
1688
1689	if (master && master != getpid())
1690		/*
1691		 * signal master to call dumpabort
1692		 */
1693		(void) kill(master, SIGTERM);
1694	else {
1695		killall();
1696
1697		if (archivefile && archive_opened)
1698			(void) unlink(archivefile);
1699		msg(gettext("The ENTIRE dump is aborted.\n"));
1700	}
1701	Exit(X_ABORT);
1702}
1703
1704void
1705dumpailing(void)
1706{
1707
1708	broadcast(gettext("DUMP IS AILING!\n"));
1709	if (!query(gettext(
1710	    "Do you want to attempt to continue? (\"yes\" or \"no\") "))) {
1711		dumpabort();
1712		/*NOTREACHED*/
1713	}
1714}
1715
1716void
1717Exit(status)
1718{
1719	/*
1720	 * Clean up message system
1721	 */
1722#ifdef TDEBUG
1723
1724	/* XGETTEXT:  #ifdef TDEBUG only */
1725	msg(gettext("pid = %ld exits with status %d\n"),
1726		(long)getpid(), status);
1727#endif /* TDEBUG */
1728	exit(status);
1729}
1730
1731static void
1732#ifdef __STDC__
1733killall(void)
1734#else
1735killall()
1736#endif
1737{
1738	struct slaves *slavep;
1739
1740	for (slavep = &slaves[0]; slavep < &slaves[SLAVES]; slavep++)
1741		if (slavep->sl_slavepid > 0) {
1742			(void) kill(slavep->sl_slavepid, SIGKILL);
1743#ifdef TDEBUG
1744
1745			/* XGETTEXT:  #ifdef TDEBUG only */
1746			msg(gettext("Slave child %ld killed\n"),
1747				(long)slavep->sl_slavepid);
1748#endif
1749		}
1750	if (writepid) {
1751		(void) kill(writepid, SIGKILL);
1752#ifdef TDEBUG
1753
1754		/* XGETTEXT:  #ifdef TDEBUG only */
1755		msg(gettext("Writer child %ld killed\n"), (long)writepid);
1756#endif
1757	}
1758	if (archivepid) {
1759		(void) kill(archivepid, SIGKILL);
1760#ifdef TDEBUG
1761
1762		/* XGETTEXT:  #ifdef TDEBUG only */
1763		msg(gettext("Archiver child %ld killed\n"), (long)archivepid);
1764#endif
1765	}
1766}
1767
1768/*ARGSUSED*/
1769static void
1770proceed(int sig)
1771{
1772	caught++;
1773}
1774
1775/*ARGSUSED*/
1776static void
1777die(int sig)
1778{
1779	Exit(X_FINOK);
1780}
1781
1782static void
1783#ifdef __STDC__
1784enslave(void)
1785#else
1786enslave()
1787#endif
1788{
1789	int cmd[2];			/* file descriptors */
1790	int i;
1791	struct sigvec sv;
1792	struct slaves *slavep;
1793	int saverr;
1794
1795	sv.sv_flags = SA_RESTART;
1796	(void) sigemptyset(&sv.sa_mask);
1797	master = getpid();
1798	/*
1799	 * slave sends SIGTERM on dumpabort
1800	 */
1801	sv.sv_handler = (void(*)(int))dumpabort;
1802	(void) sigvec(SIGTERM, &sv, (struct sigvec *)0);
1803	sv.sv_handler = tperror;
1804	(void) sigvec(SIGUSR2, &sv, (struct sigvec *)0);
1805	sv.sv_handler = proceed;
1806	(void) sigvec(SIGUSR1, &sv, (struct sigvec *)0);
1807	totalrecsout += recsout;
1808	caught = 0;
1809	recsout = 0;
1810	rotor = 0;
1811	bufclear();
1812	for (slavep = &slaves[0]; slavep < &slaves[SLAVES]; slavep++)
1813		slavep->sl_slavefd = -1;
1814	archivefd = arch = writer = -1;
1815	for (i = 0; i < SLAVES; i++) {
1816		if (pipe(cmd) < 0) {
1817			saverr = errno;
1818			msg(gettext(
1819			    "Cannot create pipe for slave process: %s\n"),
1820			    strerror(saverr));
1821			dumpabort();
1822			/*NOTREACHED*/
1823		}
1824		sighold(SIGUSR2);
1825		sighold(SIGINT);
1826		sighold(SIGTERM);
1827		if ((slaves[i].sl_slavepid = fork()) < 0) {
1828			saverr = errno;
1829			msg(gettext("Cannot create slave process: %s\n"),
1830			    strerror(saverr));
1831			dumpabort();
1832			/*NOTREACHED*/
1833		}
1834		slaves[i].sl_slavefd = cmd[1];
1835		if (slaves[i].sl_slavepid == 0) {   /* Slave starts up here */
1836			pid_t next;		    /* pid of neighbor */
1837
1838			sv.sv_handler = SIG_DFL;
1839			(void) sigvec(SIGUSR2, &sv, (struct sigvec *)0);
1840			sv.sv_handler = SIG_IGN;	/* master handler INT */
1841			(void) sigvec(SIGINT, &sv, (struct sigvec *)0);
1842			sv.sv_handler = die;		/* normal slave exit */
1843			(void) sigvec(SIGTERM, &sv, (struct sigvec *)0);
1844
1845			child_chdir();
1846			sigrelse(SIGUSR2);
1847			sigrelse(SIGINT);
1848			sigrelse(SIGTERM);
1849
1850			freeino();	/* release unneeded resources */
1851#ifdef TDEBUG
1852		(void) sleep(4); /* time for parent's message to get out */
1853		/* XGETTEXT:  #ifdef TDEBUG only */
1854		msg(gettext("Neighbor has pid = %ld\n"), (long)getpid());
1855#endif
1856			/* Closes cmd[1] as a side-effect */
1857			for (slavep = &slaves[0];
1858			    slavep < &slaves[SLAVES];
1859			    slavep++)
1860				if (slavep->sl_slavefd >= 0) {
1861					(void) close(slavep->sl_slavefd);
1862					slavep->sl_slavefd = -1;
1863				}
1864			(void) close(to);
1865			(void) close(fi);	    /* Need our own seek ptr */
1866			to = -1;
1867
1868			fi = open(disk, O_RDONLY);
1869
1870			if (fi < 0) {
1871				saverr = errno;
1872				msg(gettext(
1873				    "Cannot open dump device `%s': %s\n"),
1874					disk, strerror(saverr));
1875				dumpabort();
1876				/*NOTREACHED*/
1877			}
1878
1879			if ((unsigned)atomic((int(*)())read, cmd[0],
1880			    (char *)&next, sizeof (next)) != sizeof (next)) {
1881				cmdrderr();
1882				dumpabort();
1883				/*NOTREACHED*/
1884			}
1885			dumpoffline(cmd[0], next, i);
1886			Exit(X_FINOK);
1887		}
1888		/* Parent continues here */
1889		sigrelse(SIGUSR2);
1890		sigrelse(SIGINT);
1891		sigrelse(SIGTERM);
1892		(void) close(cmd[0]);
1893	}
1894
1895	if (archive) {
1896		archivepid = setuparchive();
1897		if (!archivepid) {
1898			dumpabort();
1899			/*NOTREACHED*/
1900		}
1901	}
1902
1903	writepid = setupwriter();
1904	if (!writepid) {
1905		dumpabort();
1906		/*NOTREACHED*/
1907	}
1908
1909	if (arch >= 0) {
1910		(void) close(arch);		/* only writer has this open */
1911		arch = -1;
1912	}
1913
1914	/* Tell each slave who follows it */
1915	for (i = 0; i < SLAVES; i++) {
1916		if ((unsigned)atomic((int(*)())write, slaves[i].sl_slavefd,
1917		    (char *)&(slaves[(i + 1) % SLAVES].sl_slavepid),
1918		    sizeof (int)) != sizeof (int)) {
1919			cmdwrterr();
1920			dumpabort();
1921			/*NOTREACHED*/
1922		}
1923	}
1924	sv.sv_handler = rollforward;		/* rcvd from writer on EOT */
1925	(void) sigvec(SIGUSR1, &sv, (struct sigvec *)0);
1926	slp = slaves;
1927	(void) kill(slp->sl_slavepid, SIGUSR1);
1928	master = 0;
1929}
1930
1931static void
1932#ifdef __STDC__
1933wait_our_turn(void)
1934#else
1935wait_our_turn()
1936#endif
1937{
1938	(void) sighold(SIGUSR1);
1939
1940	if (!caught) {
1941#ifdef INSTRUMENT
1942		(*idle)++;
1943#endif
1944		(void) sigpause(SIGUSR1);
1945	}
1946	caught = 0;
1947	(void) sigrelse(SIGUSR1);
1948}
1949
1950static void
1951dumpoffline(int cmd, pid_t next, int mynum)
1952{
1953	struct req *p = slaves[mynum].sl_req;
1954	ulong_t i;
1955	uchar_t *cp;
1956	uchar_t *blkbuf;
1957	int notactive = 0;
1958
1959	blkbuf = xmalloc(sblock->fs_bsize);
1960
1961	/*CONSTANTCONDITION*/
1962	assert(sizeof (spcl) == TP_BSIZE_MIN);
1963
1964	while (atomic((int(*)())read, cmd, (char *)p, reqsiz) == reqsiz) {
1965		if (p->br_dblk) {
1966			bread(p->br_dblk, (uchar_t *)blkbuf, p->br_size);
1967		} else {
1968			bcopy((char *)p->br_spcl, (char *)&spcl,
1969			    sizeof (spcl));
1970			ino = spcl.c_inumber;
1971		}
1972		dumptoarchive = p->aflag & BUF_ARCHIVE;
1973		wait_our_turn();
1974		if (p->br_dblk) {
1975			for (i = p->br_size, cp = blkbuf;
1976			    i > 0;
1977			    /* LINTED character pointers aren't signed */
1978			    cp += i > tp_bsize ? tp_bsize : i,
1979			    i -= i > tp_bsize ? tp_bsize : i) {
1980				/* LINTED unsigned to signed conversion ok */
1981				taprec(cp, 0, i > tp_bsize ? tp_bsize : (int)i);
1982			}
1983		} else
1984			spclrec();
1985		(void) kill(next, SIGUSR1);	/* Next slave's turn */
1986		/*
1987		 * Note that we lie about file activity since we don't
1988		 * check for it.
1989		 */
1990		if ((unsigned)atomic((int(*)())write, cmd, (char *)&notactive,
1991		    sizeof (notactive)) != sizeof (notactive)) {
1992			cmdwrterr();
1993			dumpabort();
1994			/*NOTREACHED*/
1995		}
1996	}
1997
1998	free(blkbuf);
1999}
2000
2001static int count;		/* tape blocks written since last spclrec */
2002
2003/*ARGSUSED*/
2004static void
2005onxfsz(int sig)
2006{
2007	msg(gettext("File size limit exceeded writing output volume %d\n"),
2008	    tapeno);
2009	(void) kill(master, SIGUSR2);
2010	Exit(X_REWRITE);
2011}
2012
2013static long	lastnonaddr;		/* last DS_{INODE,CLRI,BITS} written */
2014static long	lastnonaddrm;		/* and the mode thereof */
2015/*
2016 * dowrite -- the main body of the output writer process
2017 */
2018static void
2019dowrite(int cmd)
2020{
2021	struct bdesc *last =
2022	    &bufp[(NBUF*ntrec)-1];		/* last buffer in pool */
2023	struct bdesc *bp = bufp;		/* current buf in tape block */
2024	struct bdesc *begin = bufp;		/* first buf of tape block */
2025	struct bdesc *end = bufp + (ntrec-1);	/* last buf of tape block */
2026	int siz;				/* bytes written (block) */
2027	int trecs;				/* records written (block)  */
2028	long asize = 0;				/* number of 0.1" units... */
2029						/* ...written on current tape */
2030	char *tp, *rbuf = NULL;
2031	char *recmap = spcl.c_addr;		/* current tape record map */
2032	char *endmp;				/* end of valid map data */
2033	char *mp;				/* current map entry */
2034	union u_spcl *sp;
2035
2036	(void) signal(SIGXFSZ, onxfsz);
2037
2038	bzero((char *)&spcl, sizeof (spcl));
2039	count = 0;
2040
2041	if (doingverify) {
2042		rbuf = (char *)malloc((uint_t)writesize);
2043		if (rbuf == 0) {
2044			/* Restart from checkpoint */
2045			(void) kill(master, SIGUSR2);
2046			Exit(X_REWRITE);
2047		}
2048	}
2049
2050	for (;;) {
2051		/* START: wait until all buffers in tape block are full */
2052		if ((bp->b_flags & BUF_FULL) == 0) {
2053			if (caught) {		/* master signalled flush */
2054				(void) sighold(SIGUSR1);
2055				caught = 0;
2056				/* signal ready */
2057				(void) kill(master, SIGUSR1);
2058				chkpt.sl_count = 0;	/* signal not at EOT */
2059				checkpoint(bp-1, cmd);	/* send data */
2060				(void) sigpause(SIGUSR1);
2061				break;
2062			}
2063#ifdef INSTRUMENT
2064			(*readmissp)++;
2065#endif
2066			nap(50);
2067			continue;
2068		}
2069		if (bp < end) {
2070			bp++;
2071			continue;
2072		}
2073		/* END: wait until all buffers in tape block are full */
2074
2075		tp = begin->b_data;
2076		(void) sighold(SIGUSR1);
2077		if (host) {
2078			if (!doingverify)
2079				siz = rmtwrite(tp, writesize);
2080			else if ((siz = rmtread(rbuf, writesize)) ==
2081			    writesize && bcmp(rbuf, tp, writesize))
2082				siz = -1;
2083		} else {
2084			if (!doingverify)
2085				siz = write(to, tp, writesize);
2086			else if ((siz = read(to, rbuf, writesize)) ==
2087			    writesize && bcmp(rbuf, tp, writesize))
2088				siz = -1;
2089			if (siz < 0 && diskette && errno == ENOSPC)
2090				siz = 0;	/* really EOF */
2091		}
2092		(void) sigrelse(SIGUSR1);
2093		if (siz < 0 ||
2094		    (pipeout && siz != writesize)) {
2095			char buf[3000];
2096
2097			/*
2098			 * Isn't i18n wonderful?
2099			 */
2100			if (doingverify) {
2101				if (diskette)
2102					(void) snprintf(buf, sizeof (buf),
2103					    gettext(
2104		    "Verification error %ld blocks into diskette %d\n"),
2105					    asize * 2, tapeno);
2106				else if (tapeout)
2107					(void) snprintf(buf, sizeof (buf),
2108					    gettext(
2109		    "Verification error %ld feet into tape %d\n"),
2110					    (cartridge ? asize/tracks :
2111						asize)/120L,
2112					    tapeno);
2113				else
2114					(void) snprintf(buf, sizeof (buf),
2115					    gettext(
2116		    "Verification error %ld blocks into volume %d\n"),
2117					    asize * 2, tapeno);
2118
2119			} else {
2120				if (diskette)
2121					(void) snprintf(buf, sizeof (buf),
2122					    gettext(
2123			"Write error %ld blocks into diskette %d\n"),
2124					    asize * 2, tapeno);
2125				else if (tapeout)
2126					(void) snprintf(buf, sizeof (buf),
2127					    gettext(
2128			"Write error %ld feet into tape %d\n"),
2129					    (cartridge ? asize/tracks :
2130						asize)/120L, tapeno);
2131				else
2132					(void) snprintf(buf, sizeof (buf),
2133					    gettext(
2134			"Write error %ld blocks into volume %d\n"),
2135					    asize * 2, tapeno);
2136			}
2137
2138			msg(buf);
2139			/* Restart from checkpoint */
2140#ifdef TDEBUG
2141
2142			/* XGETTEXT:  #ifdef TDEBUG only */
2143			msg(gettext("sending SIGUSR2 to pid %ld\n"), master);
2144#endif
2145			(void) kill(master, SIGUSR2);
2146			Exit(X_REWRITE);
2147		}
2148		trecs = siz / tp_bsize;
2149		if (diskette)
2150			asize += trecs;	/* asize == blocks written */
2151		else
2152			asize += (siz/density + tenthsperirg);
2153		if (trecs)
2154			chkpt.sl_firstrec++;
2155		for (bp = begin; bp < begin + trecs; bp++) {
2156			if ((arch >= 0) && (bp->b_flags & BUF_ARCHIVE)) {
2157				if ((unsigned)atomic((int(*)())write, arch,
2158				    (char *)&bp->b_flags, sizeof (bp->b_flags))
2159				    != sizeof (bp->b_flags)) {
2160					cmdwrterr();
2161					dumpabort();
2162					/*NOTREACHED*/
2163				}
2164				if (atomic((int(*)())write, arch, bp->b_data,
2165				    tp_bsize) != tp_bsize) {
2166					cmdwrterr();
2167					dumpabort();
2168					/*NOTREACHED*/
2169				}
2170			}
2171			if (bp->b_flags & BUF_SPCLREC) {
2172				/*LINTED [bp->b_data is aligned]*/
2173				sp = (union u_spcl *)bp->b_data;
2174				if (sp->s_spcl.c_type != TS_ADDR) {
2175					lastnonaddr = sp->s_spcl.c_type;
2176					lastnonaddrm =
2177						sp->s_spcl.c_dinode.di_mode;
2178					if (sp->s_spcl.c_type != TS_TAPE)
2179						chkpt.sl_offset = 0;
2180				}
2181				chkpt.sl_count = sp->s_spcl.c_count;
2182				bcopy((char *)sp,
2183					(char *)&spcl, sizeof (spcl));
2184				mp = recmap;
2185				endmp = &recmap[spcl.c_count];
2186				count = 0;
2187			} else {
2188				chkpt.sl_offset++;
2189				chkpt.sl_count--;
2190				count++;
2191				mp++;
2192			}
2193			/*
2194			 * Adjust for contiguous hole
2195			 */
2196			for (; mp < endmp; mp++) {
2197				if (*mp)
2198					break;
2199				chkpt.sl_offset++;
2200				chkpt.sl_count--;
2201			}
2202		}
2203		/*
2204		 * Check for end of tape
2205		 */
2206		if (trecs < ntrec ||
2207		    (!pipeout && tsize > 0 && asize > tsize)) {
2208			if (tapeout)
2209				msg(gettext("End-of-tape detected\n"));
2210			else
2211				msg(gettext("End-of-file detected\n"));
2212			(void) sighold(SIGUSR1);
2213			caught = 0;
2214			(void) kill(master, SIGUSR1);	/* signal EOT */
2215			checkpoint(--bp, cmd);	/* send checkpoint data */
2216			(void) sigpause(SIGUSR1);
2217			break;
2218		}
2219		for (bp = begin; bp <= end; bp++)
2220			bp->b_flags = BUF_EMPTY;
2221		if (end + ntrec > last) {
2222			bp = begin = bufp;
2223			timeest(0, spcl.c_tapea);
2224		} else
2225			bp = begin = end+1;
2226		end = begin + (ntrec-1);
2227	}
2228
2229	if (rbuf != NULL)
2230		free(rbuf);
2231}
2232
2233/*
2234 * Send checkpoint info back to master.  This information
2235 * consists of the current inode number, number of logical
2236 * blocks written for that inode (or bitmap), the last logical
2237 * block number written, the number of logical blocks written
2238 * to this volume, the current dump state, and the current
2239 * special record map.
2240 */
2241static void
2242checkpoint(struct bdesc *bp, int cmd)
2243{
2244	int	state, type;
2245	ino_t	ino;
2246
2247	if (++bp >= &bufp[NBUF*ntrec])
2248		bp = bufp;
2249
2250	/*
2251	 * If we are dumping files and the record following
2252	 * the last written to tape is a special record, use
2253	 * it to get an accurate indication of current state.
2254	 */
2255	if ((bp->b_flags & BUF_SPCLREC) && (bp->b_flags & BUF_FULL) &&
2256	    lastnonaddr == TS_INODE) {
2257		/*LINTED [bp->b_data is aligned]*/
2258		union u_spcl *nextspcl = (union u_spcl *)bp->b_data;
2259
2260		if (nextspcl->s_spcl.c_type == TS_INODE) {
2261			chkpt.sl_offset = 0;
2262			chkpt.sl_count = 0;
2263		} else if (nextspcl->s_spcl.c_type == TS_END) {
2264			chkpt.sl_offset = 0;
2265			chkpt.sl_count = 1;	/* EOT indicator */
2266		}
2267		ino = nextspcl->s_spcl.c_inumber;
2268		type = nextspcl->s_spcl.c_type;
2269	} else {
2270		/*
2271		 * If not, use what we have.
2272		 */
2273		ino = spcl.c_inumber;
2274		type = spcl.c_type;
2275	}
2276
2277	switch (type) {		/* set output state */
2278	case TS_ADDR:
2279		switch (lastnonaddr) {
2280		case TS_INODE:
2281		case TS_TAPE:
2282			if ((lastnonaddrm & IFMT) == IFDIR ||
2283			    (lastnonaddrm & IFMT) == IFATTRDIR)
2284				state = DS_DIRS;
2285			else
2286				state = DS_FILES;
2287			break;
2288		case TS_CLRI:
2289			state = DS_CLRI;
2290			break;
2291		case TS_BITS:
2292			state = DS_BITS;
2293			break;
2294		}
2295		break;
2296	case TS_INODE:
2297		if ((spcl.c_dinode.di_mode & IFMT) == IFDIR ||
2298		    (spcl.c_dinode.di_mode & IFMT) == IFATTRDIR)
2299			state = DS_DIRS;
2300		else
2301			state = DS_FILES;
2302		break;
2303	case 0:			/* EOT on 1st record */
2304	case TS_TAPE:
2305		state = DS_START;
2306		ino = UFSROOTINO;
2307		break;
2308	case TS_CLRI:
2309		state = DS_CLRI;
2310		break;
2311	case TS_BITS:
2312		state = DS_BITS;
2313		break;
2314	case TS_END:
2315		if (spcl.c_type == TS_END)
2316			state = DS_DONE;
2317		else
2318			state = DS_END;
2319		break;
2320	}
2321
2322	/*
2323	 * Checkpoint info to be processed by rollforward():
2324	 *	The inode with which the next volume should begin
2325	 *	The last inode number on this volume
2326	 *	The last logical block number on this volume
2327	 *	The current output state
2328	 *	The offset within the current inode (already in sl_offset)
2329	 *	The number of records left from last spclrec (in sl_count)
2330	 *	The physical block the next vol begins with (in sl_firstrec)
2331	 */
2332	chkpt.sl_inos = ino;
2333	chkpt.sl_tapea = spcl.c_tapea + count;
2334	chkpt.sl_state = state;
2335
2336	if ((unsigned)atomic((int(*)())write, cmd, (char *)&chkpt,
2337	    sizeof (chkpt)) != sizeof (chkpt)) {
2338		cmdwrterr();
2339		dumpabort();
2340		/*NOTREACHED*/
2341	}
2342	if ((unsigned)atomic((int(*)())write, cmd, (char *)&spcl,
2343	    sizeof (spcl)) != sizeof (spcl)) {
2344		cmdwrterr();
2345		dumpabort();
2346		/*NOTREACHED*/
2347	}
2348#ifdef DEBUG
2349	if (xflag) {
2350		/* XGETTEXT:  #ifdef DEBUG only */
2351		msg(gettext("sent chkpt to master:\n"));
2352		msg("    ino %u\n", chkpt.sl_inos);
2353		msg("    1strec %u\n", chkpt.sl_firstrec);
2354		msg("    lastrec %u\n", chkpt.sl_tapea);
2355		msg("    written %u\n", chkpt.sl_offset);
2356		msg("    left %u\n", chkpt.sl_count);
2357		msg("    state %d\n", chkpt.sl_state);
2358	}
2359#endif
2360}
2361
2362/*
2363 * Since a read from a pipe may not return all we asked for,
2364 * or a write may not write all we ask if we get a signal,
2365 * loop until the count is satisfied (or error).
2366 */
2367static ssize_t
2368atomic(int (*func)(), int fd, char *buf, int count)
2369{
2370	ssize_t got = 0, need = count;
2371
2372	/* don't inherit random value if immediately get zero back from func */
2373	errno = 0;
2374	while (need > 0) {
2375		got = (*func)(fd, buf, MIN(need, 4096));
2376		if (got < 0 && errno == EINTR)
2377			continue;
2378		if (got <= 0)
2379			break;
2380		buf += got;
2381		need -= got;
2382	}
2383	/* if we got what was asked for, return count, else failure (got) */
2384	return ((need != 0) ? got : count);
2385}
2386
2387void
2388#ifdef __STDC__
2389positiontape(char *msgbuf)
2390#else
2391positiontape(char *msgbuf)
2392#endif
2393{
2394	/* Static as never change, no need to waste stack space */
2395	static struct mtget mt;
2396	static struct mtop rew = { MTREW, 1 };
2397	static struct mtop fsf = { MTFSF, 1 };
2398	char *info = strdup(gettext("Positioning `%s' to file %ld\n"));
2399	char *fail = strdup(gettext("Cannot position tape to file %d\n"));
2400	int m;
2401
2402	/* gettext()'s return value is volatile, hence the strdup()s */
2403
2404	m = (access(tape, F_OK) == 0) ? 0 : O_CREAT;
2405
2406	/*
2407	 * To avoid writing tape marks at inappropriate places, we open the
2408	 * device read-only, position it, close it, and reopen it for writing.
2409	 */
2410	while ((to = host ? rmtopen(tape, O_RDONLY) :
2411	    safe_device_open(tape, O_RDONLY|m, 0600)) < 0) {
2412		if (autoload) {
2413			if (!query_once(msgbuf, 1)) {
2414				dumpabort();
2415				/*NOTREACHED*/
2416			}
2417		} else {
2418			if (!query(msgbuf)) {
2419				dumpabort();
2420				/*NOTREACHED*/
2421			}
2422		}
2423	}
2424
2425	if (host) {
2426		if (rmtstatus(&mt) >= 0 &&
2427		    rmtioctl(MTREW, 1) >= 0 &&
2428		    filenum > 1) {
2429			msg(info, dumpdev, filenum);
2430			if (rmtioctl(MTFSF, filenum-1) < 0) {
2431				msg(fail, filenum);
2432				dumpabort();
2433				/*NOTREACHED*/
2434			}
2435		}
2436		rmtclose();
2437	} else {
2438		if (ioctl(to, MTIOCGET, &mt) >= 0 &&
2439		    ioctl(to, MTIOCTOP, &rew) >= 0 &&
2440		    filenum > 1) {
2441			msg(info, dumpdev, filenum);
2442			fsf.mt_count = filenum - 1;
2443			if (ioctl(to, MTIOCTOP, &fsf) < 0) {
2444				msg(fail, filenum);
2445				dumpabort();
2446				/*NOTREACHED*/
2447			}
2448		}
2449		(void) close(to);
2450		to = -1;
2451	}
2452
2453	free(info);
2454	free(fail);
2455}
2456
2457static void
2458#ifdef __STDC__
2459cmdwrterr(void)
2460#else
2461cmdwrterr()
2462#endif
2463{
2464	int saverr = errno;
2465	msg(gettext("Error writing command pipe: %s\n"), strerror(saverr));
2466}
2467
2468static void
2469#ifdef __STDC__
2470cmdrderr(void)
2471#else
2472cmdrderr()
2473#endif
2474{
2475	int saverr = errno;
2476	msg(gettext("Error reading command pipe: %s\n"), strerror(saverr));
2477}
2478