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
main(argc,argv)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
sighup()358 int sighup(){ msg("SIGHUP() try rewriting\n"); sigAbort();}
sigtrap()359 int sigtrap(){ msg("SIGTRAP() try rewriting\n"); sigAbort();}
sigfpe()360 int sigfpe(){ msg("SIGFPE() try rewriting\n"); sigAbort();}
sigbus()361 int sigbus(){ msg("SIGBUS() try rewriting\n"); sigAbort();}
sigsegv()362 int sigsegv(){ msg("SIGSEGV() ABORTING!\n"); abort();}
sigalrm()363 int sigalrm(){ msg("SIGALRM() try rewriting\n"); sigAbort();}
sigterm()364 int sigterm(){ msg("SIGTERM() try rewriting\n"); sigAbort();}
365
sigAbort()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
rawname(cp)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