Annotation of 43BSDTahoe/etc/savecore.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1980,1986 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: char copyright[] =
        !             9: "@(#) Copyright (c) 1980,1986 Regents of the University of California.\n\
        !            10:  All rights reserved.\n";
        !            11: #endif not lint
        !            12: 
        !            13: #ifndef lint
        !            14: static char sccsid[] = "@(#)savecore.c 5.13 (Berkeley) 10/22/87";
        !            15: #endif not lint
        !            16: 
        !            17: /*
        !            18:  * savecore
        !            19:  */
        !            20: 
        !            21: #include <stdio.h>
        !            22: #include <nlist.h>
        !            23: #include <sys/param.h>
        !            24: #include <sys/dir.h>
        !            25: #include <sys/stat.h>
        !            26: #include <sys/fs.h>
        !            27: #include <sys/time.h>
        !            28: #include <sys/file.h>
        !            29: #include <sys/syslog.h>
        !            30: 
        !            31: #define        DAY     (60L*60L*24L)
        !            32: #define        LEEWAY  (3*DAY)
        !            33: 
        !            34: #define eq(a,b) (!strcmp(a,b))
        !            35: #ifdef vax
        !            36: #define ok(number) ((number)&0x7fffffff)
        !            37: #else
        !            38: #ifdef tahoe
        !            39: #define ok(number) ((number)&~0xc0000000)
        !            40: #else
        !            41: #define ok(number) (number)
        !            42: #endif
        !            43: #endif
        !            44: 
        !            45: struct nlist current_nl[] = {  /* namelist for currently running system */
        !            46: #define X_DUMPDEV      0
        !            47:        { "_dumpdev" },
        !            48: #define X_DUMPLO       1
        !            49:        { "_dumplo" },
        !            50: #define X_TIME         2
        !            51:        { "_time" },
        !            52: #define        X_DUMPSIZE      3
        !            53:        { "_dumpsize" },
        !            54: #define X_VERSION      4
        !            55:        { "_version" },
        !            56: #define X_PANICSTR     5
        !            57:        { "_panicstr" },
        !            58: #define        X_DUMPMAG       6
        !            59:        { "_dumpmag" },
        !            60:        { "" },
        !            61: };
        !            62: 
        !            63: struct nlist dump_nl[] = {     /* name list for dumped system */
        !            64:        { "_dumpdev" },         /* entries MUST be the same as */
        !            65:        { "_dumplo" },          /*      those in current_nl[]  */
        !            66:        { "_time" },
        !            67:        { "_dumpsize" },
        !            68:        { "_version" },
        !            69:        { "_panicstr" },
        !            70:        { "_dumpmag" },
        !            71:        { "" },
        !            72: };
        !            73: 
        !            74: char   *system;
        !            75: char   *dirname;                       /* directory to save dumps in */
        !            76: char   *ddname;                        /* name of dump device */
        !            77: char   *find_dev();
        !            78: dev_t  dumpdev;                        /* dump device */
        !            79: time_t dumptime;                       /* time the dump was taken */
        !            80: int    dumplo;                         /* where dump starts on dumpdev */
        !            81: int    dumpsize;                       /* amount of memory dumped */
        !            82: int    dumpmag;                        /* magic number in dump */
        !            83: time_t now;                            /* current date */
        !            84: char   *path();
        !            85: char   *malloc();
        !            86: char   *ctime();
        !            87: char   vers[80];
        !            88: char   core_vers[80];
        !            89: char   panic_mesg[80];
        !            90: int    panicstr;
        !            91: off_t  lseek();
        !            92: off_t  Lseek();
        !            93: int    Verbose;
        !            94: int    force;
        !            95: int    clear;
        !            96: extern int errno;
        !            97: 
        !            98: main(argc, argv)
        !            99:        char **argv;
        !           100:        int argc;
        !           101: {
        !           102:        char *cp;
        !           103: 
        !           104:        argc--, argv++;
        !           105:        while (argc > 0 && argv[0][0] == '-') {
        !           106:                for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
        !           107: 
        !           108:                case 'f':
        !           109:                        force++;
        !           110:                        break;
        !           111: 
        !           112:                case 'v':
        !           113:                        Verbose++;
        !           114:                        break;
        !           115: 
        !           116:                case 'c':
        !           117:                        clear++;
        !           118:                        break;
        !           119: 
        !           120:                default:
        !           121:                usage:
        !           122:                        fprintf(stderr,
        !           123:                            "usage: savecore [-f] [-v] dirname [ system ]\n");
        !           124:                        exit(1);
        !           125:                }
        !           126:                argc--, argv++;
        !           127:        }
        !           128:        if (argc != 1 && argc != 2)
        !           129:                goto usage;
        !           130:        dirname = argv[0];
        !           131:        if (argc == 2)
        !           132:                system = argv[1];
        !           133:        openlog("savecore", LOG_ODELAY, LOG_AUTH);
        !           134:        if (access(dirname, W_OK) < 0) {
        !           135:                Perror(LOG_ERR, "%s: %m", dirname);
        !           136:                exit(1);
        !           137:        }
        !           138:        read_kmem();
        !           139:        if (!dump_exists()) {
        !           140:                if (Verbose)
        !           141:                        fprintf(stderr, "savecore: No dump exists.\n");
        !           142:                exit(0);
        !           143:        }
        !           144:        if (clear) {
        !           145:                clear_dump();
        !           146:                exit(0);
        !           147:        }
        !           148:        (void) time(&now);
        !           149:        check_kmem();
        !           150:        if (panicstr)
        !           151:                syslog(LOG_CRIT, "reboot after panic: %s\n", panic_mesg);
        !           152:        else
        !           153:                syslog(LOG_CRIT, "reboot\n");
        !           154:        if ((!get_crashtime() || !check_space()) && !force)
        !           155:                exit(1);
        !           156:        save_core();
        !           157:        clear_dump();
        !           158:        exit(0);
        !           159: }
        !           160: 
        !           161: dump_exists()
        !           162: {
        !           163:        register int dumpfd;
        !           164:        int word;
        !           165: 
        !           166:        dumpfd = Open(ddname, O_RDONLY);
        !           167:        Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET);
        !           168:        Read(dumpfd, (char *)&word, sizeof (word));
        !           169:        close(dumpfd);
        !           170:        if (Verbose && word != dumpmag) {
        !           171:                printf("dumplo = %d (%d bytes)\n", dumplo/DEV_BSIZE, dumplo);
        !           172:                printf("magic number mismatch: %x != %x\n", word, dumpmag);
        !           173:        }
        !           174:        return (word == dumpmag);
        !           175: }
        !           176: 
        !           177: clear_dump()
        !           178: {
        !           179:        register int dumpfd;
        !           180:        int zero = 0;
        !           181: 
        !           182:        dumpfd = Open(ddname, O_WRONLY);
        !           183:        Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET);
        !           184:        Write(dumpfd, (char *)&zero, sizeof (zero));
        !           185:        close(dumpfd);
        !           186: }
        !           187: 
        !           188: char *
        !           189: find_dev(dev, type)
        !           190:        register dev_t dev;
        !           191:        register int type;
        !           192: {
        !           193:        register DIR *dfd = opendir("/dev");
        !           194:        struct direct *dir;
        !           195:        struct stat statb;
        !           196:        static char devname[MAXPATHLEN + 1];
        !           197:        char *dp;
        !           198: 
        !           199:        strcpy(devname, "/dev/");
        !           200:        while ((dir = readdir(dfd))) {
        !           201:                strcpy(devname + 5, dir->d_name);
        !           202:                if (stat(devname, &statb)) {
        !           203:                        perror(devname);
        !           204:                        continue;
        !           205:                }
        !           206:                if ((statb.st_mode&S_IFMT) != type)
        !           207:                        continue;
        !           208:                if (dev == statb.st_rdev) {
        !           209:                        closedir(dfd);
        !           210:                        dp = malloc(strlen(devname)+1);
        !           211:                        strcpy(dp, devname);
        !           212:                        return (dp);
        !           213:                }
        !           214:        }
        !           215:        closedir(dfd);
        !           216:        log(LOG_ERR, "Can't find device %d/%d\n", major(dev), minor(dev));
        !           217:        exit(1);
        !           218:        /*NOTREACHED*/
        !           219: }
        !           220: 
        !           221: int    cursyms[] =
        !           222:     { X_DUMPDEV, X_DUMPLO, X_VERSION, X_DUMPMAG, -1 };
        !           223: int    dumpsyms[] =
        !           224:     { X_TIME, X_DUMPSIZE, X_VERSION, X_PANICSTR, X_DUMPMAG, -1 };
        !           225: read_kmem()
        !           226: {
        !           227:        register char *cp;
        !           228:        FILE *fp;
        !           229:        char *dump_sys;
        !           230:        int kmem, i;
        !           231:        
        !           232:        dump_sys = system ? system : "/vmunix";
        !           233:        nlist("/vmunix", current_nl);
        !           234:        nlist(dump_sys, dump_nl);
        !           235:        /*
        !           236:         * Some names we need for the currently running system,
        !           237:         * others for the system that was running when the dump was made.
        !           238:         * The values obtained from the current system are used
        !           239:         * to look for things in /dev/kmem that cannot be found
        !           240:         * in the dump_sys namelist, but are presumed to be the same
        !           241:         * (since the disk partitions are probably the same!)
        !           242:         */
        !           243:        for (i = 0; cursyms[i] != -1; i++)
        !           244:                if (current_nl[cursyms[i]].n_value == 0) {
        !           245:                        log(LOG_ERR, "/vmunix: %s not in namelist\n",
        !           246:                            current_nl[cursyms[i]].n_name);
        !           247:                        exit(1);
        !           248:                }
        !           249:        for (i = 0; dumpsyms[i] != -1; i++)
        !           250:                if (dump_nl[dumpsyms[i]].n_value == 0) {
        !           251:                        log(LOG_ERR, "%s: %s not in namelist\n", dump_sys,
        !           252:                            dump_nl[dumpsyms[i]].n_name);
        !           253:                        exit(1);
        !           254:                }
        !           255:        kmem = Open("/dev/kmem", O_RDONLY);
        !           256:        Lseek(kmem, (long)current_nl[X_DUMPDEV].n_value, L_SET);
        !           257:        Read(kmem, (char *)&dumpdev, sizeof (dumpdev));
        !           258:        Lseek(kmem, (long)current_nl[X_DUMPLO].n_value, L_SET);
        !           259:        Read(kmem, (char *)&dumplo, sizeof (dumplo));
        !           260:        Lseek(kmem, (long)current_nl[X_DUMPMAG].n_value, L_SET);
        !           261:        Read(kmem, (char *)&dumpmag, sizeof (dumpmag));
        !           262:        dumplo *= DEV_BSIZE;
        !           263:        ddname = find_dev(dumpdev, S_IFBLK);
        !           264:        fp = fdopen(kmem, "r");
        !           265:        if (fp == NULL) {
        !           266:                log(LOG_ERR, "Couldn't fdopen kmem\n");
        !           267:                exit(1);
        !           268:        }
        !           269:        if (system)
        !           270:                return;
        !           271:        fseek(fp, (long)current_nl[X_VERSION].n_value, L_SET);
        !           272:        fgets(vers, sizeof (vers), fp);
        !           273:        fclose(fp);
        !           274: }
        !           275: 
        !           276: check_kmem()
        !           277: {
        !           278:        FILE *fp;
        !           279:        register char *cp;
        !           280: 
        !           281:        fp = fopen(ddname, "r");
        !           282:        if (fp == NULL) {
        !           283:                Perror(LOG_ERR, "%s: %m", ddname);
        !           284:                exit(1);
        !           285:        }
        !           286:        fseek(fp, (off_t)(dumplo+ok(dump_nl[X_VERSION].n_value)), L_SET);
        !           287:        fgets(core_vers, sizeof (core_vers), fp);
        !           288:        fclose(fp);
        !           289:        if (!eq(vers, core_vers) && system == 0) {
        !           290:                log(LOG_WARNING, "Warning: vmunix version mismatch:\n");
        !           291:                log(LOG_WARNING, "\t%s\n", vers);
        !           292:                log(LOG_WARNING, "and\t%s\n", core_vers);
        !           293:        }
        !           294:        fp = fopen(ddname, "r");
        !           295:        fseek(fp, (off_t)(dumplo + ok(dump_nl[X_PANICSTR].n_value)), L_SET);
        !           296:        fread((char *)&panicstr, sizeof (panicstr), 1, fp);
        !           297:        if (panicstr) {
        !           298:                fseek(fp, dumplo + ok(panicstr), L_SET);
        !           299:                cp = panic_mesg;
        !           300:                do
        !           301:                        *cp = getc(fp);
        !           302:                while (*cp++);
        !           303:        }
        !           304:        fclose(fp);
        !           305: }
        !           306: 
        !           307: get_crashtime()
        !           308: {
        !           309:        int dumpfd;
        !           310:        time_t clobber = (time_t)0;
        !           311: 
        !           312:        dumpfd = Open(ddname, O_RDONLY);
        !           313:        Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_TIME].n_value)), L_SET);
        !           314:        Read(dumpfd, (char *)&dumptime, sizeof dumptime);
        !           315:        close(dumpfd);
        !           316:        if (dumptime == 0) {
        !           317:                if (Verbose)
        !           318:                        printf("Dump time is zero.\n");
        !           319:                return (0);
        !           320:        }
        !           321:        printf("System went down at %s", ctime(&dumptime));
        !           322:        if (dumptime < now - LEEWAY || dumptime > now + LEEWAY) {
        !           323:                printf("dump time is unreasonable\n");
        !           324:                return (0);
        !           325:        }
        !           326:        return (1);
        !           327: }
        !           328: 
        !           329: char *
        !           330: path(file)
        !           331:        char *file;
        !           332: {
        !           333:        register char *cp = malloc(strlen(file) + strlen(dirname) + 2);
        !           334: 
        !           335:        (void) strcpy(cp, dirname);
        !           336:        (void) strcat(cp, "/");
        !           337:        (void) strcat(cp, file);
        !           338:        return (cp);
        !           339: }
        !           340: 
        !           341: check_space()
        !           342: {
        !           343:        struct stat dsb;
        !           344:        register char *ddev;
        !           345:        int dfd, spacefree;
        !           346:        struct fs fs;
        !           347: 
        !           348:        if (stat(dirname, &dsb) < 0) {
        !           349:                Perror(LOG_ERR, "%s: %m", dirname);
        !           350:                exit(1);
        !           351:        }
        !           352:        ddev = find_dev(dsb.st_dev, S_IFBLK);
        !           353:        dfd = Open(ddev, O_RDONLY);
        !           354:        Lseek(dfd, SBOFF, L_SET);
        !           355:        Read(dfd, (char *)&fs, sizeof (fs));
        !           356:        close(dfd);
        !           357:        spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024;
        !           358:        if (spacefree < read_number("minfree")) {
        !           359:                log(LOG_WARNING, "Dump omitted, not enough space on device\n");
        !           360:                return (0);
        !           361:        }
        !           362:        if (freespace(&fs, fs.fs_minfree) < 0)
        !           363:                log(LOG_WARNING,
        !           364:                    "Dump performed, but free space threshold crossed\n");
        !           365:        return (1);
        !           366: }
        !           367: 
        !           368: read_number(fn)
        !           369:        char *fn;
        !           370: {
        !           371:        char lin[80];
        !           372:        register FILE *fp;
        !           373: 
        !           374:        fp = fopen(path(fn), "r");
        !           375:        if (fp == NULL)
        !           376:                return (0);
        !           377:        if (fgets(lin, 80, fp) == NULL) {
        !           378:                fclose(fp);
        !           379:                return (0);
        !           380:        }
        !           381:        fclose(fp);
        !           382:        return (atoi(lin));
        !           383: }
        !           384: 
        !           385: #define        BUFPAGES        (256*1024/NBPG)         /* 1/4 Mb */
        !           386: 
        !           387: save_core()
        !           388: {
        !           389:        register int n;
        !           390:        register char *cp;
        !           391:        register int ifd, ofd, bounds;
        !           392:        register FILE *fp;
        !           393: 
        !           394:        cp = malloc(BUFPAGES*NBPG);
        !           395:        if (cp == 0) {
        !           396:                fprintf(stderr, "savecore: Can't allocate i/o buffer.\n");
        !           397:                return;
        !           398:        }
        !           399:        bounds = read_number("bounds");
        !           400:        ifd = Open(system?system:"/vmunix", O_RDONLY);
        !           401:        (void)sprintf(cp, "vmunix.%d", bounds);
        !           402:        ofd = Create(path(cp), 0644);
        !           403:        while((n = Read(ifd, cp, BUFSIZ)) > 0)
        !           404:                Write(ofd, cp, n);
        !           405:        close(ifd);
        !           406:        close(ofd);
        !           407:        ifd = Open(ddname, O_RDONLY);
        !           408:        Lseek(ifd, (off_t)(dumplo + ok(dump_nl[X_DUMPSIZE].n_value)), L_SET);
        !           409:        Read(ifd, (char *)&dumpsize, sizeof (dumpsize));
        !           410:        (void)sprintf(cp, "vmcore.%d", bounds);
        !           411:        ofd = Create(path(cp), 0644);
        !           412:        Lseek(ifd, (off_t)dumplo, L_SET);
        !           413:        log(LOG_NOTICE, "Saving %d bytes of image in vmcore.%d\n",
        !           414:            NBPG*dumpsize, bounds);
        !           415:        while (dumpsize > 0) {
        !           416:                n = Read(ifd, cp,
        !           417:                    (dumpsize > BUFPAGES ? BUFPAGES : dumpsize) * NBPG);
        !           418:                if (n == 0) {
        !           419:                        log(LOG_WARNING, "WARNING: vmcore may be incomplete\n");
        !           420:                        break;
        !           421:                }
        !           422:                Write(ofd, cp, n);
        !           423:                dumpsize -= n/NBPG;
        !           424:        }
        !           425:        close(ifd);
        !           426:        close(ofd);
        !           427:        fp = fopen(path("bounds"), "w");
        !           428:        fprintf(fp, "%d\n", bounds+1);
        !           429:        fclose(fp);
        !           430:        free(cp);
        !           431: }
        !           432: 
        !           433: /*
        !           434:  * Versions of std routines that exit on error.
        !           435:  */
        !           436: Open(name, rw)
        !           437:        char *name;
        !           438:        int rw;
        !           439: {
        !           440:        int fd;
        !           441: 
        !           442:        fd = open(name, rw);
        !           443:        if (fd < 0) {
        !           444:                Perror(LOG_ERR, "%s: %m", name);
        !           445:                exit(1);
        !           446:        }
        !           447:        return (fd);
        !           448: }
        !           449: 
        !           450: Read(fd, buff, size)
        !           451:        int fd, size;
        !           452:        char *buff;
        !           453: {
        !           454:        int ret;
        !           455: 
        !           456:        ret = read(fd, buff, size);
        !           457:        if (ret < 0) {
        !           458:                Perror(LOG_ERR, "read: %m");
        !           459:                exit(1);
        !           460:        }
        !           461:        return (ret);
        !           462: }
        !           463: 
        !           464: off_t
        !           465: Lseek(fd, off, flag)
        !           466:        int fd, flag;
        !           467:        long off;
        !           468: {
        !           469:        long ret;
        !           470: 
        !           471:        ret = lseek(fd, off, flag);
        !           472:        if (ret == -1) {
        !           473:                Perror(LOG_ERR, "lseek: %m");
        !           474:                exit(1);
        !           475:        }
        !           476:        return (ret);
        !           477: }
        !           478: 
        !           479: Create(file, mode)
        !           480:        char *file;
        !           481:        int mode;
        !           482: {
        !           483:        register int fd;
        !           484: 
        !           485:        fd = creat(file, mode);
        !           486:        if (fd < 0) {
        !           487:                Perror(LOG_ERR, "%s: %m", file);
        !           488:                exit(1);
        !           489:        }
        !           490:        return (fd);
        !           491: }
        !           492: 
        !           493: Write(fd, buf, size)
        !           494:        int fd, size;
        !           495:        char *buf;
        !           496: {
        !           497: 
        !           498:        if (write(fd, buf, size) < size) {
        !           499:                Perror(LOG_ERR, "write: %m");
        !           500:                exit(1);
        !           501:        }
        !           502: }
        !           503: 
        !           504: log(level, msg, a1, a2)
        !           505:        int level;
        !           506:        char *msg;
        !           507: {
        !           508: 
        !           509:        fprintf(stderr, msg, a1, a2);
        !           510:        syslog(level, msg, a1, a2);
        !           511: }
        !           512: 
        !           513: Perror(level, msg, s)
        !           514:        int level;
        !           515:        char *msg;
        !           516: {
        !           517:        int oerrno = errno;
        !           518:        
        !           519:        perror(s);
        !           520:        errno = oerrno;
        !           521:        syslog(level, msg, s);
        !           522: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.