1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "qemu/osdep.h"
26#include "qemu/host-utils.h"
27#include <math.h>
28
29#ifdef __FreeBSD__
30#include <sys/sysctl.h>
31#include <sys/user.h>
32#endif
33
34#ifdef __NetBSD__
35#include <sys/sysctl.h>
36#endif
37
38#ifdef __HAIKU__
39#include <kernel/image.h>
40#endif
41
42#ifdef __APPLE__
43#include <mach-o/dyld.h>
44#endif
45
46#ifdef G_OS_WIN32
47#include <pathcch.h>
48#include <wchar.h>
49#endif
50
51#include "qemu/ctype.h"
52#include "qemu/cutils.h"
53#include "qemu/error-report.h"
54
55void strpadcpy(char *buf, int buf_size, const char *str, char pad)
56{
57 int len = qemu_strnlen(str, buf_size);
58 memcpy(buf, str, len);
59 memset(buf + len, pad, buf_size - len);
60}
61
62void pstrcpy(char *buf, int buf_size, const char *str)
63{
64 int c;
65 char *q = buf;
66
67 if (buf_size <= 0)
68 return;
69
70 for(;;) {
71 c = *str++;
72 if (c == 0 || q >= buf + buf_size - 1)
73 break;
74 *q++ = c;
75 }
76 *q = '\0';
77}
78
79
80char *pstrcat(char *buf, int buf_size, const char *s)
81{
82 int len;
83 len = strlen(buf);
84 if (len < buf_size)
85 pstrcpy(buf + len, buf_size - len, s);
86 return buf;
87}
88
89int strstart(const char *str, const char *val, const char **ptr)
90{
91 const char *p, *q;
92 p = str;
93 q = val;
94 while (*q != '\0') {
95 if (*p != *q)
96 return 0;
97 p++;
98 q++;
99 }
100 if (ptr)
101 *ptr = p;
102 return 1;
103}
104
105int stristart(const char *str, const char *val, const char **ptr)
106{
107 const char *p, *q;
108 p = str;
109 q = val;
110 while (*q != '\0') {
111 if (qemu_toupper(*p) != qemu_toupper(*q))
112 return 0;
113 p++;
114 q++;
115 }
116 if (ptr)
117 *ptr = p;
118 return 1;
119}
120
121
122int qemu_strnlen(const char *s, int max_len)
123{
124 int i;
125
126 for(i = 0; i < max_len; i++) {
127 if (s[i] == '\0') {
128 break;
129 }
130 }
131 return i;
132}
133
134char *qemu_strsep(char **input, const char *delim)
135{
136 char *result = *input;
137 if (result != NULL) {
138 char *p;
139
140 for (p = result; *p != '\0'; p++) {
141 if (strchr(delim, *p)) {
142 break;
143 }
144 }
145 if (*p == '\0') {
146 *input = NULL;
147 } else {
148 *p = '\0';
149 *input = p + 1;
150 }
151 }
152 return result;
153}
154
155time_t mktimegm(struct tm *tm)
156{
157 time_t t;
158 int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
159 if (m < 3) {
160 m += 12;
161 y--;
162 }
163 t = 86400ULL * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 +
164 y / 400 - 719469);
165 t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
166 return t;
167}
168
169static int64_t suffix_mul(char suffix, int64_t unit)
170{
171 switch (qemu_toupper(suffix)) {
172 case 'B':
173 return 1;
174 case 'K':
175 return unit;
176 case 'M':
177 return unit * unit;
178 case 'G':
179 return unit * unit * unit;
180 case 'T':
181 return unit * unit * unit * unit;
182 case 'P':
183 return unit * unit * unit * unit * unit;
184 case 'E':
185 return unit * unit * unit * unit * unit * unit;
186 }
187 return -1;
188}
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216static int do_strtosz(const char *nptr, const char **end,
217 const char default_suffix, int64_t unit,
218 uint64_t *result)
219{
220 int retval;
221 const char *endptr, *f;
222 unsigned char c;
223 uint64_t val, valf = 0;
224 int64_t mul;
225
226
227 retval = qemu_strtou64(nptr, &endptr, 10, &val);
228 if (retval) {
229 goto out;
230 }
231 if (memchr(nptr, '-', endptr - nptr) != NULL) {
232 endptr = nptr;
233 retval = -EINVAL;
234 goto out;
235 }
236 if (val == 0 && (*endptr == 'x' || *endptr == 'X')) {
237
238 retval = qemu_strtou64(nptr, &endptr, 16, &val);
239 if (retval) {
240 goto out;
241 }
242 if (*endptr == '.' || suffix_mul(*endptr, unit) > 0) {
243 endptr = nptr;
244 retval = -EINVAL;
245 goto out;
246 }
247 } else if (*endptr == '.') {
248
249
250
251
252
253 double fraction;
254
255 f = endptr;
256 retval = qemu_strtod_finite(f, &endptr, &fraction);
257 if (retval) {
258 endptr++;
259 } else if (memchr(f, 'e', endptr - f) || memchr(f, 'E', endptr - f)) {
260 endptr = nptr;
261 retval = -EINVAL;
262 goto out;
263 } else {
264
265 valf = (uint64_t)(fraction * 0x1p64);
266 }
267 }
268 c = *endptr;
269 mul = suffix_mul(c, unit);
270 if (mul > 0) {
271 endptr++;
272 } else {
273 mul = suffix_mul(default_suffix, unit);
274 assert(mul > 0);
275 }
276 if (mul == 1) {
277
278 if (valf != 0) {
279 endptr = nptr;
280 retval = -EINVAL;
281 goto out;
282 }
283 } else {
284 uint64_t valh, tmp;
285
286
287 mulu64(&val, &valh, val, mul);
288 mulu64(&valf, &tmp, valf, mul);
289 val += tmp;
290 valh += val < tmp;
291
292
293 tmp = valf >> 63;
294 val += tmp;
295 valh += val < tmp;
296
297
298 if (valh != 0) {
299 retval = -ERANGE;
300 goto out;
301 }
302 }
303
304 retval = 0;
305
306out:
307 if (end) {
308 *end = endptr;
309 } else if (*endptr) {
310 retval = -EINVAL;
311 }
312 if (retval == 0) {
313 *result = val;
314 }
315
316 return retval;
317}
318
319int qemu_strtosz(const char *nptr, const char **end, uint64_t *result)
320{
321 return do_strtosz(nptr, end, 'B', 1024, result);
322}
323
324int qemu_strtosz_MiB(const char *nptr, const char **end, uint64_t *result)
325{
326 return do_strtosz(nptr, end, 'M', 1024, result);
327}
328
329int qemu_strtosz_metric(const char *nptr, const char **end, uint64_t *result)
330{
331 return do_strtosz(nptr, end, 'B', 1000, result);
332}
333
334
335
336
337static int check_strtox_error(const char *nptr, char *ep,
338 const char **endptr, bool check_zero,
339 int libc_errno)
340{
341 assert(ep >= nptr);
342
343
344 if (check_zero && ep == nptr && libc_errno == 0) {
345 char *tmp;
346
347 errno = 0;
348 if (strtol(nptr, &tmp, 10) == 0 && errno == 0 &&
349 (*tmp == 'x' || *tmp == 'X')) {
350 ep = tmp;
351 }
352 }
353
354 if (endptr) {
355 *endptr = ep;
356 }
357
358
359 if (libc_errno == 0 && ep == nptr) {
360 return -EINVAL;
361 }
362
363
364 if (!endptr && *ep) {
365 return -EINVAL;
366 }
367
368 return -libc_errno;
369}
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395int qemu_strtoi(const char *nptr, const char **endptr, int base,
396 int *result)
397{
398 char *ep;
399 long long lresult;
400
401 assert((unsigned) base <= 36 && base != 1);
402 if (!nptr) {
403 if (endptr) {
404 *endptr = nptr;
405 }
406 return -EINVAL;
407 }
408
409 errno = 0;
410 lresult = strtoll(nptr, &ep, base);
411 if (lresult < INT_MIN) {
412 *result = INT_MIN;
413 errno = ERANGE;
414 } else if (lresult > INT_MAX) {
415 *result = INT_MAX;
416 errno = ERANGE;
417 } else {
418 *result = lresult;
419 }
420 return check_strtox_error(nptr, ep, endptr, lresult == 0, errno);
421}
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448int qemu_strtoui(const char *nptr, const char **endptr, int base,
449 unsigned int *result)
450{
451 char *ep;
452 long long lresult;
453
454 assert((unsigned) base <= 36 && base != 1);
455 if (!nptr) {
456 if (endptr) {
457 *endptr = nptr;
458 }
459 return -EINVAL;
460 }
461
462 errno = 0;
463 lresult = strtoull(nptr, &ep, base);
464
465
466 if (errno == ERANGE) {
467 *result = -1;
468 } else {
469 if (lresult > UINT_MAX) {
470 *result = UINT_MAX;
471 errno = ERANGE;
472 } else if (lresult < INT_MIN) {
473 *result = UINT_MAX;
474 errno = ERANGE;
475 } else {
476 *result = lresult;
477 }
478 }
479 return check_strtox_error(nptr, ep, endptr, lresult == 0, errno);
480}
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506int qemu_strtol(const char *nptr, const char **endptr, int base,
507 long *result)
508{
509 char *ep;
510
511 assert((unsigned) base <= 36 && base != 1);
512 if (!nptr) {
513 if (endptr) {
514 *endptr = nptr;
515 }
516 return -EINVAL;
517 }
518
519 errno = 0;
520 *result = strtol(nptr, &ep, base);
521 return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
522}
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549int qemu_strtoul(const char *nptr, const char **endptr, int base,
550 unsigned long *result)
551{
552 char *ep;
553
554 assert((unsigned) base <= 36 && base != 1);
555 if (!nptr) {
556 if (endptr) {
557 *endptr = nptr;
558 }
559 return -EINVAL;
560 }
561
562 errno = 0;
563 *result = strtoul(nptr, &ep, base);
564
565 if (errno == ERANGE) {
566 *result = -1;
567 }
568 return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
569}
570
571
572
573
574
575
576
577int qemu_strtoi64(const char *nptr, const char **endptr, int base,
578 int64_t *result)
579{
580 char *ep;
581
582 assert((unsigned) base <= 36 && base != 1);
583 if (!nptr) {
584 if (endptr) {
585 *endptr = nptr;
586 }
587 return -EINVAL;
588 }
589
590
591 QEMU_BUILD_BUG_ON(sizeof(int64_t) != sizeof(long long));
592 errno = 0;
593 *result = strtoll(nptr, &ep, base);
594 return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
595}
596
597
598
599
600
601
602int qemu_strtou64(const char *nptr, const char **endptr, int base,
603 uint64_t *result)
604{
605 char *ep;
606
607 assert((unsigned) base <= 36 && base != 1);
608 if (!nptr) {
609 if (endptr) {
610 *endptr = nptr;
611 }
612 return -EINVAL;
613 }
614
615
616 QEMU_BUILD_BUG_ON(sizeof(uint64_t) != sizeof(unsigned long long));
617 errno = 0;
618 *result = strtoull(nptr, &ep, base);
619
620 if (errno == ERANGE) {
621 *result = -1;
622 }
623 return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
624}
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650int qemu_strtod(const char *nptr, const char **endptr, double *result)
651{
652 char *ep;
653
654 if (!nptr) {
655 if (endptr) {
656 *endptr = nptr;
657 }
658 return -EINVAL;
659 }
660
661 errno = 0;
662 *result = strtod(nptr, &ep);
663 return check_strtox_error(nptr, ep, endptr, false, errno);
664}
665
666
667
668
669
670
671
672int qemu_strtod_finite(const char *nptr, const char **endptr, double *result)
673{
674 double tmp;
675 int ret;
676
677 ret = qemu_strtod(nptr, endptr, &tmp);
678 if (!ret && !isfinite(tmp)) {
679 if (endptr) {
680 *endptr = nptr;
681 }
682 ret = -EINVAL;
683 }
684
685 if (ret != -EINVAL) {
686 *result = tmp;
687 }
688 return ret;
689}
690
691
692
693
694
695#ifndef HAVE_STRCHRNUL
696const char *qemu_strchrnul(const char *s, int c)
697{
698 const char *e = strchr(s, c);
699 if (!e) {
700 e = s + strlen(s);
701 }
702 return e;
703}
704#endif
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734int parse_uint(const char *s, unsigned long long *value, char **endptr,
735 int base)
736{
737 int r = 0;
738 char *endp = (char *)s;
739 unsigned long long val = 0;
740
741 assert((unsigned) base <= 36 && base != 1);
742 if (!s) {
743 r = -EINVAL;
744 goto out;
745 }
746
747 errno = 0;
748 val = strtoull(s, &endp, base);
749 if (errno) {
750 r = -errno;
751 goto out;
752 }
753
754 if (endp == s) {
755 r = -EINVAL;
756 goto out;
757 }
758
759
760 while (qemu_isspace(*s)) {
761 s++;
762 }
763 if (*s == '-') {
764 val = 0;
765 r = -ERANGE;
766 goto out;
767 }
768
769out:
770 *value = val;
771 *endptr = endp;
772 return r;
773}
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789int parse_uint_full(const char *s, unsigned long long *value, int base)
790{
791 char *endp;
792 int r;
793
794 r = parse_uint(s, value, &endp, base);
795 if (r < 0) {
796 return r;
797 }
798 if (*endp) {
799 *value = 0;
800 return -EINVAL;
801 }
802
803 return 0;
804}
805
806int qemu_parse_fd(const char *param)
807{
808 long fd;
809 char *endptr;
810
811 errno = 0;
812 fd = strtol(param, &endptr, 10);
813 if (param == endptr ||
814 errno != 0 ||
815 *endptr != '\0' ||
816 fd < 0 ||
817 fd > INT_MAX ) {
818 return -1;
819 }
820 return fd;
821}
822
823
824
825
826
827int uleb128_encode_small(uint8_t *out, uint32_t n)
828{
829 g_assert(n <= 0x3fff);
830 if (n < 0x80) {
831 *out = n;
832 return 1;
833 } else {
834 *out++ = (n & 0x7f) | 0x80;
835 *out = n >> 7;
836 return 2;
837 }
838}
839
840int uleb128_decode_small(const uint8_t *in, uint32_t *n)
841{
842 if (!(*in & 0x80)) {
843 *n = *in;
844 return 1;
845 } else {
846 *n = *in++ & 0x7f;
847
848 if (*in & 0x80) {
849 return -1;
850 }
851 *n |= *in << 7;
852 return 2;
853 }
854}
855
856
857
858
859int parse_debug_env(const char *name, int max, int initial)
860{
861 char *debug_env = getenv(name);
862 char *inv = NULL;
863 long debug;
864
865 if (!debug_env) {
866 return initial;
867 }
868 errno = 0;
869 debug = strtol(debug_env, &inv, 10);
870 if (inv == debug_env) {
871 return initial;
872 }
873 if (debug < 0 || debug > max || errno != 0) {
874 warn_report("%s not in [0, %d]", name, max);
875 return initial;
876 }
877 return debug;
878}
879
880const char *si_prefix(unsigned int exp10)
881{
882 static const char *prefixes[] = {
883 "a", "f", "p", "n", "u", "m", "", "K", "M", "G", "T", "P", "E"
884 };
885
886 exp10 += 18;
887 assert(exp10 % 3 == 0 && exp10 / 3 < ARRAY_SIZE(prefixes));
888 return prefixes[exp10 / 3];
889}
890
891const char *iec_binary_prefix(unsigned int exp2)
892{
893 static const char *prefixes[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" };
894
895 assert(exp2 % 10 == 0 && exp2 / 10 < ARRAY_SIZE(prefixes));
896 return prefixes[exp2 / 10];
897}
898
899
900
901
902
903
904
905char *size_to_str(uint64_t val)
906{
907 uint64_t div;
908 int i;
909
910
911
912
913
914
915
916 frexp(val / (1000.0 / 1024.0), &i);
917 i = (i - 1) / 10 * 10;
918 div = 1ULL << i;
919
920 return g_strdup_printf("%0.3g %sB", (double)val / div, iec_binary_prefix(i));
921}
922
923char *freq_to_str(uint64_t freq_hz)
924{
925 double freq = freq_hz;
926 size_t exp10 = 0;
927
928 while (freq >= 1000.0) {
929 freq /= 1000.0;
930 exp10 += 3;
931 }
932
933 return g_strdup_printf("%0.3g %sHz", freq, si_prefix(exp10));
934}
935
936int qemu_pstrcmp0(const char **str1, const char **str2)
937{
938 return g_strcmp0(*str1, *str2);
939}
940
941static inline bool starts_with_prefix(const char *dir)
942{
943 size_t prefix_len = strlen(CONFIG_PREFIX);
944 return !memcmp(dir, CONFIG_PREFIX, prefix_len) &&
945 (!dir[prefix_len] || G_IS_DIR_SEPARATOR(dir[prefix_len]));
946}
947
948
949static inline const char *next_component(const char *dir, int *p_len)
950{
951 int len;
952 while ((*dir && G_IS_DIR_SEPARATOR(*dir)) ||
953 (*dir == '.' && (G_IS_DIR_SEPARATOR(dir[1]) || dir[1] == '\0'))) {
954 dir++;
955 }
956 len = 0;
957 while (dir[len] && !G_IS_DIR_SEPARATOR(dir[len])) {
958 len++;
959 }
960 *p_len = len;
961 return dir;
962}
963
964static const char *exec_dir;
965
966void qemu_init_exec_dir(const char *argv0)
967{
968#ifdef G_OS_WIN32
969 char *p;
970 char buf[MAX_PATH];
971 DWORD len;
972
973 if (exec_dir) {
974 return;
975 }
976
977 len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
978 if (len == 0) {
979 return;
980 }
981
982 buf[len] = 0;
983 p = buf + len - 1;
984 while (p != buf && *p != '\\') {
985 p--;
986 }
987 *p = 0;
988 if (access(buf, R_OK) == 0) {
989 exec_dir = g_strdup(buf);
990 } else {
991 exec_dir = CONFIG_BINDIR;
992 }
993#else
994 char *p = NULL;
995 char buf[PATH_MAX];
996
997 if (exec_dir) {
998 return;
999 }
1000
1001#if defined(__linux__)
1002 {
1003 int len;
1004 len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
1005 if (len > 0) {
1006 buf[len] = 0;
1007 p = buf;
1008 }
1009 }
1010#elif defined(__FreeBSD__) \
1011 || (defined(__NetBSD__) && defined(KERN_PROC_PATHNAME))
1012 {
1013#if defined(__FreeBSD__)
1014 static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
1015#else
1016 static int mib[4] = {CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME};
1017#endif
1018 size_t len = sizeof(buf) - 1;
1019
1020 *buf = '\0';
1021 if (!sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) &&
1022 *buf) {
1023 buf[sizeof(buf) - 1] = '\0';
1024 p = buf;
1025 }
1026 }
1027#elif defined(__APPLE__)
1028 {
1029 char fpath[PATH_MAX];
1030 uint32_t len = sizeof(fpath);
1031 if (_NSGetExecutablePath(fpath, &len) == 0) {
1032 p = realpath(fpath, buf);
1033 if (!p) {
1034 return;
1035 }
1036 }
1037 }
1038#elif defined(__HAIKU__)
1039 {
1040 image_info ii;
1041 int32_t c = 0;
1042
1043 *buf = '\0';
1044 while (get_next_image_info(0, &c, &ii) == B_OK) {
1045 if (ii.type == B_APP_IMAGE) {
1046 strncpy(buf, ii.name, sizeof(buf));
1047 buf[sizeof(buf) - 1] = 0;
1048 p = buf;
1049 break;
1050 }
1051 }
1052 }
1053#endif
1054
1055
1056 if (!p && argv0) {
1057 p = realpath(argv0, buf);
1058 }
1059 if (p) {
1060 exec_dir = g_path_get_dirname(p);
1061 } else {
1062 exec_dir = CONFIG_BINDIR;
1063 }
1064#endif
1065}
1066
1067const char *qemu_get_exec_dir(void)
1068{
1069 return exec_dir;
1070}
1071
1072char *get_relocated_path(const char *dir)
1073{
1074 size_t prefix_len = strlen(CONFIG_PREFIX);
1075 const char *bindir = CONFIG_BINDIR;
1076 const char *exec_dir = qemu_get_exec_dir();
1077 GString *result;
1078 int len_dir, len_bindir;
1079
1080
1081 assert(exec_dir[0]);
1082
1083 result = g_string_new(exec_dir);
1084 g_string_append(result, "/qemu-bundle");
1085 if (access(result->str, R_OK) == 0) {
1086#ifdef G_OS_WIN32
1087 size_t size = mbsrtowcs(NULL, &dir, 0, &(mbstate_t){0}) + 1;
1088 PWSTR wdir = g_new(WCHAR, size);
1089 mbsrtowcs(wdir, &dir, size, &(mbstate_t){0});
1090
1091 PCWSTR wdir_skipped_root;
1092 PathCchSkipRoot(wdir, &wdir_skipped_root);
1093
1094 size = wcsrtombs(NULL, &wdir_skipped_root, 0, &(mbstate_t){0});
1095 char *cursor = result->str + result->len;
1096 g_string_set_size(result, result->len + size);
1097 wcsrtombs(cursor, &wdir_skipped_root, size + 1, &(mbstate_t){0});
1098 g_free(wdir);
1099#else
1100 g_string_append(result, dir);
1101#endif
1102 } else if (!starts_with_prefix(dir) || !starts_with_prefix(bindir)) {
1103 g_string_assign(result, dir);
1104 } else {
1105 g_string_assign(result, exec_dir);
1106
1107
1108 len_dir = len_bindir = prefix_len;
1109 do {
1110 dir += len_dir;
1111 bindir += len_bindir;
1112 dir = next_component(dir, &len_dir);
1113 bindir = next_component(bindir, &len_bindir);
1114 } while (len_dir && len_dir == len_bindir && !memcmp(dir, bindir, len_dir));
1115
1116
1117 while (len_bindir) {
1118 bindir += len_bindir;
1119 g_string_append(result, "/..");
1120 bindir = next_component(bindir, &len_bindir);
1121 }
1122
1123 if (*dir) {
1124 assert(G_IS_DIR_SEPARATOR(dir[-1]));
1125 g_string_append(result, dir - 1);
1126 }
1127 }
1128
1129 return g_string_free(result, false);
1130}
1131