(root)/
glibc-2.38/
libio/
memstream.c
       1  /* Copyright (C) 1995-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library 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 GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include "libioP.h"
      19  #include "strfile.h"
      20  #include <stdio.h>
      21  #include <stdlib.h>
      22  
      23  
      24  struct _IO_FILE_memstream
      25  {
      26    _IO_strfile _sf;
      27    char **bufloc;
      28    size_t *sizeloc;
      29  };
      30  
      31  
      32  /* Open a stream that writes into a malloc'd buffer that is expanded as
      33     necessary.  *BUFLOC and *SIZELOC are updated with the buffer's location
      34     and the number of characters written on fflush or fclose.  */
      35  FILE *
      36  __open_memstream (char **bufloc, size_t *sizeloc)
      37  {
      38    struct locked_FILE
      39    {
      40      struct _IO_FILE_memstream fp;
      41  #ifdef _IO_MTSAFE_IO
      42      _IO_lock_t lock;
      43  #endif
      44      struct _IO_wide_data wd;
      45    } *new_f;
      46    char *buf;
      47  
      48    new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
      49    if (new_f == NULL)
      50      return NULL;
      51  #ifdef _IO_MTSAFE_IO
      52    new_f->fp._sf._sbf._f._lock = &new_f->lock;
      53  #endif
      54  
      55    buf = calloc (1, BUFSIZ);
      56    if (buf == NULL)
      57      {
      58        free (new_f);
      59        return NULL;
      60      }
      61    _IO_init_internal (&new_f->fp._sf._sbf._f, 0);
      62    _IO_JUMPS_FILE_plus (&new_f->fp._sf._sbf) = &_IO_mem_jumps;
      63    _IO_str_init_static_internal (&new_f->fp._sf, buf, BUFSIZ, buf);
      64    new_f->fp._sf._sbf._f._flags &= ~_IO_USER_BUF;
      65    new_f->fp._sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc;
      66    new_f->fp._sf._s._free_buffer_unused = (_IO_free_type) free;
      67  
      68    new_f->fp.bufloc = bufloc;
      69    new_f->fp.sizeloc = sizeloc;
      70  
      71    /* Disable single thread optimization.  BZ 21735.  */
      72    new_f->fp._sf._sbf._f._flags2 |= _IO_FLAGS2_NEED_LOCK;
      73  
      74    return (FILE *) &new_f->fp._sf._sbf;
      75  }
      76  libc_hidden_def (__open_memstream)
      77  weak_alias (__open_memstream, open_memstream)
      78  
      79  
      80  int
      81  _IO_mem_sync (FILE *fp)
      82  {
      83    struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp;
      84  
      85    if (fp->_IO_write_ptr == fp->_IO_write_end)
      86      {
      87        _IO_str_overflow (fp, '\0');
      88        --fp->_IO_write_ptr;
      89      }
      90  
      91    *mp->bufloc = fp->_IO_write_base;
      92    *mp->sizeloc = fp->_IO_write_ptr - fp->_IO_write_base;
      93  
      94    return 0;
      95  }
      96  
      97  
      98  void
      99  _IO_mem_finish (FILE *fp, int dummy)
     100  {
     101    struct _IO_FILE_memstream *mp = (struct _IO_FILE_memstream *) fp;
     102  
     103    *mp->bufloc = (char *) realloc (fp->_IO_write_base,
     104  				  fp->_IO_write_ptr - fp->_IO_write_base + 1);
     105    if (*mp->bufloc != NULL)
     106      {
     107        (*mp->bufloc)[fp->_IO_write_ptr - fp->_IO_write_base] = '\0';
     108        *mp->sizeloc = fp->_IO_write_ptr - fp->_IO_write_base;
     109  
     110        fp->_IO_buf_base = NULL;
     111      }
     112  
     113    _IO_str_finish (fp, 0);
     114  }