|
|
1.1 ! root 1: #ifndef lint ! 2: static char *sccsid = "@(#)savecore.c 4.13 (Berkeley) 83/07/02"; ! 3: #endif ! 4: ! 5: /* ! 6: * savecore ! 7: */ ! 8: #include <stdio.h> ! 9: #include <nlist.h> ! 10: #include <sys/param.h> ! 11: #include <sys/dir.h> ! 12: #include <sys/stat.h> ! 13: #include <sys/fs.h> ! 14: #include <sys/time.h> ! 15: ! 16: #define DAY (60L*60L*24L) ! 17: #define LEEWAY (3*DAY) ! 18: ! 19: #define eq(a,b) (!strcmp(a,b)) ! 20: #define ok(number) ((number)&0x3fffffff) ! 21: ! 22: #define SHUTDOWNLOG "/usr/adm/shutdownlog" ! 23: ! 24: struct nlist nl[] = { ! 25: #define X_DUMPDEV 0 ! 26: { "_dumpdev" }, ! 27: #define X_DUMPLO 1 ! 28: { "_dumplo" }, ! 29: #define X_TIME 2 ! 30: { "_time" }, ! 31: #define X_DUMPSIZE 3 ! 32: { "_dumpsize" }, ! 33: #define X_VERSION 4 ! 34: { "_version" }, ! 35: #define X_PANICSTR 5 ! 36: { "_panicstr" }, ! 37: #define X_DUMPMAG 6 ! 38: { "_dumpmag" }, ! 39: { "" }, ! 40: }; ! 41: ! 42: char *system; ! 43: char *dirname; /* directory to save dumps in */ ! 44: char *ddname; /* name of dump device */ ! 45: char *find_dev(); ! 46: dev_t dumpdev; /* dump device */ ! 47: time_t dumptime; /* time the dump was taken */ ! 48: int dumplo; /* where dump starts on dumpdev */ ! 49: int dumpsize; /* amount of memory dumped */ ! 50: int dumpmag; /* magic number in dump */ ! 51: time_t now; /* current date */ ! 52: char *path(); ! 53: unsigned malloc(); ! 54: char *ctime(); ! 55: char vers[80]; ! 56: char core_vers[80]; ! 57: char panic_mesg[80]; ! 58: int panicstr; ! 59: off_t lseek(); ! 60: off_t Lseek(); ! 61: ! 62: main(argc, argv) ! 63: char **argv; ! 64: int argc; ! 65: { ! 66: ! 67: if (argc != 2 && argc != 3) { ! 68: fprintf(stderr, "usage: savecore dirname [ system ]\n"); ! 69: exit(1); ! 70: } ! 71: dirname = argv[1]; ! 72: if (argc == 3) ! 73: system = argv[2]; ! 74: if (access(dirname, 2) < 0) { ! 75: perror(dirname); ! 76: exit(1); ! 77: } ! 78: read_kmem(); ! 79: if (dump_exists()) { ! 80: (void) time(&now); ! 81: check_kmem(); ! 82: log_entry(); ! 83: if (get_crashtime() && check_space()) { ! 84: save_core(); ! 85: clear_dump(); ! 86: } else ! 87: exit(1); ! 88: } ! 89: return 0; ! 90: } ! 91: ! 92: int ! 93: dump_exists() ! 94: { ! 95: register int dumpfd; ! 96: int word; ! 97: ! 98: dumpfd = Open(ddname, 0); ! 99: Lseek(dumpfd, (off_t)(dumplo + ok(nl[X_DUMPMAG].n_value)), 0); ! 100: Read(dumpfd, (char *)&word, sizeof word); ! 101: close(dumpfd); ! 102: return (word == dumpmag); ! 103: } ! 104: ! 105: clear_dump() ! 106: { ! 107: register int dumpfd; ! 108: int zero = 0; ! 109: ! 110: dumpfd = Open(ddname, 1); ! 111: Lseek(dumpfd, (off_t)(dumplo + ok(nl[X_DUMPMAG].n_value)), 0); ! 112: Write(dumpfd, (char *)&zero, sizeof zero); ! 113: close(dumpfd); ! 114: } ! 115: ! 116: char * ! 117: find_dev(dev, type) ! 118: register dev_t dev; ! 119: register int type; ! 120: { ! 121: register DIR *dfd = opendir("/dev"); ! 122: struct direct *dir; ! 123: struct stat statb; ! 124: static char devname[MAXPATHLEN + 1]; ! 125: char *dp; ! 126: ! 127: strcpy(devname, "/dev/"); ! 128: while ((dir = readdir(dfd))) { ! 129: strcpy(devname + 5, dir->d_name); ! 130: if (stat(devname, &statb)) { ! 131: perror(devname); ! 132: continue; ! 133: } ! 134: if ((statb.st_mode&S_IFMT) != type) ! 135: continue; ! 136: if (dev == statb.st_rdev) { ! 137: closedir(dfd); ! 138: dp = (char *)malloc(strlen(devname)+1); ! 139: strcpy(dp, devname); ! 140: return dp; ! 141: } ! 142: } ! 143: closedir(dfd); ! 144: fprintf(stderr, "savecore: Can't find device %d,%d\n", ! 145: major(dev), minor(dev)); ! 146: exit(1); ! 147: /*NOTREACHED*/ ! 148: } ! 149: ! 150: read_kmem() ! 151: { ! 152: int kmem; ! 153: FILE *fp; ! 154: register char *cp; ! 155: ! 156: nlist("/vmunix", nl); ! 157: if (nl[X_DUMPDEV].n_value == 0) { ! 158: fprintf(stderr, "savecore: /vmunix: dumpdev not in namelist\n"); ! 159: exit(1); ! 160: } ! 161: if (nl[X_DUMPLO].n_value == 0) { ! 162: fprintf(stderr, "savecore: /vmunix: dumplo not in namelist\n"); ! 163: exit(1); ! 164: } ! 165: if (nl[X_TIME].n_value == 0) { ! 166: fprintf(stderr, "savecore: /vmunix: time not in namelist\n"); ! 167: exit(1); ! 168: } ! 169: if (nl[X_DUMPSIZE].n_value == 0) { ! 170: fprintf(stderr, "savecore: /vmunix: dumpsize not in namelist\n"); ! 171: exit(1); ! 172: } ! 173: if (nl[X_VERSION].n_value == 0) { ! 174: fprintf(stderr, "savecore: /vmunix: version not in namelist\n"); ! 175: exit(1); ! 176: } ! 177: if (nl[X_PANICSTR].n_value == 0) { ! 178: fprintf(stderr, "savecore: /vmunix: panicstr not in namelist\n"); ! 179: exit(1); ! 180: } ! 181: if (nl[X_DUMPMAG].n_value == 0) { ! 182: fprintf(stderr, "savecore: /vmunix: dumpmag not in namelist\n"); ! 183: exit(1); ! 184: } ! 185: kmem = Open("/dev/kmem", 0); ! 186: Lseek(kmem, (long)nl[X_DUMPDEV].n_value, 0); ! 187: Read(kmem, (char *)&dumpdev, sizeof (dumpdev)); ! 188: Lseek(kmem, (long)nl[X_DUMPLO].n_value, 0); ! 189: Read(kmem, (char *)&dumplo, sizeof (dumplo)); ! 190: Lseek(kmem, (long)nl[X_DUMPMAG].n_value, 0); ! 191: Read(kmem, (char *)&dumpmag, sizeof (dumpmag)); ! 192: dumplo *= 1024L; ! 193: ddname = find_dev(dumpdev, S_IFBLK); ! 194: if ((fp = fdopen(kmem, "r")) == NULL) { ! 195: fprintf(stderr, "savecore: Couldn't fdopen kmem\n"); ! 196: exit(1); ! 197: } ! 198: if (system) ! 199: return; ! 200: fseek(fp, (long)nl[X_VERSION].n_value, 0); ! 201: fgets(vers, sizeof vers, fp); ! 202: fclose(fp); ! 203: } ! 204: ! 205: check_kmem() ! 206: { ! 207: FILE *fp; ! 208: register char *cp; ! 209: ! 210: if ((fp = fopen(ddname, "r")) == NULL) { ! 211: perror(ddname); ! 212: exit(1); ! 213: } ! 214: fseek(fp, (off_t)(dumplo+ok(nl[X_VERSION].n_value)), 0); ! 215: fgets(core_vers, sizeof core_vers, fp); ! 216: fclose(fp); ! 217: if (!eq(vers, core_vers)) ! 218: fprintf(stderr, ! 219: "savecore: Warning: vmunix version mismatch:\n\t%sand\n\t%s", ! 220: vers, core_vers); ! 221: fp = fopen(ddname, "r"); ! 222: fseek(fp, (off_t)(dumplo + ok(nl[X_PANICSTR].n_value)), 0); ! 223: fread((char *)&panicstr, sizeof panicstr, 1, fp); ! 224: if (panicstr) { ! 225: fseek(fp, dumplo + ok(panicstr), 0); ! 226: cp = panic_mesg; ! 227: do ! 228: *cp = getc(fp); ! 229: while (*cp++); ! 230: } ! 231: fclose(fp); ! 232: } ! 233: ! 234: get_crashtime() ! 235: { ! 236: int dumpfd; ! 237: time_t clobber = (time_t)0; ! 238: ! 239: if (system) ! 240: return (1); ! 241: dumpfd = Open(ddname, 0); ! 242: Lseek(dumpfd, (off_t)(dumplo + ok(nl[X_TIME].n_value)), 0); ! 243: Read(dumpfd, (char *)&dumptime, sizeof dumptime); ! 244: close(dumpfd); ! 245: if (dumptime == 0) ! 246: return (0); ! 247: printf("System went down at %s", ctime(&dumptime)); ! 248: if (dumptime < now - LEEWAY || dumptime > now + LEEWAY) { ! 249: printf("Dump time is unreasonable\n"); ! 250: return (0); ! 251: } ! 252: return (1); ! 253: } ! 254: ! 255: char * ! 256: path(file) ! 257: char *file; ! 258: { ! 259: register char *cp = (char *)malloc(strlen(file) + strlen(dirname) + 2); ! 260: ! 261: (void) strcpy(cp, dirname); ! 262: (void) strcat(cp, "/"); ! 263: (void) strcat(cp, file); ! 264: return (cp); ! 265: } ! 266: ! 267: check_space() ! 268: { ! 269: struct stat dsb; ! 270: register char *ddev; ! 271: int dfd, spacefree; ! 272: struct fs fs; ! 273: ! 274: if (stat(dirname, &dsb) < 0) { ! 275: perror(dirname); ! 276: exit(1); ! 277: } ! 278: ddev = find_dev(dsb.st_dev, S_IFBLK); ! 279: dfd = Open(ddev, 0); ! 280: Lseek(dfd, (long)(SBLOCK * DEV_BSIZE), 0); ! 281: Read(dfd, (char *)&fs, sizeof fs); ! 282: close(dfd); ! 283: spacefree = fs.fs_cstotal.cs_nbfree * fs.fs_bsize / 1024; ! 284: if (read_number("minfree") > spacefree) { ! 285: fprintf(stderr, ! 286: "savecore: Dump omitted, not enough space on device\n"); ! 287: return (0); ! 288: } ! 289: if (fs.fs_cstotal.cs_nbfree * fs.fs_frag + fs.fs_cstotal.cs_nffree < ! 290: fs.fs_dsize * fs.fs_minfree / 100) ! 291: fprintf(stderr, ! 292: "Dump performed, but free space threshold crossed\n"); ! 293: return (1); ! 294: } ! 295: ! 296: read_number(fn) ! 297: char *fn; ! 298: { ! 299: char lin[80]; ! 300: register FILE *fp; ! 301: ! 302: if ((fp = fopen(path(fn), "r")) == NULL) ! 303: return (0); ! 304: if (fgets(lin, 80, fp) == NULL) { ! 305: fclose(fp); ! 306: return (0); ! 307: } ! 308: fclose(fp); ! 309: return (atoi(lin)); ! 310: } ! 311: ! 312: save_core() ! 313: { ! 314: register int n; ! 315: char buffer[32*NBPG]; ! 316: register char *cp = buffer; ! 317: register int ifd, ofd, bounds; ! 318: register FILE *fp; ! 319: ! 320: bounds = read_number("bounds"); ! 321: ifd = Open(system?system:"/vmunix", 0); ! 322: sprintf(cp, "vmunix.%d", bounds); ! 323: ofd = Create(path(cp), 0644); ! 324: while((n = Read(ifd, cp, BUFSIZ)) > 0) ! 325: Write(ofd, cp, n); ! 326: close(ifd); ! 327: close(ofd); ! 328: ifd = Open(ddname, 0); ! 329: Lseek(ifd, (off_t)(dumplo + ok(nl[X_DUMPSIZE].n_value)), 0); ! 330: Read(ifd, (char *)&dumpsize, sizeof (dumpsize)); ! 331: sprintf(cp, "vmcore.%d", bounds); ! 332: ofd = Create(path(cp), 0644); ! 333: Lseek(ifd, (off_t)dumplo, 0); ! 334: printf("Saving %d bytes of image in vmcore.%d\n", NBPG*dumpsize, ! 335: bounds); ! 336: while (dumpsize > 0) { ! 337: n = Read(ifd, cp, (dumpsize > 32 ? 32 : dumpsize) * NBPG); ! 338: Write(ofd, cp, n); ! 339: dumpsize -= n/NBPG; ! 340: } ! 341: close(ifd); ! 342: close(ofd); ! 343: fp = fopen(path("bounds"), "w"); ! 344: fprintf(fp, "%d\n", bounds+1); ! 345: fclose(fp); ! 346: } ! 347: ! 348: char *days[] = { ! 349: "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ! 350: }; ! 351: ! 352: char *months[] = { ! 353: "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", ! 354: "Oct", "Nov", "Dec" ! 355: }; ! 356: ! 357: log_entry() ! 358: { ! 359: FILE *fp; ! 360: struct tm *tm, *localtime(); ! 361: ! 362: tm = localtime(&now); ! 363: fp = fopen("/usr/adm/shutdownlog", "a"); ! 364: if (fp == 0) ! 365: return; ! 366: fseek(fp, 0L, 2); ! 367: fprintf(fp, "%02d:%02d %s %s %2d, %4d. Reboot", tm->tm_hour, ! 368: tm->tm_min, days[tm->tm_wday], months[tm->tm_mon], ! 369: tm->tm_mday, tm->tm_year + 1900); ! 370: if (panicstr) ! 371: fprintf(fp, " after panic: %s\n", panic_mesg); ! 372: else ! 373: putc('\n', fp); ! 374: fclose(fp); ! 375: } ! 376: ! 377: /* ! 378: * Versions of std routines that exit on error. ! 379: */ ! 380: ! 381: Open(name, rw) ! 382: char *name; ! 383: int rw; ! 384: { ! 385: int fd; ! 386: ! 387: if ((fd = open(name, rw)) < 0) { ! 388: perror(name); ! 389: exit(1); ! 390: } ! 391: return fd; ! 392: } ! 393: ! 394: Read(fd, buff, size) ! 395: int fd, size; ! 396: char *buff; ! 397: { ! 398: int ret; ! 399: ! 400: if ((ret = read(fd, buff, size)) < 0) { ! 401: perror("read"); ! 402: exit(1); ! 403: } ! 404: return ret; ! 405: } ! 406: ! 407: off_t ! 408: Lseek(fd, off, flag) ! 409: int fd, flag; ! 410: long off; ! 411: { ! 412: long ret; ! 413: ! 414: if ((ret = lseek(fd, off, flag)) == -1L) { ! 415: perror("lseek"); ! 416: exit(1); ! 417: } ! 418: return ret; ! 419: } ! 420: ! 421: Create(file, mode) ! 422: char *file; ! 423: int mode; ! 424: { ! 425: register int fd; ! 426: ! 427: if ((fd = creat(file, mode)) < 0) { ! 428: perror(file); ! 429: exit(1); ! 430: } ! 431: return fd; ! 432: } ! 433: ! 434: Write(fd, buf, size) ! 435: int fd, size; ! 436: char *buf; ! 437: { ! 438: ! 439: if (write(fd, buf, size) < size) { ! 440: perror("write"); ! 441: exit(1); ! 442: } ! 443: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.