Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/common/vsprintf.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  linux/lib/vsprintf.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 */
6
7
/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
8
/*
9
 * Wirzenius wrote this portably, Torvalds fucked it up :-)
10
 */
11
12
/* 
13
 * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
14
 * - changed to provide snprintf and vsnprintf functions
15
 * So Feb  1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
16
 * - scnprintf and vscnprintf
17
 */
18
19
#include <xen/ctype.h>
20
#include <xen/symbols.h>
21
#include <xen/lib.h>
22
#include <xen/sched.h>
23
#include <xen/livepatch.h>
24
#include <asm/div64.h>
25
#include <asm/page.h>
26
27
/**
28
 * simple_strtoul - convert a string to an unsigned long
29
 * @cp: The start of the string
30
 * @endp: A pointer to the end of the parsed string will be placed here
31
 * @base: The number base to use
32
 */
33
unsigned long simple_strtoul(
34
    const char *cp, const char **endp, unsigned int base)
35
3
{
36
3
    unsigned long result = 0,value;
37
3
38
3
    if (!base) {
39
0
        base = 10;
40
0
        if (*cp == '0') {
41
0
            base = 8;
42
0
            cp++;
43
0
            if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
44
0
                cp++;
45
0
                base = 16;
46
0
            }
47
0
        }
48
3
    } else if (base == 16) {
49
0
        if (cp[0] == '0' && toupper(cp[1]) == 'X')
50
0
            cp += 2;
51
0
    }
52
11
    while (isxdigit(*cp) &&
53
8
           (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
54
8
        result = result*base + value;
55
8
        cp++;
56
8
    }
57
3
    if (endp)
58
3
        *endp = cp;
59
3
    return result;
60
3
}
61
62
EXPORT_SYMBOL(simple_strtoul);
63
64
/**
65
 * simple_strtol - convert a string to a signed long
66
 * @cp: The start of the string
67
 * @endp: A pointer to the end of the parsed string will be placed here
68
 * @base: The number base to use
69
 */
70
long simple_strtol(const char *cp, const char **endp, unsigned int base)
71
0
{
72
0
    if(*cp=='-')
73
0
        return -simple_strtoul(cp+1,endp,base);
74
0
    return simple_strtoul(cp,endp,base);
75
0
}
76
77
EXPORT_SYMBOL(simple_strtol);
78
79
/**
80
 * simple_strtoull - convert a string to an unsigned long long
81
 * @cp: The start of the string
82
 * @endp: A pointer to the end of the parsed string will be placed here
83
 * @base: The number base to use
84
 */
85
unsigned long long simple_strtoull(
86
    const char *cp, const char **endp, unsigned int base)
87
0
{
88
0
    unsigned long long result = 0,value;
89
0
90
0
    if (!base) {
91
0
        base = 10;
92
0
        if (*cp == '0') {
93
0
            base = 8;
94
0
            cp++;
95
0
            if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
96
0
                cp++;
97
0
                base = 16;
98
0
            }
99
0
        }
100
0
    } else if (base == 16) {
101
0
        if (cp[0] == '0' && toupper(cp[1]) == 'X')
102
0
            cp += 2;
103
0
    }
104
0
    while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
105
0
                                                               ? toupper(*cp) : *cp)-'A'+10) < base) {
106
0
        result = result*base + value;
107
0
        cp++;
108
0
    }
109
0
    if (endp)
110
0
        *endp = cp;
111
0
    return result;
112
0
}
113
114
EXPORT_SYMBOL(simple_strtoull);
115
116
/**
117
 * simple_strtoll - convert a string to a signed long long
118
 * @cp: The start of the string
119
 * @endp: A pointer to the end of the parsed string will be placed here
120
 * @base: The number base to use
121
 */
122
long long simple_strtoll(const char *cp,const char **endp,unsigned int base)
123
0
{
124
0
    if(*cp=='-')
125
0
        return -simple_strtoull(cp+1,endp,base);
126
0
    return simple_strtoull(cp,endp,base);
127
0
}
128
129
static int skip_atoi(const char **s)
130
593
{
131
593
    int i=0;
132
593
133
1.22k
    while (isdigit(**s))
134
634
        i = i*10 + *((*s)++) - '0';
135
593
    return i;
136
593
}
137
138
2.26k
#define ZEROPAD 1               /* pad with zero */
139
1.84k
#define SIGN    2               /* unsigned/signed long */
140
138
#define PLUS    4               /* show plus */
141
138
#define SPACE   8               /* space if plus */
142
2.97k
#define LEFT    16              /* left justified */
143
1.84k
#define SPECIAL 32              /* 0x */
144
978
#define LARGE   64              /* use 'ABCDEF' instead of 'abcdef' */
145
146
static char *number(
147
    char *buf, char *end, unsigned long long num,
148
    int base, int size, int precision, int type)
