1 /* $NetBSD: getdelim.c,v 1.13 2011/07/22 23:12:30 joerg Exp $ */
4 * Copyright (c) 2009 The NetBSD Foundation, Inc.
6 * This code is derived from software contributed to The NetBSD Foundation
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/cdefs.h>
31 __RCSID("$NetBSD: getdelim.c,v 1.13 2011/07/22 23:12:30 joerg Exp $");
33 #include "namespace.h"
35 #include <sys/param.h>
44 #include "reentrant.h"
48 __weak_alias(getdelim
, _getdelim
)
51 /* Minimum buffer size we create.
52 * This should allow config files to fit into our power of 2 buffer growth
53 * without the need for a realloc. */
57 __getdelim(char **__restrict buf
, size_t *__restrict buflen
,
58 int sep
, FILE *__restrict fp
)
61 size_t len
, newlen
, off
;
64 _DIAGASSERT(fp
!= NULL
);
66 if (buf
== NULL
|| buflen
== NULL
) {
71 /* If buf is NULL, we have to assume a size of zero */
75 _SET_ORIENTATION(fp
, -1);
78 /* If the input buffer is empty, refill it */
79 if (fp
->_r
<= 0 && __srefill(fp
)) {
82 /* No error, so EOF. */
86 /* Scan through looking for the separator */
87 p
= memchr(fp
->_p
, sep
, (size_t)fp
->_r
);
91 len
= (p
- fp
->_p
) + 1;
94 /* Ensure we can handle it */
95 if (newlen
< off
|| newlen
> SSIZE_MAX
) {
99 newlen
++; /* reserve space for the NULL terminator */
100 if (newlen
> *buflen
) {
103 if (!powerof2(newlen
)) {
104 /* Grow the buffer to the next power of 2 */
106 newlen
|= newlen
>> 1;
107 newlen
|= newlen
>> 2;
108 newlen
|= newlen
>> 4;
109 newlen
|= newlen
>> 8;
110 newlen
|= newlen
>> 16;
111 #if SIZE_T_MAX > 0xffffffffU
112 newlen
|= newlen
>> 32;
117 newb
= realloc(*buf
, newlen
);
124 (void)memcpy((*buf
+ off
), fp
->_p
, len
);
125 /* Safe, len is never greater than what fp->_r can fit. */
131 /* POSIX demands we return -1 on EOF. */
136 *(*buf
+ off
) = '\0';
140 fp
->_flags
|= __SERR
;
145 getdelim(char **__restrict buf
, size_t *__restrict buflen
,
146 int sep
, FILE *__restrict fp
)
151 n
= __getdelim(buf
, buflen
, sep
, fp
);