Update.
[platform/upstream/glibc.git] / libio / iofopncook.c
1 /* Copyright (C) 1993,95,97,99,2000,2002 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, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.
18
19    As a special exception, if you link the code in this file with
20    files compiled with a GNU compiler to produce an executable,
21    that does not cause the resulting executable to be covered by
22    the GNU Lesser General Public License.  This exception does not
23    however invalidate any other reasons why the executable file
24    might be covered by the GNU Lesser General Public License.
25    This exception applies to code released by its copyright holders
26    in files containing the exception.  */
27
28 #include <libioP.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <shlib-compat.h>
32
33 /* Prototyped for local functions.  */
34 static _IO_ssize_t _IO_cookie_read (register _IO_FILE* fp, void* buf,
35                                     _IO_ssize_t size);
36 static _IO_ssize_t _IO_cookie_write (register _IO_FILE* fp,
37                                      const void* buf, _IO_ssize_t size);
38 static _IO_off64_t _IO_cookie_seek (_IO_FILE *fp, _IO_off64_t offset, int dir);
39 static int _IO_cookie_close (_IO_FILE* fp);
40
41 static _IO_ssize_t
42 _IO_cookie_read (fp, buf, size)
43      _IO_FILE *fp;
44      void *buf;
45      _IO_ssize_t size;
46 {
47   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
48
49   if (cfile->__io_functions.read == NULL)
50     return -1;
51
52   return cfile->__io_functions.read (cfile->__cookie, buf, size);
53 }
54
55 static _IO_ssize_t
56 _IO_cookie_write (fp, buf, size)
57      _IO_FILE *fp;
58      const void *buf;
59      _IO_ssize_t size;
60 {
61   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
62
63   if (cfile->__io_functions.write == NULL)
64     return -1;
65
66   return cfile->__io_functions.write (cfile->__cookie, buf, size);
67 }
68
69 static _IO_off64_t
70 _IO_cookie_seek (fp, offset, dir)
71      _IO_FILE *fp;
72      _IO_off64_t offset;
73      int dir;
74 {
75   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
76
77   return ((cfile->__io_functions.seek == NULL
78            || (cfile->__io_functions.seek (cfile->__cookie, &offset, dir)
79                == -1)
80            || offset == (_IO_off64_t) -1)
81           ? _IO_pos_BAD : offset);
82 }
83
84 static int
85 _IO_cookie_close (fp)
86      _IO_FILE *fp;
87 {
88   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
89
90   if (cfile->__io_functions.close == NULL)
91     return 0;
92
93   return cfile->__io_functions.close (cfile->__cookie);
94 }
95
96
97 static struct _IO_jump_t _IO_cookie_jumps = {
98   JUMP_INIT_DUMMY,
99   JUMP_INIT(finish, INTUSE(_IO_file_finish)),
100   JUMP_INIT(overflow, INTUSE(_IO_file_overflow)),
101   JUMP_INIT(underflow, INTUSE(_IO_file_underflow)),
102   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
103   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
104   JUMP_INIT(xsputn, INTUSE(_IO_file_xsputn)),
105   JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
106   JUMP_INIT(seekoff, INTUSE(_IO_file_seekoff)),
107   JUMP_INIT(seekpos, _IO_default_seekpos),
108   JUMP_INIT(setbuf, INTUSE(_IO_file_setbuf)),
109   JUMP_INIT(sync, INTUSE(_IO_file_sync)),
110   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
111   JUMP_INIT(read, _IO_cookie_read),
112   JUMP_INIT(write, _IO_cookie_write),
113   JUMP_INIT(seek, _IO_cookie_seek),
114   JUMP_INIT(close, _IO_cookie_close),
115   JUMP_INIT(stat, _IO_default_stat),
116   JUMP_INIT(showmanyc, _IO_default_showmanyc),
117   JUMP_INIT(imbue, _IO_default_imbue),
118 };
119
120
121 void
122 _IO_cookie_init (struct _IO_cookie_file *cfile, int read_write,
123                  void *cookie, _IO_cookie_io_functions_t io_functions)
124 {
125   INTUSE(_IO_init) (&cfile->__fp.file, 0);
126   _IO_JUMPS (&cfile->__fp) = &_IO_cookie_jumps;
127
128   cfile->__cookie = cookie;
129   cfile->__io_functions = io_functions;
130
131   INTUSE(_IO_file_init) (&cfile->__fp);
132
133   cfile->__fp.file._IO_file_flags =
134     _IO_mask_flags (&cfile->__fp.file, read_write,
135                     _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
136
137   /* We use a negative number different from -1 for _fileno to mark that
138      this special stream is not associated with a real file, but still has
139      to be treated as such.  */
140   cfile->__fp.file._fileno = -2;
141 }
142
143
144 _IO_FILE *
145 _IO_fopencookie (cookie, mode, io_functions)
146      void *cookie;
147      const char *mode;
148      _IO_cookie_io_functions_t io_functions;
149 {
150   int read_write;
151   struct locked_FILE
152   {
153     struct _IO_cookie_file cfile;
154 #ifdef _IO_MTSAFE_IO
155     _IO_lock_t lock;
156 #endif
157   } *new_f;
158
159   switch (*mode++)
160     {
161     case 'r':
162       read_write = _IO_NO_WRITES;
163       break;
164     case 'w':
165       read_write = _IO_NO_READS;
166       break;
167     case 'a':
168       read_write = _IO_NO_READS|_IO_IS_APPENDING;
169       break;
170     default:
171       return NULL;
172   }
173   if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+'))
174     read_write &= _IO_IS_APPENDING;
175
176   new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
177   if (new_f == NULL)
178     return NULL;
179 #ifdef _IO_MTSAFE_IO
180   new_f->cfile.__fp.file._lock = &new_f->lock;
181 #endif
182
183   _IO_cookie_init (&new_f->cfile, read_write, cookie, io_functions);
184
185   return (_IO_FILE *) &new_f->cfile.__fp;
186 }
187
188 versioned_symbol (libc, _IO_fopencookie, fopencookie, GLIBC_2_2);
189
190 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
191
192 static _IO_off64_t _IO_old_cookie_seek (_IO_FILE *fp, _IO_off64_t offset,
193                                         int dir);
194 _IO_FILE * _IO_old_fopencookie (void *cookie, const char *mode,
195                                 _IO_cookie_io_functions_t io_functions);
196
197 static _IO_off64_t
198 _IO_old_cookie_seek (fp, offset, dir)
199      _IO_FILE *fp;
200      _IO_off64_t offset;
201      int dir;
202 {
203   struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
204   int (*seek) (_IO_FILE *, _IO_off_t, int);
205   int ret;
206
207   seek = (int (*)(_IO_FILE *, _IO_off_t, int)) cfile->__io_functions.seek;
208   if (seek == NULL)
209     return _IO_pos_BAD;
210
211   ret = seek (cfile->__cookie, offset, dir);
212
213   return (ret == -1) ? _IO_pos_BAD : ret;
214 }
215
216 static struct _IO_jump_t _IO_old_cookie_jumps = {
217   JUMP_INIT_DUMMY,
218   JUMP_INIT(finish, INTUSE(_IO_file_finish)),
219   JUMP_INIT(overflow, INTUSE(_IO_file_overflow)),
220   JUMP_INIT(underflow, INTUSE(_IO_file_underflow)),
221   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
222   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
223   JUMP_INIT(xsputn, INTUSE(_IO_file_xsputn)),
224   JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
225   JUMP_INIT(seekoff, INTUSE(_IO_file_seekoff)),
226   JUMP_INIT(seekpos, _IO_default_seekpos),
227   JUMP_INIT(setbuf, INTUSE(_IO_file_setbuf)),
228   JUMP_INIT(sync, INTUSE(_IO_file_sync)),
229   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
230   JUMP_INIT(read, _IO_cookie_read),
231   JUMP_INIT(write, _IO_cookie_write),
232   JUMP_INIT(seek, _IO_old_cookie_seek),
233   JUMP_INIT(close, _IO_cookie_close),
234   JUMP_INIT(stat, _IO_default_stat),
235   JUMP_INIT(showmanyc, _IO_default_showmanyc),
236   JUMP_INIT(imbue, _IO_default_imbue),
237 };
238
239 _IO_FILE *
240 _IO_old_fopencookie (cookie, mode, io_functions)
241      void *cookie;
242      const char *mode;
243      _IO_cookie_io_functions_t io_functions;
244 {
245   _IO_FILE *ret;
246
247   ret = _IO_fopencookie (cookie, mode, io_functions);
248   if (ret != NULL)
249     _IO_JUMPS ((struct _IO_FILE_plus *) ret) = &_IO_old_cookie_jumps;
250
251   return ret;
252 }
253
254 compat_symbol (libc, _IO_old_fopencookie, fopencookie, GLIBC_2_0);
255
256 #endif