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