]> git.proxmox.com Git - mirror_ovs.git/blob - lib/util.c
Merge "master" into "next".
[mirror_ovs.git] / lib / util.c
1 /*
2 * Copyright (c) 2008, 2009, 2010 Nicira Networks.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <config.h>
18 #include "util.h"
19 #include <errno.h>
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include "coverage.h"
25
26 const char *program_name;
27
28 void
29 out_of_memory(void)
30 {
31 ovs_fatal(0, "virtual memory exhausted");
32 }
33
34 void *
35 xcalloc(size_t count, size_t size)
36 {
37 void *p = count && size ? calloc(count, size) : malloc(1);
38 COVERAGE_INC(util_xalloc);
39 if (p == NULL) {
40 out_of_memory();
41 }
42 return p;
43 }
44
45 void *
46 xzalloc(size_t size)
47 {
48 return xcalloc(1, size);
49 }
50
51 void *
52 xmalloc(size_t size)
53 {
54 void *p = malloc(size ? size : 1);
55 COVERAGE_INC(util_xalloc);
56 if (p == NULL) {
57 out_of_memory();
58 }
59 return p;
60 }
61
62 void *
63 xrealloc(void *p, size_t size)
64 {
65 p = realloc(p, size ? size : 1);
66 COVERAGE_INC(util_xalloc);
67 if (p == NULL) {
68 out_of_memory();
69 }
70 return p;
71 }
72
73 void *
74 xmemdup(const void *p_, size_t size)
75 {
76 void *p = xmalloc(size);
77 memcpy(p, p_, size);
78 return p;
79 }
80
81 char *
82 xmemdup0(const char *p_, size_t length)
83 {
84 char *p = xmalloc(length + 1);
85 memcpy(p, p_, length);
86 p[length] = '\0';
87 return p;
88 }
89
90 char *
91 xstrdup(const char *s)
92 {
93 return xmemdup0(s, strlen(s));
94 }
95
96 char *
97 xvasprintf(const char *format, va_list args)
98 {
99 va_list args2;
100 size_t needed;
101 char *s;
102
103 va_copy(args2, args);
104 needed = vsnprintf(NULL, 0, format, args);
105
106 s = xmalloc(needed + 1);
107
108 vsnprintf(s, needed + 1, format, args2);
109 va_end(args2);
110
111 return s;
112 }
113
114 void *
115 x2nrealloc(void *p, size_t *n, size_t s)
116 {
117 *n = *n == 0 ? 1 : 2 * *n;
118 return xrealloc(p, *n * s);
119 }
120
121 char *
122 xasprintf(const char *format, ...)
123 {
124 va_list args;
125 char *s;
126
127 va_start(args, format);
128 s = xvasprintf(format, args);
129 va_end(args);
130
131 return s;
132 }
133
134 void
135 ovs_strlcpy(char *dst, const char *src, size_t size)
136 {
137 if (size > 0) {
138 size_t n = strlen(src);
139 size_t n_copy = MIN(n, size - 1);
140 memcpy(dst, src, n_copy);
141 dst[n_copy] = '\0';
142 }
143 }
144
145 void
146 ovs_fatal(int err_no, const char *format, ...)
147 {
148 va_list args;
149
150 fprintf(stderr, "%s: ", program_name);
151 va_start(args, format);
152 vfprintf(stderr, format, args);
153 va_end(args);
154 if (err_no != 0)
155 fprintf(stderr, " (%s)", strerror(err_no));
156 putc('\n', stderr);
157
158 exit(EXIT_FAILURE);
159 }
160
161 void
162 ovs_error(int err_no, const char *format, ...)
163 {
164 int save_errno = errno;
165 va_list args;
166
167 fprintf(stderr, "%s: ", program_name);
168 va_start(args, format);
169 vfprintf(stderr, format, args);
170 va_end(args);
171 if (err_no != 0) {
172 fprintf(stderr, " (%s)",
173 err_no == EOF ? "end of file" : strerror(err_no));
174 }
175 putc('\n', stderr);
176
177 errno = save_errno;
178 }
179
180 /* Sets program_name based on 'argv0'. Should be called at the beginning of
181 * main(), as "set_program_name(argv[0]);". */
182 void set_program_name(const char *argv0)
183 {
184 const char *slash = strrchr(argv0, '/');
185 program_name = slash ? slash + 1 : argv0;
186 }
187
188 /* Print the version information for the program. */
189 void
190 ovs_print_version(char *date, char *time,
191 uint8_t min_ofp, uint8_t max_ofp)
192 {
193 printf("%s (Open vSwitch) "VERSION BUILDNR"\n", program_name);
194 printf("Compiled %s %s\n", date, time);
195 if (min_ofp || max_ofp) {
196 printf("OpenFlow versions %#x:%#x\n", min_ofp, max_ofp);
197 }
198 }
199
200 /* Writes the 'size' bytes in 'buf' to 'stream' as hex bytes arranged 16 per
201 * line. Numeric offsets are also included, starting at 'ofs' for the first
202 * byte in 'buf'. If 'ascii' is true then the corresponding ASCII characters
203 * are also rendered alongside. */
204 void
205 ovs_hex_dump(FILE *stream, const void *buf_, size_t size,
206 uintptr_t ofs, bool ascii)
207 {
208 const uint8_t *buf = buf_;
209 const size_t per_line = 16; /* Maximum bytes per line. */
210
211 while (size > 0)
212 {
213 size_t start, end, n;
214 size_t i;
215
216 /* Number of bytes on this line. */
217 start = ofs % per_line;
218 end = per_line;
219 if (end - start > size)
220 end = start + size;
221 n = end - start;
222
223 /* Print line. */
224 fprintf(stream, "%08jx ", (uintmax_t) ROUND_DOWN(ofs, per_line));
225 for (i = 0; i < start; i++)
226 fprintf(stream, " ");
227 for (; i < end; i++)
228 fprintf(stream, "%02hhx%c",
229 buf[i - start], i == per_line / 2 - 1? '-' : ' ');
230 if (ascii)
231 {
232 for (; i < per_line; i++)
233 fprintf(stream, " ");
234 fprintf(stream, "|");
235 for (i = 0; i < start; i++)
236 fprintf(stream, " ");
237 for (; i < end; i++) {
238 int c = buf[i - start];
239 putc(c >= 32 && c < 127 ? c : '.', stream);
240 }
241 for (; i < per_line; i++)
242 fprintf(stream, " ");
243 fprintf(stream, "|");
244 }
245 fprintf(stream, "\n");
246
247 ofs += n;
248 buf += n;
249 size -= n;
250 }
251 }
252
253 bool
254 str_to_int(const char *s, int base, int *i)
255 {
256 long long ll;
257 bool ok = str_to_llong(s, base, &ll);
258 *i = ll;
259 return ok;
260 }
261
262 bool
263 str_to_long(const char *s, int base, long *li)
264 {
265 long long ll;
266 bool ok = str_to_llong(s, base, &ll);
267 *li = ll;
268 return ok;
269 }
270
271 bool
272 str_to_llong(const char *s, int base, long long *x)
273 {
274 int save_errno = errno;
275 char *tail;
276 errno = 0;
277 *x = strtoll(s, &tail, base);
278 if (errno == EINVAL || errno == ERANGE || tail == s || *tail != '\0') {
279 errno = save_errno;
280 *x = 0;
281 return false;
282 } else {
283 errno = save_errno;
284 return true;
285 }
286 }
287
288 bool
289 str_to_uint(const char *s, int base, unsigned int *u)
290 {
291 return str_to_int(s, base, (int *) u);
292 }
293
294 bool
295 str_to_ulong(const char *s, int base, unsigned long *ul)
296 {
297 return str_to_long(s, base, (long *) ul);
298 }
299
300 bool
301 str_to_ullong(const char *s, int base, unsigned long long *ull)
302 {
303 return str_to_llong(s, base, (long long *) ull);
304 }
305
306 /* Converts floating-point string 's' into a double. If successful, stores
307 * the double in '*d' and returns true; on failure, stores 0 in '*d' and
308 * returns false.
309 *
310 * Underflow (e.g. "1e-9999") is not considered an error, but overflow
311 * (e.g. "1e9999)" is. */
312 bool
313 str_to_double(const char *s, double *d)
314 {
315 int save_errno = errno;
316 char *tail;
317 errno = 0;
318 *d = strtod(s, &tail);
319 if (errno == EINVAL || (errno == ERANGE && *d != 0)
320 || tail == s || *tail != '\0') {
321 errno = save_errno;
322 *d = 0;
323 return false;
324 } else {
325 errno = save_errno;
326 return true;
327 }
328 }
329
330 /* Returns the value of 'c' as a hexadecimal digit. */
331 int
332 hexit_value(int c)
333 {
334 switch (c) {
335 case '0': case '1': case '2': case '3': case '4':
336 case '5': case '6': case '7': case '8': case '9':
337 return c - '0';
338
339 case 'a': case 'A':
340 return 0xa;
341
342 case 'b': case 'B':
343 return 0xb;
344
345 case 'c': case 'C':
346 return 0xc;
347
348 case 'd': case 'D':
349 return 0xd;
350
351 case 'e': case 'E':
352 return 0xe;
353
354 case 'f': case 'F':
355 return 0xf;
356 }
357
358 NOT_REACHED();
359 }
360
361 /* Returns the directory name portion of 'file_name' as a malloc()'d string,
362 * similar to the POSIX dirname() function but thread-safe. */
363 char *
364 dir_name(const char *file_name)
365 {
366 size_t len = strlen(file_name);
367 while (len > 0 && file_name[len - 1] == '/') {
368 len--;
369 }
370 while (len > 0 && file_name[len - 1] != '/') {
371 len--;
372 }
373 while (len > 0 && file_name[len - 1] == '/') {
374 len--;
375 }
376 if (!len) {
377 return xstrdup((file_name[0] == '/'
378 && file_name[1] == '/'
379 && file_name[2] != '/') ? "//"
380 : file_name[0] == '/' ? "/"
381 : ".");
382 } else {
383 return xmemdup0(file_name, len);
384 }
385 }
386
387 /* Pass a value to this function if it is marked with
388 * __attribute__((warn_unused_result)) and you genuinely want to ignore
389 * its return value. (Note that every scalar type can be implicitly
390 * converted to bool.) */
391 void ignore(bool x OVS_UNUSED) { }