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