Revision 9f9b17a4

b/cutils.c
23 23
 */
24 24
#include "qemu-common.h"
25 25
#include "host-utils.h"
26
#include <math.h>
26 27

  
27 28
void pstrcpy(char *buf, int buf_size, const char *str)
28 29
{
......
283 284
}
284 285
#endif
285 286

  
287
/*
288
 * Convert string to bytes, allowing either B/b for bytes, K/k for KB,
289
 * M/m for MB, G/g for GB or T/t for TB. Default without any postfix
290
 * is MB. End pointer will be returned in *end, if not NULL. A valid
291
 * value must be terminated by whitespace, ',' or '\0'. Return -1 on
292
 * error.
293
 */
294
ssize_t strtosz(const char *nptr, char **end)
295
{
296
    ssize_t retval = -1;
297
    char *endptr, c;
298
    int mul_required = 0;
299
    double val, mul, integral, fraction;
300

  
301
    errno = 0;
302
    val = strtod(nptr, &endptr);
303
    if (isnan(val) || endptr == nptr || errno != 0) {
304
        goto fail;
305
    }
306
    integral = modf(val, &fraction);
307
    if (integral != 0) {
308
        mul_required = 1;
309
    }
310
    /*
311
     * Any whitespace character is fine for terminating the number,
312
     * in addition we accept ',' to handle strings where the size is
313
     * part of a multi token argument.
314
     */
315
    c = *endptr;
316
    if (isspace(c) || c == '\0' || c == ',') {
317
        c = 0;
318
    }
319
    switch (c) {
320
    case 'B':
321
    case 'b':
322
        mul = 1;
323
        if (mul_required) {
324
            goto fail;
325
        }
326
        break;
327
    case 'K':
328
    case 'k':
329
        mul = 1 << 10;
330
        break;
331
    case 0:
332
        if (mul_required) {
333
            goto fail;
334
        }
335
    case 'M':
336
    case 'm':
337
        mul = 1ULL << 20;
338
        break;
339
    case 'G':
340
    case 'g':
341
        mul = 1ULL << 30;
342
        break;
343
    case 'T':
344
    case 't':
345
        mul = 1ULL << 40;
346
        break;
347
    default:
348
        goto fail;
349
    }
350
    /*
351
     * If not terminated by whitespace, ',', or \0, increment endptr
352
     * to point to next character, then check that we are terminated
353
     * by an appropriate separating character, ie. whitespace, ',', or
354
     * \0. If not, we are seeing trailing garbage, thus fail.
355
     */
356
    if (c != 0) {
357
        endptr++;
358
        if (!isspace(*endptr) && *endptr != ',' && *endptr != 0) {
359
            goto fail;
360
        }
361
    }
362
    if ((val * mul >= ~(size_t)0) || val < 0) {
363
        goto fail;
364
    }
365
    retval = val * mul;
366

  
367
fail:
368
    if (end) {
369
        *end = endptr;
370
    }
371

  
372
    return retval;
373
}
b/qemu-common.h
149 149
int qemu_fls(int i);
150 150
int qemu_fdatasync(int fd);
151 151
int fcntl_setfl(int fd, int flag);
152
ssize_t strtosz(const char *nptr, char **end);
152 153

  
153 154
/* path.c */
154 155
void init_paths(const char *prefix);
b/vl.c
710 710
        if (get_param_value(option, 128, "mem", optarg) == 0) {
711 711
            node_mem[nodenr] = 0;
712 712
        } else {
713
            value = strtoull(option, &endptr, 0);
714
            switch (*endptr) {
715
            case 0: case 'M': case 'm':
716
                value <<= 20;
717
                break;
718
            case 'G': case 'g':
719
                value <<= 30;
720
                break;
713
            ssize_t sval;
714
            sval = strtosz(option, NULL);
715
            if (sval < 0) {
716
                fprintf(stderr, "qemu: invalid numa mem size: %s\n", optarg);
717
                exit(1);
721 718
            }
722
            node_mem[nodenr] = value;
719
            node_mem[nodenr] = sval;
723 720
        }
724 721
        if (get_param_value(option, 128, "cpus", optarg) == 0) {
725 722
            node_cpumask[nodenr] = 0;
......
2139 2136
                exit(0);
2140 2137
                break;
2141 2138
            case QEMU_OPTION_m: {
2142
                uint64_t value;
2143
                char *ptr;
2139
                ssize_t value;
2144 2140

  
2145
                value = strtoul(optarg, &ptr, 10);
2146
                switch (*ptr) {
2147
                case 0: case 'M': case 'm':
2148
                    value <<= 20;
2149
                    break;
2150
                case 'G': case 'g':
2151
                    value <<= 30;
2152
                    break;
2153
                default:
2141
                value = strtosz(optarg, NULL);
2142
                if (value < 0) {
2154 2143
                    fprintf(stderr, "qemu: invalid ram size: %s\n", optarg);
2155 2144
                    exit(1);
2156 2145
                }

Also available in: Unified diff