149
909
{
150
909
    char c,sign,tmp[66];
151
909
    const char *digits;
152
909
    static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
153
909
    static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
154
909
    int i;
155
909
156
909
    ASSERT(base >= 2 && base <= 36);
157
909
158
909
    digits = (type & LARGE) ? large_digits : small_digits;
159
909
    if (type & LEFT)
160
0
        type &= ~ZEROPAD;
161
909
    c = (type & ZEROPAD) ? '0' : ' ';
162
909
    sign = 0;
163
909
    if (type & SIGN) {
164
140
        if ((signed long long) num < 0) {
165
2
            sign = '-';
166
2
            num = - (signed long long) num;
167
2
            size--;
168
138
        } else if (type & PLUS) {
169
0
            sign = '+';
170
0
            size--;
171
138
        } else if (type & SPACE) {
172
0
            sign = ' ';
173
0
            size--;
174
0
        }
175
140
    }
176
909
    if (type & SPECIAL) {
177
27
        if (num == 0)
178
1
            type &= ~SPECIAL;
179
26
        else if (base == 16)
180
26
            size -= 2;
181
0
        else if (base == 8)
182
0
            size--;
183
0
        else
184
0
            type &= ~SPECIAL;
185
27
    }
186
909
    i = 0;
187
909
    if (num == 0)
188
391
        tmp[i++]='0';
189
2.08k
    else while (num != 0)
190
1.56k
        tmp[i++] = digits[do_div(num,base)];
191
909
    if (i > precision)
192
909
        precision = i;
193
909
    size -= precision;
194
909
    if (!(type&(ZEROPAD+LEFT))) {
195
596
        while(size-->0) {
196
129
            if (buf < end)
197
129
                *buf = ' ';
198
129
            ++buf;
199
129
        }
200
467
    }
201
909
    if (sign) {
202
2
        if (buf < end)
203
2
            *buf = sign;
204
2
        ++buf;
205
2
    }
206
909
    if (type & SPECIAL) {
207
26
        if (buf < end)
208
26
            *buf = '0';
209
26
        ++buf;
210
26
        if (base == 16) {
211
26
            if (buf < end)
212
26
                *buf = digits[33];
213
26
            ++buf;
214
26
        }
215
26
    }
216
909
    if (!(type & LEFT)) {
217
1.77k
        while (size-- > 0) {
218
863
            if (buf < end)
219
863
                *buf = c;
220
863
            ++buf;
221
863
        }
222
909
    }
223
909
    while (i < precision--) {
224
0
        if (buf < end)
225
0
            *buf = '0';
226
0
        ++buf;
227
0
    }
228
2.86k
    while (i-- > 0) {
229
1.95k
        if (buf < end)
230
1.95k
            *buf = tmp[i];
231
1.95k
        ++buf;
232
1.95k
    }
233
909
    while (size-- > 0) {
234
0
        if (buf < end)
235
0
            *buf = ' ';
236
0
        ++buf;
237
0
    }
238
909
    return buf;
239
909
}
240
241
static char *string(char *str, char *end, const char *s,
242
                    int field_width, int precision, int flags)
243
243
{
244
177
    int i, len = (precision < 0) ? strlen(s) : strnlen(s, precision);
245
243
246
243
    if (!(flags & LEFT)) {
247
286
        while (len < field_width--) {
248
43
            if (str < end)
249
43
                *str = ' ';
250
43
            ++str;
251
43
        }
252
243
    }
253
3.09k
    for (i = 0; i < len; ++i) {
254
2.85k
        if (str < end)
255
2.85k
            *str = *s;
256
2.85k
        ++str; ++s;
257
2.85k
    }
258
243
    while (len < field_width--) {
259
0
        if (str < end)
260
0
            *str = ' ';
261
0
        ++str;
262
0
    }
263
243
264
243
    return str;
265
243
}
266
267
static char *pointer(char *str, char *end, const char **fmt_ptr,
268
                     const void *arg, int field_width, int precision,
269
                     int flags)
