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 *)¬active,
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