|
|
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.