Add new function xzalloc(n) as a shorthand for xcalloc(1, n).
[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 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)", strerror(err_no));
173     putc('\n', stderr);
174
175     errno = save_errno;
176 }
177
178 /* Sets program_name based on 'argv0'.  Should be called at the beginning of
179  * main(), as "set_program_name(argv[0]);".  */
180 void set_program_name(const char *argv0)
181 {
182     const char *slash = strrchr(argv0, '/');
183     program_name = slash ? slash + 1 : argv0;
184 }
185
186 /* Print the version information for the program.  */
187 void
188 ovs_print_version(char *date, char *time, 
189                   uint8_t min_ofp, uint8_t max_ofp)
190 {
191     printf("%s (Open vSwitch) "VERSION BUILDNR"\n", program_name);
192     printf("Compiled %s %s\n", date, time);
193     if (min_ofp || max_ofp) {
194         printf("OpenFlow versions %#x:%#x\n", min_ofp, max_ofp);
195     }
196 }
197
198 /* Writes the 'size' bytes in 'buf' to 'stream' as hex bytes arranged 16 per
199  * line.  Numeric offsets are also included, starting at 'ofs' for the first
200  * byte in 'buf'.  If 'ascii' is true then the corresponding ASCII characters
201  * are also rendered alongside. */
202 void
203 ovs_hex_dump(FILE *stream, const void *buf_, size_t size,
204              uintptr_t ofs, bool ascii)
205 {
206   const uint8_t *buf = buf_;
207   const size_t per_line = 16; /* Maximum bytes per line. */
208
209   while (size > 0)
210     {
211       size_t start, end, n;
212       size_t i;
213
214       /* Number of bytes on this line. */
215       start = ofs % per_line;
216       end = per_line;
217       if (end - start > size)
218         end = start + size;
219       n = end - start;
220
221       /* Print line. */
222       fprintf(stream, "%08jx  ", (uintmax_t) ROUND_DOWN(ofs, per_line));
223       for (i = 0; i < start; i++)
224         fprintf(stream, "   ");
225       for (; i < end; i++)
226         fprintf(stream, "%02hhx%c",
227                 buf[i - start], i == per_line / 2 - 1? '-' : ' ');
228       if (ascii)
229         {
230           for (; i < per_line; i++)
231             fprintf(stream, "   ");
232           fprintf(stream, "|");
233           for (i = 0; i < start; i++)
234             fprintf(stream, " ");
235           for (; i < end; i++) {
236               int c = buf[i - start];
237               putc(c >= 32 && c < 127 ? c : '.', stream);
238           }
239           for (; i < per_line; i++)
240             fprintf(stream, " ");
241           fprintf(stream, "|");
242         }
243       fprintf(stream, "\n");
244
245       ofs += n;
246       buf += n;
247       size -= n;
248     }
249 }
250
251 bool
252 str_to_int(const char *s, int base, int *i)
253 {
254     long long ll;
255     bool ok = str_to_llong(s, base, &ll);
256     *i = ll;
257     return ok;
258 }
259
260 bool
261 str_to_long(const char *s, int base, long *li)
262 {
263     long long ll;
264     bool ok = str_to_llong(s, base, &ll);
265     *li = ll;
266     return ok;
267 }
268
269 bool
270 str_to_llong(const char *s, int base, long long *x)
271 {
272     int save_errno = errno;
273     char *tail;
274     errno = 0;
275     *x = strtoll(s, &tail, base);
276     if (errno == EINVAL || errno == ERANGE || tail == s || *tail != '\0') {
277         errno = save_errno;
278         *x = 0;
279         return false;
280     } else {
281         errno = save_errno;
282         return true;
283     }
284 }
285
286 bool
287 str_to_uint(const char *s, int base, unsigned int *u)
288 {
289     return str_to_int(s, base, (int *) u);
290 }
291
292 bool
293 str_to_ulong(const char *s, int base, unsigned long *ul)
294 {
295     return str_to_long(s, base, (long *) ul);
296 }
297
298 bool
299 str_to_ullong(const char *s, int base, unsigned long long *ull)
300 {
301     return str_to_llong(s, base, (long long *) ull);
302 }