* Copyright (c) 1980, 1991 The Regents of the University of California.
* %sccs.include.redist.c%
"@(#) Copyright (c) 1980, 1991 The Regents of the University of California.\n\
static char sccsid
[] = "@(#)main.c 5.26 (Berkeley) %G%";
#include <ufs/ufs/dinode.h>
#include <protocols/dumprestore.h>
#define SBOFF (SBLOCK * DEV_BSIZE)
int notify
= 0; /* notify operator flag */
int blockswritten
= 0; /* number of blocks written on current tape */
int tapeno
= 0; /* current tape number */
int density
= 0; /* density in bytes/0.1" */
int ntrec
= NTREC
; /* # tape blocks in each tape record */
int cartridge
= 0; /* Assume non-cartridge tape */
long dev_bsize
= 1; /* recalculated below */
long blocksperfile
; /* output blocks per file */
char *host
= NULL
; /* remote host (if any) */
static long numarg
__P((int, char *, long, long, int *, char ***));
static __dead
void missingarg
__P((int, char *));
register struct dinode
*dp
;
register struct fstab
*dt
;
int i
, anydirskipped
, bflag
= 0, Tflag
= 0, honorlevel
= 1;
(void)time((time_t *)&spcl
.c_date
);
tsize
= 0; /* Default later, based on 'c' option for cart tapes */
dumpdates
= _PATH_DUMPDATES
;
if (TP_BSIZE
/ DEV_BSIZE
== 0 || TP_BSIZE
% DEV_BSIZE
!= 0)
quit("TP_BSIZE must be a multiple of DEV_BSIZE\n");
for (cp
= *argv
++; *cp
; cp
++) {
lastdump('w'); /* tell us only what has to be done */
case 'W': /* what to do */
lastdump('W'); /* tell us state of what is done */
exit(0); /* do nothing else */
case 'f': /* output file */
missingarg('f', "output file");
case 'd': /* density, in bits per inch */
density
= numarg('d', "density",
10L, 327670L, &argc
, &argv
) / 10;
if (density
>= 625 && !bflag
)
case 's': /* tape size, feet */
tsize
= numarg('s', "size",
1L, 0L, &argc
, &argv
) * 12 * 10;
case 'T': /* time of last dump */
missingarg('T', "time of last dump");
spcl
.c_ddate
= unctime(*argv
);
(void)fprintf(stderr
, "bad time \"%s\"\n",
case 'b': /* blocks per tape write */
ntrec
= numarg('b', "number of blocks per write",
1L, 1000L, &argc
, &argv
);
case 'B': /* blocks per output file */
blocksperfile
= numarg('B', "number of blocks per file",
case 'c': /* Tape is cart. not 9-track */
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case 'u': /* update /etc/dumpdates */
case 'n': /* notify operators */
honorlevel
= numarg('h', "honor level",
(void)fprintf(stderr
, "bad key '%c'\n", *cp
);
(void)fprintf(stderr
, "Must specify disk or filesystem\n");
(void)fprintf(stderr
, "Unknown arguments to dump:");
(void)fprintf(stderr
, " %s", *argv
++);
(void)fprintf(stderr
, "\n");
"You cannot use the T and u flags together.\n");
if (strcmp(tape
, "-") == 0) {
tape
= "standard output";
blocksperfile
= blocksperfile
/ ntrec
* ntrec
; /* round down */
* Determine how to default tape size and density
* 9-track 1600 bpi (160 bytes/.1") 2300 ft.
* 9-track 6250 bpi (625 bytes/.1") 2300 ft.
* cartridge 8000 bpi (100 bytes/.1") 1700 ft.
density
= cartridge
? 100 : 160;
tsize
= cartridge
? 1700L*120L : 2300L*120L;
(void)fprintf(stderr
, "remote dump not enabled\n");
(void)setuid(getuid()); /* rmthost() is the only reason to be setuid */
if (signal(SIGHUP
, SIG_IGN
) != SIG_IGN
)
if (signal(SIGTRAP
, SIG_IGN
) != SIG_IGN
)
if (signal(SIGFPE
, SIG_IGN
) != SIG_IGN
)
if (signal(SIGBUS
, SIG_IGN
) != SIG_IGN
)
if (signal(SIGSEGV
, SIG_IGN
) != SIG_IGN
)
if (signal(SIGTERM
, SIG_IGN
) != SIG_IGN
)
if (signal(SIGINT
, interrupt
) == SIG_IGN
)
set_operators(); /* /etc/group snarfed */
getfstab(); /* /etc/fstab snarfed */
* disk can be either the full special file name,
* the suffix of the special file name,
* the special name missing the leading '/',
* the file system name with or without the leading '/'.
disk
= rawname(dt
->fs_spec
);
(void)strncpy(spcl
.c_dev
, dt
->fs_spec
, NAMELEN
);
(void)strncpy(spcl
.c_filesys
, dt
->fs_file
, NAMELEN
);
(void)strncpy(spcl
.c_dev
, disk
, NAMELEN
);
(void)strncpy(spcl
.c_filesys
, "an unlisted file system",
(void)strcpy(spcl
.c_label
, "none");
(void)gethostname(spcl
.c_host
, NAMELEN
);
spcl
.c_level
= level
- '0';
getdumptime(); /* /etc/dumpdates snarfed */
msg("Date of this level %c dump: %s", level
,
spcl
.c_date
== 0 ? "the epoch\n" : ctime(&spcl
.c_date
));
msg("Date of last level %c dump: %s", lastlevel
,
spcl
.c_ddate
== 0 ? "the epoch\n" : ctime(&spcl
.c_ddate
));
msg("Dumping %s ", disk
);
msgtail("(%s) ", dt
->fs_file
);
msgtail("to %s on host %s\n", tape
, host
);
msgtail("to %s\n", tape
);
if ((diskfd
= open(disk
, O_RDONLY
)) < 0) {
msg("Cannot open %s\n", disk
);
sblock
= (struct fs
*)sblock_buf
;
bread(SBOFF
, (char *) sblock
, SBSIZE
);
if (sblock
->fs_magic
!= FS_MAGIC
)
quit("bad sblock magic number\n");
dev_bsize
= sblock
->fs_fsize
/ fsbtodb(sblock
, 1);
dev_bshift
= ffs(dev_bsize
) - 1;
if (dev_bsize
!= (1 << dev_bshift
))
quit("dev_bsize (%d) is not a power of 2", dev_bsize
);
tp_bshift
= ffs(TP_BSIZE
) - 1;
if (TP_BSIZE
!= (1 << tp_bshift
))
quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE
);
if (sblock
->fs_inodefmt
>= FS_44INODEFMT
)
spcl
.c_flags
|= DR_NEWINODEFMT
;
maxino
= sblock
->fs_ipg
* sblock
->fs_ncg
;
mapsize
= roundup(howmany(maxino
, NBBY
), TP_BSIZE
);
usedinomap
= (char *)calloc((unsigned) mapsize
, sizeof(char));
dumpdirmap
= (char *)calloc((unsigned) mapsize
, sizeof(char));
dumpinomap
= (char *)calloc((unsigned) mapsize
, sizeof(char));
tapesize
= 3 * (howmany(mapsize
* sizeof(char), TP_BSIZE
) + 1);
nonodump
= spcl
.c_level
< honorlevel
;
msg("mapping (Pass I) [regular files]\n");
anydirskipped
= mapfiles(maxino
, &tapesize
);
msg("mapping (Pass II) [directories]\n");
anydirskipped
= mapdirs(maxino
, &tapesize
);
tapesize
+= 10; /* 10 trailer blocks */
msg("estimated %ld tape blocks.\n", tapesize
);
fetapes
= (double) tapesize
/ blocksperfile
;
/* Estimate number of tapes, assuming streaming stops at
the end of each block written, and not in mid-block.
Assume no erroneous blocks; this can be compensated
for with an artificially low tape size. */
* TP_BSIZE
/* bytes/block */
* (1.0/density
) /* 0.1" / byte */
* (1.0/ntrec
) /* streaming-stops per block */
* 15.48 /* 0.1" / streaming-stop */
) * (1.0 / tsize
); /* tape / 0.1" */
/* Estimate number of tapes, for old fashioned 9-track
int tenthsperirg
= (density
== 625) ? 3 : 7;
* TP_BSIZE
/* bytes / block */
* (1.0/density
) /* 0.1" / byte */
* (1.0/ntrec
) /* IRG's / block */
* tenthsperirg
/* 0.1" / IRG */
) * (1.0 / tsize
); /* tape / 0.1" */
etapes
= fetapes
; /* truncating assignment */
/* count the dumped inodes map on each additional tape */
tapesize
+= (etapes
- 1) *
(howmany(mapsize
* sizeof(char), TP_BSIZE
) + 1);
tapesize
+= etapes
+ 10; /* headers + 10 trailer blks */
msg("estimated %ld tape blocks on %3.2f tape(s).\n",
quit("can't allocate tape buffers - try a smaller blocking factor.\n");
(void)time((time_t *)&(tstart_writing
));
dumpmap(usedinomap
, TS_CLRI
, maxino
- 1);
msg("dumping (Pass III) [directories]\n");
dirty
= 0; /* XXX just to get gcc to shut up */
for (map
= dumpdirmap
, ino
= 1; ino
< maxino
; ino
++) {
if (((ino
- 1) % NBBY
) == 0) /* map is offset by 1 */
* Skip directory inodes deleted and maybe reallocated
if ((dp
->di_mode
& IFMT
) != IFDIR
)
msg("dumping (Pass IV) [regular files]\n");
for (map
= dumpinomap
, ino
= 1; ino
< maxino
; ino
++) {
if (((ino
- 1) % NBBY
) == 0) /* map is offset by 1 */
* Skip inodes deleted and reallocated as directories.
mode
= dp
->di_mode
& IFMT
;
for (i
= 0; i
< ntrec
; i
++)
msg("DUMP: %ld tape blocks\n",spcl
.c_tapea
);
msg("DUMP: %ld tape blocks on %d volumes(s)\n",
spcl
.c_tapea
, spcl
.c_volume
);
broadcast("DUMP IS DONE!\7\7\n");
* Pick up a numeric argument. It must be nonnegative and in the given
* range (except that a vmax of 0 means unlimited).
numarg(letter
, meaning
, vmin
, vmax
, pargc
, pargv
)
missingarg(letter
, meaning
);
if (val
< vmin
|| (vmax
&& val
> vmax
))
(void)fprintf(stderr
, "bad '%c' (%s) value \"%s\"\n",
missingarg(letter
, meaning
)
(void)fprintf(stderr
, "The '%c' flag (%s) requires an argument\n",
quit("Signal on pipe: cannot recover\n");
msg("Rewriting attempted as response to unknown signal.\n");
msg("SIGSEGV: ABORTING!\n");
(void)signal(SIGSEGV
, SIG_DFL
);
char *dp
= rindex(cp
, '/');
(void)strcpy(rawbuf
, cp
);
(void)strcat(rawbuf
, "/r");
(void)strcat(rawbuf
, dp
+ 1);
extern const char *const sys_errlist
[];
return (sys_errlist
[errnum
]);
return ("bogus errno in strerror");