(root)/
gzip-1.13/
lib/
fpurge.c
       1  /* Flushing buffers of a FILE stream.
       2     Copyright (C) 2007-2023 Free Software Foundation, Inc.
       3  
       4     This file is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU Lesser General Public License as
       6     published by the Free Software Foundation; either version 2.1 of the
       7     License, or (at your option) any later version.
       8  
       9     This file is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  #include <config.h>
      18  
      19  /* Specification.  */
      20  #include <stdio.h>
      21  
      22  #if HAVE___FPURGE                   /* glibc >= 2.2, Haiku, Solaris >= 7, UnixWare >= 7.1.4.MP4, Cygwin >= 1.7.10, Android API >= 23, musl libc */
      23  # if HAVE_STDIO_EXT_H
      24  #  include <stdio_ext.h>
      25  # endif
      26  #endif
      27  #include <stdlib.h>
      28  
      29  #include "stdio-impl.h"
      30  
      31  int
      32  fpurge (FILE *fp)
      33  {
      34  #if HAVE___FPURGE                   /* glibc >= 2.2, Haiku, Solaris >= 7, UnixWare >= 7.1.4.MP4, Cygwin >= 1.7.10, Android API >= 23, musl libc */
      35  
      36    __fpurge (fp);
      37    /* The __fpurge function does not have a return value.  */
      38    return 0;
      39  
      40  #elif HAVE_FPURGE                   /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin >= 1.7 */
      41  
      42    /* Call the system's fpurge function.  */
      43  # undef fpurge
      44  # if !HAVE_DECL_FPURGE
      45    extern int fpurge (FILE *);
      46  # endif
      47    int result = fpurge (fp);
      48  # if defined __sferror || defined __DragonFly__ || defined __ANDROID__
      49    /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Minix 3, Android */
      50    if (result == 0)
      51      /* Correct the invariants that fpurge broke.
      52         <stdio.h> on BSD systems says:
      53           "The following always hold: if _flags & __SRD, _w is 0."
      54         If this invariant is not fulfilled and the stream is read-write but
      55         currently reading, subsequent putc or fputc calls will write directly
      56         into the buffer, although they shouldn't be allowed to.  */
      57      if ((fp_->_flags & __SRD) != 0)
      58        fp_->_w = 0;
      59  # endif
      60    return result;
      61  
      62  #else
      63  
      64    /* Most systems provide FILE as a struct and the necessary bitmask in
      65       <stdio.h>, because they need it for implementing getc() and putc() as
      66       fast macros.  */
      67  # if defined _IO_EOF_SEEN || defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1
      68    /* GNU libc, BeOS, Haiku, Linux libc5 */
      69    fp->_IO_read_end = fp->_IO_read_ptr;
      70    fp->_IO_write_ptr = fp->_IO_write_base;
      71    /* Avoid memory leak when there is an active ungetc buffer.  */
      72    if (fp->_IO_save_base != NULL)
      73      {
      74        free (fp->_IO_save_base);
      75        fp->_IO_save_base = NULL;
      76      }
      77    return 0;
      78  # elif defined __sferror || defined __DragonFly__ || defined __ANDROID__
      79    /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Minix 3, Android */
      80    fp_->_p = fp_->_bf._base;
      81    fp_->_r = 0;
      82    fp_->_w = ((fp_->_flags & (__SLBF | __SNBF | __SRD)) == 0 /* fully buffered and not currently reading? */
      83               ? fp_->_bf._size
      84               : 0);
      85    /* Avoid memory leak when there is an active ungetc buffer.  */
      86    if (fp_ub._base != NULL)
      87      {
      88        if (fp_ub._base != fp_->_ubuf)
      89          free (fp_ub._base);
      90        fp_ub._base = NULL;
      91      }
      92    return 0;
      93  # elif defined __EMX__              /* emx+gcc */
      94    fp->_ptr = fp->_buffer;
      95    fp->_rcount = 0;
      96    fp->_wcount = 0;
      97    fp->_ungetc_count = 0;
      98    return 0;
      99  # elif defined __minix              /* Minix */
     100    fp->_ptr = fp->_buf;
     101    if (fp->_ptr != NULL)
     102      fp->_count = 0;
     103    return 0;
     104  # elif defined _IOERR               /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, UnixWare, mingw, MSVC, NonStop Kernel, OpenVMS */
     105    fp_->_ptr = fp_->_base;
     106    if (fp_->_ptr != NULL)
     107      fp_->_cnt = 0;
     108    return 0;
     109  # elif defined __UCLIBC__           /* uClibc */
     110  #  ifdef __STDIO_BUFFERS
     111    if (fp->__modeflags & __FLAG_WRITING)
     112      fp->__bufpos = fp->__bufstart;
     113    else if (fp->__modeflags & (__FLAG_READONLY | __FLAG_READING))
     114      fp->__bufpos = fp->__bufread;
     115  #  endif
     116    return 0;
     117  # elif defined __QNX__              /* QNX */
     118    fp->_Rback = fp->_Back + sizeof (fp->_Back);
     119    fp->_Rsave = NULL;
     120    if (fp->_Mode & 0x2000 /* _MWRITE */)
     121      /* fp->_Buf <= fp->_Next <= fp->_Wend */
     122      fp->_Next = fp->_Buf;
     123    else
     124      /* fp->_Buf <= fp->_Next <= fp->_Rend */
     125      fp->_Rend = fp->_Next;
     126    return 0;
     127  # elif defined __MINT__             /* Atari FreeMiNT */
     128    if (fp->__pushed_back)
     129      {
     130        fp->__bufp = fp->__pushback_bufp;
     131        fp->__pushed_back = 0;
     132      }
     133    /* Preserve the current file position.  */
     134    if (fp->__target != -1)
     135      fp->__target += fp->__bufp - fp->__buffer;
     136    fp->__bufp = fp->__buffer;
     137    /* Nothing in the buffer, next getc is nontrivial.  */
     138    fp->__get_limit = fp->__bufp;
     139    /* Nothing in the buffer, next putc is nontrivial.  */
     140    fp->__put_limit = fp->__buffer;
     141    return 0;
     142  # elif defined EPLAN9               /* Plan9 */
     143    fp->rp = fp->wp = fp->lp = fp->buf;
     144    return 0;
     145  # else
     146  #  error "Please port gnulib fpurge.c to your platform! Look at the definitions of fflush, setvbuf and ungetc on your system, then report this to bug-gnulib."
     147  # endif
     148  
     149  #endif
     150  }