xref: /csrg-svn/sbin/dump/main.c (revision 37266)
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*37266Sbostic static char sccsid[] = "@(#)main.c	5.7 (Berkeley) 04/02/89";
922037Sdist #endif not lint
1022037Sdist 
111423Sroot #include "dump.h"
12*37266Sbostic #include "pathnames.h"
131423Sroot 
141423Sroot int	notify = 0;	/* notify operator flag */
151423Sroot int	blockswritten = 0;	/* number of blocks written on current tape */
161423Sroot int	tapeno = 0;	/* current tape number */
1710910Ssam int	density = 0;	/* density in bytes/0.1" */
1810910Ssam int	ntrec = NTREC;	/* # tape blocks in each tape record */
1910910Ssam int	cartridge = 0;	/* Assume non-cartridge tape */
2030560Smckusick long	dev_bsize = 1;	/* recalculated below */
216882Ssam #ifdef RDUMP
226882Ssam char	*host;
236882Ssam #endif
2425797Smckusick int	anydskipped;	/* set true in mark() if any directories are skipped */
2525797Smckusick 			/* this lets us avoid map pass 2 in some cases */
261423Sroot 
271423Sroot main(argc, argv)
281423Sroot 	int	argc;
291423Sroot 	char	*argv[];
301423Sroot {
311423Sroot 	char		*arg;
3218494Smckusick 	int		bflag = 0, i;
331423Sroot 	float		fetapes;
341423Sroot 	register	struct	fstab	*dt;
351423Sroot 
361423Sroot 	time(&(spcl.c_date));
371423Sroot 
3810910Ssam 	tsize = 0;	/* Default later, based on 'c' option for cart tapes */
391423Sroot 	tape = TAPE;
401423Sroot 	disk = DISK;
41*37266Sbostic 	increm = _PATH_DUMPDATES;
42*37266Sbostic 	temp = _PATH_DTMP;
435328Smckusic 	if (TP_BSIZE / DEV_BSIZE == 0 || TP_BSIZE % DEV_BSIZE != 0) {
445328Smckusic 		msg("TP_BSIZE must be a multiple of DEV_BSIZE\n");
455328Smckusic 		dumpabort();
465328Smckusic 	}
471423Sroot 	incno = '9';
481423Sroot 	uflag = 0;
491423Sroot 	arg = "u";
501423Sroot 	if(argc > 1) {
511423Sroot 		argv++;
521423Sroot 		argc--;
531423Sroot 		arg = *argv;
541423Sroot 		if (*arg == '-')
551423Sroot 			argc++;
561423Sroot 	}
571423Sroot 	while(*arg)
581423Sroot 	switch (*arg++) {
591463Sroot 	case 'w':
601463Sroot 		lastdump('w');		/* tell us only what has to be done */
611463Sroot 		exit(0);
621463Sroot 		break;
631423Sroot 	case 'W':			/* what to do */
641463Sroot 		lastdump('W');		/* tell us the current state of what has been done */
651423Sroot 		exit(0);		/* do nothing else */
661423Sroot 		break;
671423Sroot 
681423Sroot 	case 'f':			/* output file */
691423Sroot 		if(argc > 1) {
701423Sroot 			argv++;
711423Sroot 			argc--;
721423Sroot 			tape = *argv;
731423Sroot 		}
741423Sroot 		break;
751423Sroot 
761423Sroot 	case 'd':			/* density, in bits per inch */
771423Sroot 		if (argc > 1) {
781423Sroot 			argv++;
791423Sroot 			argc--;
801423Sroot 			density = atoi(*argv) / 10;
8118494Smckusick 			if (density >= 625 && !bflag)
8218494Smckusick 				ntrec = HIGHDENSITYTREC;
831423Sroot 		}
841423Sroot 		break;
851423Sroot 
861423Sroot 	case 's':			/* tape size, feet */
871423Sroot 		if(argc > 1) {
881423Sroot 			argv++;
891423Sroot 			argc--;
901423Sroot 			tsize = atol(*argv);
911423Sroot 			tsize *= 12L*10L;
921423Sroot 		}
931423Sroot 		break;
941423Sroot 
9510910Ssam 	case 'b':			/* blocks per tape write */
9610910Ssam 		if(argc > 1) {
9710910Ssam 			argv++;
9810910Ssam 			argc--;
9918494Smckusick 			bflag++;
10010910Ssam 			ntrec = atol(*argv);
10110910Ssam 		}
10210910Ssam 		break;
10310910Ssam 
10410910Ssam 	case 'c':			/* Tape is cart. not 9-track */
10510910Ssam 		cartridge++;
10610910Ssam 		break;
10710910Ssam 
1081423Sroot 	case '0':			/* dump level */
1091423Sroot 	case '1':
1101423Sroot 	case '2':
1111423Sroot 	case '3':
1121423Sroot 	case '4':
1131423Sroot 	case '5':
1141423Sroot 	case '6':
1151423Sroot 	case '7':
1161423Sroot 	case '8':
1171423Sroot 	case '9':
1181423Sroot 		incno = arg[-1];
1191423Sroot 		break;
1201423Sroot 
1211423Sroot 	case 'u':			/* update /etc/dumpdates */
1221423Sroot 		uflag++;
1231423Sroot 		break;
1241423Sroot 
1251423Sroot 	case 'n':			/* notify operators */
1261423Sroot 		notify++;
1271423Sroot 		break;
1281423Sroot 
1291423Sroot 	default:
13012331Smckusick 		fprintf(stderr, "bad key '%c%'\n", arg[-1]);
1311423Sroot 		Exit(X_ABORT);
1321423Sroot 	}
1331423Sroot 	if(argc > 1) {
1341423Sroot 		argv++;
1351423Sroot 		argc--;
1361423Sroot 		disk = *argv;
1371423Sroot 	}
13812331Smckusick 	if (strcmp(tape, "-") == 0) {
13912331Smckusick 		pipeout++;
14012331Smckusick 		tape = "standard output";
14112331Smckusick 	}
14210910Ssam 
14310910Ssam 	/*
14410910Ssam 	 * Determine how to default tape size and density
14510910Ssam 	 *
14610910Ssam 	 *         	density				tape size
14710910Ssam 	 * 9-track	1600 bpi (160 bytes/.1")	2300 ft.
14810910Ssam 	 * 9-track	6250 bpi (625 bytes/.1")	2300 ft.
14916251Smckusick  	 * cartridge	8000 bpi (100 bytes/.1")	1700 ft. (450*4 - slop)
15010910Ssam 	 */
15110910Ssam 	if (density == 0)
15210910Ssam 		density = cartridge ? 100 : 160;
15310910Ssam 	if (tsize == 0)
15416251Smckusick  		tsize = cartridge ? 1700L*120L : 2300L*120L;
15510910Ssam 
1566886Ssam #ifdef RDUMP
1576886Ssam 	{ char *index();
1586886Ssam 	  host = tape;
1596886Ssam 	  tape = index(host, ':');
1606886Ssam 	  if (tape == 0) {
16128642Smckusick 		msg("need keyletter ``f'' and device ``host:tape''\n");
1626886Ssam 		exit(1);
1636886Ssam 	  }
1646886Ssam 	  *tape++ = 0;
1656886Ssam 	  if (rmthost(host) == 0)
1666886Ssam 		exit(X_ABORT);
1676886Ssam 	}
16828860Smckusick 	setuid(getuid());	/* rmthost() is the only reason to be setuid */
1696886Ssam #endif
1701423Sroot 	if (signal(SIGHUP, sighup) == SIG_IGN)
1711423Sroot 		signal(SIGHUP, SIG_IGN);
1721423Sroot 	if (signal(SIGTRAP, sigtrap) == SIG_IGN)
1731423Sroot 		signal(SIGTRAP, SIG_IGN);
1741423Sroot 	if (signal(SIGFPE, sigfpe) == SIG_IGN)
1751423Sroot 		signal(SIGFPE, SIG_IGN);
1761423Sroot 	if (signal(SIGBUS, sigbus) == SIG_IGN)
1771423Sroot 		signal(SIGBUS, SIG_IGN);
1781423Sroot 	if (signal(SIGSEGV, sigsegv) == SIG_IGN)
1791423Sroot 		signal(SIGSEGV, SIG_IGN);
1801423Sroot 	if (signal(SIGTERM, sigterm) == SIG_IGN)
1811423Sroot 		signal(SIGTERM, SIG_IGN);
1821423Sroot 
1831423Sroot 
1841423Sroot 	if (signal(SIGINT, interrupt) == SIG_IGN)
1851423Sroot 		signal(SIGINT, SIG_IGN);
1861423Sroot 
1871423Sroot 	set_operators();	/* /etc/group snarfed */
1881423Sroot 	getfstab();		/* /etc/fstab snarfed */
1891423Sroot 	/*
1901423Sroot 	 *	disk can be either the full special file name,
1911423Sroot 	 *	the suffix of the special file name,
1921423Sroot 	 *	the special name missing the leading '/',
1931423Sroot 	 *	the file system name with or without the leading '/'.
1941423Sroot 	 */
1951423Sroot 	dt = fstabsearch(disk);
19629900Smckusick 	if (dt != 0) {
1971423Sroot 		disk = rawname(dt->fs_spec);
19829900Smckusick 		strncpy(spcl.c_dev, dt->fs_spec, NAMELEN);
19929900Smckusick 		strncpy(spcl.c_filesys, dt->fs_file, NAMELEN);
20029900Smckusick 	} else {
20129900Smckusick 		strncpy(spcl.c_dev, disk, NAMELEN);
20229900Smckusick 		strncpy(spcl.c_filesys, "an unlisted file system", NAMELEN);
20329900Smckusick 	}
20429900Smckusick 	strcpy(spcl.c_label, "none");
20529900Smckusick 	gethostname(spcl.c_host, NAMELEN);
20629900Smckusick 	spcl.c_level = incno - '0';
20729900Smckusick 	spcl.c_type = TS_TAPE;
2081423Sroot 	getitime();		/* /etc/dumpdates snarfed */
2091423Sroot 
2101423Sroot 	msg("Date of this level %c dump: %s\n", incno, prdate(spcl.c_date));
21112948Smckusick  	msg("Date of last level %c dump: %s\n",
21212948Smckusick 		lastincno, prdate(spcl.c_ddate));
2131423Sroot 	msg("Dumping %s ", disk);
2141423Sroot 	if (dt != 0)
2151423Sroot 		msgtail("(%s) ", dt->fs_file);
2168506Smckusick #ifdef RDUMP
2178506Smckusick 	msgtail("to %s on host %s\n", tape, host);
2188506Smckusick #else
2198371Smckusick 	msgtail("to %s\n", tape);
2206882Ssam #endif
2211423Sroot 
2221423Sroot 	fi = open(disk, 0);
2231423Sroot 	if (fi < 0) {
2241423Sroot 		msg("Cannot open %s\n", disk);
2251423Sroot 		Exit(X_ABORT);
2261423Sroot 	}
2271423Sroot 	esize = 0;
2285328Smckusic 	sblock = (struct fs *)buf;
2295328Smckusic 	sync();
23030560Smckusick 	bread(SBOFF, sblock, SBSIZE);
2315328Smckusic 	if (sblock->fs_magic != FS_MAGIC) {
2325328Smckusic 		msg("bad sblock magic number\n");
2335328Smckusic 		dumpabort();
2345328Smckusic 	}
23530560Smckusick 	dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1);
2365328Smckusic 	msiz = roundup(howmany(sblock->fs_ipg * sblock->fs_ncg, NBBY),
2375328Smckusic 		TP_BSIZE);
2385328Smckusic 	clrmap = (char *)calloc(msiz, sizeof(char));
2395328Smckusic 	dirmap = (char *)calloc(msiz, sizeof(char));
2405328Smckusic 	nodmap = (char *)calloc(msiz, sizeof(char));
2411423Sroot 
24225797Smckusick 	anydskipped = 0;
2431423Sroot 	msg("mapping (Pass I) [regular files]\n");
2445328Smckusic 	pass(mark, (char *)NULL);		/* mark updates esize */
2451423Sroot 
24625797Smckusick 	if (anydskipped) {
24725797Smckusick 		do {
24825797Smckusick 			msg("mapping (Pass II) [directories]\n");
24925797Smckusick 			nadded = 0;
25025797Smckusick 			pass(add, dirmap);
25125797Smckusick 		} while(nadded);
25225797Smckusick 	} else				/* keep the operators happy */
2531423Sroot 		msg("mapping (Pass II) [directories]\n");
2541423Sroot 
2551423Sroot 	bmapest(clrmap);
2561423Sroot 	bmapest(nodmap);
2571423Sroot 
25810910Ssam 	if (cartridge) {
25910910Ssam 		/* Estimate number of tapes, assuming streaming stops at
26010910Ssam 		   the end of each block written, and not in mid-block.
26110910Ssam 		   Assume no erroneous blocks; this can be compensated for
26210910Ssam 		   with an artificially low tape size. */
26310910Ssam 		fetapes =
2645328Smckusic 		(	  esize		/* blocks */
26510910Ssam 			* TP_BSIZE	/* bytes/block */
26610910Ssam 			* (1.0/density)	/* 0.1" / byte */
26710910Ssam 		  +
26810910Ssam 			  esize		/* blocks */
26910910Ssam 			* (1.0/ntrec)	/* streaming-stops per block */
27010910Ssam 			* 15.48		/* 0.1" / streaming-stop */
27110910Ssam 		) * (1.0 / tsize );	/* tape / 0.1" */
27210910Ssam 	} else {
27310910Ssam 		/* Estimate number of tapes, for old fashioned 9-track tape */
27410910Ssam 		int tenthsperirg = (density == 625) ? 3 : 7;
27510910Ssam 		fetapes =
27610910Ssam 		(	  esize		/* blocks */
2775328Smckusic 			* TP_BSIZE	/* bytes / block */
2785328Smckusic 			* (1.0/density)	/* 0.1" / byte */
2791423Sroot 		  +
2805328Smckusic 			  esize		/* blocks */
28110910Ssam 			* (1.0/ntrec)	/* IRG's / block */
28210910Ssam 			* tenthsperirg	/* 0.1" / IRG */
28310910Ssam 		) * (1.0 / tsize );	/* tape / 0.1" */
28410910Ssam 	}
2851423Sroot 	etapes = fetapes;		/* truncating assignment */
2861423Sroot 	etapes++;
2875328Smckusic 	/* count the nodemap on each additional tape */
2885328Smckusic 	for (i = 1; i < etapes; i++)
2895328Smckusic 		bmapest(nodmap);
2905328Smckusic 	esize += i + 10;	/* headers + 10 trailer blocks */
2911423Sroot 	msg("estimated %ld tape blocks on %3.2f tape(s).\n", esize, fetapes);
2921423Sroot 
29310910Ssam 	alloctape();			/* Allocate tape buffer */
29410910Ssam 
2951423Sroot 	otape();			/* bitmap is the first to tape write */
2961423Sroot 	time(&(tstart_writing));
2971423Sroot 	bitmap(clrmap, TS_CLRI);
2981423Sroot 
2991423Sroot 	msg("dumping (Pass III) [directories]\n");
30017234Smckusick  	pass(dirdump, dirmap);
3011423Sroot 
3021423Sroot 	msg("dumping (Pass IV) [regular files]\n");
3031423Sroot 	pass(dump, nodmap);
3041423Sroot 
3051423Sroot 	spcl.c_type = TS_END;
3066882Ssam #ifndef RDUMP
30710910Ssam 	for(i=0; i<ntrec; i++)
3081423Sroot 		spclrec();
3096882Ssam #endif
3101423Sroot 	msg("DUMP: %ld tape blocks on %d tape(s)\n",spcl.c_tapea,spcl.c_volume);
3111423Sroot 	msg("DUMP IS DONE\n");
3121423Sroot 
3131423Sroot 	putitime();
3146882Ssam #ifndef RDUMP
31512331Smckusick 	if (!pipeout) {
31612331Smckusick 		close(to);
31712331Smckusick 		rewind();
31812331Smckusick 	}
3196882Ssam #else
3206882Ssam 	tflush(1);
32112331Smckusick 	rewind();
3226882Ssam #endif
3231423Sroot 	broadcast("DUMP IS DONE!\7\7\n");
3241423Sroot 	Exit(X_FINOK);
3251423Sroot }
3261423Sroot 
3271423Sroot int	sighup(){	msg("SIGHUP()  try rewriting\n"); sigAbort();}
3281423Sroot int	sigtrap(){	msg("SIGTRAP()  try rewriting\n"); sigAbort();}
3291423Sroot int	sigfpe(){	msg("SIGFPE()  try rewriting\n"); sigAbort();}
3301423Sroot int	sigbus(){	msg("SIGBUS()  try rewriting\n"); sigAbort();}
3311423Sroot int	sigsegv(){	msg("SIGSEGV()  ABORTING!\n"); abort();}
3321423Sroot int	sigalrm(){	msg("SIGALRM()  try rewriting\n"); sigAbort();}
3331423Sroot int	sigterm(){	msg("SIGTERM()  try rewriting\n"); sigAbort();}
3341423Sroot 
3351423Sroot sigAbort()
3361423Sroot {
33712331Smckusick 	if (pipeout) {
33812331Smckusick 		msg("Unknown signal, cannot recover\n");
33912331Smckusick 		dumpabort();
34012331Smckusick 	}
3411423Sroot 	msg("Rewriting attempted as response to unknown signal.\n");
3421423Sroot 	fflush(stderr);
3431423Sroot 	fflush(stdout);
3441423Sroot 	close_rewind();
3451423Sroot 	exit(X_REWRITE);
3461423Sroot }
3471423Sroot 
3481423Sroot char *rawname(cp)
3491423Sroot 	char *cp;
3501423Sroot {
3511423Sroot 	static char rawbuf[32];
3524608Smckusic 	char *rindex();
3531423Sroot 	char *dp = rindex(cp, '/');
3541423Sroot 
3551423Sroot 	if (dp == 0)
3561423Sroot 		return (0);
3571423Sroot 	*dp = 0;
3581423Sroot 	strcpy(rawbuf, cp);
3591423Sroot 	*dp = '/';
3601423Sroot 	strcat(rawbuf, "/r");
3611423Sroot 	strcat(rawbuf, dp+1);
3621423Sroot 	return (rawbuf);
3631423Sroot }
364