summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <vinschen@redhat.com>2006-12-15 10:02:30 +0000
committerCorinna Vinschen <vinschen@redhat.com>2006-12-15 10:02:30 +0000
commit97fb3ca8a10bfc1ad4730c4be4f2bf0735e26bce (patch)
tree240f847596396665ad2eeccbc2bf622d4ca85351
parent044727956c13217b6fed3f1ee46f842f3d2d5bcd (diff)
downloadgdb-97fb3ca8a10bfc1ad4730c4be4f2bf0735e26bce.tar.gz
* libc/stdio/fflush.c (fflush): On seekable streams, always flush
read but unused data. * libc/stdio/fclose.c (_fclose_r): Always flush streams, since even read streams may have side effects that must happen.
-rw-r--r--newlib/ChangeLog8
-rw-r--r--newlib/libc/stdio/fclose.c122
-rw-r--r--newlib/libc/stdio/fflush.c160
3 files changed, 290 insertions, 0 deletions
diff --git a/newlib/ChangeLog b/newlib/ChangeLog
index f7105e00677..1433fbe7305 100644
--- a/newlib/ChangeLog
+++ b/newlib/ChangeLog
@@ -1,3 +1,11 @@
+2006-12-14 Jeff Johnston <jjohnstn@redhat.com>
+ Eric Blake <ebb9@byu.net>
+
+ * libc/stdio/fflush.c (fflush): On seekable streams, always flush
+ read but unused data.
+ * libc/stdio/fclose.c (_fclose_r): Always flush streams, since
+ even read streams may have side effects that must happen.
+
2006-11-30 Lev Bishop <lev.bishop@gmail.com>
* libc/include/math.h: Allow C99 functions/macros to be
diff --git a/newlib/libc/stdio/fclose.c b/newlib/libc/stdio/fclose.c
new file mode 100644
index 00000000000..76f4140d611
--- /dev/null
+++ b/newlib/libc/stdio/fclose.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+FUNCTION
+<<fclose>>---close a file
+
+INDEX
+ fclose
+INDEX
+ _fclose_r
+
+ANSI_SYNOPSIS
+ #include <stdio.h>
+ int fclose(FILE *<[fp]>);
+ int _fclose_r(struct _reent *<[reent]>, FILE *<[fp]>);
+
+TRAD_SYNOPSIS
+ #include <stdio.h>
+ int fclose(<[fp]>)
+ FILE *<[fp]>;
+
+ int fclose(<[fp]>)
+ struct _reent *<[reent]>
+ FILE *<[fp]>;
+
+DESCRIPTION
+If the file or stream identified by <[fp]> is open, <<fclose>> closes
+it, after first ensuring that any pending data is written (by calling
+<<fflush(<[fp]>)>>).
+
+The alternate function <<_fclose_r>> is a reentrant version.
+The extra argument <[reent]> is a pointer to a reentrancy structure.
+
+RETURNS
+<<fclose>> returns <<0>> if successful (including when <[fp]> is
+<<NULL>> or not an open file); otherwise, it returns <<EOF>>.
+
+PORTABILITY
+<<fclose>> is required by ANSI C.
+
+Required OS subroutines: <<close>>, <<fstat>>, <<isatty>>, <<lseek>>,
+<<read>>, <<sbrk>>, <<write>>.
+*/
+
+#include <_ansi.h>
+#include <reent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/lock.h>
+#include "local.h"
+
+int
+_DEFUN(_fclose_r, (rptr, fp),
+ struct _reent *rptr _AND
+ register FILE * fp)
+{
+ int r;
+
+ if (fp == NULL)
+ return (0); /* on NULL */
+
+ __sfp_lock_acquire ();
+
+ CHECK_INIT (rptr);
+
+ _flockfile (fp);
+
+ if (fp->_flags == 0) /* not open! */
+ {
+ _funlockfile (fp);
+ __sfp_lock_release ();
+ return (0);
+ }
+ /* 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);
+ if (fp->_close != NULL && (*fp->_close) (fp->_cookie) < 0)
+ r = EOF;
+ if (fp->_flags & __SMBF)
+ _free_r (rptr, (char *) fp->_bf._base);
+ if (HASUB (fp))
+ FREEUB (fp);
+ if (HASLB (fp))
+ FREELB (fp);
+ fp->_flags = 0; /* release this FILE for reuse */
+ _funlockfile (fp);
+#ifndef __SINGLE_THREAD__
+ __lock_close_recursive (fp->_lock);
+#endif
+
+ __sfp_lock_release ();
+
+ return (r);
+}
+
+#ifndef _REENT_ONLY
+
+int
+_DEFUN(fclose, (fp),
+ register FILE * fp)
+{
+ return _fclose_r(_REENT, fp);
+}
+
+#endif
+
diff --git a/newlib/libc/stdio/fflush.c b/newlib/libc/stdio/fflush.c
new file mode 100644
index 00000000000..f88d49cc598
--- /dev/null
+++ b/newlib/libc/stdio/fflush.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 1990, 2006 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+FUNCTION
+<<fflush>>---flush buffered file output
+
+INDEX
+ fflush
+
+ANSI_SYNOPSIS
+ #include <stdio.h>
+ int fflush(FILE *<[fp]>);
+
+TRAD_SYNOPSIS
+ #include <stdio.h>
+ int fflush(<[fp]>)
+ FILE *<[fp]>;
+
+DESCRIPTION
+The <<stdio>> output functions can buffer output before delivering it
+to the host system, in order to minimize the overhead of system calls.
+
+Use <<fflush>> to deliver any such pending output (for the file
+or stream identified by <[fp]>) to the host system.
+
+If <[fp]> is <<NULL>>, <<fflush>> delivers pending output from all
+open files.
+
+RETURNS
+<<fflush>> returns <<0>> unless it encounters a write error; in that
+situation, it returns <<EOF>>.
+
+PORTABILITY
+ANSI C requires <<fflush>>.
+
+No supporting OS subroutines are required.
+*/
+
+#include <_ansi.h>
+#include <stdio.h>
+#include "local.h"
+
+/* Flush a single file, or (if fp is NULL) all files. */
+
+int
+_DEFUN(fflush, (fp),
+ register FILE * fp)
+{
+ register unsigned char *p;
+ register int n, t;
+
+ if (fp == NULL)
+ return _fwalk (_GLOBAL_REENT, fflush);
+
+ CHECK_INIT (_REENT);
+
+ _flockfile (fp);
+
+ t = fp->_flags;
+ if ((t & __SWR) == 0)
+ {
+ _fpos_t _EXFUN((*seekfn), (_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. */
+ fp->_flags |= __SNPT;
+
+ /* For a seekable stream with buffered read characters, we will attempt
+ a seek to the current position now. A subsequent read will then get
+ the next byte from the file rather than the buffer. This conforms
+ to the POSIX and SUSv3 standards. Note that the standards allow
+ 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) (fp->_cookie, (_fpos_t) 0, SEEK_CUR);
+ if (curoff == -1L)
+ {
+ _funlockfile (fp);
+ return 0;
+ }
+ }
+ if (fp->_flags & __SRD)
+ {
+ /* Current offset is at end of buffer. Compensate for
+ characters not yet read. */
+ curoff -= fp->_r;
+ if (HASUB (fp))
+ curoff -= fp->_ur;
+ }
+ /* Now physically seek to after byte last read. */
+ if ((*seekfn)(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;
+ }
+ }
+ _funlockfile (fp);
+ return 0;
+ }
+ if ((p = fp->_bf._base) == NULL)
+ {
+ /* Nothing to flush. */
+ _funlockfile (fp);
+ return 0;
+ }
+ n = fp->_p - p; /* write this much */
+
+ /*
+ * Set these immediately to avoid problems with longjmp
+ * and to allow exchange buffering (via setvbuf) in user
+ * write function.
+ */
+ fp->_p = p;
+ fp->_w = t & (__SLBF | __SNBF) ? 0 : fp->_bf._size;
+
+ while (n > 0)
+ {
+ t = (*fp->_write) (fp->_cookie, (char *) p, n);
+ if (t <= 0)
+ {
+ fp->_flags |= __SERR;
+ _funlockfile (fp);
+ return EOF;
+ }
+ p += t;
+ n -= t;
+ }
+ _funlockfile (fp);
+ return 0;
+}