xref: /illumos-gate/usr/src/cmd/backup/dump/dumptape.c (revision 7d1e83948cb684521e72cab96020be241508f449)
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 
44 static uint_t writesize;	/* size of malloc()ed buffer for tape */
45 static 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  */
59 struct 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  */
70 struct 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 
76 struct 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 
94 static int reqsiz = 0;	/* alloctape will initialize */
95 
96 #define	SLAVES 3
97 struct 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 };
108 static struct slaves slaves[SLAVES];	/* one per slave */
109 static struct slaves *slp;	/* pointer to current slave */
110 static struct slaves chkpt;	/* checkpointed data */
111 
112 struct 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  */
121 static caddr_t shared;		/* pointer to block of shared memory */
122 static struct bdesc *bufp;	/* buffer descriptors */
123 static struct bdesc **current;	/* output buffer to fill */
124 static int *tapea;		/* logical record count */
125 
126 #ifdef INSTRUMENT
127 static int	*readmissp;	/* number of times writer was idle */
128 static 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 
139 static int recsout;		/* number of req's sent to slaves */
140 static int totalrecsout;	/* total number of req's sent to slaves */
141 static int rotor;		/* next slave to be instructed */
142 static pid_t master;		/* pid of master, for sending error signals */
143 static int writer = -1;		/* fd of tape writer */
144 static pid_t writepid;		/* pid of tape writer */
145 static int arch;		/* fd of output archiver */
146 static pid_t archivepid;	/* pid of output archiver */
147 static int archivefd;		/* fd of archive file (proper) */
148 static offset_t lf_archoffset;	/* checkpointed offset into archive file */
149 
150 int caught;			/* caught signal -- imported by mapfile() */
151 
152 #ifdef DEBUG
153 extern	int xflag;
154 #endif
155 
156 #ifdef __STDC__
157 static void cmdwrterr(void);
158 static void cmdrderr(void);
159 static void freetape(void);
160 static void bufclear(void);
161 static pid_t setuparchive(void);
162 static pid_t setupwriter(void);
163 static void nextslave(void);
164 static void tperror(int);
165 static void rollforward(int);
166 static void nap(int);
167 static void alrm(int);
168 static void just_rewind(void);
169 static void killall(void);
170 static void proceed(int);
171 static void die(int);
172 static void enslave(void);
173 static void wait_our_turn(void);
174 static void dumpoffline(int, pid_t, int);
175 static void onxfsz(int);
176 static void dowrite(int);
177 static void checkpoint(struct bdesc *, int);
178 static ssize_t atomic(int (*)(), int, char *, int);
179 #else
180 static void cmdwrterr();
181 static void cmdrderr();
182 static void freetape();
183 static void bufclear();
184 static pid_t setuparchive();
185 static pid_t setupwriter();
186 static void nextslave();
187 static void tperror();
188 static void rollforward();
189 static void nap();
190 static void alrm();
191 static void just_rewind();
192 static void killall();
193 static void proceed();
194 static void die();
195 static void enslave();
196 static void wait_our_turn();
197 static void dumpoffline();
198 static void onxfsz();
199 static void dowrite();
200 static void checkpoint();
201 static ssize_t atomic();
202 #endif
203 
204 static 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  */
210 void
211 #ifdef __STDC__
212 #else
213 #endif
214 alloctape(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 
314 static void
315 #ifdef __STDC__
316 freetape(void)
317 #else
318 freetape()
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  */
332 void
333 #ifdef __STDC__
334 reset(void)
335 #else
336 reset()
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 
357 static void
358 #ifdef __STDC__
359 bufclear(void)
360 #else
361 bufclear()
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  */
398 static pid_t
399 setuparchive(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  */
548 static pid_t
549 setupwriter(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 
610 void
611 #ifdef __STDC__
612 spclrec(void)
613 #else
614 spclrec()
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  */
676 void
677 taprec(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 
705 void
706 dmpblk(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*/
723 static void
724 tperror(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  */
771 void
772 toslave(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 
811 void
812 dospcl(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 
820 static void
821 #ifdef __STDC__
822 nextslave(void)
823 #else
824 nextslave()
825 #endif
826 {
827 	if (++rotor >= SLAVES) {
828 		rotor = 0;
829 	}
830 	slp = &slaves[rotor];
831 }
832 
833 void
834 #ifdef __STDC__
835 flushcmds(void)
836 #else
837 flushcmds()
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 
870 void
871 #ifdef __STDC__
872 flusht(void)
873 #else
874 flusht()
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 
887 jmp_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*/
898 static void
899 rollforward(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 
1006 static void
1007 nap(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 
1016 static jmp_buf alrm_buf;
1017 
1018 /*ARGSUSED*/
1019 static void
1020 alrm(int sig)
1021 {
1022 	longjmp(alrm_buf, 1);
1023 	/*NOTREACHED*/
1024 }
1025 
1026 void
1027 #ifdef __STDC__
1028 nextdevice(void)
1029 #else
1030 nextdevice()
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  */
1085 int
1086 isrewind(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 
1124 static void
1125 #ifdef __STDC__
1126 just_rewind(void)
1127 #else
1128 just_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 
1181 void
1182 #ifdef __STDC__
1183 trewind(void)
1184 #else
1185 trewind()
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 
1202 void
1203 #ifdef __STDC__
1204 close_rewind(void)
1205 #else
1206 close_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 
1240 void
1241 #ifdef __STDC__
1242 changevol(void)
1243 #else
1244 changevol()
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 
1374 void
1375 otape(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 	}
1398 restore_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 
1681 void
1682 #ifdef __STDC__
1683 dumpabort(void)
1684 #else
1685 dumpabort()
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 
1704 void
1705 dumpailing(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 
1716 void
1717 Exit(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 
1731 static void
1732 #ifdef __STDC__
1733 killall(void)
1734 #else
1735 killall()
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*/
1769 static void
1770 proceed(int sig)
1771 {
1772 	caught++;
1773 }
1774 
1775 /*ARGSUSED*/
1776 static void
1777 die(int sig)
1778 {
1779 	Exit(X_FINOK);
1780 }
1781 
1782 static void
1783 #ifdef __STDC__
1784 enslave(void)
1785 #else
1786 enslave()
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 
1931 static void
1932 #ifdef __STDC__
1933 wait_our_turn(void)
1934 #else
1935 wait_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 
1950 static void
1951 dumpoffline(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 
2001 static int count;		/* tape blocks written since last spclrec */
2002 
2003 /*ARGSUSED*/
2004 static void
2005 onxfsz(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 
2013 static long	lastnonaddr;		/* last DS_{INODE,CLRI,BITS} written */
2014 static long	lastnonaddrm;		/* and the mode thereof */
2015 /*
2016  * dowrite -- the main body of the output writer process
2017  */
2018 static void
2019 dowrite(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  */
2241 static void
2242 checkpoint(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  */
2367 static ssize_t
2368 atomic(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 
2387 void
2388 #ifdef __STDC__
2389 positiontape(char *msgbuf)
2390 #else
2391 positiontape(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 
2457 static void
2458 #ifdef __STDC__
2459 cmdwrterr(void)
2460 #else
2461 cmdwrterr()
2462 #endif
2463 {
2464 	int saverr = errno;
2465 	msg(gettext("Error writing command pipe: %s\n"), strerror(saverr));
2466 }
2467 
2468 static void
2469 #ifdef __STDC__
2470 cmdrderr(void)
2471 #else
2472 cmdrderr()
2473 #endif
2474 {
2475 	int saverr = errno;
2476 	msg(gettext("Error reading command pipe: %s\n"), strerror(saverr));
2477 }
2478