(root)/
glibc-2.38/
stdio-common/
printf_buffer_to_file.c
       1  /* Multibyte printf buffers writing data to a FILE * stream.
       2     Copyright (C) 2022-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <printf_buffer_to_file.h>
      20  
      21  #include <assert.h>
      22  #include <array_length.h>
      23  #include <libio/libioP.h>
      24  
      25  /* Switch to the file buffer if possible.  If the file has write_ptr
      26     == write_end, use the stage buffer instead.  */
      27  void
      28  __printf_buffer_to_file_switch (struct __printf_buffer_to_file *buf)
      29  {
      30    if (buf->fp->_IO_write_ptr < buf->fp->_IO_write_end)
      31      {
      32        /* buf->fp has a buffer associated with it, so write directly to
      33           it from now on.  */
      34        buf->base.write_ptr = buf->fp->_IO_write_ptr;
      35        buf->base.write_end = buf->fp->_IO_write_end;
      36      }
      37    else
      38      {
      39        /* Use the staging area if no buffer is available in buf->fp.  */
      40        buf->base.write_ptr = buf->stage;
      41        buf->base.write_end = array_end (buf->stage);
      42      }
      43  
      44    buf->base.write_base = buf->base.write_ptr;
      45  }
      46  
      47  void
      48  __printf_buffer_flush_to_file (struct __printf_buffer_to_file *buf)
      49  {
      50    /* The bytes in the buffer are always consumed.  */
      51    buf->base.written += buf->base.write_ptr - buf->base.write_base;
      52  
      53    if (buf->base.write_end == array_end (buf->stage))
      54      {
      55        /* If the stage buffer is used, make a copy into the file.  The
      56           stage buffer is always consumed fully, even if just partially
      57           written, to ensure that the file stream has all the data.  */
      58        size_t count = buf->base.write_ptr - buf->stage;
      59        if ((size_t) _IO_sputn (buf->fp, buf->stage, count) != count)
      60          {
      61            __printf_buffer_mark_failed (&buf->base);
      62            return;
      63          }
      64        /* buf->fp may have a buffer now.  */
      65        __printf_buffer_to_file_switch (buf);
      66        return;
      67      }
      68    else if (buf->base.write_end == buf->stage + 1)
      69      {
      70        /* Special one-character buffer case.  This is used to avoid
      71           flush-only overflow below.  */
      72        if (buf->base.write_ptr == buf->base.write_end)
      73          {
      74            if (__overflow (buf->fp, (unsigned char) *buf->stage) == EOF)
      75              {
      76                __printf_buffer_mark_failed (&buf->base);
      77                return;
      78              }
      79            __printf_buffer_to_file_switch (buf);
      80          }
      81        /* Else there is nothing to write.  */
      82        return;
      83      }
      84  
      85    /* We have written directly into the buf->fp buffer.  */
      86    assert (buf->base.write_end == buf->fp->_IO_write_end);
      87  
      88    /* Mark the bytes as written.  */
      89    buf->fp->_IO_write_ptr = buf->base.write_ptr;
      90  
      91    if (buf->base.write_ptr == buf->base.write_end)
      92      {
      93        /* The buffer in buf->fp has been filled.  This should just call
      94           __overflow (buf->fp, EOF), but flush-only overflow is obscure
      95           and not always correctly implemented.  See bug 28949.  Be
      96           conservative and switch to a one-character buffer instead, to
      97           obtain one more character for a regular __overflow call.  */
      98        buf->base.write_ptr = buf->stage;
      99        buf->base.write_end = buf->stage + 1;
     100      }
     101    /* The bytes in the file stream were already marked as written above.  */
     102  
     103    buf->base.write_base = buf->base.write_ptr;
     104  }
     105  
     106  void
     107  __printf_buffer_to_file_init (struct __printf_buffer_to_file *buf, FILE *fp)
     108  {
     109    __printf_buffer_init (&buf->base, buf->stage, array_length (buf->stage),
     110                          __printf_buffer_mode_to_file);
     111    buf->fp = fp;
     112    __printf_buffer_to_file_switch (buf);
     113  }
     114  
     115  int
     116  __printf_buffer_to_file_done (struct __printf_buffer_to_file *buf)
     117  {
     118    if (__printf_buffer_has_failed (&buf->base))
     119      return -1;
     120    __printf_buffer_flush_to_file (buf);
     121    return __printf_buffer_done (&buf->base);
     122  }