270
47
{
271
47
    const char *fmt = *fmt_ptr, *s;
272
47
273
47
    /* Custom %p suffixes. See XEN_ROOT/docs/misc/printk-formats.txt */
274
47
    switch ( fmt[1] )
275
47
    {
276
0
    case 'h': /* Raw buffer as hex string. */
277
0
    {
278
0
        const uint8_t *hex_buffer = arg;
279
0
        char sep = ' '; /* Separator character. */
280
0
        unsigned int i;
281
0
282
0
        /* Consumed 'h' from the format string. */
283
0
        ++*fmt_ptr;
284
0
285
0
        /* Bound user count from %* to between 0 and 64 bytes. */
286
0
        if ( field_width <= 0 )
287
0
            return str;
288
0
        if ( field_width > 64 )
289
0
            field_width = 64;
290
0
291
0
        /*
292
0
         * Peek ahead in the format string to see if a recognised separator
293
0
         * modifier is present.
294
0
         */
295
0
        switch ( fmt[2] )
296
0
        {
297
0
        case 'C': /* Colons. */
298
0
            ++*fmt_ptr;
299
0
            sep = ':';
300
0
            break;
301
0
302
0
        case 'D': /* Dashes. */
303
0
            ++*fmt_ptr;
304
0
            sep = '-';
305
0
            break;
306
0
307
0
        case 'N': /* No separator. */
308
0
            ++*fmt_ptr;
309
0
            sep = 0;
310
0
            break;
311
0
        }
312
0
313
0
        for ( i = 0; ; )
314
0
        {
315
0
            /* Each byte: 2 chars, 0-padded, base 16, no hex prefix. */
316
0
            str = number(str, end, hex_buffer[i], 16, 2, -1, ZEROPAD);
317
0
318
0
            if ( ++i == field_width )
319
0
                return str;
320
0
321
0
            if ( sep )
322
0
            {
323
0
                if ( str < end )
324
0
                    *str = sep;
325
0
                ++str;
326
0
            }
327
0
        }
328
0
    }
329
0
330
3
    case 's': /* Symbol name with offset and size (iff offset != 0) */
331
3
    case 'S': /* Symbol name unconditionally with offset and size */
332
3
    {
333
3
        unsigned long sym_size, sym_offset;
334
3
        char namebuf[KSYM_NAME_LEN+1];
335
3
336
3
        /* Advance parents fmt string, as we have consumed 's' or 'S' */
337
3
        ++*fmt_ptr;
338
3
339
3
        s = symbols_lookup((unsigned long)arg, &sym_size, &sym_offset, namebuf);
340
3
341
3
        /* If the symbol is not found, fall back to printing the address */
342
3
        if ( !s )
343
3
            break;
344
3
345
3
        /* Print symbol name */
346
0
        str = string(str, end, s, -1, -1, 0);
347
0
348
0
        if ( fmt[1] == 'S' || sym_offset != 0 )
349
0
        {
350
0
            /* Print '+<offset>/<len>' */
351
0
            str = number(str, end, sym_offset, 16, -1, -1, SPECIAL|SIGN|PLUS);
352
0
            if ( str < end )
353
0
                *str = '/';
354
0
            ++str;
355
0
            str = number(str, end, sym_size, 16, -1, -1, SPECIAL);
356
0
        }
357
0
358
0
        /*
359
0
         * namebuf contents and s for core hypervisor are same but for Live Patch
360
0
         * payloads they differ (namebuf contains the name of the payload).
361
0
         */
362
0
        if ( namebuf != s )
363
0
        {
364
0
            str = string(str, end, " [", -1, -1, 0);
365
0
            str = string(str, end, namebuf, -1, -1, 0);
366
0
            str = string(str, end, "]", -1, -1, 0);
367
0
        }
368
0
369
0
        return str;
370
3
    }
371
3
372
34
    case 'v': /* d<domain-id>v<vcpu-id> from a struct vcpu */
373
34
    {
374
34
        const struct vcpu *v = arg;
375
34
376
34
        ++*fmt_ptr;
377
34
        if ( unlikely(v->domain->domain_id == DOMID_IDLE) )
378
1
            str = string(str, end, "IDLE", -1, -1, 0);
379
34
        else
380
33
        {
381
33
            if ( str < end )
382
33
                *str = 'd';
383
33
            str = number(str + 1, end, v->domain->domain_id, 10, -1, -1, 0);
384
33
        }
385
34
        if ( str < end )
386
34
            *str = 'v';
387
34
        return number(str + 1, end, v->vcpu_id, 10, -1, -1, 0);
388
3
    }
389
47
    }
390
47
391
13
    if ( field_width == -1 )
392
13
    {
393
13
        field_width = 2 * sizeof(void *);
394
13
        flags |= ZEROPAD;
395
13
    }
396
13
397
13
    return number(str, end, (unsigned long)arg,
398
13
                  16, field_width, precision, flags);
399
47
}
400
401
/**
402
 * vsnprintf - Format a string and place it in a buffer
403
 * @buf: The buffer to place the result into
404
 * @size: The size of the buffer, including the trailing null space
405
 * @fmt: The format string to use
406
 * @args: Arguments for the format string
407
 *
408
 * The return value is the number of characters which would
409
 * be generated for the given input, excluding the trailing
410
 * '\0', as per ISO C99. If you want to have the exact
411
 * number of characters written into @buf as return value
412
 * (not including the trailing '\0'), use vscnprintf. If the
413
 * return is greater than or equal to @size, the resulting
414
 * string is truncated.
415
 *
416
 * Call this function if you are already dealing with a va_list.
417
 * You probably want snprintf instead.
418
 */
