Merge "Switch to upstream OpenBSD fread/fvwrite."
This commit is contained in:
commit
1acd9716c2
4 changed files with 91 additions and 196 deletions
|
@ -75,8 +75,6 @@ libc_common_src_files := \
|
|||
bionic/time64.c \
|
||||
bionic/unlockpt.c \
|
||||
stdio/findfp.c \
|
||||
stdio/fread.c \
|
||||
stdio/fvwrite.c \
|
||||
stdio/snprintf.c\
|
||||
stdio/sprintf.c \
|
||||
stdlib/atexit.c \
|
||||
|
@ -363,12 +361,14 @@ libc_upstream_openbsd_src_files := \
|
|||
upstream-openbsd/lib/libc/stdio/fpurge.c \
|
||||
upstream-openbsd/lib/libc/stdio/fputc.c \
|
||||
upstream-openbsd/lib/libc/stdio/fputs.c \
|
||||
upstream-openbsd/lib/libc/stdio/fread.c \
|
||||
upstream-openbsd/lib/libc/stdio/freopen.c \
|
||||
upstream-openbsd/lib/libc/stdio/fscanf.c \
|
||||
upstream-openbsd/lib/libc/stdio/fseek.c \
|
||||
upstream-openbsd/lib/libc/stdio/fsetpos.c \
|
||||
upstream-openbsd/lib/libc/stdio/ftell.c \
|
||||
upstream-openbsd/lib/libc/stdio/funopen.c \
|
||||
upstream-openbsd/lib/libc/stdio/fvwrite.c \
|
||||
upstream-openbsd/lib/libc/stdio/fwalk.c \
|
||||
upstream-openbsd/lib/libc/stdio/getc.c \
|
||||
upstream-openbsd/lib/libc/stdio/getchar.c \
|
||||
|
|
|
@ -1,175 +0,0 @@
|
|||
/* $OpenBSD: fread.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Chris Torek.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "local.h"
|
||||
|
||||
static int
|
||||
lflush(FILE *fp)
|
||||
{
|
||||
if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
|
||||
return (__sflush_locked(fp));
|
||||
return (0);
|
||||
}
|
||||
|
||||
size_t
|
||||
fread(void *buf, size_t size, size_t count, FILE *fp)
|
||||
{
|
||||
size_t resid;
|
||||
char *p;
|
||||
int r;
|
||||
size_t total;
|
||||
|
||||
/*
|
||||
* The ANSI standard requires a return value of 0 for a count
|
||||
* or a size of 0. Peculiarily, it imposes no such requirements
|
||||
* on fwrite; it only requires fread to be broken.
|
||||
*/
|
||||
if ((resid = count * size) == 0)
|
||||
return (0);
|
||||
FLOCKFILE(fp);
|
||||
if (fp->_r < 0)
|
||||
fp->_r = 0;
|
||||
total = resid;
|
||||
p = buf;
|
||||
|
||||
#if 1 /* BIONIC: optimize unbuffered reads */
|
||||
if (fp->_flags & __SNBF && fp->_ur == 0)
|
||||
{
|
||||
/* the following comes mainly from __srefill(), with slight
|
||||
* modifications
|
||||
*/
|
||||
|
||||
/* make sure stdio is set up */
|
||||
if (!__sdidinit)
|
||||
__sinit();
|
||||
|
||||
fp->_r = 0; /* largely a convenience for callers */
|
||||
|
||||
/* SysV does not make this test; take it out for compatibility */
|
||||
if (fp->_flags & __SEOF) {
|
||||
FUNLOCKFILE(fp);
|
||||
return (EOF);
|
||||
}
|
||||
|
||||
/* if not already reading, have to be reading and writing */
|
||||
if ((fp->_flags & __SRD) == 0) {
|
||||
if ((fp->_flags & __SRW) == 0) {
|
||||
fp->_flags |= __SERR;
|
||||
FUNLOCKFILE(fp);
|
||||
errno = EBADF;
|
||||
return (EOF);
|
||||
}
|
||||
/* switch to reading */
|
||||
if (fp->_flags & __SWR) {
|
||||
if (__sflush(fp)) {
|
||||
FUNLOCKFILE(fp);
|
||||
return (EOF);
|
||||
}
|
||||
fp->_flags &= ~__SWR;
|
||||
fp->_w = 0;
|
||||
fp->_lbfsize = 0;
|
||||
}
|
||||
fp->_flags |= __SRD;
|
||||
} else {
|
||||
/*
|
||||
* We were reading. If there is an ungetc buffer,
|
||||
* we must have been reading from that. Drop it,
|
||||
* restoring the previous buffer (if any). If there
|
||||
* is anything in that buffer, return.
|
||||
*/
|
||||
if (HASUB(fp)) {
|
||||
FREEUB(fp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Before reading from a line buffered or unbuffered file,
|
||||
* flush all line buffered output files, per the ANSI C
|
||||
* standard.
|
||||
*/
|
||||
|
||||
if (fp->_flags & (__SLBF|__SNBF)) {
|
||||
/* Ignore this file in _fwalk to deadlock. */
|
||||
fp->_flags |= __SIGN;
|
||||
(void) _fwalk(lflush);
|
||||
fp->_flags &= ~__SIGN;
|
||||
|
||||
/* Now flush this file without locking it. */
|
||||
if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
|
||||
__sflush(fp);
|
||||
}
|
||||
|
||||
while (resid > 0) {
|
||||
int len = (*fp->_read)(fp->_cookie, p, resid );
|
||||
fp->_flags &= ~__SMOD;
|
||||
if (len <= 0) {
|
||||
if (len == 0)
|
||||
fp->_flags |= __SEOF;
|
||||
else {
|
||||
fp->_flags |= __SERR;
|
||||
}
|
||||
FUNLOCKFILE(fp);
|
||||
return ((total - resid) / size);
|
||||
}
|
||||
p += len;
|
||||
resid -= len;
|
||||
}
|
||||
FUNLOCKFILE(fp);
|
||||
return (count);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
while (resid > (size_t)(r = fp->_r)) {
|
||||
(void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
|
||||
fp->_p += r;
|
||||
/* fp->_r = 0 ... done in __srefill */
|
||||
p += r;
|
||||
resid -= r;
|
||||
if (__srefill(fp)) {
|
||||
/* no more input: return partial result */
|
||||
FUNLOCKFILE(fp);
|
||||
return ((total - resid) / size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(void)memcpy((void *)p, (void *)fp->_p, resid);
|
||||
fp->_r -= resid;
|
||||
fp->_p += resid;
|
||||
FUNLOCKFILE(fp);
|
||||
return (count);
|
||||
}
|
74
libc/upstream-openbsd/lib/libc/stdio/fread.c
Normal file
74
libc/upstream-openbsd/lib/libc/stdio/fread.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* $OpenBSD: fread.c,v 1.11 2009/11/21 09:53:44 guenther Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Chris Torek.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "local.h"
|
||||
|
||||
size_t
|
||||
fread(void *buf, size_t size, size_t count, FILE *fp)
|
||||
{
|
||||
size_t resid;
|
||||
char *p;
|
||||
int r;
|
||||
size_t total;
|
||||
|
||||
/*
|
||||
* ANSI and SUSv2 require a return value of 0 if size or count are 0.
|
||||
*/
|
||||
if ((resid = count * size) == 0)
|
||||
return (0);
|
||||
FLOCKFILE(fp);
|
||||
_SET_ORIENTATION(fp, -1);
|
||||
if (fp->_r < 0)
|
||||
fp->_r = 0;
|
||||
total = resid;
|
||||
p = buf;
|
||||
while (resid > (r = fp->_r)) {
|
||||
(void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
|
||||
fp->_p += r;
|
||||
/* fp->_r = 0 ... done in __srefill */
|
||||
p += r;
|
||||
resid -= r;
|
||||
if (__srefill(fp)) {
|
||||
/* no more input: return partial result */
|
||||
FUNLOCKFILE(fp);
|
||||
return ((total - resid) / size);
|
||||
}
|
||||
}
|
||||
(void)memcpy((void *)p, (void *)fp->_p, resid);
|
||||
fp->_r -= resid;
|
||||
fp->_p += resid;
|
||||
FUNLOCKFILE(fp);
|
||||
return (count);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: fvwrite.c,v 1.14 2005/08/08 08:05:36 espie Exp $ */
|
||||
/* $OpenBSD: fvwrite.c,v 1.17 2009/11/09 00:18:27 kurt Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
|
@ -44,11 +44,11 @@
|
|||
* This routine is large and unsightly, but most of the ugliness due
|
||||
* to the three different kinds of output buffering is handled here.
|
||||
*/
|
||||
__LIBC_HIDDEN__ int
|
||||
int
|
||||
__sfvwrite(FILE *fp, struct __suio *uio)
|
||||
{
|
||||
size_t len;
|
||||
const char *p;
|
||||
char *p;
|
||||
struct __siov *iov;
|
||||
int w, s;
|
||||
char *nl;
|
||||
|
@ -82,11 +82,7 @@ __sfvwrite(FILE *fp, struct __suio *uio)
|
|||
*/
|
||||
do {
|
||||
GETIOV(;);
|
||||
#if 1 /* BIONIC: don't limit to 1KB writes */
|
||||
w = (*fp->_write)(fp->_cookie, p, len);
|
||||
#else
|
||||
w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ2));
|
||||
#endif
|
||||
w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ));
|
||||
if (w <= 0)
|
||||
goto err;
|
||||
p += w;
|
||||
|
@ -107,7 +103,7 @@ __sfvwrite(FILE *fp, struct __suio *uio)
|
|||
do {
|
||||
GETIOV(;);
|
||||
if ((fp->_flags & (__SALC | __SSTR)) ==
|
||||
(__SALC | __SSTR) && fp->_w < (int)len) {
|
||||
(__SALC | __SSTR) && fp->_w < len) {
|
||||
size_t blen = fp->_p - fp->_bf._base;
|
||||
unsigned char *_base;
|
||||
int _size;
|
||||
|
@ -116,7 +112,7 @@ __sfvwrite(FILE *fp, struct __suio *uio)
|
|||
_size = fp->_bf._size;
|
||||
do {
|
||||
_size = (_size << 1) + 1;
|
||||
} while (_size < (int)(blen + len));
|
||||
} while (_size < blen + len);
|
||||
_base = realloc(fp->_bf._base, _size + 1);
|
||||
if (_base == NULL)
|
||||
goto err;
|
||||
|
@ -127,20 +123,20 @@ __sfvwrite(FILE *fp, struct __suio *uio)
|
|||
}
|
||||
w = fp->_w;
|
||||
if (fp->_flags & __SSTR) {
|
||||
if ((int)len < w)
|
||||
if (len < w)
|
||||
w = len;
|
||||
COPY(w); /* copy MIN(fp->_w,len), */
|
||||
fp->_w -= w;
|
||||
fp->_p += w;
|
||||
w = len; /* but pretend copied all */
|
||||
} else if (fp->_p > fp->_bf._base && (int)len > w) {
|
||||
} else if (fp->_p > fp->_bf._base && len > w) {
|
||||
/* fill and flush */
|
||||
COPY(w);
|
||||
/* fp->_w -= w; */ /* unneeded */
|
||||
fp->_p += w;
|
||||
if (fflush(fp))
|
||||
if (__sflush(fp))
|
||||
goto err;
|
||||
} else if ((int)len >= (w = fp->_bf._size)) {
|
||||
} else if (len >= (w = fp->_bf._size)) {
|
||||
/* write directly */
|
||||
w = (*fp->_write)(fp->_cookie, p, w);
|
||||
if (w <= 0)
|
||||
|
@ -169,21 +165,21 @@ __sfvwrite(FILE *fp, struct __suio *uio)
|
|||
GETIOV(nlknown = 0);
|
||||
if (!nlknown) {
|
||||
nl = memchr((void *)p, '\n', len);
|
||||
nldist = nl ? nl + 1 - p : (int)len + 1;
|
||||
nldist = nl ? nl + 1 - p : len + 1;
|
||||
nlknown = 1;
|
||||
}
|
||||
s = MIN((int)len, nldist);
|
||||
s = MIN(len, nldist);
|
||||
w = fp->_w + fp->_bf._size;
|
||||
if (fp->_p > fp->_bf._base && s > w) {
|
||||
COPY(w);
|
||||
/* fp->_w -= w; */
|
||||
fp->_p += w;
|
||||
if (fflush(fp))
|
||||
if (__sflush(fp))
|
||||
goto err;
|
||||
} else if (s >= (w = fp->_bf._size)) {
|
||||
w = (*fp->_write)(fp->_cookie, p, w);
|
||||
if (w <= 0)
|
||||
goto err;
|
||||
goto err;
|
||||
} else {
|
||||
w = s;
|
||||
COPY(w);
|
||||
|
@ -192,7 +188,7 @@ __sfvwrite(FILE *fp, struct __suio *uio)
|
|||
}
|
||||
if ((nldist -= w) == 0) {
|
||||
/* copied the newline: flush and forget */
|
||||
if (fflush(fp))
|
||||
if (__sflush(fp))
|
||||
goto err;
|
||||
nlknown = 0;
|
||||
}
|
Loading…
Reference in a new issue