Back to index

glibc  2.9
iofopncook.c
Go to the documentation of this file.
00001 /* Copyright (C) 1993,95,97,99,2000,2002,2004, 2005
00002    Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.
00019 
00020    As a special exception, if you link the code in this file with
00021    files compiled with a GNU compiler to produce an executable,
00022    that does not cause the resulting executable to be covered by
00023    the GNU Lesser General Public License.  This exception does not
00024    however invalidate any other reasons why the executable file
00025    might be covered by the GNU Lesser General Public License.
00026    This exception applies to code released by its copyright holders
00027    in files containing the exception.  */
00028 
00029 #include <libioP.h>
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <shlib-compat.h>
00033 
00034 /* Prototyped for local functions.  */
00035 static _IO_ssize_t _IO_cookie_read (register _IO_FILE* fp, void* buf,
00036                                 _IO_ssize_t size);
00037 static _IO_ssize_t _IO_cookie_write (register _IO_FILE* fp,
00038                                  const void* buf, _IO_ssize_t size);
00039 static _IO_off64_t _IO_cookie_seek (_IO_FILE *fp, _IO_off64_t offset, int dir);
00040 static _IO_off64_t _IO_cookie_seekoff (_IO_FILE *fp, _IO_off64_t offset,
00041                                    int dir, int mode);
00042 static int _IO_cookie_close (_IO_FILE* fp);
00043 
00044 static _IO_ssize_t
00045 _IO_cookie_read (fp, buf, size)
00046      _IO_FILE *fp;
00047      void *buf;
00048      _IO_ssize_t size;
00049 {
00050   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
00051 
00052   if (cfile->__io_functions.read == NULL)
00053     return -1;
00054 
00055   return cfile->__io_functions.read (cfile->__cookie, buf, size);
00056 }
00057 
00058 static _IO_ssize_t
00059 _IO_cookie_write (fp, buf, size)
00060      _IO_FILE *fp;
00061      const void *buf;
00062      _IO_ssize_t size;
00063 {
00064   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
00065 
00066   if (cfile->__io_functions.write == NULL)
00067     {
00068       fp->_flags |= _IO_ERR_SEEN;
00069       return 0;
00070     }
00071 
00072   _IO_ssize_t n = cfile->__io_functions.write (cfile->__cookie, buf, size);
00073   if (n < size)
00074     fp->_flags |= _IO_ERR_SEEN;
00075 
00076   return n;
00077 }
00078 
00079 static _IO_off64_t
00080 _IO_cookie_seek (fp, offset, dir)
00081      _IO_FILE *fp;
00082      _IO_off64_t offset;
00083      int dir;
00084 {
00085   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
00086 
00087   return ((cfile->__io_functions.seek == NULL
00088           || (cfile->__io_functions.seek (cfile->__cookie, &offset, dir)
00089               == -1)
00090           || offset == (_IO_off64_t) -1)
00091          ? _IO_pos_BAD : offset);
00092 }
00093 
00094 static int
00095 _IO_cookie_close (fp)
00096      _IO_FILE *fp;
00097 {
00098   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
00099 
00100   if (cfile->__io_functions.close == NULL)
00101     return 0;
00102 
00103   return cfile->__io_functions.close (cfile->__cookie);
00104 }
00105 
00106 
00107 static _IO_off64_t
00108 _IO_cookie_seekoff (fp, offset, dir, mode)
00109      _IO_FILE *fp;
00110      _IO_off64_t offset;
00111      int dir;
00112      int mode;
00113 {
00114   /* We must force the fileops code to always use seek to determine
00115      the position.  */
00116   fp->_offset = _IO_pos_BAD;
00117   return INTUSE(_IO_file_seekoff) (fp, offset, dir, mode);
00118 }
00119 
00120 
00121 static const struct _IO_jump_t _IO_cookie_jumps = {
00122   JUMP_INIT_DUMMY,
00123   JUMP_INIT(finish, INTUSE(_IO_file_finish)),
00124   JUMP_INIT(overflow, INTUSE(_IO_file_overflow)),
00125   JUMP_INIT(underflow, INTUSE(_IO_file_underflow)),
00126   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
00127   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
00128   JUMP_INIT(xsputn, INTUSE(_IO_file_xsputn)),
00129   JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
00130   JUMP_INIT(seekoff, _IO_cookie_seekoff),
00131   JUMP_INIT(seekpos, _IO_default_seekpos),
00132   JUMP_INIT(setbuf, INTUSE(_IO_file_setbuf)),
00133   JUMP_INIT(sync, INTUSE(_IO_file_sync)),
00134   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
00135   JUMP_INIT(read, _IO_cookie_read),
00136   JUMP_INIT(write, _IO_cookie_write),
00137   JUMP_INIT(seek, _IO_cookie_seek),
00138   JUMP_INIT(close, _IO_cookie_close),
00139   JUMP_INIT(stat, _IO_default_stat),
00140   JUMP_INIT(showmanyc, _IO_default_showmanyc),
00141   JUMP_INIT(imbue, _IO_default_imbue),
00142 };
00143 
00144 
00145 void
00146 _IO_cookie_init (struct _IO_cookie_file *cfile, int read_write,
00147                void *cookie, _IO_cookie_io_functions_t io_functions)
00148 {
00149   INTUSE(_IO_init) (&cfile->__fp.file, 0);
00150   _IO_JUMPS (&cfile->__fp) = &_IO_cookie_jumps;
00151 
00152   cfile->__cookie = cookie;
00153   cfile->__io_functions = io_functions;
00154 
00155   INTUSE(_IO_file_init) (&cfile->__fp);
00156 
00157   cfile->__fp.file._IO_file_flags =
00158     _IO_mask_flags (&cfile->__fp.file, read_write,
00159                   _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
00160 
00161   /* We use a negative number different from -1 for _fileno to mark that
00162      this special stream is not associated with a real file, but still has
00163      to be treated as such.  */
00164   cfile->__fp.file._fileno = -2;
00165 }
00166 
00167 
00168 _IO_FILE *
00169 _IO_fopencookie (cookie, mode, io_functions)
00170      void *cookie;
00171      const char *mode;
00172      _IO_cookie_io_functions_t io_functions;
00173 {
00174   int read_write;
00175   struct locked_FILE
00176   {
00177     struct _IO_cookie_file cfile;
00178 #ifdef _IO_MTSAFE_IO
00179     _IO_lock_t lock;
00180 #endif
00181   } *new_f;
00182 
00183   switch (*mode++)
00184     {
00185     case 'r':
00186       read_write = _IO_NO_WRITES;
00187       break;
00188     case 'w':
00189       read_write = _IO_NO_READS;
00190       break;
00191     case 'a':
00192       read_write = _IO_NO_READS|_IO_IS_APPENDING;
00193       break;
00194     default:
00195       return NULL;
00196   }
00197   if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+'))
00198     read_write &= _IO_IS_APPENDING;
00199 
00200   new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
00201   if (new_f == NULL)
00202     return NULL;
00203 #ifdef _IO_MTSAFE_IO
00204   new_f->cfile.__fp.file._lock = &new_f->lock;
00205 #endif
00206 
00207   _IO_cookie_init (&new_f->cfile, read_write, cookie, io_functions);
00208 
00209   return (_IO_FILE *) &new_f->cfile.__fp;
00210 }
00211 
00212 versioned_symbol (libc, _IO_fopencookie, fopencookie, GLIBC_2_2);
00213 
00214 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
00215 
00216 static _IO_off64_t _IO_old_cookie_seek (_IO_FILE *fp, _IO_off64_t offset,
00217                                    int dir);
00218 _IO_FILE * _IO_old_fopencookie (void *cookie, const char *mode,
00219                             _IO_cookie_io_functions_t io_functions);
00220 
00221 static _IO_off64_t
00222 attribute_compat_text_section
00223 _IO_old_cookie_seek (fp, offset, dir)
00224      _IO_FILE *fp;
00225      _IO_off64_t offset;
00226      int dir;
00227 {
00228   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
00229   int (*seek) (_IO_FILE *, _IO_off_t, int);
00230   int ret;
00231 
00232   seek = (int (*)(_IO_FILE *, _IO_off_t, int)) cfile->__io_functions.seek;
00233   if (seek == NULL)
00234     return _IO_pos_BAD;
00235 
00236   ret = seek (cfile->__cookie, offset, dir);
00237 
00238   return (ret == -1) ? _IO_pos_BAD : ret;
00239 }
00240 
00241 static const struct _IO_jump_t _IO_old_cookie_jumps = {
00242   JUMP_INIT_DUMMY,
00243   JUMP_INIT(finish, INTUSE(_IO_file_finish)),
00244   JUMP_INIT(overflow, INTUSE(_IO_file_overflow)),
00245   JUMP_INIT(underflow, INTUSE(_IO_file_underflow)),
00246   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
00247   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
00248   JUMP_INIT(xsputn, INTUSE(_IO_file_xsputn)),
00249   JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
00250   JUMP_INIT(seekoff, _IO_cookie_seekoff),
00251   JUMP_INIT(seekpos, _IO_default_seekpos),
00252   JUMP_INIT(setbuf, INTUSE(_IO_file_setbuf)),
00253   JUMP_INIT(sync, INTUSE(_IO_file_sync)),
00254   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
00255   JUMP_INIT(read, _IO_cookie_read),
00256   JUMP_INIT(write, _IO_cookie_write),
00257   JUMP_INIT(seek, _IO_old_cookie_seek),
00258   JUMP_INIT(close, _IO_cookie_close),
00259   JUMP_INIT(stat, _IO_default_stat),
00260   JUMP_INIT(showmanyc, _IO_default_showmanyc),
00261   JUMP_INIT(imbue, _IO_default_imbue),
00262 };
00263 
00264 _IO_FILE *
00265 attribute_compat_text_section
00266 _IO_old_fopencookie (cookie, mode, io_functions)
00267      void *cookie;
00268      const char *mode;
00269      _IO_cookie_io_functions_t io_functions;
00270 {
00271   _IO_FILE *ret;
00272 
00273   ret = _IO_fopencookie (cookie, mode, io_functions);
00274   if (ret != NULL)
00275     _IO_JUMPS ((struct _IO_FILE_plus *) ret) = &_IO_old_cookie_jumps;
00276 
00277   return ret;
00278 }
00279 
00280 compat_symbol (libc, _IO_old_fopencookie, fopencookie, GLIBC_2_0);
00281 
00282 #endif