vasprintf.c (6a18a77221ca134826742f1aa91fe4966f772b22) vasprintf.c (15aa00d597010009c3fb718ded37438aa3f601ab)
1/* $OpenBSD: vasprintf.c,v 1.4 1998/06/21 22:13:47 millert Exp $ */
2
3/*
4 * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
5 * All rights reserved.
1/*-
2 * Copyright (c) 1996 Peter Wemm <peter@freebsd.org>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
12 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
28 */
29
24 */
25
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD$");
26#if defined(LIBC_RCS) && !defined(lint)
27static char rcsid[] = "$Id$";
28#endif /* LIBC_RCS and not lint */
32
33#include <stdio.h>
34#include <stdlib.h>
29
30#include <stdio.h>
31#include <stdlib.h>
35#include <errno.h>
36#include "local.h"
37
32
33#if __STDC__
34#include <stdarg.h>
35#else
36#include <varargs.h>
37#endif
38
39#define CHUNK_SPARE 128 /* how much spare to allocate to avoid realloc calls */
40
41struct bufcookie {
42 char *base; /* start of buffer */
43 int size;
44 int left;
45};
46
47static int
48writehook(cookie, buf, len)
49 void *cookie;
50 char *buf;
51 int len;
52{
53 struct bufcookie *h = (struct bufcookie *)cookie;
54
55 if (len == 0)
56 return 0;
57
58 if (len > h->left) {
59 /* grow malloc region */
60 h->left = h->left + len + CHUNK_SPARE;
61 h->size = h->size + len + CHUNK_SPARE;
62 h->base = realloc(h->base, h->size);
63 if (h->base == NULL)
64 return (-1);
65 }
66 /* "write" it */
67 (void)memcpy(h->base + h->size - h->left, buf, len);
68 h->left -= len;
69 return (0);
70}
71
72
38int
73int
39vasprintf(char **str, const char *fmt, __va_list ap)
74vasprintf(str, fmt, ap)
75 char **str;
76 const char *fmt;
77 va_list ap;
40{
78{
41 FILE f = FAKE_FILE;
42 int ret;
79 int ret;
80 FILE *f;
81 struct bufcookie h;
43
82
44 f._flags = __SWR | __SSTR | __SALC;
45 f._bf._base = f._p = malloc(128);
46 if (f._bf._base == NULL) {
47 *str = NULL;
48 errno = ENOMEM;
83 h.base = malloc(CHUNK_SPARE);
84 if (h.base == NULL)
49 return (-1);
85 return (-1);
86 h.size = CHUNK_SPARE;
87 h.left = CHUNK_SPARE;
88
89 f = funopen(&h, NULL, writehook, NULL, NULL);
90 if (f == NULL) {
91 free(h.base);
92 return (-1);
50 }
93 }
51 f._bf._size = f._w = 127; /* Leave room for the NUL */
52 ret = __vfprintf(&f, fmt, ap);
94 ret = vfprintf(f, fmt, ap);
95 fclose(f);
53 if (ret < 0) {
96 if (ret < 0) {
54 free(f._bf._base);
55 *str = NULL;
56 errno = ENOMEM;
97 free(h.base);
57 return (-1);
58 }
98 return (-1);
99 }
59 *f._p = '\0';
60 *str = (char *)f._bf._base;
100 if (h.base == NULL) /* failed to realloc in writehook */
101 return (-1);
102
103 h.base[h.size - h.left] = '\0';
104 *str = realloc(h.base, h.size - h.left + 1);
105 if (*str == NULL) /* failed to realloc it to actual size */
106 return -1;
61 return (ret);
62}
107 return (ret);
108}