419
int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
420
682
{
421
682
    unsigned long long num;
422
682
    int base;
423
682
    char *str, *end, c;
424
682
    const char *s;
425
682
426
682
    int flags;          /* flags to number() */
427
682
428
682
    int field_width;    /* width of output field */
429
682
    int precision;              /* min. # of digits for integers; max
430
682
                                   number of chars for from string */
431
682
    int qualifier;              /* 'h', 'l', or 'L' for integer fields */
432
682
                                /* 'z' support added 23/7/1999 S.H.    */
433
682
                                /* 'z' changed to 'Z' --davidm 1/25/99 */
434
682
435
682
    /* Reject out-of-range values early */
436
682
    BUG_ON(((int)size < 0) || ((unsigned int)size != size));
437
682
438
682
    str = buf;
439
682
    end = buf + size;
440
682
441
682
    if (end < buf) {
442
0
        end = ((void *) -1);
443
0
        size = end - buf;
444
0
    }
445
682
446
13.1k
    for (; *fmt ; ++fmt) {
447
12.5k
        if (*fmt != '%') {
448
11.3k
            if (str < end)
449
11.3k
                *str = *fmt;
450
11.3k
            ++str;
451
11.3k
            continue;
452
11.3k
        }
453
12.5k
454
12.5k
        /* process flags */
455
1.12k
        flags = 0;
456
1.57k
    repeat:
457
1.57k
        ++fmt;          /* this also skips first '%' */
458
1.57k
        switch (*fmt) {
459
0
        case '-': flags |= LEFT; goto repeat;
460
0
        case '+': flags |= PLUS; goto repeat;
461
0
        case ' ': flags |= SPACE; goto repeat;
462
27
        case '#': flags |= SPECIAL; goto repeat;
463
429
        case '0': flags |= ZEROPAD; goto repeat;
464
1.57k
        }
465
1.57k
466
1.57k
        /* get field width */
467
1.12k
        field_width = -1;
468
1.12k
        if (isdigit(*fmt))
469
527
            field_width = skip_atoi(&fmt);
470
593
        else if (*fmt == '*') {
471
0
            ++fmt;
472
0
            /* it's the next argument */
473
0
            field_width = va_arg(args, int);
474
0
            if (field_width < 0) {
475
0
                field_width = -field_width;
476
0
                flags |= LEFT;
477
0
            }
478
0
        }
479
1.12k
480
1.12k
        /* get the precision */
481
1.12k
        precision = -1;
482
1.12k
        if (*fmt == '.') {
483
66
            ++fmt;
484
66
            if (isdigit(*fmt))
485
66
                precision = skip_atoi(&fmt);
486
0
            else if (*fmt == '*') {
487
0
                ++fmt;
488
0
                          /* it's the next argument */
489
0
                precision = va_arg(args, int);
490
0
            }
491
66
            if (precision < 0)
492
0
                precision = 0;
493
66
        }
494
1.12k
495
1.12k
        /* get the conversion qualifier */
496
1.12k
        qualifier = -1;
497
1.12k
        if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
498
997
            *fmt =='Z' || *fmt == 'z') {
499
123
            qualifier = *fmt;
500
123
            ++fmt;
501
123
            if (qualifier == 'l' && *fmt == 'l') {
502
0
                qualifier = 'L';
503
0
                ++fmt;
504
0
            }
505
123
        }
506
1.12k
507
1.12k
        /* default base */
508
1.12k
        base = 10;
509
1.12k
510
1.12k
        switch (*fmt) {
511
2
        case 'c':
512
2
            if (!(flags & LEFT)) {
513
2
                while (--field_width > 0) {
514
0
                    if (str < end)
515
0
                        *str = ' ';
516
0
                    ++str;
517
0
                }
518
2
            }
519
2
            c = (unsigned char) va_arg(args, int);
520
2
            if (str < end)
521
2
                *str = c;
522
2
            ++str;
523
2
            while (--field_width > 0) {
524
0
                if (str < end)
525
0
                    *str = ' ';
526
0
                ++str;
527
0
            }
528
2
            continue;
529
2
530
242
        case 's':
531
242
            s = va_arg(args, char *);
532
242
            if ((unsigned long)s < PAGE_SIZE)
533
0
                s = "<NULL>";
534
242
535
242
            str = string(str, end, s, field_width, precision, flags);
536
242
            continue;
537
2
538
47
        case 'p':
539
47
            /* pointer() might advance fmt (%pS for example) */
540
47
            str = pointer(str, end, &fmt, va_arg(args, const void *),
541
47
                          field_width, precision, flags);
542
47
            continue;
543
2
544
2
545
0
        case 'n':
546
0
            if (qualifier == 'l') {
547
0
                long * ip = va_arg(args, long *);
548
0
                *ip = (str - buf);
549
0
            } else if (qualifier == 'Z' || qualifier == 'z') {
550
0
                size_t * ip = va_arg(args, size_t *);
551
0
                *ip = (str - buf);
552
0
            } else {
553
0
                int * ip = va_arg(args, int *);
554
0
                *ip = (str - buf);
555
0
            }
556
0
            continue;
557
2
558
0
        case '%':
559
0
            if (str < end)
560
0
                *str = '%';
561
0
            ++str;
562
0
            continue;
563
2
564
2
            /* integer number formats - set up the flags and "break" */
565
0
        case 'o':
566
0
            base = 8;
567
0
            break;
568
2
569
69
        case 'X':
570
69
            flags |= LARGE;
571
514
        case 'x':
572
514
            base = 16;
573
514
            break;
574
69
575
140
        case 'd':
576
140
        case 'i':
577
140
            flags |= SIGN;
578
315
        case 'u':
579
315
            break;
580
140
581
0
        default:
582
0
            if (str < end)
583
0
                *str = '%';
584
0
            ++str;
585
0
            if (*fmt) {
586
0
                if (str < end)
587
0
                    *str = *fmt;
588
0
                ++str;
589
0
            } else {
590
0
                --fmt;
591
0
            }
592
0
            continue;
593
1.12k
        }
594
829
        if (qualifier == 'L')
595
38
            num = va_arg(args, long long);
596
791
        else if (qualifier == 'l') {
597
85
            num = va_arg(args, unsigned long);
598
85
            if (flags & SIGN)
599
1
                num = (signed long) num;
600
706
        } else if (qualifier == 'Z' || qualifier == 'z') {
601
0
            num = va_arg(args, size_t);
602
706
        } else if (qualifier == 'h') {
603
0
            num = (unsigned short) va_arg(args, int);
604
0
            if (flags & SIGN)
605
0
                num = (signed short) num;
606
706
        } else {
607
706
            num = va_arg(args, unsigned int);
608
706
            if (flags & SIGN)
609
139
                num = (signed int) num;
610
706
        }
611
829
612
829
        str = number(str, end, num, base,
613
829
                     field_width, precision, flags);
614
829
    }
