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