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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * Copyright (c) 1980 Regents of the University of California.
32 * All rights reserved. The Berkeley software License Agreement
33 * specifies the terms and conditions for redistribution.
39 #include <priv_utils.h>
43 int notify
= 0; /* notify operator flag */
44 int blockswritten
= 0; /* number of blocks written on current tape */
45 uint_t tapeno
= 0; /* current tape number */
46 daddr32_t filenum
= 0; /* current file number on tape */
47 int density
= 0; /* density in bytes/0.1" */
48 int tenthsperirg
; /* inter-record-gap in 0.1"'s */
49 uint_t ntrec
= 0; /* # tape blocks in each tape record */
50 uint_t saved_ntrec
= 0; /* saved value of ntrec */
51 uint_t forceflag
= 0; /* forced to change tp_bsize */
52 int cartridge
= 0; /* assume non-cartridge tape */
53 uint_t tracks
; /* # tracks on a cartridge tape */
54 int diskette
= 0; /* assume not dumping to a diskette */
55 int printsize
= 0; /* just print estimated size and exit */
56 int mapfd
= -1; /* if >= 0, file descriptor for mmap */
57 int32_t tp_bsize
= TP_BSIZE_MIN
; /* tape block record size (frag size) */
59 int xflag
; /* debugging switch */
65 * This should be struct fs, but there are trailing bits on disk
66 * that we also need to read in as part of it. It's an array of
67 * longs instead of char to force proper alignment.
69 static long sblock_buf
[SBSIZE
/sizeof (long)];
72 static char *mb(uoff_t
);
73 static void nextstate(int);
76 static void nextstate();
79 extern jmp_buf checkpoint_buf
; /* context for return from checkpoint */
80 #define FUDGE_FACTOR 0x2000000
83 main(int argc
, char *argv
[])
86 int bflag
= 0, i
, error
= 0, saverr
;
89 char msgbuf
[3000], *msgp
;
91 uoff_t esize_shift
= 0;
95 if (myname
= strrchr(argv
[0], '/'))
100 if (strcmp("hsmdump", myname
) == 0) {
101 msg(gettext("hsmdump emulation is no longer supported.\n"));
106 autoload_period
= 12;
107 autoload_tries
= 12; /* traditional default of ~2.5 minutes */
109 (void) setlocale(LC_ALL
, "");
110 #if !defined(TEXT_DOMAIN)
111 #define TEXT_DOMAIN "SYS_TEST"
112 #endif /* TEXT_DOMAIN */
113 (void) textdomain(TEXT_DOMAIN
);
116 * If someone strips the set-uid bit, dump will still work for local
117 * tapes. Fail when we try to access a remote tape.
119 (void) __init_suid_priv(0, PRIV_NET_PRIVADDR
, NULL
);
121 if (sysinfo(SI_HOSTNAME
, spcl
.c_host
, sizeof (spcl
.c_host
)) < 0) {
123 msg(gettext("Could not get host name: %s\n"),
125 bzero(spcl
.c_host
, sizeof (spcl
.c_host
));
129 tsize
= 0; /* no default size, detect EOT dynamically */
148 switch (*arg
++) { /* BE CAUTIOUS OF FALLTHROUGHS */
151 * This undocumented option causes each process to
152 * mkdir debug_chdir/getpid(), and chdir to it. This is
153 * to ease the collection of profiling information and
161 "Each process shall try to chdir to %s/<pid>\n"),
165 msg(gettext("Missing move-to-dir (M) name\n"));
172 lastdump('w'); /* tell us only what has to be done */
176 case 'W': /* what to do */
177 lastdump('W'); /* tell state of what has been done */
178 exit(0); /* do nothing else */
192 "Unreasonable autoload timeout period\n"));
196 units
= *(*argv
+ strlen(*argv
) - 1);
204 case '0': case '1': case '2': case '3': case '4':
205 case '5': case '6': case '7': case '8': case '9':
211 "Unknown timeout units indicator `%c'\n"),
217 ((count
* multiplier
) / autoload_period
);
219 msg(gettext("Missing autoload timeout period\n"));
225 case 'f': /* output file */
231 msg(gettext("Bad output device name\n"));
236 msg(gettext("Missing output device name\n"));
240 if (strcmp(tape
, "-") == 0 && verify
) {
242 "Cannot verify when dumping to standard out.\n"));
248 case 'd': /* density, in bits per inch */
252 density
= atoi(*argv
) / 10;
255 "Density must be a positive integer\n"));
260 msg(gettext("Missing density\n"));
266 case 's': /* tape size, feet */
271 if ((*argv
[0] == '-') || (tsize
== 0)) {
273 "Tape size must be a positive integer\n"));
278 msg(gettext("Missing tape size\n"));
284 case 't': /* tracks */
288 tracks
= atoi(*argv
);
290 msg(gettext("Missing track count\n"));
296 case 'b': /* blocks per tape write */
302 * We save the ntrec in case we need to change
303 * tp_bsize later, we will have to recalculate
306 saved_ntrec
= ntrec
= atoi(*argv
);
307 if (ntrec
== 0 || (ntrec
&1) || ntrec
> (MAXNTREC
*2)) {
309 "Block size must be a positive, even integer <= %d\n"),
314 ntrec
/= (tp_bsize
/DEV_BSIZE
);
316 msg(gettext("Missing blocking factor\n"));
322 case 'c': /* Tape is cart. not 9-track */
323 case 'C': /* 'C' to be consistent with 'D' */
327 case '0': /* dump level */
340 case 'u': /* update /etc/dumpdates */
344 case 'n': /* notify operators */
348 case 'a': /* create archive file */
353 if (**argv
== '\0') {
354 msg(gettext("Bad archive file name\n"));
358 archivefile
= strdup(*argv
);
359 if (archivefile
== NULL
) {
361 msg(gettext("Cannot allocate memory: %s\n"),
367 msg(gettext("Missing archive file name\n"));
376 if (strcmp(tape
, "-") == 0) {
378 "Cannot verify when dumping to standard out.\n"));
392 if (**argv
== '\0') {
393 msg(gettext("Missing name for dumpdates "
399 if (strlen(dname
) > MAXNAMLEN
+ 2) {
400 msg(gettext("Dumpdates entry name too "
405 for (i
= 0; i
< strlen(dname
); i
++) {
406 if (isspace(*(dname
+i
))) {
407 msg(gettext("Dumpdates entry name may "
408 "not contain white space.\n"));
414 msg(gettext("Missing name for dumpdates entry.\n"));
423 if (**argv
== '\0') {
424 msg(gettext("Missing tape label name\n"));
429 if (strlen(tlabel
) > (sizeof (spcl
.c_label
) - 1)) {
430 tlabel
[sizeof (spcl
.c_label
) - 1] = '\0';
432 "Truncating label to maximum supported length: `%s'\n"),
436 msg(gettext("Missing tape label name\n"));
461 msg(gettext("Bad option `%c'\n"), arg
[-1]);
468 if (**argv
== '\0') {
469 msg(gettext("Bad disk name\n"));
477 (void) fprintf(stderr
, gettext(
478 "Usage: %s [0123456789fustdWwnNDCcbavloS [argument]] filesystem\n"),
485 if (signal(SIGINT
, interrupt
) == SIG_IGN
)
486 (void) signal(SIGINT
, SIG_IGN
);
488 if (strcmp(tape
, "-") == 0) {
490 tape
= gettext("standard output");
491 dumpdev
= sdumpdev
= strdup(tape
);
492 if (dumpdev
== NULL
) {
494 msg(gettext("Cannot allocate memory: %s\n"),
499 /*CONSTANTCONDITION*/
500 assert(sizeof (spcl
.c_label
) > 5);
501 (void) strcpy(spcl
.c_label
, "none");
502 } else if (*tape
== '+') {
504 (void) strcpy(spcl
.c_label
, tlabel
);
506 /* if not already set, set diskette to default */
507 if (diskette
&& strcmp(tape
, DEFTAPE
) == 0)
510 (void) strcpy(spcl
.c_label
, tlabel
);
512 if (cartridge
&& diskette
) {
514 msg(gettext("Cannot select both cartridge and diskette\n"));
516 if (density
&& diskette
) {
518 msg(gettext("Cannot select density of diskette\n"));
520 if (tracks
&& diskette
) {
522 msg(gettext("Cannot select number of tracks of diskette\n"));
530 * Determine how to default tape size and density
533 * 9-track 1600 bpi (160 bytes/.1") 2300 ft.
534 * 9-track 6250 bpi (625 bytes/.1") 2300 ft.
536 * Most Sun-2's came with 4 track (20MB) cartridge tape drives,
537 * while most other machines (Sun-3's and non-Sun's) come with
538 * 9 track (45MB) cartridge tape drives. Some Sun-2's came with
539 * 9 track drives, but there is no way for the software to detect
540 * which drive type is installed. Sigh... We make the gross
541 * assumption that #ifdef mc68010 will test for a Sun-2.
543 * cartridge 8000 bpi (100 bytes/.1") 425 * tracks ft.
546 density
= cartridge
? 100 : 625;
551 ntrec
= CARTRIDGETREC
;
554 else if (density
>= 625)
555 ntrec
= HIGHDENSITYTREC
;
559 * save ntrec in case we have to change tp_bsize later.
561 saved_ntrec
= (ntrec
* (tp_bsize
/DEV_BSIZE
));
568 if (signal(SIGHUP
, sigAbort
) == SIG_IGN
)
569 (void) signal(SIGHUP
, SIG_IGN
);
570 if (signal(SIGTRAP
, sigAbort
) == SIG_IGN
)
571 (void) signal(SIGTRAP
, SIG_IGN
);
572 if (signal(SIGFPE
, sigAbort
) == SIG_IGN
)
573 (void) signal(SIGFPE
, SIG_IGN
);
574 if (signal(SIGBUS
, sigAbort
) == SIG_IGN
)
575 (void) signal(SIGBUS
, SIG_IGN
);
576 if (signal(SIGSEGV
, sigAbort
) == SIG_IGN
)
577 (void) signal(SIGSEGV
, SIG_IGN
);
578 if (signal(SIGTERM
, sigAbort
) == SIG_IGN
)
579 (void) signal(SIGTERM
, SIG_IGN
);
580 if (signal(SIGUSR1
, sigAbort
) == SIG_IGN
)
581 (void) signal(SIGUSR1
, SIG_IGN
);
582 if (signal(SIGPIPE
, sigAbort
) == SIG_IGN
)
583 (void) signal(SIGPIPE
, SIG_IGN
);
585 mnttabread(); /* /etc/fstab, /etc/mtab snarfed */
588 * disk can be either the full special file name,
589 * the suffix of the special file name,
590 * the special name missing the leading '/',
591 * the file system name with or without the leading '/'.
592 * NB: we attempt to avoid dumping the block device
593 * (using rawname) because specfs and the vm system
594 * are not necessarily in sync.
598 * Attempt to roll the log if its root user before doing the dump.
599 * There's nothing the user can do if we are unable to roll the log,
600 * so we'll silently ignore failures.
602 if (getuid() == 0 && rl_roll_log(disk
) != RL_SUCCESS
&&
604 /* Try it again with leading '/'. */
607 slashed
= (char *)malloc(strlen(disk
) + 2);
608 if (slashed
!= NULL
) {
609 (void) sprintf(slashed
, "%c%s", '/', disk
);
610 (void) rl_roll_log(slashed
);
614 dt
= mnttabsearch(disk
, 0);
616 filesystem
= dt
->mnt_mountp
;
618 /* LINTED: disk is not NULL */
621 disk
= rawname(dt
->mnt_special
);
622 disk_dynamic
= (disk
!= dt
->mnt_special
);
624 (void) strncpy(spcl
.c_dev
, dt
->mnt_special
,
625 sizeof (spcl
.c_dev
));
626 spcl
.c_dev
[sizeof (spcl
.c_dev
) - 1] = '\0';
627 (void) strncpy(spcl
.c_filesys
, dt
->mnt_mountp
,
628 sizeof (spcl
.c_filesys
));
629 spcl
.c_filesys
[sizeof (spcl
.c_filesys
) - 1] = '\0';
631 (void) strncpy(spcl
.c_dev
, disk
, sizeof (spcl
.c_dev
));
632 spcl
.c_dev
[sizeof (spcl
.c_dev
) - 1] = '\0';
634 /* check for partial filesystem dump */
636 dt
= mnttabsearch(disk
, 1);
638 filesystem
= dt
->mnt_mountp
;
641 disk
= rawname(dt
->mnt_special
);
642 disk_dynamic
= (disk
!= dt
->mnt_special
);
644 (void) strncpy(spcl
.c_filesys
,
645 "a partial file system", sizeof (spcl
.c_filesys
));
646 spcl
.c_filesys
[sizeof (spcl
.c_filesys
) - 1] = '\0';
651 char *old_disk
= disk
;
653 (void) strncpy(spcl
.c_filesys
,
654 "an unlisted file system",
655 sizeof (spcl
.c_filesys
));
656 spcl
.c_filesys
[sizeof (spcl
.c_filesys
) - 1] = '\0';
658 disk
= rawname(old_disk
);
659 if (disk
!= old_disk
) {
665 * If disk == old_disk, then disk_dynamic's state
671 fi
= open64(disk
, O_RDONLY
);
675 msg(gettext("Cannot open dump device `%s': %s\n"),
676 disk
, strerror(saverr
));
680 if (sscanf(&incno
, "%1d", &spcl
.c_level
) != 1) {
681 msg(gettext("Bad dump level `%c' specified\n"), incno
);
685 getitime(); /* /etc/dumpdates snarfed */
687 sblock
= (struct fs
*)&sblock_buf
;
690 bread((diskaddr_t
)SBLOCK
, (uchar_t
*)sblock
, (long)SBSIZE
);
691 if ((sblock
->fs_magic
!= FS_MAGIC
) &&
692 (sblock
->fs_magic
!= MTB_UFS_MAGIC
)) {
694 "Warning - super-block on device `%s' is corrupt - run fsck\n"),
700 if (sblock
->fs_magic
== FS_MAGIC
&&
701 (sblock
->fs_version
!= UFS_EFISTYLE4NONEFI_VERSION_2
&&
702 sblock
->fs_version
!= UFS_VERSION_MIN
)) {
703 msg(gettext("Unrecognized UFS version: %d\n"),
709 if (sblock
->fs_magic
== MTB_UFS_MAGIC
&&
710 (sblock
->fs_version
< MTB_UFS_VERSION_MIN
||
711 sblock
->fs_version
> MTB_UFS_VERSION_1
)) {
712 msg(gettext("Unrecognized UFS version: %d\n"),
719 * Try to set up for using mmap(2). It only works on the block
720 * device, but if we can use it, things go somewhat faster. If
721 * we can't open it, we'll silently fall back to the old method
722 * (read/memcpy). We also only try this if it's been cleanly
723 * unmounted. Dumping a live filesystem this way runs into
724 * buffer consistency problems. Of course, we don't support
725 * running dump on a mounted filesystem, but some people do it
728 if (sblock
->fs_clean
== FSCLEAN
) {
729 char *block
= unrawname(disk
);
732 mapfd
= open(block
, O_RDONLY
, 0);
738 bread((diskaddr_t
)SBLOCK
, (uchar_t
*)sblock
, (long)SBSIZE
);
739 if ((sblock
->fs_magic
!= FS_MAGIC
) &&
740 (sblock
->fs_magic
!= MTB_UFS_MAGIC
)) { /* paranoia */
741 msg(gettext("bad super-block magic number, run fsck\n"));
746 if (sblock
->fs_magic
== FS_MAGIC
&&
747 (sblock
->fs_version
!= UFS_EFISTYLE4NONEFI_VERSION_2
&&
748 sblock
->fs_version
!= UFS_VERSION_MIN
)) {
749 msg(gettext("Unrecognized UFS version: %d\n"),
755 if (sblock
->fs_magic
== MTB_UFS_MAGIC
&&
756 (sblock
->fs_version
< MTB_UFS_VERSION_MIN
||
757 sblock
->fs_version
> MTB_UFS_VERSION_1
)) {
758 msg(gettext("Unrecognized UFS version: %d\n"),
767 /* XXX should sanity-check the super block before trusting/using it */
769 /* LINTED XXX time truncated - tolerate until tape format changes */
770 spcl
.c_date
= (time32_t
)time(NULL
);
771 bcopy(&(spcl
.c_shadow
), c_shadow_save
, sizeof (c_shadow_save
));
773 snapdate
= is_fssnap_dump(disk
);
775 spcl
.c_date
= snapdate
;
778 msg(gettext("Date of this level %c dump: %s\n"),
779 incno
, prdate(spcl
.c_date
));
780 msg(gettext("Date of last level %c dump: %s\n"),
781 (uchar_t
)lastincno
, prdate(spcl
.c_ddate
));
782 msg(gettext("Dumping %s "), disk
);
784 msgtail("(%.*s:%s) ",
785 /* LINTED unsigned -> signed cast ok */
786 (int)sizeof (spcl
.c_host
), spcl
.c_host
, filesystem
);
787 msgtail(gettext("to %s.\n"), sdumpdev
);
790 esize
= f_esize
= o_esize
= 0;
791 msiz
= roundup(d_howmany(sblock
->fs_ipg
* sblock
->fs_ncg
, NBBY
),
794 clrmap
= (uchar_t
*)xcalloc(msiz
, sizeof (*clrmap
));
795 filmap
= (uchar_t
*)xcalloc(msiz
, sizeof (*filmap
));
796 dirmap
= (uchar_t
*)xcalloc(msiz
, sizeof (*dirmap
));
797 nodmap
= (uchar_t
*)xcalloc(msiz
, sizeof (*nodmap
));
798 shamap
= (uchar_t
*)xcalloc(msiz
, sizeof (*shamap
));
799 activemap
= (uchar_t
*)xcalloc(msiz
, sizeof (*activemap
));
801 if (clrmap
== NULL
|| filmap
== NULL
|| dirmap
== NULL
||
802 nodmap
== NULL
|| shamap
== NULL
|| activemap
== NULL
) {
804 "Internal error: NULL map pointer while re-dumping active files"));
813 /* retain active map */
820 * Read cylinder group inode-used bitmaps to avoid reading clear inodes.
823 uchar_t
*clrp
= clrmap
;
825 (struct cg
*)xcalloc((uint_t
)sblock
->fs_cgsize
, 1);
827 for (i
= 0; i
< sblock
->fs_ncg
; i
++) {
828 bread(fsbtodb(sblock
, cgtod(sblock
, i
)),
829 (uchar_t
*)cgp
, sblock
->fs_cgsize
);
830 bcopy(cg_inosused(cgp
), clrp
,
831 (int)sblock
->fs_ipg
/ NBBY
);
832 clrp
+= sblock
->fs_ipg
/ NBBY
;
835 /* XXX right-shift clrmap one bit. why? */
836 for (i
= 0; clrp
> clrmap
; i
<<= NBBY
) {
837 i
|= *--clrp
& ((1<<NBBY
) - 1);
843 msgp
= gettext("Mapping (Pass I) [regular files]\n");
849 if (partial_mark(argc
, argv
)) {
852 pass(mark
, clrmap
); /* mark updates 'x'_esize */
854 pass(active_mark
, clrmap
); /* updates 'x'_esize */
860 msgp
= gettext("Mapping (Pass II) [directories]\n");
868 ino
= 0; /* adjust estimated size for shadow inodes */
869 pass(markshad
, nodmap
);
871 pass(estshad
, shamap
);
876 esize
= o_esize
+ f_esize
;
878 /* estimate number of floppies */
880 fetapes
= (double)(esize
+ ntrec
) / (double)tsize
;
881 } else if (cartridge
) {
883 * Estimate number of tapes, assuming streaming stops at
884 * the end of each block written, and not in mid-block.
885 * Assume no erroneous blocks; this can be compensated for
886 * with an artificially low tape size.
888 tenthsperirg
= 16; /* actually 15.48, says Archive */
890 fetapes
= ((double)esize
/* blocks */
891 * (tp_bsize
/* bytes/block */
892 * (1.0/density
)) /* 0.1" / byte */
894 (double)esize
/* blocks */
895 * (1.0/ntrec
) /* streaming-stops per block */
896 * tenthsperirg
) /* 0.1" / streaming-stop */
897 * (1.0 / tsize
); /* tape / 0.1" */
899 /* Estimate number of tapes, for old fashioned 9-track tape */
901 /* sun has long irg's */
902 tenthsperirg
= (density
== 625) ? 6 : 12;
904 tenthsperirg
= (density
== 625) ? 5 : 8;
907 fetapes
= ((double)esize
/* blocks */
908 * (tp_bsize
/* bytes / block */
909 * (1.0/density
)) /* 0.1" / byte */
911 (double)esize
/* blocks */
912 * (1.0/ntrec
) /* IRG's / block */
913 * tenthsperirg
) /* 0.1" / IRG */
914 * (1.0 / tsize
); /* tape / 0.1" */
917 etapes
= fetapes
; /* truncating assignment */
919 /* count the nodemap on each additional tape */
920 for (i
= 1; i
< etapes
; i
++)
923 * If the above bmapest is called, it changes o_esize and f_esize.
924 * So we will recalculate esize here anyway to make sure.
925 * Also, add tape headers and trailer records.
927 esize
= o_esize
+ f_esize
+ etapes
+ ntrec
;
930 * If the estimated number of tp_bsize tape blocks is greater than
931 * INT_MAX we have to adjust tp_bsize and ntrec to handle
932 * the larger dump. esize is an estimate, so we 'fudge'
933 * INT_MAX a little. If tp_bsize is adjusted, it will be adjusted
934 * to the size needed for this dump (2048, 4096, 8192, ...)
936 if (esize
> (INT_MAX
- FUDGE_FACTOR
)) { /* esize is too big */
939 ((esize
+ (INT_MAX
- FUDGE_FACTOR
) - 1)/
940 ((uoff_t
)(INT_MAX
- FUDGE_FACTOR
))) - 1;
941 if ((esize_shift
> ESIZE_SHIFT_MAX
) || (ntrec
== 0)) {
943 "Block factor %d ('b' flag) is too small for this size dump.");
944 msg(msgp
, saved_ntrec
);
949 * recalculate esize from:
950 * o_esize - header tape records
951 * (f_esize + (num_mult -1)) >> esize_shift - new non-header
952 * tape records for files/maps
953 * etapes - TS_TAPE records
954 * ntrec - TS_END records
956 * ntrec is adjusted so a tape record is still 'b' flag
957 * number of DEV_BSIZE (512) in size
959 new_mult
= (tp_bsize
<< esize_shift
)/tp_bsize
;
960 tp_bsize
= (tp_bsize
<< esize_shift
);
961 esize
= o_esize
+ ((f_esize
+
962 (new_mult
- 1)) >> esize_shift
) + etapes
+ ntrec
;
963 ntrec
= (saved_ntrec
/(tp_bsize
/DEV_BSIZE
));
965 if (forceflag
!= 0) {
967 "Forcing larger tape block size (%d).\n");
970 alloctape(); /* allocate tape buffers */
972 assert((tp_bsize
/ DEV_BSIZE
!= 0) && (tp_bsize
% DEV_BSIZE
== 0));
974 * If all we wanted was the size estimate,
975 * just print it out and exit.
978 (void) printf("%llu\n", esize
* tp_bsize
);
985 "Estimated %lld blocks (%s) on %3.2f diskettes.\n");
988 "Estimated %lld blocks (%s) on %3.2f tapes.\n");
991 (esize
*(tp_bsize
/DEV_BSIZE
)), mb(esize
), fetapes
);
993 msgp
= gettext("Estimated %lld blocks (%s).\n");
994 msg(msgp
, (esize
*(tp_bsize
/DEV_BSIZE
)), mb(esize
));
999 otape(1); /* bitmap is the first to tape write */
1001 (void) time(tstart_writing
);
1003 /* filmap indicates all non-directory inodes */
1005 uchar_t
*np
, *fp
, *dp
;
1009 for (i
= 0; i
< msiz
; i
++)
1010 *fp
++ = *np
++ ^ *dp
++;
1013 while (dumpstate
!= DS_DONE
) {
1015 * When we receive EOT notification from
1016 * the writer, the signal handler calls
1017 * rollforward and then jumps here.
1019 (void) setjmp(checkpoint_buf
);
1020 switch (dumpstate
) {
1023 * We get here if a tape error occurred
1024 * after releasing the name lock but before
1025 * the volume containing the last of the
1026 * dir info was completed. We have to start
1027 * all over in this case.
1030 char *rmsg
= gettext(
1031 "Warning - output error occurred after releasing name lock\n\
1032 \tThe dump will restart\n");
1041 bitmap(clrmap
, TS_CLRI
);
1047 if (BIT(UFSROOTINO
, nodmap
)) /* empty dump check */
1048 bitmap(nodmap
, TS_BITS
);
1052 "Dumping (Pass III) [directories]\n");
1058 pass(dirdump
, dirmap
);
1059 nextstate(DS_FILES
);
1062 "Dumping (Pass IV) [regular files]\n");
1069 pass(lf_dump
, filmap
);
1072 dumpstate
= DS_END
; /* don't reset ino */
1076 spcl
.c_type
= TS_END
;
1077 for (i
= 0; i
< ntrec
; i
++) {
1085 msg(gettext("Internal state error\n"));
1091 if ((! doingactive
) && (! active
))
1093 if (verify
&& !doingverify
) {
1094 msgp
= gettext("Finished writing last dump volume\n");
1098 if (spcl
.c_volume
> 1)
1099 (void) snprintf(msgbuf
, sizeof (msgbuf
),
1100 gettext("%lld blocks (%s) on %ld volumes"),
1101 ((uint64_t)spcl
.c_tapea
*(tp_bsize
/DEV_BSIZE
)),
1102 mb((uoff_t
)(unsigned)(spcl
.c_tapea
)),
1105 (void) snprintf(msgbuf
, sizeof (msgbuf
),
1106 gettext("%lld blocks (%s) on 1 volume"),
1107 ((uint64_t)spcl
.c_tapea
*(tp_bsize
/DEV_BSIZE
)),
1108 mb((uoff_t
)(unsigned)(spcl
.c_tapea
)));
1109 if (timeclock((time_t)0) != (time_t)0) {
1110 (void) snprintf(kbsbuf
, sizeof (kbsbuf
),
1111 gettext(" at %ld KB/sec"),
1112 (long)(((float)spcl
.c_tapea
/ (float)timeclock((time_t)0))
1114 (void) strcat(msgbuf
, kbsbuf
);
1116 (void) strcat(msgbuf
, "\n");
1118 (void) timeclock((time_t)-1);
1121 msg(gettext("Archiving dump to `%s'\n"), archivefile
);
1122 if (active
&& !verify
) {
1127 msgp
= gettext("DUMP IS DONE\n");
1148 sigtype
= "SIGTRAP";
1154 msg(gettext("%s ABORTING!\n"), "SIGBUS()");
1155 (void) signal(SIGUSR2
, SIG_DFL
);
1159 msg(gettext("%s ABORTING!\n"), "SIGSEGV()");
1160 (void) signal(SIGUSR2
, SIG_DFL
);
1164 sigtype
= "SIGALRM";
1167 sigtype
= "SIGTERM";
1170 msg(gettext("Broken pipe\n"));
1177 msg(gettext("%s() try rewriting\n"), sigtype
);
1179 msg(gettext("Unknown signal, Cannot recover\n"));
1183 msg(gettext("Rewriting attempted as response to unknown signal.\n"));
1184 (void) fflush(stderr
);
1185 (void) fflush(stdout
);
1190 /* Note that returned value is malloc'd if != cp && != NULL */
1196 extern char *getfullrawname();
1198 if (stat64(cp
, &st
) < 0 || (st
.st_mode
& S_IFMT
) != S_IFBLK
)
1201 dp
= getfullrawname(cp
);
1209 if (stat64(dp
, &st
) < 0 || (st
.st_mode
& S_IFMT
) != S_IFCHR
) {
1220 static char buf
[16];
1223 (void) snprintf(buf
, sizeof (buf
), "%lldKB", blks
);
1225 (void) snprintf(buf
, sizeof (buf
), "%.2fMB",
1226 ((double)(blks
*tp_bsize
)) / (double)(1024*1024));
1231 void (*nsignal(int sig
, void (*act
)(int)))(int)
1233 struct sigaction sa
, osa
;
1235 sa
.sa_handler
= act
;
1236 (void) sigemptyset(&sa
.sa_mask
);
1237 sa
.sa_flags
= SA_RESTART
;
1238 if (sigaction(sig
, &sa
, &osa
) < 0)
1239 return ((void (*)(int))-1);
1240 return (osa
.sa_handler
);
1245 nextstate(int state
)
1247 /* LINTED assigned value never used - kept for documentary purposes */
1249 /* LINTED assigned value never used - kept for documentary purposes */
1251 /* LINTED assigned value never used - kept for documentary purposes */
1257 * timeclock() function, for keeping track of how much time we've spent
1258 * writing to the tape device. it always returns the amount of time
1259 * already spent, in milliseconds. if you pass it a positive, then that's
1260 * telling it that we're writing, so the time counts. if you pass it a
1261 * zero, then that's telling it we're not writing; perhaps we're waiting
1264 * a state of -1 resets everything.
1267 timeclock(time32_t state
)
1269 static int *currentState
= NULL
;
1270 static struct timeval
*clockstart
;
1271 static time32_t
*emilli
;
1273 struct timeval current
[1];
1277 fprintf(stderr
, "pid=%d timeclock ", getpid());
1278 if (state
== (time32_t
)-1)
1279 fprintf(stderr
, "cleared\n");
1281 fprintf(stderr
, "ticking\n");
1283 fprintf(stderr
, "paused\n");
1286 /* if we haven't setup the shared memory, init */
1287 if (currentState
== NULL
) {
1288 if ((fd
= open("/dev/zero", O_RDWR
)) < 0) {
1290 msg(gettext("Cannot open `%s': %s\n"),
1291 "/dev/zero", strerror(saverr
));
1295 /*LINTED [mmap always returns an aligned value]*/
1296 currentState
= mmap(NULL
, getpagesize(),
1297 PROT_READ
|PROT_WRITE
, MAP_SHARED
, fd
, (off_t
)0);
1298 if (currentState
== (int *)-1) {
1301 "Cannot memory map monitor variables: %s\n"),
1308 /* LINTED currentState is sufficiently aligned */
1309 clockstart
= (struct timeval
*)(currentState
+ 1);
1310 emilli
= (time32_t
*)(clockstart
+ 1);
1311 /* Note everything is initialized to zero via /dev/zero */
1314 if (state
== (time32_t
)-1) {
1315 bzero(clockstart
, sizeof (*clockstart
));
1317 *emilli
= (time32_t
)0;
1321 (void) gettimeofday(current
, NULL
);
1323 if (*currentState
!= 0) {
1324 current
->tv_usec
+= 1000000;
1327 /* LINTED: result will fit in a time32_t */
1328 *emilli
+= (current
->tv_sec
- clockstart
->tv_sec
) * 1000;
1329 /* LINTED: result will fit in a time32_t */
1330 *emilli
+= (current
->tv_usec
- clockstart
->tv_usec
) / 1000;
1334 bcopy(current
, clockstart
, sizeof (current
));
1336 *currentState
= state
;
1342 statcmp(const struct stat64
*left
, const struct stat64
*right
)
1346 if ((left
->st_dev
== right
->st_dev
) &&
1347 (left
->st_ino
== right
->st_ino
) &&
1348 (left
->st_mode
== right
->st_mode
) &&
1349 (left
->st_nlink
== right
->st_nlink
) &&
1350 (left
->st_uid
== right
->st_uid
) &&
1351 (left
->st_gid
== right
->st_gid
) &&
1352 (left
->st_rdev
== right
->st_rdev
) &&
1353 (left
->st_ctim
.tv_sec
== right
->st_ctim
.tv_sec
) &&
1354 (left
->st_ctim
.tv_nsec
== right
->st_ctim
.tv_nsec
) &&
1355 (left
->st_mtim
.tv_sec
== right
->st_mtim
.tv_sec
) &&
1356 (left
->st_mtim
.tv_nsec
== right
->st_mtim
.tv_nsec
)) {
1358 * Unlike in the ufsrestore version
1359 * st_blocks and st_blksiz are not
1360 * compared. The reason for this is
1361 * problems with zfs dump files. Zfs
1362 * changes it's statistics in those
1372 * Safely open a file or device.
1375 safe_open_common(const char *filename
, int mode
, int perms
, int device
)
1381 struct stat64 pre_stat
, pre_lstat
;
1382 struct stat64 post_stat
, post_lstat
;
1385 * Don't want to be spoofed into trashing something we
1386 * shouldn't, thus the following rigamarole. If it doesn't
1387 * exist, we create it and proceed. Otherwise, require that
1388 * what's there be a real file with no extraneous links and
1389 * owned by whoever ran us.
1391 * The silliness with using both lstat() and fstat() is to avoid
1392 * race-condition games with someone replacing the file with a
1393 * symlink after we've opened it. If there was an flstat(),
1394 * we wouldn't need the fstat().
1396 * The initial open with the hard-coded flags is ok even if we
1397 * are intending to open only for reading. If it succeeds,
1398 * then the file did not exist, and we'll synthesize an appropriate
1399 * complaint below. Otherwise, it does exist, so we won't be
1400 * truncating it with the open.
1402 if ((fd
= open(filename
, O_WRONLY
|O_CREAT
|O_TRUNC
|O_EXCL
|O_LARGEFILE
,
1404 if (errno
== EEXIST
) {
1405 if (lstat64(filename
, &pre_lstat
) < 0) {
1409 if (stat64(filename
, &pre_stat
) < 0) {
1413 working_mode
= mode
& (O_WRONLY
|O_RDWR
|O_RDONLY
);
1414 working_mode
|= O_LARGEFILE
;
1415 if ((fd
= open(filename
, working_mode
)) < 0) {
1416 if (errno
== ENOENT
) {
1418 "Unexpected condition detected: %s used to exist, but doesn't any longer\n");
1419 msg(errtext
, filename
);
1420 syslog(LOG_WARNING
, errtext
, filename
);
1426 if (lstat64(filename
, &post_lstat
) < 0) {
1433 if (fstat64(fd
, &post_stat
) < 0) {
1441 * Can't just use memcmp(3C), because the access
1442 * time is updated by open(2).
1444 if (statcmp(&pre_lstat
, &post_lstat
) != 0) {
1445 errtext
= gettext("Unexpected change detected: "
1446 "%s's lstat(2) information changed\n");
1447 msg(errtext
, filename
);
1448 syslog(LOG_WARNING
, errtext
, filename
);
1453 if (statcmp(&pre_stat
, &post_stat
) != 0) {
1454 errtext
= gettext("Unexpected change detected: "
1455 "%s's stat(2) information changed\n"),
1456 msg(errtext
, filename
);
1457 syslog(LOG_WARNING
, errtext
, filename
);
1463 * If inode, device, or type are wrong, bail out.
1464 * Note using post_stat instead of post_lstat for the
1465 * S_ISCHR() test. This is to allow the /dev ->
1466 * /devices bit to work, as long as the final target
1467 * is a character device (i.e., raw disk or tape).
1469 if (device
&& !(S_ISCHR(post_stat
.st_mode
)) &&
1470 !(S_ISFIFO(post_stat
.st_mode
)) &&
1471 !(S_ISREG(post_lstat
.st_mode
))) {
1472 errtext
= gettext("Unexpected condition "
1473 "detected: %s is not a supported device\n"),
1474 msg(errtext
, filename
);
1475 syslog(LOG_WARNING
, errtext
, filename
);
1479 } else if (!device
&&
1480 (!S_ISREG(post_lstat
.st_mode
) ||
1481 (post_stat
.st_ino
!= post_lstat
.st_ino
) ||
1482 (post_stat
.st_dev
!= post_lstat
.st_dev
))) {
1483 errtext
= gettext("Unexpected condition "
1484 "detected: %s is not a regular file\n"),
1485 msg(errtext
, filename
);
1486 syslog(LOG_WARNING
, errtext
, filename
);
1493 * Bad link count implies someone's linked our
1494 * target to something else, which we probably
1495 * shouldn't step on.
1497 if (post_lstat
.st_nlink
!= 1) {
1498 errtext
= gettext("Unexpected condition "
1499 "detected: %s must have exactly one "
1500 "link\n"), msg(errtext
, filename
);
1501 syslog(LOG_WARNING
, errtext
, filename
);
1507 * Root might make a file, but non-root might
1508 * need to open it. If the permissions let us
1509 * get this far, then let it through.
1511 if (post_lstat
.st_uid
!= getuid() &&
1512 post_lstat
.st_uid
!= 0) {
1513 errtext
= gettext("Unsupported "
1514 "condition detected: %s "
1515 "must be owned by uid %ld or 0\n"),
1516 msg(errtext
, filename
, (long)getuid());
1517 syslog(LOG_WARNING
, errtext
, filename
,
1523 if (mode
& O_TRUNC
) {
1524 if (ftruncate(fd
, (off_t
)0) < 0) {
1525 msg("ftruncate(%s): %s\n",
1526 filename
, strerror(errno
));
1533 * Didn't exist, but couldn't open it.
1539 * If truncating open succeeded for a read-only open,
1540 * bail out, as we really shouldn't have succeeded.
1542 if (mode
& O_RDONLY
) {
1543 /* Undo the O_CREAT */
1544 (void) unlink(filename
);
1545 msg("open(%s): %s\n",
1546 filename
, strerror(ENOENT
));
1557 * Safely open a file.
1560 safe_file_open(const char *filename
, int mode
, int perms
)
1562 return (safe_open_common(filename
, mode
, perms
, 0));
1566 * Safely open a device.
1569 safe_device_open(const char *filename
, int mode
, int perms
)
1571 return (safe_open_common(filename
, mode
, perms
, 1));
1575 * STDIO version of safe_open
1578 safe_fopen(const char *filename
, const char *smode
, int perms
)
1584 * accepts only modes "r", "r+", and "w"
1586 if (smode
[0] == 'r') {
1587 if (smode
[1] == '\0') {
1589 } else if ((smode
[1] == '+') && (smode
[2] == '\0')) {
1592 } else if ((smode
[0] == 'w') && (smode
[1] == '\0')) {
1595 msg(gettext("internal error: safe_fopen: invalid mode `%s'\n"),
1600 fd
= safe_file_open(filename
, bmode
, perms
);
1603 * caller is expected to report error.
1606 return (fdopen(fd
, smode
));
1614 char name
[MAXPATHLEN
];
1616 if (debug_chdir
!= NULL
) {
1617 snprintf(name
, sizeof (name
), "%s/%ld",
1618 debug_chdir
, (long)getpid());
1619 if (mkdir(name
, 0755) < 0)
1620 msg("mkdir(%s): %s", name
, strerror(errno
));
1621 if (chdir(name
) < 0)
1622 msg("chdir(%s): %s", name
, strerror(errno
));