(root)/
glibc-2.38/
libio/
iofopncook.c
       1  /* Copyright (C) 1993-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     As a special exception, if you link the code in this file with
      19     files compiled with a GNU compiler to produce an executable,
      20     that does not cause the resulting executable to be covered by
      21     the GNU Lesser General Public License.  This exception does not
      22     however invalidate any other reasons why the executable file
      23     might be covered by the GNU Lesser General Public License.
      24     This exception applies to code released by its copyright holders
      25     in files containing the exception.  */
      26  
      27  #include <libioP.h>
      28  #include <stdio.h>
      29  #include <stdlib.h>
      30  #include <shlib-compat.h>
      31  #include <pointer_guard.h>
      32  
      33  ssize_t
      34  _IO_cookie_read (FILE *fp, void *buf, ssize_t size)
      35  {
      36    struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
      37    cookie_read_function_t *read_cb = cfile->__io_functions.read;
      38    PTR_DEMANGLE (read_cb);
      39  
      40    if (read_cb == NULL)
      41      return -1;
      42  
      43    return read_cb (cfile->__cookie, buf, size);
      44  }
      45  
      46  ssize_t
      47  _IO_cookie_write (FILE *fp, const void *buf, ssize_t size)
      48  {
      49    struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
      50    cookie_write_function_t *write_cb = cfile->__io_functions.write;
      51    PTR_DEMANGLE (write_cb);
      52  
      53    if (write_cb == NULL)
      54      {
      55        fp->_flags |= _IO_ERR_SEEN;
      56        return 0;
      57      }
      58  
      59    ssize_t n = write_cb (cfile->__cookie, buf, size);
      60    if (n < size)
      61      fp->_flags |= _IO_ERR_SEEN;
      62  
      63    return n;
      64  }
      65  
      66  off64_t
      67  _IO_cookie_seek (FILE *fp, off64_t offset, int dir)
      68  {
      69    struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
      70    cookie_seek_function_t *seek_cb = cfile->__io_functions.seek;
      71    PTR_DEMANGLE (seek_cb);
      72  
      73    return ((seek_cb == NULL
      74  	   || (seek_cb (cfile->__cookie, &offset, dir)
      75  	       == -1)
      76  	   || offset == (off64_t) -1)
      77  	  ? _IO_pos_BAD : offset);
      78  }
      79  
      80  int
      81  _IO_cookie_close (FILE *fp)
      82  {
      83    struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
      84    cookie_close_function_t *close_cb = cfile->__io_functions.close;
      85    PTR_DEMANGLE (close_cb);
      86  
      87    if (close_cb == NULL)
      88      return 0;
      89  
      90    return close_cb (cfile->__cookie);
      91  }
      92  
      93  
      94  off64_t
      95  _IO_cookie_seekoff (FILE *fp, off64_t offset, int dir, int mode)
      96  {
      97    /* We must force the fileops code to always use seek to determine
      98       the position.  */
      99    fp->_offset = _IO_pos_BAD;
     100    return _IO_file_seekoff (fp, offset, dir, mode);
     101  }
     102  
     103  /* Copy the callbacks from SOURCE to *TARGET, with pointer
     104     mangling.  */
     105  static void
     106  set_callbacks (cookie_io_functions_t *target,
     107  	       cookie_io_functions_t source)
     108  {
     109    PTR_MANGLE (source.read);
     110    PTR_MANGLE (source.write);
     111    PTR_MANGLE (source.seek);
     112    PTR_MANGLE (source.close);
     113    *target = source;
     114  }
     115  
     116  void
     117  _IO_cookie_init (struct _IO_cookie_file *cfile, int read_write,
     118  		 void *cookie, cookie_io_functions_t io_functions)
     119  {
     120    _IO_init_internal (&cfile->__fp.file, 0);
     121    _IO_JUMPS (&cfile->__fp) = &_IO_cookie_jumps;
     122  
     123    cfile->__cookie = cookie;
     124    set_callbacks (&cfile->__io_functions, io_functions);
     125  
     126    _IO_new_file_init_internal (&cfile->__fp);
     127  
     128    _IO_mask_flags (&cfile->__fp.file, read_write,
     129  		  _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
     130  
     131    cfile->__fp.file._flags2 |= _IO_FLAGS2_NEED_LOCK;
     132  
     133    /* We use a negative number different from -1 for _fileno to mark that
     134       this special stream is not associated with a real file, but still has
     135       to be treated as such.  */
     136    cfile->__fp.file._fileno = -2;
     137  }
     138  
     139  
     140  FILE *
     141  _IO_fopencookie (void *cookie, const char *mode,
     142  		 cookie_io_functions_t io_functions)
     143  {
     144    int read_write;
     145    struct locked_FILE
     146    {
     147      struct _IO_cookie_file cfile;
     148  #ifdef _IO_MTSAFE_IO
     149      _IO_lock_t lock;
     150  #endif
     151    } *new_f;
     152  
     153    switch (*mode++)
     154      {
     155      case 'r':
     156        read_write = _IO_NO_WRITES;
     157        break;
     158      case 'w':
     159        read_write = _IO_NO_READS;
     160        break;
     161      case 'a':
     162        read_write = _IO_NO_READS|_IO_IS_APPENDING;
     163        break;
     164      default:
     165        __set_errno (EINVAL);
     166        return NULL;
     167    }
     168    if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+'))
     169      read_write &= _IO_IS_APPENDING;
     170  
     171    new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
     172    if (new_f == NULL)
     173      return NULL;
     174  #ifdef _IO_MTSAFE_IO
     175    new_f->cfile.__fp.file._lock = &new_f->lock;
     176  #endif
     177  
     178    _IO_cookie_init (&new_f->cfile, read_write, cookie, io_functions);
     179  
     180    return (FILE *) &new_f->cfile.__fp;
     181  }
     182  
     183  versioned_symbol (libc, _IO_fopencookie, fopencookie, GLIBC_2_2);
     184  
     185  #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
     186  
     187  off64_t
     188  attribute_compat_text_section
     189  _IO_old_cookie_seek (FILE *fp, off64_t offset, int dir)
     190  {
     191    struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
     192    int (*seek_cb) (FILE *, off_t, int)
     193      = (int (*) (FILE *, off_t, int)) cfile->__io_functions.seek;
     194    PTR_DEMANGLE (seek_cb);
     195  
     196    if (seek_cb == NULL)
     197      return _IO_pos_BAD;
     198  
     199    int ret = seek_cb (cfile->__cookie, offset, dir);
     200  
     201    return (ret == -1) ? _IO_pos_BAD : ret;
     202  }
     203  
     204  FILE *
     205  attribute_compat_text_section
     206  _IO_old_fopencookie (void *cookie, const char *mode,
     207  		     cookie_io_functions_t io_functions)
     208  {
     209    FILE *ret;
     210  
     211    ret = _IO_fopencookie (cookie, mode, io_functions);
     212    if (ret != NULL)
     213      _IO_JUMPS_FILE_plus (ret) = &_IO_old_cookie_jumps;
     214  
     215    return ret;
     216  }
     217  
     218  compat_symbol (libc, _IO_old_fopencookie, fopencookie, GLIBC_2_0);
     219  
     220  #endif