Merge changes from citrix branch into master.
[sliver-openvswitch.git] / lib / util.c
1 /*
2  * Copyright (c) 2008, 2009 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 xmalloc(size_t size) 
47 {
48     void *p = malloc(size ? size : 1);
49     COVERAGE_INC(util_xalloc);
50     if (p == NULL) {
51         out_of_memory();
52     }
53     return p;
54 }
55
56 void *
57 xrealloc(void *p, size_t size) 
58 {
59     p = realloc(p, size ? size : 1);
60     COVERAGE_INC(util_xalloc);
61     if (p == NULL) {
62         out_of_memory();
63     }
64     return p;
65 }
66
67 void *
68 xmemdup(const void *p_, size_t size)
69 {
70     void *p = xmalloc(size);
71     memcpy(p, p_, size);
72     return p;
73 }
74
75 char *
76 xmemdup0(const char *p_, size_t length)
77 {
78     char *p = xmalloc(length + 1);
79     memcpy(p, p_, length);
80     p[length] = '\0';
81     return p;
82 }
83
84 char *
85 xstrdup(const char *s) 
86 {
87     return xmemdup0(s, strlen(s));
88 }
89
90 char *
91 xvasprintf(const char *format, va_list args)
92 {
93     va_list args2;
94     size_t needed;
95     char *s;
96
97     va_copy(args2, args);
98     needed = vsnprintf(NULL, 0, format, args);
99
100     s = xmalloc(needed + 1);
101
102     vsnprintf(s, needed + 1, format, args2);
103     va_end(args2);
104
105     return s;
106 }
107
108 void *
109 x2nrealloc(void *p, size_t *n, size_t s)
110 {
111     *n = *n == 0 ? 1 : 2 * *n;
112     return xrealloc(p, *n * s);
113 }
114
115 char *
116 xasprintf(const char *format, ...)
117 {
118     va_list args;
119     char *s;
120
121     va_start(args, format);
122     s = xvasprintf(format, args);
123     va_end(args);
124
125     return s;
126 }
127
128 void
129 ovs_strlcpy(char *dst, const char *src, size_t size)
130 {
131     if (size > 0) {
132         size_t n = strlen(src);
133         size_t n_copy = MIN(n, size - 1);
134         memcpy(dst, src, n_copy);
135         dst[n_copy] = '\0';
136     }
137 }
138
139 void
140 ovs_fatal(int err_no, const char *format, ...)
141 {
142     va_list args;
143
144     fprintf(stderr, "%s: ", program_name);
145     va_start(args, format);
146     vfprintf(stderr, format, args);
147     va_end(args);
148     if (err_no != 0)
149         fprintf(stderr, " (%s)", strerror(err_no));
150     putc('\n', stderr);
151
152     exit(EXIT_FAILURE);
153 }
154
155 void
156 ovs_error(int err_no, const char *format, ...)
157 {
158     int save_errno = errno;
159     va_list args;
160
161     fprintf(stderr, "%s: ", program_name);
162     va_start(args, format);
163     vfprintf(stderr, format, args);
164     va_end(args);
165     if (err_no != 0)
166         fprintf(stderr, " (%s)", strerror(err_no));
167     putc('\n', stderr);
168
169     errno = save_errno;
170 }
171
172 /* Sets program_name based on 'argv0'.  Should be called at the beginning of
173  * main(), as "set_program_name(argv[0]);".  */
174 void set_program_name(const char *argv0)
175 {
176     const char *slash = strrchr(argv0, '/');
177     program_name = slash ? slash + 1 : argv0;
178 }
179
180 /* Print the version information for the program.  */
181 void
182 ovs_print_version(char *date, char *time, 
183                   uint8_t min_ofp, uint8_t max_ofp)
184 {
185     printf("%s (Open vSwitch) "VERSION BUILDNR"\n", program_name);
186     printf("Compiled %s %s\n", date, time);
187     if (min_ofp || max_ofp) {
188         printf("OpenFlow versions %#x:%#x\n", min_ofp, max_ofp);
189     }
190 }
191
192 /* Writes the 'size' bytes in 'buf' to 'stream' as hex bytes arranged 16 per
193  * line.  Numeric offsets are also included, starting at 'ofs' for the first
194  * byte in 'buf'.  If 'ascii' is true then the corresponding ASCII characters
195  * are also rendered alongside. */
196 void
197 ovs_hex_dump(FILE *stream, const void *buf_, size_t size,
198              uintptr_t ofs, bool ascii)
199 {
200   const uint8_t *buf = buf_;
201   const size_t per_line = 16; /* Maximum bytes per line. */
202
203   while (size > 0)
204     {
205       size_t start, end, n;
206       size_t i;
207
208       /* Number of bytes on this line. */
209       start = ofs % per_line;
210       end = per_line;
211       if (end - start > size)
212         end = start + size;
213       n = end - start;
214
215       /* Print line. */
216       fprintf(stream, "%08jx  ", (uintmax_t) ROUND_DOWN(ofs, per_line));
217       for (i = 0; i < start; i++)
218         fprintf(stream, "   ");
219       for (; i < end; i++)
220         fprintf(stream, "%02hhx%c",
221                 buf[i - start], i == per_line / 2 - 1? '-' : ' ');
222       if (ascii)
223         {
224           for (; i < per_line; i++)
225             fprintf(stream, "   ");
226           fprintf(stream, "|");
227           for (i = 0; i < start; i++)
228             fprintf(stream, " ");
229           for (; i < end; i++) {
230               int c = buf[i - start];
231               putc(c >= 32 && c < 127 ? c : '.', stream);
232           }
233           for (; i < per_line; i++)
234             fprintf(stream, " ");
235           fprintf(stream, "|");
236         }
237       fprintf(stream, "\n");
238
239       ofs += n;
240       buf += n;
241       size -= n;
242     }
243 }
244
245 bool
246 str_to_int(const char *s, int base, int *i)
247 {
248     long long ll;
249     bool ok = str_to_llong(s, base, &ll);
250     *i = ll;
251     return ok;
252 }
253
254 bool
255 str_to_long(const char *s, int base, long *li)
256 {
257     long long ll;
258     bool ok = str_to_llong(s, base, &ll);
259     *li = ll;
260     return ok;
261 }
262
263 bool
264 str_to_llong(const char *s, int base, long long *x)
265 {
266     int save_errno = errno;
267     char *tail;
268     errno = 0;
269     *x = strtoll(s, &tail, base);
270     if (errno == EINVAL || errno == ERANGE || tail == s || *tail != '\0') {
271         errno = save_errno;
272         *x = 0;
273         return false;
274     } else {
275         errno = save_errno;
276         return true;
277     }
278 }
279
280 bool
281 str_to_uint(const char *s, int base, unsigned int *u)
282 {
283     return str_to_int(s, base, (int *) u);
284 }
285
286 bool
287 str_to_ulong(const char *s, int base, unsigned long *ul)
288 {
289     return str_to_long(s, base, (long *) ul);
290 }
291
292 bool
293 str_to_ullong(const char *s, int base, unsigned long long *ull)
294 {
295     return str_to_llong(s, base, (long long *) ull);
296 }