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