diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-06-11 14:56:03 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-06-11 14:56:03 -0400 |
commit | e5d57574f5c33207a58aba33773f05acca18c88e (patch) | |
tree | d8df642d72f524187c622e5da024e982d91a60dc | |
parent | 70b2b8bca3912a33f0eb08f95219a344faaa959b (diff) |
trace-cmd: Add tracecmd_local_events()
Add tracecmd_local_events() that returns an pevent that will
consist of the events local to the machine. It reads the
/debugfs/tracing/events directory to create them.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | trace-cmd.h | 1 | ||||
-rw-r--r-- | trace-util.c | 182 |
2 files changed, 183 insertions, 0 deletions
diff --git a/trace-cmd.h b/trace-cmd.h index ea6c356..b732484 100644 --- a/trace-cmd.h +++ b/trace-cmd.h | |||
@@ -37,6 +37,7 @@ void tracecmd_unload_plugins(struct plugin_list *list); | |||
37 | 37 | ||
38 | char **tracecmd_event_systems(const char *tracing_dir); | 38 | char **tracecmd_event_systems(const char *tracing_dir); |
39 | char **tracecmd_system_events(const char *tracing_dir, const char *system); | 39 | char **tracecmd_system_events(const char *tracing_dir, const char *system); |
40 | struct pevent *tracecmd_local_events(const char *tracing_dir); | ||
40 | 41 | ||
41 | enum { | 42 | enum { |
42 | RINGBUF_TYPE_PADDING = 29, | 43 | RINGBUF_TYPE_PADDING = 29, |
diff --git a/trace-util.c b/trace-util.c index 456687c..6d813c5 100644 --- a/trace-util.c +++ b/trace-util.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #include <ctype.h> | 26 | #include <ctype.h> |
27 | #include <errno.h> | 27 | #include <errno.h> |
28 | #include <dlfcn.h> | 28 | #include <dlfcn.h> |
29 | #include <fcntl.h> | ||
30 | #include <unistd.h> | ||
29 | #include <sys/mount.h> | 31 | #include <sys/mount.h> |
30 | #include <sys/types.h> | 32 | #include <sys/types.h> |
31 | #include <sys/stat.h> | 33 | #include <sys/stat.h> |
@@ -412,6 +414,186 @@ char **tracecmd_system_events(const char *tracing_dir, const char *system) | |||
412 | return events; | 414 | return events; |
413 | } | 415 | } |
414 | 416 | ||
417 | static int read_file(const char *file, char **buffer) | ||
418 | { | ||
419 | char *buf; | ||
420 | int len = 0; | ||
421 | int fd; | ||
422 | int r; | ||
423 | |||
424 | fd = open(file, O_RDONLY); | ||
425 | if (fd < 0) | ||
426 | return -1; | ||
427 | |||
428 | buf = malloc_or_die(BUFSIZ); | ||
429 | |||
430 | while ((r = read(fd, buf + len, BUFSIZ)) > 0) { | ||
431 | len += r; | ||
432 | buf = realloc(buf, len + BUFSIZ); | ||
433 | if (!buf) { | ||
434 | len = -1; | ||
435 | goto out; | ||
436 | } | ||
437 | } | ||
438 | |||
439 | *buffer = buf; | ||
440 | |||
441 | out: | ||
442 | close(fd); | ||
443 | |||
444 | return len; | ||
445 | } | ||
446 | |||
447 | static void load_events(struct pevent *pevent, const char *system, | ||
448 | const char *sys_dir) | ||
449 | { | ||
450 | struct dirent *dent; | ||
451 | struct stat st; | ||
452 | DIR *dir; | ||
453 | int len = 0; | ||
454 | int ret; | ||
455 | |||
456 | ret = stat(sys_dir, &st); | ||
457 | if (ret < 0 || !S_ISDIR(st.st_mode)) | ||
458 | return; | ||
459 | |||
460 | dir = opendir(sys_dir); | ||
461 | if (!dir) | ||
462 | return; | ||
463 | |||
464 | while ((dent = readdir(dir))) { | ||
465 | const char *name = dent->d_name; | ||
466 | char *event; | ||
467 | char *format; | ||
468 | char *buf; | ||
469 | |||
470 | if (strcmp(name, ".") == 0 || | ||
471 | strcmp(name, "..") == 0) | ||
472 | continue; | ||
473 | |||
474 | event = append_file(sys_dir, name); | ||
475 | ret = stat(event, &st); | ||
476 | if (ret < 0 || !S_ISDIR(st.st_mode)) | ||
477 | goto free_event; | ||
478 | |||
479 | format = append_file(event, "format"); | ||
480 | ret = stat(format, &st); | ||
481 | if (ret < 0) | ||
482 | goto free_format; | ||
483 | |||
484 | len = read_file(format, &buf); | ||
485 | if (len < 0) | ||
486 | goto free_format; | ||
487 | |||
488 | pevent_parse_event(pevent, buf, len, system); | ||
489 | free(buf); | ||
490 | free_format: | ||
491 | free(format); | ||
492 | free_event: | ||
493 | free(event); | ||
494 | } | ||
495 | |||
496 | closedir(dir); | ||
497 | } | ||
498 | |||
499 | static int read_header(struct pevent *pevent, const char *events_dir) | ||
500 | { | ||
501 | struct stat st; | ||
502 | char *header; | ||
503 | char *buf; | ||
504 | int len; | ||
505 | int ret = -1; | ||
506 | |||
507 | header = append_file(events_dir, "header_page"); | ||
508 | |||
509 | ret = stat(header, &st); | ||
510 | if (ret < 0) | ||
511 | goto out; | ||
512 | |||
513 | len = read_file(header, &buf); | ||
514 | if (len < 0) | ||
515 | goto out; | ||
516 | |||
517 | pevent_parse_header_page(pevent, buf, len, sizeof(long)); | ||
518 | |||
519 | free(buf); | ||
520 | |||
521 | ret = 0; | ||
522 | out: | ||
523 | free(header); | ||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | /** | ||
528 | * tracecmd_local_events - create a pevent from the events on system | ||
529 | * @tracing_dir: The directory that contains the events. | ||
530 | * | ||
531 | * Returns a pevent structure that contains the pevents local to | ||
532 | * the system. | ||
533 | */ | ||
534 | struct pevent *tracecmd_local_events(const char *tracing_dir) | ||
535 | { | ||
536 | struct pevent *pevent = NULL; | ||
537 | struct dirent *dent; | ||
538 | char *events_dir; | ||
539 | struct stat st; | ||
540 | DIR *dir; | ||
541 | int ret; | ||
542 | |||
543 | if (!tracing_dir) | ||
544 | return NULL; | ||
545 | |||
546 | events_dir = append_file(tracing_dir, "events"); | ||
547 | if (!events_dir) | ||
548 | return NULL; | ||
549 | |||
550 | ret = stat(events_dir, &st); | ||
551 | if (ret < 0 || !S_ISDIR(st.st_mode)) | ||
552 | goto out_free; | ||
553 | |||
554 | dir = opendir(events_dir); | ||
555 | if (!dir) | ||
556 | goto out_free; | ||
557 | |||
558 | pevent = pevent_alloc(); | ||
559 | if (!pevent) | ||
560 | goto out_free; | ||
561 | |||
562 | ret = read_header(pevent, events_dir); | ||
563 | if (ret < 0) { | ||
564 | pevent_free(pevent); | ||
565 | pevent = NULL; | ||
566 | goto out_free; | ||
567 | } | ||
568 | |||
569 | while ((dent = readdir(dir))) { | ||
570 | const char *name = dent->d_name; | ||
571 | char *sys; | ||
572 | |||
573 | if (strcmp(name, ".") == 0 || | ||
574 | strcmp(name, "..") == 0) | ||
575 | continue; | ||
576 | |||
577 | sys = append_file(events_dir, name); | ||
578 | ret = stat(sys, &st); | ||
579 | if (ret < 0 || !S_ISDIR(st.st_mode)) { | ||
580 | free(sys); | ||
581 | continue; | ||
582 | } | ||
583 | |||
584 | load_events(pevent, name, sys); | ||
585 | |||
586 | free(sys); | ||
587 | } | ||
588 | |||
589 | closedir(dir); | ||
590 | |||
591 | out_free: | ||
592 | free(events_dir); | ||
593 | |||
594 | return pevent; | ||
595 | } | ||
596 | |||
415 | static void | 597 | static void |
416 | trace_util_load_plugins_dir(struct pevent *pevent, const char *suffix, | 598 | trace_util_load_plugins_dir(struct pevent *pevent, const char *suffix, |
417 | const char *path, | 599 | const char *path, |