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