glibc/libio/iogetdelim.c
Zack Weinberg 30bfee2630 Remove miscellaneous debris from libio.
This patch eliminates a number of #if 0 and #ifdef TODO blocks, macros
that are never used, macros that provide portability to substrates that
lack basic things like EINVAL and off_t, and other such debris.

I preserved IO_DEBUG and CHECK_FILE, even though as far as I can tell
IO_DEBUG is never defined and therefore CHECK_FILE never does
anything, because it seems like we might actually want to turn it _on_.

Installed stripped libraries and executables are unchanged, except,
again, that the line number of an assertion changes (this time it's
somewhere in fileops.c).

	* libio/libio.h (_IO_pos_BAD, _IO_pos_0, _IO_pos_adjust):
	Define here, unconditionally.
	* libio/iolibio.h (_IO_pos_BAD): Don't define here.
	* libio/libioP.h: Remove #if 0 blocks.
	(_IO_pos_BAD, _IO_pos_0, _IO_pos_adjust): Don't define here.
	(_IO_va_start, COERCE_FILE, MAYBE_SET_EINVAL): Don't define.
	(CHECK_FILE): Don't use MAYBE_SET_EINVAL or COERCE_FILE.  Fix style.

	* libio/clearerr.c, libio/fputc.c, libio/getchar.c:
	Assume weak_alias is always defined.

	* libio/fileops.c, libio/genops.c, libio/oldfileops.c
	* libio/oldpclose.c, libio/pclose.c, libio/wfileops.c:
	Remove #if 0 and #ifdef TODO blocks.
	Assume text_set_element is always defined.

	* libio/iofdopen.c, libio/iogetdelim.c, libio/oldiofdopen.c
	Use __set_errno (EINVAL) instead of MAYBE_SET_EINVAL.
	* libio/tst-mmap-eofsync.c: Make #if 1 block unconditional.
2018-02-21 14:39:54 -05:00

128 lines
3.5 KiB
C

/* Copyright (C) 1994-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>.
As a special exception, if you link the code in this file with
files compiled with a GNU compiler to produce an executable,
that does not cause the resulting executable to be covered by
the GNU Lesser General Public License. This exception does not
however invalidate any other reasons why the executable file
might be covered by the GNU Lesser General Public License.
This exception applies to code released by its copyright holders
in files containing the exception. */
#include <stdlib.h>
#include "libioP.h"
#include <string.h>
#include <errno.h>
#include <limits.h>
/* Read up to (and including) a TERMINATOR from FP into *LINEPTR
(and null-terminate it). *LINEPTR is a pointer returned from malloc (or
NULL), pointing to *N characters of space. It is realloc'ed as
necessary. Returns the number of characters read (not including the
null terminator), or -1 on error or EOF. */
ssize_t
_IO_getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
{
ssize_t result;
ssize_t cur_len = 0;
ssize_t len;
if (lineptr == NULL || n == NULL)
{
__set_errno (EINVAL);
return -1;
}
CHECK_FILE (fp, -1);
_IO_acquire_lock (fp);
if (_IO_ferror_unlocked (fp))
{
result = -1;
goto unlock_return;
}
if (*lineptr == NULL || *n == 0)
{
*n = 120;
*lineptr = (char *) malloc (*n);
if (*lineptr == NULL)
{
result = -1;
goto unlock_return;
}
}
len = fp->_IO_read_end - fp->_IO_read_ptr;
if (len <= 0)
{
if (__underflow (fp) == EOF)
{
result = -1;
goto unlock_return;
}
len = fp->_IO_read_end - fp->_IO_read_ptr;
}
for (;;)
{
size_t needed;
char *t;
t = (char *) memchr ((void *) fp->_IO_read_ptr, delimiter, len);
if (t != NULL)
len = (t - fp->_IO_read_ptr) + 1;
if (__glibc_unlikely (len >= SSIZE_MAX - cur_len))
{
__set_errno (EOVERFLOW);
result = -1;
goto unlock_return;
}
/* Make enough space for len+1 (for final NUL) bytes. */
needed = cur_len + len + 1;
if (needed > *n)
{
char *new_lineptr;
if (needed < 2 * *n)
needed = 2 * *n; /* Be generous. */
new_lineptr = (char *) realloc (*lineptr, needed);
if (new_lineptr == NULL)
{
result = -1;
goto unlock_return;
}
*lineptr = new_lineptr;
*n = needed;
}
memcpy (*lineptr + cur_len, (void *) fp->_IO_read_ptr, len);
fp->_IO_read_ptr += len;
cur_len += len;
if (t != NULL || __underflow (fp) == EOF)
break;
len = fp->_IO_read_end - fp->_IO_read_ptr;
}
(*lineptr)[cur_len] = '\0';
result = cur_len;
unlock_return:
_IO_release_lock (fp);
return result;
}
weak_alias (_IO_getdelim, __getdelim)
weak_alias (_IO_getdelim, getdelim)