This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: fseek064 calling fflush on Cygwin


In _fflush_r, please alter fp->_flags prior to unlocking the file instead of just afterwards (two instances below). Other than that, patch is fine.

Thanks,

-- Jeff J.

Eric Blake wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Eric Blake on 6/22/2007 2:26 PM:
So, it would seem that fflush is not 64 bit safe and fseeko64 should not
be calling it, but I'm not sure how to fix it.

In environments with large files, fflush needs to check for __SL64, in which
case it should call fp->_seek64, not fp->_seek.  That clinches it - I need to
complete my patch to make fflush reentrant and 64-bit safe.  I'll hopefully
have something by early next week.

So much for 'early next week'. Here's the full patch - okay to apply?


2007-07-13 Eric Blake <ebb9@byu.net>

	Fix fflush issues.
	* libc/stdio/fflush.c (_fflush_r): New function.
	(fflush): Fix reentrancy and large offset behavior.
	* libc/include/stdio.h (_fflush_r): Add prototype.
	* libc/stdio/fclose.c (_fclose_r): All fflush callers changed.
	* libc/stdio/freopen.c (_freopen_r): Likewise.
	* libc/stdio/fseek.c (_fseek_r): Likewise.
	* libc/stdio/ftell.c (_ftell_r): Likewise.
	* libc/stdio/fvwrite.c (__sfvwrite_r): Likewise.
	* libc/stdio/refill.c (__srefill_r): Likewise.
	* libc/stdio/setvbuf.c (setvbuf): Likewise.
	* libc/stdio/ungetc.c (_ungetc_r): Likewise.
	* libc/stdio/vfprintf.c (__sbprintf): Likewise.
	* libc/stdio/wbuf.c (__swbuf_r): Likewise.
	* libc/stdio64/freopen64.c (_freopen64_r): Likewise.
	* libc/stdio64/fseeko64.c (_fseeko64_r): Likewise.  Defer to
	32-bit version if not large file.
	* libc/stdio64/ftello64.c (_ftello64_r): Likewise.
	* libc/stdio64/tmpfile64.c (_tmpfile64_r): Avoid compile warning.

- --
Don't work too hard, make some time for fun as well!

Eric Blake             ebb9@byu.net
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFGl7zT84KuGfSFAYARAjyXAKCL7Cls9L3+NapyKM63j18l24ki7wCgjDSA
pK+NaaEnit0ZGUo0nHMzFC8=
=AgZb
-----END PGP SIGNATURE-----


------------------------------------------------------------------------


