xref: /csrg-svn/sbin/dump/main.c (revision 46614)
122037Sdist /*
222037Sdist  * Copyright (c) 1980 Regents of the University of California.
322037Sdist  * All rights reserved.  The Berkeley software License Agreement
422037Sdist  * specifies the terms and conditions for redistribution.
522037Sdist  */
622037Sdist 
722037Sdist #ifndef lint
8*46614Smckusick static char sccsid[] = "@(#)main.c	5.11 (Berkeley) 02/24/91";
946586Storek #endif /* not lint */
1022037Sdist 
111423Sroot #include "dump.h"
1246586Storek #include <fcntl.h>
1337266Sbostic #include "pathnames.h"
141423Sroot 
151423Sroot int	notify = 0;	/* notify operator flag */
161423Sroot int	blockswritten = 0;	/* number of blocks written on current tape */
171423Sroot int	tapeno = 0;	/* current tape number */
1810910Ssam int	density = 0;	/* density in bytes/0.1" */
1910910Ssam int	ntrec = NTREC;	/* # tape blocks in each tape record */
2010910Ssam int	cartridge = 0;	/* Assume non-cartridge tape */
2130560Smckusick long	dev_bsize = 1;	/* recalculated below */
22*46614Smckusick long	blocksperfile;	/* output blocks per file */
236882Ssam #ifdef RDUMP
246882Ssam char	*host;
2546586Storek int	rmthost();
266882Ssam #endif
2725797Smckusick int	anydskipped;	/* set true in mark() if any directories are skipped */
2825797Smckusick 			/* this lets us avoid map pass 2 in some cases */
291423Sroot 
301423Sroot main(argc, argv)
311423Sroot 	int	argc;
321423Sroot 	char	*argv[];
331423Sroot {
341423Sroot 	char		*arg;
3518494Smckusick 	int		bflag = 0, i;
361423Sroot 	float		fetapes;
371423Sroot 	register	struct	fstab	*dt;
381423Sroot 
391423Sroot 	time(&(spcl.c_date));
401423Sroot 
4110910Ssam 	tsize = 0;	/* Default later, based on 'c' option for cart tapes */
4237946Sbostic 	tape = _PATH_DEFTAPE;
4337946Sbostic 	disk = _PATH_DEFDISK;
4437266Sbostic 	increm = _PATH_DUMPDATES;
4537266Sbostic 	temp = _PATH_DTMP;
4646586Storek 	if (TP_BSIZE / DEV_BSIZE == 0 || TP_BSIZE % DEV_BSIZE != 0)
4746586Storek 		quit("TP_BSIZE must be a multiple of DEV_BSIZE\n");
481423Sroot 	incno = '9';
491423Sroot 	uflag = 0;
501423Sroot 	arg = "u";
511423Sroot 	if(argc > 1) {
521423Sroot 		argv++;
531423Sroot 		argc--;
541423Sroot 		arg = *argv;
551423Sroot 		if (*arg == '-')
561423Sroot 			argc++;
571423Sroot 	}
581423Sroot 	while(*arg)
591423Sroot 	switch (*arg++) {
601463Sroot 	case 'w':
611463Sroot 		lastdump('w');		/* tell us only what has to be done */
621463Sroot 		exit(0);
631463Sroot 		break;
641423Sroot 	case 'W':			/* what to do */
651463Sroot 		lastdump('W');		/* tell us the current state of what has been done */
661423Sroot 		exit(0);		/* do nothing else */
671423Sroot 		break;
681423Sroot 
691423Sroot 	case 'f':			/* output file */
701423Sroot 		if(argc > 1) {
711423Sroot 			argv++;
721423Sroot 			argc--;
731423Sroot 			tape = *argv;
741423Sroot 		}
751423Sroot 		break;
761423Sroot 
771423Sroot 	case 'd':			/* density, in bits per inch */
781423Sroot 		if (argc > 1) {
791423Sroot 			argv++;
801423Sroot 			argc--;
811423Sroot 			density = atoi(*argv) / 10;
8218494Smckusick 			if (density >= 625 && !bflag)
8318494Smckusick 				ntrec = HIGHDENSITYTREC;
841423Sroot 		}
851423Sroot 		break;
861423Sroot 
871423Sroot 	case 's':			/* tape size, feet */
881423Sroot 		if(argc > 1) {
891423Sroot 			argv++;
901423Sroot 			argc--;
911423Sroot 			tsize = atol(*argv);
921423Sroot 			tsize *= 12L*10L;
931423Sroot 		}
941423Sroot 		break;
951423Sroot 
9610910Ssam 	case 'b':			/* blocks per tape write */
9710910Ssam 		if(argc > 1) {
9810910Ssam 			argv++;
9910910Ssam 			argc--;
10018494Smckusick 			bflag++;
10110910Ssam 			ntrec = atol(*argv);
102*46614Smckusick 			if (ntrec <= 0) {
103*46614Smckusick 				fprintf(stderr,
104*46614Smckusick 				    "bad number of blocks per write \"%s\"\n",
105*46614Smckusick 				    *arg);
106*46614Smckusick 				Exit(X_ABORT);
107*46614Smckusick 			}
10810910Ssam 		}
10910910Ssam 		break;
11010910Ssam 
111*46614Smckusick 	case 'B':			/* blocks per output file */
112*46614Smckusick 		if(argc > 1) {
113*46614Smckusick 			argv++;
114*46614Smckusick 			argc--;
115*46614Smckusick 			blocksperfile = atol(*argv);
116*46614Smckusick 		}
117*46614Smckusick 		break;
118*46614Smckusick 
11910910Ssam 	case 'c':			/* Tape is cart. not 9-track */
12010910Ssam 		cartridge++;
12110910Ssam 		break;
12210910Ssam 
1231423Sroot 	case '0':			/* dump level */
1241423Sroot 	case '1':
1251423Sroot 	case '2':
1261423Sroot 	case '3':
1271423Sroot 	case '4':
1281423Sroot 	case '5':
1291423Sroot 	case '6':
1301423Sroot 	case '7':
1311423Sroot 	case '8':
1321423Sroot 	case '9':
1331423Sroot 		incno = arg[-1];
1341423Sroot 		break;
1351423Sroot 
1361423Sroot 	case 'u':			/* update /etc/dumpdates */
1371423Sroot 		uflag++;
1381423Sroot 		break;
1391423Sroot 
1401423Sroot 	case 'n':			/* notify operators */
1411423Sroot 		notify++;
1421423Sroot 		break;
1431423Sroot 
1441423Sroot 	default:
145*46614Smckusick 		fprintf(stderr, "bad key '%c'\n", arg[-1]);
1461423Sroot 		Exit(X_ABORT);
1471423Sroot 	}
1481423Sroot 	if(argc > 1) {
1491423Sroot 		argv++;
1501423Sroot 		argc--;
1511423Sroot 		disk = *argv;
1521423Sroot 	}
15312331Smckusick 	if (strcmp(tape, "-") == 0) {
15412331Smckusick 		pipeout++;
15512331Smckusick 		tape = "standard output";
15612331Smckusick 	}
15710910Ssam 
158*46614Smckusick 	if (blocksperfile)
159*46614Smckusick 		blocksperfile = blocksperfile / ntrec * ntrec; /* round down */
160*46614Smckusick 	else {
161*46614Smckusick 		/*
162*46614Smckusick 		 * Determine how to default tape size and density
163*46614Smckusick 		 *
164*46614Smckusick 		 *         	density				tape size
165*46614Smckusick 		 * 9-track	1600 bpi (160 bytes/.1")	2300 ft.
166*46614Smckusick 		 * 9-track	6250 bpi (625 bytes/.1")	2300 ft.
167*46614Smckusick 		 * cartridge	8000 bpi (100 bytes/.1")	1700 ft.
168*46614Smckusick 		 *						(450*4 - slop)
169*46614Smckusick 		 */
170*46614Smckusick 		if (density == 0)
171*46614Smckusick 			density = cartridge ? 100 : 160;
172*46614Smckusick 		if (tsize == 0)
173*46614Smckusick 			tsize = cartridge ? 1700L*120L : 2300L*120L;
174*46614Smckusick 	}
17510910Ssam 
1766886Ssam #ifdef RDUMP
1776886Ssam 	{ char *index();
1786886Ssam 	  host = tape;
1796886Ssam 	  tape = index(host, ':');
1806886Ssam 	  if (tape == 0) {
18128642Smckusick 		msg("need keyletter ``f'' and device ``host:tape''\n");
1826886Ssam 		exit(1);
1836886Ssam 	  }
1846886Ssam 	  *tape++ = 0;
1856886Ssam 	  if (rmthost(host) == 0)
1866886Ssam 		exit(X_ABORT);
1876886Ssam 	}
18828860Smckusick 	setuid(getuid());	/* rmthost() is the only reason to be setuid */
1896886Ssam #endif
190*46614Smckusick 	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
191*46614Smckusick 		signal(SIGHUP, sighup);
192*46614Smckusick 	if (signal(SIGTRAP, SIG_IGN) != SIG_IGN)
193*46614Smckusick 		signal(SIGTRAP, sigtrap);
194*46614Smckusick 	if (signal(SIGFPE, SIG_IGN) != SIG_IGN)
195*46614Smckusick 		signal(SIGFPE, sigfpe);
196*46614Smckusick 	if (signal(SIGBUS, SIG_IGN) != SIG_IGN)
197*46614Smckusick 		signal(SIGBUS, sigbus);
198*46614Smckusick 	if (signal(SIGSEGV, SIG_IGN) != SIG_IGN)
199*46614Smckusick 		signal(SIGSEGV, sigsegv);
200*46614Smckusick 	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
201*46614Smckusick 		signal(SIGTERM, sigterm);
2021423Sroot 
2031423Sroot 
2041423Sroot 	if (signal(SIGINT, interrupt) == SIG_IGN)
2051423Sroot 		signal(SIGINT, SIG_IGN);
2061423Sroot 
2071423Sroot 	set_operators();	/* /etc/group snarfed */
2081423Sroot 	getfstab();		/* /etc/fstab snarfed */
2091423Sroot 	/*
2101423Sroot 	 *	disk can be either the full special file name,
2111423Sroot 	 *	the suffix of the special file name,
2121423Sroot 	 *	the special name missing the leading '/',
2131423Sroot 	 *	the file system name with or without the leading '/'.
2141423Sroot 	 */
2151423Sroot 	dt = fstabsearch(disk);
21629900Smckusick 	if (dt != 0) {
2171423Sroot 		disk = rawname(dt->fs_spec);
21829900Smckusick 		strncpy(spcl.c_dev, dt->fs_spec, NAMELEN);
21929900Smckusick 		strncpy(spcl.c_filesys, dt->fs_file, NAMELEN);
22029900Smckusick 	} else {
22129900Smckusick 		strncpy(spcl.c_dev, disk, NAMELEN);
22229900Smckusick 		strncpy(spcl.c_filesys, "an unlisted file system", NAMELEN);
22329900Smckusick 	}
22429900Smckusick 	strcpy(spcl.c_label, "none");
22529900Smckusick 	gethostname(spcl.c_host, NAMELEN);
22629900Smckusick 	spcl.c_level = incno - '0';
22729900Smckusick 	spcl.c_type = TS_TAPE;
2281423Sroot 	getitime();		/* /etc/dumpdates snarfed */
2291423Sroot 
2301423Sroot 	msg("Date of this level %c dump: %s\n", incno, prdate(spcl.c_date));
23112948Smckusick  	msg("Date of last level %c dump: %s\n",
23212948Smckusick 		lastincno, prdate(spcl.c_ddate));
2331423Sroot 	msg("Dumping %s ", disk);
2341423Sroot 	if (dt != 0)
2351423Sroot 		msgtail("(%s) ", dt->fs_file);
2368506Smckusick #ifdef RDUMP
2378506Smckusick 	msgtail("to %s on host %s\n", tape, host);
2388506Smckusick #else
2398371Smckusick 	msgtail("to %s\n", tape);
2406882Ssam #endif
2411423Sroot 
2421423Sroot 	fi = open(disk, 0);
2431423Sroot 	if (fi < 0) {
2441423Sroot 		msg("Cannot open %s\n", disk);
2451423Sroot 		Exit(X_ABORT);
2461423Sroot 	}
2471423Sroot 	esize = 0;
2485328Smckusic 	sblock = (struct fs *)buf;
2495328Smckusic 	sync();
25030560Smckusick 	bread(SBOFF, sblock, SBSIZE);
25146586Storek 	if (sblock->fs_magic != FS_MAGIC)
25246586Storek 		quit("bad sblock magic number\n");
25330560Smckusick 	dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1);
25446586Storek 	dev_bshift = ffs(dev_bsize) - 1;
25546586Storek 	if (dev_bsize != (1 << dev_bshift))
25646586Storek 		quit("dev_bsize (%d) is not a power of 2", dev_bsize);
25746586Storek 	tp_bshift = ffs(TP_BSIZE) - 1;
25846586Storek 	if (TP_BSIZE != (1 << tp_bshift))
25946586Storek 		quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE);
2605328Smckusic 	msiz = roundup(howmany(sblock->fs_ipg * sblock->fs_ncg, NBBY),
2615328Smckusic 		TP_BSIZE);
2625328Smckusic 	clrmap = (char *)calloc(msiz, sizeof(char));
2635328Smckusic 	dirmap = (char *)calloc(msiz, sizeof(char));
2645328Smckusic 	nodmap = (char *)calloc(msiz, sizeof(char));
2651423Sroot 
26625797Smckusick 	anydskipped = 0;
2671423Sroot 	msg("mapping (Pass I) [regular files]\n");
2685328Smckusic 	pass(mark, (char *)NULL);		/* mark updates esize */
2691423Sroot 
27025797Smckusick 	if (anydskipped) {
27125797Smckusick 		do {
27225797Smckusick 			msg("mapping (Pass II) [directories]\n");
27325797Smckusick 			nadded = 0;
27425797Smckusick 			pass(add, dirmap);
27546586Storek 		} while (nadded);
27625797Smckusick 	} else				/* keep the operators happy */
2771423Sroot 		msg("mapping (Pass II) [directories]\n");
2781423Sroot 
2791423Sroot 	bmapest(clrmap);
2801423Sroot 	bmapest(nodmap);
2811423Sroot 
282*46614Smckusick 	if (pipeout)
283*46614Smckusick 		esize += 10;	/* 10 trailer blocks */
284*46614Smckusick 	else {
285*46614Smckusick 		if (blocksperfile)
286*46614Smckusick 			fetapes = esize / blocksperfile;
287*46614Smckusick 		else if (cartridge) {
288*46614Smckusick 			/* Estimate number of tapes, assuming streaming stops at
289*46614Smckusick 			   the end of each block written, and not in mid-block.
290*46614Smckusick 			   Assume no erroneous blocks; this can be compensated
291*46614Smckusick 			   for with an artificially low tape size. */
292*46614Smckusick 			fetapes =
293*46614Smckusick 			(	  esize		/* blocks */
294*46614Smckusick 				* TP_BSIZE	/* bytes/block */
295*46614Smckusick 				* (1.0/density)	/* 0.1" / byte */
296*46614Smckusick 			  +
297*46614Smckusick 				  esize		/* blocks */
298*46614Smckusick 				* (1.0/ntrec)	/* streaming-stops per block */
299*46614Smckusick 				* 15.48		/* 0.1" / streaming-stop */
300*46614Smckusick 			) * (1.0 / tsize );	/* tape / 0.1" */
301*46614Smckusick 		} else {
302*46614Smckusick 			/* Estimate number of tapes, for old fashioned 9-track
303*46614Smckusick 			   tape */
304*46614Smckusick 			int tenthsperirg = (density == 625) ? 3 : 7;
305*46614Smckusick 			fetapes =
306*46614Smckusick 			(	  esize		/* blocks */
307*46614Smckusick 				* TP_BSIZE	/* bytes / block */
308*46614Smckusick 				* (1.0/density)	/* 0.1" / byte */
309*46614Smckusick 			  +
310*46614Smckusick 				  esize		/* blocks */
311*46614Smckusick 				* (1.0/ntrec)	/* IRG's / block */
312*46614Smckusick 				* tenthsperirg	/* 0.1" / IRG */
313*46614Smckusick 			) * (1.0 / tsize );	/* tape / 0.1" */
314*46614Smckusick 		}
315*46614Smckusick 		etapes = fetapes;		/* truncating assignment */
316*46614Smckusick 		etapes++;
317*46614Smckusick 		/* count the nodemap on each additional tape */
318*46614Smckusick 		for (i = 1; i < etapes; i++)
319*46614Smckusick 			bmapest(nodmap);
320*46614Smckusick 		esize += i + 10;	/* headers + 10 trailer blocks */
32110910Ssam 	}
322*46614Smckusick 	if (pipeout)
323*46614Smckusick 		msg("estimated %ld tape blocks.\n", esize);
324*46614Smckusick 	else
325*46614Smckusick 		msg("estimated %ld tape blocks on %3.2f tape(s).\n",
326*46614Smckusick 		    esize, fetapes);
3271423Sroot 
32810910Ssam 	alloctape();			/* Allocate tape buffer */
32910910Ssam 
3301423Sroot 	otape();			/* bitmap is the first to tape write */
3311423Sroot 	time(&(tstart_writing));
3321423Sroot 	bitmap(clrmap, TS_CLRI);
3331423Sroot 
3341423Sroot 	msg("dumping (Pass III) [directories]\n");
33517234Smckusick  	pass(dirdump, dirmap);
3361423Sroot 
3371423Sroot 	msg("dumping (Pass IV) [regular files]\n");
3381423Sroot 	pass(dump, nodmap);
3391423Sroot 
3401423Sroot 	spcl.c_type = TS_END;
3416882Ssam #ifndef RDUMP
34210910Ssam 	for(i=0; i<ntrec; i++)
3431423Sroot 		spclrec();
3446882Ssam #endif
345*46614Smckusick 	if (pipeout)
346*46614Smckusick 		msg("DUMP: %ld tape blocks\n",spcl.c_tapea);
347*46614Smckusick 	else
348*46614Smckusick 		msg("DUMP: %ld tape blocks on %d volumes(s)\n",
349*46614Smckusick 		    spcl.c_tapea, spcl.c_volume);
3501423Sroot 	msg("DUMP IS DONE\n");
3511423Sroot 
3521423Sroot 	putitime();
3536882Ssam #ifndef RDUMP
35412331Smckusick 	if (!pipeout) {
35512331Smckusick 		close(to);
35646239Storek 		trewind();
35712331Smckusick 	}
3586882Ssam #else
3596882Ssam 	tflush(1);
36046239Storek 	trewind();
3616882Ssam #endif
3621423Sroot 	broadcast("DUMP IS DONE!\7\7\n");
3631423Sroot 	Exit(X_FINOK);
36446586Storek 	/* NOTREACHED */
3651423Sroot }
3661423Sroot 
36746586Storek void
3681423Sroot sigAbort()
3691423Sroot {
37046586Storek 	if (pipeout)
37146586Storek 		quit("Unknown signal, cannot recover\n");
3721423Sroot 	msg("Rewriting attempted as response to unknown signal.\n");
3731423Sroot 	fflush(stderr);
3741423Sroot 	fflush(stdout);
3751423Sroot 	close_rewind();
3761423Sroot 	exit(X_REWRITE);
3771423Sroot }
3781423Sroot 
37946586Storek void	sighup(){	msg("SIGHUP()  try rewriting\n"); sigAbort();}
38046586Storek void	sigtrap(){	msg("SIGTRAP()  try rewriting\n"); sigAbort();}
38146586Storek void	sigfpe(){	msg("SIGFPE()  try rewriting\n"); sigAbort();}
38246586Storek void	sigbus(){	msg("SIGBUS()  try rewriting\n"); sigAbort();}
38346586Storek void	sigsegv(){	msg("SIGSEGV()  ABORTING!\n"); abort();}
38446586Storek void	sigalrm(){	msg("SIGALRM()  try rewriting\n"); sigAbort();}
38546586Storek void	sigterm(){	msg("SIGTERM()  try rewriting\n"); sigAbort();}
38646586Storek 
38746586Storek char *
38846586Storek rawname(cp)
3891423Sroot 	char *cp;
3901423Sroot {
3911423Sroot 	static char rawbuf[32];
3924608Smckusic 	char *rindex();
3931423Sroot 	char *dp = rindex(cp, '/');
3941423Sroot 
3951423Sroot 	if (dp == 0)
3961423Sroot 		return (0);
3971423Sroot 	*dp = 0;
3981423Sroot 	strcpy(rawbuf, cp);
3991423Sroot 	*dp = '/';
4001423Sroot 	strcat(rawbuf, "/r");
4011423Sroot 	strcat(rawbuf, dp+1);
4021423Sroot 	return (rawbuf);
4031423Sroot }
404