xref: /openbmc/linux/tools/perf/util/util.c (revision 840ef8b7cc584a23c4f9d05352f4dbaf8e56e5ab)
1 #include "../perf.h"
2 #include "util.h"
3 #include <sys/mman.h>
4 #ifdef BACKTRACE_SUPPORT
5 #include <execinfo.h>
6 #endif
7 #include <stdio.h>
8 #include <stdlib.h>
9 
10 /*
11  * XXX We need to find a better place for these things...
12  */
13 unsigned int page_size;
14 
15 bool test_attr__enabled;
16 
17 bool perf_host  = true;
18 bool perf_guest = false;
19 
20 void event_attr_init(struct perf_event_attr *attr)
21 {
22 	if (!perf_host)
23 		attr->exclude_host  = 1;
24 	if (!perf_guest)
25 		attr->exclude_guest = 1;
26 	/* to capture ABI version */
27 	attr->size = sizeof(*attr);
28 }
29 
30 int mkdir_p(char *path, mode_t mode)
31 {
32 	struct stat st;
33 	int err;
34 	char *d = path;
35 
36 	if (*d != '/')
37 		return -1;
38 
39 	if (stat(path, &st) == 0)
40 		return 0;
41 
42 	while (*++d == '/');
43 
44 	while ((d = strchr(d, '/'))) {
45 		*d = '\0';
46 		err = stat(path, &st) && mkdir(path, mode);
47 		*d++ = '/';
48 		if (err)
49 			return -1;
50 		while (*d == '/')
51 			++d;
52 	}
53 	return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
54 }
55 
56 static int slow_copyfile(const char *from, const char *to)
57 {
58 	int err = 0;
59 	char *line = NULL;
60 	size_t n;
61 	FILE *from_fp = fopen(from, "r"), *to_fp;
62 
63 	if (from_fp == NULL)
64 		goto out;
65 
66 	to_fp = fopen(to, "w");
67 	if (to_fp == NULL)
68 		goto out_fclose_from;
69 
70 	while (getline(&line, &n, from_fp) > 0)
71 		if (fputs(line, to_fp) == EOF)
72 			goto out_fclose_to;
73 	err = 0;
74 out_fclose_to:
75 	fclose(to_fp);
76 	free(line);
77 out_fclose_from:
78 	fclose(from_fp);
79 out:
80 	return err;
81 }
82 
83 int copyfile(const char *from, const char *to)
84 {
85 	int fromfd, tofd;
86 	struct stat st;
87 	void *addr;
88 	int err = -1;
89 
90 	if (stat(from, &st))
91 		goto out;
92 
93 	if (st.st_size == 0) /* /proc? do it slowly... */
94 		return slow_copyfile(from, to);
95 
96 	fromfd = open(from, O_RDONLY);
97 	if (fromfd < 0)
98 		goto out;
99 
100 	tofd = creat(to, 0755);
101 	if (tofd < 0)
102 		goto out_close_from;
103 
104 	addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fromfd, 0);
105 	if (addr == MAP_FAILED)
106 		goto out_close_to;
107 
108 	if (write(tofd, addr, st.st_size) == st.st_size)
109 		err = 0;
110 
111 	munmap(addr, st.st_size);
112 out_close_to:
113 	close(tofd);
114 	if (err)
115 		unlink(to);
116 out_close_from:
117 	close(fromfd);
118 out:
119 	return err;
120 }
121 
122 unsigned long convert_unit(unsigned long value, char *unit)
123 {
124 	*unit = ' ';
125 
126 	if (value > 1000) {
127 		value /= 1000;
128 		*unit = 'K';
129 	}
130 
131 	if (value > 1000) {
132 		value /= 1000;
133 		*unit = 'M';
134 	}
135 
136 	if (value > 1000) {
137 		value /= 1000;
138 		*unit = 'G';
139 	}
140 
141 	return value;
142 }
143 
144 int readn(int fd, void *buf, size_t n)
145 {
146 	void *buf_start = buf;
147 
148 	while (n) {
149 		int ret = read(fd, buf, n);
150 
151 		if (ret <= 0)
152 			return ret;
153 
154 		n -= ret;
155 		buf += ret;
156 	}
157 
158 	return buf - buf_start;
159 }
160 
161 size_t hex_width(u64 v)
162 {
163 	size_t n = 1;
164 
165 	while ((v >>= 4))
166 		++n;
167 
168 	return n;
169 }
170 
171 static int hex(char ch)
172 {
173 	if ((ch >= '0') && (ch <= '9'))
174 		return ch - '0';
175 	if ((ch >= 'a') && (ch <= 'f'))
176 		return ch - 'a' + 10;
177 	if ((ch >= 'A') && (ch <= 'F'))
178 		return ch - 'A' + 10;
179 	return -1;
180 }
181 
182 /*
183  * While we find nice hex chars, build a long_val.
184  * Return number of chars processed.
185  */
186 int hex2u64(const char *ptr, u64 *long_val)
187 {
188 	const char *p = ptr;
189 	*long_val = 0;
190 
191 	while (*p) {
192 		const int hex_val = hex(*p);
193 
194 		if (hex_val < 0)
195 			break;
196 
197 		*long_val = (*long_val << 4) | hex_val;
198 		p++;
199 	}
200 
201 	return p - ptr;
202 }
203 
204 /* Obtain a backtrace and print it to stdout. */
205 #ifdef BACKTRACE_SUPPORT
206 void dump_stack(void)
207 {
208 	void *array[16];
209 	size_t size = backtrace(array, ARRAY_SIZE(array));
210 	char **strings = backtrace_symbols(array, size);
211 	size_t i;
212 
213 	printf("Obtained %zd stack frames.\n", size);
214 
215 	for (i = 0; i < size; i++)
216 		printf("%s\n", strings[i]);
217 
218 	free(strings);
219 }
220 #else
221 void dump_stack(void) {}
222 #endif
223 
224 void get_term_dimensions(struct winsize *ws)
225 {
226 	char *s = getenv("LINES");
227 
228 	if (s != NULL) {
229 		ws->ws_row = atoi(s);
230 		s = getenv("COLUMNS");
231 		if (s != NULL) {
232 			ws->ws_col = atoi(s);
233 			if (ws->ws_row && ws->ws_col)
234 				return;
235 		}
236 	}
237 #ifdef TIOCGWINSZ
238 	if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
239 	    ws->ws_row && ws->ws_col)
240 		return;
241 #endif
242 	ws->ws_row = 25;
243 	ws->ws_col = 80;
244 }
245