perf annotate: Fix typo
[linux-2.6-block.git] / tools / perf / util / util.c
CommitLineData
1aed2671 1#include "../perf.h"
4cf40131 2#include "util.h"
69e3f52d 3#include <sys/mman.h>
89fe808a 4#ifdef HAVE_BACKTRACE_SUPPORT
dc4552bf 5#include <execinfo.h>
c9f08bee 6#endif
dc4552bf
ACM
7#include <stdio.h>
8#include <stdlib.h>
cef82c9f
JO
9#include <string.h>
10#include <errno.h>
838d1452 11#include <linux/kernel.h>
4cf40131 12
1aed2671
JR
13/*
14 * XXX We need to find a better place for these things...
15 */
0c1fe6b2
ACM
16unsigned int page_size;
17
0c6332e9
ACM
18bool test_attr__enabled;
19
1aed2671 20bool perf_host = true;
c4a7dca9 21bool perf_guest = false;
1aed2671 22
1355915a
BP
23char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
24
1aed2671
JR
25void event_attr_init(struct perf_event_attr *attr)
26{
27 if (!perf_host)
28 attr->exclude_host = 1;
29 if (!perf_guest)
30 attr->exclude_guest = 1;
7e1ccd38
SE
31 /* to capture ABI version */
32 attr->size = sizeof(*attr);
1aed2671
JR
33}
34
4cf40131
ACM
35int mkdir_p(char *path, mode_t mode)
36{
37 struct stat st;
38 int err;
39 char *d = path;
40
41 if (*d != '/')
42 return -1;
43
44 if (stat(path, &st) == 0)
45 return 0;
46
47 while (*++d == '/');
48
49 while ((d = strchr(d, '/'))) {
50 *d = '\0';
51 err = stat(path, &st) && mkdir(path, mode);
52 *d++ = '/';
53 if (err)
54 return -1;
55 while (*d == '/')
56 ++d;
57 }
58 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
59}
60
9a17d726 61static int slow_copyfile(const char *from, const char *to, mode_t mode)
9e201442 62{
9a17d726 63 int err = -1;
9e201442
ACM
64 char *line = NULL;
65 size_t n;
66 FILE *from_fp = fopen(from, "r"), *to_fp;
9a17d726 67 mode_t old_umask;
9e201442
ACM
68
69 if (from_fp == NULL)
70 goto out;
71
9a17d726 72 old_umask = umask(mode ^ 0777);
9e201442 73 to_fp = fopen(to, "w");
9a17d726 74 umask(old_umask);
9e201442
ACM
75 if (to_fp == NULL)
76 goto out_fclose_from;
77
78 while (getline(&line, &n, from_fp) > 0)
79 if (fputs(line, to_fp) == EOF)
80 goto out_fclose_to;
81 err = 0;
82out_fclose_to:
83 fclose(to_fp);
84 free(line);
85out_fclose_from:
86 fclose(from_fp);
87out:
88 return err;
89}
90
9a17d726 91int copyfile_mode(const char *from, const char *to, mode_t mode)
4cf40131
ACM
92{
93 int fromfd, tofd;
94 struct stat st;
95 void *addr;
96 int err = -1;
97
98 if (stat(from, &st))
99 goto out;
100
9e201442 101 if (st.st_size == 0) /* /proc? do it slowly... */
9a17d726 102 return slow_copyfile(from, to, mode);
9e201442 103
4cf40131
ACM
104 fromfd = open(from, O_RDONLY);
105 if (fromfd < 0)
106 goto out;
107
9a17d726 108 tofd = creat(to, mode);
4cf40131
ACM
109 if (tofd < 0)
110 goto out_close_from;
111
112 addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fromfd, 0);
113 if (addr == MAP_FAILED)
114 goto out_close_to;
115
116 if (write(tofd, addr, st.st_size) == st.st_size)
117 err = 0;
118
119 munmap(addr, st.st_size);
120out_close_to:
121 close(tofd);
122 if (err)
123 unlink(to);
124out_close_from:
125 close(fromfd);
126out:
127 return err;
128}
c82ee828 129
9a17d726
AH
130int copyfile(const char *from, const char *to)
131{
132 return copyfile_mode(from, to, 0755);
133}
134
c82ee828
ACM
135unsigned long convert_unit(unsigned long value, char *unit)
136{
137 *unit = ' ';
138
139 if (value > 1000) {
140 value /= 1000;
141 *unit = 'K';
142 }
143
144 if (value > 1000) {
145 value /= 1000;
146 *unit = 'M';
147 }
148
149 if (value > 1000) {
150 value /= 1000;
151 *unit = 'G';
152 }
153
154 return value;
155}
1e7972cc 156
bc3a502b 157static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
1e7972cc
ACM
158{
159 void *buf_start = buf;
838d1452 160 size_t left = n;
1e7972cc 161
838d1452 162 while (left) {
bc3a502b
JO
163 ssize_t ret = is_read ? read(fd, buf, left) :
164 write(fd, buf, left);
1e7972cc
ACM
165
166 if (ret <= 0)
167 return ret;
168
838d1452
JO
169 left -= ret;
170 buf += ret;
1e7972cc
ACM
171 }
172
838d1452
JO
173 BUG_ON((size_t)(buf - buf_start) != n);
174 return n;
1e7972cc 175}
61e04b33 176
bc3a502b
JO
177/*
178 * Read exactly 'n' bytes or return an error.
179 */
180ssize_t readn(int fd, void *buf, size_t n)
181{
182 return ion(true, fd, buf, n);
183}
184
185/*
186 * Write exactly 'n' bytes or return an error.
187 */
188ssize_t writen(int fd, void *buf, size_t n)
189{
190 return ion(false, fd, buf, n);
191}
192
61e04b33
ACM
193size_t hex_width(u64 v)
194{
195 size_t n = 1;
196
197 while ((v >>= 4))
198 ++n;
199
200 return n;
201}
dc4552bf 202
b2aff5f6
JO
203static int hex(char ch)
204{
205 if ((ch >= '0') && (ch <= '9'))
206 return ch - '0';
207 if ((ch >= 'a') && (ch <= 'f'))
208 return ch - 'a' + 10;
209 if ((ch >= 'A') && (ch <= 'F'))
210 return ch - 'A' + 10;
211 return -1;
212}
213
214/*
215 * While we find nice hex chars, build a long_val.
216 * Return number of chars processed.
217 */
218int hex2u64(const char *ptr, u64 *long_val)
219{
220 const char *p = ptr;
221 *long_val = 0;
222
223 while (*p) {
224 const int hex_val = hex(*p);
225
226 if (hex_val < 0)
227 break;
228
229 *long_val = (*long_val << 4) | hex_val;
230 p++;
231 }
232
233 return p - ptr;
234}
235
dc4552bf 236/* Obtain a backtrace and print it to stdout. */
89fe808a 237#ifdef HAVE_BACKTRACE_SUPPORT
dc4552bf
ACM
238void dump_stack(void)
239{
240 void *array[16];
241 size_t size = backtrace(array, ARRAY_SIZE(array));
242 char **strings = backtrace_symbols(array, size);
243 size_t i;
244
245 printf("Obtained %zd stack frames.\n", size);
246
247 for (i = 0; i < size; i++)
248 printf("%s\n", strings[i]);
249
250 free(strings);
251}
c9f08bee
IT
252#else
253void dump_stack(void) {}
254#endif
2c803e52
DA
255
256void get_term_dimensions(struct winsize *ws)
257{
258 char *s = getenv("LINES");
259
260 if (s != NULL) {
261 ws->ws_row = atoi(s);
262 s = getenv("COLUMNS");
263 if (s != NULL) {
264 ws->ws_col = atoi(s);
265 if (ws->ws_row && ws->ws_col)
266 return;
267 }
268 }
269#ifdef TIOCGWINSZ
270 if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
271 ws->ws_row && ws->ws_col)
272 return;
273#endif
274 ws->ws_row = 25;
275 ws->ws_col = 80;
276}
1355915a
BP
277
278static void set_tracing_events_path(const char *mountpoint)
279{
280 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
281 mountpoint, "tracing/events");
282}
283
284const char *perf_debugfs_mount(const char *mountpoint)
285{
286 const char *mnt;
287
288 mnt = debugfs_mount(mountpoint);
289 if (!mnt)
290 return NULL;
291
292 set_tracing_events_path(mnt);
293
294 return mnt;
295}
296
297void perf_debugfs_set_path(const char *mntpt)
298{
299 snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt);
300 set_tracing_events_path(mntpt);
301}
167aedc4
NK
302
303static const char *find_debugfs(void)
304{
305 const char *path = perf_debugfs_mount(NULL);
306
307 if (!path)
308 fprintf(stderr, "Your kernel does not support the debugfs filesystem");
309
310 return path;
311}
312
313/*
314 * Finds the path to the debugfs/tracing
315 * Allocates the string and stores it.
316 */
317const char *find_tracing_dir(void)
318{
319 static char *tracing;
320 static int tracing_found;
321 const char *debugfs;
322
323 if (tracing_found)
324 return tracing;
325
326 debugfs = find_debugfs();
327 if (!debugfs)
328 return NULL;
329
330 tracing = malloc(strlen(debugfs) + 9);
331 if (!tracing)
332 return NULL;
333
334 sprintf(tracing, "%s/tracing", debugfs);
335
336 tracing_found = 1;
337 return tracing;
338}
339
340char *get_tracing_file(const char *name)
341{
342 const char *tracing;
343 char *file;
344
345 tracing = find_tracing_dir();
346 if (!tracing)
347 return NULL;
348
349 file = malloc(strlen(tracing) + strlen(name) + 2);
350 if (!file)
351 return NULL;
352
353 sprintf(file, "%s/%s", tracing, name);
354 return file;
355}
356
357void put_tracing_file(char *file)
358{
359 free(file);
360}
3b47abe1
NK
361
362int parse_nsec_time(const char *str, u64 *ptime)
363{
364 u64 time_sec, time_nsec;
365 char *end;
366
367 time_sec = strtoul(str, &end, 10);
368 if (*end != '.' && *end != '\0')
369 return -1;
370
371 if (*end == '.') {
372 int i;
373 char nsec_buf[10];
374
375 if (strlen(++end) > 9)
376 return -1;
377
378 strncpy(nsec_buf, end, 9);
379 nsec_buf[9] = '\0';
380
381 /* make it nsec precision */
382 for (i = strlen(nsec_buf); i < 9; i++)
383 nsec_buf[i] = '0';
384
385 time_nsec = strtoul(nsec_buf, &end, 10);
386 if (*end != '\0')
387 return -1;
388 } else
389 time_nsec = 0;
390
391 *ptime = time_sec * NSEC_PER_SEC + time_nsec;
392 return 0;
393}
27050f53
JO
394
395unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
396{
397 struct parse_tag *i = tags;
398
399 while (i->tag) {
400 char *s;
401
402 s = strchr(str, i->tag);
403 if (s) {
404 unsigned long int value;
405 char *endptr;
406
407 value = strtoul(str, &endptr, 10);
408 if (s != endptr)
409 break;
410
56921bec
AH
411 if (value > ULONG_MAX / i->mult)
412 break;
27050f53
JO
413 value *= i->mult;
414 return value;
415 }
416 i++;
417 }
418
419 return (unsigned long) -1;
420}
97a07f10
ACM
421
422int filename__read_int(const char *filename, int *value)
423{
424 char line[64];
425 int fd = open(filename, O_RDONLY), err = -1;
426
427 if (fd < 0)
428 return -1;
429
430 if (read(fd, line, sizeof(line)) > 0) {
431 *value = atoi(line);
432 err = 0;
433 }
434
435 close(fd);
436 return err;
437}
cef82c9f
JO
438
439int filename__read_str(const char *filename, char **buf, size_t *sizep)
440{
441 size_t size = 0, alloc_size = 0;
442 void *bf = NULL, *nbf;
443 int fd, n, err = 0;
444
445 fd = open(filename, O_RDONLY);
446 if (fd < 0)
447 return -errno;
448
449 do {
450 if (size == alloc_size) {
451 alloc_size += BUFSIZ;
452 nbf = realloc(bf, alloc_size);
453 if (!nbf) {
454 err = -ENOMEM;
455 break;
456 }
457
458 bf = nbf;
459 }
460
461 n = read(fd, bf + size, alloc_size - size);
462 if (n < 0) {
463 if (size) {
464 pr_warning("read failed %d: %s\n",
465 errno, strerror(errno));
466 err = 0;
467 } else
468 err = -errno;
469
470 break;
471 }
472
473 size += n;
474 } while (n > 0);
475
476 if (!err) {
477 *sizep = size;
478 *buf = bf;
479 } else
480 free(bf);
481
482 close(fd);
483 return err;
484}