]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/iogetdelim.c
sparc (64bit): Regenerate ulps
[thirdparty/glibc.git] / libio / iogetdelim.c
CommitLineData
6d7e8eda 1/* Copyright (C) 1994-2023 Free Software Foundation, Inc.
41bdb6e2 2 This file is part of the GNU C Library.
96aa2d94 3
41bdb6e2
AJ
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
96aa2d94 8
41bdb6e2
AJ
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
40a55d20 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 12 Lesser General Public License for more details.
96aa2d94 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6 15 License along with the GNU C Library; if not, see
5a82c748 16 <https://www.gnu.org/licenses/>.
96aa2d94 17
41bdb6e2
AJ
18 As a special exception, if you link the code in this file with
19 files compiled with a GNU compiler to produce an executable,
20 that does not cause the resulting executable to be covered by
21 the GNU Lesser General Public License. This exception does not
22 however invalidate any other reasons why the executable file
23 might be covered by the GNU Lesser General Public License.
24 This exception applies to code released by its copyright holders
25 in files containing the exception. */
96aa2d94 26
96aa2d94 27#include <stdlib.h>
96aa2d94
RM
28#include "libioP.h"
29#include <string.h>
30#include <errno.h>
60160d83 31#include <limits.h>
96aa2d94
RM
32
33/* Read up to (and including) a TERMINATOR from FP into *LINEPTR
34 (and null-terminate it). *LINEPTR is a pointer returned from malloc (or
35 NULL), pointing to *N characters of space. It is realloc'ed as
36 necessary. Returns the number of characters read (not including the
37 null terminator), or -1 on error or EOF. */
38
9964a145 39ssize_t
7fcdb532 40__getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
96aa2d94 41{
9964a145
ZW
42 ssize_t result;
43 ssize_t cur_len = 0;
44 ssize_t len;
96aa2d94 45
96aa2d94 46 CHECK_FILE (fp, -1);
0261d33f 47 _IO_acquire_lock (fp);
7c713e28
RM
48 if (_IO_ferror_unlocked (fp))
49 {
50 result = -1;
51 goto unlock_return;
52 }
96aa2d94 53
a09183ae
AS
54 if (lineptr == NULL || n == NULL)
55 {
56 __set_errno (EINVAL);
57 fseterr_unlocked (fp);
58 result = -1;
59 goto unlock_return;
60 }
61
96aa2d94
RM
62 if (*lineptr == NULL || *n == 0)
63 {
64 *n = 120;
65 *lineptr = (char *) malloc (*n);
66 if (*lineptr == NULL)
7c713e28 67 {
a09183ae 68 fseterr_unlocked (fp);
7c713e28
RM
69 result = -1;
70 goto unlock_return;
71 }
96aa2d94
RM
72 }
73
74 len = fp->_IO_read_end - fp->_IO_read_ptr;
75 if (len <= 0)
76 {
77 if (__underflow (fp) == EOF)
7c713e28
RM
78 {
79 result = -1;
80 goto unlock_return;
81 }
96aa2d94
RM
82 len = fp->_IO_read_end - fp->_IO_read_ptr;
83 }
84
85 for (;;)
86 {
9964a145 87 size_t needed;
96aa2d94
RM
88 char *t;
89 t = (char *) memchr ((void *) fp->_IO_read_ptr, delimiter, len);
90 if (t != NULL)
91 len = (t - fp->_IO_read_ptr) + 1;
a1ffb40e 92 if (__glibc_unlikely (len >= SSIZE_MAX - cur_len))
6cebdfd8
UD
93 {
94 __set_errno (EOVERFLOW);
a09183ae 95 fseterr_unlocked (fp);
6cebdfd8
UD
96 result = -1;
97 goto unlock_return;
98 }
77a58cad 99 /* Make enough space for len+1 (for final NUL) bytes. */
96aa2d94
RM
100 needed = cur_len + len + 1;
101 if (needed > *n)
102 {
d1dddedf
UD
103 char *new_lineptr;
104
77a58cad 105 if (needed < 2 * *n)
96aa2d94 106 needed = 2 * *n; /* Be generous. */
d1dddedf
UD
107 new_lineptr = (char *) realloc (*lineptr, needed);
108 if (new_lineptr == NULL)
7c713e28 109 {
a09183ae 110 fseterr_unlocked (fp);
7c713e28
RM
111 result = -1;
112 goto unlock_return;
113 }
d1dddedf
UD
114 *lineptr = new_lineptr;
115 *n = needed;
96aa2d94
RM
116 }
117 memcpy (*lineptr + cur_len, (void *) fp->_IO_read_ptr, len);
118 fp->_IO_read_ptr += len;
119 cur_len += len;
120 if (t != NULL || __underflow (fp) == EOF)
121 break;
122 len = fp->_IO_read_end - fp->_IO_read_ptr;
123 }
77a58cad 124 (*lineptr)[cur_len] = '\0';
7c713e28
RM
125 result = cur_len;
126
127unlock_return:
0261d33f 128 _IO_release_lock (fp);
7c713e28 129 return result;
96aa2d94 130}
7fcdb532
FW
131libc_hidden_def (__getdelim)
132weak_alias (__getdelim, getdelim)