ofproto: Implement Nicira Extended Match flexible flow match (NXM).
[sliver-openvswitch.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 <unistd.h>
25 #include "coverage.h"
26 #include "vlog.h"
27
28 VLOG_DEFINE_THIS_MODULE(util);
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)",
160                 err_no == EOF ? "end of file" : strerror(err_no));
161     putc('\n', stderr);
162
163     exit(EXIT_FAILURE);
164 }
165
166 void
167 ovs_error(int err_no, const char *format, ...)
168 {
169     int save_errno = errno;
170     va_list args;
171
172     fprintf(stderr, "%s: ", program_name);
173     va_start(args, format);
174     vfprintf(stderr, format, args);
175     va_end(args);
176     if (err_no != 0) {
177         fprintf(stderr, " (%s)",
178                 err_no == EOF ? "end of file" : strerror(err_no));
179     }
180     putc('\n', stderr);
181
182     errno = save_errno;
183 }
184
185 /* Sets program_name based on 'argv0'.  Should be called at the beginning of
186  * main(), as "set_program_name(argv[0]);".  */
187 void set_program_name(const char *argv0)
188 {
189     const char *slash = strrchr(argv0, '/');
190     program_name = slash ? slash + 1 : argv0;
191 }
192
193 /* Print the version information for the program.  */
194 void
195 ovs_print_version(char *date, char *time,
196                   uint8_t min_ofp, uint8_t max_ofp)
197 {
198     printf("%s (Open vSwitch) "VERSION BUILDNR"\n", program_name);
199     printf("Compiled %s %s\n", date, time);
200     if (min_ofp || max_ofp) {
201         printf("OpenFlow versions %#x:%#x\n", min_ofp, max_ofp);
202     }
203 }
204
205 /* Writes the 'size' bytes in 'buf' to 'stream' as hex bytes arranged 16 per
206  * line.  Numeric offsets are also included, starting at 'ofs' for the first
207  * byte in 'buf'.  If 'ascii' is true then the corresponding ASCII characters
208  * are also rendered alongside. */
209 void
210 ovs_hex_dump(FILE *stream, const void *buf_, size_t size,
211              uintptr_t ofs, bool ascii)
212 {
213   const uint8_t *buf = buf_;
214   const size_t per_line = 16; /* Maximum bytes per line. */
215
216   while (size > 0)
217     {
218       size_t start, end, n;
219       size_t i;
220
221       /* Number of bytes on this line. */
222       start = ofs % per_line;
223       end = per_line;
224       if (end - start > size)
225         end = start + size;
226       n = end - start;
227
228       /* Print line. */
229       fprintf(stream, "%08jx  ", (uintmax_t) ROUND_DOWN(ofs, per_line));
230       for (i = 0; i < start; i++)
231         fprintf(stream, "   ");
232       for (; i < end; i++)
233         fprintf(stream, "%02hhx%c",
234                 buf[i - start], i == per_line / 2 - 1? '-' : ' ');
235       if (ascii)
236         {
237           for (; i < per_line; i++)
238             fprintf(stream, "   ");
239           fprintf(stream, "|");
240           for (i = 0; i < start; i++)
241             fprintf(stream, " ");
242           for (; i < end; i++) {
243               int c = buf[i - start];
244               putc(c >= 32 && c < 127 ? c : '.', stream);
245           }
246           for (; i < per_line; i++)
247             fprintf(stream, " ");
248           fprintf(stream, "|");
249         }
250       fprintf(stream, "\n");
251
252       ofs += n;
253       buf += n;
254       size -= n;
255     }
256 }
257
258 bool
259 str_to_int(const char *s, int base, int *i)
260 {
261     long long ll;
262     bool ok = str_to_llong(s, base, &ll);
263     *i = ll;
264     return ok;
265 }
266
267 bool
268 str_to_long(const char *s, int base, long *li)
269 {
270     long long ll;
271     bool ok = str_to_llong(s, base, &ll);
272     *li = ll;
273     return ok;
274 }
275
276 bool
277 str_to_llong(const char *s, int base, long long *x)
278 {
279     int save_errno = errno;
280     char *tail;
281     errno = 0;
282     *x = strtoll(s, &tail, base);
283     if (errno == EINVAL || errno == ERANGE || tail == s || *tail != '\0') {
284         errno = save_errno;
285         *x = 0;
286         return false;
287     } else {
288         errno = save_errno;
289         return true;
290     }
291 }
292
293 bool
294 str_to_uint(const char *s, int base, unsigned int *u)
295 {
296     return str_to_int(s, base, (int *) u);
297 }
298
299 bool
300 str_to_ulong(const char *s, int base, unsigned long *ul)
301 {
302     return str_to_long(s, base, (long *) ul);
303 }
304
305 bool
306 str_to_ullong(const char *s, int base, unsigned long long *ull)
307 {
308     return str_to_llong(s, base, (long long *) ull);
309 }
310
311 /* Converts floating-point string 's' into a double.  If successful, stores
312  * the double in '*d' and returns true; on failure, stores 0 in '*d' and
313  * returns false.
314  *
315  * Underflow (e.g. "1e-9999") is not considered an error, but overflow
316  * (e.g. "1e9999)" is. */
317 bool
318 str_to_double(const char *s, double *d)
319 {
320     int save_errno = errno;
321     char *tail;
322     errno = 0;
323     *d = strtod(s, &tail);
324     if (errno == EINVAL || (errno == ERANGE && *d != 0)
325         || tail == s || *tail != '\0') {
326         errno = save_errno;
327         *d = 0;
328         return false;
329     } else {
330         errno = save_errno;
331         return true;
332     }
333 }
334
335 /* Returns the value of 'c' as a hexadecimal digit. */
336 int
337 hexit_value(int c)
338 {
339     switch (c) {
340     case '0': case '1': case '2': case '3': case '4':
341     case '5': case '6': case '7': case '8': case '9':
342         return c - '0';
343
344     case 'a': case 'A':
345         return 0xa;
346
347     case 'b': case 'B':
348         return 0xb;
349
350     case 'c': case 'C':
351         return 0xc;
352
353     case 'd': case 'D':
354         return 0xd;
355
356     case 'e': case 'E':
357         return 0xe;
358
359     case 'f': case 'F':
360         return 0xf;
361
362     default:
363         return -1;
364     }
365 }
366
367 /* Returns the current working directory as a malloc()'d string, or a null
368  * pointer if the current working directory cannot be determined. */
369 char *
370 get_cwd(void)
371 {
372     long int path_max;
373     size_t size;
374
375     /* Get maximum path length or at least a reasonable estimate. */
376     path_max = pathconf(".", _PC_PATH_MAX);
377     size = (path_max < 0 ? 1024
378             : path_max > 10240 ? 10240
379             : path_max);
380
381     /* Get current working directory. */
382     for (;;) {
383         char *buf = xmalloc(size);
384         if (getcwd(buf, size)) {
385             return xrealloc(buf, strlen(buf) + 1);
386         } else {
387             int error = errno;
388             free(buf);
389             if (error != ERANGE) {
390                 VLOG_WARN("getcwd failed (%s)", strerror(error));
391                 return NULL;
392             }
393             size *= 2;
394         }
395     }
396 }
397
398 /* Returns the directory name portion of 'file_name' as a malloc()'d string,
399  * similar to the POSIX dirname() function but thread-safe. */
400 char *
401 dir_name(const char *file_name)
402 {
403     size_t len = strlen(file_name);
404     while (len > 0 && file_name[len - 1] == '/') {
405         len--;
406     }
407     while (len > 0 && file_name[len - 1] != '/') {
408         len--;
409     }
410     while (len > 0 && file_name[len - 1] == '/') {
411         len--;
412     }
413     if (!len) {
414         return xstrdup((file_name[0] == '/'
415                         && file_name[1] == '/'
416                         && file_name[2] != '/') ? "//"
417                        : file_name[0] == '/' ? "/"
418                        : ".");
419     } else {
420         return xmemdup0(file_name, len);
421     }
422 }
423
424 /* If 'file_name' starts with '/', returns a copy of 'file_name'.  Otherwise,
425  * returns an absolute path to 'file_name' considering it relative to 'dir',
426  * which itself must be absolute.  'dir' may be null or the empty string, in
427  * which case the current working directory is used.
428  *
429  * Returns a null pointer if 'dir' is null and getcwd() fails. */
430 char *
431 abs_file_name(const char *dir, const char *file_name)
432 {
433     if (file_name[0] == '/') {
434         return xstrdup(file_name);
435     } else if (dir && dir[0]) {
436         char *separator = dir[strlen(dir) - 1] == '/' ? "" : "/";
437         return xasprintf("%s%s%s", dir, separator, file_name);
438     } else {
439         char *cwd = get_cwd();
440         if (cwd) {
441             char *abs_name = xasprintf("%s/%s", cwd, file_name);
442             free(cwd);
443             return abs_name;
444         } else {
445             return NULL;
446         }
447     }
448 }
449
450
451 /* Pass a value to this function if it is marked with
452  * __attribute__((warn_unused_result)) and you genuinely want to ignore
453  * its return value.  (Note that every scalar type can be implicitly
454  * converted to bool.) */
455 void ignore(bool x OVS_UNUSED) { }