132001Spc /* 232001Spc * Copyright (c) 1980 Regents of the University of California. 332001Spc * All rights reserved. The Berkeley software License Agreement 432001Spc * specifies the terms and conditions for redistribution. 532001Spc */ 632001Spc 732001Spc #ifndef lint 8*32003Spc static char sccsid[] = "@(#)dumpmain.c 5.6 (Berkeley) 2/23/87"; 932001Spc #endif not lint 1032001Spc 1132001Spc #include "dump.h" 1232001Spc 1332001Spc int notify = 0; /* notify operator flag */ 1432001Spc int blockswritten = 0; /* number of blocks written on current tape */ 1532001Spc int tapeno = 0; /* current tape number */ 1632001Spc int density = 0; /* density in bytes/0.1" */ 1732001Spc int ntrec = NTREC; /* # tape blocks in each tape record */ 1832001Spc int cartridge = 0; /* Assume non-cartridge tape */ 1932001Spc #ifdef RDUMP 2032001Spc char *host; 2132001Spc #endif 2232001Spc int anydskipped; /* set true in mark() if any directories are skipped */ 2332001Spc /* this lets us avoid map pass 2 in some cases */ 2432001Spc 2532001Spc main(argc, argv) 2632001Spc int argc; 2732001Spc char *argv[]; 2832001Spc { 2932001Spc char *arg; 3032001Spc int bflag = 0, i; 3132001Spc float fetapes; 3232001Spc register struct fstab *dt; 3332001Spc 3432001Spc time(&(spcl.c_date)); 3532001Spc 3632001Spc tsize = 0; /* Default later, based on 'c' option for cart tapes */ 3732001Spc tape = TAPE; 3832001Spc disk = DISK; 3932001Spc increm = NINCREM; 4032001Spc temp = TEMP; 4132001Spc if (TP_BSIZE / DEV_BSIZE == 0 || TP_BSIZE % DEV_BSIZE != 0) { 4232001Spc msg("TP_BSIZE must be a multiple of DEV_BSIZE\n"); 4332001Spc dumpabort(); 4432001Spc } 4532001Spc incno = '9'; 4632001Spc uflag = 0; 4732001Spc arg = "u"; 4832001Spc if(argc > 1) { 4932001Spc argv++; 5032001Spc argc--; 5132001Spc arg = *argv; 5232001Spc if (*arg == '-') 5332001Spc argc++; 5432001Spc } 5532001Spc while(*arg) 5632001Spc switch (*arg++) { 5732001Spc case 'w': 5832001Spc lastdump('w'); /* tell us only what has to be done */ 5932001Spc exit(0); 6032001Spc break; 6132001Spc case 'W': /* what to do */ 6232001Spc lastdump('W'); /* tell us the current state of what has been done */ 6332001Spc exit(0); /* do nothing else */ 6432001Spc break; 6532001Spc 6632001Spc case 'f': /* output file */ 6732001Spc if(argc > 1) { 6832001Spc argv++; 6932001Spc argc--; 7032001Spc tape = *argv; 7132001Spc } 7232001Spc break; 7332001Spc 7432001Spc case 'd': /* density, in bits per inch */ 7532001Spc if (argc > 1) { 7632001Spc argv++; 7732001Spc argc--; 7832001Spc density = atoi(*argv) / 10; 7932001Spc if (density >= 625 && !bflag) 8032001Spc ntrec = HIGHDENSITYTREC; 8132001Spc } 8232001Spc break; 8332001Spc 8432001Spc case 's': /* tape size, feet */ 8532001Spc if(argc > 1) { 8632001Spc argv++; 8732001Spc argc--; 8832001Spc tsize = atol(*argv); 8932001Spc tsize *= 12L*10L; 9032001Spc } 9132001Spc break; 9232001Spc 9332001Spc case 'b': /* blocks per tape write */ 9432001Spc if(argc > 1) { 9532001Spc argv++; 9632001Spc argc--; 9732001Spc bflag++; 9832001Spc ntrec = atol(*argv); 9932001Spc } 10032001Spc break; 10132001Spc 10232001Spc case 'c': /* Tape is cart. not 9-track */ 10332001Spc cartridge++; 10432001Spc break; 10532001Spc 10632001Spc case '0': /* dump level */ 10732001Spc case '1': 10832001Spc case '2': 10932001Spc case '3': 11032001Spc case '4': 11132001Spc case '5': 11232001Spc case '6': 11332001Spc case '7': 11432001Spc case '8': 11532001Spc case '9': 11632001Spc incno = arg[-1]; 11732001Spc break; 11832001Spc 11932001Spc case 'u': /* update /etc/dumpdates */ 12032001Spc uflag++; 12132001Spc break; 12232001Spc 12332001Spc case 'n': /* notify operators */ 12432001Spc notify++; 12532001Spc break; 12632001Spc 12732001Spc default: 12832001Spc fprintf(stderr, "bad key '%c%'\n", arg[-1]); 12932001Spc Exit(X_ABORT); 13032001Spc } 13132001Spc if(argc > 1) { 13232001Spc argv++; 13332001Spc argc--; 13432001Spc disk = *argv; 13532001Spc } 13632001Spc if (strcmp(tape, "-") == 0) { 13732001Spc pipeout++; 13832001Spc tape = "standard output"; 13932001Spc } 14032001Spc 14132001Spc /* 14232001Spc * Determine how to default tape size and density 14332001Spc * 14432001Spc * density tape size 14532001Spc * 9-track 1600 bpi (160 bytes/.1") 2300 ft. 14632001Spc * 9-track 6250 bpi (625 bytes/.1") 2300 ft. 14732001Spc * cartridge 8000 bpi (100 bytes/.1") 1700 ft. (450*4 - slop) 14832001Spc */ 14932001Spc if (density == 0) 15032001Spc density = cartridge ? 100 : 160; 15132001Spc if (tsize == 0) 15232001Spc tsize = cartridge ? 1700L*120L : 2300L*120L; 15332001Spc 15432001Spc #ifdef RDUMP 15532001Spc { char *index(); 15632001Spc host = tape; 15732001Spc tape = index(host, ':'); 15832001Spc if (tape == 0) { 15932001Spc msg("need keyletter ``f'' and device ``host:tape''\n"); 16032001Spc exit(1); 16132001Spc } 16232001Spc *tape++ = 0; 16332001Spc if (rmthost(host) == 0) 16432001Spc exit(X_ABORT); 16532001Spc } 16632001Spc setuid(getuid()); /* rmthost() is the only reason to be setuid */ 16732001Spc #endif 16832001Spc if (signal(SIGHUP, sighup) == SIG_IGN) 16932001Spc signal(SIGHUP, SIG_IGN); 17032001Spc if (signal(SIGTRAP, sigtrap) == SIG_IGN) 17132001Spc signal(SIGTRAP, SIG_IGN); 17232001Spc if (signal(SIGFPE, sigfpe) == SIG_IGN) 17332001Spc signal(SIGFPE, SIG_IGN); 17432001Spc if (signal(SIGBUS, sigbus) == SIG_IGN) 17532001Spc signal(SIGBUS, SIG_IGN); 17632001Spc if (signal(SIGSEGV, sigsegv) == SIG_IGN) 17732001Spc signal(SIGSEGV, SIG_IGN); 17832001Spc if (signal(SIGTERM, sigterm) == SIG_IGN) 17932001Spc signal(SIGTERM, SIG_IGN); 18032001Spc 18132001Spc 18232001Spc if (signal(SIGINT, interrupt) == SIG_IGN) 18332001Spc signal(SIGINT, SIG_IGN); 18432001Spc 18532001Spc set_operators(); /* /etc/group snarfed */ 18632001Spc getfstab(); /* /etc/fstab snarfed */ 18732001Spc /* 18832001Spc * disk can be either the full special file name, 18932001Spc * the suffix of the special file name, 19032001Spc * the special name missing the leading '/', 19132001Spc * the file system name with or without the leading '/'. 19232001Spc */ 19332001Spc dt = fstabsearch(disk); 194*32003Spc if (dt != 0) { 19532001Spc disk = rawname(dt->fs_spec); 196*32003Spc strncpy(spcl.c_dev, dt->fs_spec, NAMELEN); 197*32003Spc strncpy(spcl.c_filesys, dt->fs_file, NAMELEN); 198*32003Spc } else { 199*32003Spc strncpy(spcl.c_dev, disk, NAMELEN); 200*32003Spc strncpy(spcl.c_filesys, "an unlisted file system", NAMELEN); 201*32003Spc } 202*32003Spc strcpy(spcl.c_label, "none"); 203*32003Spc gethostname(spcl.c_host, NAMELEN); 204*32003Spc spcl.c_level = incno - '0'; 205*32003Spc spcl.c_type = TS_TAPE; 20632001Spc getitime(); /* /etc/dumpdates snarfed */ 20732001Spc 20832001Spc msg("Date of this level %c dump: %s\n", incno, prdate(spcl.c_date)); 20932001Spc msg("Date of last level %c dump: %s\n", 21032001Spc lastincno, prdate(spcl.c_ddate)); 21132001Spc msg("Dumping %s ", disk); 21232001Spc if (dt != 0) 21332001Spc msgtail("(%s) ", dt->fs_file); 21432001Spc #ifdef RDUMP 21532001Spc msgtail("to %s on host %s\n", tape, host); 21632001Spc #else 21732001Spc msgtail("to %s\n", tape); 21832001Spc #endif 21932001Spc 22032001Spc fi = open(disk, 0); 22132001Spc if (fi < 0) { 22232001Spc msg("Cannot open %s\n", disk); 22332001Spc Exit(X_ABORT); 22432001Spc } 22532001Spc esize = 0; 22632001Spc sblock = (struct fs *)buf; 22732001Spc sync(); 22832001Spc bread(SBLOCK, sblock, SBSIZE); 22932001Spc if (sblock->fs_magic != FS_MAGIC) { 23032001Spc msg("bad sblock magic number\n"); 23132001Spc dumpabort(); 23232001Spc } 23332001Spc msiz = roundup(howmany(sblock->fs_ipg * sblock->fs_ncg, NBBY), 23432001Spc TP_BSIZE); 23532001Spc clrmap = (char *)calloc(msiz, sizeof(char)); 23632001Spc dirmap = (char *)calloc(msiz, sizeof(char)); 23732001Spc nodmap = (char *)calloc(msiz, sizeof(char)); 23832001Spc 23932001Spc anydskipped = 0; 24032001Spc msg("mapping (Pass I) [regular files]\n"); 24132001Spc pass(mark, (char *)NULL); /* mark updates esize */ 24232001Spc 24332001Spc if (anydskipped) { 24432001Spc do { 24532001Spc msg("mapping (Pass II) [directories]\n"); 24632001Spc nadded = 0; 24732001Spc pass(add, dirmap); 24832001Spc } while(nadded); 24932001Spc } else /* keep the operators happy */ 25032001Spc msg("mapping (Pass II) [directories]\n"); 25132001Spc 25232001Spc bmapest(clrmap); 25332001Spc bmapest(nodmap); 25432001Spc 25532001Spc if (cartridge) { 25632001Spc /* Estimate number of tapes, assuming streaming stops at 25732001Spc the end of each block written, and not in mid-block. 25832001Spc Assume no erroneous blocks; this can be compensated for 25932001Spc with an artificially low tape size. */ 26032001Spc fetapes = 26132001Spc ( esize /* blocks */ 26232001Spc * TP_BSIZE /* bytes/block */ 26332001Spc * (1.0/density) /* 0.1" / byte */ 26432001Spc + 26532001Spc esize /* blocks */ 26632001Spc * (1.0/ntrec) /* streaming-stops per block */ 26732001Spc * 15.48 /* 0.1" / streaming-stop */ 26832001Spc ) * (1.0 / tsize ); /* tape / 0.1" */ 26932001Spc } else { 27032001Spc /* Estimate number of tapes, for old fashioned 9-track tape */ 27132001Spc int tenthsperirg = (density == 625) ? 3 : 7; 27232001Spc fetapes = 27332001Spc ( esize /* blocks */ 27432001Spc * TP_BSIZE /* bytes / block */ 27532001Spc * (1.0/density) /* 0.1" / byte */ 27632001Spc + 27732001Spc esize /* blocks */ 27832001Spc * (1.0/ntrec) /* IRG's / block */ 27932001Spc * tenthsperirg /* 0.1" / IRG */ 28032001Spc ) * (1.0 / tsize ); /* tape / 0.1" */ 28132001Spc } 28232001Spc etapes = fetapes; /* truncating assignment */ 28332001Spc etapes++; 28432001Spc /* count the nodemap on each additional tape */ 28532001Spc for (i = 1; i < etapes; i++) 28632001Spc bmapest(nodmap); 28732001Spc esize += i + 10; /* headers + 10 trailer blocks */ 28832001Spc msg("estimated %ld tape blocks on %3.2f tape(s).\n", esize, fetapes); 28932001Spc 29032001Spc alloctape(); /* Allocate tape buffer */ 29132001Spc 29232001Spc otape(); /* bitmap is the first to tape write */ 29332001Spc time(&(tstart_writing)); 29432001Spc bitmap(clrmap, TS_CLRI); 29532001Spc 29632001Spc msg("dumping (Pass III) [directories]\n"); 29732001Spc pass(dirdump, dirmap); 29832001Spc 29932001Spc msg("dumping (Pass IV) [regular files]\n"); 30032001Spc pass(dump, nodmap); 30132001Spc 30232001Spc spcl.c_type = TS_END; 30332001Spc #ifndef RDUMP 30432001Spc for(i=0; i<ntrec; i++) 30532001Spc spclrec(); 30632001Spc #endif 30732001Spc msg("DUMP: %ld tape blocks on %d tape(s)\n",spcl.c_tapea,spcl.c_volume); 30832001Spc msg("DUMP IS DONE\n"); 30932001Spc 31032001Spc putitime(); 31132001Spc #ifndef RDUMP 31232001Spc if (!pipeout) { 31332001Spc close(to); 31432001Spc rewind(); 31532001Spc } 31632001Spc #else 31732001Spc tflush(1); 31832001Spc rewind(); 31932001Spc #endif 32032001Spc broadcast("DUMP IS DONE!\7\7\n"); 32132001Spc Exit(X_FINOK); 32232001Spc } 32332001Spc 32432001Spc int sighup(){ msg("SIGHUP() try rewriting\n"); sigAbort();} 32532001Spc int sigtrap(){ msg("SIGTRAP() try rewriting\n"); sigAbort();} 32632001Spc int sigfpe(){ msg("SIGFPE() try rewriting\n"); sigAbort();} 32732001Spc int sigbus(){ msg("SIGBUS() try rewriting\n"); sigAbort();} 32832001Spc int sigsegv(){ msg("SIGSEGV() ABORTING!\n"); abort();} 32932001Spc int sigalrm(){ msg("SIGALRM() try rewriting\n"); sigAbort();} 33032001Spc int sigterm(){ msg("SIGTERM() try rewriting\n"); sigAbort();} 33132001Spc 33232001Spc sigAbort() 33332001Spc { 33432001Spc if (pipeout) { 33532001Spc msg("Unknown signal, cannot recover\n"); 33632001Spc dumpabort(); 33732001Spc } 33832001Spc msg("Rewriting attempted as response to unknown signal.\n"); 33932001Spc fflush(stderr); 34032001Spc fflush(stdout); 34132001Spc close_rewind(); 34232001Spc exit(X_REWRITE); 34332001Spc } 34432001Spc 34532001Spc char *rawname(cp) 34632001Spc char *cp; 34732001Spc { 34832001Spc static char rawbuf[32]; 34932001Spc char *rindex(); 35032001Spc char *dp = rindex(cp, '/'); 35132001Spc 35232001Spc if (dp == 0) 35332001Spc return (0); 35432001Spc *dp = 0; 35532001Spc strcpy(rawbuf, cp); 35632001Spc *dp = '/'; 35732001Spc strcat(rawbuf, "/r"); 35832001Spc strcat(rawbuf, dp+1); 35932001Spc return (rawbuf); 36032001Spc } 361