Index: libc/stdio/fflush.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fflush.c,v
retrieving revision 1.10
diff -u -p -r1.10 fflush.c
--- libc/stdio/fflush.c 4 Jun 2007 18:10:17 -0000 1.10
+++ libc/stdio/fflush.c 13 Jul 2007 15:42:31 -0000
@@ -26,10 +26,7 @@ ANSI_SYNOPSIS
#include <stdio.h>
int fflush(FILE *<[fp]>);
-TRAD_SYNOPSIS
- #include <stdio.h>
- int fflush(<[fp]>)
- FILE *<[fp]>;
+ int _fflush_r(struct _reent *<[reent]>, FILE *<[fp]>);
DESCRIPTION
The <<stdio>> output functions can buffer output before delivering it
@@ -41,32 +38,41 @@ or stream identified by <[fp]>) to the h
If <[fp]> is <<NULL>>, <<fflush>> delivers pending output from all
open files.
+Additionally, if <[fp]> is a seekable input stream visiting a file
+descriptor, set the position of the file descriptor to match next
+unread byte, useful for obeying POSIX semantics when ending a process
+without consuming all input from the stream.
+
+The alternate function <<_fflush_r>> is a reentrant version, where the
+extra argument <[reent]> is a pointer to a reentrancy structure, and
+<[fp]> must not be NULL.
+
RETURNS
<<fflush>> returns <<0>> unless it encounters a write error; in that
situation, it returns <<EOF>>.
PORTABILITY
-ANSI C requires <<fflush>>.
+ANSI C requires <<fflush>>. The behavior on input streams is only
+specified by POSIX, and not all implementations follow POSIX rules.
No supporting OS subroutines are required.
*/
#include <_ansi.h>
#include <stdio.h>
+#include <errno.h>
#include "local.h"
/* Flush a single file, or (if fp is NULL) all files. */
int
-_DEFUN(fflush, (fp),
+_DEFUN(_fflush_r, (ptr, fp),
+ struct _reent *ptr _AND
register FILE * fp)
{
register unsigned char *p;
register int n, t;
- if (fp == NULL)
- return _fwalk (_GLOBAL_REENT, fflush);
-
#ifdef _REENT_SMALL
/* For REENT_SMALL platforms, it is possible we are being
called for the first time on a std stream. This std
@@ -83,15 +89,13 @@ _DEFUN(fflush, (fp),
return 0;
#endif /* _REENT_SMALL */
- CHECK_INIT (_REENT, fp);
+ CHECK_INIT (ptr, fp);
_flockfile (fp);
t = fp->_flags;
if ((t & __SWR) == 0)
{
- _fpos_t _EXFUN((*seekfn), (struct _reent *, _PTR, _fpos_t, int));
-
/* For a read stream, an fflush causes the next seek to be
unoptimized (i.e. forces a system-level seek). This conforms
to the POSIX and SUSv3 standards. */
@@ -104,21 +108,35 @@ _DEFUN(fflush, (fp),
this seek to be deferred until necessary, but we choose to do it here
to make the change simpler, more contained, and less likely
to miss a code scenario. */
- if ((fp->_r > 0 || fp->_ur > 0) && (seekfn = fp->_seek) != NULL)
+ if ((fp->_r > 0 || fp->_ur > 0) && fp->_seek != NULL)
{
- _fpos_t curoff;
+ int tmp;
+#ifdef __LARGE64_FILES
+ _fpos64_t curoff;
+#else
+ _fpos_t curoff;
+#endif
/* Get the physical position we are at in the file. */
if (fp->_flags & __SOFF)
curoff = fp->_offset;
else
{
- /* We don't know current physical offset, so ask for it. */
- curoff = seekfn (_REENT, fp->_cookie, (_fpos_t) 0, SEEK_CUR);
+ /* We don't know current physical offset, so ask for it.
+ Only ESPIPE is ignorable. */
+#ifdef __LARGE64_FILES
+ if (fp->_flags & __SL64)
+ curoff = fp->_seek64 (ptr, fp->_cookie, 0, SEEK_CUR);
+ else
+#endif
+ curoff = fp->_seek (ptr, fp->_cookie, 0, SEEK_CUR);
if (curoff == -1L)
{
_funlockfile (fp);
- return 0;
+ if (ptr->_errno == ESPIPE)
+ return 0;
+ fp->_flags |= __SERR;
+ return EOF;
}
}
if (fp->_flags & __SRD)
@@ -130,7 +148,13 @@ _DEFUN(fflush, (fp),
curoff -= fp->_ur;
}
/* Now physically seek to after byte last read. */
- if (seekfn (_REENT, fp->_cookie, curoff, SEEK_SET) != -1)
+#ifdef __LARGE64_FILES
+ if (fp->_flags & __SL64)
+ tmp = fp->_seek64 (ptr, fp->_cookie, curoff, SEEK_SET);
+ else
+#endif
+ tmp = fp->_seek (ptr, fp->_cookie, curoff, SEEK_SET);
+ if (tmp == 0)
{
/* Seek successful. We can clear read buffer now. */
fp->_flags &= ~__SNPT;
@@ -139,6 +163,12 @@ _DEFUN(fflush, (fp),
if (fp->_flags & __SOFF)
fp->_offset = curoff;
}
+ else
+ {
+ _funlockfile (fp);
+ fp->_flags |= __SERR;
+ return EOF;
+ }
}
_funlockfile (fp);
return 0;
@@ -161,7 +191,7 @@ _DEFUN(fflush, (fp),
while (n > 0)
{
- t = fp->_write (_REENT, fp->_cookie, (char *) p, n);
+ t = fp->_write (ptr, fp->_cookie, (char *) p, n);
if (t <= 0)
{
fp->_flags |= __SERR;
@@ -174,3 +204,17 @@ _DEFUN(fflush, (fp),
_funlockfile (fp);
return 0;
}
+
+#ifndef _REENT_ONLY
+
+int
+_DEFUN(fflush, (fp),
+ register FILE * fp)
+{
+ if (fp == NULL)
+ return _fwalk_reent (_GLOBAL_REENT, _fflush_r);
+
+ return _fflush_r (_REENT, fp);
+}
+
+#endif /* _REENT_ONLY */
Index: libc/stdio/fclose.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fclose.c,v
retrieving revision 1.14
diff -u -p -r1.14 fclose.c
--- libc/stdio/fclose.c 4 Jun 2007 18:10:17 -0000 1.14
+++ libc/stdio/fclose.c 13 Jul 2007 15:30:44 -0000
@@ -89,7 +89,7 @@ _DEFUN(_fclose_r, (rptr, fp),
/* Unconditionally flush to allow special handling for seekable read
files to reposition file to last byte processed as opposed to
last byte read ahead into the buffer. */
- r = fflush (fp);
+ r = _fflush_r (rptr, fp);
if (fp->_close != NULL && fp->_close (rptr, fp->_cookie) < 0)
r = EOF;
if (fp->_flags & __SMBF)
Index: libc/stdio/freopen.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/freopen.c,v
retrieving revision 1.20
diff -u -p -r1.20 freopen.c
--- libc/stdio/freopen.c 4 Jun 2007 18:10:17 -0000 1.20
+++ libc/stdio/freopen.c 13 Jul 2007 15:30:44 -0000
@@ -124,7 +124,7 @@ _DEFUN(_freopen_r, (ptr, file, mode, fp)
else
{
if (fp->_flags & __SWR)
- fflush (fp);
+ _fflush_r (ptr, fp);
/*
* If close is NULL, closing is a no-op, hence pointless.
* If file is NULL, the file should not be closed.
Index: libc/stdio/fseek.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fseek.c,v
retrieving revision 1.17
diff -u -p -r1.17 fseek.c
--- libc/stdio/fseek.c 4 Jun 2007 18:10:17 -0000 1.17
+++ libc/stdio/fseek.c 13 Jul 2007 15:30:49 -0000
@@ -145,7 +145,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whenc
if (fp->_flags & __SAPP && fp->_flags & __SWR)
{
/* So flush the buffer and seek to the end. */
- fflush (fp);
+ _fflush_r (ptr, fp);
}
/* Have to be able to seek. */
@@ -170,7 +170,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whenc
* we have to first find the current stream offset a la
* ftell (see ftell for details).
*/
- fflush (fp); /* may adjust seek offset on append stream */
+ _fflush_r (ptr, fp); /* may adjust seek offset on append stream */
if (fp->_flags & __SOFF)
curoff = fp->_offset;
else
@@ -356,7 +356,8 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whenc
*/
dumb:
- if (fflush (fp) || seekfn (ptr, fp->_cookie, offset, whence) == POS_ERR)
+ if (_fflush_r (ptr, fp)
+ || seekfn (ptr, fp->_cookie, offset, whence) == POS_ERR)
{
_funlockfile (fp);
return EOF;
Index: libc/stdio/ftell.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/ftell.c,v
retrieving revision 1.11
diff -u -p -r1.11 ftell.c
--- libc/stdio/ftell.c 4 Jun 2007 18:10:17 -0000 1.11
+++ libc/stdio/ftell.c 13 Jul 2007 15:30:49 -0000
@@ -120,7 +120,7 @@ _DEFUN(_ftell_r, (ptr, fp),
/* Find offset of underlying I/O object, then
adjust for buffered bytes. */
- fflush(fp); /* may adjust seek offset on append stream */
+ _fflush_r (ptr, fp); /* may adjust seek offset on append stream */
if (fp->_flags & __SOFF)
pos = fp->_offset;
else
Index: libc/stdio/fvwrite.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fvwrite.c,v
retrieving revision 1.13
diff -u -p -r1.13 fvwrite.c
--- libc/stdio/fvwrite.c 4 Jun 2007 18:10:17 -0000 1.13
+++ libc/stdio/fvwrite.c 13 Jul 2007 15:30:49 -0000
@@ -185,7 +185,7 @@ _DEFUN(__sfvwrite_r, (ptr, fp, uio),
COPY (w);
/* fp->_w -= w; *//* unneeded */
fp->_p += w;
- if (fflush (fp))
+ if (_fflush_r (ptr, fp))
goto err;
}
else if (len >= (w = fp->_bf._size))
@@ -235,7 +235,7 @@ _DEFUN(__sfvwrite_r, (ptr, fp, uio),
COPY (w);
/* fp->_w -= w; */
fp->_p += w;
- if (fflush (fp))
+ if (_fflush_r (ptr, fp))
goto err;
}
else if (s >= (w = fp->_bf._size))
@@ -254,7 +254,7 @@ _DEFUN(__sfvwrite_r, (ptr, fp, uio),
if ((nldist -= w) == 0)
{
/* copied the newline: flush and forget */
- if (fflush (fp))
+ if (_fflush_r (ptr, fp))
goto err;
nlknown = 0;
}
Index: libc/stdio/refill.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/refill.c,v
retrieving revision 1.10
diff -u -p -r1.10 refill.c
--- libc/stdio/refill.c 4 Jun 2007 18:10:17 -0000 1.10
+++ libc/stdio/refill.c 13 Jul 2007 15:30:49 -0000
@@ -65,7 +65,7 @@ _DEFUN(__srefill_r, (ptr, fp),
/* switch to reading */
if (fp->_flags & __SWR)
{
- if (fflush (fp))
+ if (_fflush_r (ptr, fp))
return EOF;
fp->_flags &= ~__SWR;
fp->_w = 0;
Index: libc/stdio/setvbuf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/setvbuf.c,v
retrieving revision 1.6
diff -u -p -r1.6 setvbuf.c
--- libc/stdio/setvbuf.c 26 Sep 2006 21:22:19 -0000 1.6
+++ libc/stdio/setvbuf.c 13 Jul 2007 15:30:49 -0000
@@ -126,7 +126,7 @@ _DEFUN(setvbuf, (fp, buf, mode, size),
* non buffer flags, and clear malloc flag.
*/
- _CAST_VOID fflush (fp);
+ _fflush_r (_REENT, fp);
fp->_r = 0;
fp->_lbfsize = 0;
if (fp->_flags & __SMBF)
Index: libc/stdio/ungetc.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/ungetc.c,v
retrieving revision 1.7
diff -u -p -r1.7 ungetc.c
--- libc/stdio/ungetc.c 26 Sep 2006 21:22:19 -0000 1.7
+++ libc/stdio/ungetc.c 13 Jul 2007 15:30:49 -0000
@@ -101,7 +101,7 @@ _DEFUN(_ungetc_r, (rptr, c, fp),
}
if (fp->_flags & __SWR)
{
- if (fflush (fp))
+ if (_fflush_r (rptr, fp))
{
_funlockfile (fp);
return EOF;
Index: libc/stdio/vfprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vfprintf.c,v
retrieving revision 1.63
diff -u -p -r1.63 vfprintf.c
--- libc/stdio/vfprintf.c 27 May 2007 14:19:15 -0000 1.63
+++ libc/stdio/vfprintf.c 13 Jul 2007 15:30:52 -0000
@@ -212,7 +212,7 @@ _DEFUN(__sbprintf, (rptr, fp, fmt, ap),
/* do the work, then copy any error status */
ret = _VFPRINTF_R (rptr, &fake, fmt, ap);
- if (ret >= 0 && fflush(&fake))
+ if (ret >= 0 && _fflush_r (rptr, &fake))
ret = EOF;
if (fake._flags & __SERR)
fp->_flags |= __SERR;
Index: libc/stdio/wbuf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/wbuf.c,v
retrieving revision 1.7
diff -u -p -r1.7 wbuf.c
--- libc/stdio/wbuf.c 15 Mar 2007 18:40:48 -0000 1.7
+++ libc/stdio/wbuf.c 13 Jul 2007 15:30:52 -0000
@@ -74,14 +74,14 @@ _DEFUN(__swbuf_r, (ptr, c, fp),
n = fp->_p - fp->_bf._base;
if (n >= fp->_bf._size)
{
- if (fflush (fp))
+ if (_fflush_r (ptr, fp))
return EOF;
n = 0;
}
fp->_w--;
*fp->_p++ = c;
if (++n == fp->_bf._size || (fp->_flags & __SLBF && c == '\n'))
- if (fflush (fp))
+ if (_fflush_r (ptr, fp))
return EOF;
return c;
}
Index: libc/stdio64/freopen64.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio64/freopen64.c,v
retrieving revision 1.16
diff -u -p -r1.16 freopen64.c
--- libc/stdio64/freopen64.c 4 Jun 2007 18:10:17 -0000 1.16
+++ libc/stdio64/freopen64.c 13 Jul 2007 15:30:52 -0000
@@ -124,7 +124,7 @@ _DEFUN (_freopen64_r, (ptr, file, mode, else
{
if (fp->_flags & __SWR)
- fflush (fp);
+ _fflush_r (ptr, fp);
/*
* If close is NULL, closing is a no-op, hence pointless.
* If file is NULL, the file should not be closed.
Index: libc/stdio64/fseeko64.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio64/fseeko64.c,v
retrieving revision 1.11
diff -u -p -r1.11 fseeko64.c
--- libc/stdio64/fseeko64.c 4 Jun 2007 18:10:17 -0000 1.11
+++ libc/stdio64/fseeko64.c 13 Jul 2007 15:30:52 -0000
@@ -111,11 +111,22 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, w
struct stat64 st;
int havepos;
+ /* Only do 64-bit seek on large file. */
+ if (!(fp->_flags & __SL64))
+ {
+ if ((_off_t) offset != offset)
+ {
+ ptr->_errno = EOVERFLOW;
+ return EOF;
+ }
+ return (_off64_t) _fseeko_r (ptr, fp, offset, whence);
+ }
+
/* Make sure stdio is set up. */
CHECK_INIT (ptr, fp);
- _flockfile(fp);
+ _flockfile (fp);
curoff = fp->_offset;
@@ -125,12 +136,12 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, w
if (fp->_flags & __SAPP && fp->_flags & __SWR)
{
/* So flush the buffer and seek to the end. */
- fflush (fp);
+ _fflush_r (ptr, fp);
}
/* Have to be able to seek. */
- if ((seekfn = fp->_seek64) == NULL || !(fp->_flags & __SL64))
+ if ((seekfn = fp->_seek64) == NULL)
{
ptr->_errno = ESPIPE; /* ??? */
_funlockfile(fp);
@@ -150,7 +161,7 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, w
* we have to first find the current stream offset a la
* ftell (see ftell for details).
*/
- fflush(fp); /* may adjust seek offset on append stream */
+ _fflush_r (ptr, fp); /* may adjust seek offset on append stream */
if (fp->_flags & __SOFF)
curoff = fp->_offset;
else
@@ -323,7 +334,8 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, w
*/
dumb:
- if (fflush (fp) || seekfn (ptr, fp->_cookie, offset, whence) == POS_ERR)
+ if (_fflush_r (ptr, fp)
+ || seekfn (ptr, fp->_cookie, offset, whence) == POS_ERR)
{
_funlockfile(fp);
return EOF;
Index: libc/stdio64/ftello64.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio64/ftello64.c,v
retrieving revision 1.7
diff -u -p -r1.7 ftello64.c
--- libc/stdio64/ftello64.c 4 Jun 2007 18:10:17 -0000 1.7
+++ libc/stdio64/ftello64.c 13 Jul 2007 15:30:52 -0000
@@ -91,6 +91,10 @@ _DEFUN (_ftello64_r, (ptr, fp),
{
_fpos64_t pos;
+ /* Only do 64-bit tell on large file. */
+ if (!(fp->_flags & __SL64))
+ return (_off64_t) _ftello_r (ptr, fp);
+
/* Ensure stdio is set up. */
CHECK_INIT (ptr, fp);
@@ -106,7 +110,7 @@ _DEFUN (_ftello64_r, (ptr, fp),
/* Find offset of underlying I/O object, then
adjust for buffered bytes. */
- fflush(fp); /* may adjust seek offset on append stream */
+ _fflush_r (ptr, fp); /* may adjust seek offset on append stream */
if (fp->_flags & __SOFF)
pos = fp->_offset;
else
Index: libc/stdio64/tmpfile64.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio64/tmpfile64.c,v
retrieving revision 1.5
diff -u -p -r1.5 tmpfile64.c
--- libc/stdio64/tmpfile64.c 17 May 2007 12:10:29 -0000 1.5
+++ libc/stdio64/tmpfile64.c 13 Jul 2007 15:30:52 -0000
@@ -48,6 +48,7 @@ Supporting OS subroutines required: <<cl
*/
#include <stdio.h>
+#include <reent.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]