1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "qemu/osdep.h"
25#include "qemu-common.h"
26#include "qemu/host-utils.h"
27#include <math.h>
28
29#include "qemu/sockets.h"
30#include "qemu/iov.h"
31#include "net/net.h"
32#include "qemu/cutils.h"
33
34void strpadcpy(char *buf, int buf_size, const char *str, char pad)
35{
36 int len = qemu_strnlen(str, buf_size);
37 memcpy(buf, str, len);
38 memset(buf + len, pad, buf_size - len);
39}
40
41void pstrcpy(char *buf, int buf_size, const char *str)
42{
43 int c;
44 char *q = buf;
45
46 if (buf_size <= 0)
47 return;
48
49 for(;;) {
50 c = *str++;
51 if (c == 0 || q >= buf + buf_size - 1)
52 break;
53 *q++ = c;
54 }
55 *q = '\0';
56}
57
58
59char *pstrcat(char *buf, int buf_size, const char *s)
60{
61 int len;
62 len = strlen(buf);
63 if (len < buf_size)
64 pstrcpy(buf + len, buf_size - len, s);
65 return buf;
66}
67
68int strstart(const char *str, const char *val, const char **ptr)
69{
70 const char *p, *q;
71 p = str;
72 q = val;
73 while (*q != '\0') {
74 if (*p != *q)
75 return 0;
76 p++;
77 q++;
78 }
79 if (ptr)
80 *ptr = p;
81 return 1;
82}
83
84int stristart(const char *str, const char *val, const char **ptr)
85{
86 const char *p, *q;
87 p = str;
88 q = val;
89 while (*q != '\0') {
90 if (qemu_toupper(*p) != qemu_toupper(*q))
91 return 0;
92 p++;
93 q++;
94 }
95 if (ptr)
96 *ptr = p;
97 return 1;
98}
99
100
101int qemu_strnlen(const char *s, int max_len)
102{
103 int i;
104
105 for(i = 0; i < max_len; i++) {
106 if (s[i] == '\0') {
107 break;
108 }
109 }
110 return i;
111}
112
113char *qemu_strsep(char **input, const char *delim)
114{
115 char *result = *input;
116 if (result != NULL) {
117 char *p;
118
119 for (p = result; *p != '\0'; p++) {
120 if (strchr(delim, *p)) {
121 break;
122 }
123 }
124 if (*p == '\0') {
125 *input = NULL;
126 } else {
127 *p = '\0';
128 *input = p + 1;
129 }
130 }
131 return result;
132}
133
134time_t mktimegm(struct tm *tm)
135{
136 time_t t;
137 int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
138 if (m < 3) {
139 m += 12;
140 y--;
141 }
142 t = 86400ULL * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 +
143 y / 400 - 719469);
144 t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
145 return t;
146}
147
148
149
150
151
152
153
154
155int qemu_fdatasync(int fd)
156{
157#ifdef CONFIG_FDATASYNC
158 return fdatasync(fd);
159#else
160 return fsync(fd);
161#endif
162}
163
164#ifndef _WIN32
165
166int fcntl_setfl(int fd, int flag)
167{
168 int flags;
169
170 flags = fcntl(fd, F_GETFL);
171 if (flags == -1)
172 return -errno;
173
174 if (fcntl(fd, F_SETFL, flags | flag) == -1)
175 return -errno;
176
177 return 0;
178}
179#endif
180
181static int64_t suffix_mul(char suffix, int64_t unit)
182{
183 switch (qemu_toupper(suffix)) {
184 case 'B':
185 return 1;
186 case 'K':
187 return unit;
188 case 'M':
189 return unit * unit;
190 case 'G':
191 return unit * unit * unit;
192 case 'T':
193 return unit * unit * unit * unit;
194 case 'P':
195 return unit * unit * unit * unit * unit;
196 case 'E':
197 return unit * unit * unit * unit * unit * unit;
198 }
199 return -1;
200}
201
202
203
204
205
206
207
208static int do_strtosz(const char *nptr, char **end,
209 const char default_suffix, int64_t unit,
210 uint64_t *result)
211{
212 int retval;
213 char *endptr;
214 unsigned char c;
215 int mul_required = 0;
216 double val, mul, integral, fraction;
217
218 errno = 0;
219 val = strtod(nptr, &endptr);
220 if (isnan(val) || endptr == nptr || errno != 0) {
221 retval = -EINVAL;
222 goto out;
223 }
224 fraction = modf(val, &integral);
225 if (fraction != 0) {
226 mul_required = 1;
227 }
228 c = *endptr;
229 mul = suffix_mul(c, unit);
230 if (mul >= 0) {
231 endptr++;
232 } else {
233 mul = suffix_mul(default_suffix, unit);
234 assert(mul >= 0);
235 }
236 if (mul == 1 && mul_required) {
237 retval = -EINVAL;
238 goto out;
239 }
240
241
242
243
244 if ((val * mul >= 0xfffffffffffffc00) || val < 0) {
245 retval = -ERANGE;
246 goto out;
247 }
248 *result = val * mul;
249 retval = 0;
250
251out:
252 if (end) {
253 *end = endptr;
254 } else if (*endptr) {
255 retval = -EINVAL;
256 }
257
258 return retval;
259}
260
261int qemu_strtosz(const char *nptr, char **end, uint64_t *result)
262{
263 return do_strtosz(nptr, end, 'B', 1024, result);
264}
265
266int qemu_strtosz_MiB(const char *nptr, char **end, uint64_t *result)
267{
268 return do_strtosz(nptr, end, 'M', 1024, result);
269}
270
271int qemu_strtosz_metric(const char *nptr, char **end, uint64_t *result)
272{
273 return do_strtosz(nptr, end, 'B', 1000, result);
274}
275
276
277
278
279static int check_strtox_error(const char *nptr, char *ep,
280 const char **endptr, int libc_errno)
281{
282 if (endptr) {
283 *endptr = ep;
284 }
285
286
287 if (libc_errno == 0 && ep == nptr) {
288 return -EINVAL;
289 }
290
291
292 if (!endptr && *ep) {
293 return -EINVAL;
294 }
295
296 return -libc_errno;
297}
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323int qemu_strtol(const char *nptr, const char **endptr, int base,
324 long *result)
325{
326 char *ep;
327
328 if (!nptr) {
329 if (endptr) {
330 *endptr = nptr;
331 }
332 return -EINVAL;
333 }
334
335 errno = 0;
336 *result = strtol(nptr, &ep, base);
337 return check_strtox_error(nptr, ep, endptr, errno);
338}
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365int qemu_strtoul(const char *nptr, const char **endptr, int base,
366 unsigned long *result)
367{
368 char *ep;
369
370 if (!nptr) {
371 if (endptr) {
372 *endptr = nptr;
373 }
374 return -EINVAL;
375 }
376
377 errno = 0;
378 *result = strtoul(nptr, &ep, base);
379
380 if (errno == ERANGE) {
381 *result = -1;
382 }
383 return check_strtox_error(nptr, ep, endptr, errno);
384}
385
386
387
388
389
390
391
392int qemu_strtoi64(const char *nptr, const char **endptr, int base,
393 int64_t *result)
394{
395 char *ep;
396
397 if (!nptr) {
398 if (endptr) {
399 *endptr = nptr;
400 }
401 return -EINVAL;
402 }
403
404 errno = 0;
405
406 *result = strtoll(nptr, &ep, base);
407 return check_strtox_error(nptr, ep, endptr, errno);
408}
409
410
411
412
413
414
415int qemu_strtou64(const char *nptr, const char **endptr, int base,
416 uint64_t *result)
417{
418 char *ep;
419
420 if (!nptr) {
421 if (endptr) {
422 *endptr = nptr;
423 }
424 return -EINVAL;
425 }
426
427 errno = 0;
428
429 *result = strtoull(nptr, &ep, base);
430
431 if (errno == ERANGE) {
432 *result = -1;
433 }
434 return check_strtox_error(nptr, ep, endptr, errno);
435}
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465int parse_uint(const char *s, unsigned long long *value, char **endptr,
466 int base)
467{
468 int r = 0;
469 char *endp = (char *)s;
470 unsigned long long val = 0;
471
472 if (!s) {
473 r = -EINVAL;
474 goto out;
475 }
476
477 errno = 0;
478 val = strtoull(s, &endp, base);
479 if (errno) {
480 r = -errno;
481 goto out;
482 }
483
484 if (endp == s) {
485 r = -EINVAL;
486 goto out;
487 }
488
489
490 while (isspace((unsigned char)*s)) {
491 s++;
492 }
493 if (*s == '-') {
494 val = 0;
495 r = -ERANGE;
496 goto out;
497 }
498
499out:
500 *value = val;
501 *endptr = endp;
502 return r;
503}
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519int parse_uint_full(const char *s, unsigned long long *value, int base)
520{
521 char *endp;
522 int r;
523
524 r = parse_uint(s, value, &endp, base);
525 if (r < 0) {
526 return r;
527 }
528 if (*endp) {
529 *value = 0;
530 return -EINVAL;
531 }
532
533 return 0;
534}
535
536int qemu_parse_fd(const char *param)
537{
538 long fd;
539 char *endptr;
540
541 errno = 0;
542 fd = strtol(param, &endptr, 10);
543 if (param == endptr ||
544 errno != 0 ||
545 *endptr != '\0' ||
546 fd < 0 ||
547 fd > INT_MAX ) {
548 return -1;
549 }
550 return fd;
551}
552
553
554
555
556
557int uleb128_encode_small(uint8_t *out, uint32_t n)
558{
559 g_assert(n <= 0x3fff);
560 if (n < 0x80) {
561 *out++ = n;
562 return 1;
563 } else {
564 *out++ = (n & 0x7f) | 0x80;
565 *out++ = n >> 7;
566 return 2;
567 }
568}
569
570int uleb128_decode_small(const uint8_t *in, uint32_t *n)
571{
572 if (!(*in & 0x80)) {
573 *n = *in++;
574 return 1;
575 } else {
576 *n = *in++ & 0x7f;
577
578 if (*in & 0x80) {
579 return -1;
580 }
581 *n |= *in++ << 7;
582 return 2;
583 }
584}
585
586
587
588
589int parse_debug_env(const char *name, int max, int initial)
590{
591 char *debug_env = getenv(name);
592 char *inv = NULL;
593 long debug;
594
595 if (!debug_env) {
596 return initial;
597 }
598 errno = 0;
599 debug = strtol(debug_env, &inv, 10);
600 if (inv == debug_env) {
601 return initial;
602 }
603 if (debug < 0 || debug > max || errno != 0) {
604 fprintf(stderr, "warning: %s not in [0, %d]", name, max);
605 return initial;
606 }
607 return debug;
608}
609
610
611
612
613const char *qemu_ether_ntoa(const MACAddr *mac)
614{
615 static char ret[18];
616
617 snprintf(ret, sizeof(ret), "%02x:%02x:%02x:%02x:%02x:%02x",
618 mac->a[0], mac->a[1], mac->a[2], mac->a[3], mac->a[4], mac->a[5]);
619
620 return ret;
621}
622
623
624
625
626
627
628
629char *size_to_str(uint64_t val)
630{
631 static const char *suffixes[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" };
632 unsigned long div;
633 int i;
634
635
636
637
638
639
640
641 frexp(val / (1000.0 / 1024.0), &i);
642 i = (i - 1) / 10;
643 div = 1ULL << (i * 10);
644
645 return g_strdup_printf("%0.3g %sB", (double)val / div, suffixes[i]);
646}
647