615
682
616
682
    /* don't write out a null byte if the buf size is zero */
617
682
    if (size > 0) {
618
682
        if (str < end)
619
682
            *str = '\0';
620
682
        else
621
0
            end[-1] = '\0';
622
682
    }
623
682
    /* the trailing null byte doesn't count towards the total
624
682
     * ++str;
625
682
     */
626
682
    return str-buf;
627
682
}
628
629
EXPORT_SYMBOL(vsnprintf);
630
631
/**
632
 * vscnprintf - Format a string and place it in a buffer
633
 * @buf: The buffer to place the result into
634
 * @size: The size of the buffer, including the trailing null space
635
 * @fmt: The format string to use
636
 * @args: Arguments for the format string
637
 *
638
 * The return value is the number of characters which have been written into
639
 * the @buf not including the trailing '\0'. If @size is <= 0 the function
640
 * returns 0.
641
 *
642
 * Call this function if you are already dealing with a va_list.
643
 * You probably want scnprintf instead.
644
 */
645
int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
646
0
{
647
0
    int i;
648
0
649
0
    i = vsnprintf(buf,size,fmt,args);
650
0
    if (i >= size)
651
0
        i = size - 1;
652
0
    return (i > 0) ? i : 0;
653
0
}
654
655
EXPORT_SYMBOL(vscnprintf);
656
657
/**
658
 * snprintf - Format a string and place it in a buffer
659
 * @buf: The buffer to place the result into
660
 * @size: The size of the buffer, including the trailing null space
661
 * @fmt: The format string to use
662
 * @...: Arguments for the format string
663
 *
664
 * The return value is the number of characters which would be
665
 * generated for the given input, excluding the trailing null,
666
 * as per ISO C99.  If the return is greater than or equal to
667
 * @size, the resulting string is truncated.
668
 */
