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 */ 24aafd7584SPeter Maydell #include "qemu/osdep.h" 25baacf047SPaolo Bonzini #include "qemu-common.h" 26baacf047SPaolo Bonzini #include "qemu/host-utils.h" 27baacf047SPaolo Bonzini #include <math.h> 28baacf047SPaolo Bonzini 29baacf047SPaolo Bonzini #include "qemu/sockets.h" 30baacf047SPaolo Bonzini #include "qemu/iov.h" 314297c8eeSAlexey Kardashevskiy #include "net/net.h" 32f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 3305cb8ed5SAlistair Francis #include "qemu/error-report.h" 34baacf047SPaolo Bonzini 35baacf047SPaolo Bonzini void strpadcpy(char *buf, int buf_size, const char *str, char pad) 36baacf047SPaolo Bonzini { 37baacf047SPaolo Bonzini int len = qemu_strnlen(str, buf_size); 38baacf047SPaolo Bonzini memcpy(buf, str, len); 39baacf047SPaolo Bonzini memset(buf + len, pad, buf_size - len); 40baacf047SPaolo Bonzini } 41baacf047SPaolo Bonzini 42baacf047SPaolo Bonzini void pstrcpy(char *buf, int buf_size, const char *str) 43baacf047SPaolo Bonzini { 44baacf047SPaolo Bonzini int c; 45baacf047SPaolo Bonzini char *q = buf; 46baacf047SPaolo Bonzini 47baacf047SPaolo Bonzini if (buf_size <= 0) 48baacf047SPaolo Bonzini return; 49baacf047SPaolo Bonzini 50baacf047SPaolo Bonzini for(;;) { 51baacf047SPaolo Bonzini c = *str++; 52baacf047SPaolo Bonzini if (c == 0 || q >= buf + buf_size - 1) 53baacf047SPaolo Bonzini break; 54baacf047SPaolo Bonzini *q++ = c; 55baacf047SPaolo Bonzini } 56baacf047SPaolo Bonzini *q = '\0'; 57baacf047SPaolo Bonzini } 58baacf047SPaolo Bonzini 59baacf047SPaolo Bonzini /* strcat and truncate. */ 60baacf047SPaolo Bonzini char *pstrcat(char *buf, int buf_size, const char *s) 61baacf047SPaolo Bonzini { 62baacf047SPaolo Bonzini int len; 63baacf047SPaolo Bonzini len = strlen(buf); 64baacf047SPaolo Bonzini if (len < buf_size) 65baacf047SPaolo Bonzini pstrcpy(buf + len, buf_size - len, s); 66baacf047SPaolo Bonzini return buf; 67baacf047SPaolo Bonzini } 68baacf047SPaolo Bonzini 69baacf047SPaolo Bonzini int strstart(const char *str, const char *val, const char **ptr) 70baacf047SPaolo Bonzini { 71baacf047SPaolo Bonzini const char *p, *q; 72baacf047SPaolo Bonzini p = str; 73baacf047SPaolo Bonzini q = val; 74baacf047SPaolo Bonzini while (*q != '\0') { 75baacf047SPaolo Bonzini if (*p != *q) 76baacf047SPaolo Bonzini return 0; 77baacf047SPaolo Bonzini p++; 78baacf047SPaolo Bonzini q++; 79baacf047SPaolo Bonzini } 80baacf047SPaolo Bonzini if (ptr) 81baacf047SPaolo Bonzini *ptr = p; 82baacf047SPaolo Bonzini return 1; 83baacf047SPaolo Bonzini } 84baacf047SPaolo Bonzini 85baacf047SPaolo Bonzini int stristart(const char *str, const char *val, const char **ptr) 86baacf047SPaolo Bonzini { 87baacf047SPaolo Bonzini const char *p, *q; 88baacf047SPaolo Bonzini p = str; 89baacf047SPaolo Bonzini q = val; 90baacf047SPaolo Bonzini while (*q != '\0') { 91baacf047SPaolo Bonzini if (qemu_toupper(*p) != qemu_toupper(*q)) 92baacf047SPaolo Bonzini return 0; 93baacf047SPaolo Bonzini p++; 94baacf047SPaolo Bonzini q++; 95baacf047SPaolo Bonzini } 96baacf047SPaolo Bonzini if (ptr) 97baacf047SPaolo Bonzini *ptr = p; 98baacf047SPaolo Bonzini return 1; 99baacf047SPaolo Bonzini } 100baacf047SPaolo Bonzini 101baacf047SPaolo Bonzini /* XXX: use host strnlen if available ? */ 102baacf047SPaolo Bonzini int qemu_strnlen(const char *s, int max_len) 103baacf047SPaolo Bonzini { 104baacf047SPaolo Bonzini int i; 105baacf047SPaolo Bonzini 106baacf047SPaolo Bonzini for(i = 0; i < max_len; i++) { 107baacf047SPaolo Bonzini if (s[i] == '\0') { 108baacf047SPaolo Bonzini break; 109baacf047SPaolo Bonzini } 110baacf047SPaolo Bonzini } 111baacf047SPaolo Bonzini return i; 112baacf047SPaolo Bonzini } 113baacf047SPaolo Bonzini 114a38ed811SKevin Wolf char *qemu_strsep(char **input, const char *delim) 115a38ed811SKevin Wolf { 116a38ed811SKevin Wolf char *result = *input; 117a38ed811SKevin Wolf if (result != NULL) { 118a38ed811SKevin Wolf char *p; 119a38ed811SKevin Wolf 120a38ed811SKevin Wolf for (p = result; *p != '\0'; p++) { 121a38ed811SKevin Wolf if (strchr(delim, *p)) { 122a38ed811SKevin Wolf break; 123a38ed811SKevin Wolf } 124a38ed811SKevin Wolf } 125a38ed811SKevin Wolf if (*p == '\0') { 126a38ed811SKevin Wolf *input = NULL; 127a38ed811SKevin Wolf } else { 128a38ed811SKevin Wolf *p = '\0'; 129a38ed811SKevin Wolf *input = p + 1; 130a38ed811SKevin Wolf } 131a38ed811SKevin Wolf } 132a38ed811SKevin Wolf return result; 133a38ed811SKevin Wolf } 134a38ed811SKevin Wolf 135baacf047SPaolo Bonzini time_t mktimegm(struct tm *tm) 136baacf047SPaolo Bonzini { 137baacf047SPaolo Bonzini time_t t; 138baacf047SPaolo Bonzini int y = tm->tm_year + 1900, m = tm->tm_mon + 1, d = tm->tm_mday; 139baacf047SPaolo Bonzini if (m < 3) { 140baacf047SPaolo Bonzini m += 12; 141baacf047SPaolo Bonzini y--; 142baacf047SPaolo Bonzini } 143baacf047SPaolo Bonzini t = 86400ULL * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + 144baacf047SPaolo Bonzini y / 400 - 719469); 145baacf047SPaolo Bonzini t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec; 146baacf047SPaolo Bonzini return t; 147baacf047SPaolo Bonzini } 148baacf047SPaolo Bonzini 149baacf047SPaolo Bonzini /* 150baacf047SPaolo Bonzini * Make sure data goes on disk, but if possible do not bother to 151baacf047SPaolo Bonzini * write out the inode just for timestamp updates. 152baacf047SPaolo Bonzini * 153baacf047SPaolo Bonzini * Unfortunately even in 2009 many operating systems do not support 154baacf047SPaolo Bonzini * fdatasync and have to fall back to fsync. 155baacf047SPaolo Bonzini */ 156baacf047SPaolo Bonzini int qemu_fdatasync(int fd) 157baacf047SPaolo Bonzini { 158baacf047SPaolo Bonzini #ifdef CONFIG_FDATASYNC 159baacf047SPaolo Bonzini return fdatasync(fd); 160baacf047SPaolo Bonzini #else 161baacf047SPaolo Bonzini return fsync(fd); 162baacf047SPaolo Bonzini #endif 163baacf047SPaolo Bonzini } 164baacf047SPaolo Bonzini 165baacf047SPaolo Bonzini #ifndef _WIN32 166baacf047SPaolo Bonzini /* Sets a specific flag */ 167baacf047SPaolo Bonzini int fcntl_setfl(int fd, int flag) 168baacf047SPaolo Bonzini { 169baacf047SPaolo Bonzini int flags; 170baacf047SPaolo Bonzini 171baacf047SPaolo Bonzini flags = fcntl(fd, F_GETFL); 172baacf047SPaolo Bonzini if (flags == -1) 173baacf047SPaolo Bonzini return -errno; 174baacf047SPaolo Bonzini 175baacf047SPaolo Bonzini if (fcntl(fd, F_SETFL, flags | flag) == -1) 176baacf047SPaolo Bonzini return -errno; 177baacf047SPaolo Bonzini 178baacf047SPaolo Bonzini return 0; 179baacf047SPaolo Bonzini } 180baacf047SPaolo Bonzini #endif 181baacf047SPaolo Bonzini 182baacf047SPaolo Bonzini static int64_t suffix_mul(char suffix, int64_t unit) 183baacf047SPaolo Bonzini { 184baacf047SPaolo Bonzini switch (qemu_toupper(suffix)) { 18517f94256SMarkus Armbruster case 'B': 186baacf047SPaolo Bonzini return 1; 18717f94256SMarkus Armbruster case 'K': 188baacf047SPaolo Bonzini return unit; 18917f94256SMarkus Armbruster case 'M': 190baacf047SPaolo Bonzini return unit * unit; 19117f94256SMarkus Armbruster case 'G': 192baacf047SPaolo Bonzini return unit * unit * unit; 19317f94256SMarkus Armbruster case 'T': 194baacf047SPaolo Bonzini return unit * unit * unit * unit; 19517f94256SMarkus Armbruster case 'P': 1965e00984aSKevin Wolf return unit * unit * unit * unit * unit; 19717f94256SMarkus Armbruster case 'E': 1985e00984aSKevin Wolf return unit * unit * unit * unit * unit * unit; 199baacf047SPaolo Bonzini } 200baacf047SPaolo Bonzini return -1; 201baacf047SPaolo Bonzini } 202baacf047SPaolo Bonzini 203baacf047SPaolo Bonzini /* 204baacf047SPaolo Bonzini * Convert string to bytes, allowing either B/b for bytes, K/k for KB, 205baacf047SPaolo Bonzini * M/m for MB, G/g for GB or T/t for TB. End pointer will be returned 206baacf047SPaolo Bonzini * in *end, if not NULL. Return -ERANGE on overflow, Return -EINVAL on 207baacf047SPaolo Bonzini * other error. 208baacf047SPaolo Bonzini */ 209f17fd4fdSMarkus Armbruster static int do_strtosz(const char *nptr, char **end, 210f17fd4fdSMarkus Armbruster const char default_suffix, int64_t unit, 211f46bfdbfSMarkus Armbruster uint64_t *result) 212baacf047SPaolo Bonzini { 213f17fd4fdSMarkus Armbruster int retval; 214baacf047SPaolo Bonzini char *endptr; 215baacf047SPaolo Bonzini unsigned char c; 216baacf047SPaolo Bonzini int mul_required = 0; 217baacf047SPaolo Bonzini double val, mul, integral, fraction; 218baacf047SPaolo Bonzini 219baacf047SPaolo Bonzini errno = 0; 220baacf047SPaolo Bonzini val = strtod(nptr, &endptr); 221baacf047SPaolo Bonzini if (isnan(val) || endptr == nptr || errno != 0) { 2224fcdf65aSMarkus Armbruster retval = -EINVAL; 2234fcdf65aSMarkus Armbruster goto out; 224baacf047SPaolo Bonzini } 225baacf047SPaolo Bonzini fraction = modf(val, &integral); 226baacf047SPaolo Bonzini if (fraction != 0) { 227baacf047SPaolo Bonzini mul_required = 1; 228baacf047SPaolo Bonzini } 229baacf047SPaolo Bonzini c = *endptr; 230baacf047SPaolo Bonzini mul = suffix_mul(c, unit); 231baacf047SPaolo Bonzini if (mul >= 0) { 232baacf047SPaolo Bonzini endptr++; 233baacf047SPaolo Bonzini } else { 234baacf047SPaolo Bonzini mul = suffix_mul(default_suffix, unit); 235baacf047SPaolo Bonzini assert(mul >= 0); 236baacf047SPaolo Bonzini } 237baacf047SPaolo Bonzini if (mul == 1 && mul_required) { 2384fcdf65aSMarkus Armbruster retval = -EINVAL; 2394fcdf65aSMarkus Armbruster goto out; 240baacf047SPaolo Bonzini } 241f46bfdbfSMarkus Armbruster /* 242f46bfdbfSMarkus Armbruster * Values >= 0xfffffffffffffc00 overflow uint64_t after their trip 243f46bfdbfSMarkus Armbruster * through double (53 bits of precision). 244f46bfdbfSMarkus Armbruster */ 245f46bfdbfSMarkus Armbruster if ((val * mul >= 0xfffffffffffffc00) || val < 0) { 246baacf047SPaolo Bonzini retval = -ERANGE; 2474fcdf65aSMarkus Armbruster goto out; 248baacf047SPaolo Bonzini } 249f17fd4fdSMarkus Armbruster *result = val * mul; 250f17fd4fdSMarkus Armbruster retval = 0; 251baacf047SPaolo Bonzini 2524fcdf65aSMarkus Armbruster out: 253baacf047SPaolo Bonzini if (end) { 254baacf047SPaolo Bonzini *end = endptr; 2554fcdf65aSMarkus Armbruster } else if (*endptr) { 2564fcdf65aSMarkus Armbruster retval = -EINVAL; 257baacf047SPaolo Bonzini } 258baacf047SPaolo Bonzini 259baacf047SPaolo Bonzini return retval; 260baacf047SPaolo Bonzini } 261baacf047SPaolo Bonzini 262f46bfdbfSMarkus Armbruster int qemu_strtosz(const char *nptr, char **end, uint64_t *result) 263baacf047SPaolo Bonzini { 264f17fd4fdSMarkus Armbruster return do_strtosz(nptr, end, 'B', 1024, result); 265baacf047SPaolo Bonzini } 266baacf047SPaolo Bonzini 267f46bfdbfSMarkus Armbruster int qemu_strtosz_MiB(const char *nptr, char **end, uint64_t *result) 268baacf047SPaolo Bonzini { 269f17fd4fdSMarkus Armbruster return do_strtosz(nptr, end, 'M', 1024, result); 270baacf047SPaolo Bonzini } 271baacf047SPaolo Bonzini 272f46bfdbfSMarkus Armbruster int qemu_strtosz_metric(const char *nptr, char **end, uint64_t *result) 273d2734d26SMarkus Armbruster { 274f17fd4fdSMarkus Armbruster return do_strtosz(nptr, end, 'B', 1000, result); 275d2734d26SMarkus Armbruster } 276d2734d26SMarkus Armbruster 277e3f9fe2dSEduardo Habkost /** 278717adf96SMarkus Armbruster * Helper function for error checking after strtol() and the like 279764e0fa4SCarlos L. Torres */ 280717adf96SMarkus Armbruster static int check_strtox_error(const char *nptr, char *ep, 281717adf96SMarkus Armbruster const char **endptr, int libc_errno) 282764e0fa4SCarlos L. Torres { 283*53a90b97SEric Blake assert(ep >= nptr); 284717adf96SMarkus Armbruster if (endptr) { 285717adf96SMarkus Armbruster *endptr = ep; 286764e0fa4SCarlos L. Torres } 2874baef267SMarkus Armbruster 2884baef267SMarkus Armbruster /* Turn "no conversion" into an error */ 2894baef267SMarkus Armbruster if (libc_errno == 0 && ep == nptr) { 2904baef267SMarkus Armbruster return -EINVAL; 2914baef267SMarkus Armbruster } 2924baef267SMarkus Armbruster 2934baef267SMarkus Armbruster /* Fail when we're expected to consume the string, but didn't */ 2944baef267SMarkus Armbruster if (!endptr && *ep) { 2954baef267SMarkus Armbruster return -EINVAL; 2964baef267SMarkus Armbruster } 2974baef267SMarkus Armbruster 298717adf96SMarkus Armbruster return -libc_errno; 299764e0fa4SCarlos L. Torres } 300764e0fa4SCarlos L. Torres 301764e0fa4SCarlos L. Torres /** 302473a2a33SDaniel P. Berrange * Convert string @nptr to an integer, and store it in @result. 303473a2a33SDaniel P. Berrange * 304473a2a33SDaniel P. Berrange * This is a wrapper around strtol() that is harder to misuse. 305473a2a33SDaniel P. Berrange * Semantics of @nptr, @endptr, @base match strtol() with differences 306473a2a33SDaniel P. Berrange * noted below. 307473a2a33SDaniel P. Berrange * 308473a2a33SDaniel P. Berrange * @nptr may be null, and no conversion is performed then. 309473a2a33SDaniel P. Berrange * 310473a2a33SDaniel P. Berrange * If no conversion is performed, store @nptr in *@endptr and return 311473a2a33SDaniel P. Berrange * -EINVAL. 312473a2a33SDaniel P. Berrange * 313473a2a33SDaniel P. Berrange * If @endptr is null, and the string isn't fully converted, return 314473a2a33SDaniel P. Berrange * -EINVAL. This is the case when the pointer that would be stored in 315473a2a33SDaniel P. Berrange * a non-null @endptr points to a character other than '\0'. 316473a2a33SDaniel P. Berrange * 317473a2a33SDaniel P. Berrange * If the conversion overflows @result, store INT_MAX in @result, 318473a2a33SDaniel P. Berrange * and return -ERANGE. 319473a2a33SDaniel P. Berrange * 320473a2a33SDaniel P. Berrange * If the conversion underflows @result, store INT_MIN in @result, 321473a2a33SDaniel P. Berrange * and return -ERANGE. 322473a2a33SDaniel P. Berrange * 323473a2a33SDaniel P. Berrange * Else store the converted value in @result, and return zero. 324473a2a33SDaniel P. Berrange */ 325473a2a33SDaniel P. Berrange int qemu_strtoi(const char *nptr, const char **endptr, int base, 326473a2a33SDaniel P. Berrange int *result) 327473a2a33SDaniel P. Berrange { 328473a2a33SDaniel P. Berrange char *ep; 329473a2a33SDaniel P. Berrange long long lresult; 330473a2a33SDaniel P. Berrange 331*53a90b97SEric Blake assert((unsigned) base <= 36 && base != 1); 332473a2a33SDaniel P. Berrange if (!nptr) { 333473a2a33SDaniel P. Berrange if (endptr) { 334473a2a33SDaniel P. Berrange *endptr = nptr; 335473a2a33SDaniel P. Berrange } 336473a2a33SDaniel P. Berrange return -EINVAL; 337473a2a33SDaniel P. Berrange } 338473a2a33SDaniel P. Berrange 339473a2a33SDaniel P. Berrange errno = 0; 340473a2a33SDaniel P. Berrange lresult = strtoll(nptr, &ep, base); 341473a2a33SDaniel P. Berrange if (lresult < INT_MIN) { 342473a2a33SDaniel P. Berrange *result = INT_MIN; 343473a2a33SDaniel P. Berrange errno = ERANGE; 344473a2a33SDaniel P. Berrange } else if (lresult > INT_MAX) { 345473a2a33SDaniel P. Berrange *result = INT_MAX; 346473a2a33SDaniel P. Berrange errno = ERANGE; 347473a2a33SDaniel P. Berrange } else { 348473a2a33SDaniel P. Berrange *result = lresult; 349473a2a33SDaniel P. Berrange } 350473a2a33SDaniel P. Berrange return check_strtox_error(nptr, ep, endptr, errno); 351473a2a33SDaniel P. Berrange } 352473a2a33SDaniel P. Berrange 353473a2a33SDaniel P. Berrange /** 354473a2a33SDaniel P. Berrange * Convert string @nptr to an unsigned integer, and store it in @result. 355473a2a33SDaniel P. Berrange * 356473a2a33SDaniel P. Berrange * This is a wrapper around strtoul() that is harder to misuse. 357473a2a33SDaniel P. Berrange * Semantics of @nptr, @endptr, @base match strtoul() with differences 358473a2a33SDaniel P. Berrange * noted below. 359473a2a33SDaniel P. Berrange * 360473a2a33SDaniel P. Berrange * @nptr may be null, and no conversion is performed then. 361473a2a33SDaniel P. Berrange * 362473a2a33SDaniel P. Berrange * If no conversion is performed, store @nptr in *@endptr and return 363473a2a33SDaniel P. Berrange * -EINVAL. 364473a2a33SDaniel P. Berrange * 365473a2a33SDaniel P. Berrange * If @endptr is null, and the string isn't fully converted, return 366473a2a33SDaniel P. Berrange * -EINVAL. This is the case when the pointer that would be stored in 367473a2a33SDaniel P. Berrange * a non-null @endptr points to a character other than '\0'. 368473a2a33SDaniel P. Berrange * 369473a2a33SDaniel P. Berrange * If the conversion overflows @result, store UINT_MAX in @result, 370473a2a33SDaniel P. Berrange * and return -ERANGE. 371473a2a33SDaniel P. Berrange * 372473a2a33SDaniel P. Berrange * Else store the converted value in @result, and return zero. 373473a2a33SDaniel P. Berrange * 374473a2a33SDaniel P. Berrange * Note that a number with a leading minus sign gets converted without 375473a2a33SDaniel P. Berrange * the minus sign, checked for overflow (see above), then negated (in 376473a2a33SDaniel P. Berrange * @result's type). This is exactly how strtoul() works. 377473a2a33SDaniel P. Berrange */ 378473a2a33SDaniel P. Berrange int qemu_strtoui(const char *nptr, const char **endptr, int base, 379473a2a33SDaniel P. Berrange unsigned int *result) 380473a2a33SDaniel P. Berrange { 381473a2a33SDaniel P. Berrange char *ep; 382473a2a33SDaniel P. Berrange long long lresult; 383473a2a33SDaniel P. Berrange 384*53a90b97SEric Blake assert((unsigned) base <= 36 && base != 1); 385473a2a33SDaniel P. Berrange if (!nptr) { 386473a2a33SDaniel P. Berrange if (endptr) { 387473a2a33SDaniel P. Berrange *endptr = nptr; 388473a2a33SDaniel P. Berrange } 389473a2a33SDaniel P. Berrange return -EINVAL; 390473a2a33SDaniel P. Berrange } 391473a2a33SDaniel P. Berrange 392473a2a33SDaniel P. Berrange errno = 0; 393473a2a33SDaniel P. Berrange lresult = strtoull(nptr, &ep, base); 394473a2a33SDaniel P. Berrange 395473a2a33SDaniel P. Berrange /* Windows returns 1 for negative out-of-range values. */ 396473a2a33SDaniel P. Berrange if (errno == ERANGE) { 397473a2a33SDaniel P. Berrange *result = -1; 398473a2a33SDaniel P. Berrange } else { 399473a2a33SDaniel P. Berrange if (lresult > UINT_MAX) { 400473a2a33SDaniel P. Berrange *result = UINT_MAX; 401473a2a33SDaniel P. Berrange errno = ERANGE; 402473a2a33SDaniel P. Berrange } else if (lresult < INT_MIN) { 403473a2a33SDaniel P. Berrange *result = UINT_MAX; 404473a2a33SDaniel P. Berrange errno = ERANGE; 405473a2a33SDaniel P. Berrange } else { 406473a2a33SDaniel P. Berrange *result = lresult; 407473a2a33SDaniel P. Berrange } 408473a2a33SDaniel P. Berrange } 409473a2a33SDaniel P. Berrange return check_strtox_error(nptr, ep, endptr, errno); 410473a2a33SDaniel P. Berrange } 411473a2a33SDaniel P. Berrange 412473a2a33SDaniel P. Berrange /** 4134295f879SMarkus Armbruster * Convert string @nptr to a long integer, and store it in @result. 414764e0fa4SCarlos L. Torres * 4154295f879SMarkus Armbruster * This is a wrapper around strtol() that is harder to misuse. 4164295f879SMarkus Armbruster * Semantics of @nptr, @endptr, @base match strtol() with differences 4174295f879SMarkus Armbruster * noted below. 418764e0fa4SCarlos L. Torres * 4194295f879SMarkus Armbruster * @nptr may be null, and no conversion is performed then. 420764e0fa4SCarlos L. Torres * 4214295f879SMarkus Armbruster * If no conversion is performed, store @nptr in *@endptr and return 4224295f879SMarkus Armbruster * -EINVAL. 423764e0fa4SCarlos L. Torres * 4244295f879SMarkus Armbruster * If @endptr is null, and the string isn't fully converted, return 4254295f879SMarkus Armbruster * -EINVAL. This is the case when the pointer that would be stored in 4264295f879SMarkus Armbruster * a non-null @endptr points to a character other than '\0'. 4274295f879SMarkus Armbruster * 4284295f879SMarkus Armbruster * If the conversion overflows @result, store LONG_MAX in @result, 4294295f879SMarkus Armbruster * and return -ERANGE. 4304295f879SMarkus Armbruster * 4314295f879SMarkus Armbruster * If the conversion underflows @result, store LONG_MIN in @result, 4324295f879SMarkus Armbruster * and return -ERANGE. 4334295f879SMarkus Armbruster * 4344295f879SMarkus Armbruster * Else store the converted value in @result, and return zero. 435764e0fa4SCarlos L. Torres */ 436764e0fa4SCarlos L. Torres int qemu_strtol(const char *nptr, const char **endptr, int base, 437764e0fa4SCarlos L. Torres long *result) 438764e0fa4SCarlos L. Torres { 439717adf96SMarkus Armbruster char *ep; 4404baef267SMarkus Armbruster 441*53a90b97SEric Blake assert((unsigned) base <= 36 && base != 1); 442764e0fa4SCarlos L. Torres if (!nptr) { 443764e0fa4SCarlos L. Torres if (endptr) { 444764e0fa4SCarlos L. Torres *endptr = nptr; 445764e0fa4SCarlos L. Torres } 4464baef267SMarkus Armbruster return -EINVAL; 4474baef267SMarkus Armbruster } 4484baef267SMarkus Armbruster 449764e0fa4SCarlos L. Torres errno = 0; 450717adf96SMarkus Armbruster *result = strtol(nptr, &ep, base); 4514baef267SMarkus Armbruster return check_strtox_error(nptr, ep, endptr, errno); 452764e0fa4SCarlos L. Torres } 453c817c015SCarlos L. Torres 454c817c015SCarlos L. Torres /** 4554295f879SMarkus Armbruster * Convert string @nptr to an unsigned long, and store it in @result. 456c817c015SCarlos L. Torres * 4574295f879SMarkus Armbruster * This is a wrapper around strtoul() that is harder to misuse. 4584295f879SMarkus Armbruster * Semantics of @nptr, @endptr, @base match strtoul() with differences 4594295f879SMarkus Armbruster * noted below. 460c817c015SCarlos L. Torres * 4614295f879SMarkus Armbruster * @nptr may be null, and no conversion is performed then. 462c817c015SCarlos L. Torres * 4634295f879SMarkus Armbruster * If no conversion is performed, store @nptr in *@endptr and return 4644295f879SMarkus Armbruster * -EINVAL. 4654295f879SMarkus Armbruster * 4664295f879SMarkus Armbruster * If @endptr is null, and the string isn't fully converted, return 4674295f879SMarkus Armbruster * -EINVAL. This is the case when the pointer that would be stored in 4684295f879SMarkus Armbruster * a non-null @endptr points to a character other than '\0'. 4694295f879SMarkus Armbruster * 4704295f879SMarkus Armbruster * If the conversion overflows @result, store ULONG_MAX in @result, 4714295f879SMarkus Armbruster * and return -ERANGE. 4724295f879SMarkus Armbruster * 4734295f879SMarkus Armbruster * Else store the converted value in @result, and return zero. 4744295f879SMarkus Armbruster * 4754295f879SMarkus Armbruster * Note that a number with a leading minus sign gets converted without 4764295f879SMarkus Armbruster * the minus sign, checked for overflow (see above), then negated (in 4774295f879SMarkus Armbruster * @result's type). This is exactly how strtoul() works. 478c817c015SCarlos L. Torres */ 479c817c015SCarlos L. Torres int qemu_strtoul(const char *nptr, const char **endptr, int base, 480c817c015SCarlos L. Torres unsigned long *result) 481c817c015SCarlos L. Torres { 482717adf96SMarkus Armbruster char *ep; 4834baef267SMarkus Armbruster 484*53a90b97SEric Blake assert((unsigned) base <= 36 && base != 1); 485c817c015SCarlos L. Torres if (!nptr) { 486c817c015SCarlos L. Torres if (endptr) { 487c817c015SCarlos L. Torres *endptr = nptr; 488c817c015SCarlos L. Torres } 4894baef267SMarkus Armbruster return -EINVAL; 4904baef267SMarkus Armbruster } 4914baef267SMarkus Armbruster 492c817c015SCarlos L. Torres errno = 0; 493717adf96SMarkus Armbruster *result = strtoul(nptr, &ep, base); 49447d4be12SPaolo Bonzini /* Windows returns 1 for negative out-of-range values. */ 49547d4be12SPaolo Bonzini if (errno == ERANGE) { 49647d4be12SPaolo Bonzini *result = -1; 49747d4be12SPaolo Bonzini } 4984baef267SMarkus Armbruster return check_strtox_error(nptr, ep, endptr, errno); 499c817c015SCarlos L. Torres } 500c817c015SCarlos L. Torres 501764e0fa4SCarlos L. Torres /** 5024295f879SMarkus Armbruster * Convert string @nptr to an int64_t. 5038ac4df40SCarlos L. Torres * 5044295f879SMarkus Armbruster * Works like qemu_strtol(), except it stores INT64_MAX on overflow, 5054295f879SMarkus Armbruster * and INT_MIN on underflow. 5068ac4df40SCarlos L. Torres */ 507b30d1886SMarkus Armbruster int qemu_strtoi64(const char *nptr, const char **endptr, int base, 5088ac4df40SCarlos L. Torres int64_t *result) 5098ac4df40SCarlos L. Torres { 510717adf96SMarkus Armbruster char *ep; 5114baef267SMarkus Armbruster 512*53a90b97SEric Blake assert((unsigned) base <= 36 && base != 1); 5138ac4df40SCarlos L. Torres if (!nptr) { 5148ac4df40SCarlos L. Torres if (endptr) { 5158ac4df40SCarlos L. Torres *endptr = nptr; 5168ac4df40SCarlos L. Torres } 5174baef267SMarkus Armbruster return -EINVAL; 5184baef267SMarkus Armbruster } 5194baef267SMarkus Armbruster 5208ac4df40SCarlos L. Torres errno = 0; 5214295f879SMarkus Armbruster /* FIXME This assumes int64_t is long long */ 522717adf96SMarkus Armbruster *result = strtoll(nptr, &ep, base); 5234baef267SMarkus Armbruster return check_strtox_error(nptr, ep, endptr, errno); 5248ac4df40SCarlos L. Torres } 5258ac4df40SCarlos L. Torres 5268ac4df40SCarlos L. Torres /** 5274295f879SMarkus Armbruster * Convert string @nptr to an uint64_t. 5283904e6bfSCarlos L. Torres * 5294295f879SMarkus Armbruster * Works like qemu_strtoul(), except it stores UINT64_MAX on overflow. 5303904e6bfSCarlos L. Torres */ 531b30d1886SMarkus Armbruster int qemu_strtou64(const char *nptr, const char **endptr, int base, 5323904e6bfSCarlos L. Torres uint64_t *result) 5333904e6bfSCarlos L. Torres { 534717adf96SMarkus Armbruster char *ep; 5354baef267SMarkus Armbruster 536*53a90b97SEric Blake assert((unsigned) base <= 36 && base != 1); 5373904e6bfSCarlos L. Torres if (!nptr) { 5383904e6bfSCarlos L. Torres if (endptr) { 5393904e6bfSCarlos L. Torres *endptr = nptr; 5403904e6bfSCarlos L. Torres } 5414baef267SMarkus Armbruster return -EINVAL; 5424baef267SMarkus Armbruster } 5434baef267SMarkus Armbruster 5443904e6bfSCarlos L. Torres errno = 0; 5454295f879SMarkus Armbruster /* FIXME This assumes uint64_t is unsigned long long */ 546717adf96SMarkus Armbruster *result = strtoull(nptr, &ep, base); 54747d4be12SPaolo Bonzini /* Windows returns 1 for negative out-of-range values. */ 54847d4be12SPaolo Bonzini if (errno == ERANGE) { 54947d4be12SPaolo Bonzini *result = -1; 55047d4be12SPaolo Bonzini } 5514baef267SMarkus Armbruster return check_strtox_error(nptr, ep, endptr, errno); 5523904e6bfSCarlos L. Torres } 5533904e6bfSCarlos L. Torres 5543904e6bfSCarlos L. Torres /** 5555c99fa37SKeno Fischer * Searches for the first occurrence of 'c' in 's', and returns a pointer 5565c99fa37SKeno Fischer * to the trailing null byte if none was found. 5575c99fa37SKeno Fischer */ 5585c99fa37SKeno Fischer #ifndef HAVE_STRCHRNUL 5595c99fa37SKeno Fischer const char *qemu_strchrnul(const char *s, int c) 5605c99fa37SKeno Fischer { 5615c99fa37SKeno Fischer const char *e = strchr(s, c); 5625c99fa37SKeno Fischer if (!e) { 5635c99fa37SKeno Fischer e = s + strlen(s); 5645c99fa37SKeno Fischer } 5655c99fa37SKeno Fischer return e; 5665c99fa37SKeno Fischer } 5675c99fa37SKeno Fischer #endif 5685c99fa37SKeno Fischer 5695c99fa37SKeno Fischer /** 570e3f9fe2dSEduardo Habkost * parse_uint: 571e3f9fe2dSEduardo Habkost * 572e3f9fe2dSEduardo Habkost * @s: String to parse 573e3f9fe2dSEduardo Habkost * @value: Destination for parsed integer value 574e3f9fe2dSEduardo Habkost * @endptr: Destination for pointer to first character not consumed 575e3f9fe2dSEduardo Habkost * @base: integer base, between 2 and 36 inclusive, or 0 576e3f9fe2dSEduardo Habkost * 577e3f9fe2dSEduardo Habkost * Parse unsigned integer 578e3f9fe2dSEduardo Habkost * 579e3f9fe2dSEduardo Habkost * Parsed syntax is like strtoull()'s: arbitrary whitespace, a single optional 580e3f9fe2dSEduardo Habkost * '+' or '-', an optional "0x" if @base is 0 or 16, one or more digits. 581e3f9fe2dSEduardo Habkost * 582e3f9fe2dSEduardo Habkost * If @s is null, or @base is invalid, or @s doesn't start with an 583e3f9fe2dSEduardo Habkost * integer in the syntax above, set *@value to 0, *@endptr to @s, and 584e3f9fe2dSEduardo Habkost * return -EINVAL. 585e3f9fe2dSEduardo Habkost * 586e3f9fe2dSEduardo Habkost * Set *@endptr to point right beyond the parsed integer (even if the integer 587e3f9fe2dSEduardo Habkost * overflows or is negative, all digits will be parsed and *@endptr will 588e3f9fe2dSEduardo Habkost * point right beyond them). 589e3f9fe2dSEduardo Habkost * 590e3f9fe2dSEduardo Habkost * If the integer is negative, set *@value to 0, and return -ERANGE. 591e3f9fe2dSEduardo Habkost * 592e3f9fe2dSEduardo Habkost * If the integer overflows unsigned long long, set *@value to 593e3f9fe2dSEduardo Habkost * ULLONG_MAX, and return -ERANGE. 594e3f9fe2dSEduardo Habkost * 595e3f9fe2dSEduardo Habkost * Else, set *@value to the parsed integer, and return 0. 596e3f9fe2dSEduardo Habkost */ 597e3f9fe2dSEduardo Habkost int parse_uint(const char *s, unsigned long long *value, char **endptr, 598e3f9fe2dSEduardo Habkost int base) 599e3f9fe2dSEduardo Habkost { 600e3f9fe2dSEduardo Habkost int r = 0; 601e3f9fe2dSEduardo Habkost char *endp = (char *)s; 602e3f9fe2dSEduardo Habkost unsigned long long val = 0; 603e3f9fe2dSEduardo Habkost 604*53a90b97SEric Blake assert((unsigned) base <= 36 && base != 1); 605e3f9fe2dSEduardo Habkost if (!s) { 606e3f9fe2dSEduardo Habkost r = -EINVAL; 607e3f9fe2dSEduardo Habkost goto out; 608e3f9fe2dSEduardo Habkost } 609e3f9fe2dSEduardo Habkost 610e3f9fe2dSEduardo Habkost errno = 0; 611e3f9fe2dSEduardo Habkost val = strtoull(s, &endp, base); 612e3f9fe2dSEduardo Habkost if (errno) { 613e3f9fe2dSEduardo Habkost r = -errno; 614e3f9fe2dSEduardo Habkost goto out; 615e3f9fe2dSEduardo Habkost } 616e3f9fe2dSEduardo Habkost 617e3f9fe2dSEduardo Habkost if (endp == s) { 618e3f9fe2dSEduardo Habkost r = -EINVAL; 619e3f9fe2dSEduardo Habkost goto out; 620e3f9fe2dSEduardo Habkost } 621e3f9fe2dSEduardo Habkost 622e3f9fe2dSEduardo Habkost /* make sure we reject negative numbers: */ 623e3f9fe2dSEduardo Habkost while (isspace((unsigned char)*s)) { 624e3f9fe2dSEduardo Habkost s++; 625e3f9fe2dSEduardo Habkost } 626e3f9fe2dSEduardo Habkost if (*s == '-') { 627e3f9fe2dSEduardo Habkost val = 0; 628e3f9fe2dSEduardo Habkost r = -ERANGE; 629e3f9fe2dSEduardo Habkost goto out; 630e3f9fe2dSEduardo Habkost } 631e3f9fe2dSEduardo Habkost 632e3f9fe2dSEduardo Habkost out: 633e3f9fe2dSEduardo Habkost *value = val; 634e3f9fe2dSEduardo Habkost *endptr = endp; 635e3f9fe2dSEduardo Habkost return r; 636e3f9fe2dSEduardo Habkost } 637e3f9fe2dSEduardo Habkost 638e3f9fe2dSEduardo Habkost /** 639e3f9fe2dSEduardo Habkost * parse_uint_full: 640e3f9fe2dSEduardo Habkost * 641e3f9fe2dSEduardo Habkost * @s: String to parse 642e3f9fe2dSEduardo Habkost * @value: Destination for parsed integer value 643e3f9fe2dSEduardo Habkost * @base: integer base, between 2 and 36 inclusive, or 0 644e3f9fe2dSEduardo Habkost * 645e3f9fe2dSEduardo Habkost * Parse unsigned integer from entire string 646e3f9fe2dSEduardo Habkost * 647e3f9fe2dSEduardo Habkost * Have the same behavior of parse_uint(), but with an additional check 648e3f9fe2dSEduardo Habkost * for additional data after the parsed number. If extra characters are present 649e3f9fe2dSEduardo Habkost * after the parsed number, the function will return -EINVAL, and *@v will 650e3f9fe2dSEduardo Habkost * be set to 0. 651e3f9fe2dSEduardo Habkost */ 652e3f9fe2dSEduardo Habkost int parse_uint_full(const char *s, unsigned long long *value, int base) 653e3f9fe2dSEduardo Habkost { 654e3f9fe2dSEduardo Habkost char *endp; 655e3f9fe2dSEduardo Habkost int r; 656e3f9fe2dSEduardo Habkost 657e3f9fe2dSEduardo Habkost r = parse_uint(s, value, &endp, base); 658e3f9fe2dSEduardo Habkost if (r < 0) { 659e3f9fe2dSEduardo Habkost return r; 660e3f9fe2dSEduardo Habkost } 661e3f9fe2dSEduardo Habkost if (*endp) { 662e3f9fe2dSEduardo Habkost *value = 0; 663e3f9fe2dSEduardo Habkost return -EINVAL; 664e3f9fe2dSEduardo Habkost } 665e3f9fe2dSEduardo Habkost 666e3f9fe2dSEduardo Habkost return 0; 667e3f9fe2dSEduardo Habkost } 668e3f9fe2dSEduardo Habkost 669baacf047SPaolo Bonzini int qemu_parse_fd(const char *param) 670baacf047SPaolo Bonzini { 671e9c5c1f4SLaszlo Ersek long fd; 672e9c5c1f4SLaszlo Ersek char *endptr; 673baacf047SPaolo Bonzini 674e9c5c1f4SLaszlo Ersek errno = 0; 675baacf047SPaolo Bonzini fd = strtol(param, &endptr, 10); 676e9c5c1f4SLaszlo Ersek if (param == endptr /* no conversion performed */ || 677e9c5c1f4SLaszlo Ersek errno != 0 /* not representable as long; possibly others */ || 678e9c5c1f4SLaszlo Ersek *endptr != '\0' /* final string not empty */ || 679e9c5c1f4SLaszlo Ersek fd < 0 /* invalid as file descriptor */ || 680e9c5c1f4SLaszlo Ersek fd > INT_MAX /* not representable as int */) { 681baacf047SPaolo Bonzini return -1; 682baacf047SPaolo Bonzini } 683baacf047SPaolo Bonzini return fd; 684baacf047SPaolo Bonzini } 685baacf047SPaolo Bonzini 686baacf047SPaolo Bonzini /* 687baacf047SPaolo Bonzini * Implementation of ULEB128 (http://en.wikipedia.org/wiki/LEB128) 688baacf047SPaolo Bonzini * Input is limited to 14-bit numbers 689baacf047SPaolo Bonzini */ 690baacf047SPaolo Bonzini int uleb128_encode_small(uint8_t *out, uint32_t n) 691baacf047SPaolo Bonzini { 692baacf047SPaolo Bonzini g_assert(n <= 0x3fff); 693baacf047SPaolo Bonzini if (n < 0x80) { 694baacf047SPaolo Bonzini *out++ = n; 695baacf047SPaolo Bonzini return 1; 696baacf047SPaolo Bonzini } else { 697baacf047SPaolo Bonzini *out++ = (n & 0x7f) | 0x80; 698baacf047SPaolo Bonzini *out++ = n >> 7; 699baacf047SPaolo Bonzini return 2; 700baacf047SPaolo Bonzini } 701baacf047SPaolo Bonzini } 702baacf047SPaolo Bonzini 703baacf047SPaolo Bonzini int uleb128_decode_small(const uint8_t *in, uint32_t *n) 704baacf047SPaolo Bonzini { 705baacf047SPaolo Bonzini if (!(*in & 0x80)) { 706baacf047SPaolo Bonzini *n = *in++; 707baacf047SPaolo Bonzini return 1; 708baacf047SPaolo Bonzini } else { 709baacf047SPaolo Bonzini *n = *in++ & 0x7f; 710baacf047SPaolo Bonzini /* we exceed 14 bit number */ 711baacf047SPaolo Bonzini if (*in & 0x80) { 712baacf047SPaolo Bonzini return -1; 713baacf047SPaolo Bonzini } 714baacf047SPaolo Bonzini *n |= *in++ << 7; 715baacf047SPaolo Bonzini return 2; 716baacf047SPaolo Bonzini } 717baacf047SPaolo Bonzini } 718b16352acSAlon Levy 719b16352acSAlon Levy /* 720b16352acSAlon Levy * helper to parse debug environment variables 721b16352acSAlon Levy */ 722b16352acSAlon Levy int parse_debug_env(const char *name, int max, int initial) 723b16352acSAlon Levy { 724b16352acSAlon Levy char *debug_env = getenv(name); 725b16352acSAlon Levy char *inv = NULL; 726cc5d0e04SPaolo Bonzini long debug; 727b16352acSAlon Levy 728b16352acSAlon Levy if (!debug_env) { 729b16352acSAlon Levy return initial; 730b16352acSAlon Levy } 731cc5d0e04SPaolo Bonzini errno = 0; 732b16352acSAlon Levy debug = strtol(debug_env, &inv, 10); 733b16352acSAlon Levy if (inv == debug_env) { 734b16352acSAlon Levy return initial; 735b16352acSAlon Levy } 736cc5d0e04SPaolo Bonzini if (debug < 0 || debug > max || errno != 0) { 73705cb8ed5SAlistair Francis warn_report("%s not in [0, %d]", name, max); 738b16352acSAlon Levy return initial; 739b16352acSAlon Levy } 740b16352acSAlon Levy return debug; 741b16352acSAlon Levy } 7424297c8eeSAlexey Kardashevskiy 7434297c8eeSAlexey Kardashevskiy /* 7444297c8eeSAlexey Kardashevskiy * Helper to print ethernet mac address 7454297c8eeSAlexey Kardashevskiy */ 7464297c8eeSAlexey Kardashevskiy const char *qemu_ether_ntoa(const MACAddr *mac) 7474297c8eeSAlexey Kardashevskiy { 7484297c8eeSAlexey Kardashevskiy static char ret[18]; 7494297c8eeSAlexey Kardashevskiy 7504297c8eeSAlexey Kardashevskiy snprintf(ret, sizeof(ret), "%02x:%02x:%02x:%02x:%02x:%02x", 7514297c8eeSAlexey Kardashevskiy mac->a[0], mac->a[1], mac->a[2], mac->a[3], mac->a[4], mac->a[5]); 7524297c8eeSAlexey Kardashevskiy 7534297c8eeSAlexey Kardashevskiy return ret; 7544297c8eeSAlexey Kardashevskiy } 75522951aaaSPeter Xu 75622951aaaSPeter Xu /* 75722951aaaSPeter Xu * Return human readable string for size @val. 75822951aaaSPeter Xu * @val can be anything that uint64_t allows (no more than "16 EiB"). 75922951aaaSPeter Xu * Use IEC binary units like KiB, MiB, and so forth. 76022951aaaSPeter Xu * Caller is responsible for passing it to g_free(). 76122951aaaSPeter Xu */ 76222951aaaSPeter Xu char *size_to_str(uint64_t val) 76322951aaaSPeter Xu { 76422951aaaSPeter Xu static const char *suffixes[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" }; 76522951aaaSPeter Xu unsigned long div; 76622951aaaSPeter Xu int i; 76722951aaaSPeter Xu 76822951aaaSPeter Xu /* 76922951aaaSPeter Xu * The exponent (returned in i) minus one gives us 77022951aaaSPeter Xu * floor(log2(val * 1024 / 1000). The correction makes us 77122951aaaSPeter Xu * switch to the higher power when the integer part is >= 1000. 77222951aaaSPeter Xu * (see e41b509d68afb1f for more info) 77322951aaaSPeter Xu */ 77422951aaaSPeter Xu frexp(val / (1000.0 / 1024.0), &i); 77522951aaaSPeter Xu i = (i - 1) / 10; 77622951aaaSPeter Xu div = 1ULL << (i * 10); 77722951aaaSPeter Xu 77822951aaaSPeter Xu return g_strdup_printf("%0.3g %sB", (double)val / div, suffixes[i]); 77922951aaaSPeter Xu } 78085e33a28SMarc-André Lureau 78185e33a28SMarc-André Lureau int qemu_pstrcmp0(const char **str1, const char **str2) 78285e33a28SMarc-André Lureau { 78385e33a28SMarc-André Lureau return g_strcmp0(*str1, *str2); 78485e33a28SMarc-André Lureau } 785