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*46795Sbostic static char sccsid[] = "@(#)main.c 5.13 (Berkeley) 02/28/91"; 946586Storek #endif /* not lint */ 1022037Sdist 11*46795Sbostic #include <sys/param.h> 12*46795Sbostic #include <ufs/dir.h> 13*46795Sbostic #include <ufs/dinode.h> 14*46795Sbostic #include <ufs/fs.h> 15*46795Sbostic #include <protocols/dumprestore.h> 16*46795Sbostic #include <signal.h> 17*46795Sbostic #ifdef __STDC__ 18*46795Sbostic #include <time.h> 19*46795Sbostic #endif 20*46795Sbostic #include <fcntl.h> 21*46795Sbostic #include <fstab.h> 22*46795Sbostic #include <stdio.h> 23*46795Sbostic #ifdef __STDC__ 24*46795Sbostic #include <unistd.h> 25*46795Sbostic #include <stdlib.h> 26*46795Sbostic #include <string.h> 27*46795Sbostic #endif 281423Sroot #include "dump.h" 2937266Sbostic #include "pathnames.h" 301423Sroot 311423Sroot int notify = 0; /* notify operator flag */ 321423Sroot int blockswritten = 0; /* number of blocks written on current tape */ 331423Sroot int tapeno = 0; /* current tape number */ 3410910Ssam int density = 0; /* density in bytes/0.1" */ 3510910Ssam int ntrec = NTREC; /* # tape blocks in each tape record */ 3610910Ssam int cartridge = 0; /* Assume non-cartridge tape */ 3730560Smckusick long dev_bsize = 1; /* recalculated below */ 3846614Smckusick long blocksperfile; /* output blocks per file */ 396882Ssam #ifdef RDUMP 406882Ssam char *host; 4146586Storek int rmthost(); 426882Ssam #endif 431423Sroot 441423Sroot main(argc, argv) 4546794Smckusick int argc; 46*46795Sbostic char **argv; 471423Sroot { 4846794Smckusick register ino_t ino; 4946794Smckusick register long bits; 5046794Smckusick register struct dinode *dp; 5146794Smckusick register struct fstab *dt; 5246794Smckusick register char *map; 5346794Smckusick register char *cp; 5446794Smckusick int i, anydirskipped, bflag = 0; 5546794Smckusick float fetapes; 5646794Smckusick ino_t maxino; 571423Sroot 581423Sroot time(&(spcl.c_date)); 591423Sroot 6010910Ssam tsize = 0; /* Default later, based on 'c' option for cart tapes */ 6137946Sbostic tape = _PATH_DEFTAPE; 6246794Smckusick dumpdates = _PATH_DUMPDATES; 6337266Sbostic temp = _PATH_DTMP; 6446586Storek if (TP_BSIZE / DEV_BSIZE == 0 || TP_BSIZE % DEV_BSIZE != 0) 6546586Storek quit("TP_BSIZE must be a multiple of DEV_BSIZE\n"); 6646794Smckusick level = '0'; 6746794Smckusick argv++; 6846794Smckusick argc -= 2; 6946794Smckusick for (cp = *argv++; *cp; cp++) { 7046794Smckusick switch (*cp) { 7146794Smckusick case '-': 7246794Smckusick continue; 731423Sroot 7446794Smckusick case 'w': 7546794Smckusick lastdump('w'); /* tell us only what has to be done */ 7646794Smckusick exit(0); 7746794Smckusick 7846794Smckusick case 'W': /* what to do */ 7946794Smckusick lastdump('W'); /* tell us state of what is done */ 8046794Smckusick exit(0); /* do nothing else */ 8146794Smckusick 8246794Smckusick case 'f': /* output file */ 8346794Smckusick if (argc < 1) 8446794Smckusick break; 8546794Smckusick tape = *argv++; 861423Sroot argc--; 8746794Smckusick continue; 881423Sroot 8946794Smckusick case 'd': /* density, in bits per inch */ 9046794Smckusick if (argc < 1) 9146794Smckusick break; 9246794Smckusick density = atoi(*argv) / 10; 9346794Smckusick if (density < 1) { 9446794Smckusick fprintf(stderr, "bad density \"%s\"\n", *argv); 9546794Smckusick Exit(X_ABORT); 9646794Smckusick } 9746794Smckusick argc--; 981423Sroot argv++; 9918494Smckusick if (density >= 625 && !bflag) 10018494Smckusick ntrec = HIGHDENSITYTREC; 10146794Smckusick continue; 1021423Sroot 10346794Smckusick case 's': /* tape size, feet */ 10446794Smckusick if (argc < 1) 10546794Smckusick break; 10646794Smckusick tsize = atol(*argv); 10746794Smckusick if (tsize < 1) { 10846794Smckusick fprintf(stderr, "bad size \"%s\"\n", *argv); 10946794Smckusick Exit(X_ABORT); 11046794Smckusick } 11146794Smckusick argc--; 1121423Sroot argv++; 11346794Smckusick tsize *= 12 * 10; 11446794Smckusick continue; 1151423Sroot 11646794Smckusick case 'b': /* blocks per tape write */ 11746794Smckusick if (argc < 1) 11846794Smckusick break; 11918494Smckusick bflag++; 12010910Ssam ntrec = atol(*argv); 12146794Smckusick if (ntrec < 1) { 12246794Smckusick fprintf(stderr, "%s \"%s\"\n", 12346794Smckusick "bad number of blocks per write ", *argv); 12446614Smckusick Exit(X_ABORT); 12546614Smckusick } 12646794Smckusick argc--; 12746794Smckusick argv++; 12846794Smckusick continue; 12910910Ssam 13046794Smckusick case 'B': /* blocks per output file */ 13146794Smckusick if (argc < 1) 13246794Smckusick break; 13346794Smckusick blocksperfile = atol(*argv); 13446794Smckusick if (blocksperfile < 1) { 13546794Smckusick fprintf(stderr, "%s \"%s\"\n", 13646794Smckusick "bad number of blocks per file ", *argv); 13746794Smckusick Exit(X_ABORT); 13846794Smckusick } 13946794Smckusick argc--; 14046614Smckusick argv++; 14146794Smckusick continue; 14246614Smckusick 14346794Smckusick case 'c': /* Tape is cart. not 9-track */ 14446794Smckusick cartridge++; 14546794Smckusick continue; 14610910Ssam 14746794Smckusick case '0': /* dump level */ 14846794Smckusick case '1': 14946794Smckusick case '2': 15046794Smckusick case '3': 15146794Smckusick case '4': 15246794Smckusick case '5': 15346794Smckusick case '6': 15446794Smckusick case '7': 15546794Smckusick case '8': 15646794Smckusick case '9': 15746794Smckusick level = *cp; 15846794Smckusick continue; 1591423Sroot 16046794Smckusick case 'u': /* update /etc/dumpdates */ 16146794Smckusick uflag++; 16246794Smckusick continue; 1631423Sroot 16446794Smckusick case 'n': /* notify operators */ 16546794Smckusick notify++; 16646794Smckusick continue; 1671423Sroot 16846794Smckusick default: 16946794Smckusick fprintf(stderr, "bad key '%c'\n", *cp); 17046794Smckusick Exit(X_ABORT); 17146794Smckusick } 17246794Smckusick fprintf(stderr, "missing argument to '%c'\n", *cp); 1731423Sroot Exit(X_ABORT); 1741423Sroot } 17546794Smckusick if (argc < 1) { 17646794Smckusick fprintf(stderr, "Must specify disk or filesystem\n"); 17746794Smckusick Exit(X_ABORT); 17846794Smckusick } else { 17946794Smckusick disk = *argv++; 1801423Sroot argc--; 1811423Sroot } 18246794Smckusick if (argc >= 1) { 18346794Smckusick fprintf(stderr, "Unknown arguments to dump:"); 18446794Smckusick while (argc--) 18546794Smckusick fprintf(stderr, " %s", *argv++); 18646794Smckusick fprintf(stderr, "\n"); 18746794Smckusick Exit(X_ABORT); 18846794Smckusick } 18912331Smckusick if (strcmp(tape, "-") == 0) { 19012331Smckusick pipeout++; 19112331Smckusick tape = "standard output"; 19212331Smckusick } 19310910Ssam 19446614Smckusick if (blocksperfile) 19546614Smckusick blocksperfile = blocksperfile / ntrec * ntrec; /* round down */ 19646614Smckusick else { 19746614Smckusick /* 19846614Smckusick * Determine how to default tape size and density 19946614Smckusick * 20046614Smckusick * density tape size 20146614Smckusick * 9-track 1600 bpi (160 bytes/.1") 2300 ft. 20246614Smckusick * 9-track 6250 bpi (625 bytes/.1") 2300 ft. 20346614Smckusick * cartridge 8000 bpi (100 bytes/.1") 1700 ft. 20446614Smckusick * (450*4 - slop) 20546614Smckusick */ 20646614Smckusick if (density == 0) 20746614Smckusick density = cartridge ? 100 : 160; 20846614Smckusick if (tsize == 0) 20946614Smckusick tsize = cartridge ? 1700L*120L : 2300L*120L; 21046614Smckusick } 21110910Ssam 2126886Ssam #ifdef RDUMP 2136886Ssam { char *index(); 2146886Ssam host = tape; 2156886Ssam tape = index(host, ':'); 2166886Ssam if (tape == 0) { 21728642Smckusick msg("need keyletter ``f'' and device ``host:tape''\n"); 2186886Ssam exit(1); 2196886Ssam } 2206886Ssam *tape++ = 0; 2216886Ssam if (rmthost(host) == 0) 2226886Ssam exit(X_ABORT); 2236886Ssam } 22428860Smckusick setuid(getuid()); /* rmthost() is the only reason to be setuid */ 2256886Ssam #endif 22646614Smckusick if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 22746614Smckusick signal(SIGHUP, sighup); 22846614Smckusick if (signal(SIGTRAP, SIG_IGN) != SIG_IGN) 22946614Smckusick signal(SIGTRAP, sigtrap); 23046614Smckusick if (signal(SIGFPE, SIG_IGN) != SIG_IGN) 23146614Smckusick signal(SIGFPE, sigfpe); 23246614Smckusick if (signal(SIGBUS, SIG_IGN) != SIG_IGN) 23346614Smckusick signal(SIGBUS, sigbus); 23446614Smckusick if (signal(SIGSEGV, SIG_IGN) != SIG_IGN) 23546614Smckusick signal(SIGSEGV, sigsegv); 23646614Smckusick if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 23746614Smckusick signal(SIGTERM, sigterm); 2381423Sroot 2391423Sroot 2401423Sroot if (signal(SIGINT, interrupt) == SIG_IGN) 2411423Sroot signal(SIGINT, SIG_IGN); 2421423Sroot 2431423Sroot set_operators(); /* /etc/group snarfed */ 2441423Sroot getfstab(); /* /etc/fstab snarfed */ 2451423Sroot /* 2461423Sroot * disk can be either the full special file name, 2471423Sroot * the suffix of the special file name, 2481423Sroot * the special name missing the leading '/', 2491423Sroot * the file system name with or without the leading '/'. 2501423Sroot */ 2511423Sroot dt = fstabsearch(disk); 25229900Smckusick if (dt != 0) { 2531423Sroot disk = rawname(dt->fs_spec); 25429900Smckusick strncpy(spcl.c_dev, dt->fs_spec, NAMELEN); 25529900Smckusick strncpy(spcl.c_filesys, dt->fs_file, NAMELEN); 25629900Smckusick } else { 25729900Smckusick strncpy(spcl.c_dev, disk, NAMELEN); 25829900Smckusick strncpy(spcl.c_filesys, "an unlisted file system", NAMELEN); 25929900Smckusick } 26029900Smckusick strcpy(spcl.c_label, "none"); 26129900Smckusick gethostname(spcl.c_host, NAMELEN); 26246794Smckusick spcl.c_level = level - '0'; 26329900Smckusick spcl.c_type = TS_TAPE; 26446794Smckusick getdumptime(); /* /etc/dumpdates snarfed */ 2651423Sroot 26646794Smckusick msg("Date of this level %c dump: %s", level, 26746794Smckusick spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date)); 26846794Smckusick msg("Date of last level %c dump: %s", lastlevel, 26946794Smckusick spcl.c_ddate == 0 ? "the epoch\n" : ctime(&spcl.c_ddate)); 2701423Sroot msg("Dumping %s ", disk); 2711423Sroot if (dt != 0) 2721423Sroot msgtail("(%s) ", dt->fs_file); 2738506Smckusick #ifdef RDUMP 2748506Smckusick msgtail("to %s on host %s\n", tape, host); 2758506Smckusick #else 2768371Smckusick msgtail("to %s\n", tape); 2776882Ssam #endif 2781423Sroot 27946794Smckusick if ((diskfd = open(disk, O_RDONLY)) < 0) { 2801423Sroot msg("Cannot open %s\n", disk); 2811423Sroot Exit(X_ABORT); 2821423Sroot } 28346794Smckusick sync(); 2845328Smckusic sblock = (struct fs *)buf; 28530560Smckusick bread(SBOFF, sblock, SBSIZE); 28646586Storek if (sblock->fs_magic != FS_MAGIC) 28746586Storek quit("bad sblock magic number\n"); 28830560Smckusick dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1); 28946586Storek dev_bshift = ffs(dev_bsize) - 1; 29046586Storek if (dev_bsize != (1 << dev_bshift)) 29146586Storek quit("dev_bsize (%d) is not a power of 2", dev_bsize); 29246586Storek tp_bshift = ffs(TP_BSIZE) - 1; 29346586Storek if (TP_BSIZE != (1 << tp_bshift)) 29446586Storek quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE); 29546794Smckusick maxino = sblock->fs_ipg * sblock->fs_ncg - 1; 29646794Smckusick mapsize = roundup(howmany(sblock->fs_ipg * sblock->fs_ncg, NBBY), 2975328Smckusic TP_BSIZE); 29846794Smckusick usedinomap = (char *)calloc(mapsize, sizeof(char)); 29946794Smckusick dumpdirmap = (char *)calloc(mapsize, sizeof(char)); 30046794Smckusick dumpinomap = (char *)calloc(mapsize, sizeof(char)); 30146794Smckusick tapesize = 3 * (howmany(mapsize * sizeof(char), TP_BSIZE) + 1); 3021423Sroot 3031423Sroot msg("mapping (Pass I) [regular files]\n"); 30446794Smckusick anydirskipped = mapfiles(maxino, &tapesize); 3051423Sroot 30646794Smckusick msg("mapping (Pass II) [directories]\n"); 30746794Smckusick while (anydirskipped) { 30846794Smckusick anydirskipped = mapdirs(maxino, &tapesize); 30946794Smckusick } 3101423Sroot 31146614Smckusick if (pipeout) 31246794Smckusick tapesize += 10; /* 10 trailer blocks */ 31346614Smckusick else { 31446614Smckusick if (blocksperfile) 31546794Smckusick fetapes = tapesize / blocksperfile; 31646614Smckusick else if (cartridge) { 31746614Smckusick /* Estimate number of tapes, assuming streaming stops at 31846614Smckusick the end of each block written, and not in mid-block. 31946614Smckusick Assume no erroneous blocks; this can be compensated 32046614Smckusick for with an artificially low tape size. */ 32146614Smckusick fetapes = 32246794Smckusick ( tapesize /* blocks */ 32346614Smckusick * TP_BSIZE /* bytes/block */ 32446614Smckusick * (1.0/density) /* 0.1" / byte */ 32546614Smckusick + 32646794Smckusick tapesize /* blocks */ 32746614Smckusick * (1.0/ntrec) /* streaming-stops per block */ 32846614Smckusick * 15.48 /* 0.1" / streaming-stop */ 32946614Smckusick ) * (1.0 / tsize ); /* tape / 0.1" */ 33046614Smckusick } else { 33146614Smckusick /* Estimate number of tapes, for old fashioned 9-track 33246614Smckusick tape */ 33346614Smckusick int tenthsperirg = (density == 625) ? 3 : 7; 33446614Smckusick fetapes = 33546794Smckusick ( tapesize /* blocks */ 33646614Smckusick * TP_BSIZE /* bytes / block */ 33746614Smckusick * (1.0/density) /* 0.1" / byte */ 33846614Smckusick + 33946794Smckusick tapesize /* blocks */ 34046614Smckusick * (1.0/ntrec) /* IRG's / block */ 34146614Smckusick * tenthsperirg /* 0.1" / IRG */ 34246614Smckusick ) * (1.0 / tsize ); /* tape / 0.1" */ 34346614Smckusick } 34446614Smckusick etapes = fetapes; /* truncating assignment */ 34546614Smckusick etapes++; 34646794Smckusick /* count the dumped inodes map on each additional tape */ 34746794Smckusick tapesize += (etapes - 1) * 34846794Smckusick (howmany(mapsize * sizeof(char), TP_BSIZE) + 1); 34946794Smckusick tapesize += etapes + 10; /* headers + 10 trailer blks */ 35010910Ssam } 35146614Smckusick if (pipeout) 35246794Smckusick msg("estimated %ld tape blocks.\n", tapesize); 35346614Smckusick else 35446614Smckusick msg("estimated %ld tape blocks on %3.2f tape(s).\n", 35546794Smckusick tapesize, fetapes); 3561423Sroot 35710910Ssam alloctape(); /* Allocate tape buffer */ 35810910Ssam 35946794Smckusick startnewtape(); 3601423Sroot time(&(tstart_writing)); 36146794Smckusick dumpmap(usedinomap, TS_CLRI, maxino); 3621423Sroot 3631423Sroot msg("dumping (Pass III) [directories]\n"); 36446794Smckusick for (map = dumpdirmap, ino = 0; ino < maxino; ) { 36546794Smckusick if ((ino % NBBY) == 0) 36646794Smckusick bits = *map++; 36746794Smckusick else 36846794Smckusick bits >>= 1; 36946794Smckusick ino++; 37046794Smckusick if ((bits & 1) == 0) 37146794Smckusick continue; 37246794Smckusick /* 37346794Smckusick * Skip directory inodes deleted and maybe reallocated 37446794Smckusick */ 37546794Smckusick dp = getino(ino); 37646794Smckusick if ((dp->di_mode & IFMT) != IFDIR) 37746794Smckusick continue; 37846794Smckusick dumpino(dp, ino); 37946794Smckusick } 3801423Sroot 3811423Sroot msg("dumping (Pass IV) [regular files]\n"); 38246794Smckusick for (map = dumpinomap, ino = 0; ino < maxino; ) { 38346794Smckusick if ((ino % NBBY) == 0) 38446794Smckusick bits = *map++; 38546794Smckusick else 38646794Smckusick bits >>= 1; 38746794Smckusick ino++; 38846794Smckusick if ((bits & 1) == 0) 38946794Smckusick continue; 39046794Smckusick /* 39146794Smckusick * Skip inodes deleted and reallocated as directories. 39246794Smckusick */ 39346794Smckusick dp = getino(ino); 39446794Smckusick if ((dp->di_mode & IFMT) == IFDIR) 39546794Smckusick continue; 39646794Smckusick dumpino(dp, ino); 39746794Smckusick } 3981423Sroot 3991423Sroot spcl.c_type = TS_END; 4006882Ssam #ifndef RDUMP 40146794Smckusick for (i = 0; i < ntrec; i++) 40246794Smckusick writeheader(maxino); 4036882Ssam #endif 40446614Smckusick if (pipeout) 40546614Smckusick msg("DUMP: %ld tape blocks\n",spcl.c_tapea); 40646614Smckusick else 40746614Smckusick msg("DUMP: %ld tape blocks on %d volumes(s)\n", 40846614Smckusick spcl.c_tapea, spcl.c_volume); 4091423Sroot msg("DUMP IS DONE\n"); 4101423Sroot 41146794Smckusick putdumptime(); 4126882Ssam #ifndef RDUMP 41312331Smckusick if (!pipeout) { 41446794Smckusick close(tapefd); 41546239Storek trewind(); 41612331Smckusick } 4176882Ssam #else 41846794Smckusick for (i = 0; i < ntrec; i++) 41946794Smckusick writeheader(curino); 42046239Storek trewind(); 4216882Ssam #endif 4221423Sroot broadcast("DUMP IS DONE!\7\7\n"); 4231423Sroot Exit(X_FINOK); 42446586Storek /* NOTREACHED */ 4251423Sroot } 4261423Sroot 42746586Storek void 4281423Sroot sigAbort() 4291423Sroot { 43046586Storek if (pipeout) 43146586Storek quit("Unknown signal, cannot recover\n"); 4321423Sroot msg("Rewriting attempted as response to unknown signal.\n"); 4331423Sroot fflush(stderr); 4341423Sroot fflush(stdout); 4351423Sroot close_rewind(); 4361423Sroot exit(X_REWRITE); 4371423Sroot } 4381423Sroot 43946586Storek void sighup(){ msg("SIGHUP() try rewriting\n"); sigAbort();} 44046586Storek void sigtrap(){ msg("SIGTRAP() try rewriting\n"); sigAbort();} 44146586Storek void sigfpe(){ msg("SIGFPE() try rewriting\n"); sigAbort();} 44246586Storek void sigbus(){ msg("SIGBUS() try rewriting\n"); sigAbort();} 44346586Storek void sigsegv(){ msg("SIGSEGV() ABORTING!\n"); abort();} 44446586Storek void sigalrm(){ msg("SIGALRM() try rewriting\n"); sigAbort();} 44546586Storek void sigterm(){ msg("SIGTERM() try rewriting\n"); sigAbort();} 44646586Storek 44746586Storek char * 44846586Storek rawname(cp) 4491423Sroot char *cp; 4501423Sroot { 4511423Sroot static char rawbuf[32]; 4524608Smckusic char *rindex(); 4531423Sroot char *dp = rindex(cp, '/'); 4541423Sroot 4551423Sroot if (dp == 0) 4561423Sroot return (0); 4571423Sroot *dp = 0; 4581423Sroot strcpy(rawbuf, cp); 4591423Sroot *dp = '/'; 4601423Sroot strcat(rawbuf, "/r"); 4611423Sroot strcat(rawbuf, dp+1); 4621423Sroot return (rawbuf); 4631423Sroot } 464