xref: /qemu/util/cutils.c (revision 8b902e3d)
1baacf047SPaolo Bonzini /*
2baacf047SPaolo Bonzini  * Simple C functions to supplement the C library
3baacf047SPaolo Bonzini  *
4baacf047SPaolo Bonzini  * Copyright (c) 2006 Fabrice Bellard
5baacf047SPaolo Bonzini  *
6baacf047SPaolo Bonzini  * Permission is hereby granted, free of charge, to any person obtaining a copy
7baacf047SPaolo Bonzini  * of this software and associated documentation files (the "Software"), to deal
8baacf047SPaolo Bonzini  * in the Software without restriction, including without limitation the rights
9baacf047SPaolo Bonzini  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10baacf047SPaolo Bonzini  * copies of the Software, and to permit persons to whom the Software is
11baacf047SPaolo Bonzini  * furnished to do so, subject to the following conditions:
12baacf047SPaolo Bonzini  *
13baacf047SPaolo Bonzini  * The above copyright notice and this permission notice shall be included in
14baacf047SPaolo Bonzini  * all copies or substantial portions of the Software.
15baacf047SPaolo Bonzini  *
16baacf047SPaolo Bonzini  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17baacf047SPaolo Bonzini  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18baacf047SPaolo Bonzini  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19baacf047SPaolo Bonzini  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20baacf047SPaolo Bonzini  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21baacf047SPaolo Bonzini  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22baacf047SPaolo Bonzini  * THE SOFTWARE.
23baacf047SPaolo Bonzini  */
24856dfd8aSMarkus Armbruster 
25aafd7584SPeter Maydell #include "qemu/osdep.h"
26baacf047SPaolo Bonzini #include "qemu/host-utils.h"
27baacf047SPaolo Bonzini #include <math.h>
28baacf047SPaolo Bonzini 
2906680b15SMarc-André Lureau #ifdef __FreeBSD__
3006680b15SMarc-André Lureau #include <sys/sysctl.h>
3106680b15SMarc-André Lureau #include <sys/user.h>
3206680b15SMarc-André Lureau #endif
3306680b15SMarc-André Lureau 
3406680b15SMarc-André Lureau #ifdef __NetBSD__
3506680b15SMarc-André Lureau #include <sys/sysctl.h>
3606680b15SMarc-André Lureau #endif
3706680b15SMarc-André Lureau 
380a979a13SThomas Huth #ifdef __HAIKU__
390a979a13SThomas Huth #include <kernel/image.h>
400a979a13SThomas Huth #endif
410a979a13SThomas Huth 
424311682eSPhilippe Mathieu-Daudé #ifdef __APPLE__
434311682eSPhilippe Mathieu-Daudé #include <mach-o/dyld.h>
444311682eSPhilippe Mathieu-Daudé #endif
454311682eSPhilippe Mathieu-Daudé 
46cf60ccc3SAkihiko Odaki #ifdef G_OS_WIN32
47cf60ccc3SAkihiko Odaki #include <pathcch.h>
48cf60ccc3SAkihiko Odaki #include <wchar.h>
49cf60ccc3SAkihiko Odaki #endif
50cf60ccc3SAkihiko Odaki 
51856dfd8aSMarkus Armbruster #include "qemu/ctype.h"
52f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
5305cb8ed5SAlistair Francis #include "qemu/error-report.h"
54baacf047SPaolo Bonzini 
55baacf047SPaolo Bonzini void strpadcpy(char *buf, int buf_size, const char *str, char pad)
56baacf047SPaolo Bonzini {
57baacf047SPaolo Bonzini     int len = qemu_strnlen(str, buf_size);
58baacf047SPaolo Bonzini     memcpy(buf, str, len);
59baacf047SPaolo Bonzini     memset(buf + len, pad, buf_size - len);
60baacf047SPaolo Bonzini }
61baacf047SPaolo Bonzini 
62baacf047SPaolo Bonzini void pstrcpy(char *buf, int buf_size, const char *str)
63baacf047SPaolo Bonzini {
64baacf047SPaolo Bonzini     int c;
65baacf047SPaolo Bonzini     char *q = buf;
66baacf047SPaolo Bonzini 
67baacf047SPaolo Bonzini     if (buf_size <= 0)
68baacf047SPaolo Bonzini         return;
69baacf047SPaolo Bonzini 
70baacf047SPaolo Bonzini     for(;;) {
71baacf047SPaolo Bonzini         c = *str++;
72baacf047SPaolo Bonzini         if (c == 0 || q >= buf + buf_size - 1)
73baacf047SPaolo Bonzini             break;
74baacf047SPaolo Bonzini         *q++ = c;
75baacf047SPaolo Bonzini     }
76baacf047SPaolo Bonzini     *q = '\0';
77baacf047SPaolo Bonzini }
78baacf047SPaolo Bonzini 
79baacf047SPaolo Bonzini /* strcat and truncate. */
80baacf047SPaolo Bonzini char *pstrcat(char *buf, int buf_size, const char *s)
81baacf047SPaolo Bonzini {
82baacf047SPaolo Bonzini     int len;
83baacf047SPaolo Bonzini     len = strlen(buf);
84baacf047SPaolo Bonzini     if (len < buf_size)
85baacf047SPaolo Bonzini         pstrcpy(buf + len, buf_size - len, s);
86baacf047SPaolo Bonzini     return buf;
87baacf047SPaolo Bonzini }
88baacf047SPaolo Bonzini 
89baacf047SPaolo Bonzini int strstart(const char *str, const char *val, const char **ptr)
90baacf047SPaolo Bonzini {
91baacf047SPaolo Bonzini     const char *p, *q;
92baacf047SPaolo Bonzini     p = str;
93baacf047SPaolo Bonzini     q = val;
94baacf047SPaolo Bonzini     while (*q != '\0') {
95baacf047SPaolo Bonzini         if (*p != *q)
96baacf047SPaolo Bonzini             return 0;
97baacf047SPaolo Bonzini         p++;
98baacf047SPaolo Bonzini         q++;
99baacf047SPaolo Bonzini     }
100baacf047SPaolo Bonzini     if (ptr)
101baacf047SPaolo Bonzini         *ptr = p;
102baacf047SPaolo Bonzini     return 1;
103baacf047SPaolo Bonzini }
104baacf047SPaolo Bonzini 
105baacf047SPaolo Bonzini int stristart(const char *str, const char *val, const char **ptr)
106baacf047SPaolo Bonzini {
107baacf047SPaolo Bonzini     const char *p, *q;
108baacf047SPaolo Bonzini     p = str;
109baacf047SPaolo Bonzini     q = val;
110baacf047SPaolo Bonzini     while (*q != '\0') {
111baacf047SPaolo Bonzini         if (qemu_toupper(*p) != qemu_toupper(*q))
112baacf047SPaolo Bonzini             return 0;
113baacf047SPaolo Bonzini         p++;
114baacf047SPaolo Bonzini         q++;
115baacf047SPaolo Bonzini     }
116baacf047SPaolo Bonzini     if (ptr)
117baacf047SPaolo Bonzini         *ptr = p;
118baacf047SPaolo Bonzini     return 1;
119baacf047SPaolo Bonzini }
120baacf047SPaolo Bonzini 
121baacf047SPaolo Bonzini /* XXX: use host strnlen if available ? */
122baacf047SPaolo Bonzini int qemu_strnlen(const char *s, int max_len)
123baacf047SPaolo Bonzini {
124baacf047SPaolo Bonzini     int i;
125baacf047SPaolo Bonzini 
126baacf047SPaolo Bonzini     for(i = 0; i < max_len; i++) {
127baacf047SPaolo Bonzini         if (s[i] == '\0') {
128baacf047SPaolo Bonzini             break;
129baacf047SPaolo Bonzini         }
130baacf047SPaolo Bonzini     }
131baacf047SPaolo Bonzini     return i;
132baacf047SPaolo Bonzini }
133baacf047SPaolo Bonzini 
134a38ed811SKevin Wolf char *qemu_strsep(char **input, const char *delim)
135a38ed811SKevin Wolf {
136a38ed811SKevin Wolf     char *result = *input;
137a38ed811SKevin Wolf     if (result != NULL) {
138a38ed811SKevin Wolf         char *p;
139a38ed811SKevin Wolf 
140a38ed811SKevin Wolf         for (p = result; *p != '\0'; p++) {
141a38ed811SKevin Wolf             if (strchr(delim, *p)) {
142a38ed811SKevin Wolf                 break;
143a38ed811SKevin Wolf             }
144a38ed811SKevin Wolf         }
145a38ed811SKevin Wolf         if (*p == '\0') {
146a38ed811SKevin Wolf             *input = NULL;
147a38ed811SKevin Wolf         } else {
148a38ed811SKevin Wolf             *p = '\0';
149a38ed811SKevin Wolf             *input = p + 1;
150a38ed811SKevin Wolf         }
151a38ed811SKevin Wolf     }
152a38ed811SKevin Wolf     return result;
153a38ed811SKevin Wolf }
154a38ed811SKevin Wolf 
155baacf047SPaolo Bonzini time_t mktimegm(struct tm *tm)
156baacf047SPaolo Bonzini {
157baacf047SPaolo Bonzini     time_t t;
158baacf047SPaolo Bonzini     int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday;
159baacf047SPaolo Bonzini     if (m < 3) {
160baacf047SPaolo Bonzini         m += 12;
161baacf047SPaolo Bonzini         y--;
162baacf047SPaolo Bonzini     }
163baacf047SPaolo Bonzini     t = 86400ULL * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 +
164baacf047SPaolo Bonzini                  y / 400 - 719469);
165baacf047SPaolo Bonzini     t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec;
166baacf047SPaolo Bonzini     return t;
167baacf047SPaolo Bonzini }
168baacf047SPaolo Bonzini 
169baacf047SPaolo Bonzini static int64_t suffix_mul(char suffix, int64_t unit)
170baacf047SPaolo Bonzini {
171baacf047SPaolo Bonzini     switch (qemu_toupper(suffix)) {
17217f94256SMarkus Armbruster     case 'B':
173baacf047SPaolo Bonzini         return 1;
17417f94256SMarkus Armbruster     case 'K':
175baacf047SPaolo Bonzini         return unit;
17617f94256SMarkus Armbruster     case 'M':
177baacf047SPaolo Bonzini         return unit * unit;
17817f94256SMarkus Armbruster     case 'G':
179baacf047SPaolo Bonzini         return unit * unit * unit;
18017f94256SMarkus Armbruster     case 'T':
181baacf047SPaolo Bonzini         return unit * unit * unit * unit;
18217f94256SMarkus Armbruster     case 'P':
1835e00984aSKevin Wolf         return unit * unit * unit * unit * unit;
18417f94256SMarkus Armbruster     case 'E':
1855e00984aSKevin Wolf         return unit * unit * unit * unit * unit * unit;
186baacf047SPaolo Bonzini     }
187baacf047SPaolo Bonzini     return -1;
188baacf047SPaolo Bonzini }
189baacf047SPaolo Bonzini 
190baacf047SPaolo Bonzini /*
191cf923b78SEric Blake  * Convert size string to bytes.
192cf923b78SEric Blake  *
193cf923b78SEric Blake  * The size parsing supports the following syntaxes
194cf923b78SEric Blake  * - 12345 - decimal, scale determined by @default_suffix and @unit
195cf923b78SEric Blake  * - 12345{bBkKmMgGtTpPeE} - decimal, scale determined by suffix and @unit
196cf923b78SEric Blake  * - 12345.678{kKmMgGtTpPeE} - decimal, scale determined by suffix, and
197cf923b78SEric Blake  *   fractional portion is truncated to byte
198cf923b78SEric Blake  * - 0x7fEE - hexadecimal, unit determined by @default_suffix
199cf923b78SEric Blake  *
200cf923b78SEric Blake  * The following are intentionally not supported
2018b902e3dSPaolo Bonzini  * - hex with scaling suffix, such as 0x20M
202cf923b78SEric Blake  * - octal, such as 08
203cf923b78SEric Blake  * - fractional hex, such as 0x1.8
204cf923b78SEric Blake  * - floating point exponents, such as 1e3
205cf923b78SEric Blake  *
206cf923b78SEric Blake  * The end pointer will be returned in *end, if not NULL.  If there is
207cf923b78SEric Blake  * no fraction, the input can be decimal or hexadecimal; if there is a
208cf923b78SEric Blake  * fraction, then the input must be decimal and there must be a suffix
209cf923b78SEric Blake  * (possibly by @default_suffix) larger than Byte, and the fractional
210cf923b78SEric Blake  * portion may suffer from precision loss or rounding.  The input must
211cf923b78SEric Blake  * be positive.
212cf923b78SEric Blake  *
213cf923b78SEric Blake  * Return -ERANGE on overflow (with *@end advanced), and -EINVAL on
214cf923b78SEric Blake  * other error (with *@end left unchanged).
215baacf047SPaolo Bonzini  */
216af02f4c5SDavid Hildenbrand static int do_strtosz(const char *nptr, const char **end,
217f17fd4fdSMarkus Armbruster                       const char default_suffix, int64_t unit,
218f46bfdbfSMarkus Armbruster                       uint64_t *result)
219baacf047SPaolo Bonzini {
220f17fd4fdSMarkus Armbruster     int retval;
221cf923b78SEric Blake     const char *endptr, *f;
222baacf047SPaolo Bonzini     unsigned char c;
2237625a1edSRichard Henderson     uint64_t val, valf = 0;
224cf923b78SEric Blake     int64_t mul;
225baacf047SPaolo Bonzini 
226cf923b78SEric Blake     /* Parse integral portion as decimal. */
227cf923b78SEric Blake     retval = qemu_strtou64(nptr, &endptr, 10, &val);
228af02f4c5SDavid Hildenbrand     if (retval) {
2294fcdf65aSMarkus Armbruster         goto out;
230baacf047SPaolo Bonzini     }
231cf923b78SEric Blake     if (memchr(nptr, '-', endptr - nptr) != NULL) {
232cf923b78SEric Blake         endptr = nptr;
2334fcdf65aSMarkus Armbruster         retval = -EINVAL;
2344fcdf65aSMarkus Armbruster         goto out;
235baacf047SPaolo Bonzini     }
236cf923b78SEric Blake     if (val == 0 && (*endptr == 'x' || *endptr == 'X')) {
2378b902e3dSPaolo Bonzini         /* Input looks like hex; reparse, and insist on no fraction or suffix. */
238cf923b78SEric Blake         retval = qemu_strtou64(nptr, &endptr, 16, &val);
239cf923b78SEric Blake         if (retval) {
240cf923b78SEric Blake             goto out;
241cf923b78SEric Blake         }
2428b902e3dSPaolo Bonzini         if (*endptr == '.' || suffix_mul(*endptr, unit) > 0) {
243cf923b78SEric Blake             endptr = nptr;
244cf923b78SEric Blake             retval = -EINVAL;
245cf923b78SEric Blake             goto out;
246cf923b78SEric Blake         }
247cf923b78SEric Blake     } else if (*endptr == '.') {
248f46bfdbfSMarkus Armbruster         /*
249cf923b78SEric Blake          * Input looks like a fraction.  Make sure even 1.k works
250cf923b78SEric Blake          * without fractional digits.  If we see an exponent, treat
251cf923b78SEric Blake          * the entire input as invalid instead.
252f46bfdbfSMarkus Armbruster          */
2537625a1edSRichard Henderson         double fraction;
2547625a1edSRichard Henderson 
255cf923b78SEric Blake         f = endptr;
256cf923b78SEric Blake         retval = qemu_strtod_finite(f, &endptr, &fraction);
257cf923b78SEric Blake         if (retval) {
258cf923b78SEric Blake             endptr++;
259cf923b78SEric Blake         } else if (memchr(f, 'e', endptr - f) || memchr(f, 'E', endptr - f)) {
260cf923b78SEric Blake             endptr = nptr;
261cf923b78SEric Blake             retval = -EINVAL;
262cf923b78SEric Blake             goto out;
2637625a1edSRichard Henderson         } else {
2647625a1edSRichard Henderson             /* Extract into a 64-bit fixed-point fraction. */
2657625a1edSRichard Henderson             valf = (uint64_t)(fraction * 0x1p64);
266cf923b78SEric Blake         }
267cf923b78SEric Blake     }
268cf923b78SEric Blake     c = *endptr;
269cf923b78SEric Blake     mul = suffix_mul(c, unit);
270cf923b78SEric Blake     if (mul > 0) {
271cf923b78SEric Blake         endptr++;
272cf923b78SEric Blake     } else {
273cf923b78SEric Blake         mul = suffix_mul(default_suffix, unit);
274cf923b78SEric Blake         assert(mul > 0);
275cf923b78SEric Blake     }
2767625a1edSRichard Henderson     if (mul == 1) {
2777625a1edSRichard Henderson         /* When a fraction is present, a scale is required. */
2787625a1edSRichard Henderson         if (valf != 0) {
279cf923b78SEric Blake             endptr = nptr;
280cf923b78SEric Blake             retval = -EINVAL;
281cf923b78SEric Blake             goto out;
282cf923b78SEric Blake         }
2837625a1edSRichard Henderson     } else {
2847625a1edSRichard Henderson         uint64_t valh, tmp;
2857625a1edSRichard Henderson 
2867625a1edSRichard Henderson         /* Compute exact result: 64.64 x 64.0 -> 128.64 fixed point */
2877625a1edSRichard Henderson         mulu64(&val, &valh, val, mul);
2887625a1edSRichard Henderson         mulu64(&valf, &tmp, valf, mul);
2897625a1edSRichard Henderson         val += tmp;
2907625a1edSRichard Henderson         valh += val < tmp;
2917625a1edSRichard Henderson 
2927625a1edSRichard Henderson         /* Round 0.5 upward. */
2937625a1edSRichard Henderson         tmp = valf >> 63;
2947625a1edSRichard Henderson         val += tmp;
2957625a1edSRichard Henderson         valh += val < tmp;
2967625a1edSRichard Henderson 
2977625a1edSRichard Henderson         /* Report overflow. */
2987625a1edSRichard Henderson         if (valh != 0) {
299baacf047SPaolo Bonzini             retval = -ERANGE;
3004fcdf65aSMarkus Armbruster             goto out;
301baacf047SPaolo Bonzini         }
3027625a1edSRichard Henderson     }
3037625a1edSRichard Henderson 
304f17fd4fdSMarkus Armbruster     retval = 0;
305baacf047SPaolo Bonzini 
3064fcdf65aSMarkus Armbruster out:
307baacf047SPaolo Bonzini     if (end) {
308baacf047SPaolo Bonzini         *end = endptr;
3094fcdf65aSMarkus Armbruster     } else if (*endptr) {
3104fcdf65aSMarkus Armbruster         retval = -EINVAL;
311baacf047SPaolo Bonzini     }
312061d7909SEric Blake     if (retval == 0) {
313061d7909SEric Blake         *result = val;
314061d7909SEric Blake     }
315baacf047SPaolo Bonzini 
316baacf047SPaolo Bonzini     return retval;
317baacf047SPaolo Bonzini }
318baacf047SPaolo Bonzini 
319af02f4c5SDavid Hildenbrand int qemu_strtosz(const char *nptr, const char **end, uint64_t *result)
320baacf047SPaolo Bonzini {
321f17fd4fdSMarkus Armbruster     return do_strtosz(nptr, end, 'B', 1024, result);
322baacf047SPaolo Bonzini }
323baacf047SPaolo Bonzini 
324af02f4c5SDavid Hildenbrand int qemu_strtosz_MiB(const char *nptr, const char **end, uint64_t *result)
325baacf047SPaolo Bonzini {
326f17fd4fdSMarkus Armbruster     return do_strtosz(nptr, end, 'M', 1024, result);
327baacf047SPaolo Bonzini }
328baacf047SPaolo Bonzini 
329af02f4c5SDavid Hildenbrand int qemu_strtosz_metric(const char *nptr, const char **end, uint64_t *result)
330d2734d26SMarkus Armbruster {
331f17fd4fdSMarkus Armbruster     return do_strtosz(nptr, end, 'B', 1000, result);
332d2734d26SMarkus Armbruster }
333d2734d26SMarkus Armbruster 
334e3f9fe2dSEduardo Habkost /**
335717adf96SMarkus Armbruster  * Helper function for error checking after strtol() and the like
336764e0fa4SCarlos L. Torres  */
337717adf96SMarkus Armbruster static int check_strtox_error(const char *nptr, char *ep,
3386162f7daSEric Blake                               const char **endptr, bool check_zero,
3396162f7daSEric Blake                               int libc_errno)
340764e0fa4SCarlos L. Torres {
34153a90b97SEric Blake     assert(ep >= nptr);
3426162f7daSEric Blake 
3436162f7daSEric Blake     /* Windows has a bug in that it fails to parse 0 from "0x" in base 16 */
3446162f7daSEric Blake     if (check_zero && ep == nptr && libc_errno == 0) {
3456162f7daSEric Blake         char *tmp;
3466162f7daSEric Blake 
3476162f7daSEric Blake         errno = 0;
3486162f7daSEric Blake         if (strtol(nptr, &tmp, 10) == 0 && errno == 0 &&
3496162f7daSEric Blake             (*tmp == 'x' || *tmp == 'X')) {
3506162f7daSEric Blake             ep = tmp;
3516162f7daSEric Blake         }
3526162f7daSEric Blake     }
3536162f7daSEric Blake 
354717adf96SMarkus Armbruster     if (endptr) {
355717adf96SMarkus Armbruster         *endptr = ep;
356764e0fa4SCarlos L. Torres     }
3574baef267SMarkus Armbruster 
3584baef267SMarkus Armbruster     /* Turn "no conversion" into an error */
3594baef267SMarkus Armbruster     if (libc_errno == 0 && ep == nptr) {
3604baef267SMarkus Armbruster         return -EINVAL;
3614baef267SMarkus Armbruster     }
3624baef267SMarkus Armbruster 
3634baef267SMarkus Armbruster     /* Fail when we're expected to consume the string, but didn't */
3644baef267SMarkus Armbruster     if (!endptr && *ep) {
3654baef267SMarkus Armbruster         return -EINVAL;
3664baef267SMarkus Armbruster     }
3674baef267SMarkus Armbruster 
368717adf96SMarkus Armbruster     return -libc_errno;
369764e0fa4SCarlos L. Torres }
370764e0fa4SCarlos L. Torres 
371764e0fa4SCarlos L. Torres /**
372473a2a33SDaniel P. Berrange  * Convert string @nptr to an integer, and store it in @result.
373473a2a33SDaniel P. Berrange  *
374473a2a33SDaniel P. Berrange  * This is a wrapper around strtol() that is harder to misuse.
375473a2a33SDaniel P. Berrange  * Semantics of @nptr, @endptr, @base match strtol() with differences
376473a2a33SDaniel P. Berrange  * noted below.
377473a2a33SDaniel P. Berrange  *
378473a2a33SDaniel P. Berrange  * @nptr may be null, and no conversion is performed then.
379473a2a33SDaniel P. Berrange  *
380473a2a33SDaniel P. Berrange  * If no conversion is performed, store @nptr in *@endptr and return
381473a2a33SDaniel P. Berrange  * -EINVAL.
382473a2a33SDaniel P. Berrange  *
383473a2a33SDaniel P. Berrange  * If @endptr is null, and the string isn't fully converted, return
384473a2a33SDaniel P. Berrange  * -EINVAL.  This is the case when the pointer that would be stored in
385473a2a33SDaniel P. Berrange  * a non-null @endptr points to a character other than '\0'.
386473a2a33SDaniel P. Berrange  *
387473a2a33SDaniel P. Berrange  * If the conversion overflows @result, store INT_MAX in @result,
388473a2a33SDaniel P. Berrange  * and return -ERANGE.
389473a2a33SDaniel P. Berrange  *
390473a2a33SDaniel P. Berrange  * If the conversion underflows @result, store INT_MIN in @result,
391473a2a33SDaniel P. Berrange  * and return -ERANGE.
392473a2a33SDaniel P. Berrange  *
393473a2a33SDaniel P. Berrange  * Else store the converted value in @result, and return zero.
394473a2a33SDaniel P. Berrange  */
395473a2a33SDaniel P. Berrange int qemu_strtoi(const char *nptr, const char **endptr, int base,
396473a2a33SDaniel P. Berrange                 int *result)
397473a2a33SDaniel P. Berrange {
398473a2a33SDaniel P. Berrange     char *ep;
399473a2a33SDaniel P. Berrange     long long lresult;
400473a2a33SDaniel P. Berrange 
40153a90b97SEric Blake     assert((unsigned) base <= 36 && base != 1);
402473a2a33SDaniel P. Berrange     if (!nptr) {
403473a2a33SDaniel P. Berrange         if (endptr) {
404473a2a33SDaniel P. Berrange             *endptr = nptr;
405473a2a33SDaniel P. Berrange         }
406473a2a33SDaniel P. Berrange         return -EINVAL;
407473a2a33SDaniel P. Berrange     }
408473a2a33SDaniel P. Berrange 
409473a2a33SDaniel P. Berrange     errno = 0;
410473a2a33SDaniel P. Berrange     lresult = strtoll(nptr, &ep, base);
411473a2a33SDaniel P. Berrange     if (lresult < INT_MIN) {
412473a2a33SDaniel P. Berrange         *result = INT_MIN;
413473a2a33SDaniel P. Berrange         errno = ERANGE;
414473a2a33SDaniel P. Berrange     } else if (lresult > INT_MAX) {
415473a2a33SDaniel P. Berrange         *result = INT_MAX;
416473a2a33SDaniel P. Berrange         errno = ERANGE;
417473a2a33SDaniel P. Berrange     } else {
418473a2a33SDaniel P. Berrange         *result = lresult;
419473a2a33SDaniel P. Berrange     }
4206162f7daSEric Blake     return check_strtox_error(nptr, ep, endptr, lresult == 0, errno);
421473a2a33SDaniel P. Berrange }
422473a2a33SDaniel P. Berrange 
423473a2a33SDaniel P. Berrange /**
424473a2a33SDaniel P. Berrange  * Convert string @nptr to an unsigned integer, and store it in @result.
425473a2a33SDaniel P. Berrange  *
426473a2a33SDaniel P. Berrange  * This is a wrapper around strtoul() that is harder to misuse.
427473a2a33SDaniel P. Berrange  * Semantics of @nptr, @endptr, @base match strtoul() with differences
428473a2a33SDaniel P. Berrange  * noted below.
429473a2a33SDaniel P. Berrange  *
430473a2a33SDaniel P. Berrange  * @nptr may be null, and no conversion is performed then.
431473a2a33SDaniel P. Berrange  *
432473a2a33SDaniel P. Berrange  * If no conversion is performed, store @nptr in *@endptr and return
433473a2a33SDaniel P. Berrange  * -EINVAL.
434473a2a33SDaniel P. Berrange  *
435473a2a33SDaniel P. Berrange  * If @endptr is null, and the string isn't fully converted, return
436473a2a33SDaniel P. Berrange  * -EINVAL.  This is the case when the pointer that would be stored in
437473a2a33SDaniel P. Berrange  * a non-null @endptr points to a character other than '\0'.
438473a2a33SDaniel P. Berrange  *
439473a2a33SDaniel P. Berrange  * If the conversion overflows @result, store UINT_MAX in @result,
440473a2a33SDaniel P. Berrange  * and return -ERANGE.
441473a2a33SDaniel P. Berrange  *
442473a2a33SDaniel P. Berrange  * Else store the converted value in @result, and return zero.
443473a2a33SDaniel P. Berrange  *
444473a2a33SDaniel P. Berrange  * Note that a number with a leading minus sign gets converted without
445473a2a33SDaniel P. Berrange  * the minus sign, checked for overflow (see above), then negated (in
446473a2a33SDaniel P. Berrange  * @result's type).  This is exactly how strtoul() works.
447473a2a33SDaniel P. Berrange  */
448473a2a33SDaniel P. Berrange int qemu_strtoui(const char *nptr, const char **endptr, int base,
449473a2a33SDaniel P. Berrange                  unsigned int *result)
450473a2a33SDaniel P. Berrange {
451473a2a33SDaniel P. Berrange     char *ep;
452473a2a33SDaniel P. Berrange     long long lresult;
453473a2a33SDaniel P. Berrange 
45453a90b97SEric Blake     assert((unsigned) base <= 36 && base != 1);
455473a2a33SDaniel P. Berrange     if (!nptr) {
456473a2a33SDaniel P. Berrange         if (endptr) {
457473a2a33SDaniel P. Berrange             *endptr = nptr;
458473a2a33SDaniel P. Berrange         }
459473a2a33SDaniel P. Berrange         return -EINVAL;
460473a2a33SDaniel P. Berrange     }
461473a2a33SDaniel P. Berrange 
462473a2a33SDaniel P. Berrange     errno = 0;
463473a2a33SDaniel P. Berrange     lresult = strtoull(nptr, &ep, base);
464473a2a33SDaniel P. Berrange 
465473a2a33SDaniel P. Berrange     /* Windows returns 1 for negative out-of-range values.  */
466473a2a33SDaniel P. Berrange     if (errno == ERANGE) {
467473a2a33SDaniel P. Berrange         *result = -1;
468473a2a33SDaniel P. Berrange     } else {
469473a2a33SDaniel P. Berrange         if (lresult > UINT_MAX) {
470473a2a33SDaniel P. Berrange             *result = UINT_MAX;
471473a2a33SDaniel P. Berrange             errno = ERANGE;
472473a2a33SDaniel P. Berrange         } else if (lresult < INT_MIN) {
473473a2a33SDaniel P. Berrange             *result = UINT_MAX;
474473a2a33SDaniel P. Berrange             errno = ERANGE;
475473a2a33SDaniel P. Berrange         } else {
476473a2a33SDaniel P. Berrange             *result = lresult;
477473a2a33SDaniel P. Berrange         }
478473a2a33SDaniel P. Berrange     }
4796162f7daSEric Blake     return check_strtox_error(nptr, ep, endptr, lresult == 0, errno);
480473a2a33SDaniel P. Berrange }
481473a2a33SDaniel P. Berrange 
482473a2a33SDaniel P. Berrange /**
4834295f879SMarkus Armbruster  * Convert string @nptr to a long integer, and store it in @result.
484764e0fa4SCarlos L. Torres  *
4854295f879SMarkus Armbruster  * This is a wrapper around strtol() that is harder to misuse.
4864295f879SMarkus Armbruster  * Semantics of @nptr, @endptr, @base match strtol() with differences
4874295f879SMarkus Armbruster  * noted below.
488764e0fa4SCarlos L. Torres  *
4894295f879SMarkus Armbruster  * @nptr may be null, and no conversion is performed then.
490764e0fa4SCarlos L. Torres  *
4914295f879SMarkus Armbruster  * If no conversion is performed, store @nptr in *@endptr and return
4924295f879SMarkus Armbruster  * -EINVAL.
493764e0fa4SCarlos L. Torres  *
4944295f879SMarkus Armbruster  * If @endptr is null, and the string isn't fully converted, return
4954295f879SMarkus Armbruster  * -EINVAL.  This is the case when the pointer that would be stored in
4964295f879SMarkus Armbruster  * a non-null @endptr points to a character other than '\0'.
4974295f879SMarkus Armbruster  *
4984295f879SMarkus Armbruster  * If the conversion overflows @result, store LONG_MAX in @result,
4994295f879SMarkus Armbruster  * and return -ERANGE.
5004295f879SMarkus Armbruster  *
5014295f879SMarkus Armbruster  * If the conversion underflows @result, store LONG_MIN in @result,
5024295f879SMarkus Armbruster  * and return -ERANGE.
5034295f879SMarkus Armbruster  *
5044295f879SMarkus Armbruster  * Else store the converted value in @result, and return zero.
505764e0fa4SCarlos L. Torres  */
506764e0fa4SCarlos L. Torres int qemu_strtol(const char *nptr, const char **endptr, int base,
507764e0fa4SCarlos L. Torres                 long *result)
508764e0fa4SCarlos L. Torres {
509717adf96SMarkus Armbruster     char *ep;
5104baef267SMarkus Armbruster 
51153a90b97SEric Blake     assert((unsigned) base <= 36 && base != 1);
512764e0fa4SCarlos L. Torres     if (!nptr) {
513764e0fa4SCarlos L. Torres         if (endptr) {
514764e0fa4SCarlos L. Torres             *endptr = nptr;
515764e0fa4SCarlos L. Torres         }
5164baef267SMarkus Armbruster         return -EINVAL;
5174baef267SMarkus Armbruster     }
5184baef267SMarkus Armbruster 
519764e0fa4SCarlos L. Torres     errno = 0;
520717adf96SMarkus Armbruster     *result = strtol(nptr, &ep, base);
5216162f7daSEric Blake     return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
522764e0fa4SCarlos L. Torres }
523c817c015SCarlos L. Torres 
524c817c015SCarlos L. Torres /**
5254295f879SMarkus Armbruster  * Convert string @nptr to an unsigned long, and store it in @result.
526c817c015SCarlos L. Torres  *
5274295f879SMarkus Armbruster  * This is a wrapper around strtoul() that is harder to misuse.
5284295f879SMarkus Armbruster  * Semantics of @nptr, @endptr, @base match strtoul() with differences
5294295f879SMarkus Armbruster  * noted below.
530c817c015SCarlos L. Torres  *
5314295f879SMarkus Armbruster  * @nptr may be null, and no conversion is performed then.
532c817c015SCarlos L. Torres  *
5334295f879SMarkus Armbruster  * If no conversion is performed, store @nptr in *@endptr and return
5344295f879SMarkus Armbruster  * -EINVAL.
5354295f879SMarkus Armbruster  *
5364295f879SMarkus Armbruster  * If @endptr is null, and the string isn't fully converted, return
5374295f879SMarkus Armbruster  * -EINVAL.  This is the case when the pointer that would be stored in
5384295f879SMarkus Armbruster  * a non-null @endptr points to a character other than '\0'.
5394295f879SMarkus Armbruster  *
5404295f879SMarkus Armbruster  * If the conversion overflows @result, store ULONG_MAX in @result,
5414295f879SMarkus Armbruster  * and return -ERANGE.
5424295f879SMarkus Armbruster  *
5434295f879SMarkus Armbruster  * Else store the converted value in @result, and return zero.
5444295f879SMarkus Armbruster  *
5454295f879SMarkus Armbruster  * Note that a number with a leading minus sign gets converted without
5464295f879SMarkus Armbruster  * the minus sign, checked for overflow (see above), then negated (in
5474295f879SMarkus Armbruster  * @result's type).  This is exactly how strtoul() works.
548c817c015SCarlos L. Torres  */
549c817c015SCarlos L. Torres int qemu_strtoul(const char *nptr, const char **endptr, int base,
550c817c015SCarlos L. Torres                  unsigned long *result)
551c817c015SCarlos L. Torres {
552717adf96SMarkus Armbruster     char *ep;
5534baef267SMarkus Armbruster 
55453a90b97SEric Blake     assert((unsigned) base <= 36 && base != 1);
555c817c015SCarlos L. Torres     if (!nptr) {
556c817c015SCarlos L. Torres         if (endptr) {
557c817c015SCarlos L. Torres             *endptr = nptr;
558c817c015SCarlos L. Torres         }
5594baef267SMarkus Armbruster         return -EINVAL;
5604baef267SMarkus Armbruster     }
5614baef267SMarkus Armbruster 
562c817c015SCarlos L. Torres     errno = 0;
563717adf96SMarkus Armbruster     *result = strtoul(nptr, &ep, base);
56447d4be12SPaolo Bonzini     /* Windows returns 1 for negative out-of-range values.  */
56547d4be12SPaolo Bonzini     if (errno == ERANGE) {
56647d4be12SPaolo Bonzini         *result = -1;
56747d4be12SPaolo Bonzini     }
5686162f7daSEric Blake     return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
569c817c015SCarlos L. Torres }
570c817c015SCarlos L. Torres 
571764e0fa4SCarlos L. Torres /**
5724295f879SMarkus Armbruster  * Convert string @nptr to an int64_t.
5738ac4df40SCarlos L. Torres  *
5744295f879SMarkus Armbruster  * Works like qemu_strtol(), except it stores INT64_MAX on overflow,
575369276ebSMarkus Armbruster  * and INT64_MIN on underflow.
5768ac4df40SCarlos L. Torres  */
577b30d1886SMarkus Armbruster int qemu_strtoi64(const char *nptr, const char **endptr, int base,
5788ac4df40SCarlos L. Torres                  int64_t *result)
5798ac4df40SCarlos L. Torres {
580717adf96SMarkus Armbruster     char *ep;
5814baef267SMarkus Armbruster 
58253a90b97SEric Blake     assert((unsigned) base <= 36 && base != 1);
5838ac4df40SCarlos L. Torres     if (!nptr) {
5848ac4df40SCarlos L. Torres         if (endptr) {
5858ac4df40SCarlos L. Torres             *endptr = nptr;
5868ac4df40SCarlos L. Torres         }
5874baef267SMarkus Armbruster         return -EINVAL;
5884baef267SMarkus Armbruster     }
5894baef267SMarkus Armbruster 
590369276ebSMarkus Armbruster     /* This assumes int64_t is long long TODO relax */
591369276ebSMarkus Armbruster     QEMU_BUILD_BUG_ON(sizeof(int64_t) != sizeof(long long));
5928ac4df40SCarlos L. Torres     errno = 0;
593717adf96SMarkus Armbruster     *result = strtoll(nptr, &ep, base);
5946162f7daSEric Blake     return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
5958ac4df40SCarlos L. Torres }
5968ac4df40SCarlos L. Torres 
5978ac4df40SCarlos L. Torres /**
5984295f879SMarkus Armbruster  * Convert string @nptr to an uint64_t.
5993904e6bfSCarlos L. Torres  *
6004295f879SMarkus Armbruster  * Works like qemu_strtoul(), except it stores UINT64_MAX on overflow.
6013904e6bfSCarlos L. Torres  */
602b30d1886SMarkus Armbruster int qemu_strtou64(const char *nptr, const char **endptr, int base,
6033904e6bfSCarlos L. Torres                   uint64_t *result)
6043904e6bfSCarlos L. Torres {
605717adf96SMarkus Armbruster     char *ep;
6064baef267SMarkus Armbruster 
60753a90b97SEric Blake     assert((unsigned) base <= 36 && base != 1);
6083904e6bfSCarlos L. Torres     if (!nptr) {
6093904e6bfSCarlos L. Torres         if (endptr) {
6103904e6bfSCarlos L. Torres             *endptr = nptr;
6113904e6bfSCarlos L. Torres         }
6124baef267SMarkus Armbruster         return -EINVAL;
6134baef267SMarkus Armbruster     }
6144baef267SMarkus Armbruster 
615369276ebSMarkus Armbruster     /* This assumes uint64_t is unsigned long long TODO relax */
616369276ebSMarkus Armbruster     QEMU_BUILD_BUG_ON(sizeof(uint64_t) != sizeof(unsigned long long));
6173904e6bfSCarlos L. Torres     errno = 0;
618717adf96SMarkus Armbruster     *result = strtoull(nptr, &ep, base);
61947d4be12SPaolo Bonzini     /* Windows returns 1 for negative out-of-range values.  */
62047d4be12SPaolo Bonzini     if (errno == ERANGE) {
62147d4be12SPaolo Bonzini         *result = -1;
62247d4be12SPaolo Bonzini     }
6236162f7daSEric Blake     return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
6243904e6bfSCarlos L. Torres }
6253904e6bfSCarlos L. Torres 
6263904e6bfSCarlos L. Torres /**
627ca28f548SDavid Hildenbrand  * Convert string @nptr to a double.
628ca28f548SDavid Hildenbrand   *
629ca28f548SDavid Hildenbrand  * This is a wrapper around strtod() that is harder to misuse.
630ca28f548SDavid Hildenbrand  * Semantics of @nptr and @endptr match strtod() with differences
631ca28f548SDavid Hildenbrand  * noted below.
632ca28f548SDavid Hildenbrand  *
633ca28f548SDavid Hildenbrand  * @nptr may be null, and no conversion is performed then.
634ca28f548SDavid Hildenbrand  *
635ca28f548SDavid Hildenbrand  * If no conversion is performed, store @nptr in *@endptr and return
636ca28f548SDavid Hildenbrand  * -EINVAL.
637ca28f548SDavid Hildenbrand  *
638ca28f548SDavid Hildenbrand  * If @endptr is null, and the string isn't fully converted, return
639ca28f548SDavid Hildenbrand  * -EINVAL. This is the case when the pointer that would be stored in
640ca28f548SDavid Hildenbrand  * a non-null @endptr points to a character other than '\0'.
641ca28f548SDavid Hildenbrand  *
642ca28f548SDavid Hildenbrand  * If the conversion overflows, store +/-HUGE_VAL in @result, depending
643ca28f548SDavid Hildenbrand  * on the sign, and return -ERANGE.
644ca28f548SDavid Hildenbrand  *
645ca28f548SDavid Hildenbrand  * If the conversion underflows, store +/-0.0 in @result, depending on the
646ca28f548SDavid Hildenbrand  * sign, and return -ERANGE.
647ca28f548SDavid Hildenbrand  *
648ca28f548SDavid Hildenbrand  * Else store the converted value in @result, and return zero.
649ca28f548SDavid Hildenbrand  */
650ca28f548SDavid Hildenbrand int qemu_strtod(const char *nptr, const char **endptr, double *result)
651ca28f548SDavid Hildenbrand {
652ca28f548SDavid Hildenbrand     char *ep;
653ca28f548SDavid Hildenbrand 
654ca28f548SDavid Hildenbrand     if (!nptr) {
655ca28f548SDavid Hildenbrand         if (endptr) {
656ca28f548SDavid Hildenbrand             *endptr = nptr;
657ca28f548SDavid Hildenbrand         }
658ca28f548SDavid Hildenbrand         return -EINVAL;
659ca28f548SDavid Hildenbrand     }
660ca28f548SDavid Hildenbrand 
661ca28f548SDavid Hildenbrand     errno = 0;
662ca28f548SDavid Hildenbrand     *result = strtod(nptr, &ep);
6636162f7daSEric Blake     return check_strtox_error(nptr, ep, endptr, false, errno);
664ca28f548SDavid Hildenbrand }
665ca28f548SDavid Hildenbrand 
666ca28f548SDavid Hildenbrand /**
667ca28f548SDavid Hildenbrand  * Convert string @nptr to a finite double.
668ca28f548SDavid Hildenbrand  *
669ca28f548SDavid Hildenbrand  * Works like qemu_strtod(), except that "NaN" and "inf" are rejected
670ca28f548SDavid Hildenbrand  * with -EINVAL and no conversion is performed.
671ca28f548SDavid Hildenbrand  */
672ca28f548SDavid Hildenbrand int qemu_strtod_finite(const char *nptr, const char **endptr, double *result)
673ca28f548SDavid Hildenbrand {
674ca28f548SDavid Hildenbrand     double tmp;
675ca28f548SDavid Hildenbrand     int ret;
676ca28f548SDavid Hildenbrand 
677ca28f548SDavid Hildenbrand     ret = qemu_strtod(nptr, endptr, &tmp);
678ca28f548SDavid Hildenbrand     if (!ret && !isfinite(tmp)) {
679ca28f548SDavid Hildenbrand         if (endptr) {
680ca28f548SDavid Hildenbrand             *endptr = nptr;
681ca28f548SDavid Hildenbrand         }
682ca28f548SDavid Hildenbrand         ret = -EINVAL;
683ca28f548SDavid Hildenbrand     }
684ca28f548SDavid Hildenbrand 
685ca28f548SDavid Hildenbrand     if (ret != -EINVAL) {
686ca28f548SDavid Hildenbrand         *result = tmp;
687ca28f548SDavid Hildenbrand     }
688ca28f548SDavid Hildenbrand     return ret;
689ca28f548SDavid Hildenbrand }
690ca28f548SDavid Hildenbrand 
691ca28f548SDavid Hildenbrand /**
6925c99fa37SKeno Fischer  * Searches for the first occurrence of 'c' in 's', and returns a pointer
6935c99fa37SKeno Fischer  * to the trailing null byte if none was found.
6945c99fa37SKeno Fischer  */
6955c99fa37SKeno Fischer #ifndef HAVE_STRCHRNUL
6965c99fa37SKeno Fischer const char *qemu_strchrnul(const char *s, int c)
6975c99fa37SKeno Fischer {
6985c99fa37SKeno Fischer     const char *e = strchr(s, c);
6995c99fa37SKeno Fischer     if (!e) {
7005c99fa37SKeno Fischer         e = s + strlen(s);
7015c99fa37SKeno Fischer     }
7025c99fa37SKeno Fischer     return e;
7035c99fa37SKeno Fischer }
7045c99fa37SKeno Fischer #endif
7055c99fa37SKeno Fischer 
7065c99fa37SKeno Fischer /**
707e3f9fe2dSEduardo Habkost  * parse_uint:
708e3f9fe2dSEduardo Habkost  *
709e3f9fe2dSEduardo Habkost  * @s: String to parse
710e3f9fe2dSEduardo Habkost  * @value: Destination for parsed integer value
711e3f9fe2dSEduardo Habkost  * @endptr: Destination for pointer to first character not consumed
712e3f9fe2dSEduardo Habkost  * @base: integer base, between 2 and 36 inclusive, or 0
713e3f9fe2dSEduardo Habkost  *
714e3f9fe2dSEduardo Habkost  * Parse unsigned integer
715e3f9fe2dSEduardo Habkost  *
716e3f9fe2dSEduardo Habkost  * Parsed syntax is like strtoull()'s: arbitrary whitespace, a single optional
717e3f9fe2dSEduardo Habkost  * '+' or '-', an optional "0x" if @base is 0 or 16, one or more digits.
718e3f9fe2dSEduardo Habkost  *
719e3f9fe2dSEduardo Habkost  * If @s is null, or @base is invalid, or @s doesn't start with an
720e3f9fe2dSEduardo Habkost  * integer in the syntax above, set *@value to 0, *@endptr to @s, and
721e3f9fe2dSEduardo Habkost  * return -EINVAL.
722e3f9fe2dSEduardo Habkost  *
723e3f9fe2dSEduardo Habkost  * Set *@endptr to point right beyond the parsed integer (even if the integer
724e3f9fe2dSEduardo Habkost  * overflows or is negative, all digits will be parsed and *@endptr will
725e3f9fe2dSEduardo Habkost  * point right beyond them).
726e3f9fe2dSEduardo Habkost  *
727e3f9fe2dSEduardo Habkost  * If the integer is negative, set *@value to 0, and return -ERANGE.
728e3f9fe2dSEduardo Habkost  *
729e3f9fe2dSEduardo Habkost  * If the integer overflows unsigned long long, set *@value to
730e3f9fe2dSEduardo Habkost  * ULLONG_MAX, and return -ERANGE.
731e3f9fe2dSEduardo Habkost  *
732e3f9fe2dSEduardo Habkost  * Else, set *@value to the parsed integer, and return 0.
733e3f9fe2dSEduardo Habkost  */
734e3f9fe2dSEduardo Habkost int parse_uint(const char *s, unsigned long long *value, char **endptr,
735e3f9fe2dSEduardo Habkost                int base)
736e3f9fe2dSEduardo Habkost {
737e3f9fe2dSEduardo Habkost     int r = 0;
738e3f9fe2dSEduardo Habkost     char *endp = (char *)s;
739e3f9fe2dSEduardo Habkost     unsigned long long val = 0;
740e3f9fe2dSEduardo Habkost 
74153a90b97SEric Blake     assert((unsigned) base <= 36 && base != 1);
742e3f9fe2dSEduardo Habkost     if (!s) {
743e3f9fe2dSEduardo Habkost         r = -EINVAL;
744e3f9fe2dSEduardo Habkost         goto out;
745e3f9fe2dSEduardo Habkost     }
746e3f9fe2dSEduardo Habkost 
747e3f9fe2dSEduardo Habkost     errno = 0;
748e3f9fe2dSEduardo Habkost     val = strtoull(s, &endp, base);
749e3f9fe2dSEduardo Habkost     if (errno) {
750e3f9fe2dSEduardo Habkost         r = -errno;
751e3f9fe2dSEduardo Habkost         goto out;
752e3f9fe2dSEduardo Habkost     }
753e3f9fe2dSEduardo Habkost 
754e3f9fe2dSEduardo Habkost     if (endp == s) {
755e3f9fe2dSEduardo Habkost         r = -EINVAL;
756e3f9fe2dSEduardo Habkost         goto out;
757e3f9fe2dSEduardo Habkost     }
758e3f9fe2dSEduardo Habkost 
759e3f9fe2dSEduardo Habkost     /* make sure we reject negative numbers: */
760db3d11eeSMarkus Armbruster     while (qemu_isspace(*s)) {
761e3f9fe2dSEduardo Habkost         s++;
762e3f9fe2dSEduardo Habkost     }
763e3f9fe2dSEduardo Habkost     if (*s == '-') {
764e3f9fe2dSEduardo Habkost         val = 0;
765e3f9fe2dSEduardo Habkost         r = -ERANGE;
766e3f9fe2dSEduardo Habkost         goto out;
767e3f9fe2dSEduardo Habkost     }
768e3f9fe2dSEduardo Habkost 
769e3f9fe2dSEduardo Habkost out:
770e3f9fe2dSEduardo Habkost     *value = val;
771e3f9fe2dSEduardo Habkost     *endptr = endp;
772e3f9fe2dSEduardo Habkost     return r;
773e3f9fe2dSEduardo Habkost }
774e3f9fe2dSEduardo Habkost 
775e3f9fe2dSEduardo Habkost /**
776e3f9fe2dSEduardo Habkost  * parse_uint_full:
777e3f9fe2dSEduardo Habkost  *
778e3f9fe2dSEduardo Habkost  * @s: String to parse
779e3f9fe2dSEduardo Habkost  * @value: Destination for parsed integer value
780e3f9fe2dSEduardo Habkost  * @base: integer base, between 2 and 36 inclusive, or 0
781e3f9fe2dSEduardo Habkost  *
782e3f9fe2dSEduardo Habkost  * Parse unsigned integer from entire string
783e3f9fe2dSEduardo Habkost  *
784e3f9fe2dSEduardo Habkost  * Have the same behavior of parse_uint(), but with an additional check
785e3f9fe2dSEduardo Habkost  * for additional data after the parsed number. If extra characters are present
786e3f9fe2dSEduardo Habkost  * after the parsed number, the function will return -EINVAL, and *@v will
787e3f9fe2dSEduardo Habkost  * be set to 0.
788e3f9fe2dSEduardo Habkost  */
789e3f9fe2dSEduardo Habkost int parse_uint_full(const char *s, unsigned long long *value, int base)
790e3f9fe2dSEduardo Habkost {
791e3f9fe2dSEduardo Habkost     char *endp;
792e3f9fe2dSEduardo Habkost     int r;
793e3f9fe2dSEduardo Habkost 
794e3f9fe2dSEduardo Habkost     r = parse_uint(s, value, &endp, base);
795e3f9fe2dSEduardo Habkost     if (r < 0) {
796e3f9fe2dSEduardo Habkost         return r;
797e3f9fe2dSEduardo Habkost     }
798e3f9fe2dSEduardo Habkost     if (*endp) {
799e3f9fe2dSEduardo Habkost         *value = 0;
800e3f9fe2dSEduardo Habkost         return -EINVAL;
801e3f9fe2dSEduardo Habkost     }
802e3f9fe2dSEduardo Habkost 
803e3f9fe2dSEduardo Habkost     return 0;
804e3f9fe2dSEduardo Habkost }
805e3f9fe2dSEduardo Habkost 
806baacf047SPaolo Bonzini int qemu_parse_fd(const char *param)
807baacf047SPaolo Bonzini {
808e9c5c1f4SLaszlo Ersek     long fd;
809e9c5c1f4SLaszlo Ersek     char *endptr;
810baacf047SPaolo Bonzini 
811e9c5c1f4SLaszlo Ersek     errno = 0;
812baacf047SPaolo Bonzini     fd = strtol(param, &endptr, 10);
813e9c5c1f4SLaszlo Ersek     if (param == endptr /* no conversion performed */                    ||
814e9c5c1f4SLaszlo Ersek         errno != 0      /* not representable as long; possibly others */ ||
815e9c5c1f4SLaszlo Ersek         *endptr != '\0' /* final string not empty */                     ||
816e9c5c1f4SLaszlo Ersek         fd < 0          /* invalid as file descriptor */                 ||
817e9c5c1f4SLaszlo Ersek         fd > INT_MAX    /* not representable as int */) {
818baacf047SPaolo Bonzini         return -1;
819baacf047SPaolo Bonzini     }
820baacf047SPaolo Bonzini     return fd;
821baacf047SPaolo Bonzini }
822baacf047SPaolo Bonzini 
823baacf047SPaolo Bonzini /*
824baacf047SPaolo Bonzini  * Implementation of  ULEB128 (http://en.wikipedia.org/wiki/LEB128)
825baacf047SPaolo Bonzini  * Input is limited to 14-bit numbers
826baacf047SPaolo Bonzini  */
827baacf047SPaolo Bonzini int uleb128_encode_small(uint8_t *out, uint32_t n)
828baacf047SPaolo Bonzini {
829baacf047SPaolo Bonzini     g_assert(n <= 0x3fff);
830baacf047SPaolo Bonzini     if (n < 0x80) {
8317c960d61SWei Yang         *out = n;
832baacf047SPaolo Bonzini         return 1;
833baacf047SPaolo Bonzini     } else {
834baacf047SPaolo Bonzini         *out++ = (n & 0x7f) | 0x80;
8357c960d61SWei Yang         *out = n >> 7;
836baacf047SPaolo Bonzini         return 2;
837baacf047SPaolo Bonzini     }
838baacf047SPaolo Bonzini }
839baacf047SPaolo Bonzini 
840baacf047SPaolo Bonzini int uleb128_decode_small(const uint8_t *in, uint32_t *n)
841baacf047SPaolo Bonzini {
842baacf047SPaolo Bonzini     if (!(*in & 0x80)) {
8437c960d61SWei Yang         *n = *in;
844baacf047SPaolo Bonzini         return 1;
845baacf047SPaolo Bonzini     } else {
846baacf047SPaolo Bonzini         *n = *in++ & 0x7f;
847baacf047SPaolo Bonzini         /* we exceed 14 bit number */
848baacf047SPaolo Bonzini         if (*in & 0x80) {
849baacf047SPaolo Bonzini             return -1;
850baacf047SPaolo Bonzini         }
8517c960d61SWei Yang         *n |= *in << 7;
852baacf047SPaolo Bonzini         return 2;
853baacf047SPaolo Bonzini     }
854baacf047SPaolo Bonzini }
855b16352acSAlon Levy 
856b16352acSAlon Levy /*
857b16352acSAlon Levy  * helper to parse debug environment variables
858b16352acSAlon Levy  */
859b16352acSAlon Levy int parse_debug_env(const char *name, int max, int initial)
860b16352acSAlon Levy {
861b16352acSAlon Levy     char *debug_env = getenv(name);
862b16352acSAlon Levy     char *inv = NULL;
863cc5d0e04SPaolo Bonzini     long debug;
864b16352acSAlon Levy 
865b16352acSAlon Levy     if (!debug_env) {
866b16352acSAlon Levy         return initial;
867b16352acSAlon Levy     }
868cc5d0e04SPaolo Bonzini     errno = 0;
869b16352acSAlon Levy     debug = strtol(debug_env, &inv, 10);
870b16352acSAlon Levy     if (inv == debug_env) {
871b16352acSAlon Levy         return initial;
872b16352acSAlon Levy     }
873cc5d0e04SPaolo Bonzini     if (debug < 0 || debug > max || errno != 0) {
87405cb8ed5SAlistair Francis         warn_report("%s not in [0, %d]", name, max);
875b16352acSAlon Levy         return initial;
876b16352acSAlon Levy     }
877b16352acSAlon Levy     return debug;
878b16352acSAlon Levy }
8794297c8eeSAlexey Kardashevskiy 
880cfb34489SPaolo Bonzini const char *si_prefix(unsigned int exp10)
881cfb34489SPaolo Bonzini {
882cfb34489SPaolo Bonzini     static const char *prefixes[] = {
883cfb34489SPaolo Bonzini         "a", "f", "p", "n", "u", "m", "", "K", "M", "G", "T", "P", "E"
884cfb34489SPaolo Bonzini     };
885cfb34489SPaolo Bonzini 
886cfb34489SPaolo Bonzini     exp10 += 18;
887cfb34489SPaolo Bonzini     assert(exp10 % 3 == 0 && exp10 / 3 < ARRAY_SIZE(prefixes));
888cfb34489SPaolo Bonzini     return prefixes[exp10 / 3];
889cfb34489SPaolo Bonzini }
890cfb34489SPaolo Bonzini 
891cfb34489SPaolo Bonzini const char *iec_binary_prefix(unsigned int exp2)
892cfb34489SPaolo Bonzini {
893cfb34489SPaolo Bonzini     static const char *prefixes[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" };
894cfb34489SPaolo Bonzini 
895cfb34489SPaolo Bonzini     assert(exp2 % 10 == 0 && exp2 / 10 < ARRAY_SIZE(prefixes));
896cfb34489SPaolo Bonzini     return prefixes[exp2 / 10];
897cfb34489SPaolo Bonzini }
898cfb34489SPaolo Bonzini 
8994297c8eeSAlexey Kardashevskiy /*
90022951aaaSPeter Xu  * Return human readable string for size @val.
90122951aaaSPeter Xu  * @val can be anything that uint64_t allows (no more than "16 EiB").
90222951aaaSPeter Xu  * Use IEC binary units like KiB, MiB, and so forth.
90322951aaaSPeter Xu  * Caller is responsible for passing it to g_free().
90422951aaaSPeter Xu  */
90522951aaaSPeter Xu char *size_to_str(uint64_t val)
90622951aaaSPeter Xu {
907754da867SEric Blake     uint64_t div;
90822951aaaSPeter Xu     int i;
90922951aaaSPeter Xu 
91022951aaaSPeter Xu     /*
91122951aaaSPeter Xu      * The exponent (returned in i) minus one gives us
91222951aaaSPeter Xu      * floor(log2(val * 1024 / 1000).  The correction makes us
91322951aaaSPeter Xu      * switch to the higher power when the integer part is >= 1000.
91422951aaaSPeter Xu      * (see e41b509d68afb1f for more info)
91522951aaaSPeter Xu      */
91622951aaaSPeter Xu     frexp(val / (1000.0 / 1024.0), &i);
917cfb34489SPaolo Bonzini     i = (i - 1) / 10 * 10;
918cfb34489SPaolo Bonzini     div = 1ULL << i;
91922951aaaSPeter Xu 
920cfb34489SPaolo Bonzini     return g_strdup_printf("%0.3g %sB", (double)val / div, iec_binary_prefix(i));
92122951aaaSPeter Xu }
92285e33a28SMarc-André Lureau 
923709616c7SPhilippe Mathieu-Daudé char *freq_to_str(uint64_t freq_hz)
924709616c7SPhilippe Mathieu-Daudé {
925709616c7SPhilippe Mathieu-Daudé     double freq = freq_hz;
926cfb34489SPaolo Bonzini     size_t exp10 = 0;
927709616c7SPhilippe Mathieu-Daudé 
9286d7ccc57SPhilippe Mathieu-Daudé     while (freq >= 1000.0) {
929709616c7SPhilippe Mathieu-Daudé         freq /= 1000.0;
930cfb34489SPaolo Bonzini         exp10 += 3;
931709616c7SPhilippe Mathieu-Daudé     }
932709616c7SPhilippe Mathieu-Daudé 
933cfb34489SPaolo Bonzini     return g_strdup_printf("%0.3g %sHz", freq, si_prefix(exp10));
934709616c7SPhilippe Mathieu-Daudé }
935709616c7SPhilippe Mathieu-Daudé 
93685e33a28SMarc-André Lureau int qemu_pstrcmp0(const char **str1, const char **str2)
93785e33a28SMarc-André Lureau {
93885e33a28SMarc-André Lureau     return g_strcmp0(*str1, *str2);
93985e33a28SMarc-André Lureau }
940f4f5ed2cSPaolo Bonzini 
941f4f5ed2cSPaolo Bonzini static inline bool starts_with_prefix(const char *dir)
942f4f5ed2cSPaolo Bonzini {
943f4f5ed2cSPaolo Bonzini     size_t prefix_len = strlen(CONFIG_PREFIX);
944f4f5ed2cSPaolo Bonzini     return !memcmp(dir, CONFIG_PREFIX, prefix_len) &&
945f4f5ed2cSPaolo Bonzini         (!dir[prefix_len] || G_IS_DIR_SEPARATOR(dir[prefix_len]));
946f4f5ed2cSPaolo Bonzini }
947f4f5ed2cSPaolo Bonzini 
948f4f5ed2cSPaolo Bonzini /* Return the next path component in dir, and store its length in *p_len.  */
949f4f5ed2cSPaolo Bonzini static inline const char *next_component(const char *dir, int *p_len)
950f4f5ed2cSPaolo Bonzini {
951f4f5ed2cSPaolo Bonzini     int len;
952342e3a4fSStefan Weil     while ((*dir && G_IS_DIR_SEPARATOR(*dir)) ||
953342e3a4fSStefan Weil            (*dir == '.' && (G_IS_DIR_SEPARATOR(dir[1]) || dir[1] == '\0'))) {
954f4f5ed2cSPaolo Bonzini         dir++;
955f4f5ed2cSPaolo Bonzini     }
956f4f5ed2cSPaolo Bonzini     len = 0;
957f4f5ed2cSPaolo Bonzini     while (dir[len] && !G_IS_DIR_SEPARATOR(dir[len])) {
958f4f5ed2cSPaolo Bonzini         len++;
959f4f5ed2cSPaolo Bonzini     }
960f4f5ed2cSPaolo Bonzini     *p_len = len;
961f4f5ed2cSPaolo Bonzini     return dir;
962f4f5ed2cSPaolo Bonzini }
963f4f5ed2cSPaolo Bonzini 
96406680b15SMarc-André Lureau static const char *exec_dir;
96506680b15SMarc-André Lureau 
96606680b15SMarc-André Lureau void qemu_init_exec_dir(const char *argv0)
96706680b15SMarc-André Lureau {
96806680b15SMarc-André Lureau #ifdef G_OS_WIN32
96906680b15SMarc-André Lureau     char *p;
97006680b15SMarc-André Lureau     char buf[MAX_PATH];
97106680b15SMarc-André Lureau     DWORD len;
97206680b15SMarc-André Lureau 
97306680b15SMarc-André Lureau     if (exec_dir) {
97406680b15SMarc-André Lureau         return;
97506680b15SMarc-André Lureau     }
97606680b15SMarc-André Lureau 
97706680b15SMarc-André Lureau     len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
97806680b15SMarc-André Lureau     if (len == 0) {
97906680b15SMarc-André Lureau         return;
98006680b15SMarc-André Lureau     }
98106680b15SMarc-André Lureau 
98206680b15SMarc-André Lureau     buf[len] = 0;
98306680b15SMarc-André Lureau     p = buf + len - 1;
98406680b15SMarc-André Lureau     while (p != buf && *p != '\\') {
98506680b15SMarc-André Lureau         p--;
98606680b15SMarc-André Lureau     }
98706680b15SMarc-André Lureau     *p = 0;
98806680b15SMarc-André Lureau     if (access(buf, R_OK) == 0) {
98906680b15SMarc-André Lureau         exec_dir = g_strdup(buf);
99006680b15SMarc-André Lureau     } else {
99106680b15SMarc-André Lureau         exec_dir = CONFIG_BINDIR;
99206680b15SMarc-André Lureau     }
99306680b15SMarc-André Lureau #else
99406680b15SMarc-André Lureau     char *p = NULL;
99506680b15SMarc-André Lureau     char buf[PATH_MAX];
99606680b15SMarc-André Lureau 
99706680b15SMarc-André Lureau     if (exec_dir) {
99806680b15SMarc-André Lureau         return;
99906680b15SMarc-André Lureau     }
100006680b15SMarc-André Lureau 
100106680b15SMarc-André Lureau #if defined(__linux__)
100206680b15SMarc-André Lureau     {
100306680b15SMarc-André Lureau         int len;
100406680b15SMarc-André Lureau         len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
100506680b15SMarc-André Lureau         if (len > 0) {
100606680b15SMarc-André Lureau             buf[len] = 0;
100706680b15SMarc-André Lureau             p = buf;
100806680b15SMarc-André Lureau         }
100906680b15SMarc-André Lureau     }
101006680b15SMarc-André Lureau #elif defined(__FreeBSD__) \
101106680b15SMarc-André Lureau       || (defined(__NetBSD__) && defined(KERN_PROC_PATHNAME))
101206680b15SMarc-André Lureau     {
101306680b15SMarc-André Lureau #if defined(__FreeBSD__)
101406680b15SMarc-André Lureau         static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
101506680b15SMarc-André Lureau #else
101606680b15SMarc-André Lureau         static int mib[4] = {CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME};
101706680b15SMarc-André Lureau #endif
101806680b15SMarc-André Lureau         size_t len = sizeof(buf) - 1;
101906680b15SMarc-André Lureau 
102006680b15SMarc-André Lureau         *buf = '\0';
102106680b15SMarc-André Lureau         if (!sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) &&
102206680b15SMarc-André Lureau             *buf) {
102306680b15SMarc-André Lureau             buf[sizeof(buf) - 1] = '\0';
102406680b15SMarc-André Lureau             p = buf;
102506680b15SMarc-André Lureau         }
102606680b15SMarc-André Lureau     }
102706680b15SMarc-André Lureau #elif defined(__APPLE__)
102806680b15SMarc-André Lureau     {
102906680b15SMarc-André Lureau         char fpath[PATH_MAX];
103006680b15SMarc-André Lureau         uint32_t len = sizeof(fpath);
103106680b15SMarc-André Lureau         if (_NSGetExecutablePath(fpath, &len) == 0) {
103206680b15SMarc-André Lureau             p = realpath(fpath, buf);
103306680b15SMarc-André Lureau             if (!p) {
103406680b15SMarc-André Lureau                 return;
103506680b15SMarc-André Lureau             }
103606680b15SMarc-André Lureau         }
103706680b15SMarc-André Lureau     }
103806680b15SMarc-André Lureau #elif defined(__HAIKU__)
103906680b15SMarc-André Lureau     {
104006680b15SMarc-André Lureau         image_info ii;
104106680b15SMarc-André Lureau         int32_t c = 0;
104206680b15SMarc-André Lureau 
104306680b15SMarc-André Lureau         *buf = '\0';
104406680b15SMarc-André Lureau         while (get_next_image_info(0, &c, &ii) == B_OK) {
104506680b15SMarc-André Lureau             if (ii.type == B_APP_IMAGE) {
104606680b15SMarc-André Lureau                 strncpy(buf, ii.name, sizeof(buf));
104706680b15SMarc-André Lureau                 buf[sizeof(buf) - 1] = 0;
104806680b15SMarc-André Lureau                 p = buf;
104906680b15SMarc-André Lureau                 break;
105006680b15SMarc-André Lureau             }
105106680b15SMarc-André Lureau         }
105206680b15SMarc-André Lureau     }
105306680b15SMarc-André Lureau #endif
105406680b15SMarc-André Lureau     /* If we don't have any way of figuring out the actual executable
105506680b15SMarc-André Lureau        location then try argv[0].  */
105606680b15SMarc-André Lureau     if (!p && argv0) {
105706680b15SMarc-André Lureau         p = realpath(argv0, buf);
105806680b15SMarc-André Lureau     }
105906680b15SMarc-André Lureau     if (p) {
106006680b15SMarc-André Lureau         exec_dir = g_path_get_dirname(p);
106106680b15SMarc-André Lureau     } else {
106206680b15SMarc-André Lureau         exec_dir = CONFIG_BINDIR;
106306680b15SMarc-André Lureau     }
106406680b15SMarc-André Lureau #endif
106506680b15SMarc-André Lureau }
106606680b15SMarc-André Lureau 
106706680b15SMarc-André Lureau const char *qemu_get_exec_dir(void)
106806680b15SMarc-André Lureau {
106906680b15SMarc-André Lureau     return exec_dir;
107006680b15SMarc-André Lureau }
107106680b15SMarc-André Lureau 
1072f4f5ed2cSPaolo Bonzini char *get_relocated_path(const char *dir)
1073f4f5ed2cSPaolo Bonzini {
1074f4f5ed2cSPaolo Bonzini     size_t prefix_len = strlen(CONFIG_PREFIX);
1075f4f5ed2cSPaolo Bonzini     const char *bindir = CONFIG_BINDIR;
1076f4f5ed2cSPaolo Bonzini     const char *exec_dir = qemu_get_exec_dir();
1077f4f5ed2cSPaolo Bonzini     GString *result;
1078f4f5ed2cSPaolo Bonzini     int len_dir, len_bindir;
1079f4f5ed2cSPaolo Bonzini 
1080f4f5ed2cSPaolo Bonzini     /* Fail if qemu_init_exec_dir was not called.  */
1081f4f5ed2cSPaolo Bonzini     assert(exec_dir[0]);
1082f4f5ed2cSPaolo Bonzini 
1083f4f5ed2cSPaolo Bonzini     result = g_string_new(exec_dir);
1084cf60ccc3SAkihiko Odaki     g_string_append(result, "/qemu-bundle");
1085cf60ccc3SAkihiko Odaki     if (access(result->str, R_OK) == 0) {
1086cf60ccc3SAkihiko Odaki #ifdef G_OS_WIN32
1087cf60ccc3SAkihiko Odaki         size_t size = mbsrtowcs(NULL, &dir, 0, &(mbstate_t){0}) + 1;
1088cf60ccc3SAkihiko Odaki         PWSTR wdir = g_new(WCHAR, size);
1089cf60ccc3SAkihiko Odaki         mbsrtowcs(wdir, &dir, size, &(mbstate_t){0});
1090cf60ccc3SAkihiko Odaki 
1091cf60ccc3SAkihiko Odaki         PCWSTR wdir_skipped_root;
1092cf60ccc3SAkihiko Odaki         PathCchSkipRoot(wdir, &wdir_skipped_root);
1093cf60ccc3SAkihiko Odaki 
1094cf60ccc3SAkihiko Odaki         size = wcsrtombs(NULL, &wdir_skipped_root, 0, &(mbstate_t){0});
1095cf60ccc3SAkihiko Odaki         char *cursor = result->str + result->len;
1096cf60ccc3SAkihiko Odaki         g_string_set_size(result, result->len + size);
1097cf60ccc3SAkihiko Odaki         wcsrtombs(cursor, &wdir_skipped_root, size + 1, &(mbstate_t){0});
1098cf60ccc3SAkihiko Odaki         g_free(wdir);
1099cf60ccc3SAkihiko Odaki #else
1100cf60ccc3SAkihiko Odaki         g_string_append(result, dir);
1101cf60ccc3SAkihiko Odaki #endif
1102cf60ccc3SAkihiko Odaki     } else if (!starts_with_prefix(dir) || !starts_with_prefix(bindir)) {
1103cf60ccc3SAkihiko Odaki         g_string_assign(result, dir);
1104cf60ccc3SAkihiko Odaki     } else {
1105cf60ccc3SAkihiko Odaki         g_string_assign(result, exec_dir);
1106f4f5ed2cSPaolo Bonzini 
1107f4f5ed2cSPaolo Bonzini         /* Advance over common components.  */
1108f4f5ed2cSPaolo Bonzini         len_dir = len_bindir = prefix_len;
1109f4f5ed2cSPaolo Bonzini         do {
1110f4f5ed2cSPaolo Bonzini             dir += len_dir;
1111f4f5ed2cSPaolo Bonzini             bindir += len_bindir;
1112f4f5ed2cSPaolo Bonzini             dir = next_component(dir, &len_dir);
1113f4f5ed2cSPaolo Bonzini             bindir = next_component(bindir, &len_bindir);
11147a3b7f6bSSunil Muthuswamy         } while (len_dir && len_dir == len_bindir && !memcmp(dir, bindir, len_dir));
1115f4f5ed2cSPaolo Bonzini 
1116f4f5ed2cSPaolo Bonzini         /* Ascend from bindir to the common prefix with dir.  */
1117f4f5ed2cSPaolo Bonzini         while (len_bindir) {
1118f4f5ed2cSPaolo Bonzini             bindir += len_bindir;
1119f4f5ed2cSPaolo Bonzini             g_string_append(result, "/..");
1120f4f5ed2cSPaolo Bonzini             bindir = next_component(bindir, &len_bindir);
1121f4f5ed2cSPaolo Bonzini         }
1122f4f5ed2cSPaolo Bonzini 
1123f4f5ed2cSPaolo Bonzini         if (*dir) {
1124f4f5ed2cSPaolo Bonzini             assert(G_IS_DIR_SEPARATOR(dir[-1]));
1125f4f5ed2cSPaolo Bonzini             g_string_append(result, dir - 1);
1126f4f5ed2cSPaolo Bonzini         }
1127cf60ccc3SAkihiko Odaki     }
1128cf60ccc3SAkihiko Odaki 
1129b6d003dbSStefano Garzarella     return g_string_free(result, false);
1130f4f5ed2cSPaolo Bonzini }
1131