(root)/
glibc-2.38/
stdio-common/
Xprintf_buffer_flush.c
       1  /* Flush wrapper for struct __*printf_buffer.  Generic version.
       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.h>
      20  
      21  #include <assert.h>
      22  #include <stdint.h>
      23  
      24  /* Xprintf (buffer_do_flush) (BUF) performs the flush operation.  The
      25     actual implementation is specific to the multibyte and wide
      26     variants.
      27  
      28     If the flush fails, Xprintf_buffer_mark_failed (BUF) must be
      29     called, and BUF->write_ptr and BUF->write_end can be left
      30     unchanged.
      31  
      32     The function must not do anything if failure has already occurred,
      33     that is, if BUF->mode == Xprintf (buffer_mode_failed).
      34  
      35     The framework implicitly invokes flush with BUF->write_ptr ==
      36     BUF->write_end only.  (This is particularly relevant to the
      37     __sprintf_chk flush, which just calls __chk_fail.)  But in some
      38     cases, Xprintf_buffer_flush may be called explicitly (when
      39     BUF->mode/the backing function is known).  In that case, it is
      40     possible that BUF->write_ptr < BUF->write_end is true.
      41  
      42     If the flush succeeds, the pointers are changed so that
      43     BUF->write_ptr < BUF->write_end.  It is possible to switch to a
      44     completely different buffer here.  If the buffer is moved, it may
      45     be necessary to updated BUF->write_base and BUF->written from the
      46     flush function as well.
      47  
      48     Note that when chaining buffers, in the flush function for the
      49     outer buffer (to which data is written first), it is necessary to
      50     check for BUF->next->failed (for the inner buffer) and set
      51     BUF->base.failed to true (for the outer buffer).  This should come
      52     towards the end of the outer flush function.  Usually, there is
      53     also some unwrapping step afterwards; it has to check the outer
      54     buffer (BUF->base.failed) and propagate any error to the inner
      55     buffer (BUF->next->failed), so essentially in the other
      56     direction.  */
      57  static void Xprintf (buffer_do_flush) (struct Xprintf_buffer *buf);
      58  
      59  bool
      60  Xprintf_buffer_flush (struct Xprintf_buffer *buf)
      61  {
      62    if (__glibc_unlikely (Xprintf_buffer_has_failed (buf)))
      63      return false;
      64  
      65    Xprintf (buffer_do_flush) (buf);
      66    if (Xprintf_buffer_has_failed (buf))
      67      return false;
      68  
      69    /* Ensure that the flush has made available some bytes.  */
      70    assert (buf->write_ptr != buf->write_end);
      71    return true;
      72  }