669
int snprintf(char * buf, size_t size, const char *fmt, ...)
670
227
{
671
227
    va_list args;
672
227
    int i;
673
227
674
227
    va_start(args, fmt);
675
227
    i=vsnprintf(buf,size,fmt,args);
676
227
    va_end(args);
677
227
    return i;
678
227
}
679
680
EXPORT_SYMBOL(snprintf);
681
682
/**
683
 * scnprintf - Format a string and place it in a buffer
684
 * @buf: The buffer to place the result into
685
 * @size: The size of the buffer, including the trailing null space
686
 * @fmt: The format string to use
687
 * @...: Arguments for the format string
688
 *
689
 * The return value is the number of characters written into @buf not including
690
 * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is
691
 * greater than or equal to @size, the resulting string is truncated.
692
 */
693
694
int scnprintf(char * buf, size_t size, const char *fmt, ...)
695
0
{
696
0
    va_list args;
697
0
    int i;
698
0
699
0
    va_start(args, fmt);
700
0
    i = vsnprintf(buf, size, fmt, args);
701
0
    va_end(args);
702
0
    if (i >= size)
703
0
        i = size - 1;
704
0
    return (i > 0) ? i : 0;
705
0
}
706
EXPORT_SYMBOL(scnprintf);
707
708
/**
709
 * vasprintf - Format a string and allocate a buffer to place it in
710
 *
711
 * @bufp: Pointer to a pointer to receive the allocated buffer
712
 * @fmt: The format string to use
713
 * @args: Arguments for the format string
714
 *
715
 * -ENOMEM is returned on failure and @bufp is not touched.
716
 * On success, 0 is returned. The buffer passed back is
717
 * guaranteed to be null terminated. The memory is allocated
718
 * from xenheap, so the buffer should be freed with xfree().
719
 */
720
int vasprintf(char **bufp, const char *fmt, va_list args)
721
0
{
722
0
    va_list args_copy;
723
0
    size_t size;
724
0
    char *buf;
725
0
726
0
    va_copy(args_copy, args);
727
0
    size = vsnprintf(NULL, 0, fmt, args_copy);
728
0
    va_end(args_copy);
729
0
730
0
    buf = xmalloc_array(char, ++size);
731
0
    if ( !buf )
732
0
        return -ENOMEM;
733
0
734
0
    (void) vsnprintf(buf, size, fmt, args);
735
0
736
0
    *bufp = buf;
737
0
    return 0;
738
0
}
739
740
/**
741
 * asprintf - Format a string and place it in a buffer
742
 * @bufp: Pointer to a pointer to receive the allocated buffer
743
 * @fmt: The format string to use
744
 * @...: Arguments for the format string
745
 *
746
 * -ENOMEM is returned on failure and @bufp is not touched.
747
 * On success, 0 is returned. The buffer passed back is
748
 * guaranteed to be null terminated. The memory is allocated
749
 * from xenheap, so the buffer should be freed with xfree().
750
 */
751
int asprintf(char **bufp, const char *fmt, ...)
752
0
{
753
0
    va_list args;
754
0
    int i;
755
0
756
0
    va_start(args, fmt);
757
0
    i=vasprintf(bufp,fmt,args);
758
0
    va_end(args);
759
0
    return i;
760
0
}
761
762
/*
763
 * Local variables:
764
 * mode: C
765
 * c-file-style: "BSD"
766
 * c-basic-offset: 4
767
 * tab-width: 4
768
 * indent-tabs-mode: nil
769
 * End:
770
 */