dpif-linux: Use hash instead of sorted array.
[openvswitch] / 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 <unistd.h>
25 #include "coverage.h"
26
27 #define THIS_MODULE VLM_util
28 #include "vlog.h"
29
30 const char *program_name;
31
32 void
33 out_of_memory(void) 
34 {
35     ovs_fatal(0, "virtual memory exhausted");
36 }
37
38 void *
39 xcalloc(size_t count, size_t size) 
40 {
41     void *p = count && size ? calloc(count, size) : malloc(1);
42     COVERAGE_INC(util_xalloc);
43     if (p == NULL) {
44         out_of_memory();
45     }
46     return p;
47 }
48
49 void *
50 xzalloc(size_t size)
51 {
52     return xcalloc(1, size);
53 }
54
55 void *
56 xmalloc(size_t size) 
57 {
58     void *p = malloc(size ? size : 1);
59     COVERAGE_INC(util_xalloc);
60     if (p == NULL) {
61         out_of_memory();
62     }
63     return p;
64 }
65
66 void *
67 xrealloc(void *p, size_t size) 
68 {
69     p = realloc(p, size ? size : 1);
70     COVERAGE_INC(util_xalloc);
71     if (p == NULL) {
72         out_of_memory();
73     }
74     return p;
75 }
76
77 void *
78 xmemdup(const void *p_, size_t size)
79 {
80     void *p = xmalloc(size);
81     memcpy(p, p_, size);
82     return p;
83 }
84
85 char *
86 xmemdup0(const char *p_, size_t length)
87 {
88     char *p = xmalloc(length + 1);
89     memcpy(p, p_, length);
90     p[length] = '\0';
91     return p;
92 }
93
94 char *
95 xstrdup(const char *s) 
96 {
97     return xmemdup0(s, strlen(s));
98 }
99
100 char *
101 xvasprintf(const char *format, va_list args)
102 {
103     va_list args2;
104     size_t needed;
105     char *s;
106
107     va_copy(args2, args);
108     needed = vsnprintf(NULL, 0, format, args);
109
110     s = xmalloc(needed + 1);
111
112     vsnprintf(s, needed + 1, format, args2);
113     va_end(args2);
114
115     return s;
116 }
117
118 void *
119 x2nrealloc(void *p, size_t *n, size_t s)
120 {
121     *n = *n == 0 ? 1 : 2 * *n;
122     return xrealloc(p, *n * s);
123 }
124
125 char *
126 xasprintf(const char *format, ...)
127 {
128     va_list args;
129     char *s;
130
131     va_start(args, format);
132     s = xvasprintf(format, args);
133     va_end(args);
134
135     return s;
136 }
137
138 void
139 ovs_strlcpy(char *dst, const char *src, size_t size)
140 {
141     if (size > 0) {
142         size_t n = strlen(src);
143         size_t n_copy = MIN(n, size - 1);
144         memcpy(dst, src, n_copy);
145         dst[n_copy] = '\0';
146     }
147 }
148
149 void
150 ovs_fatal(int err_no, const char *format, ...)
151 {
152     va_list args;
153
154     fprintf(stderr, "%s: ", program_name);
155     va_start(args, format);
156     vfprintf(stderr, format, args);
157     va_end(args);
158     if (err_no != 0)
159         fprintf(stderr, " (%s)", strerror(err_no));
160     putc('\n', stderr);
161
162     exit(EXIT_FAILURE);
163 }
164
165 void
166 ovs_error(int err_no, const char *format, ...)
167 {
168     int save_errno = errno;
169     va_list args;
170
171     fprintf(stderr, "%s: ", program_name);
172     va_start(args, format);
173     vfprintf(stderr, format, args);
174     va_end(args);
175     if (err_no != 0) {
176         fprintf(stderr, " (%s)",
177                 err_no == EOF ? "end of file" : strerror(err_no));
178     }
179     putc('\n', stderr);
180
181     errno = save_errno;
182 }
183
184 /* Sets program_name based on 'argv0'.  Should be called at the beginning of
185  * main(), as "set_program_name(argv[0]);".  */
186 void set_program_name(const char *argv0)
187 {
188     const char *slash = strrchr(argv0, '/');
189     program_name = slash ? slash + 1 : argv0;
190 }
191
192 /* Print the version information for the program.  */
193 void
194 ovs_print_version(char *date, char *time, 
195                   uint8_t min_ofp, uint8_t max_ofp)
196 {
197     printf("%s (Open vSwitch) "VERSION BUILDNR"\n", program_name);
198     printf("Compiled %s %s\n", date, time);
199     if (min_ofp || max_ofp) {
200         printf("OpenFlow versions %#x:%#x\n", min_ofp, max_ofp);
201     }
202 }
203
204 /* Writes the 'size' bytes in 'buf' to 'stream' as hex bytes arranged 16 per
205  * line.  Numeric offsets are also included, starting at 'ofs' for the first
206  * byte in 'buf'.  If 'ascii' is true then the corresponding ASCII characters
207  * are also rendered alongside. */
208 void
209 ovs_hex_dump(FILE *stream, const void *buf_, size_t size,
210              uintptr_t ofs, bool ascii)
211 {
212   const uint8_t *buf = buf_;
213   const size_t per_line = 16; /* Maximum bytes per line. */
214
215   while (size > 0)
216     {
217       size_t start, end, n;
218       size_t i;
219
220       /* Number of bytes on this line. */
221       start = ofs % per_line;
222       end = per_line;
223       if (end - start > size)
224         end = start + size;
225       n = end - start;
226
227       /* Print line. */
228       fprintf(stream, "%08jx  ", (uintmax_t) ROUND_DOWN(ofs, per_line));
229       for (i = 0; i < start; i++)
230         fprintf(stream, "   ");
231       for (; i < end; i++)
232         fprintf(stream, "%02hhx%c",
233                 buf[i - start], i == per_line / 2 - 1? '-' : ' ');
234       if (ascii)
235         {
236           for (; i < per_line; i++)
237             fprintf(stream, "   ");
238           fprintf(stream, "|");
239           for (i = 0; i < start; i++)
240             fprintf(stream, " ");
241           for (; i < end; i++) {
242               int c = buf[i - start];
243               putc(c >= 32 && c < 127 ? c : '.', stream);
244           }
245           for (; i < per_line; i++)
246             fprintf(stream, " ");
247           fprintf(stream, "|");
248         }
249       fprintf(stream, "\n");
250
251       ofs += n;
252       buf += n;
253       size -= n;
254     }
255 }
256
257 bool
258 str_to_int(const char *s, int base, int *i)
259 {
260     long long ll;
261     bool ok = str_to_llong(s, base, &ll);
262     *i = ll;
263     return ok;
264 }
265
266 bool
267 str_to_long(const char *s, int base, long *li)
268 {
269     long long ll;
270     bool ok = str_to_llong(s, base, &ll);
271     *li = ll;
272     return ok;
273 }
274
275 bool
276 str_to_llong(const char *s, int base, long long *x)
277 {
278     int save_errno = errno;
279     char *tail;
280     errno = 0;
281     *x = strtoll(s, &tail, base);
282     if (errno == EINVAL || errno == ERANGE || tail == s || *tail != '\0') {
283         errno = save_errno;
284         *x = 0;
285         return false;
286     } else {
287         errno = save_errno;
288         return true;
289     }
290 }
291
292 bool
293 str_to_uint(const char *s, int base, unsigned int *u)
294 {
295     return str_to_int(s, base, (int *) u);
296 }
297
298 bool
299 str_to_ulong(const char *s, int base, unsigned long *ul)
300 {
301     return str_to_long(s, base, (long *) ul);
302 }
303
304 bool
305 str_to_ullong(const char *s, int base, unsigned long long *ull)
306 {
307     return str_to_llong(s, base, (long long *) ull);
308 }
309
310 /* Converts floating-point string 's' into a double.  If successful, stores
311  * the double in '*d' and returns true; on failure, stores 0 in '*d' and
312  * returns false.
313  *
314  * Underflow (e.g. "1e-9999") is not considered an error, but overflow
315  * (e.g. "1e9999)" is. */
316 bool
317 str_to_double(const char *s, double *d)
318 {
319     int save_errno = errno;
320     char *tail;
321     errno = 0;
322     *d = strtod(s, &tail);
323     if (errno == EINVAL || (errno == ERANGE && *d != 0)
324         || tail == s || *tail != '\0') {
325         errno = save_errno;
326         *d = 0;
327         return false;
328     } else {
329         errno = save_errno;
330         return true;
331     }
332 }
333
334 /* Returns the value of 'c' as a hexadecimal digit. */
335 int
336 hexit_value(int c)
337 {
338     switch (c) {
339     case '0': case '1': case '2': case '3': case '4':
340     case '5': case '6': case '7': case '8': case '9':
341         return c - '0';
342
343     case 'a': case 'A':
344         return 0xa;
345
346     case 'b': case 'B':
347         return 0xb;
348
349     case 'c': case 'C':
350         return 0xc;
351
352     case 'd': case 'D':
353         return 0xd;
354
355     case 'e': case 'E':
356         return 0xe;
357
358     case 'f': case 'F':
359         return 0xf;
360     }
361
362     NOT_REACHED();
363 }
364
365 /* Returns the current working directory as a malloc()'d string, or a null
366  * pointer if the current working directory cannot be determined. */
367 char *
368 get_cwd(void)
369 {
370     long int path_max;
371     size_t size;
372
373     /* Get maximum path length or at least a reasonable estimate. */
374     path_max = pathconf(".", _PC_PATH_MAX);
375     size = (path_max < 0 ? 1024
376             : path_max > 10240 ? 10240
377             : path_max);
378
379     /* Get current working directory. */
380     for (;;) {
381         char *buf = xmalloc(size);
382         if (getcwd(buf, size)) {
383             return xrealloc(buf, strlen(buf) + 1);
384         } else {
385             int error = errno;
386             free(buf);
387             if (error != ERANGE) {
388                 VLOG_WARN("getcwd failed (%s)", strerror(error));
389                 return NULL;
390             }
391             size *= 2;
392         }
393     }
394 }
395
396 /* Returns the directory name portion of 'file_name' as a malloc()'d string,
397  * similar to the POSIX dirname() function but thread-safe. */
398 char *
399 dir_name(const char *file_name)
400 {
401     size_t len = strlen(file_name);
402     while (len > 0 && file_name[len - 1] == '/') {
403         len--;
404     }
405     while (len > 0 && file_name[len - 1] != '/') {
406         len--;
407     }
408     while (len > 0 && file_name[len - 1] == '/') {
409         len--;
410     }
411     if (!len) {
412         return xstrdup((file_name[0] == '/'
413                         && file_name[1] == '/'
414                         && file_name[2] != '/') ? "//"
415                        : file_name[0] == '/' ? "/"
416                        : ".");
417     } else {
418         return xmemdup0(file_name, len);
419     }
420 }
421
422 /* If 'file_name' starts with '/', returns a copy of 'file_name'.  Otherwise,
423  * returns an absolute path to 'file_name' considering it relative to 'dir',
424  * which itself must be absolute.  'dir' may be null or the empty string, in
425  * which case the current working directory is used.
426  *
427  * Returns a null pointer if 'dir' is null and getcwd() fails. */
428 char *
429 abs_file_name(const char *dir, const char *file_name)
430 {
431     if (file_name[0] == '/') {
432         return xstrdup(file_name);
433     } else if (dir && dir[0]) {
434         char *separator = dir[strlen(dir) - 1] == '/' ? "" : "/";
435         return xasprintf("%s%s%s", dir, separator, file_name);
436     } else {
437         char *cwd = get_cwd();
438         if (cwd) {
439             char *abs_name = xasprintf("%s/%s", cwd, file_name);
440             free(cwd);
441             return abs_name;
442         } else {
443             return NULL;
444         }
445     }
446 }
447
448
449 /* Pass a value to this function if it is marked with
450  * __attribute__((warn_unused_result)) and you genuinely want to ignore 
451  * its return value.  (Note that every scalar type can be implicitly 
452  * converted to bool.) */
453 void ignore(bool x OVS_UNUSED) { }