xref: /original-bsd/sbin/dump/main.c (revision 2301fdfb)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)main.c	5.6 (Berkeley) 02/23/87";
9 #endif not lint
10 
11 #include "dump.h"
12 
13 int	notify = 0;	/* notify operator flag */
14 int	blockswritten = 0;	/* number of blocks written on current tape */
15 int	tapeno = 0;	/* current tape number */
16 int	density = 0;	/* density in bytes/0.1" */
17 int	ntrec = NTREC;	/* # tape blocks in each tape record */
18 int	cartridge = 0;	/* Assume non-cartridge tape */
19 long	dev_bsize = 1;	/* recalculated below */
20 #ifdef RDUMP
21 char	*host;
22 #endif
23 int	anydskipped;	/* set true in mark() if any directories are skipped */
24 			/* this lets us avoid map pass 2 in some cases */
25 
26 main(argc, argv)
27 	int	argc;
28 	char	*argv[];
29 {
30 	char		*arg;
31 	int		bflag = 0, i;
32 	float		fetapes;
33 	register	struct	fstab	*dt;
34 
35 	time(&(spcl.c_date));
36 
37 	tsize = 0;	/* Default later, based on 'c' option for cart tapes */
38 	tape = TAPE;
39 	disk = DISK;
40 	increm = NINCREM;
41 	temp = TEMP;
42 	if (TP_BSIZE / DEV_BSIZE == 0 || TP_BSIZE % DEV_BSIZE != 0) {
43 		msg("TP_BSIZE must be a multiple of DEV_BSIZE\n");
44 		dumpabort();
45 	}
46 	incno = '9';
47 	uflag = 0;
48 	arg = "u";
49 	if(argc > 1) {
50 		argv++;
51 		argc--;
52 		arg = *argv;
53 		if (*arg == '-')
54 			argc++;
55 	}
56 	while(*arg)
57 	switch (*arg++) {
58 	case 'w':
59 		lastdump('w');		/* tell us only what has to be done */
60 		exit(0);
61 		break;
62 	case 'W':			/* what to do */
63 		lastdump('W');		/* tell us the current state of what has been done */
64 		exit(0);		/* do nothing else */
65 		break;
66 
67 	case 'f':			/* output file */
68 		if(argc > 1) {
69 			argv++;
70 			argc--;
71 			tape = *argv;
72 		}
73 		break;
74 
75 	case 'd':			/* density, in bits per inch */
76 		if (argc > 1) {
77 			argv++;
78 			argc--;
79 			density = atoi(*argv) / 10;
80 			if (density >= 625 && !bflag)
81 				ntrec = HIGHDENSITYTREC;
82 		}
83 		break;
84 
85 	case 's':			/* tape size, feet */
86 		if(argc > 1) {
87 			argv++;
88 			argc--;
89 			tsize = atol(*argv);
90 			tsize *= 12L*10L;
91 		}
92 		break;
93 
94 	case 'b':			/* blocks per tape write */
95 		if(argc > 1) {
96 			argv++;
97 			argc--;
98 			bflag++;
99 			ntrec = atol(*argv);
100 		}
101 		break;
102 
103 	case 'c':			/* Tape is cart. not 9-track */
104 		cartridge++;
105 		break;
106 
107 	case '0':			/* dump level */
108 	case '1':
109 	case '2':
110 	case '3':
111 	case '4':
112 	case '5':
113 	case '6':
114 	case '7':
115 	case '8':
116 	case '9':
117 		incno = arg[-1];
118 		break;
119 
120 	case 'u':			/* update /etc/dumpdates */
121 		uflag++;
122 		break;
123 
124 	case 'n':			/* notify operators */
125 		notify++;
126 		break;
127 
128 	default:
129 		fprintf(stderr, "bad key '%c%'\n", arg[-1]);
130 		Exit(X_ABORT);
131 	}
132 	if(argc > 1) {
133 		argv++;
134 		argc--;
135 		disk = *argv;
136 	}
137 	if (strcmp(tape, "-") == 0) {
138 		pipeout++;
139 		tape = "standard output";
140 	}
141 
142 	/*
143 	 * Determine how to default tape size and density
144 	 *
145 	 *         	density				tape size
146 	 * 9-track	1600 bpi (160 bytes/.1")	2300 ft.
147 	 * 9-track	6250 bpi (625 bytes/.1")	2300 ft.
148  	 * cartridge	8000 bpi (100 bytes/.1")	1700 ft. (450*4 - slop)
149 	 */
150 	if (density == 0)
151 		density = cartridge ? 100 : 160;
152 	if (tsize == 0)
153  		tsize = cartridge ? 1700L*120L : 2300L*120L;
154 
155 #ifdef RDUMP
156 	{ char *index();
157 	  host = tape;
158 	  tape = index(host, ':');
159 	  if (tape == 0) {
160 		msg("need keyletter ``f'' and device ``host:tape''\n");
161 		exit(1);
162 	  }
163 	  *tape++ = 0;
164 	  if (rmthost(host) == 0)
165 		exit(X_ABORT);
166 	}
167 	setuid(getuid());	/* rmthost() is the only reason to be setuid */
168 #endif
169 	if (signal(SIGHUP, sighup) == SIG_IGN)
170 		signal(SIGHUP, SIG_IGN);
171 	if (signal(SIGTRAP, sigtrap) == SIG_IGN)
172 		signal(SIGTRAP, SIG_IGN);
173 	if (signal(SIGFPE, sigfpe) == SIG_IGN)
174 		signal(SIGFPE, SIG_IGN);
175 	if (signal(SIGBUS, sigbus) == SIG_IGN)
176 		signal(SIGBUS, SIG_IGN);
177 	if (signal(SIGSEGV, sigsegv) == SIG_IGN)
178 		signal(SIGSEGV, SIG_IGN);
179 	if (signal(SIGTERM, sigterm) == SIG_IGN)
180 		signal(SIGTERM, SIG_IGN);
181 
182 
183 	if (signal(SIGINT, interrupt) == SIG_IGN)
184 		signal(SIGINT, SIG_IGN);
185 
186 	set_operators();	/* /etc/group snarfed */
187 	getfstab();		/* /etc/fstab snarfed */
188 	/*
189 	 *	disk can be either the full special file name,
190 	 *	the suffix of the special file name,
191 	 *	the special name missing the leading '/',
192 	 *	the file system name with or without the leading '/'.
193 	 */
194 	dt = fstabsearch(disk);
195 	if (dt != 0) {
196 		disk = rawname(dt->fs_spec);
197 		strncpy(spcl.c_dev, dt->fs_spec, NAMELEN);
198 		strncpy(spcl.c_filesys, dt->fs_file, NAMELEN);
199 	} else {
200 		strncpy(spcl.c_dev, disk, NAMELEN);
201 		strncpy(spcl.c_filesys, "an unlisted file system", NAMELEN);
202 	}
203 	strcpy(spcl.c_label, "none");
204 	gethostname(spcl.c_host, NAMELEN);
205 	spcl.c_level = incno - '0';
206 	spcl.c_type = TS_TAPE;
207 	getitime();		/* /etc/dumpdates snarfed */
208 
209 	msg("Date of this level %c dump: %s\n", incno, prdate(spcl.c_date));
210  	msg("Date of last level %c dump: %s\n",
211 		lastincno, prdate(spcl.c_ddate));
212 	msg("Dumping %s ", disk);
213 	if (dt != 0)
214 		msgtail("(%s) ", dt->fs_file);
215 #ifdef RDUMP
216 	msgtail("to %s on host %s\n", tape, host);
217 #else
218 	msgtail("to %s\n", tape);
219 #endif
220 
221 	fi = open(disk, 0);
222 	if (fi < 0) {
223 		msg("Cannot open %s\n", disk);
224 		Exit(X_ABORT);
225 	}
226 	esize = 0;
227 	sblock = (struct fs *)buf;
228 	sync();
229 	bread(SBOFF, sblock, SBSIZE);
230 	if (sblock->fs_magic != FS_MAGIC) {
231 		msg("bad sblock magic number\n");
232 		dumpabort();
233 	}
234 	dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1);
235 	msiz = roundup(howmany(sblock->fs_ipg * sblock->fs_ncg, NBBY),
236 		TP_BSIZE);
237 	clrmap = (char *)calloc(msiz, sizeof(char));
238 	dirmap = (char *)calloc(msiz, sizeof(char));
239 	nodmap = (char *)calloc(msiz, sizeof(char));
240 
241 	anydskipped = 0;
242 	msg("mapping (Pass I) [regular files]\n");
243 	pass(mark, (char *)NULL);		/* mark updates esize */
244 
245 	if (anydskipped) {
246 		do {
247 			msg("mapping (Pass II) [directories]\n");
248 			nadded = 0;
249 			pass(add, dirmap);
250 		} while(nadded);
251 	} else				/* keep the operators happy */
252 		msg("mapping (Pass II) [directories]\n");
253 
254 	bmapest(clrmap);
255 	bmapest(nodmap);
256 
257 	if (cartridge) {
258 		/* Estimate number of tapes, assuming streaming stops at
259 		   the end of each block written, and not in mid-block.
260 		   Assume no erroneous blocks; this can be compensated for
261 		   with an artificially low tape size. */
262 		fetapes =
263 		(	  esize		/* blocks */
264 			* TP_BSIZE	/* bytes/block */
265 			* (1.0/density)	/* 0.1" / byte */
266 		  +
267 			  esize		/* blocks */
268 			* (1.0/ntrec)	/* streaming-stops per block */
269 			* 15.48		/* 0.1" / streaming-stop */
270 		) * (1.0 / tsize );	/* tape / 0.1" */
271 	} else {
272 		/* Estimate number of tapes, for old fashioned 9-track tape */
273 		int tenthsperirg = (density == 625) ? 3 : 7;
274 		fetapes =
275 		(	  esize		/* blocks */
276 			* TP_BSIZE	/* bytes / block */
277 			* (1.0/density)	/* 0.1" / byte */
278 		  +
279 			  esize		/* blocks */
280 			* (1.0/ntrec)	/* IRG's / block */
281 			* tenthsperirg	/* 0.1" / IRG */
282 		) * (1.0 / tsize );	/* tape / 0.1" */
283 	}
284 	etapes = fetapes;		/* truncating assignment */
285 	etapes++;
286 	/* count the nodemap on each additional tape */
287 	for (i = 1; i < etapes; i++)
288 		bmapest(nodmap);
289 	esize += i + 10;	/* headers + 10 trailer blocks */
290 	msg("estimated %ld tape blocks on %3.2f tape(s).\n", esize, fetapes);
291 
292 	alloctape();			/* Allocate tape buffer */
293 
294 	otape();			/* bitmap is the first to tape write */
295 	time(&(tstart_writing));
296 	bitmap(clrmap, TS_CLRI);
297 
298 	msg("dumping (Pass III) [directories]\n");
299  	pass(dirdump, dirmap);
300 
301 	msg("dumping (Pass IV) [regular files]\n");
302 	pass(dump, nodmap);
303 
304 	spcl.c_type = TS_END;
305 #ifndef RDUMP
306 	for(i=0; i<ntrec; i++)
307 		spclrec();
308 #endif
309 	msg("DUMP: %ld tape blocks on %d tape(s)\n",spcl.c_tapea,spcl.c_volume);
310 	msg("DUMP IS DONE\n");
311 
312 	putitime();
313 #ifndef RDUMP
314 	if (!pipeout) {
315 		close(to);
316 		rewind();
317 	}
318 #else
319 	tflush(1);
320 	rewind();
321 #endif
322 	broadcast("DUMP IS DONE!\7\7\n");
323 	Exit(X_FINOK);
324 }
325 
326 int	sighup(){	msg("SIGHUP()  try rewriting\n"); sigAbort();}
327 int	sigtrap(){	msg("SIGTRAP()  try rewriting\n"); sigAbort();}
328 int	sigfpe(){	msg("SIGFPE()  try rewriting\n"); sigAbort();}
329 int	sigbus(){	msg("SIGBUS()  try rewriting\n"); sigAbort();}
330 int	sigsegv(){	msg("SIGSEGV()  ABORTING!\n"); abort();}
331 int	sigalrm(){	msg("SIGALRM()  try rewriting\n"); sigAbort();}
332 int	sigterm(){	msg("SIGTERM()  try rewriting\n"); sigAbort();}
333 
334 sigAbort()
335 {
336 	if (pipeout) {
337 		msg("Unknown signal, cannot recover\n");
338 		dumpabort();
339 	}
340 	msg("Rewriting attempted as response to unknown signal.\n");
341 	fflush(stderr);
342 	fflush(stdout);
343 	close_rewind();
344 	exit(X_REWRITE);
345 }
346 
347 char *rawname(cp)
348 	char *cp;
349 {
350 	static char rawbuf[32];
351 	char *rindex();
352 	char *dp = rindex(cp, '/');
353 
354 	if (dp == 0)
355 		return (0);
356 	*dp = 0;
357 	strcpy(rawbuf, cp);
358 	*dp = '/';
359 	strcat(rawbuf, "/r");
360 	strcat(rawbuf, dp+1);
361 	return (rawbuf);
362 }
363