|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include <libc.h> ! 3: #include <errno.h> ! 4: #include <fstab.h> /* only for compatibility hack/guess */ ! 5: ! 6: /* ! 7: * dump header. manifest in the system; ! 8: * address and magic number are guaranteed not to change ! 9: */ ! 10: ! 11: #define MAGICADDR 0x20 /* where the header always will be */ ! 12: #define DUMPMAG 0x79646e61 /* magic number */ ! 13: #define DUMPBAD 0 /* not the magic number */ ! 14: #define DUMPBLK 512 /* dump size in these units */ ! 15: struct dumpmagic { ! 16: long magic; ! 17: long time; /* when the dump was written */ ! 18: long len; /* 512-byte blocks in dump */ ! 19: }; ! 20: ! 21: struct dumpmagic *magic; ! 22: struct dumpmagic *dumpdata(); ! 23: char *outfile, *infile; /* only so we can print them */ ! 24: ! 25: #define NBLKS 16 /* blocks of dump to read at once */ ! 26: ! 27: main(argc, argv) ! 28: int argc; ! 29: char **argv; ! 30: { ! 31: char *writedir; ! 32: char *readname; ! 33: int fr, to; ! 34: ! 35: if (argc < 2) { ! 36: fprintf(stderr, "usage: savecore target dump\n"); ! 37: exit(1); ! 38: } ! 39: setbuf(stdout, NULL); ! 40: writedir = argv[1]; ! 41: readname = NULL; ! 42: if (argc > 2) ! 43: readname = argv[2]; ! 44: if ((fr = opendump(readname)) < 0) ! 45: exit(2); /* nothing to copy */ ! 46: if ((to = openout(writedir)) < 0) ! 47: exit(1); ! 48: printf("%s %s: %ld bytes of crash dump from %s", ! 49: outfile, infile, magic->len*DUMPBLK, ctime(&magic->time)); ! 50: if (copydump(fr, to)) ! 51: dumpinval(fr); ! 52: copysys(); ! 53: exit(0); ! 54: } ! 55: ! 56: /* ! 57: * open an output file: ! 58: * if it exists and is a directory, make a new file there ! 59: * if it doesn't, or is a regular file, just copy it to that name ! 60: */ ! 61: ! 62: openout(name) ! 63: char *name; ! 64: { ! 65: int fd; ! 66: int i; ! 67: static char namebuf[20]; ! 68: ! 69: if ((fd = creat(name, 0666)) >= 0) { ! 70: outfile = name; ! 71: return (fd); ! 72: } ! 73: if (errno != EISDIR) { ! 74: perror(name); ! 75: return (-1); ! 76: } ! 77: if (chdir(name) < 0) { ! 78: perror(name); ! 79: return (-1); ! 80: } ! 81: for (i = 0; ; i++) { ! 82: sprintf(namebuf, "z.%d", i); ! 83: if (access(namebuf, 0) < 0) ! 84: break; ! 85: } ! 86: if ((fd = creat(namebuf, 0666)) >= 0) { ! 87: outfile = namebuf; ! 88: return (fd); ! 89: } ! 90: perror(namebuf); ! 91: return (-1); ! 92: } ! 93: ! 94: /* ! 95: * copy /unix to a place in the directory, ! 96: * with a suffix matching the dump we just wrote ! 97: * if output was just a filename, don't bother. ! 98: * why bother anyway? ! 99: */ ! 100: copysys() ! 101: { ! 102: } ! 103: ! 104: /* ! 105: * open the crash dump ! 106: * if no name was given, make a guess: ! 107: * try the swap devices in /etc/fstab ! 108: * if that doesn't work, guess at the default swap device. ! 109: * the dogma is that the name should be supplied anyway, ! 110: * and the guesses are for compatibility ! 111: */ ! 112: char *swapguess[] = { "/dev/ra01", "/dev/hp01", "/dev/em01", NULL }; ! 113: ! 114: int ! 115: opendump(name) ! 116: char *name; ! 117: { ! 118: int fd; ! 119: register struct fstab *fp; ! 120: register int i; ! 121: ! 122: if (name) { ! 123: if ((fd = open(name, 2)) < 0) { ! 124: perror(name); ! 125: return (-1); ! 126: } ! 127: if ((magic = dumpdata(fd)) == NULL) { ! 128: close(fd); ! 129: return (-1); ! 130: } ! 131: infile = name; ! 132: return (fd); ! 133: } ! 134: /* ! 135: * the hard part ! 136: */ ! 137: printf("I can guess your dump device!\n"); ! 138: while ((fp = getfsent()) != NULL) { ! 139: if (fp->fs_ftype != FSSWAP) ! 140: continue; ! 141: if ((fd = open(fp->fs_spec, 2)) < 0) ! 142: continue; ! 143: if ((magic = dumpdata(fd)) == NULL) { ! 144: printf("Is it %s? No.\n", fp->fs_spec); ! 145: close(fd); ! 146: continue; ! 147: } ! 148: printf("It's %s.\n", fp->fs_spec); ! 149: infile = fp->fs_spec; ! 150: return (fd); ! 151: } ! 152: for (i = 0; swapguess[i]; i++) { ! 153: if ((fd = open(swapguess[i], 2)) < 0) ! 154: continue; ! 155: if ((magic = dumpdata(fd)) == NULL) { ! 156: printf("Is it %s? No.\n", swapguess[i]); ! 157: close(fd); ! 158: continue; ! 159: } ! 160: printf("It's %s.\n", swapguess[i]); ! 161: infile = swapguess[i]; ! 162: return (fd); ! 163: } ! 164: printf("I give up!\n"); ! 165: return (-1); ! 166: } ! 167: ! 168: /* ! 169: * copy the crash dump ! 170: */ ! 171: copydump(fr, to) ! 172: int fr, to; ! 173: { ! 174: char buf[NBLKS*DUMPBLK]; ! 175: register int n, r; ! 176: register long b; ! 177: ! 178: lseek(fr, (long)0, 0); ! 179: for (b = magic->len * DUMPBLK; b > 0; b -= n) { ! 180: if (b > sizeof(buf)) ! 181: r = sizeof(buf); ! 182: else ! 183: r = b; ! 184: if ((n = read(fr, buf, r)) <= 0) { ! 185: if (n < 0) ! 186: perror("read dump"); ! 187: else ! 188: fprintf(stderr, "premature EOF on dump: %ld missing\n", b); ! 189: return (1); /* accept it anyway */ ! 190: } ! 191: if (write(to, buf, n) != n) { ! 192: perror("write dump"); ! 193: return (0); ! 194: } ! 195: } ! 196: return (1); ! 197: } ! 198: ! 199: static char hbuf[DUMPBLK]; ! 200: ! 201: /* ! 202: * read the header out of a dump, ! 203: * and check it for validity ! 204: */ ! 205: struct dumpmagic * ! 206: dumpdata(fd) ! 207: int fd; ! 208: { ! 209: register struct dumpmagic *mp; ! 210: ! 211: if (lseek(fd, 0L, 0) < 0) ! 212: return (NULL); ! 213: if (read(fd, hbuf, sizeof(hbuf)) != sizeof(hbuf)) ! 214: return (NULL); ! 215: mp = (struct dumpmagic *)&hbuf[MAGICADDR]; ! 216: if (mp->magic != DUMPMAG) ! 217: return (NULL); ! 218: return (mp); ! 219: } ! 220: ! 221: /* ! 222: * scribble on the header, ! 223: * so we won't read this dump again ! 224: */ ! 225: dumpinval(fd) ! 226: int fd; ! 227: { ! 228: ! 229: ((struct dumpmagic *)&hbuf[MAGICADDR])->magic = DUMPBAD; ! 230: lseek(fd, 0L, 0); ! 231: if (write(fd, hbuf, sizeof(hbuf)) != sizeof(hbuf)) ! 232: perror("taint header"); ! 233: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.