Print this page
5218 posix definition of NULL
correct unistd.h and iso/stddef_iso.h
update gate source affected
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/tnf/tnfxtract/tnfxtract.c
+++ new/usr/src/cmd/tnf/tnfxtract/tnfxtract.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 #pragma ident "%Z%%M% %I% %E% SMI"
28 28
29 29 #include <unistd.h>
30 30 #include <stdlib.h>
31 31 #include <stdio.h>
32 32 #include <libintl.h>
33 33 #include <unistd.h>
34 34 #include <string.h>
35 35 #include <sys/types.h>
36 36 #include <sys/stat.h>
37 37 #include <kvm.h>
38 38 #include <fcntl.h>
39 39 #include <sys/mman.h>
40 40 #include <sys/tnf.h>
41 41 #include <sys/tnf_com.h>
42 42 #include <nlist.h>
43 43 #include <errno.h>
44 44
45 45 #define TNFDEV "/dev/tnfmap"
46 46
47 47 #define MAXFWTRY 5
48 48
49 49 typedef struct {
50 50 boolean_t ever_read;
51 51 tnf_uint32_t generation;
52 52 tnf_uint16_t bytes_valid;
53 53 } BLOCK_STATUS;
54 54
55 55 static char *dumpfile; /* Dump file if extracting from crashdump */
56 56 static char *namelist; /* Symbol tbl. if extracting from crashdump */
57 57 static kvm_t *kvm_p; /* Handle for kvm_open, kvm_read, ... */
58 58
59 59 static struct nlist kvm_syms[] = {
60 60 { "tnf_buf" },
61 61 { "tnf_trace_file_size" },
62 62 { NULL }
63 63 };
64 64
65 65 static uintptr_t dump_bufaddr;
66 66 static size_t tnf_bufsize;
67 67 static char *program_name;
68 68 static int input_fd;
69 69 static int output_fd;
70 70 static tnf_file_header_t *tnf_header;
71 71
72 72 /*
73 73 * usage() - gives a description of the arguments, and exits
74 74 */
75 75
76 76 static void
77 77 usage(char *argv[], const char *msg)
78 78 {
79 79 if (msg)
80 80 (void) fprintf(stderr,
81 81 gettext("%s: %s\n"), argv[0], msg);
82 82
83 83 (void) fprintf(stderr, gettext(
84 84 "usage: %s [-d <dumpfile> -n <symbolfile> ] "
85 85 "<output-filename>\n"), argv[0]);
86 86 exit(1);
87 87 } /* end usage */
88 88
89 89
90 90 /*
91 91 * Write 'size' bytes at offset 'offset' from 'addr'
92 92 * to the output file. Bail out unceremoniously if anything goes wrong.
93 93 */
94 94 static void
95 95 writeout(char *addr, int offset, int size)
96 96
97 97 {
98 98 if (lseek(output_fd, offset, SEEK_SET) < 0) {
99 99 perror("lseek");
100 100 exit(1);
101 101 }
102 102 if (write(output_fd, addr, size) != size) {
103 103 perror("write");
104 104 exit(1);
105 105 }
106 106 }
107 107
108 108
109 109 static void
110 110 dumpfile_init()
111 111
112 112 {
113 113 kvm_p = kvm_open(namelist, dumpfile, NULL, O_RDONLY, program_name);
114 114 if (kvm_p == NULL) {
115 115 /* kvm_open prints an error message */
116 116 exit(1);
117 117 }
118 118 if (kvm_nlist(kvm_p, kvm_syms) != 0) {
119 119 (void) fprintf(stderr, gettext(
120 120 "Symbol lookup error in %s\n"), namelist);
↓ open down ↓ |
120 lines elided |
↑ open up ↑ |
121 121 exit(1);
122 122 }
123 123 if (kvm_read(kvm_p, kvm_syms[0].n_value, (char *) &dump_bufaddr,
124 124 sizeof (dump_bufaddr)) != sizeof (dump_bufaddr) ||
125 125 kvm_read(kvm_p, kvm_syms[1].n_value, (char *) &tnf_bufsize,
126 126 sizeof (tnf_bufsize)) != sizeof (tnf_bufsize)) {
127 127 (void) fprintf(stderr, gettext(
128 128 "kvm_read error in %s\n"), dumpfile);
129 129 exit(1);
130 130 }
131 - if (dump_bufaddr == NULL || tnf_bufsize == 0) {
131 + if (dump_bufaddr == (uintptr_t)NULL || tnf_bufsize == 0) {
132 132 (void) fprintf(stderr, gettext(
133 133 "No trace data available in the kernel.\n"));
134 134 exit(1);
135 135 }
136 136 }
137 137
138 138 static void
139 139 live_kernel_init()
140 140
141 141 {
142 142 tifiocstate_t tstate;
143 143
144 144 if ((input_fd = open(TNFDEV, O_RDWR)) < 0) {
145 145 perror(TNFDEV);
146 146 exit(1);
147 147 }
148 148 if (ioctl(input_fd, TIFIOCGSTATE, &tstate) < 0) {
149 149 perror(gettext("Error getting trace system state"));
150 150 exit(1);
151 151 }
152 152 if (tstate.buffer_state != TIFIOCBUF_OK) {
153 153 (void) fprintf(stderr, gettext(
154 154 "No trace data available in the kernel.\n"));
155 155 exit(1);
156 156 }
157 157 tnf_bufsize = tstate.buffer_size;
158 158 }
159 159
160 160 static void
161 161 read_tnf_header(char *addr)
162 162
163 163 {
164 164 if (dumpfile != NULL) {
165 165 if (kvm_read(kvm_p, dump_bufaddr, addr, 512) != 512) {
166 166 (void) fprintf(stderr, gettext(
167 167 "Error reading tnf header from dump file.\n"));
168 168 exit(1);
169 169 }
170 170 } else {
171 171 if (ioctl(input_fd, TIFIOCGHEADER, addr) != 0) {
172 172 perror(gettext("Error reading tnf header from kernel"));
173 173 exit(1);
174 174 }
175 175 }
176 176 }
177 177
178 178 static int
179 179 read_tnf_block(tnf_block_header_t *addr, int block_num)
180 180
181 181 {
182 182 int offset;
183 183 tifiocgblock_t ioctl_arg;
184 184
185 185 if (dumpfile != NULL) {
186 186 offset = tnf_header->directory_size +
187 187 block_num * tnf_header->block_size;
188 188 if (kvm_read(kvm_p, dump_bufaddr + offset, (char *) addr,
189 189 tnf_header->block_size) != tnf_header->block_size) {
190 190 (void) fprintf(stderr, gettext(
191 191 "Error reading tnf block.\n"));
192 192 exit(1);
193 193 }
194 194 } else {
195 195 ioctl_arg.dst_addr = (char *) addr;
196 196 ioctl_arg.block_num = block_num;
197 197 if (ioctl(input_fd, TIFIOCGBLOCK, &ioctl_arg) < 0) {
198 198 if (errno == EBUSY)
199 199 return (EBUSY);
200 200 perror(gettext("Error reading tnf block"));
201 201 exit(1);
202 202 }
203 203 }
204 204 return (0);
205 205 }
206 206
207 207 static void
208 208 read_tnf_fwzone(tnf_ref32_t *dest, int start, int slots)
209 209
210 210 {
211 211 int offset;
212 212 int len;
213 213 tifiocgfw_t ioctl_arg;
214 214
215 215 if (dumpfile != NULL) {
216 216 /* LINTED assignment of 64-bit integer to 32-bit integer */
217 217 offset = tnf_header->block_size + start * sizeof (tnf_ref32_t);
218 218 /* LINTED assignment of 64-bit integer to 32-bit integer */
219 219 len = slots * sizeof (tnf_ref32_t);
220 220 if (kvm_read(kvm_p, dump_bufaddr + offset, (char *) dest,
221 221 len) != len) {
222 222 (void) fprintf(stderr, gettext(
223 223 "Error reading tnf forwarding zone.\n"));
224 224 exit(1);
225 225 }
226 226 } else {
227 227 /* LINTED pointer cast may result in improper alignment */
228 228 ioctl_arg.dst_addr = (long *) dest;
229 229 ioctl_arg.start = start;
230 230 ioctl_arg.slots = slots;
231 231 if (ioctl(input_fd, TIFIOCGFWZONE, &ioctl_arg) < 0) {
232 232 perror(gettext("Error reading tnf block"));
233 233 exit(1);
234 234 }
235 235 }
236 236 }
237 237
238 238 int
239 239 main(int argc, char *argv[])
240 240 {
241 241 const char *optstr = "d:n:";
242 242 const char *outfile;
243 243 char *local_buf;
244 244 int c;
245 245 tnf_uint32_t *magicp;
246 246 tnf_block_header_t *block_base, *blockp;
247 247 BLOCK_STATUS *block_stat, *bsp;
248 248 int block_num;
249 249 boolean_t any_unread, any_different, retry;
250 250 tnf_ref32_t *fwzone;
251 251 int fwzonesize;
252 252 int i;
253 253 int fwtries;
254 254 int block_count;
255 255
256 256 program_name = argv[0];
257 257 while ((c = getopt(argc, argv, optstr)) != EOF) {
258 258 switch (c) {
259 259 case 'd':
260 260 dumpfile = optarg;
261 261 break;
262 262 case 'n':
263 263 namelist = optarg;
264 264 break;
265 265 case '?':
266 266 usage(argv, gettext("unrecognized argument"));
267 267 }
268 268 }
269 269 if (optind != argc - 1) {
270 270 usage(argv, gettext("too many or too few arguments"));
271 271 } else {
272 272 outfile = argv[optind];
273 273 }
274 274 if ((dumpfile != NULL) ^ (namelist != NULL)) {
275 275 usage(argv, gettext("must specify both or neither of the "
276 276 "-d and -n options"));
277 277 }
278 278
279 279 output_fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0600);
280 280 if (output_fd < 0) {
281 281 perror(outfile);
282 282 exit(1);
283 283 }
284 284 if (dumpfile != NULL)
285 285 dumpfile_init();
286 286 else
287 287 live_kernel_init();
288 288
289 289 if ((local_buf = malloc(tnf_bufsize)) == NULL) {
290 290 (void) fprintf(stderr,
291 291 gettext("tnfxtract memory allocation failure\n"));
292 292 exit(1);
293 293 }
294 294
295 295 /* Read header, get block size, check for version mismatch */
296 296 read_tnf_header(local_buf);
297 297 /*LINTED pointer cast may result in improper alignment*/
298 298 magicp = (tnf_uint32_t *) local_buf;
299 299 /*LINTED pointer cast may result in improper alignment*/
300 300 tnf_header = (tnf_file_header_t *)(local_buf + sizeof (*magicp));
301 301 if (*magicp != TNF_MAGIC) {
302 302 (void) fprintf(stderr, gettext(
303 303 "Buffer is not in TNF format.\n"));
304 304 exit(1);
305 305 }
306 306 if (tnf_header->file_version != TNF_FILE_VERSION) {
307 307 (void) fprintf(stderr,
308 308 gettext("Version mismatch (tnfxtract: %d; buffer: %d)\n"),
309 309 TNF_FILE_VERSION, tnf_header->file_version);
310 310 exit(1);
311 311 }
312 312 writeout(local_buf, 0, tnf_header->block_size);
313 313 /* LINTED pointer cast may result in improper alignment */
314 314 block_base = (tnf_block_header_t *)
315 315 (local_buf + tnf_header->directory_size);
316 316 block_count = tnf_header->block_count -
317 317 tnf_header->directory_size / tnf_header->block_size;
318 318 fwzonesize = tnf_header->directory_size - tnf_header->block_size;
319 319
320 320 block_stat = (BLOCK_STATUS *)
321 321 calloc(block_count, sizeof (BLOCK_STATUS));
322 322 if (block_stat == NULL) {
323 323 (void) fprintf(stderr,
324 324 gettext("tnfxtract memory allocation failure\n"));
325 325 exit(1);
326 326 }
327 327
328 328 for (bsp = block_stat; bsp != block_stat + block_count; ++bsp)
329 329 bsp->ever_read = B_FALSE;
330 330 /*
331 331 * Make repeated passes until we've read every non-tag block.
332 332 */
333 333 do {
334 334 any_unread = B_FALSE;
335 335 bsp = block_stat;
336 336 block_num = 0;
337 337 blockp = block_base;
338 338 while (block_num != block_count) {
339 339 if (!bsp->ever_read) {
340 340 if (read_tnf_block(blockp, block_num) != 0)
341 341 any_unread = B_TRUE;
342 342 else {
343 343 bsp->ever_read = B_TRUE;
344 344 bsp->generation = blockp->generation;
345 345 bsp->bytes_valid = blockp->bytes_valid;
346 346 writeout((char *) blockp,
347 347 /* LINTED cast 64 to 32 bit */
348 348 (int)((char *) blockp - local_buf),
349 349 tnf_header->block_size);
350 350 }
351 351 }
352 352 ++bsp;
353 353 ++block_num;
354 354 /* LINTED pointer cast may result in improper alignment */
355 355 blockp = (tnf_block_header_t *)
356 356 ((char *) blockp + tnf_header->block_size);
357 357 }
358 358 } while (any_unread);
359 359
360 360 /*
361 361 * Then read tag blocks only, until we have two consecutive,
362 362 * consistent reads.
363 363 */
364 364 do {
365 365 any_different = B_FALSE;
366 366 bsp = block_stat;
367 367 block_num = 0;
368 368 blockp = block_base;
369 369 while (block_num != block_count) {
370 370 if (read_tnf_block(blockp, block_num) == 0 &&
371 371 blockp->generation == TNF_TAG_GENERATION_NUM &&
372 372 (bsp->generation != TNF_TAG_GENERATION_NUM ||
373 373 bsp->bytes_valid != blockp->bytes_valid)) {
374 374 bsp->generation = TNF_TAG_GENERATION_NUM;
375 375 bsp->bytes_valid = blockp->bytes_valid;
376 376 writeout((char *) blockp,
377 377 /* LINTED cast 64bit to 32 bit */
378 378 (int)((char *) blockp - local_buf),
379 379 tnf_header->block_size);
380 380 any_different = B_TRUE;
381 381 }
382 382 ++bsp;
383 383 ++block_num;
384 384 /* LINTED pointer cast may result in improper alignment */
385 385 blockp = (tnf_block_header_t *)
386 386 ((char *) blockp + tnf_header->block_size);
387 387 }
388 388 } while (any_different);
389 389
390 390 /*
391 391 * Then read the forwarding pointers. If any are -1:
392 392 * sleep briefly, then make another pass.
393 393 */
394 394 /*LINTED pointer cast may result in improper alignment*/
395 395 fwzone = (tnf_ref32_t *)(local_buf + tnf_header->block_size);
396 396
397 397 read_tnf_fwzone(fwzone, 0,
398 398 /* LINTED cast from 64-bit integer to 32-bit integer */
399 399 (int)(fwzonesize / sizeof (fwzone[0])));
400 400 fwtries = 0;
401 401 while (fwtries != MAXFWTRY) {
402 402 retry = B_FALSE;
403 403 for (i = 0; i != fwzonesize / sizeof (fwzone[0]); ++i) {
404 404 if (fwzone[i] == -1) {
405 405 read_tnf_fwzone(&fwzone[i], i, 1);
406 406 if (!retry) {
407 407 retry = B_TRUE;
408 408 ++fwtries;
409 409 }
410 410 }
411 411 }
412 412 if (!retry)
413 413 break;
414 414 sleep(2);
415 415 }
416 416 if (fwtries == MAXFWTRY) {
417 417 (void) fprintf(stderr, gettext(
418 418 "Warning: forwarding pointers may "
419 419 "be invalid.\n"));
420 420 }
421 421 writeout((char *) fwzone, tnf_header->block_size, fwzonesize);
422 422 return (0);
423 423 }
↓ open down ↓ |
282 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX