]> sourceware.org Git - newlib-cygwin.git/commitdiff
Fix fflush issues.
authorEric Blake <eblake@redhat.com>
Fri, 13 Jul 2007 20:37:53 +0000 (20:37 +0000)
committerEric Blake <eblake@redhat.com>
Fri, 13 Jul 2007 20:37:53 +0000 (20:37 +0000)
* 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.

17 files changed:
newlib/ChangeLog
newlib/libc/include/stdio.h
newlib/libc/stdio/fclose.c
newlib/libc/stdio/fflush.c
newlib/libc/stdio/freopen.c
newlib/libc/stdio/fseek.c
newlib/libc/stdio/ftell.c
newlib/libc/stdio/fvwrite.c
newlib/libc/stdio/refill.c
newlib/libc/stdio/setvbuf.c
newlib/libc/stdio/ungetc.c
newlib/libc/stdio/vfprintf.c
newlib/libc/stdio/wbuf.c
newlib/libc/stdio64/freopen64.c
newlib/libc/stdio64/fseeko64.c
newlib/libc/stdio64/ftello64.c
newlib/libc/stdio64/tmpfile64.c

index 5f0b3b4994e145d40f3936af34bf5b66c6f0753c..47f0e30f242f65c4581382531f9603461a2603a6 100644 (file)
@@ -1,5 +1,25 @@
 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.
+
        Documentation updates.
        * libc/stdio/ungetc.c: Document ungetc.
        * libc/stdio/Makefile.am (CHEWOUT_FILES): Sort, match current list
index babb1c3c580d22ab493cc7e210a4664f0c1ef358..b387a445556b9aaf088f5779381e3bf4e30c1900 100644 (file)
@@ -348,12 +348,13 @@ int       _EXFUN(_dprintf_r, (struct _reent *, int, const char *, ...)
 int    _EXFUN(_fclose_r, (struct _reent *, FILE *));
 int    _EXFUN(_fcloseall_r, (struct _reent *));
 FILE * _EXFUN(_fdopen_r, (struct _reent *, int, const char *));
-FILE * _EXFUN(_fopen_r, (struct _reent *, const char *, const char *));
+int    _EXFUN(_fflush_r, (struct _reent *, FILE *));
 char *  _EXFUN(_fgets_r, (struct _reent *, char *, int, FILE *));
 int    _EXFUN(_fiprintf_r, (struct _reent *, FILE *, const char *, ...)
                _ATTRIBUTE ((__format__ (__printf__, 3, 4))));
 int    _EXFUN(_fiscanf_r, (struct _reent *, FILE *, const char *, ...)
                _ATTRIBUTE ((__format__ (__scanf__, 3, 4))));
+FILE * _EXFUN(_fopen_r, (struct _reent *, const char *, const char *));
 int    _EXFUN(_fprintf_r, (struct _reent *, FILE *, const char *, ...)
                _ATTRIBUTE ((__format__ (__printf__, 3, 4))));
 int    _EXFUN(_fputc_r, (struct _reent *, int, FILE *));
index 18cddf0c8035d2b2b409d1fe54fbedc5dba6cf2a..a14a63f3f6da73a8412e913746e87feb2baa926e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1990, 2007 The Regents of the University of California.
+ * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
@@ -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 d375d95098fa8e32ea3a9ded2c166bf8dabfaa13..24bd6c10e7767e580eba8b80187709e09c2ffdb6 100644 (file)
@@ -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 host system.
 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,22 +108,38 @@ _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)
-        {
-          _fpos_t curoff;
-
-          /* 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);
-              if (curoff == -1L)
-                {
-                  _funlockfile (fp);
-                  return 0;
-                }
+      if ((fp->_r > 0 || fp->_ur > 0) && fp->_seek != NULL)
+       {
+         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.
+                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)
+               {
+                 int result = EOF;
+                 if (ptr->_errno == ESPIPE)
+                   result = 0;
+                 else
+                   fp->_flags |= __SERR;
+                 _funlockfile (fp);
+                 return result;
+               }
             }
           if (fp->_flags & __SRD)
             {
@@ -129,17 +149,29 @@ _DEFUN(fflush, (fp),
               if (HASUB (fp))
                 curoff -= fp->_ur;
             }
-          /* Now physically seek to after byte last read.  */
-          if (seekfn (_REENT, fp->_cookie, curoff, SEEK_SET) != -1)
-            {
-              /* Seek successful.  We can clear read buffer now.  */
-              fp->_flags &= ~__SNPT;
-              fp->_r = 0;
-              fp->_p = fp->_bf._base;
-              if (fp->_flags & __SOFF)
-                fp->_offset = curoff;
-            }
-        }
+         /* Now physically seek to after byte last read.  */
+#ifdef __LARGE64_FILES
+         if (fp->_flags & __SL64)
+           tmp = (fp->_seek64 (ptr, fp->_cookie, curoff, SEEK_SET) == curoff);
+         else
+#endif
+           tmp = (fp->_seek (ptr, fp->_cookie, curoff, SEEK_SET) == curoff);
+         if (tmp)
+           {
+             /* Seek successful.  We can clear read buffer now.  */
+             fp->_flags &= ~__SNPT;
+             fp->_r = 0;
+             fp->_p = fp->_bf._base;
+             if (fp->_flags & __SOFF)
+               fp->_offset = curoff;
+           }
+         else
+           {
+             fp->_flags |= __SERR;
+             _funlockfile (fp);
+             return EOF;
+           }
+       }
       _funlockfile (fp);
       return 0;
     }
@@ -161,7 +193,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 +206,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 f6d658c63733e11e8781b362f9d2f97241fedc8c..247f8c6ad30ef87a996c1d49cd1cc52793497117 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1990, 2006, 2007 The Regents of the University of California.
+ * Copyright (c) 1990, 2007 The Regents of the University of California.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
@@ -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 028c62a3fd589630d557f06c2a7d8ed3ab60567f..569bad742ba31f0a6ccc1d48125d510d5c579b3c 100644 (file)
@@ -145,7 +145,7 @@ _DEFUN(_fseek_r, (ptr, fp, offset, whence),
   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, whence),
        * 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, whence),
    */
 
 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 b77879d73a425cf17a6fb574e31b34338872a2d1..2aa10b2c78c45b6595561f3a5e33d20dfc14d5d5 100644 (file)
@@ -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 75fc8347b3b7be4c2df9a136b771d0170cf88e15..d3878dc171e68d84d10a0500e44fdd106acb2c31 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1990, 2006, 2007 The Regents of the University of California.
+ * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
@@ -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 f4644ce962eb29140a637904818d65109bbbaaaf..6b329a852896b118bf02e4d8fa3766cfd93349b4 100644 (file)
@@ -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 561f68b54638ccc6d3ebf952d78132c6a4ab44ac..583a081f4cf80146cc3f278a89cc0cafd72acb2a 100644 (file)
@@ -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 59834ded7bea7d919d1d7e6927dcb729a1cbdbce..d65cddab6c4de28ccd950b2c95b8f7153bd1f117 100644 (file)
@@ -143,7 +143,7 @@ _DEFUN(_ungetc_r, (rptr, c, fp),
         }
       if (fp->_flags & __SWR)
        {
-         if (fflush (fp))
+         if (_fflush_r (rptr, fp))
             {
               _funlockfile (fp);
               return EOF;
index 0c1a47bb6148852e2dcc1d06d3cdb2173f3fe8c3..5bbd7594f7233b50c4e71dfec820b85bcc74c5aa 100644 (file)
@@ -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 ea8f64d8d8202e96b94d7cb57c98eae8fb2287aa..bd7f15d9b9eed596f69eb5da8b3e4113300c891c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1990, 2007 The Regents of the University of California.
+ * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
@@ -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 0362407e9ee8318d639eb249d6cd96f1c16cd1b4..866d8c94362e9b860b048ffc86578fa3686baf7c 100644 (file)
@@ -124,7 +124,7 @@ _DEFUN (_freopen64_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 fe07bfe2de38275cddfd9cd2391b3e7a20c1c55d..280484e6216052434ea70ac08e10fb4e91b8351c 100644 (file)
@@ -111,11 +111,22 @@ _DEFUN (_fseeko64_r, (ptr, fp, offset, whence),
   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, whence),
   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, whence),
        * 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, whence),
    */
 
 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 b596d323443728995368b83e0b41397c95af60ba..2fdfb784e70842b6fe957e1ebd764af294ab2f8c 100644 (file)
@@ -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 511606c78dd6d151d0c318b97d8fa29f285f8178..98a7d78174aa78ecda9f2ae5fce93c0b88cdb3dc 100644 (file)
@@ -48,6 +48,7 @@ Supporting OS subroutines required: <<close>>, <<fstat>>, <<getpid>>,
 */
 
 #include <stdio.h>
+#include <reent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/stat.h>
This page took 0.11318 seconds and 5 git commands to generate.