122037Sdist /* 222037Sdist * Copyright (c) 1980 Regents of the University of California. 322037Sdist * All rights reserved. The Berkeley software License Agreement 422037Sdist * specifies the terms and conditions for redistribution. 522037Sdist */ 622037Sdist 722037Sdist #ifndef lint 8*46794Smckusick static char sccsid[] = "@(#)main.c 5.12 (Berkeley) 02/28/91"; 946586Storek #endif /* not lint */ 1022037Sdist 111423Sroot #include "dump.h" 1246586Storek #include <fcntl.h> 1337266Sbostic #include "pathnames.h" 141423Sroot 151423Sroot int notify = 0; /* notify operator flag */ 161423Sroot int blockswritten = 0; /* number of blocks written on current tape */ 171423Sroot int tapeno = 0; /* current tape number */ 1810910Ssam int density = 0; /* density in bytes/0.1" */ 1910910Ssam int ntrec = NTREC; /* # tape blocks in each tape record */ 2010910Ssam int cartridge = 0; /* Assume non-cartridge tape */ 2130560Smckusick long dev_bsize = 1; /* recalculated below */ 2246614Smckusick long blocksperfile; /* output blocks per file */ 236882Ssam #ifdef RDUMP 246882Ssam char *host; 2546586Storek int rmthost(); 266882Ssam #endif 271423Sroot 281423Sroot main(argc, argv) 29*46794Smckusick int argc; 30*46794Smckusick char *argv[]; 311423Sroot { 32*46794Smckusick register ino_t ino; 33*46794Smckusick register long bits; 34*46794Smckusick register struct dinode *dp; 35*46794Smckusick register struct fstab *dt; 36*46794Smckusick register char *map; 37*46794Smckusick register char *cp; 38*46794Smckusick int i, anydirskipped, bflag = 0; 39*46794Smckusick float fetapes; 40*46794Smckusick ino_t maxino; 411423Sroot 421423Sroot time(&(spcl.c_date)); 431423Sroot 4410910Ssam tsize = 0; /* Default later, based on 'c' option for cart tapes */ 4537946Sbostic tape = _PATH_DEFTAPE; 46*46794Smckusick dumpdates = _PATH_DUMPDATES; 4737266Sbostic temp = _PATH_DTMP; 4846586Storek if (TP_BSIZE / DEV_BSIZE == 0 || TP_BSIZE % DEV_BSIZE != 0) 4946586Storek quit("TP_BSIZE must be a multiple of DEV_BSIZE\n"); 50*46794Smckusick level = '0'; 51*46794Smckusick argv++; 52*46794Smckusick argc -= 2; 53*46794Smckusick for (cp = *argv++; *cp; cp++) { 54*46794Smckusick switch (*cp) { 55*46794Smckusick case '-': 56*46794Smckusick continue; 571423Sroot 58*46794Smckusick case 'w': 59*46794Smckusick lastdump('w'); /* tell us only what has to be done */ 60*46794Smckusick exit(0); 61*46794Smckusick 62*46794Smckusick case 'W': /* what to do */ 63*46794Smckusick lastdump('W'); /* tell us state of what is done */ 64*46794Smckusick exit(0); /* do nothing else */ 65*46794Smckusick 66*46794Smckusick case 'f': /* output file */ 67*46794Smckusick if (argc < 1) 68*46794Smckusick break; 69*46794Smckusick tape = *argv++; 701423Sroot argc--; 71*46794Smckusick continue; 721423Sroot 73*46794Smckusick case 'd': /* density, in bits per inch */ 74*46794Smckusick if (argc < 1) 75*46794Smckusick break; 76*46794Smckusick density = atoi(*argv) / 10; 77*46794Smckusick if (density < 1) { 78*46794Smckusick fprintf(stderr, "bad density \"%s\"\n", *argv); 79*46794Smckusick Exit(X_ABORT); 80*46794Smckusick } 81*46794Smckusick argc--; 821423Sroot argv++; 8318494Smckusick if (density >= 625 && !bflag) 8418494Smckusick ntrec = HIGHDENSITYTREC; 85*46794Smckusick continue; 861423Sroot 87*46794Smckusick case 's': /* tape size, feet */ 88*46794Smckusick if (argc < 1) 89*46794Smckusick break; 90*46794Smckusick tsize = atol(*argv); 91*46794Smckusick if (tsize < 1) { 92*46794Smckusick fprintf(stderr, "bad size \"%s\"\n", *argv); 93*46794Smckusick Exit(X_ABORT); 94*46794Smckusick } 95*46794Smckusick argc--; 961423Sroot argv++; 97*46794Smckusick tsize *= 12 * 10; 98*46794Smckusick continue; 991423Sroot 100*46794Smckusick case 'b': /* blocks per tape write */ 101*46794Smckusick if (argc < 1) 102*46794Smckusick break; 10318494Smckusick bflag++; 10410910Ssam ntrec = atol(*argv); 105*46794Smckusick if (ntrec < 1) { 106*46794Smckusick fprintf(stderr, "%s \"%s\"\n", 107*46794Smckusick "bad number of blocks per write ", *argv); 10846614Smckusick Exit(X_ABORT); 10946614Smckusick } 110*46794Smckusick argc--; 111*46794Smckusick argv++; 112*46794Smckusick continue; 11310910Ssam 114*46794Smckusick case 'B': /* blocks per output file */ 115*46794Smckusick if (argc < 1) 116*46794Smckusick break; 117*46794Smckusick blocksperfile = atol(*argv); 118*46794Smckusick if (blocksperfile < 1) { 119*46794Smckusick fprintf(stderr, "%s \"%s\"\n", 120*46794Smckusick "bad number of blocks per file ", *argv); 121*46794Smckusick Exit(X_ABORT); 122*46794Smckusick } 123*46794Smckusick argc--; 12446614Smckusick argv++; 125*46794Smckusick continue; 12646614Smckusick 127*46794Smckusick case 'c': /* Tape is cart. not 9-track */ 128*46794Smckusick cartridge++; 129*46794Smckusick continue; 13010910Ssam 131*46794Smckusick case '0': /* dump level */ 132*46794Smckusick case '1': 133*46794Smckusick case '2': 134*46794Smckusick case '3': 135*46794Smckusick case '4': 136*46794Smckusick case '5': 137*46794Smckusick case '6': 138*46794Smckusick case '7': 139*46794Smckusick case '8': 140*46794Smckusick case '9': 141*46794Smckusick level = *cp; 142*46794Smckusick continue; 1431423Sroot 144*46794Smckusick case 'u': /* update /etc/dumpdates */ 145*46794Smckusick uflag++; 146*46794Smckusick continue; 1471423Sroot 148*46794Smckusick case 'n': /* notify operators */ 149*46794Smckusick notify++; 150*46794Smckusick continue; 1511423Sroot 152*46794Smckusick default: 153*46794Smckusick fprintf(stderr, "bad key '%c'\n", *cp); 154*46794Smckusick Exit(X_ABORT); 155*46794Smckusick } 156*46794Smckusick fprintf(stderr, "missing argument to '%c'\n", *cp); 1571423Sroot Exit(X_ABORT); 1581423Sroot } 159*46794Smckusick if (argc < 1) { 160*46794Smckusick fprintf(stderr, "Must specify disk or filesystem\n"); 161*46794Smckusick Exit(X_ABORT); 162*46794Smckusick } else { 163*46794Smckusick disk = *argv++; 1641423Sroot argc--; 1651423Sroot } 166*46794Smckusick if (argc >= 1) { 167*46794Smckusick fprintf(stderr, "Unknown arguments to dump:"); 168*46794Smckusick while (argc--) 169*46794Smckusick fprintf(stderr, " %s", *argv++); 170*46794Smckusick fprintf(stderr, "\n"); 171*46794Smckusick Exit(X_ABORT); 172*46794Smckusick } 17312331Smckusick if (strcmp(tape, "-") == 0) { 17412331Smckusick pipeout++; 17512331Smckusick tape = "standard output"; 17612331Smckusick } 17710910Ssam 17846614Smckusick if (blocksperfile) 17946614Smckusick blocksperfile = blocksperfile / ntrec * ntrec; /* round down */ 18046614Smckusick else { 18146614Smckusick /* 18246614Smckusick * Determine how to default tape size and density 18346614Smckusick * 18446614Smckusick * density tape size 18546614Smckusick * 9-track 1600 bpi (160 bytes/.1") 2300 ft. 18646614Smckusick * 9-track 6250 bpi (625 bytes/.1") 2300 ft. 18746614Smckusick * cartridge 8000 bpi (100 bytes/.1") 1700 ft. 18846614Smckusick * (450*4 - slop) 18946614Smckusick */ 19046614Smckusick if (density == 0) 19146614Smckusick density = cartridge ? 100 : 160; 19246614Smckusick if (tsize == 0) 19346614Smckusick tsize = cartridge ? 1700L*120L : 2300L*120L; 19446614Smckusick } 19510910Ssam 1966886Ssam #ifdef RDUMP 1976886Ssam { char *index(); 1986886Ssam host = tape; 1996886Ssam tape = index(host, ':'); 2006886Ssam if (tape == 0) { 20128642Smckusick msg("need keyletter ``f'' and device ``host:tape''\n"); 2026886Ssam exit(1); 2036886Ssam } 2046886Ssam *tape++ = 0; 2056886Ssam if (rmthost(host) == 0) 2066886Ssam exit(X_ABORT); 2076886Ssam } 20828860Smckusick setuid(getuid()); /* rmthost() is the only reason to be setuid */ 2096886Ssam #endif 21046614Smckusick if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 21146614Smckusick signal(SIGHUP, sighup); 21246614Smckusick if (signal(SIGTRAP, SIG_IGN) != SIG_IGN) 21346614Smckusick signal(SIGTRAP, sigtrap); 21446614Smckusick if (signal(SIGFPE, SIG_IGN) != SIG_IGN) 21546614Smckusick signal(SIGFPE, sigfpe); 21646614Smckusick if (signal(SIGBUS, SIG_IGN) != SIG_IGN) 21746614Smckusick signal(SIGBUS, sigbus); 21846614Smckusick if (signal(SIGSEGV, SIG_IGN) != SIG_IGN) 21946614Smckusick signal(SIGSEGV, sigsegv); 22046614Smckusick if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 22146614Smckusick signal(SIGTERM, sigterm); 2221423Sroot 2231423Sroot 2241423Sroot if (signal(SIGINT, interrupt) == SIG_IGN) 2251423Sroot signal(SIGINT, SIG_IGN); 2261423Sroot 2271423Sroot set_operators(); /* /etc/group snarfed */ 2281423Sroot getfstab(); /* /etc/fstab snarfed */ 2291423Sroot /* 2301423Sroot * disk can be either the full special file name, 2311423Sroot * the suffix of the special file name, 2321423Sroot * the special name missing the leading '/', 2331423Sroot * the file system name with or without the leading '/'. 2341423Sroot */ 2351423Sroot dt = fstabsearch(disk); 23629900Smckusick if (dt != 0) { 2371423Sroot disk = rawname(dt->fs_spec); 23829900Smckusick strncpy(spcl.c_dev, dt->fs_spec, NAMELEN); 23929900Smckusick strncpy(spcl.c_filesys, dt->fs_file, NAMELEN); 24029900Smckusick } else { 24129900Smckusick strncpy(spcl.c_dev, disk, NAMELEN); 24229900Smckusick strncpy(spcl.c_filesys, "an unlisted file system", NAMELEN); 24329900Smckusick } 24429900Smckusick strcpy(spcl.c_label, "none"); 24529900Smckusick gethostname(spcl.c_host, NAMELEN); 246*46794Smckusick spcl.c_level = level - '0'; 24729900Smckusick spcl.c_type = TS_TAPE; 248*46794Smckusick getdumptime(); /* /etc/dumpdates snarfed */ 2491423Sroot 250*46794Smckusick msg("Date of this level %c dump: %s", level, 251*46794Smckusick spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date)); 252*46794Smckusick msg("Date of last level %c dump: %s", lastlevel, 253*46794Smckusick spcl.c_ddate == 0 ? "the epoch\n" : ctime(&spcl.c_ddate)); 2541423Sroot msg("Dumping %s ", disk); 2551423Sroot if (dt != 0) 2561423Sroot msgtail("(%s) ", dt->fs_file); 2578506Smckusick #ifdef RDUMP 2588506Smckusick msgtail("to %s on host %s\n", tape, host); 2598506Smckusick #else 2608371Smckusick msgtail("to %s\n", tape); 2616882Ssam #endif 2621423Sroot 263*46794Smckusick if ((diskfd = open(disk, O_RDONLY)) < 0) { 2641423Sroot msg("Cannot open %s\n", disk); 2651423Sroot Exit(X_ABORT); 2661423Sroot } 267*46794Smckusick sync(); 2685328Smckusic sblock = (struct fs *)buf; 26930560Smckusick bread(SBOFF, sblock, SBSIZE); 27046586Storek if (sblock->fs_magic != FS_MAGIC) 27146586Storek quit("bad sblock magic number\n"); 27230560Smckusick dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1); 27346586Storek dev_bshift = ffs(dev_bsize) - 1; 27446586Storek if (dev_bsize != (1 << dev_bshift)) 27546586Storek quit("dev_bsize (%d) is not a power of 2", dev_bsize); 27646586Storek tp_bshift = ffs(TP_BSIZE) - 1; 27746586Storek if (TP_BSIZE != (1 << tp_bshift)) 27846586Storek quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE); 279*46794Smckusick maxino = sblock->fs_ipg * sblock->fs_ncg - 1; 280*46794Smckusick mapsize = roundup(howmany(sblock->fs_ipg * sblock->fs_ncg, NBBY), 2815328Smckusic TP_BSIZE); 282*46794Smckusick usedinomap = (char *)calloc(mapsize, sizeof(char)); 283*46794Smckusick dumpdirmap = (char *)calloc(mapsize, sizeof(char)); 284*46794Smckusick dumpinomap = (char *)calloc(mapsize, sizeof(char)); 285*46794Smckusick tapesize = 3 * (howmany(mapsize * sizeof(char), TP_BSIZE) + 1); 2861423Sroot 2871423Sroot msg("mapping (Pass I) [regular files]\n"); 288*46794Smckusick anydirskipped = mapfiles(maxino, &tapesize); 2891423Sroot 290*46794Smckusick msg("mapping (Pass II) [directories]\n"); 291*46794Smckusick while (anydirskipped) { 292*46794Smckusick anydirskipped = mapdirs(maxino, &tapesize); 293*46794Smckusick } 2941423Sroot 29546614Smckusick if (pipeout) 296*46794Smckusick tapesize += 10; /* 10 trailer blocks */ 29746614Smckusick else { 29846614Smckusick if (blocksperfile) 299*46794Smckusick fetapes = tapesize / blocksperfile; 30046614Smckusick else if (cartridge) { 30146614Smckusick /* Estimate number of tapes, assuming streaming stops at 30246614Smckusick the end of each block written, and not in mid-block. 30346614Smckusick Assume no erroneous blocks; this can be compensated 30446614Smckusick for with an artificially low tape size. */ 30546614Smckusick fetapes = 306*46794Smckusick ( tapesize /* blocks */ 30746614Smckusick * TP_BSIZE /* bytes/block */ 30846614Smckusick * (1.0/density) /* 0.1" / byte */ 30946614Smckusick + 310*46794Smckusick tapesize /* blocks */ 31146614Smckusick * (1.0/ntrec) /* streaming-stops per block */ 31246614Smckusick * 15.48 /* 0.1" / streaming-stop */ 31346614Smckusick ) * (1.0 / tsize ); /* tape / 0.1" */ 31446614Smckusick } else { 31546614Smckusick /* Estimate number of tapes, for old fashioned 9-track 31646614Smckusick tape */ 31746614Smckusick int tenthsperirg = (density == 625) ? 3 : 7; 31846614Smckusick fetapes = 319*46794Smckusick ( tapesize /* blocks */ 32046614Smckusick * TP_BSIZE /* bytes / block */ 32146614Smckusick * (1.0/density) /* 0.1" / byte */ 32246614Smckusick + 323*46794Smckusick tapesize /* blocks */ 32446614Smckusick * (1.0/ntrec) /* IRG's / block */ 32546614Smckusick * tenthsperirg /* 0.1" / IRG */ 32646614Smckusick ) * (1.0 / tsize ); /* tape / 0.1" */ 32746614Smckusick } 32846614Smckusick etapes = fetapes; /* truncating assignment */ 32946614Smckusick etapes++; 330*46794Smckusick /* count the dumped inodes map on each additional tape */ 331*46794Smckusick tapesize += (etapes - 1) * 332*46794Smckusick (howmany(mapsize * sizeof(char), TP_BSIZE) + 1); 333*46794Smckusick tapesize += etapes + 10; /* headers + 10 trailer blks */ 33410910Ssam } 33546614Smckusick if (pipeout) 336*46794Smckusick msg("estimated %ld tape blocks.\n", tapesize); 33746614Smckusick else 33846614Smckusick msg("estimated %ld tape blocks on %3.2f tape(s).\n", 339*46794Smckusick tapesize, fetapes); 3401423Sroot 34110910Ssam alloctape(); /* Allocate tape buffer */ 34210910Ssam 343*46794Smckusick startnewtape(); 3441423Sroot time(&(tstart_writing)); 345*46794Smckusick dumpmap(usedinomap, TS_CLRI, maxino); 3461423Sroot 3471423Sroot msg("dumping (Pass III) [directories]\n"); 348*46794Smckusick for (map = dumpdirmap, ino = 0; ino < maxino; ) { 349*46794Smckusick if ((ino % NBBY) == 0) 350*46794Smckusick bits = *map++; 351*46794Smckusick else 352*46794Smckusick bits >>= 1; 353*46794Smckusick ino++; 354*46794Smckusick if ((bits & 1) == 0) 355*46794Smckusick continue; 356*46794Smckusick /* 357*46794Smckusick * Skip directory inodes deleted and maybe reallocated 358*46794Smckusick */ 359*46794Smckusick dp = getino(ino); 360*46794Smckusick if ((dp->di_mode & IFMT) != IFDIR) 361*46794Smckusick continue; 362*46794Smckusick dumpino(dp, ino); 363*46794Smckusick } 3641423Sroot 3651423Sroot msg("dumping (Pass IV) [regular files]\n"); 366*46794Smckusick for (map = dumpinomap, ino = 0; ino < maxino; ) { 367*46794Smckusick if ((ino % NBBY) == 0) 368*46794Smckusick bits = *map++; 369*46794Smckusick else 370*46794Smckusick bits >>= 1; 371*46794Smckusick ino++; 372*46794Smckusick if ((bits & 1) == 0) 373*46794Smckusick continue; 374*46794Smckusick /* 375*46794Smckusick * Skip inodes deleted and reallocated as directories. 376*46794Smckusick */ 377*46794Smckusick dp = getino(ino); 378*46794Smckusick if ((dp->di_mode & IFMT) == IFDIR) 379*46794Smckusick continue; 380*46794Smckusick dumpino(dp, ino); 381*46794Smckusick } 3821423Sroot 3831423Sroot spcl.c_type = TS_END; 3846882Ssam #ifndef RDUMP 385*46794Smckusick for (i = 0; i < ntrec; i++) 386*46794Smckusick writeheader(maxino); 3876882Ssam #endif 38846614Smckusick if (pipeout) 38946614Smckusick msg("DUMP: %ld tape blocks\n",spcl.c_tapea); 39046614Smckusick else 39146614Smckusick msg("DUMP: %ld tape blocks on %d volumes(s)\n", 39246614Smckusick spcl.c_tapea, spcl.c_volume); 3931423Sroot msg("DUMP IS DONE\n"); 3941423Sroot 395*46794Smckusick putdumptime(); 3966882Ssam #ifndef RDUMP 39712331Smckusick if (!pipeout) { 398*46794Smckusick close(tapefd); 39946239Storek trewind(); 40012331Smckusick } 4016882Ssam #else 402*46794Smckusick for (i = 0; i < ntrec; i++) 403*46794Smckusick writeheader(curino); 40446239Storek trewind(); 4056882Ssam #endif 4061423Sroot broadcast("DUMP IS DONE!\7\7\n"); 4071423Sroot Exit(X_FINOK); 40846586Storek /* NOTREACHED */ 4091423Sroot } 4101423Sroot 41146586Storek void 4121423Sroot sigAbort() 4131423Sroot { 41446586Storek if (pipeout) 41546586Storek quit("Unknown signal, cannot recover\n"); 4161423Sroot msg("Rewriting attempted as response to unknown signal.\n"); 4171423Sroot fflush(stderr); 4181423Sroot fflush(stdout); 4191423Sroot close_rewind(); 4201423Sroot exit(X_REWRITE); 4211423Sroot } 4221423Sroot 42346586Storek void sighup(){ msg("SIGHUP() try rewriting\n"); sigAbort();} 42446586Storek void sigtrap(){ msg("SIGTRAP() try rewriting\n"); sigAbort();} 42546586Storek void sigfpe(){ msg("SIGFPE() try rewriting\n"); sigAbort();} 42646586Storek void sigbus(){ msg("SIGBUS() try rewriting\n"); sigAbort();} 42746586Storek void sigsegv(){ msg("SIGSEGV() ABORTING!\n"); abort();} 42846586Storek void sigalrm(){ msg("SIGALRM() try rewriting\n"); sigAbort();} 42946586Storek void sigterm(){ msg("SIGTERM() try rewriting\n"); sigAbort();} 43046586Storek 43146586Storek char * 43246586Storek rawname(cp) 4331423Sroot char *cp; 4341423Sroot { 4351423Sroot static char rawbuf[32]; 4364608Smckusic char *rindex(); 4371423Sroot char *dp = rindex(cp, '/'); 4381423Sroot 4391423Sroot if (dp == 0) 4401423Sroot return (0); 4411423Sroot *dp = 0; 4421423Sroot strcpy(rawbuf, cp); 4431423Sroot *dp = '/'; 4441423Sroot strcat(rawbuf, "/r"); 4451423Sroot strcat(rawbuf, dp+1); 4461423Sroot return (rawbuf); 4471423Sroot } 448