Arnaldo Carvalho de Melo | 94c744b | 2009-12-11 21:24:02 -0200 | [diff] [blame] | 1 | #include <linux/kernel.h> |
| 2 | |
| 3 | #include <unistd.h> |
| 4 | #include <sys/types.h> |
| 5 | |
| 6 | #include "session.h" |
| 7 | #include "util.h" |
| 8 | |
| 9 | static int perf_session__open(struct perf_session *self, bool force) |
| 10 | { |
| 11 | struct stat input_stat; |
| 12 | |
| 13 | self->fd = open(self->filename, O_RDONLY); |
| 14 | if (self->fd < 0) { |
| 15 | pr_err("failed to open file: %s", self->filename); |
| 16 | if (!strcmp(self->filename, "perf.data")) |
| 17 | pr_err(" (try 'perf record' first)"); |
| 18 | pr_err("\n"); |
| 19 | return -errno; |
| 20 | } |
| 21 | |
| 22 | if (fstat(self->fd, &input_stat) < 0) |
| 23 | goto out_close; |
| 24 | |
| 25 | if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) { |
| 26 | pr_err("file %s not owned by current user or root\n", |
| 27 | self->filename); |
| 28 | goto out_close; |
| 29 | } |
| 30 | |
| 31 | if (!input_stat.st_size) { |
| 32 | pr_info("zero-sized file (%s), nothing to do!\n", |
| 33 | self->filename); |
| 34 | goto out_close; |
| 35 | } |
| 36 | |
| 37 | if (perf_header__read(&self->header, self->fd) < 0) { |
| 38 | pr_err("incompatible file format"); |
| 39 | goto out_close; |
| 40 | } |
| 41 | |
| 42 | self->size = input_stat.st_size; |
| 43 | return 0; |
| 44 | |
| 45 | out_close: |
| 46 | close(self->fd); |
| 47 | self->fd = -1; |
| 48 | return -1; |
| 49 | } |
| 50 | |
Arnaldo Carvalho de Melo | 301a0b0 | 2009-12-13 19:50:25 -0200 | [diff] [blame] | 51 | struct perf_session *perf_session__new(const char *filename, int mode, |
| 52 | bool force) |
Arnaldo Carvalho de Melo | 94c744b | 2009-12-11 21:24:02 -0200 | [diff] [blame] | 53 | { |
| 54 | size_t len = strlen(filename) + 1; |
| 55 | struct perf_session *self = zalloc(sizeof(*self) + len); |
| 56 | |
| 57 | if (self == NULL) |
| 58 | goto out; |
| 59 | |
| 60 | if (perf_header__init(&self->header) < 0) |
| 61 | goto out_delete; |
| 62 | |
| 63 | memcpy(self->filename, filename, len); |
Arnaldo Carvalho de Melo | ec91336 | 2009-12-13 19:50:27 -0200 | [diff] [blame^] | 64 | self->mmap_window = 32; |
| 65 | self->cwd = NULL; |
| 66 | self->cwdlen = 0; |
Arnaldo Carvalho de Melo | 94c744b | 2009-12-11 21:24:02 -0200 | [diff] [blame] | 67 | |
| 68 | if (mode == O_RDONLY && perf_session__open(self, force) < 0) { |
| 69 | perf_session__delete(self); |
| 70 | self = NULL; |
| 71 | } |
| 72 | out: |
| 73 | return self; |
| 74 | out_delete: |
| 75 | free(self); |
| 76 | return NULL; |
| 77 | } |
| 78 | |
| 79 | void perf_session__delete(struct perf_session *self) |
| 80 | { |
| 81 | perf_header__exit(&self->header); |
| 82 | close(self->fd); |
Arnaldo Carvalho de Melo | ec91336 | 2009-12-13 19:50:27 -0200 | [diff] [blame^] | 83 | free(self->cwd); |
Arnaldo Carvalho de Melo | 94c744b | 2009-12-11 21:24:02 -0200 | [diff] [blame] | 84 | free(self); |
| 85 | } |