diff options
author | Corinna Vinschen <vinschen@redhat.com> | 2006-12-15 10:02:30 +0000 |
---|---|---|
committer | Corinna Vinschen <vinschen@redhat.com> | 2006-12-15 10:02:30 +0000 |
commit | 97fb3ca8a10bfc1ad4730c4be4f2bf0735e26bce (patch) | |
tree | 240f847596396665ad2eeccbc2bf622d4ca85351 | |
parent | 044727956c13217b6fed3f1ee46f842f3d2d5bcd (diff) | |
download | gdb-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/ChangeLog | 8 | ||||
-rw-r--r-- | newlib/libc/stdio/fclose.c | 122 | ||||
-rw-r--r-- | newlib/libc/stdio/fflush.c | 160 |
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; +} |