aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/abspath.c81
-rw-r--r--tools/perf/util/cache.h55
-rw-r--r--tools/perf/util/config.c461
-rw-r--r--tools/perf/util/exec_cmd.c2
-rw-r--r--tools/perf/util/exec_cmd.h1
-rw-r--r--tools/perf/util/help.c30
-rw-r--r--tools/perf/util/path.c202
-rw-r--r--tools/perf/util/quote.c433
-rw-r--r--tools/perf/util/quote.h39
-rw-r--r--tools/perf/util/run-command.c90
-rw-r--r--tools/perf/util/run-command.h30
-rw-r--r--tools/perf/util/session.c1
-rw-r--r--tools/perf/util/sigchain.c2
-rw-r--r--tools/perf/util/sigchain.h1
-rw-r--r--tools/perf/util/strbuf.c229
-rw-r--r--tools/perf/util/strbuf.h45
-rw-r--r--tools/perf/util/util.h154
-rw-r--r--tools/perf/util/wrapper.c72
18 files changed, 19 insertions, 1909 deletions
diff --git a/tools/perf/util/abspath.c b/tools/perf/util/abspath.c
index a791dd467261..0e76affe9c36 100644
--- a/tools/perf/util/abspath.c
+++ b/tools/perf/util/abspath.c
@@ -1,86 +1,5 @@
1#include "cache.h" 1#include "cache.h"
2 2
3/*
4 * Do not use this for inspecting *tracked* content. When path is a
5 * symlink to a directory, we do not want to say it is a directory when
6 * dealing with tracked content in the working tree.
7 */
8static int is_directory(const char *path)
9{
10 struct stat st;
11 return (!stat(path, &st) && S_ISDIR(st.st_mode));
12}
13
14/* We allow "recursive" symbolic links. Only within reason, though. */
15#define MAXDEPTH 5
16
17const char *make_absolute_path(const char *path)
18{
19 static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
20 char cwd[1024] = "";
21 int buf_index = 1, len;
22
23 int depth = MAXDEPTH;
24 char *last_elem = NULL;
25 struct stat st;
26
27 if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
28 die ("Too long path: %.*s", 60, path);
29
30 while (depth--) {
31 if (!is_directory(buf)) {
32 char *last_slash = strrchr(buf, '/');
33 if (last_slash) {
34 *last_slash = '\0';
35 last_elem = xstrdup(last_slash + 1);
36 } else {
37 last_elem = xstrdup(buf);
38 *buf = '\0';
39 }
40 }
41
42 if (*buf) {
43 if (!*cwd && !getcwd(cwd, sizeof(cwd)))
44 die ("Could not get current working directory");
45
46 if (chdir(buf))
47 die ("Could not switch to '%s'", buf);
48 }
49 if (!getcwd(buf, PATH_MAX))
50 die ("Could not get current working directory");
51
52 if (last_elem) {
53 len = strlen(buf);
54
55 if (len + strlen(last_elem) + 2 > PATH_MAX)
56 die ("Too long path name: '%s/%s'",
57 buf, last_elem);
58 buf[len] = '/';
59 strcpy(buf + len + 1, last_elem);
60 free(last_elem);
61 last_elem = NULL;
62 }
63
64 if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
65 len = readlink(buf, next_buf, PATH_MAX);
66 if (len < 0)
67 die ("Invalid symlink: %s", buf);
68 if (PATH_MAX <= len)
69 die("symbolic link too long: %s", buf);
70 next_buf[len] = '\0';
71 buf = next_buf;
72 buf_index = 1 - buf_index;
73 next_buf = bufs[buf_index];
74 } else
75 break;
76 }
77
78 if (*cwd && chdir(cwd))
79 die ("Could not change back to '%s'", cwd);
80
81 return buf;
82}
83
84static const char *get_pwd_cwd(void) 3static const char *get_pwd_cwd(void)
85{ 4{
86 static char cwd[PATH_MAX + 1]; 5 static char cwd[PATH_MAX + 1];
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 4b9aab7f0405..5eca52595b62 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -13,56 +13,16 @@
13 13
14#define PERF_DIR_ENVIRONMENT "PERF_DIR" 14#define PERF_DIR_ENVIRONMENT "PERF_DIR"
15#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE" 15#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE"
16#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
17#define DB_ENVIRONMENT "PERF_OBJECT_DIRECTORY"
18#define INDEX_ENVIRONMENT "PERF_INDEX_FILE"
19#define GRAFT_ENVIRONMENT "PERF_GRAFT_FILE"
20#define TEMPLATE_DIR_ENVIRONMENT "PERF_TEMPLATE_DIR"
21#define CONFIG_ENVIRONMENT "PERF_CONFIG"
22#define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH" 16#define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH"
23#define CEILING_DIRECTORIES_ENVIRONMENT "PERF_CEILING_DIRECTORIES" 17#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
24#define PERFATTRIBUTES_FILE ".perfattributes"
25#define INFOATTRIBUTES_FILE "info/attributes"
26#define ATTRIBUTE_MACRO_PREFIX "[attr]"
27#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" 18#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
28 19
29typedef int (*config_fn_t)(const char *, const char *, void *); 20typedef int (*config_fn_t)(const char *, const char *, void *);
30extern int perf_default_config(const char *, const char *, void *); 21extern int perf_default_config(const char *, const char *, void *);
31extern int perf_config_from_file(config_fn_t fn, const char *, void *);
32extern int perf_config(config_fn_t fn, void *); 22extern int perf_config(config_fn_t fn, void *);
33extern int perf_parse_ulong(const char *, unsigned long *);
34extern int perf_config_int(const char *, const char *); 23extern int perf_config_int(const char *, const char *);
35extern unsigned long perf_config_ulong(const char *, const char *);
36extern int perf_config_bool_or_int(const char *, const char *, int *);
37extern int perf_config_bool(const char *, const char *); 24extern int perf_config_bool(const char *, const char *);
38extern int perf_config_string(const char **, const char *, const char *);
39extern int perf_config_set(const char *, const char *);
40extern int perf_config_set_multivar(const char *, const char *, const char *, int);
41extern int perf_config_rename_section(const char *, const char *);
42extern const char *perf_etc_perfconfig(void);
43extern int check_repository_format_version(const char *var, const char *value, void *cb);
44extern int perf_config_system(void);
45extern int perf_config_global(void);
46extern int config_error_nonbool(const char *); 25extern int config_error_nonbool(const char *);
47extern const char *config_exclusive_filename;
48
49#define MAX_PERFNAME (1000)
50extern char perf_default_email[MAX_PERFNAME];
51extern char perf_default_name[MAX_PERFNAME];
52extern int user_ident_explicitly_given;
53
54extern const char *perf_log_output_encoding;
55extern const char *perf_mailmap_file;
56
57/* IO helper functions */
58extern void maybe_flush_or_die(FILE *, const char *);
59extern int copy_fd(int ifd, int ofd);
60extern int copy_file(const char *dst, const char *src, int mode);
61extern ssize_t write_in_full(int fd, const void *buf, size_t count);
62extern void write_or_die(int fd, const void *buf, size_t count);
63extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg);
64extern int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg);
65extern void fsync_or_die(int fd, const char *);
66 26
67/* pager.c */ 27/* pager.c */
68extern void setup_pager(void); 28extern void setup_pager(void);
@@ -83,9 +43,6 @@ void setup_browser(void);
83void exit_browser(bool wait_for_ok); 43void exit_browser(bool wait_for_ok);
84#endif 44#endif
85 45
86extern const char *editor_program;
87extern const char *excludes_file;
88
89char *alias_lookup(const char *alias); 46char *alias_lookup(const char *alias);
90int split_cmdline(char *cmdline, const char ***argv); 47int split_cmdline(char *cmdline, const char ***argv);
91 48
@@ -115,22 +72,12 @@ static inline int is_absolute_path(const char *path)
115 return path[0] == '/'; 72 return path[0] == '/';
116} 73}
117 74
118const char *make_absolute_path(const char *path);
119const char *make_nonrelative_path(const char *path); 75const char *make_nonrelative_path(const char *path);
120const char *make_relative_path(const char *abs, const char *base);
121int normalize_path_copy(char *dst, const char *src);
122int longest_ancestor_length(const char *path, const char *prefix_list);
123char *strip_path_suffix(const char *path, const char *suffix); 76char *strip_path_suffix(const char *path, const char *suffix);
124 77
125extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); 78extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
126extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2))); 79extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
127/* perf_mkstemp() - create tmp file honoring TMPDIR variable */
128extern int perf_mkstemp(char *path, size_t len, const char *template);
129 80
130extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
131 __attribute__((format (printf, 3, 4)));
132extern char *perf_snpath(char *buf, size_t n, const char *fmt, ...)
133 __attribute__((format (printf, 3, 4)));
134extern char *perf_pathdup(const char *fmt, ...) 81extern char *perf_pathdup(const char *fmt, ...)
135 __attribute__((format (printf, 1, 2))); 82 __attribute__((format (printf, 1, 2)));
136 83
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 8784649109ce..dabe892d0e53 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -16,7 +16,7 @@ static const char *config_file_name;
16static int config_linenr; 16static int config_linenr;
17static int config_file_eof; 17static int config_file_eof;
18 18
19const char *config_exclusive_filename = NULL; 19static const char *config_exclusive_filename;
20 20
21static int get_next_char(void) 21static int get_next_char(void)
22{ 22{
@@ -291,19 +291,6 @@ static int perf_parse_long(const char *value, long *ret)
291 return 0; 291 return 0;
292} 292}
293 293
294int perf_parse_ulong(const char *value, unsigned long *ret)
295{
296 if (value && *value) {
297 char *end;
298 unsigned long val = strtoul(value, &end, 0);
299 if (!parse_unit_factor(end, &val))
300 return 0;
301 *ret = val;
302 return 1;
303 }
304 return 0;
305}
306
307static void die_bad_config(const char *name) 294static void die_bad_config(const char *name)
308{ 295{
309 if (config_file_name) 296 if (config_file_name)
@@ -319,15 +306,7 @@ int perf_config_int(const char *name, const char *value)
319 return ret; 306 return ret;
320} 307}
321 308
322unsigned long perf_config_ulong(const char *name, const char *value) 309static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool)
323{
324 unsigned long ret;
325 if (!perf_parse_ulong(value, &ret))
326 die_bad_config(name);
327 return ret;
328}
329
330int perf_config_bool_or_int(const char *name, const char *value, int *is_bool)
331{ 310{
332 *is_bool = 1; 311 *is_bool = 1;
333 if (!value) 312 if (!value)
@@ -348,14 +327,6 @@ int perf_config_bool(const char *name, const char *value)
348 return !!perf_config_bool_or_int(name, value, &discard); 327 return !!perf_config_bool_or_int(name, value, &discard);
349} 328}
350 329
351int perf_config_string(const char **dest, const char *var, const char *value)
352{
353 if (!value)
354 return config_error_nonbool(var);
355 *dest = strdup(value);
356 return 0;
357}
358
359static int perf_default_core_config(const char *var __used, const char *value __used) 330static int perf_default_core_config(const char *var __used, const char *value __used)
360{ 331{
361 /* Add other config variables here and to Documentation/config.txt. */ 332 /* Add other config variables here and to Documentation/config.txt. */
@@ -371,7 +342,7 @@ int perf_default_config(const char *var, const char *value, void *dummy __used)
371 return 0; 342 return 0;
372} 343}
373 344
374int perf_config_from_file(config_fn_t fn, const char *filename, void *data) 345static int perf_config_from_file(config_fn_t fn, const char *filename, void *data)
375{ 346{
376 int ret; 347 int ret;
377 FILE *f = fopen(filename, "r"); 348 FILE *f = fopen(filename, "r");
@@ -389,7 +360,7 @@ int perf_config_from_file(config_fn_t fn, const char *filename, void *data)
389 return ret; 360 return ret;
390} 361}
391 362
392const char *perf_etc_perfconfig(void) 363static const char *perf_etc_perfconfig(void)
393{ 364{
394 static const char *system_wide; 365 static const char *system_wide;
395 if (!system_wide) 366 if (!system_wide)
@@ -403,12 +374,12 @@ static int perf_env_bool(const char *k, int def)
403 return v ? perf_config_bool(k, v) : def; 374 return v ? perf_config_bool(k, v) : def;
404} 375}
405 376
406int perf_config_system(void) 377static int perf_config_system(void)
407{ 378{
408 return !perf_env_bool("PERF_CONFIG_NOSYSTEM", 0); 379 return !perf_env_bool("PERF_CONFIG_NOSYSTEM", 0);
409} 380}
410 381
411int perf_config_global(void) 382static int perf_config_global(void)
412{ 383{
413 return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0); 384 return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0);
414} 385}
@@ -450,426 +421,6 @@ int perf_config(config_fn_t fn, void *data)
450} 421}
451 422
452/* 423/*
453 * Find all the stuff for perf_config_set() below.
454 */
455
456#define MAX_MATCHES 512
457
458static struct {
459 int baselen;
460 char* key;
461 int do_not_match;
462 regex_t* value_regex;
463 int multi_replace;
464 size_t offset[MAX_MATCHES];
465 enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state;
466 int seen;
467} store;
468
469static int matches(const char* key, const char* value)
470{
471 return !strcmp(key, store.key) &&
472 (store.value_regex == NULL ||
473 (store.do_not_match ^
474 !regexec(store.value_regex, value, 0, NULL, 0)));
475}
476
477static int store_aux(const char* key, const char* value, void *cb __used)
478{
479 int section_len;
480 const char *ep;
481
482 switch (store.state) {
483 case KEY_SEEN:
484 if (matches(key, value)) {
485 if (store.seen == 1 && store.multi_replace == 0) {
486 warning("%s has multiple values", key);
487 } else if (store.seen >= MAX_MATCHES) {
488 error("too many matches for %s", key);
489 return 1;
490 }
491
492 store.offset[store.seen] = ftell(config_file);
493 store.seen++;
494 }
495 break;
496 case SECTION_SEEN:
497 /*
498 * What we are looking for is in store.key (both
499 * section and var), and its section part is baselen
500 * long. We found key (again, both section and var).
501 * We would want to know if this key is in the same
502 * section as what we are looking for. We already
503 * know we are in the same section as what should
504 * hold store.key.
505 */
506 ep = strrchr(key, '.');
507 section_len = ep - key;
508
509 if ((section_len != store.baselen) ||
510 memcmp(key, store.key, section_len+1)) {
511 store.state = SECTION_END_SEEN;
512 break;
513 }
514
515 /*
516 * Do not increment matches: this is no match, but we
517 * just made sure we are in the desired section.
518 */
519 store.offset[store.seen] = ftell(config_file);
520 /* fallthru */
521 case SECTION_END_SEEN:
522 case START:
523 if (matches(key, value)) {
524 store.offset[store.seen] = ftell(config_file);
525 store.state = KEY_SEEN;
526 store.seen++;
527 } else {
528 if (strrchr(key, '.') - key == store.baselen &&
529 !strncmp(key, store.key, store.baselen)) {
530 store.state = SECTION_SEEN;
531 store.offset[store.seen] = ftell(config_file);
532 }
533 }
534 default:
535 break;
536 }
537 return 0;
538}
539
540static int store_write_section(int fd, const char* key)
541{
542 const char *dot;
543 int i, success;
544 struct strbuf sb = STRBUF_INIT;
545
546 dot = memchr(key, '.', store.baselen);
547 if (dot) {
548 strbuf_addf(&sb, "[%.*s \"", (int)(dot - key), key);
549 for (i = dot - key + 1; i < store.baselen; i++) {
550 if (key[i] == '"' || key[i] == '\\')
551 strbuf_addch(&sb, '\\');
552 strbuf_addch(&sb, key[i]);
553 }
554 strbuf_addstr(&sb, "\"]\n");
555 } else {
556 strbuf_addf(&sb, "[%.*s]\n", store.baselen, key);
557 }
558
559 success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len);
560 strbuf_release(&sb);
561
562 return success;
563}
564
565static int store_write_pair(int fd, const char* key, const char* value)
566{
567 int i, success;
568 int length = strlen(key + store.baselen + 1);
569 const char *quote = "";
570 struct strbuf sb = STRBUF_INIT;
571
572 /*
573 * Check to see if the value needs to be surrounded with a dq pair.
574 * Note that problematic characters are always backslash-quoted; this
575 * check is about not losing leading or trailing SP and strings that
576 * follow beginning-of-comment characters (i.e. ';' and '#') by the
577 * configuration parser.
578 */
579 if (value[0] == ' ')
580 quote = "\"";
581 for (i = 0; value[i]; i++)
582 if (value[i] == ';' || value[i] == '#')
583 quote = "\"";
584 if (i && value[i - 1] == ' ')
585 quote = "\"";
586
587 strbuf_addf(&sb, "\t%.*s = %s",
588 length, key + store.baselen + 1, quote);
589
590 for (i = 0; value[i]; i++)
591 switch (value[i]) {
592 case '\n':
593 strbuf_addstr(&sb, "\\n");
594 break;
595 case '\t':
596 strbuf_addstr(&sb, "\\t");
597 break;
598 case '"':
599 case '\\':
600 strbuf_addch(&sb, '\\');
601 default:
602 strbuf_addch(&sb, value[i]);
603 break;
604 }
605 strbuf_addf(&sb, "%s\n", quote);
606
607 success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len);
608 strbuf_release(&sb);
609
610 return success;
611}
612
613static ssize_t find_beginning_of_line(const char* contents, size_t size,
614 size_t offset_, int* found_bracket)
615{
616 size_t equal_offset = size, bracket_offset = size;
617 ssize_t offset;
618
619contline:
620 for (offset = offset_-2; offset > 0
621 && contents[offset] != '\n'; offset--)
622 switch (contents[offset]) {
623 case '=': equal_offset = offset; break;
624 case ']': bracket_offset = offset; break;
625 default: break;
626 }
627 if (offset > 0 && contents[offset-1] == '\\') {
628 offset_ = offset;
629 goto contline;
630 }
631 if (bracket_offset < equal_offset) {
632 *found_bracket = 1;
633 offset = bracket_offset+1;
634 } else
635 offset++;
636
637 return offset;
638}
639
640int perf_config_set(const char* key, const char* value)
641{
642 return perf_config_set_multivar(key, value, NULL, 0);
643}
644
645/*
646 * If value==NULL, unset in (remove from) config,
647 * if value_regex!=NULL, disregard key/value pairs where value does not match.
648 * if multi_replace==0, nothing, or only one matching key/value is replaced,
649 * else all matching key/values (regardless how many) are removed,
650 * before the new pair is written.
651 *
652 * Returns 0 on success.
653 *
654 * This function does this:
655 *
656 * - it locks the config file by creating ".perf/config.lock"
657 *
658 * - it then parses the config using store_aux() as validator to find
659 * the position on the key/value pair to replace. If it is to be unset,
660 * it must be found exactly once.
661 *
662 * - the config file is mmap()ed and the part before the match (if any) is
663 * written to the lock file, then the changed part and the rest.
664 *
665 * - the config file is removed and the lock file rename()d to it.
666 *
667 */
668int perf_config_set_multivar(const char* key, const char* value,
669 const char* value_regex, int multi_replace)
670{
671 int i, dot;
672 int fd = -1, in_fd;
673 int ret = 0;
674 char* config_filename;
675 const char* last_dot = strrchr(key, '.');
676
677 if (config_exclusive_filename)
678 config_filename = strdup(config_exclusive_filename);
679 else
680 config_filename = perf_pathdup("config");
681
682 /*
683 * Since "key" actually contains the section name and the real
684 * key name separated by a dot, we have to know where the dot is.
685 */
686
687 if (last_dot == NULL) {
688 error("key does not contain a section: %s", key);
689 ret = 2;
690 goto out_free;
691 }
692 store.baselen = last_dot - key;
693
694 store.multi_replace = multi_replace;
695
696 /*
697 * Validate the key and while at it, lower case it for matching.
698 */
699 store.key = malloc(strlen(key) + 1);
700 dot = 0;
701 for (i = 0; key[i]; i++) {
702 unsigned char c = key[i];
703 if (c == '.')
704 dot = 1;
705 /* Leave the extended basename untouched.. */
706 if (!dot || i > store.baselen) {
707 if (!iskeychar(c) || (i == store.baselen+1 && !isalpha(c))) {
708 error("invalid key: %s", key);
709 free(store.key);
710 ret = 1;
711 goto out_free;
712 }
713 c = tolower(c);
714 } else if (c == '\n') {
715 error("invalid key (newline): %s", key);
716 free(store.key);
717 ret = 1;
718 goto out_free;
719 }
720 store.key[i] = c;
721 }
722 store.key[i] = 0;
723
724 /*
725 * If .perf/config does not exist yet, write a minimal version.
726 */
727 in_fd = open(config_filename, O_RDONLY);
728 if ( in_fd < 0 ) {
729 free(store.key);
730
731 if ( ENOENT != errno ) {
732 error("opening %s: %s", config_filename,
733 strerror(errno));
734 ret = 3; /* same as "invalid config file" */
735 goto out_free;
736 }
737 /* if nothing to unset, error out */
738 if (value == NULL) {
739 ret = 5;
740 goto out_free;
741 }
742
743 store.key = (char*)key;
744 if (!store_write_section(fd, key) ||
745 !store_write_pair(fd, key, value))
746 goto write_err_out;
747 } else {
748 struct stat st;
749 char *contents;
750 ssize_t contents_sz, copy_begin, copy_end;
751 int new_line = 0;
752
753 if (value_regex == NULL)
754 store.value_regex = NULL;
755 else {
756 if (value_regex[0] == '!') {
757 store.do_not_match = 1;
758 value_regex++;
759 } else
760 store.do_not_match = 0;
761
762 store.value_regex = (regex_t*)malloc(sizeof(regex_t));
763 if (regcomp(store.value_regex, value_regex,
764 REG_EXTENDED)) {
765 error("invalid pattern: %s", value_regex);
766 free(store.value_regex);
767 ret = 6;
768 goto out_free;
769 }
770 }
771
772 store.offset[0] = 0;
773 store.state = START;
774 store.seen = 0;
775
776 /*
777 * After this, store.offset will contain the *end* offset
778 * of the last match, or remain at 0 if no match was found.
779 * As a side effect, we make sure to transform only a valid
780 * existing config file.
781 */
782 if (perf_config_from_file(store_aux, config_filename, NULL)) {
783 error("invalid config file %s", config_filename);
784 free(store.key);
785 if (store.value_regex != NULL) {
786 regfree(store.value_regex);
787 free(store.value_regex);
788 }
789 ret = 3;
790 goto out_free;
791 }
792
793 free(store.key);
794 if (store.value_regex != NULL) {
795 regfree(store.value_regex);
796 free(store.value_regex);
797 }
798
799 /* if nothing to unset, or too many matches, error out */
800 if ((store.seen == 0 && value == NULL) ||
801 (store.seen > 1 && multi_replace == 0)) {
802 ret = 5;
803 goto out_free;
804 }
805
806 fstat(in_fd, &st);
807 contents_sz = xsize_t(st.st_size);
808 contents = mmap(NULL, contents_sz, PROT_READ,
809 MAP_PRIVATE, in_fd, 0);
810 close(in_fd);
811
812 if (store.seen == 0)
813 store.seen = 1;
814
815 for (i = 0, copy_begin = 0; i < store.seen; i++) {
816 if (store.offset[i] == 0) {
817 store.offset[i] = copy_end = contents_sz;
818 } else if (store.state != KEY_SEEN) {
819 copy_end = store.offset[i];
820 } else
821 copy_end = find_beginning_of_line(
822 contents, contents_sz,
823 store.offset[i]-2, &new_line);
824
825 if (copy_end > 0 && contents[copy_end-1] != '\n')
826 new_line = 1;
827
828 /* write the first part of the config */
829 if (copy_end > copy_begin) {
830 if (write_in_full(fd, contents + copy_begin,
831 copy_end - copy_begin) <
832 copy_end - copy_begin)
833 goto write_err_out;
834 if (new_line &&
835 write_in_full(fd, "\n", 1) != 1)
836 goto write_err_out;
837 }
838 copy_begin = store.offset[i];
839 }
840
841 /* write the pair (value == NULL means unset) */
842 if (value != NULL) {
843 if (store.state == START) {
844 if (!store_write_section(fd, key))
845 goto write_err_out;
846 }
847 if (!store_write_pair(fd, key, value))
848 goto write_err_out;
849 }
850
851 /* write the rest of the config */
852 if (copy_begin < contents_sz)
853 if (write_in_full(fd, contents + copy_begin,
854 contents_sz - copy_begin) <
855 contents_sz - copy_begin)
856 goto write_err_out;
857
858 munmap(contents, contents_sz);
859 }
860
861 ret = 0;
862
863out_free:
864 free(config_filename);
865 return ret;
866
867write_err_out:
868 goto out_free;
869
870}
871
872/*
873 * Call this to report error for your variable that should not 424 * Call this to report error for your variable that should not
874 * get a boolean value (i.e. "[my] var" means "true"). 425 * get a boolean value (i.e. "[my] var" means "true").
875 */ 426 */
diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c
index 2745605dba11..c1b3d34e5716 100644
--- a/tools/perf/util/exec_cmd.c
+++ b/tools/perf/util/exec_cmd.c
@@ -116,7 +116,7 @@ void setup_path(void)
116 strbuf_release(&new_path); 116 strbuf_release(&new_path);
117} 117}
118 118
119const char **prepare_perf_cmd(const char **argv) 119static const char **prepare_perf_cmd(const char **argv)
120{ 120{
121 int argc; 121 int argc;
122 const char **nargv; 122 const char **nargv;
diff --git a/tools/perf/util/exec_cmd.h b/tools/perf/util/exec_cmd.h
index 31647ac92ed1..bc4b915963f5 100644
--- a/tools/perf/util/exec_cmd.h
+++ b/tools/perf/util/exec_cmd.h
@@ -5,7 +5,6 @@ extern void perf_set_argv_exec_path(const char *exec_path);
5extern const char *perf_extract_argv0_path(const char *path); 5extern const char *perf_extract_argv0_path(const char *path);
6extern const char *perf_exec_path(void); 6extern const char *perf_exec_path(void);
7extern void setup_path(void); 7extern void setup_path(void);
8extern const char **prepare_perf_cmd(const char **argv);
9extern int execv_perf_cmd(const char **argv); /* NULL terminated */ 8extern int execv_perf_cmd(const char **argv); /* NULL terminated */
10extern int execl_perf_cmd(const char *cmd, ...); 9extern int execl_perf_cmd(const char *cmd, ...);
11extern const char *system_path(const char *path); 10extern const char *system_path(const char *path);
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c
index fbb00978b2e2..6f2975a00358 100644
--- a/tools/perf/util/help.c
+++ b/tools/perf/util/help.c
@@ -4,28 +4,6 @@
4#include "levenshtein.h" 4#include "levenshtein.h"
5#include "help.h" 5#include "help.h"
6 6
7/* most GUI terminals set COLUMNS (although some don't export it) */
8static int term_columns(void)
9{
10 char *col_string = getenv("COLUMNS");
11 int n_cols;
12
13 if (col_string && (n_cols = atoi(col_string)) > 0)
14 return n_cols;
15
16#ifdef TIOCGWINSZ
17 {
18 struct winsize ws;
19 if (!ioctl(1, TIOCGWINSZ, &ws)) {
20 if (ws.ws_col)
21 return ws.ws_col;
22 }
23 }
24#endif
25
26 return 80;
27}
28
29void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) 7void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
30{ 8{
31 struct cmdname *ent = malloc(sizeof(*ent) + len + 1); 9 struct cmdname *ent = malloc(sizeof(*ent) + len + 1);
@@ -96,9 +74,13 @@ static void pretty_print_string_list(struct cmdnames *cmds, int longest)
96{ 74{
97 int cols = 1, rows; 75 int cols = 1, rows;
98 int space = longest + 1; /* min 1 SP between words */ 76 int space = longest + 1; /* min 1 SP between words */
99 int max_cols = term_columns() - 1; /* don't print *on* the edge */ 77 struct winsize win;
78 int max_cols;
100 int i, j; 79 int i, j;
101 80
81 get_term_dimensions(&win);
82 max_cols = win.ws_col - 1; /* don't print *on* the edge */
83
102 if (space < max_cols) 84 if (space < max_cols)
103 cols = max_cols / space; 85 cols = max_cols / space;
104 rows = (cmds->cnt + cols - 1) / cols; 86 rows = (cmds->cnt + cols - 1) / cols;
@@ -324,7 +306,7 @@ const char *help_unknown_cmd(const char *cmd)
324 306
325 main_cmds.names[0] = NULL; 307 main_cmds.names[0] = NULL;
326 clean_cmdnames(&main_cmds); 308 clean_cmdnames(&main_cmds);
327 fprintf(stderr, "WARNING: You called a Git program named '%s', " 309 fprintf(stderr, "WARNING: You called a perf program named '%s', "
328 "which does not exist.\n" 310 "which does not exist.\n"
329 "Continuing under the assumption that you meant '%s'\n", 311 "Continuing under the assumption that you meant '%s'\n",
330 cmd, assumed); 312 cmd, assumed);
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index fd1f2faaade4..b276c187802a 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -54,21 +54,6 @@ static char *cleanup_path(char *path)
54 return path; 54 return path;
55} 55}
56 56
57char *mksnpath(char *buf, size_t n, const char *fmt, ...)
58{
59 va_list args;
60 unsigned len;
61
62 va_start(args, fmt);
63 len = vsnprintf(buf, n, fmt, args);
64 va_end(args);
65 if (len >= n) {
66 strlcpy(buf, bad_path, n);
67 return buf;
68 }
69 return cleanup_path(buf);
70}
71
72static char *perf_vsnpath(char *buf, size_t n, const char *fmt, va_list args) 57static char *perf_vsnpath(char *buf, size_t n, const char *fmt, va_list args)
73{ 58{
74 const char *perf_dir = get_perf_dir(); 59 const char *perf_dir = get_perf_dir();
@@ -89,15 +74,6 @@ bad:
89 return buf; 74 return buf;
90} 75}
91 76
92char *perf_snpath(char *buf, size_t n, const char *fmt, ...)
93{
94 va_list args;
95 va_start(args, fmt);
96 (void)perf_vsnpath(buf, n, fmt, args);
97 va_end(args);
98 return buf;
99}
100
101char *perf_pathdup(const char *fmt, ...) 77char *perf_pathdup(const char *fmt, ...)
102{ 78{
103 char path[PATH_MAX]; 79 char path[PATH_MAX];
@@ -143,184 +119,6 @@ char *perf_path(const char *fmt, ...)
143 return cleanup_path(pathname); 119 return cleanup_path(pathname);
144} 120}
145 121
146
147/* perf_mkstemp() - create tmp file honoring TMPDIR variable */
148int perf_mkstemp(char *path, size_t len, const char *template)
149{
150 const char *tmp;
151 size_t n;
152
153 tmp = getenv("TMPDIR");
154 if (!tmp)
155 tmp = "/tmp";
156 n = snprintf(path, len, "%s/%s", tmp, template);
157 if (len <= n) {
158 errno = ENAMETOOLONG;
159 return -1;
160 }
161 return mkstemp(path);
162}
163
164
165const char *make_relative_path(const char *abs_path, const char *base)
166{
167 static char buf[PATH_MAX + 1];
168 int baselen;
169
170 if (!base)
171 return abs_path;
172
173 baselen = strlen(base);
174 if (prefixcmp(abs_path, base))
175 return abs_path;
176 if (abs_path[baselen] == '/')
177 baselen++;
178 else if (base[baselen - 1] != '/')
179 return abs_path;
180
181 strcpy(buf, abs_path + baselen);
182
183 return buf;
184}
185
186/*
187 * It is okay if dst == src, but they should not overlap otherwise.
188 *
189 * Performs the following normalizations on src, storing the result in dst:
190 * - Ensures that components are separated by '/' (Windows only)
191 * - Squashes sequences of '/'.
192 * - Removes "." components.
193 * - Removes ".." components, and the components the precede them.
194 * Returns failure (non-zero) if a ".." component appears as first path
195 * component anytime during the normalization. Otherwise, returns success (0).
196 *
197 * Note that this function is purely textual. It does not follow symlinks,
198 * verify the existence of the path, or make any system calls.
199 */
200int normalize_path_copy(char *dst, const char *src)
201{
202 char *dst0;
203
204 if (has_dos_drive_prefix(src)) {
205 *dst++ = *src++;
206 *dst++ = *src++;
207 }
208 dst0 = dst;
209
210 if (is_dir_sep(*src)) {
211 *dst++ = '/';
212 while (is_dir_sep(*src))
213 src++;
214 }
215
216 for (;;) {
217 char c = *src;
218
219 /*
220 * A path component that begins with . could be
221 * special:
222 * (1) "." and ends -- ignore and terminate.
223 * (2) "./" -- ignore them, eat slash and continue.
224 * (3) ".." and ends -- strip one and terminate.
225 * (4) "../" -- strip one, eat slash and continue.
226 */
227 if (c == '.') {
228 if (!src[1]) {
229 /* (1) */
230 src++;
231 } else if (is_dir_sep(src[1])) {
232 /* (2) */
233 src += 2;
234 while (is_dir_sep(*src))
235 src++;
236 continue;
237 } else if (src[1] == '.') {
238 if (!src[2]) {
239 /* (3) */
240 src += 2;
241 goto up_one;
242 } else if (is_dir_sep(src[2])) {
243 /* (4) */
244 src += 3;
245 while (is_dir_sep(*src))
246 src++;
247 goto up_one;
248 }
249 }
250 }
251
252 /* copy up to the next '/', and eat all '/' */
253 while ((c = *src++) != '\0' && !is_dir_sep(c))
254 *dst++ = c;
255 if (is_dir_sep(c)) {
256 *dst++ = '/';
257 while (is_dir_sep(c))
258 c = *src++;
259 src--;
260 } else if (!c)
261 break;
262 continue;
263
264 up_one:
265 /*
266 * dst0..dst is prefix portion, and dst[-1] is '/';
267 * go up one level.
268 */
269 dst--; /* go to trailing '/' */
270 if (dst <= dst0)
271 return -1;
272 /* Windows: dst[-1] cannot be backslash anymore */
273 while (dst0 < dst && dst[-1] != '/')
274 dst--;
275 }
276 *dst = '\0';
277 return 0;
278}
279
280/*
281 * path = Canonical absolute path
282 * prefix_list = Colon-separated list of absolute paths
283 *
284 * Determines, for each path in prefix_list, whether the "prefix" really
285 * is an ancestor directory of path. Returns the length of the longest
286 * ancestor directory, excluding any trailing slashes, or -1 if no prefix
287 * is an ancestor. (Note that this means 0 is returned if prefix_list is
288 * "/".) "/foo" is not considered an ancestor of "/foobar". Directories
289 * are not considered to be their own ancestors. path must be in a
290 * canonical form: empty components, or "." or ".." components are not
291 * allowed. prefix_list may be null, which is like "".
292 */
293int longest_ancestor_length(const char *path, const char *prefix_list)
294{
295 char buf[PATH_MAX+1];
296 const char *ceil, *colon;
297 int len, max_len = -1;
298
299 if (prefix_list == NULL || !strcmp(path, "/"))
300 return -1;
301
302 for (colon = ceil = prefix_list; *colon; ceil = colon+1) {
303 for (colon = ceil; *colon && *colon != PATH_SEP; colon++);
304 len = colon - ceil;
305 if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil))
306 continue;
307 strlcpy(buf, ceil, len+1);
308 if (normalize_path_copy(buf, buf) < 0)
309 continue;
310 len = strlen(buf);
311 if (len > 0 && buf[len-1] == '/')
312 buf[--len] = '\0';
313
314 if (!strncmp(path, buf, len) &&
315 path[len] == '/' &&
316 len > max_len) {
317 max_len = len;
318 }
319 }
320
321 return max_len;
322}
323
324/* strip arbitrary amount of directory separators at end of path */ 122/* strip arbitrary amount of directory separators at end of path */
325static inline int chomp_trailing_dir_sep(const char *path, int len) 123static inline int chomp_trailing_dir_sep(const char *path, int len)
326{ 124{
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c
index 2726fe40eb5d..01f03242b86a 100644
--- a/tools/perf/util/quote.c
+++ b/tools/perf/util/quote.c
@@ -1,8 +1,6 @@
1#include "cache.h" 1#include "cache.h"
2#include "quote.h" 2#include "quote.h"
3 3
4int quote_path_fully = 1;
5
6/* Help to copy the thing properly quoted for the shell safety. 4/* Help to copy the thing properly quoted for the shell safety.
7 * any single quote is replaced with '\'', any exclamation point 5 * any single quote is replaced with '\'', any exclamation point
8 * is replaced with '\!', and the whole thing is enclosed in a 6 * is replaced with '\!', and the whole thing is enclosed in a
@@ -19,7 +17,7 @@ static inline int need_bs_quote(char c)
19 return (c == '\'' || c == '!'); 17 return (c == '\'' || c == '!');
20} 18}
21 19
22void sq_quote_buf(struct strbuf *dst, const char *src) 20static void sq_quote_buf(struct strbuf *dst, const char *src)
23{ 21{
24 char *to_free = NULL; 22 char *to_free = NULL;
25 23
@@ -41,23 +39,6 @@ void sq_quote_buf(struct strbuf *dst, const char *src)
41 free(to_free); 39 free(to_free);
42} 40}
43 41
44void sq_quote_print(FILE *stream, const char *src)
45{
46 char c;
47
48 fputc('\'', stream);
49 while ((c = *src++)) {
50 if (need_bs_quote(c)) {
51 fputs("'\\", stream);
52 fputc(c, stream);
53 fputc('\'', stream);
54 } else {
55 fputc(c, stream);
56 }
57 }
58 fputc('\'', stream);
59}
60
61void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen) 42void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
62{ 43{
63 int i; 44 int i;
@@ -71,415 +52,3 @@ void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
71 die("Too many or long arguments"); 52 die("Too many or long arguments");
72 } 53 }
73} 54}
74
75char *sq_dequote_step(char *arg, char **next)
76{
77 char *dst = arg;
78 char *src = arg;
79 char c;
80
81 if (*src != '\'')
82 return NULL;
83 for (;;) {
84 c = *++src;
85 if (!c)
86 return NULL;
87 if (c != '\'') {
88 *dst++ = c;
89 continue;
90 }
91 /* We stepped out of sq */
92 switch (*++src) {
93 case '\0':
94 *dst = 0;
95 if (next)
96 *next = NULL;
97 return arg;
98 case '\\':
99 c = *++src;
100 if (need_bs_quote(c) && *++src == '\'') {
101 *dst++ = c;
102 continue;
103 }
104 /* Fallthrough */
105 default:
106 if (!next || !isspace(*src))
107 return NULL;
108 do {
109 c = *++src;
110 } while (isspace(c));
111 *dst = 0;
112 *next = src;
113 return arg;
114 }
115 }
116}
117
118char *sq_dequote(char *arg)
119{
120 return sq_dequote_step(arg, NULL);
121}
122
123int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc)
124{
125 char *next = arg;
126
127 if (!*arg)
128 return 0;
129 do {
130 char *dequoted = sq_dequote_step(next, &next);
131 if (!dequoted)
132 return -1;
133 ALLOC_GROW(*argv, *nr + 1, *alloc);
134 (*argv)[(*nr)++] = dequoted;
135 } while (next);
136
137 return 0;
138}
139
140/* 1 means: quote as octal
141 * 0 means: quote as octal if (quote_path_fully)
142 * -1 means: never quote
143 * c: quote as "\\c"
144 */
145#define X8(x) x, x, x, x, x, x, x, x
146#define X16(x) X8(x), X8(x)
147static signed char const sq_lookup[256] = {
148 /* 0 1 2 3 4 5 6 7 */
149 /* 0x00 */ 1, 1, 1, 1, 1, 1, 1, 'a',
150 /* 0x08 */ 'b', 't', 'n', 'v', 'f', 'r', 1, 1,
151 /* 0x10 */ X16(1),
152 /* 0x20 */ -1, -1, '"', -1, -1, -1, -1, -1,
153 /* 0x28 */ X16(-1), X16(-1), X16(-1),
154 /* 0x58 */ -1, -1, -1, -1,'\\', -1, -1, -1,
155 /* 0x60 */ X16(-1), X8(-1),
156 /* 0x78 */ -1, -1, -1, -1, -1, -1, -1, 1,
157 /* 0x80 */ /* set to 0 */
158};
159
160static inline int sq_must_quote(char c)
161{
162 return sq_lookup[(unsigned char)c] + quote_path_fully > 0;
163}
164
165/*
166 * Returns the longest prefix not needing a quote up to maxlen if
167 * positive.
168 * This stops at the first \0 because it's marked as a character
169 * needing an escape.
170 */
171static ssize_t next_quote_pos(const char *s, ssize_t maxlen)
172{
173 ssize_t len;
174
175 if (maxlen < 0) {
176 for (len = 0; !sq_must_quote(s[len]); len++);
177 } else {
178 for (len = 0; len < maxlen && !sq_must_quote(s[len]); len++);
179 }
180 return len;
181}
182
183/*
184 * C-style name quoting.
185 *
186 * (1) if sb and fp are both NULL, inspect the input name and counts the
187 * number of bytes that are needed to hold c_style quoted version of name,
188 * counting the double quotes around it but not terminating NUL, and
189 * returns it.
190 * However, if name does not need c_style quoting, it returns 0.
191 *
192 * (2) if sb or fp are not NULL, it emits the c_style quoted version
193 * of name, enclosed with double quotes if asked and needed only.
194 * Return value is the same as in (1).
195 */
196static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
197 struct strbuf *sb, FILE *fp, int no_dq)
198{
199#define EMIT(c) \
200 do { \
201 if (sb) strbuf_addch(sb, (c)); \
202 if (fp) fputc((c), fp); \
203 count++; \
204 } while (0)
205
206#define EMITBUF(s, l) \
207 do { \
208 int __ret; \
209 if (sb) strbuf_add(sb, (s), (l)); \
210 if (fp) __ret = fwrite((s), (l), 1, fp); \
211 count += (l); \
212 } while (0)
213
214 ssize_t len, count = 0;
215 const char *p = name;
216
217 for (;;) {
218 int ch;
219
220 len = next_quote_pos(p, maxlen);
221 if (len == maxlen || !p[len])
222 break;
223
224 if (!no_dq && p == name)
225 EMIT('"');
226
227 EMITBUF(p, len);
228 EMIT('\\');
229 p += len;
230 ch = (unsigned char)*p++;
231 if (sq_lookup[ch] >= ' ') {
232 EMIT(sq_lookup[ch]);
233 } else {
234 EMIT(((ch >> 6) & 03) + '0');
235 EMIT(((ch >> 3) & 07) + '0');
236 EMIT(((ch >> 0) & 07) + '0');
237 }
238 }
239
240 EMITBUF(p, len);
241 if (p == name) /* no ending quote needed */
242 return 0;
243
244 if (!no_dq)
245 EMIT('"');
246 return count;
247}
248
249size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, int nodq)
250{
251 return quote_c_style_counted(name, -1, sb, fp, nodq);
252}
253
254void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path, int nodq)
255{
256 if (quote_c_style(prefix, NULL, NULL, 0) ||
257 quote_c_style(path, NULL, NULL, 0)) {
258 if (!nodq)
259 strbuf_addch(sb, '"');
260 quote_c_style(prefix, sb, NULL, 1);
261 quote_c_style(path, sb, NULL, 1);
262 if (!nodq)
263 strbuf_addch(sb, '"');
264 } else {
265 strbuf_addstr(sb, prefix);
266 strbuf_addstr(sb, path);
267 }
268}
269
270void write_name_quoted(const char *name, FILE *fp, int terminator)
271{
272 if (terminator) {
273 quote_c_style(name, NULL, fp, 0);
274 } else {
275 fputs(name, fp);
276 }
277 fputc(terminator, fp);
278}
279
280void write_name_quotedpfx(const char *pfx, ssize_t pfxlen,
281 const char *name, FILE *fp, int terminator)
282{
283 int needquote = 0;
284
285 if (terminator) {
286 needquote = next_quote_pos(pfx, pfxlen) < pfxlen
287 || name[next_quote_pos(name, -1)];
288 }
289 if (needquote) {
290 fputc('"', fp);
291 quote_c_style_counted(pfx, pfxlen, NULL, fp, 1);
292 quote_c_style(name, NULL, fp, 1);
293 fputc('"', fp);
294 } else {
295 int ret;
296
297 ret = fwrite(pfx, pfxlen, 1, fp);
298 fputs(name, fp);
299 }
300 fputc(terminator, fp);
301}
302
303/* quote path as relative to the given prefix */
304char *quote_path_relative(const char *in, int len,
305 struct strbuf *out, const char *prefix)
306{
307 int needquote;
308
309 if (len < 0)
310 len = strlen(in);
311
312 /* "../" prefix itself does not need quoting, but "in" might. */
313 needquote = (next_quote_pos(in, len) < len);
314 strbuf_setlen(out, 0);
315 strbuf_grow(out, len);
316
317 if (needquote)
318 strbuf_addch(out, '"');
319 if (prefix) {
320 int off = 0;
321 while (off < len && prefix[off] && prefix[off] == in[off])
322 if (prefix[off] == '/') {
323 prefix += off + 1;
324 in += off + 1;
325 len -= off + 1;
326 off = 0;
327 } else
328 off++;
329
330 for (; *prefix; prefix++)
331 if (*prefix == '/')
332 strbuf_addstr(out, "../");
333 }
334
335 quote_c_style_counted (in, len, out, NULL, 1);
336
337 if (needquote)
338 strbuf_addch(out, '"');
339 if (!out->len)
340 strbuf_addstr(out, "./");
341
342 return out->buf;
343}
344
345/*
346 * C-style name unquoting.
347 *
348 * Quoted should point at the opening double quote.
349 * + Returns 0 if it was able to unquote the string properly, and appends the
350 * result in the strbuf `sb'.
351 * + Returns -1 in case of error, and doesn't touch the strbuf. Though note
352 * that this function will allocate memory in the strbuf, so calling
353 * strbuf_release is mandatory whichever result unquote_c_style returns.
354 *
355 * Updates endp pointer to point at one past the ending double quote if given.
356 */
357int unquote_c_style(struct strbuf *sb, const char *quoted, const char **endp)
358{
359 size_t oldlen = sb->len, len;
360 int ch, ac;
361
362 if (*quoted++ != '"')
363 return -1;
364
365 for (;;) {
366 len = strcspn(quoted, "\"\\");
367 strbuf_add(sb, quoted, len);
368 quoted += len;
369
370 switch (*quoted++) {
371 case '"':
372 if (endp)
373 *endp = quoted;
374 return 0;
375 case '\\':
376 break;
377 default:
378 goto error;
379 }
380
381 switch ((ch = *quoted++)) {
382 case 'a': ch = '\a'; break;
383 case 'b': ch = '\b'; break;
384 case 'f': ch = '\f'; break;
385 case 'n': ch = '\n'; break;
386 case 'r': ch = '\r'; break;
387 case 't': ch = '\t'; break;
388 case 'v': ch = '\v'; break;
389
390 case '\\': case '"':
391 break; /* verbatim */
392
393 /* octal values with first digit over 4 overflow */
394 case '0': case '1': case '2': case '3':
395 ac = ((ch - '0') << 6);
396 if ((ch = *quoted++) < '0' || '7' < ch)
397 goto error;
398 ac |= ((ch - '0') << 3);
399 if ((ch = *quoted++) < '0' || '7' < ch)
400 goto error;
401 ac |= (ch - '0');
402 ch = ac;
403 break;
404 default:
405 goto error;
406 }
407 strbuf_addch(sb, ch);
408 }
409
410 error:
411 strbuf_setlen(sb, oldlen);
412 return -1;
413}
414
415/* quoting as a string literal for other languages */
416
417void perl_quote_print(FILE *stream, const char *src)
418{
419 const char sq = '\'';
420 const char bq = '\\';
421 char c;
422
423 fputc(sq, stream);
424 while ((c = *src++)) {
425 if (c == sq || c == bq)
426 fputc(bq, stream);
427 fputc(c, stream);
428 }
429 fputc(sq, stream);
430}
431
432void python_quote_print(FILE *stream, const char *src)
433{
434 const char sq = '\'';
435 const char bq = '\\';
436 const char nl = '\n';
437 char c;
438
439 fputc(sq, stream);
440 while ((c = *src++)) {
441 if (c == nl) {
442 fputc(bq, stream);
443 fputc('n', stream);
444 continue;
445 }
446 if (c == sq || c == bq)
447 fputc(bq, stream);
448 fputc(c, stream);
449 }
450 fputc(sq, stream);
451}
452
453void tcl_quote_print(FILE *stream, const char *src)
454{
455 char c;
456
457 fputc('"', stream);
458 while ((c = *src++)) {
459 switch (c) {
460 case '[': case ']':
461 case '{': case '}':
462 case '$': case '\\': case '"':
463 fputc('\\', stream);
464 default:
465 fputc(c, stream);
466 break;
467 case '\f':
468 fputs("\\f", stream);
469 break;
470 case '\r':
471 fputs("\\r", stream);
472 break;
473 case '\n':
474 fputs("\\n", stream);
475 break;
476 case '\t':
477 fputs("\\t", stream);
478 break;
479 case '\v':
480 fputs("\\v", stream);
481 break;
482 }
483 }
484 fputc('"', stream);
485}
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h
index b6a019733919..172889ea234f 100644
--- a/tools/perf/util/quote.h
+++ b/tools/perf/util/quote.h
@@ -22,47 +22,8 @@
22 * 22 *
23 * Note that the above examples leak memory! Remember to free result from 23 * Note that the above examples leak memory! Remember to free result from
24 * sq_quote() in a real application. 24 * sq_quote() in a real application.
25 *
26 * sq_quote_buf() writes to an existing buffer of specified size; it
27 * will return the number of characters that would have been written
28 * excluding the final null regardless of the buffer size.
29 */ 25 */
30 26
31extern void sq_quote_print(FILE *stream, const char *src);
32
33extern void sq_quote_buf(struct strbuf *, const char *src);
34extern void sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen); 27extern void sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen);
35 28
36/* This unwraps what sq_quote() produces in place, but returns
37 * NULL if the input does not look like what sq_quote would have
38 * produced.
39 */
40extern char *sq_dequote(char *);
41
42/*
43 * Same as the above, but can be used to unwrap many arguments in the
44 * same string separated by space. "next" is changed to point to the
45 * next argument that should be passed as first parameter. When there
46 * is no more argument to be dequoted, "next" is updated to point to NULL.
47 */
48extern char *sq_dequote_step(char *arg, char **next);
49extern int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc);
50
51extern int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);
52extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq);
53extern void quote_two_c_style(struct strbuf *, const char *, const char *, int);
54
55extern void write_name_quoted(const char *name, FILE *, int terminator);
56extern void write_name_quotedpfx(const char *pfx, ssize_t pfxlen,
57 const char *name, FILE *, int terminator);
58
59/* quote path as relative to the given prefix */
60char *quote_path_relative(const char *in, int len,
61 struct strbuf *out, const char *prefix);
62
63/* quoting as a string literal for other languages */
64extern void perl_quote_print(FILE *stream, const char *src);
65extern void python_quote_print(FILE *stream, const char *src);
66extern void tcl_quote_print(FILE *stream, const char *src);
67
68#endif /* __PERF_QUOTE_H */ 29#endif /* __PERF_QUOTE_H */
diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c
index 2b615acf94d7..da8e9b285f51 100644
--- a/tools/perf/util/run-command.c
+++ b/tools/perf/util/run-command.c
@@ -212,93 +212,3 @@ int run_command_v_opt(const char **argv, int opt)
212 prepare_run_command_v_opt(&cmd, argv, opt); 212 prepare_run_command_v_opt(&cmd, argv, opt);
213 return run_command(&cmd); 213 return run_command(&cmd);
214} 214}
215
216int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env)
217{
218 struct child_process cmd;
219 prepare_run_command_v_opt(&cmd, argv, opt);
220 cmd.dir = dir;
221 cmd.env = env;
222 return run_command(&cmd);
223}
224
225int start_async(struct async *async)
226{
227 int pipe_out[2];
228
229 if (pipe(pipe_out) < 0)
230 return error("cannot create pipe: %s", strerror(errno));
231 async->out = pipe_out[0];
232
233 /* Flush stdio before fork() to avoid cloning buffers */
234 fflush(NULL);
235
236 async->pid = fork();
237 if (async->pid < 0) {
238 error("fork (async) failed: %s", strerror(errno));
239 close_pair(pipe_out);
240 return -1;
241 }
242 if (!async->pid) {
243 close(pipe_out[0]);
244 exit(!!async->proc(pipe_out[1], async->data));
245 }
246 close(pipe_out[1]);
247
248 return 0;
249}
250
251int finish_async(struct async *async)
252{
253 int ret = 0;
254
255 if (wait_or_whine(async->pid))
256 ret = error("waitpid (async) failed");
257
258 return ret;
259}
260
261int run_hook(const char *index_file, const char *name, ...)
262{
263 struct child_process hook;
264 const char **argv = NULL, *env[2];
265 char idx[PATH_MAX];
266 va_list args;
267 int ret;
268 size_t i = 0, alloc = 0;
269
270 if (access(perf_path("hooks/%s", name), X_OK) < 0)
271 return 0;
272
273 va_start(args, name);
274 ALLOC_GROW(argv, i + 1, alloc);
275 argv[i++] = perf_path("hooks/%s", name);
276 while (argv[i-1]) {
277 ALLOC_GROW(argv, i + 1, alloc);
278 argv[i++] = va_arg(args, const char *);
279 }
280 va_end(args);
281
282 memset(&hook, 0, sizeof(hook));
283 hook.argv = argv;
284 hook.no_stdin = 1;
285 hook.stdout_to_stderr = 1;
286 if (index_file) {
287 snprintf(idx, sizeof(idx), "PERF_INDEX_FILE=%s", index_file);
288 env[0] = idx;
289 env[1] = NULL;
290 hook.env = env;
291 }
292
293 ret = start_command(&hook);
294 free(argv);
295 if (ret) {
296 warning("Could not spawn %s", argv[0]);
297 return ret;
298 }
299 ret = finish_command(&hook);
300 if (ret == -ERR_RUN_COMMAND_WAITPID_SIGNAL)
301 warning("%s exited due to uncaught signal", argv[0]);
302
303 return ret;
304}
diff --git a/tools/perf/util/run-command.h b/tools/perf/util/run-command.h
index d79028727ce2..1ef264d5069c 100644
--- a/tools/perf/util/run-command.h
+++ b/tools/perf/util/run-command.h
@@ -50,39 +50,9 @@ int start_command(struct child_process *);
50int finish_command(struct child_process *); 50int finish_command(struct child_process *);
51int run_command(struct child_process *); 51int run_command(struct child_process *);
52 52
53extern int run_hook(const char *index_file, const char *name, ...);
54
55#define RUN_COMMAND_NO_STDIN 1 53#define RUN_COMMAND_NO_STDIN 1
56#define RUN_PERF_CMD 2 /*If this is to be perf sub-command */ 54#define RUN_PERF_CMD 2 /*If this is to be perf sub-command */
57#define RUN_COMMAND_STDOUT_TO_STDERR 4 55#define RUN_COMMAND_STDOUT_TO_STDERR 4
58int run_command_v_opt(const char **argv, int opt); 56int run_command_v_opt(const char **argv, int opt);
59 57
60/*
61 * env (the environment) is to be formatted like environ: "VAR=VALUE".
62 * To unset an environment variable use just "VAR".
63 */
64int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env);
65
66/*
67 * The purpose of the following functions is to feed a pipe by running
68 * a function asynchronously and providing output that the caller reads.
69 *
70 * It is expected that no synchronization and mutual exclusion between
71 * the caller and the feed function is necessary so that the function
72 * can run in a thread without interfering with the caller.
73 */
74struct async {
75 /*
76 * proc writes to fd and closes it;
77 * returns 0 on success, non-zero on failure
78 */
79 int (*proc)(int fd, void *data);
80 void *data;
81 int out; /* caller reads from here and closes it */
82 pid_t pid;
83};
84
85int start_async(struct async *async);
86int finish_async(struct async *async);
87
88#endif /* __PERF_RUN_COMMAND_H */ 58#endif /* __PERF_RUN_COMMAND_H */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 25bfca4f10f0..e4eaa6d02f57 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -5,6 +5,7 @@
5#include <byteswap.h> 5#include <byteswap.h>
6#include <unistd.h> 6#include <unistd.h>
7#include <sys/types.h> 7#include <sys/types.h>
8#include <sys/mman.h>
8 9
9#include "session.h" 10#include "session.h"
10#include "sort.h" 11#include "sort.h"
diff --git a/tools/perf/util/sigchain.c b/tools/perf/util/sigchain.c
index 1118b99e57d3..ba785e9b1841 100644
--- a/tools/perf/util/sigchain.c
+++ b/tools/perf/util/sigchain.c
@@ -16,7 +16,7 @@ static void check_signum(int sig)
16 die("BUG: signal out of range: %d", sig); 16 die("BUG: signal out of range: %d", sig);
17} 17}
18 18
19int sigchain_push(int sig, sigchain_fun f) 19static int sigchain_push(int sig, sigchain_fun f)
20{ 20{
21 struct sigchain_signal *s = signals + sig; 21 struct sigchain_signal *s = signals + sig;
22 check_signum(sig); 22 check_signum(sig);
diff --git a/tools/perf/util/sigchain.h b/tools/perf/util/sigchain.h
index 1a53c11265fd..959d64eb5557 100644
--- a/tools/perf/util/sigchain.h
+++ b/tools/perf/util/sigchain.h
@@ -3,7 +3,6 @@
3 3
4typedef void (*sigchain_fun)(int); 4typedef void (*sigchain_fun)(int);
5 5
6int sigchain_push(int sig, sigchain_fun f);
7int sigchain_pop(int sig); 6int sigchain_pop(int sig);
8 7
9void sigchain_push_common(sigchain_fun f); 8void sigchain_push_common(sigchain_fun f);
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index 5249d5a1b0c2..92e068517c1a 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -41,16 +41,6 @@ char *strbuf_detach(struct strbuf *sb, size_t *sz)
41 return res; 41 return res;
42} 42}
43 43
44void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc)
45{
46 strbuf_release(sb);
47 sb->buf = buf;
48 sb->len = len;
49 sb->alloc = alloc;
50 strbuf_grow(sb, 0);
51 sb->buf[sb->len] = '\0';
52}
53
54void strbuf_grow(struct strbuf *sb, size_t extra) 44void strbuf_grow(struct strbuf *sb, size_t extra)
55{ 45{
56 if (sb->len + extra + 1 <= sb->len) 46 if (sb->len + extra + 1 <= sb->len)
@@ -60,94 +50,7 @@ void strbuf_grow(struct strbuf *sb, size_t extra)
60 ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); 50 ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
61} 51}
62 52
63void strbuf_trim(struct strbuf *sb) 53static void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
64{
65 char *b = sb->buf;
66 while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
67 sb->len--;
68 while (sb->len > 0 && isspace(*b)) {
69 b++;
70 sb->len--;
71 }
72 memmove(sb->buf, b, sb->len);
73 sb->buf[sb->len] = '\0';
74}
75void strbuf_rtrim(struct strbuf *sb)
76{
77 while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
78 sb->len--;
79 sb->buf[sb->len] = '\0';
80}
81
82void strbuf_ltrim(struct strbuf *sb)
83{
84 char *b = sb->buf;
85 while (sb->len > 0 && isspace(*b)) {
86 b++;
87 sb->len--;
88 }
89 memmove(sb->buf, b, sb->len);
90 sb->buf[sb->len] = '\0';
91}
92
93void strbuf_tolower(struct strbuf *sb)
94{
95 unsigned int i;
96
97 for (i = 0; i < sb->len; i++)
98 sb->buf[i] = tolower(sb->buf[i]);
99}
100
101struct strbuf **strbuf_split(const struct strbuf *sb, int delim)
102{
103 int alloc = 2, pos = 0;
104 char *n, *p;
105 struct strbuf **ret;
106 struct strbuf *t;
107
108 ret = calloc(alloc, sizeof(struct strbuf *));
109 p = n = sb->buf;
110 while (n < sb->buf + sb->len) {
111 int len;
112 n = memchr(n, delim, sb->len - (n - sb->buf));
113 if (pos + 1 >= alloc) {
114 alloc = alloc * 2;
115 ret = realloc(ret, sizeof(struct strbuf *) * alloc);
116 }
117 if (!n)
118 n = sb->buf + sb->len - 1;
119 len = n - p + 1;
120 t = malloc(sizeof(struct strbuf));
121 strbuf_init(t, len);
122 strbuf_add(t, p, len);
123 ret[pos] = t;
124 ret[++pos] = NULL;
125 p = ++n;
126 }
127 return ret;
128}
129
130void strbuf_list_free(struct strbuf **sbs)
131{
132 struct strbuf **s = sbs;
133
134 while (*s) {
135 strbuf_release(*s);
136 free(*s++);
137 }
138 free(sbs);
139}
140
141int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
142{
143 int len = a->len < b->len ? a->len: b->len;
144 int cmp = memcmp(a->buf, b->buf, len);
145 if (cmp)
146 return cmp;
147 return a->len < b->len ? -1: a->len != b->len;
148}
149
150void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
151 const void *data, size_t dlen) 54 const void *data, size_t dlen)
152{ 55{
153 if (pos + len < pos) 56 if (pos + len < pos)
@@ -166,11 +69,6 @@ void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
166 strbuf_setlen(sb, sb->len + dlen - len); 69 strbuf_setlen(sb, sb->len + dlen - len);
167} 70}
168 71
169void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
170{
171 strbuf_splice(sb, pos, 0, data, len);
172}
173
174void strbuf_remove(struct strbuf *sb, size_t pos, size_t len) 72void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
175{ 73{
176 strbuf_splice(sb, pos, len, NULL, 0); 74 strbuf_splice(sb, pos, len, NULL, 0);
@@ -183,13 +81,6 @@ void strbuf_add(struct strbuf *sb, const void *data, size_t len)
183 strbuf_setlen(sb, sb->len + len); 81 strbuf_setlen(sb, sb->len + len);
184} 82}
185 83
186void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
187{
188 strbuf_grow(sb, len);
189 memcpy(sb->buf + sb->len, sb->buf + pos, len);
190 strbuf_setlen(sb, sb->len + len);
191}
192
193void strbuf_addf(struct strbuf *sb, const char *fmt, ...) 84void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
194{ 85{
195 int len; 86 int len;
@@ -214,57 +105,6 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
214 strbuf_setlen(sb, sb->len + len); 105 strbuf_setlen(sb, sb->len + len);
215} 106}
216 107
217void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,
218 void *context)
219{
220 for (;;) {
221 const char *percent;
222 size_t consumed;
223
224 percent = strchrnul(format, '%');
225 strbuf_add(sb, format, percent - format);
226 if (!*percent)
227 break;
228 format = percent + 1;
229
230 consumed = fn(sb, format, context);
231 if (consumed)
232 format += consumed;
233 else
234 strbuf_addch(sb, '%');
235 }
236}
237
238size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder,
239 void *context)
240{
241 struct strbuf_expand_dict_entry *e = context;
242 size_t len;
243
244 for (; e->placeholder && (len = strlen(e->placeholder)); e++) {
245 if (!strncmp(placeholder, e->placeholder, len)) {
246 if (e->value)
247 strbuf_addstr(sb, e->value);
248 return len;
249 }
250 }
251 return 0;
252}
253
254size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
255{
256 size_t res;
257 size_t oldalloc = sb->alloc;
258
259 strbuf_grow(sb, size);
260 res = fread(sb->buf + sb->len, 1, size, f);
261 if (res > 0)
262 strbuf_setlen(sb, sb->len + res);
263 else if (oldalloc == 0)
264 strbuf_release(sb);
265 return res;
266}
267
268ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) 108ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
269{ 109{
270 size_t oldlen = sb->len; 110 size_t oldlen = sb->len;
@@ -291,70 +131,3 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
291 sb->buf[sb->len] = '\0'; 131 sb->buf[sb->len] = '\0';
292 return sb->len - oldlen; 132 return sb->len - oldlen;
293} 133}
294
295#define STRBUF_MAXLINK (2*PATH_MAX)
296
297int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint)
298{
299 size_t oldalloc = sb->alloc;
300
301 if (hint < 32)
302 hint = 32;
303
304 while (hint < STRBUF_MAXLINK) {
305 ssize_t len;
306
307 strbuf_grow(sb, hint);
308 len = readlink(path, sb->buf, hint);
309 if (len < 0) {
310 if (errno != ERANGE)
311 break;
312 } else if (len < hint) {
313 strbuf_setlen(sb, len);
314 return 0;
315 }
316
317 /* .. the buffer was too small - try again */
318 hint *= 2;
319 }
320 if (oldalloc == 0)
321 strbuf_release(sb);
322 return -1;
323}
324
325int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
326{
327 int ch;
328
329 strbuf_grow(sb, 0);
330 if (feof(fp))
331 return EOF;
332
333 strbuf_reset(sb);
334 while ((ch = fgetc(fp)) != EOF) {
335 if (ch == term)
336 break;
337 strbuf_grow(sb, 1);
338 sb->buf[sb->len++] = ch;
339 }
340 if (ch == EOF && sb->len == 0)
341 return EOF;
342
343 sb->buf[sb->len] = '\0';
344 return 0;
345}
346
347int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint)
348{
349 int fd, len;
350
351 fd = open(path, O_RDONLY);
352 if (fd < 0)
353 return -1;
354 len = strbuf_read(sb, fd, hint);
355 close(fd);
356 if (len < 0)
357 return -1;
358
359 return len;
360}
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
index a3d121d6c83e..436ac319f6c7 100644
--- a/tools/perf/util/strbuf.h
+++ b/tools/perf/util/strbuf.h
@@ -53,12 +53,6 @@ struct strbuf {
53extern void strbuf_init(struct strbuf *buf, ssize_t hint); 53extern void strbuf_init(struct strbuf *buf, ssize_t hint);
54extern void strbuf_release(struct strbuf *); 54extern void strbuf_release(struct strbuf *);
55extern char *strbuf_detach(struct strbuf *, size_t *); 55extern char *strbuf_detach(struct strbuf *, size_t *);
56extern void strbuf_attach(struct strbuf *, void *, size_t, size_t);
57static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) {
58 struct strbuf tmp = *a;
59 *a = *b;
60 *b = tmp;
61}
62 56
63/*----- strbuf size related -----*/ 57/*----- strbuf size related -----*/
64static inline ssize_t strbuf_avail(const struct strbuf *sb) { 58static inline ssize_t strbuf_avail(const struct strbuf *sb) {
@@ -74,17 +68,6 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len) {
74 sb->len = len; 68 sb->len = len;
75 sb->buf[len] = '\0'; 69 sb->buf[len] = '\0';
76} 70}
77#define strbuf_reset(sb) strbuf_setlen(sb, 0)
78
79/*----- content related -----*/
80extern void strbuf_trim(struct strbuf *);
81extern void strbuf_rtrim(struct strbuf *);
82extern void strbuf_ltrim(struct strbuf *);
83extern int strbuf_cmp(const struct strbuf *, const struct strbuf *);
84extern void strbuf_tolower(struct strbuf *);
85
86extern struct strbuf **strbuf_split(const struct strbuf *, int delim);
87extern void strbuf_list_free(struct strbuf **);
88 71
89/*----- add data in your buffer -----*/ 72/*----- add data in your buffer -----*/
90static inline void strbuf_addch(struct strbuf *sb, int c) { 73static inline void strbuf_addch(struct strbuf *sb, int c) {
@@ -93,45 +76,17 @@ static inline void strbuf_addch(struct strbuf *sb, int c) {
93 sb->buf[sb->len] = '\0'; 76 sb->buf[sb->len] = '\0';
94} 77}
95 78
96extern void strbuf_insert(struct strbuf *, size_t pos, const void *, size_t);
97extern void strbuf_remove(struct strbuf *, size_t pos, size_t len); 79extern void strbuf_remove(struct strbuf *, size_t pos, size_t len);
98 80
99/* splice pos..pos+len with given data */
100extern void strbuf_splice(struct strbuf *, size_t pos, size_t len,
101 const void *, size_t);
102
103extern void strbuf_add(struct strbuf *, const void *, size_t); 81extern void strbuf_add(struct strbuf *, const void *, size_t);
104static inline void strbuf_addstr(struct strbuf *sb, const char *s) { 82static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
105 strbuf_add(sb, s, strlen(s)); 83 strbuf_add(sb, s, strlen(s));
106} 84}
107static inline void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2) {
108 strbuf_add(sb, sb2->buf, sb2->len);
109}
110extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len);
111
112typedef size_t (*expand_fn_t) (struct strbuf *sb, const char *placeholder, void *context);
113extern void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn, void *context);
114struct strbuf_expand_dict_entry {
115 const char *placeholder;
116 const char *value;
117};
118extern size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder, void *context);
119 85
120__attribute__((format(printf,2,3))) 86__attribute__((format(printf,2,3)))
121extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...); 87extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
122 88
123extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
124/* XXX: if read fails, any partial read is undone */ 89/* XXX: if read fails, any partial read is undone */
125extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); 90extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
126extern int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint);
127extern int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint);
128
129extern int strbuf_getline(struct strbuf *, FILE *, int);
130
131extern void stripspace(struct strbuf *buf, int skip_comments);
132extern int launch_editor(const char *path, struct strbuf *buffer, const char *const *env);
133
134extern int strbuf_branchname(struct strbuf *sb, const char *name);
135extern int strbuf_check_branch_ref(struct strbuf *sb, const char *name);
136 91
137#endif /* __PERF_STRBUF_H */ 92#endif /* __PERF_STRBUF_H */
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 0795bf304b19..52118a0c0bad 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -152,7 +152,6 @@ extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)))
152extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); 152extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
153 153
154extern int prefixcmp(const char *str, const char *prefix); 154extern int prefixcmp(const char *str, const char *prefix);
155extern time_t tm_to_time_t(const struct tm *tm);
156 155
157static inline const char *skip_prefix(const char *str, const char *prefix) 156static inline const char *skip_prefix(const char *str, const char *prefix)
158{ 157{
@@ -160,119 +159,6 @@ static inline const char *skip_prefix(const char *str, const char *prefix)
160 return strncmp(str, prefix, len) ? NULL : str + len; 159 return strncmp(str, prefix, len) ? NULL : str + len;
161} 160}
162 161
163#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
164
165#ifndef PROT_READ
166#define PROT_READ 1
167#define PROT_WRITE 2
168#define MAP_PRIVATE 1
169#define MAP_FAILED ((void*)-1)
170#endif
171
172#define mmap git_mmap
173#define munmap git_munmap
174extern void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
175extern int git_munmap(void *start, size_t length);
176
177#else /* NO_MMAP || USE_WIN32_MMAP */
178
179#include <sys/mman.h>
180
181#endif /* NO_MMAP || USE_WIN32_MMAP */
182
183#ifdef NO_MMAP
184
185/* This value must be multiple of (pagesize * 2) */
186#define DEFAULT_PACKED_GIT_WINDOW_SIZE (1 * 1024 * 1024)
187
188#else /* NO_MMAP */
189
190/* This value must be multiple of (pagesize * 2) */
191#define DEFAULT_PACKED_GIT_WINDOW_SIZE \
192 (sizeof(void*) >= 8 \
193 ? 1 * 1024 * 1024 * 1024 \
194 : 32 * 1024 * 1024)
195
196#endif /* NO_MMAP */
197
198#ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
199#define on_disk_bytes(st) ((st).st_size)
200#else
201#define on_disk_bytes(st) ((st).st_blocks * 512)
202#endif
203
204#define DEFAULT_PACKED_GIT_LIMIT \
205 ((1024L * 1024L) * (sizeof(void*) >= 8 ? 8192 : 256))
206
207#ifdef NO_PREAD
208#define pread git_pread
209extern ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
210#endif
211/*
212 * Forward decl that will remind us if its twin in cache.h changes.
213 * This function is used in compat/pread.c. But we can't include
214 * cache.h there.
215 */
216extern ssize_t read_in_full(int fd, void *buf, size_t count);
217
218#ifdef NO_SETENV
219#define setenv gitsetenv
220extern int gitsetenv(const char *, const char *, int);
221#endif
222
223#ifdef NO_MKDTEMP
224#define mkdtemp gitmkdtemp
225extern char *gitmkdtemp(char *);
226#endif
227
228#ifdef NO_UNSETENV
229#define unsetenv gitunsetenv
230extern void gitunsetenv(const char *);
231#endif
232
233#ifdef NO_STRCASESTR
234#define strcasestr gitstrcasestr
235extern char *gitstrcasestr(const char *haystack, const char *needle);
236#endif
237
238#ifdef NO_STRLCPY
239#define strlcpy gitstrlcpy
240extern size_t gitstrlcpy(char *, const char *, size_t);
241#endif
242
243#ifdef NO_STRTOUMAX
244#define strtoumax gitstrtoumax
245extern uintmax_t gitstrtoumax(const char *, char **, int);
246#endif
247
248#ifdef NO_HSTRERROR
249#define hstrerror githstrerror
250extern const char *githstrerror(int herror);
251#endif
252
253#ifdef NO_MEMMEM
254#define memmem gitmemmem
255void *gitmemmem(const void *haystack, size_t haystacklen,
256 const void *needle, size_t needlelen);
257#endif
258
259#ifdef FREAD_READS_DIRECTORIES
260#ifdef fopen
261#undef fopen
262#endif
263#define fopen(a,b) git_fopen(a,b)
264extern FILE *git_fopen(const char*, const char*);
265#endif
266
267#ifdef SNPRINTF_RETURNS_BOGUS
268#define snprintf git_snprintf
269extern int git_snprintf(char *str, size_t maxsize,
270 const char *format, ...);
271#define vsnprintf git_vsnprintf
272extern int git_vsnprintf(char *str, size_t maxsize,
273 const char *format, va_list ap);
274#endif
275
276#ifdef __GLIBC_PREREQ 162#ifdef __GLIBC_PREREQ
277#if __GLIBC_PREREQ(2, 1) 163#if __GLIBC_PREREQ(2, 1)
278#define HAVE_STRCHRNUL 164#define HAVE_STRCHRNUL
@@ -294,7 +180,6 @@ static inline char *gitstrchrnul(const char *s, int c)
294 */ 180 */
295extern char *xstrdup(const char *str); 181extern char *xstrdup(const char *str);
296extern void *xmalloc(size_t size) __attribute__((weak)); 182extern void *xmalloc(size_t size) __attribute__((weak));
297extern void *xmemdupz(const void *data, size_t len);
298extern char *xstrndup(const char *str, size_t len); 183extern char *xstrndup(const char *str, size_t len);
299extern void *xrealloc(void *ptr, size_t size) __attribute__((weak)); 184extern void *xrealloc(void *ptr, size_t size) __attribute__((weak));
300 185
@@ -310,11 +195,6 @@ static inline void *zalloc(size_t size)
310 return calloc(1, size); 195 return calloc(1, size);
311} 196}
312 197
313static inline size_t xsize_t(off_t len)
314{
315 return (size_t)len;
316}
317
318static inline int has_extension(const char *filename, const char *ext) 198static inline int has_extension(const char *filename, const char *ext)
319{ 199{
320 size_t len = strlen(filename); 200 size_t len = strlen(filename);
@@ -351,8 +231,6 @@ extern unsigned char sane_ctype[256];
351#define isalpha(x) sane_istest(x,GIT_ALPHA) 231#define isalpha(x) sane_istest(x,GIT_ALPHA)
352#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) 232#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
353#define isprint(x) sane_istest(x,GIT_PRINT) 233#define isprint(x) sane_istest(x,GIT_PRINT)
354#define is_glob_special(x) sane_istest(x,GIT_GLOB_SPECIAL)
355#define is_regex_special(x) sane_istest(x,GIT_GLOB_SPECIAL | GIT_REGEX_SPECIAL)
356#define tolower(x) sane_case((unsigned char)(x), 0x20) 234#define tolower(x) sane_case((unsigned char)(x), 0x20)
357#define toupper(x) sane_case((unsigned char)(x), 0) 235#define toupper(x) sane_case((unsigned char)(x), 0)
358 236
@@ -363,38 +241,6 @@ static inline int sane_case(int x, int high)
363 return x; 241 return x;
364} 242}
365 243
366static inline int strtoul_ui(char const *s, int base, unsigned int *result)
367{
368 unsigned long ul;
369 char *p;
370
371 errno = 0;
372 ul = strtoul(s, &p, base);
373 if (errno || *p || p == s || (unsigned int) ul != ul)
374 return -1;
375 *result = ul;
376 return 0;
377}
378
379static inline int strtol_i(char const *s, int base, int *result)
380{
381 long ul;
382 char *p;
383
384 errno = 0;
385 ul = strtol(s, &p, base);
386 if (errno || *p || p == s || (int) ul != ul)
387 return -1;
388 *result = ul;
389 return 0;
390}
391
392#ifdef INTERNAL_QSORT
393void git_qsort(void *base, size_t nmemb, size_t size,
394 int(*compar)(const void *, const void *));
395#define qsort git_qsort
396#endif
397
398#ifndef DIR_HAS_BSD_GROUP_SEMANTICS 244#ifndef DIR_HAS_BSD_GROUP_SEMANTICS
399# define FORCE_DIR_SET_GID S_ISGID 245# define FORCE_DIR_SET_GID S_ISGID
400#else 246#else
diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c
index bf44ca85d23b..c4ced7c1251d 100644
--- a/tools/perf/util/wrapper.c
+++ b/tools/perf/util/wrapper.c
@@ -48,7 +48,7 @@ void *xmalloc(size_t size)
48 * and returns a pointer to the allocated memory. If the allocation fails, 48 * and returns a pointer to the allocated memory. If the allocation fails,
49 * the program dies. 49 * the program dies.
50 */ 50 */
51void *xmemdupz(const void *data, size_t len) 51static void *xmemdupz(const void *data, size_t len)
52{ 52{
53 char *p = xmalloc(len + 1); 53 char *p = xmalloc(len + 1);
54 memcpy(p, data, len); 54 memcpy(p, data, len);
@@ -78,73 +78,3 @@ void *xrealloc(void *ptr, size_t size)
78 } 78 }
79 return ret; 79 return ret;
80} 80}
81
82/*
83 * xread() is the same a read(), but it automatically restarts read()
84 * operations with a recoverable error (EAGAIN and EINTR). xread()
85 * DOES NOT GUARANTEE that "len" bytes is read even if the data is available.
86 */
87static ssize_t xread(int fd, void *buf, size_t len)
88{
89 ssize_t nr;
90 while (1) {
91 nr = read(fd, buf, len);
92 if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
93 continue;
94 return nr;
95 }
96}
97
98/*
99 * xwrite() is the same a write(), but it automatically restarts write()
100 * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT
101 * GUARANTEE that "len" bytes is written even if the operation is successful.
102 */
103static ssize_t xwrite(int fd, const void *buf, size_t len)
104{
105 ssize_t nr;
106 while (1) {
107 nr = write(fd, buf, len);
108 if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
109 continue;
110 return nr;
111 }
112}
113
114ssize_t read_in_full(int fd, void *buf, size_t count)
115{
116 char *p = buf;
117 ssize_t total = 0;
118
119 while (count > 0) {
120 ssize_t loaded = xread(fd, p, count);
121 if (loaded <= 0)
122 return total ? total : loaded;
123 count -= loaded;
124 p += loaded;
125 total += loaded;
126 }
127
128 return total;
129}
130
131ssize_t write_in_full(int fd, const void *buf, size_t count)
132{
133 const char *p = buf;
134 ssize_t total = 0;
135
136 while (count > 0) {
137 ssize_t written = xwrite(fd, p, count);
138 if (written < 0)
139 return -1;
140 if (!written) {
141 errno = ENOSPC;
142 return -1;
143 }
144 count -= written;
145 p += written;
146 total += written;
147 }
148
149 return total;
150}