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