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.
40 #include <priv_utils.h>
44 int notify
= 0; /* notify operator flag */
45 int blockswritten
= 0; /* number of blocks written on current tape */
46 uint_t tapeno
= 0; /* current tape number */
47 daddr32_t filenum
= 0; /* current file number on tape */
48 int density
= 0; /* density in bytes/0.1" */
49 int tenthsperirg
; /* inter-record-gap in 0.1"'s */
50 uint_t ntrec
= 0; /* # tape blocks in each tape record */
51 uint_t saved_ntrec
= 0; /* saved value of ntrec */
52 uint_t forceflag
= 0; /* forced to change tp_bsize */
53 int cartridge
= 0; /* assume non-cartridge tape */
54 uint_t tracks
; /* # tracks on a cartridge tape */
55 int diskette
= 0; /* assume not dumping to a diskette */
56 int printsize
= 0; /* just print estimated size and exit */
57 int mapfd
= -1; /* if >= 0, file descriptor for mmap */
58 int32_t tp_bsize
= TP_BSIZE_MIN
; /* tape block record size (frag size) */
60 int xflag
; /* debugging switch */
66 * This should be struct fs, but there are trailing bits on disk
67 * that we also need to read in as part of it. It's an array of
68 * longs instead of char to force proper alignment.
70 static long sblock_buf
[SBSIZE
/sizeof (long)];
73 static char *mb(u_offset_t
);
74 static void nextstate(int);
77 static void nextstate();
80 extern jmp_buf checkpoint_buf
; /* context for return from checkpoint */
81 #define FUDGE_FACTOR 0x2000000
84 main(int argc
, char *argv
[])
87 int bflag
= 0, i
, error
= 0, saverr
;
90 char msgbuf
[3000], *msgp
;
92 u_offset_t esize_shift
= 0;
98 if (myname
= strrchr(argv
[0], '/'))
103 if (strcmp("hsmdump", myname
) == 0) {
104 msg(gettext("hsmdump emulation is no longer supported.\n"));
109 autoload_period
= 12;
110 autoload_tries
= 12; /* traditional default of ~2.5 minutes */
112 (void) setlocale(LC_ALL
, "");
113 #if !defined(TEXT_DOMAIN)
114 #define TEXT_DOMAIN "SYS_TEST"
115 #endif /* TEXT_DOMAIN */
116 (void) textdomain(TEXT_DOMAIN
);
119 * If someone strips the set-uid bit, dump will still work for local
120 * tapes. Fail when we try to access a remote tape.
122 (void) __init_suid_priv(0, PRIV_NET_PRIVADDR
, (char *)NULL
);
124 if (sysinfo(SI_HOSTNAME
, spcl
.c_host
, sizeof (spcl
.c_host
)) < 0) {
126 msg(gettext("Could not get host name: %s\n"),
128 bzero(spcl
.c_host
, sizeof (spcl
.c_host
));
132 tsize
= 0; /* no default size, detect EOT dynamically */
151 switch (*arg
++) { /* BE CAUTIOUS OF FALLTHROUGHS */
154 * This undocumented option causes each process to
155 * mkdir debug_chdir/getpid(), and chdir to it. This is
156 * to ease the collection of profiling information and
164 "Each process shall try to chdir to %s/<pid>\n"),
168 msg(gettext("Missing move-to-dir (M) name\n"));
175 lastdump('w'); /* tell us only what has to be done */
179 case 'W': /* what to do */
180 lastdump('W'); /* tell state of what has been done */
181 exit(0); /* do nothing else */
195 "Unreasonable autoload timeout period\n"));
199 units
= *(*argv
+ strlen(*argv
) - 1);
207 case '0': case '1': case '2': case '3': case '4':
208 case '5': case '6': case '7': case '8': case '9':
214 "Unknown timeout units indicator `%c'\n"),
220 ((count
* multiplier
) / autoload_period
);
222 msg(gettext("Missing autoload timeout period\n"));
228 case 'f': /* output file */
234 msg(gettext("Bad output device name\n"));
239 msg(gettext("Missing output device name\n"));
243 if (strcmp(tape
, "-") == 0 && verify
) {
245 "Cannot verify when dumping to standard out.\n"));
251 case 'd': /* density, in bits per inch */
255 density
= atoi(*argv
) / 10;
258 "Density must be a positive integer\n"));
263 msg(gettext("Missing density\n"));
269 case 's': /* tape size, feet */
274 if ((*argv
[0] == '-') || (tsize
== 0)) {
276 "Tape size must be a positive integer\n"));
281 msg(gettext("Missing tape size\n"));
287 case 't': /* tracks */
291 tracks
= atoi(*argv
);
293 msg(gettext("Missing track count\n"));
299 case 'b': /* blocks per tape write */
305 * We save the ntrec in case we need to change
306 * tp_bsize later, we will have to recalculate
309 saved_ntrec
= ntrec
= atoi(*argv
);
310 if (ntrec
== 0 || (ntrec
&1) || ntrec
> (MAXNTREC
*2)) {
312 "Block size must be a positive, even integer <= %d\n"),
317 ntrec
/= (tp_bsize
/DEV_BSIZE
);
319 msg(gettext("Missing blocking factor\n"));
325 case 'c': /* Tape is cart. not 9-track */
326 case 'C': /* 'C' to be consistent with 'D' */
330 case '0': /* dump level */
343 case 'u': /* update /etc/dumpdates */
347 case 'n': /* notify operators */
351 case 'a': /* create archive file */
356 if (**argv
== '\0') {
357 msg(gettext("Bad archive file name\n"));
361 archivefile
= strdup(*argv
);
362 if (archivefile
== NULL
) {
364 msg(gettext("Cannot allocate memory: %s\n"),
370 msg(gettext("Missing archive file name\n"));
379 if (strcmp(tape
, "-") == 0) {
381 "Cannot verify when dumping to standard out.\n"));
395 if (**argv
== '\0') {
396 msg(gettext("Missing name for dumpdates "
402 if (strlen(dname
) > MAXNAMLEN
+ 2) {
403 msg(gettext("Dumpdates entry name too "
408 for (i
= 0; i
< strlen(dname
); i
++) {
409 if (isspace(*(dname
+i
))) {
410 msg(gettext("Dumpdates entry name may "
411 "not contain white space.\n"));
417 msg(gettext("Missing name for dumpdates entry.\n"));
426 if (**argv
== '\0') {
427 msg(gettext("Missing tape label name\n"));
432 if (strlen(tlabel
) > (sizeof (spcl
.c_label
) - 1)) {
433 tlabel
[sizeof (spcl
.c_label
) - 1] = '\0';
435 "Truncating label to maximum supported length: `%s'\n"),
439 msg(gettext("Missing tape label name\n"));
464 msg(gettext("Bad option `%c'\n"), arg
[-1]);
471 if (**argv
== '\0') {
472 msg(gettext("Bad disk name\n"));
480 (void) fprintf(stderr
, gettext(
481 "Usage: %s [0123456789fustdWwnNDCcbavloS [argument]] filesystem\n"),
488 if (signal(SIGINT
, interrupt
) == SIG_IGN
)
489 (void) signal(SIGINT
, SIG_IGN
);
491 if (strcmp(tape
, "-") == 0) {
493 tape
= gettext("standard output");
494 dumpdev
= sdumpdev
= strdup(tape
);
495 if (dumpdev
== NULL
) {
497 msg(gettext("Cannot allocate memory: %s\n"),
502 /*CONSTANTCONDITION*/
503 assert(sizeof (spcl
.c_label
) > 5);
504 (void) strcpy(spcl
.c_label
, "none");
505 } else if (*tape
== '+') {
507 (void) strcpy(spcl
.c_label
, tlabel
);
509 /* if not already set, set diskette to default */
510 if (diskette
&& strcmp(tape
, DEFTAPE
) == 0)
513 (void) strcpy(spcl
.c_label
, tlabel
);
515 if (cartridge
&& diskette
) {
517 msg(gettext("Cannot select both cartridge and diskette\n"));
519 if (density
&& diskette
) {
521 msg(gettext("Cannot select density of diskette\n"));
523 if (tracks
&& diskette
) {
525 msg(gettext("Cannot select number of tracks of diskette\n"));
533 * Determine how to default tape size and density
536 * 9-track 1600 bpi (160 bytes/.1") 2300 ft.
537 * 9-track 6250 bpi (625 bytes/.1") 2300 ft.
539 * Most Sun-2's came with 4 track (20MB) cartridge tape drives,
540 * while most other machines (Sun-3's and non-Sun's) come with
541 * 9 track (45MB) cartridge tape drives. Some Sun-2's came with
542 * 9 track drives, but there is no way for the software to detect
543 * which drive type is installed. Sigh... We make the gross
544 * assumption that #ifdef mc68010 will test for a Sun-2.
546 * cartridge 8000 bpi (100 bytes/.1") 425 * tracks ft.
549 density
= cartridge
? 100 : 625;
554 ntrec
= CARTRIDGETREC
;
557 else if (density
>= 625)
558 ntrec
= HIGHDENSITYTREC
;
562 * save ntrec in case we have to change tp_bsize later.
564 saved_ntrec
= (ntrec
* (tp_bsize
/DEV_BSIZE
));
573 char *cp
= strchr(host
, '@');
579 if (rmthost(host
, ntrec
) == 0) {
580 msg(gettext("Cannot connect to tape host `%s'\n"), cp
);
585 if (signal(SIGHUP
, sigAbort
) == SIG_IGN
)
586 (void) signal(SIGHUP
, SIG_IGN
);
587 if (signal(SIGTRAP
, sigAbort
) == SIG_IGN
)
588 (void) signal(SIGTRAP
, SIG_IGN
);
589 if (signal(SIGFPE
, sigAbort
) == SIG_IGN
)
590 (void) signal(SIGFPE
, SIG_IGN
);
591 if (signal(SIGBUS
, sigAbort
) == SIG_IGN
)
592 (void) signal(SIGBUS
, SIG_IGN
);
593 if (signal(SIGSEGV
, sigAbort
) == SIG_IGN
)
594 (void) signal(SIGSEGV
, SIG_IGN
);
595 if (signal(SIGTERM
, sigAbort
) == SIG_IGN
)
596 (void) signal(SIGTERM
, SIG_IGN
);
597 if (signal(SIGUSR1
, sigAbort
) == SIG_IGN
)
598 (void) signal(SIGUSR1
, SIG_IGN
);
599 if (signal(SIGPIPE
, sigAbort
) == SIG_IGN
)
600 (void) signal(SIGPIPE
, SIG_IGN
);
602 mnttabread(); /* /etc/fstab, /etc/mtab snarfed */
605 * disk can be either the full special file name,
606 * the suffix of the special file name,
607 * the special name missing the leading '/',
608 * the file system name with or without the leading '/'.
609 * NB: we attempt to avoid dumping the block device
610 * (using rawname) because specfs and the vm system
611 * are not necessarily in sync.
615 * Attempt to roll the log if its root user before doing the dump.
616 * There's nothing the user can do if we are unable to roll the log,
617 * so we'll silently ignore failures.
619 if (getuid() == 0 && rl_roll_log(disk
) != RL_SUCCESS
&&
621 /* Try it again with leading '/'. */
624 slashed
= (char *)malloc(strlen(disk
) + 2);
625 if (slashed
!= (char *)NULL
) {
626 (void) sprintf(slashed
, "%c%s", '/', disk
);
627 (void) rl_roll_log(slashed
);
631 dt
= mnttabsearch(disk
, 0);
633 filesystem
= dt
->mnt_mountp
;
635 /* LINTED: disk is not NULL */
638 disk
= rawname(dt
->mnt_special
);
639 disk_dynamic
= (disk
!= dt
->mnt_special
);
641 (void) strncpy(spcl
.c_dev
, dt
->mnt_special
,
642 sizeof (spcl
.c_dev
));
643 spcl
.c_dev
[sizeof (spcl
.c_dev
) - 1] = '\0';
644 (void) strncpy(spcl
.c_filesys
, dt
->mnt_mountp
,
645 sizeof (spcl
.c_filesys
));
646 spcl
.c_filesys
[sizeof (spcl
.c_filesys
) - 1] = '\0';
648 (void) strncpy(spcl
.c_dev
, disk
, sizeof (spcl
.c_dev
));
649 spcl
.c_dev
[sizeof (spcl
.c_dev
) - 1] = '\0';
651 /* check for partial filesystem dump */
653 dt
= mnttabsearch(disk
, 1);
655 filesystem
= dt
->mnt_mountp
;
658 disk
= rawname(dt
->mnt_special
);
659 disk_dynamic
= (disk
!= dt
->mnt_special
);
661 (void) strncpy(spcl
.c_filesys
,
662 "a partial file system", sizeof (spcl
.c_filesys
));
663 spcl
.c_filesys
[sizeof (spcl
.c_filesys
) - 1] = '\0';
668 char *old_disk
= disk
;
670 (void) strncpy(spcl
.c_filesys
,
671 "an unlisted file system",
672 sizeof (spcl
.c_filesys
));
673 spcl
.c_filesys
[sizeof (spcl
.c_filesys
) - 1] = '\0';
675 disk
= rawname(old_disk
);
676 if (disk
!= old_disk
) {
682 * If disk == old_disk, then disk_dynamic's state
688 fi
= open64(disk
, O_RDONLY
);
692 msg(gettext("Cannot open dump device `%s': %s\n"),
693 disk
, strerror(saverr
));
697 if (sscanf(&incno
, "%1d", &spcl
.c_level
) != 1) {
698 msg(gettext("Bad dump level `%c' specified\n"), incno
);
702 getitime(); /* /etc/dumpdates snarfed */
704 sblock
= (struct fs
*)&sblock_buf
;
707 bread((diskaddr_t
)SBLOCK
, (uchar_t
*)sblock
, (long)SBSIZE
);
708 if ((sblock
->fs_magic
!= FS_MAGIC
) &&
709 (sblock
->fs_magic
!= MTB_UFS_MAGIC
)) {
711 "Warning - super-block on device `%s' is corrupt - run fsck\n"),
717 if (sblock
->fs_magic
== FS_MAGIC
&&
718 (sblock
->fs_version
!= UFS_EFISTYLE4NONEFI_VERSION_2
&&
719 sblock
->fs_version
!= UFS_VERSION_MIN
)) {
720 msg(gettext("Unrecognized UFS version: %d\n"),
726 if (sblock
->fs_magic
== MTB_UFS_MAGIC
&&
727 (sblock
->fs_version
< MTB_UFS_VERSION_MIN
||
728 sblock
->fs_version
> MTB_UFS_VERSION_1
)) {
729 msg(gettext("Unrecognized UFS version: %d\n"),
736 * Try to set up for using mmap(2). It only works on the block
737 * device, but if we can use it, things go somewhat faster. If
738 * we can't open it, we'll silently fall back to the old method
739 * (read/memcpy). We also only try this if it's been cleanly
740 * unmounted. Dumping a live filesystem this way runs into
741 * buffer consistency problems. Of course, we don't support
742 * running dump on a mounted filesystem, but some people do it
745 if (sblock
->fs_clean
== FSCLEAN
) {
746 char *block
= unrawname(disk
);
749 mapfd
= open(block
, O_RDONLY
, 0);
755 bread((diskaddr_t
)SBLOCK
, (uchar_t
*)sblock
, (long)SBSIZE
);
756 if ((sblock
->fs_magic
!= FS_MAGIC
) &&
757 (sblock
->fs_magic
!= MTB_UFS_MAGIC
)) { /* paranoia */
758 msg(gettext("bad super-block magic number, run fsck\n"));
763 if (sblock
->fs_magic
== FS_MAGIC
&&
764 (sblock
->fs_version
!= UFS_EFISTYLE4NONEFI_VERSION_2
&&
765 sblock
->fs_version
!= UFS_VERSION_MIN
)) {
766 msg(gettext("Unrecognized UFS version: %d\n"),
772 if (sblock
->fs_magic
== MTB_UFS_MAGIC
&&
773 (sblock
->fs_version
< MTB_UFS_VERSION_MIN
||
774 sblock
->fs_version
> MTB_UFS_VERSION_1
)) {
775 msg(gettext("Unrecognized UFS version: %d\n"),
784 /* XXX should sanity-check the super block before trusting/using it */
786 /* LINTED XXX time truncated - tolerate until tape format changes */
787 spcl
.c_date
= (time32_t
)time((time_t *)NULL
);
788 bcopy(&(spcl
.c_shadow
), c_shadow_save
, sizeof (c_shadow_save
));
790 snapdate
= is_fssnap_dump(disk
);
792 spcl
.c_date
= snapdate
;
795 msg(gettext("Date of this level %c dump: %s\n"),
796 incno
, prdate(spcl
.c_date
));
797 msg(gettext("Date of last level %c dump: %s\n"),
798 (uchar_t
)lastincno
, prdate(spcl
.c_ddate
));
799 msg(gettext("Dumping %s "), disk
);
801 msgtail("(%.*s:%s) ",
802 /* LINTED unsigned -> signed cast ok */
803 (int)sizeof (spcl
.c_host
), spcl
.c_host
, filesystem
);
804 msgtail(gettext("to %s.\n"), sdumpdev
);
807 esize
= f_esize
= o_esize
= 0;
808 msiz
= roundup(d_howmany(sblock
->fs_ipg
* sblock
->fs_ncg
, NBBY
),
811 clrmap
= (uchar_t
*)xcalloc(msiz
, sizeof (*clrmap
));
812 filmap
= (uchar_t
*)xcalloc(msiz
, sizeof (*filmap
));
813 dirmap
= (uchar_t
*)xcalloc(msiz
, sizeof (*dirmap
));
814 nodmap
= (uchar_t
*)xcalloc(msiz
, sizeof (*nodmap
));
815 shamap
= (uchar_t
*)xcalloc(msiz
, sizeof (*shamap
));
816 activemap
= (uchar_t
*)xcalloc(msiz
, sizeof (*activemap
));
818 if (clrmap
== NULL
|| filmap
== NULL
|| dirmap
== NULL
||
819 nodmap
== NULL
|| shamap
== NULL
|| activemap
== NULL
) {
821 "Internal error: NULL map pointer while re-dumping active files"));
830 /* retain active map */
837 * Read cylinder group inode-used bitmaps to avoid reading clear inodes.
840 uchar_t
*clrp
= clrmap
;
842 (struct cg
*)xcalloc((uint_t
)sblock
->fs_cgsize
, 1);
844 for (i
= 0; i
< sblock
->fs_ncg
; i
++) {
845 bread(fsbtodb(sblock
, cgtod(sblock
, i
)),
846 (uchar_t
*)cgp
, sblock
->fs_cgsize
);
847 bcopy(cg_inosused(cgp
), clrp
,
848 (int)sblock
->fs_ipg
/ NBBY
);
849 clrp
+= sblock
->fs_ipg
/ NBBY
;
852 /* XXX right-shift clrmap one bit. why? */
853 for (i
= 0; clrp
> clrmap
; i
<<= NBBY
) {
854 i
|= *--clrp
& ((1<<NBBY
) - 1);
860 msgp
= gettext("Mapping (Pass I) [regular files]\n");
866 if (partial_mark(argc
, argv
)) {
869 pass(mark
, clrmap
); /* mark updates 'x'_esize */
871 pass(active_mark
, clrmap
); /* updates 'x'_esize */
877 msgp
= gettext("Mapping (Pass II) [directories]\n");
885 ino
= 0; /* adjust estimated size for shadow inodes */
886 pass(markshad
, nodmap
);
888 pass(estshad
, shamap
);
893 esize
= o_esize
+ f_esize
;
895 /* estimate number of floppies */
897 fetapes
= (double)(esize
+ ntrec
) / (double)tsize
;
898 } else if (cartridge
) {
900 * Estimate number of tapes, assuming streaming stops at
901 * the end of each block written, and not in mid-block.
902 * Assume no erroneous blocks; this can be compensated for
903 * with an artificially low tape size.
905 tenthsperirg
= 16; /* actually 15.48, says Archive */
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
) /* streaming-stops per block */
913 * tenthsperirg
) /* 0.1" / streaming-stop */
914 * (1.0 / tsize
); /* tape / 0.1" */
916 /* Estimate number of tapes, for old fashioned 9-track tape */
918 /* sun has long irg's */
919 tenthsperirg
= (density
== 625) ? 6 : 12;
921 tenthsperirg
= (density
== 625) ? 5 : 8;
924 fetapes
= ((double)esize
/* blocks */
925 * (tp_bsize
/* bytes / block */
926 * (1.0/density
)) /* 0.1" / byte */
928 (double)esize
/* blocks */
929 * (1.0/ntrec
) /* IRG's / block */
930 * tenthsperirg
) /* 0.1" / IRG */
931 * (1.0 / tsize
); /* tape / 0.1" */
934 etapes
= fetapes
; /* truncating assignment */
936 /* count the nodemap on each additional tape */
937 for (i
= 1; i
< etapes
; i
++)
940 * If the above bmapest is called, it changes o_esize and f_esize.
941 * So we will recalculate esize here anyway to make sure.
942 * Also, add tape headers and trailer records.
944 esize
= o_esize
+ f_esize
+ etapes
+ ntrec
;
947 * If the estimated number of tp_bsize tape blocks is greater than
948 * INT_MAX we have to adjust tp_bsize and ntrec to handle
949 * the larger dump. esize is an estimate, so we 'fudge'
950 * INT_MAX a little. If tp_bsize is adjusted, it will be adjusted
951 * to the size needed for this dump (2048, 4096, 8192, ...)
953 if (esize
> (INT_MAX
- FUDGE_FACTOR
)) { /* esize is too big */
956 ((esize
+ (INT_MAX
- FUDGE_FACTOR
) - 1)/
957 ((u_offset_t
)(INT_MAX
- FUDGE_FACTOR
))) - 1;
958 if ((esize_shift
> ESIZE_SHIFT_MAX
) || (ntrec
== 0)) {
960 "Block factor %d ('b' flag) is too small for this size dump.");
961 msg(msgp
, saved_ntrec
);
966 * recalculate esize from:
967 * o_esize - header tape records
968 * (f_esize + (num_mult -1)) >> esize_shift - new non-header
969 * tape records for files/maps
970 * etapes - TS_TAPE records
971 * ntrec - TS_END records
973 * ntrec is adjusted so a tape record is still 'b' flag
974 * number of DEV_BSIZE (512) in size
976 new_mult
= (tp_bsize
<< esize_shift
)/tp_bsize
;
977 tp_bsize
= (tp_bsize
<< esize_shift
);
978 esize
= o_esize
+ ((f_esize
+
979 (new_mult
- 1)) >> esize_shift
) + etapes
+ ntrec
;
980 ntrec
= (saved_ntrec
/(tp_bsize
/DEV_BSIZE
));
982 if (forceflag
!= 0) {
984 "Forcing larger tape block size (%d).\n");
987 alloctape(); /* allocate tape buffers */
989 assert((tp_bsize
/ DEV_BSIZE
!= 0) && (tp_bsize
% DEV_BSIZE
== 0));
991 * If all we wanted was the size estimate,
992 * just print it out and exit.
995 (void) printf("%llu\n", esize
* tp_bsize
);
1002 "Estimated %lld blocks (%s) on %3.2f diskettes.\n");
1005 "Estimated %lld blocks (%s) on %3.2f tapes.\n");
1008 (esize
*(tp_bsize
/DEV_BSIZE
)), mb(esize
), fetapes
);
1010 msgp
= gettext("Estimated %lld blocks (%s).\n");
1011 msg(msgp
, (esize
*(tp_bsize
/DEV_BSIZE
)), mb(esize
));
1014 dumpstate
= DS_CLRI
;
1016 otape(1); /* bitmap is the first to tape write */
1018 (void) time(tstart_writing
);
1020 /* filmap indicates all non-directory inodes */
1022 uchar_t
*np
, *fp
, *dp
;
1026 for (i
= 0; i
< msiz
; i
++)
1027 *fp
++ = *np
++ ^ *dp
++;
1030 while (dumpstate
!= DS_DONE
) {
1032 * When we receive EOT notification from
1033 * the writer, the signal handler calls
1034 * rollforward and then jumps here.
1036 (void) setjmp(checkpoint_buf
);
1037 switch (dumpstate
) {
1040 * We get here if a tape error occurred
1041 * after releasing the name lock but before
1042 * the volume containing the last of the
1043 * dir info was completed. We have to start
1044 * all over in this case.
1047 char *rmsg
= gettext(
1048 "Warning - output error occurred after releasing name lock\n\
1049 \tThe dump will restart\n");
1058 bitmap(clrmap
, TS_CLRI
);
1064 if (BIT(UFSROOTINO
, nodmap
)) /* empty dump check */
1065 bitmap(nodmap
, TS_BITS
);
1069 "Dumping (Pass III) [directories]\n");
1075 pass(dirdump
, dirmap
);
1076 nextstate(DS_FILES
);
1079 "Dumping (Pass IV) [regular files]\n");
1086 pass(lf_dump
, filmap
);
1089 dumpstate
= DS_END
; /* don't reset ino */
1093 spcl
.c_type
= TS_END
;
1094 for (i
= 0; i
< ntrec
; i
++) {
1102 msg(gettext("Internal state error\n"));
1108 if ((! doingactive
) && (! active
))
1110 if (verify
&& !doingverify
) {
1111 msgp
= gettext("Finished writing last dump volume\n");
1115 if (spcl
.c_volume
> 1)
1116 (void) snprintf(msgbuf
, sizeof (msgbuf
),
1117 gettext("%lld blocks (%s) on %ld volumes"),
1118 ((uint64_t)spcl
.c_tapea
*(tp_bsize
/DEV_BSIZE
)),
1119 mb((u_offset_t
)(unsigned)(spcl
.c_tapea
)),
1122 (void) snprintf(msgbuf
, sizeof (msgbuf
),
1123 gettext("%lld blocks (%s) on 1 volume"),
1124 ((uint64_t)spcl
.c_tapea
*(tp_bsize
/DEV_BSIZE
)),
1125 mb((u_offset_t
)(unsigned)(spcl
.c_tapea
)));
1126 if (timeclock((time_t)0) != (time_t)0) {
1127 (void) snprintf(kbsbuf
, sizeof (kbsbuf
),
1128 gettext(" at %ld KB/sec"),
1129 (long)(((float)spcl
.c_tapea
/ (float)timeclock((time_t)0))
1131 (void) strcat(msgbuf
, kbsbuf
);
1133 (void) strcat(msgbuf
, "\n");
1135 (void) timeclock((time_t)-1);
1138 msg(gettext("Archiving dump to `%s'\n"), archivefile
);
1139 if (active
&& !verify
) {
1144 msgp
= gettext("DUMP IS DONE\n");
1165 sigtype
= "SIGTRAP";
1171 msg(gettext("%s ABORTING!\n"), "SIGBUS()");
1172 (void) signal(SIGUSR2
, SIG_DFL
);
1176 msg(gettext("%s ABORTING!\n"), "SIGSEGV()");
1177 (void) signal(SIGUSR2
, SIG_DFL
);
1181 sigtype
= "SIGALRM";
1184 sigtype
= "SIGTERM";
1187 msg(gettext("Broken pipe\n"));
1194 msg(gettext("%s() try rewriting\n"), sigtype
);
1196 msg(gettext("Unknown signal, Cannot recover\n"));
1200 msg(gettext("Rewriting attempted as response to unknown signal.\n"));
1201 (void) fflush(stderr
);
1202 (void) fflush(stdout
);
1207 /* Note that returned value is malloc'd if != cp && != NULL */
1213 extern char *getfullrawname();
1215 if (stat64(cp
, &st
) < 0 || (st
.st_mode
& S_IFMT
) != S_IFBLK
)
1218 dp
= getfullrawname(cp
);
1226 if (stat64(dp
, &st
) < 0 || (st
.st_mode
& S_IFMT
) != S_IFCHR
) {
1237 static char buf
[16];
1240 (void) snprintf(buf
, sizeof (buf
), "%lldKB", blks
);
1242 (void) snprintf(buf
, sizeof (buf
), "%.2fMB",
1243 ((double)(blks
*tp_bsize
)) / (double)(1024*1024));
1248 void (*nsignal(int sig
, void (*act
)(int)))(int)
1250 struct sigaction sa
, osa
;
1252 sa
.sa_handler
= act
;
1253 (void) sigemptyset(&sa
.sa_mask
);
1254 sa
.sa_flags
= SA_RESTART
;
1255 if (sigaction(sig
, &sa
, &osa
) < 0)
1256 return ((void (*)(int))-1);
1257 return (osa
.sa_handler
);
1262 nextstate(int state
)
1264 /* LINTED assigned value never used - kept for documentary purposes */
1266 /* LINTED assigned value never used - kept for documentary purposes */
1268 /* LINTED assigned value never used - kept for documentary purposes */
1274 * timeclock() function, for keeping track of how much time we've spent
1275 * writing to the tape device. it always returns the amount of time
1276 * already spent, in milliseconds. if you pass it a positive, then that's
1277 * telling it that we're writing, so the time counts. if you pass it a
1278 * zero, then that's telling it we're not writing; perhaps we're waiting
1281 * a state of -1 resets everything.
1284 timeclock(time32_t state
)
1286 static int *currentState
= NULL
;
1287 static struct timeval
*clockstart
;
1288 static time32_t
*emilli
;
1290 struct timeval current
[1];
1294 fprintf(stderr
, "pid=%d timeclock ", getpid());
1295 if (state
== (time32_t
)-1)
1296 fprintf(stderr
, "cleared\n");
1298 fprintf(stderr
, "ticking\n");
1300 fprintf(stderr
, "paused\n");
1303 /* if we haven't setup the shared memory, init */
1304 if (currentState
== (int *)NULL
) {
1305 if ((fd
= open("/dev/zero", O_RDWR
)) < 0) {
1307 msg(gettext("Cannot open `%s': %s\n"),
1308 "/dev/zero", strerror(saverr
));
1312 /*LINTED [mmap always returns an aligned value]*/
1313 currentState
= (int *)mmap((char *)0, getpagesize(),
1314 PROT_READ
|PROT_WRITE
, MAP_SHARED
, fd
, (off_t
)0);
1315 if (currentState
== (int *)-1) {
1318 "Cannot memory map monitor variables: %s\n"),
1325 /* LINTED currentState is sufficiently aligned */
1326 clockstart
= (struct timeval
*)(currentState
+ 1);
1327 emilli
= (time32_t
*)(clockstart
+ 1);
1328 /* Note everything is initialized to zero via /dev/zero */
1331 if (state
== (time32_t
)-1) {
1332 bzero(clockstart
, sizeof (*clockstart
));
1334 *emilli
= (time32_t
)0;
1338 (void) gettimeofday(current
, NULL
);
1340 if (*currentState
!= 0) {
1341 current
->tv_usec
+= 1000000;
1344 /* LINTED: result will fit in a time32_t */
1345 *emilli
+= (current
->tv_sec
- clockstart
->tv_sec
) * 1000;
1346 /* LINTED: result will fit in a time32_t */
1347 *emilli
+= (current
->tv_usec
- clockstart
->tv_usec
) / 1000;
1351 bcopy(current
, clockstart
, sizeof (current
));
1353 *currentState
= state
;
1359 statcmp(const struct stat64
*left
, const struct stat64
*right
)
1363 if ((left
->st_dev
== right
->st_dev
) &&
1364 (left
->st_ino
== right
->st_ino
) &&
1365 (left
->st_mode
== right
->st_mode
) &&
1366 (left
->st_nlink
== right
->st_nlink
) &&
1367 (left
->st_uid
== right
->st_uid
) &&
1368 (left
->st_gid
== right
->st_gid
) &&
1369 (left
->st_rdev
== right
->st_rdev
) &&
1370 (left
->st_ctim
.tv_sec
== right
->st_ctim
.tv_sec
) &&
1371 (left
->st_ctim
.tv_nsec
== right
->st_ctim
.tv_nsec
) &&
1372 (left
->st_mtim
.tv_sec
== right
->st_mtim
.tv_sec
) &&
1373 (left
->st_mtim
.tv_nsec
== right
->st_mtim
.tv_nsec
)) {
1375 * Unlike in the ufsrestore version
1376 * st_blocks and st_blksiz are not
1377 * compared. The reason for this is
1378 * problems with zfs dump files. Zfs
1379 * changes it's statistics in those
1389 * Safely open a file or device.
1392 safe_open_common(const char *filename
, int mode
, int perms
, int device
)
1398 struct stat64 pre_stat
, pre_lstat
;
1399 struct stat64 post_stat
, post_lstat
;
1402 * Don't want to be spoofed into trashing something we
1403 * shouldn't, thus the following rigamarole. If it doesn't
1404 * exist, we create it and proceed. Otherwise, require that
1405 * what's there be a real file with no extraneous links and
1406 * owned by whoever ran us.
1408 * The silliness with using both lstat() and fstat() is to avoid
1409 * race-condition games with someone replacing the file with a
1410 * symlink after we've opened it. If there was an flstat(),
1411 * we wouldn't need the fstat().
1413 * The initial open with the hard-coded flags is ok even if we
1414 * are intending to open only for reading. If it succeeds,
1415 * then the file did not exist, and we'll synthesize an appropriate
1416 * complaint below. Otherwise, it does exist, so we won't be
1417 * truncating it with the open.
1419 if ((fd
= open(filename
, O_WRONLY
|O_CREAT
|O_TRUNC
|O_EXCL
|O_LARGEFILE
,
1421 if (errno
== EEXIST
) {
1422 if (lstat64(filename
, &pre_lstat
) < 0) {
1426 if (stat64(filename
, &pre_stat
) < 0) {
1430 working_mode
= mode
& (O_WRONLY
|O_RDWR
|O_RDONLY
);
1431 working_mode
|= O_LARGEFILE
;
1432 if ((fd
= open(filename
, working_mode
)) < 0) {
1433 if (errno
== ENOENT
) {
1435 "Unexpected condition detected: %s used to exist, but doesn't any longer\n");
1436 msg(errtext
, filename
);
1437 syslog(LOG_WARNING
, errtext
, filename
);
1443 if (lstat64(filename
, &post_lstat
) < 0) {
1450 if (fstat64(fd
, &post_stat
) < 0) {
1458 * Can't just use memcmp(3C), because the access
1459 * time is updated by open(2).
1461 if (statcmp(&pre_lstat
, &post_lstat
) != 0) {
1462 errtext
= gettext("Unexpected change detected: "
1463 "%s's lstat(2) information changed\n");
1464 msg(errtext
, filename
);
1465 syslog(LOG_WARNING
, errtext
, filename
);
1470 if (statcmp(&pre_stat
, &post_stat
) != 0) {
1471 errtext
= gettext("Unexpected change detected: "
1472 "%s's stat(2) information changed\n"),
1473 msg(errtext
, filename
);
1474 syslog(LOG_WARNING
, errtext
, filename
);
1480 * If inode, device, or type are wrong, bail out.
1481 * Note using post_stat instead of post_lstat for the
1482 * S_ISCHR() test. This is to allow the /dev ->
1483 * /devices bit to work, as long as the final target
1484 * is a character device (i.e., raw disk or tape).
1486 if (device
&& !(S_ISCHR(post_stat
.st_mode
)) &&
1487 !(S_ISFIFO(post_stat
.st_mode
)) &&
1488 !(S_ISREG(post_lstat
.st_mode
))) {
1489 errtext
= gettext("Unexpected condition "
1490 "detected: %s is not a supported device\n"),
1491 msg(errtext
, filename
);
1492 syslog(LOG_WARNING
, errtext
, filename
);
1496 } else if (!device
&&
1497 (!S_ISREG(post_lstat
.st_mode
) ||
1498 (post_stat
.st_ino
!= post_lstat
.st_ino
) ||
1499 (post_stat
.st_dev
!= post_lstat
.st_dev
))) {
1500 errtext
= gettext("Unexpected condition "
1501 "detected: %s is not a regular file\n"),
1502 msg(errtext
, filename
);
1503 syslog(LOG_WARNING
, errtext
, filename
);
1510 * Bad link count implies someone's linked our
1511 * target to something else, which we probably
1512 * shouldn't step on.
1514 if (post_lstat
.st_nlink
!= 1) {
1515 errtext
= gettext("Unexpected condition "
1516 "detected: %s must have exactly one "
1517 "link\n"), msg(errtext
, filename
);
1518 syslog(LOG_WARNING
, errtext
, filename
);
1524 * Root might make a file, but non-root might
1525 * need to open it. If the permissions let us
1526 * get this far, then let it through.
1528 if (post_lstat
.st_uid
!= getuid() &&
1529 post_lstat
.st_uid
!= 0) {
1530 errtext
= gettext("Unsupported "
1531 "condition detected: %s "
1532 "must be owned by uid %ld or 0\n"),
1533 msg(errtext
, filename
, (long)getuid());
1534 syslog(LOG_WARNING
, errtext
, filename
,
1540 if (mode
& O_TRUNC
) {
1541 if (ftruncate(fd
, (off_t
)0) < 0) {
1542 msg("ftruncate(%s): %s\n",
1543 filename
, strerror(errno
));
1550 * Didn't exist, but couldn't open it.
1556 * If truncating open succeeded for a read-only open,
1557 * bail out, as we really shouldn't have succeeded.
1559 if (mode
& O_RDONLY
) {
1560 /* Undo the O_CREAT */
1561 (void) unlink(filename
);
1562 msg("open(%s): %s\n",
1563 filename
, strerror(ENOENT
));
1574 * Safely open a file.
1577 safe_file_open(const char *filename
, int mode
, int perms
)
1579 return (safe_open_common(filename
, mode
, perms
, 0));
1583 * Safely open a device.
1586 safe_device_open(const char *filename
, int mode
, int perms
)
1588 return (safe_open_common(filename
, mode
, perms
, 1));
1592 * STDIO version of safe_open
1595 safe_fopen(const char *filename
, const char *smode
, int perms
)
1601 * accepts only modes "r", "r+", and "w"
1603 if (smode
[0] == 'r') {
1604 if (smode
[1] == '\0') {
1606 } else if ((smode
[1] == '+') && (smode
[2] == '\0')) {
1609 } else if ((smode
[0] == 'w') && (smode
[1] == '\0')) {
1612 msg(gettext("internal error: safe_fopen: invalid mode `%s'\n"),
1617 fd
= safe_file_open(filename
, bmode
, perms
);
1620 * caller is expected to report error.
1623 return (fdopen(fd
, smode
));
1625 return ((FILE *)NULL
);
1631 char name
[MAXPATHLEN
];
1633 if (debug_chdir
!= NULL
) {
1634 snprintf(name
, sizeof (name
), "%s/%ld",
1635 debug_chdir
, (long)getpid());
1636 if (mkdir(name
, 0755) < 0)
1637 msg("mkdir(%s): %s", name
, strerror(errno
));
1638 if (chdir(name
) < 0)
1639 msg("chdir(%s): %s", name
, strerror(errno
));