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