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