]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/fileops.c
Define our own dso_handle.
[thirdparty/glibc.git] / libio / fileops.c
CommitLineData
284749da 1/* Copyright (C) 1993, 1995, 1997-2001, 2002 Free Software Foundation, Inc.
41bdb6e2 2 This file is part of the GNU C Library.
40a55d20 3 Written by Per Bothner <bothner@cygnus.com>.
96aa2d94 4
41bdb6e2
AJ
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.
96aa2d94 9
41bdb6e2
AJ
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
40a55d20 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
96aa2d94 14
41bdb6e2
AJ
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA.
96aa2d94 19
41bdb6e2
AJ
20 As a special exception, if you link the code in this file with
21 files compiled with a GNU compiler to produce an executable,
22 that does not cause the resulting executable to be covered by
23 the GNU Lesser General Public License. This exception does not
24 however invalidate any other reasons why the executable file
25 might be covered by the GNU Lesser General Public License.
26 This exception applies to code released by its copyright holders
27 in files containing the exception. */
96aa2d94 28
96aa2d94 29
fa0bc87c
RM
30#ifndef _POSIX_SOURCE
31# define _POSIX_SOURCE
32#endif
96aa2d94 33#include "libioP.h"
129d706d 34#include <assert.h>
96aa2d94 35#include <fcntl.h>
284749da 36#include <sys/param.h>
96aa2d94
RM
37#include <sys/types.h>
38#include <sys/stat.h>
39#include <string.h>
40#include <errno.h>
c9f10034 41#include <unistd.h>
00bc5db0
UD
42#ifdef __STDC__
43#include <stdlib.h>
44#endif
4e2e9999
UD
45#if _LIBC
46# include "../wcsmbs/wcsmbsload.h"
129d706d
UD
47# include "../iconv/gconv_charset.h"
48# include "../iconv/gconv_int.h"
0bf98029 49# include <shlib-compat.h>
4e2e9999 50#endif
96aa2d94
RM
51#ifndef errno
52extern int errno;
53#endif
4547c1a4
UD
54#ifndef __set_errno
55# define __set_errno(Val) errno = (Val)
56#endif
96aa2d94 57
68dbb3a6
UD
58
59#ifdef _LIBC
61eb22d3
UD
60# define open(Name, Flags, Prot) __open (Name, Flags, Prot)
61# define close(FD) __close (FD)
61eb22d3
UD
62# define lseek(FD, Offset, Whence) __lseek (FD, Offset, Whence)
63# define read(FD, Buf, NBytes) __read (FD, Buf, NBytes)
64# define write(FD, Buf, NBytes) __write (FD, Buf, NBytes)
4483f2c0 65# define _IO_do_write _IO_new_do_write /* For macro uses. */
319d719d
UD
66#else
67# define _IO_new_do_write _IO_do_write
68# define _IO_new_file_attach _IO_file_attach
69# define _IO_new_file_close_it _IO_file_close_it
70# define _IO_new_file_finish _IO_file_finish
71# define _IO_new_file_fopen _IO_file_fopen
72# define _IO_new_file_init _IO_file_init
73# define _IO_new_file_setbuf _IO_file_setbuf
74# define _IO_new_file_sync _IO_file_sync
75# define _IO_new_file_overflow _IO_file_overflow
76# define _IO_new_file_seekoff _IO_file_seekoff
77# define _IO_new_file_underflow _IO_file_underflow
78# define _IO_new_file_write _IO_file_write
79# define _IO_new_file_xsputn _IO_file_xsputn
68dbb3a6
UD
80#endif
81
129d706d
UD
82
83#ifdef _LIBC
ab26a24a 84extern struct __gconv_trans_data __libio_translit attribute_hidden;
129d706d
UD
85#endif
86
87
96aa2d94
RM
88/* An fstream can be in at most one of put mode, get mode, or putback mode.
89 Putback mode is a variant of get mode.
90
91 In a filebuf, there is only one current position, instead of two
6d52618b 92 separate get and put pointers. In get mode, the current position
96aa2d94
RM
93 is that of gptr(); in put mode that of pptr().
94
95 The position in the buffer that corresponds to the position
a18f587d
UD
96 in external file system is normally _IO_read_end, except in putback
97 mode, when it is _IO_save_end.
96aa2d94
RM
98 If the field _fb._offset is >= 0, it gives the offset in
99 the file as a whole corresponding to eGptr(). (?)
100
101 PUT MODE:
a18f587d
UD
102 If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
103 and _IO_read_base are equal to each other. These are usually equal
104 to _IO_buf_base, though not necessarily if we have switched from
105 get mode to put mode. (The reason is to maintain the invariant
106 that _IO_read_end corresponds to the external file position.)
107 _IO_write_base is non-NULL and usually equal to _IO_base_base.
108 We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
109 The un-flushed character are those between _IO_write_base and _IO_write_ptr.
110
96aa2d94
RM
111 GET MODE:
112 If a filebuf is in get or putback mode, eback() != egptr().
113 In get mode, the unread characters are between gptr() and egptr().
114 The OS file position corresponds to that of egptr().
a18f587d 115
96aa2d94
RM
116 PUTBACK MODE:
117 Putback mode is used to remember "excess" characters that have
118 been sputbackc'd in a separate putback buffer.
119 In putback mode, the get buffer points to the special putback buffer.
120 The unread characters are the characters between gptr() and egptr()
121 in the putback buffer, as well as the area between save_gptr()
122 and save_egptr(), which point into the original reserve buffer.
123 (The pointers save_gptr() and save_egptr() are the values
124 of gptr() and egptr() at the time putback mode was entered.)
125 The OS position corresponds to that of save_egptr().
23396375 126
96aa2d94 127 LINE BUFFERED OUTPUT:
a18f587d 128 During line buffered output, _IO_write_base==base() && epptr()==base().
96aa2d94
RM
129 However, ptr() may be anywhere between base() and ebuf().
130 This forces a call to filebuf::overflow(int C) on every put.
131 If there is more space in the buffer, and C is not a '\n',
132 then C is inserted, and pptr() incremented.
23396375 133
96aa2d94
RM
134 UNBUFFERED STREAMS:
135 If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
136*/
137
138#define CLOSED_FILEBUF_FLAGS \
139 (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
140
141
142void
b259e746 143_IO_new_file_init (fp)
2ca8b1ee 144 struct _IO_FILE_plus *fp;
96aa2d94
RM
145{
146 /* POSIX.1 allows another file handle to be used to change the position
147 of our file descriptor. Hence we actually don't know the actual
148 position before we do the first fseek (and until a following fflush). */
2ca8b1ee
GM
149 fp->file._offset = _IO_pos_BAD;
150 fp->file._IO_file_flags |= CLOSED_FILEBUF_FLAGS;
96aa2d94 151
77fe0b9c 152 INTUSE(_IO_link_in) (fp);
2ca8b1ee 153 fp->file._fileno = -1;
96aa2d94 154}
77fe0b9c 155INTDEF2(_IO_new_file_init, _IO_file_init)
96aa2d94
RM
156
157int
b259e746 158_IO_new_file_close_it (fp)
40a55d20 159 _IO_FILE *fp;
96aa2d94 160{
fa0bc87c 161 int write_status, close_status;
40a55d20 162 if (!_IO_file_is_open (fp))
96aa2d94
RM
163 return EOF;
164
3384a8d6
UD
165 if ((fp->_flags & _IO_NO_WRITES) == 0
166 && (fp->_flags & _IO_CURRENTLY_PUTTING) != 0)
167 write_status = _IO_do_flush (fp);
168 else
169 write_status = 0;
96aa2d94 170
77fe0b9c 171 INTUSE(_IO_unsave_markers) (fp);
96aa2d94
RM
172
173 close_status = _IO_SYSCLOSE (fp);
174
175 /* Free buffer. */
d64b6ad0
UD
176 if (fp->_mode <= 0)
177 {
77fe0b9c 178 INTUSE(_IO_setb) (fp, NULL, NULL, 0);
d64b6ad0
UD
179 _IO_setg (fp, NULL, NULL, NULL);
180 _IO_setp (fp, NULL, NULL);
181 }
319d719d 182#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
d64b6ad0
UD
183 else
184 {
44c4ccbc
UD
185 if (_IO_have_wbackup (fp))
186 INTUSE(_IO_free_wbackup_area) (fp);
77fe0b9c 187 INTUSE(_IO_wsetb) (fp, NULL, NULL, 0);
d64b6ad0
UD
188 _IO_wsetg (fp, NULL, NULL, NULL);
189 _IO_wsetp (fp, NULL, NULL);
190 }
319d719d 191#endif
96aa2d94 192
77fe0b9c 193 INTUSE(_IO_un_link) ((struct _IO_FILE_plus *) fp);
96aa2d94 194 fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
110215a9 195 fp->_fileno = -1;
bd355af0 196 fp->_offset = _IO_pos_BAD;
96aa2d94 197
fa0bc87c 198 return close_status ? close_status : write_status;
96aa2d94 199}
77fe0b9c 200INTDEF2(_IO_new_file_close_it, _IO_file_close_it)
96aa2d94
RM
201
202void
b259e746 203_IO_new_file_finish (fp, dummy)
40a55d20
UD
204 _IO_FILE *fp;
205 int dummy;
96aa2d94 206{
40a55d20 207 if (_IO_file_is_open (fp))
96aa2d94
RM
208 {
209 _IO_do_flush (fp);
210 if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
211 _IO_SYSCLOSE (fp);
212 }
77fe0b9c 213 INTUSE(_IO_default_finish) (fp, 0);
96aa2d94 214}
77fe0b9c 215INTDEF2(_IO_new_file_finish, _IO_file_finish)
96aa2d94 216
bd355af0
UD
217#if defined __GNUC__ && __GNUC__ >= 2
218__inline__
219#endif
220_IO_FILE *
221_IO_file_open (fp, filename, posix_mode, prot, read_write, is32not64)
222 _IO_FILE *fp;
223 const char *filename;
224 int posix_mode;
225 int prot;
226 int read_write;
227 int is32not64;
228{
229 int fdesc;
230#ifdef _G_OPEN64
231 fdesc = (is32not64
232 ? open (filename, posix_mode, prot)
233 : _G_OPEN64 (filename, posix_mode, prot));
234#else
235 fdesc = open (filename, posix_mode, prot);
236#endif
237 if (fdesc < 0)
238 return NULL;
239 fp->_fileno = fdesc;
240 _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
c096ab25 241 if ((read_write & _IO_IS_APPENDING) && (read_write & _IO_NO_READS))
bd355af0
UD
242 if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
243 == _IO_pos_BAD && errno != ESPIPE)
2c617417
UD
244 {
245 close (fdesc);
246 return NULL;
247 }
77fe0b9c 248 INTUSE(_IO_link_in) ((struct _IO_FILE_plus *) fp);
bd355af0
UD
249 return fp;
250}
251
96aa2d94 252_IO_FILE *
b259e746 253_IO_new_file_fopen (fp, filename, mode, is32not64)
40a55d20
UD
254 _IO_FILE *fp;
255 const char *filename;
256 const char *mode;
dfd2257a 257 int is32not64;
96aa2d94
RM
258{
259 int oflags = 0, omode;
bd355af0 260 int read_write;
96aa2d94 261 int oprot = 0666;
f38931a9 262 int i;
4e2e9999 263 _IO_FILE *result;
129d706d 264#ifdef _LIBC
4e2e9999 265 const char *cs;
129d706d 266 const char *last_recognized;
4e2e9999
UD
267#endif
268
96aa2d94
RM
269 if (_IO_file_is_open (fp))
270 return 0;
f38931a9 271 switch (*mode)
40a55d20
UD
272 {
273 case 'r':
274 omode = O_RDONLY;
275 read_write = _IO_NO_WRITES;
276 break;
277 case 'w':
278 omode = O_WRONLY;
279 oflags = O_CREAT|O_TRUNC;
280 read_write = _IO_NO_READS;
281 break;
282 case 'a':
283 omode = O_WRONLY;
284 oflags = O_CREAT|O_APPEND;
285 read_write = _IO_NO_READS|_IO_IS_APPENDING;
286 break;
287 default:
288 __set_errno (EINVAL);
289 return NULL;
290 }
129d706d
UD
291#ifdef _LIBC
292 last_recognized = mode;
293#endif
b7fc6d07 294 for (i = 1; i < 5; ++i)
40a55d20 295 {
f38931a9
UD
296 switch (*++mode)
297 {
298 case '\0':
299 break;
300 case '+':
301 omode = O_RDWR;
302 read_write &= _IO_IS_APPENDING;
129d706d
UD
303#ifdef _LIBC
304 last_recognized = mode;
305#endif
f38931a9
UD
306 continue;
307 case 'x':
308 oflags |= O_EXCL;
129d706d
UD
309#ifdef _LIBC
310 last_recognized = mode;
311#endif
f38931a9
UD
312 continue;
313 case 'b':
129d706d
UD
314#ifdef _LIBC
315 last_recognized = mode;
316#endif
b7fc6d07
UD
317 continue;
318 case 'm':
319 fp->_flags2 |= _IO_FLAGS2_MMAP;
320 continue;
f38931a9
UD
321 default:
322 /* Ignore. */
323 continue;
324 }
325 break;
40a55d20 326 }
f38931a9 327
4e2e9999
UD
328 result = _IO_file_open (fp, filename, omode|oflags, oprot, read_write,
329 is32not64);
330
331
129d706d
UD
332#ifdef _LIBC
333 if (result != NULL)
4e2e9999 334 {
129d706d
UD
335 /* Test whether the mode string specifies the conversion. */
336 cs = strstr (last_recognized + 1, ",ccs=");
337 if (cs != NULL)
338 {
339 /* Yep. Load the appropriate conversions and set the orientation
340 to wide. */
341 struct gconv_fcts fcts;
342 struct _IO_codecvt *cc;
343 char *endp = __strchrnul (cs + 5, ',');
344 char ccs[endp - (cs + 5) + 3];
345
346 *((char *) __mempcpy (ccs, cs + 5, endp - (cs + 5))) = '\0';
347 strip (ccs, ccs);
348
349 if (__wcsmbs_named_conv (&fcts, ccs[2] == '\0'
350 ? upstr (ccs, cs + 5) : ccs) != 0)
351 {
352 /* Something went wrong, we cannot load the conversion modules.
353 This means we cannot proceed since the user explicitly asked
354 for these. */
355 __set_errno (EINVAL);
356 return NULL;
357 }
358
359 assert (fcts.towc_nsteps == 1);
360 assert (fcts.tomb_nsteps == 1);
361
362 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
363 fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_base;
364
365 /* Clear the state. We start all over again. */
366 memset (&fp->_wide_data->_IO_state, '\0', sizeof (__mbstate_t));
367 memset (&fp->_wide_data->_IO_last_state, '\0', sizeof (__mbstate_t));
368
369 cc = fp->_codecvt = &fp->_wide_data->_codecvt;
370
371 /* The functions are always the same. */
372 *cc = __libio_codecvt;
373
374 cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps;
375 cc->__cd_in.__cd.__steps = fcts.towc;
376
377 cc->__cd_in.__cd.__data[0].__invocation_counter = 0;
378 cc->__cd_in.__cd.__data[0].__internal_use = 1;
379 cc->__cd_in.__cd.__data[0].__flags = __GCONV_IS_LAST;
380 cc->__cd_in.__cd.__data[0].__statep = &result->_wide_data->_IO_state;
381
382 /* XXX For now no transliteration. */
383 cc->__cd_in.__cd.__data[0].__trans = NULL;
384
385 cc->__cd_out.__cd.__nsteps = fcts.tomb_nsteps;
386 cc->__cd_out.__cd.__steps = fcts.tomb;
387
388 cc->__cd_out.__cd.__data[0].__invocation_counter = 0;
389 cc->__cd_out.__cd.__data[0].__internal_use = 1;
390 cc->__cd_out.__cd.__data[0].__flags = __GCONV_IS_LAST;
391 cc->__cd_out.__cd.__data[0].__statep =
392 &result->_wide_data->_IO_state;
393
394 /* And now the transliteration. */
395 cc->__cd_out.__cd.__data[0].__trans = &__libio_translit;
396
397 /* Set the mode now. */
398 result->_mode = 1;
399
400 /* We don't need the step data structure anymore. */
401 __gconv_release_cache (fcts.towc, fcts.towc_nsteps);
402 __gconv_release_cache (fcts.tomb, fcts.tomb_nsteps);
403 }
4e2e9999
UD
404 }
405#endif /* GNU libc */
406
407 return result;
96aa2d94 408}
77fe0b9c 409INTDEF2(_IO_new_file_fopen, _IO_file_fopen)
96aa2d94 410
40a55d20 411_IO_FILE *
b259e746 412_IO_new_file_attach (fp, fd)
40a55d20
UD
413 _IO_FILE *fp;
414 int fd;
96aa2d94 415{
40a55d20 416 if (_IO_file_is_open (fp))
96aa2d94
RM
417 return NULL;
418 fp->_fileno = fd;
419 fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
420 fp->_flags |= _IO_DELETE_DONT_CLOSE;
f65fd747
UD
421 /* Get the current position of the file. */
422 /* We have to do that since that may be junk. */
bd355af0 423 fp->_offset = _IO_pos_BAD;
dfd2257a 424 if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
f65fd747
UD
425 == _IO_pos_BAD && errno != ESPIPE)
426 return NULL;
96aa2d94
RM
427 return fp;
428}
77fe0b9c 429INTDEF2(_IO_new_file_attach, _IO_file_attach)
96aa2d94 430
40a55d20 431_IO_FILE *
b259e746 432_IO_new_file_setbuf (fp, p, len)
40a55d20
UD
433 _IO_FILE *fp;
434 char *p;
435 _IO_ssize_t len;
96aa2d94 436{
d64b6ad0
UD
437 if (_IO_default_setbuf (fp, p, len) == NULL)
438 return NULL;
96aa2d94 439
d64b6ad0
UD
440 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
441 = fp->_IO_buf_base;
442 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
96aa2d94 443
d64b6ad0 444 return fp;
96aa2d94 445}
77fe0b9c 446INTDEF2(_IO_new_file_setbuf, _IO_file_setbuf)
96aa2d94 447
bff334e0
UD
448
449_IO_FILE *
450_IO_file_setbuf_mmap (fp, p, len)
451 _IO_FILE *fp;
452 char *p;
453 _IO_ssize_t len;
454{
455 _IO_FILE *result;
456
457 /* Change the function table. */
230491f0 458 _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &INTUSE(_IO_file_jumps);
bff334e0
UD
459 fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
460
461 /* And perform the normal operation. */
462 result = _IO_new_file_setbuf (fp, p, len);
463
464 /* If the call failed, restore to using mmap. */
465 if (result == NULL)
466 {
467 _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps_mmap;
468 fp->_wide_data->_wide_vtable = &_IO_wfile_jumps_mmap;
469 }
470
471 return result;
472}
473
0720f75c
UD
474static int new_do_write __P ((_IO_FILE *, const char *, _IO_size_t));
475
96aa2d94 476/* Write TO_DO bytes from DATA to FP.
68dbb3a6 477 Then mark FP as having empty buffers. */
96aa2d94
RM
478
479int
b259e746 480_IO_new_do_write (fp, data, to_do)
40a55d20
UD
481 _IO_FILE *fp;
482 const char *data;
483 _IO_size_t to_do;
0720f75c 484{
6dd67bd5
UD
485 return (to_do == 0
486 || (_IO_size_t) new_do_write (fp, data, to_do) == to_do) ? 0 : EOF;
0720f75c 487}
77fe0b9c 488INTDEF2(_IO_new_do_write, _IO_do_write)
0720f75c
UD
489
490static
491int
492new_do_write (fp, data, to_do)
493 _IO_FILE *fp;
494 const char *data;
495 _IO_size_t to_do;
96aa2d94
RM
496{
497 _IO_size_t count;
96aa2d94
RM
498 if (fp->_flags & _IO_IS_APPENDING)
499 /* On a system without a proper O_APPEND implementation,
500 you would need to sys_seek(0, SEEK_END) here, but is
501 is not needed nor desirable for Unix- or Posix-like systems.
502 Instead, just indicate that offset (before and after) is
503 unpredictable. */
bd355af0 504 fp->_offset = _IO_pos_BAD;
96aa2d94 505 else if (fp->_IO_read_end != fp->_IO_write_base)
23396375 506 {
d64b6ad0 507 _IO_off64_t new_pos
40a55d20 508 = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
96aa2d94 509 if (new_pos == _IO_pos_BAD)
0720f75c 510 return 0;
bd355af0 511 fp->_offset = new_pos;
96aa2d94
RM
512 }
513 count = _IO_SYSWRITE (fp, data, to_do);
0720f75c 514 if (fp->_cur_column && count)
77fe0b9c
UD
515 fp->_cur_column = INTUSE(_IO_adjust_column) (fp->_cur_column - 1, data,
516 count) + 1;
40a55d20 517 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
96aa2d94 518 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
076bfcf6 519 fp->_IO_write_end = (fp->_mode <= 0
d64b6ad0 520 && (fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
40a55d20 521 ? fp->_IO_buf_base : fp->_IO_buf_end);
0720f75c 522 return count;
96aa2d94
RM
523}
524
525int
b259e746 526_IO_new_file_underflow (fp)
40a55d20 527 _IO_FILE *fp;
96aa2d94
RM
528{
529 _IO_ssize_t count;
530#if 0
531 /* SysV does not make this test; take it out for compatibility */
532 if (fp->_flags & _IO_EOF_SEEN)
533 return (EOF);
534#endif
535
536 if (fp->_flags & _IO_NO_READS)
feb3c934 537 {
58034572 538 fp->_flags |= _IO_ERR_SEEN;
feb3c934
UD
539 __set_errno (EBADF);
540 return EOF;
541 }
96aa2d94 542 if (fp->_IO_read_ptr < fp->_IO_read_end)
40a55d20 543 return *(unsigned char *) fp->_IO_read_ptr;
96aa2d94
RM
544
545 if (fp->_IO_buf_base == NULL)
00bc5db0
UD
546 {
547 /* Maybe we already have a push back pointer. */
548 if (fp->_IO_save_base != NULL)
549 {
550 free (fp->_IO_save_base);
551 fp->_flags &= ~_IO_IN_BACKUP;
552 }
77fe0b9c 553 INTUSE(_IO_doallocbuf) (fp);
00bc5db0 554 }
96aa2d94
RM
555
556 /* Flush all line buffered files before reading. */
557 /* FIXME This can/should be moved to genops ?? */
558 if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
3d759cb8
UD
559 {
560#if 0
77fe0b9c 561 INTUSE(_IO_flush_all_linebuffered) ();
3d759cb8
UD
562#else
563 /* We used to flush all line-buffered stream. This really isn't
564 required by any standard. My recollection is that
565 traditional Unix systems did this for stdout. stderr better
566 not be line buffered. So we do just that here
567 explicitly. --drepper */
568 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
569 _IO_stdout);
570 _IO_flockfile (_IO_stdout);
571
572 if ((_IO_stdout->_flags & (_IO_LINKED | _IO_NO_WRITES | _IO_LINE_BUF))
573 == (_IO_LINKED | _IO_LINE_BUF))
574 _IO_OVERFLOW (_IO_stdout, EOF);
575
576 _IO_funlockfile (_IO_stdout);
577 _IO_cleanup_region_end (0);
578#endif
579 }
96aa2d94 580
77fe0b9c 581 INTUSE(_IO_switch_to_get_mode) (fp);
96aa2d94 582
2d7da676
UD
583 /* This is very tricky. We have to adjust those
584 pointers before we call _IO_SYSREAD () since
585 we may longjump () out while waiting for
586 input. Those pointers may be screwed up. H.J. */
587 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
588 fp->_IO_read_end = fp->_IO_buf_base;
589 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
590 = fp->_IO_buf_base;
591
96aa2d94
RM
592 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
593 fp->_IO_buf_end - fp->_IO_buf_base);
594 if (count <= 0)
595 {
596 if (count == 0)
597 fp->_flags |= _IO_EOF_SEEN;
598 else
599 fp->_flags |= _IO_ERR_SEEN, count = 0;
600 }
2d7da676 601 fp->_IO_read_end += count;
96aa2d94
RM
602 if (count == 0)
603 return EOF;
bd355af0
UD
604 if (fp->_offset != _IO_pos_BAD)
605 _IO_pos_adjust (fp->_offset, count);
40a55d20 606 return *(unsigned char *) fp->_IO_read_ptr;
96aa2d94 607}
77fe0b9c 608INTDEF2(_IO_new_file_underflow, _IO_file_underflow)
96aa2d94 609
acbee5f6
RM
610/* Guts of underflow callback if we mmap the file. This stats the file and
611 updates the stream state to match. In the normal case we return zero.
612 If the file is no longer eligible for mmap, its jump tables are reset to
613 the vanilla ones and we return nonzero. */
614static int
615mmap_remap_check (_IO_FILE *fp)
0469311e 616{
acbee5f6
RM
617 struct _G_stat64 st;
618
619 if (_IO_SYSSTAT (fp, &st) == 0
620 && S_ISREG (st.st_mode) && st.st_size != 0
621 /* Limit the file size to 1MB for 32-bit machines. */
622 && (sizeof (ptrdiff_t) > 4 || st.st_size < 1*1024*1024))
0469311e 623 {
acbee5f6
RM
624 const size_t pagesize = __getpagesize ();
625# define ROUNDED(x) (((x) + pagesize - 1) & ~(pagesize - 1))
626 if (ROUNDED (st.st_size) < ROUNDED (fp->_IO_buf_end
627 - fp->_IO_buf_base))
628 {
629 /* We can trim off some pages past the end of the file. */
630 (void) __munmap (fp->_IO_buf_base + ROUNDED (st.st_size),
631 ROUNDED (fp->_IO_buf_end - fp->_IO_buf_base)
632 - ROUNDED (st.st_size));
633 fp->_IO_buf_end = fp->_IO_buf_base + st.st_size;
634 }
635 else if (ROUNDED (st.st_size) > ROUNDED (fp->_IO_buf_end
636 - fp->_IO_buf_base))
637 {
638 /* The file added some pages. We need to remap it. */
639 void *p;
640#if defined __linux__ /* XXX */
641 p = __mremap (fp->_IO_buf_base, ROUNDED (fp->_IO_buf_end
642 - fp->_IO_buf_base),
643 ROUNDED (st.st_size), MREMAP_MAYMOVE);
644 if (p == MAP_FAILED)
645 {
646 (void) __munmap (fp->_IO_buf_base,
647 fp->_IO_buf_end - fp->_IO_buf_base);
648 goto punt;
649 }
650#else
651 (void) __munmap (fp->_IO_buf_base,
652 fp->_IO_buf_end - fp->_IO_buf_base);
653# ifdef _G_MMAP64
654 p = _G_MMAP64 (NULL, st.st_size, PROT_READ, MAP_SHARED,
655 fp->_fileno, 0);
656# else
657 p = __mmap (NULL, st.st_size, PROT_READ, MAP_SHARED,
658 fp->_fileno, 0);
659# endif
660 if (p == MAP_FAILED)
661 goto punt;
662#endif
663 fp->_IO_buf_base = p;
664 fp->_IO_buf_end = fp->_IO_buf_base + st.st_size;
665 }
666 else
667 {
668 /* The number of pages didn't change. */
669 fp->_IO_buf_end = fp->_IO_buf_base + st.st_size;
670 }
671# undef ROUNDED
672
673 fp->_offset -= fp->_IO_read_end - fp->_IO_read_ptr;
fc77d66a
RM
674 _IO_setg (fp, fp->_IO_buf_base,
675 fp->_offset < fp->_IO_buf_end - fp->_IO_buf_base
676 ? fp->_IO_buf_base + fp->_offset : fp->_IO_buf_end,
acbee5f6 677 fp->_IO_buf_end);
c4292489 678
fc77d66a
RM
679 /* If we are already positioned at or past the end of the file, don't
680 change the current offset. If not, seek past what we have mapped,
681 mimicking the position left by a normal underflow reading into its
682 buffer until EOF. */
683
684 if (fp->_offset < fp->_IO_buf_end - fp->_IO_buf_base)
685 {
686 if (
0469311e 687# ifdef _G_LSEEK64
fc77d66a 688 _G_LSEEK64
0469311e 689# else
fc77d66a 690 __lseek
0469311e 691# endif
fc77d66a
RM
692 (fp->_fileno, fp->_IO_buf_end - fp->_IO_buf_base, SEEK_SET)
693 != fp->_IO_buf_end - fp->_IO_buf_base)
694 fp->_flags |= _IO_ERR_SEEN;
695 else
696 fp->_offset = fp->_IO_buf_end - fp->_IO_buf_base;
0469311e 697 }
acbee5f6
RM
698
699 return 0;
700 }
701 else
702 {
703 /* Life is no longer good for mmap. Punt it. */
704 (void) __munmap (fp->_IO_buf_base,
705 fp->_IO_buf_end - fp->_IO_buf_base);
706 punt:
707 fp->_IO_buf_base = fp->_IO_buf_end = NULL;
708 _IO_setg (fp, NULL, NULL, NULL);
709 if (fp->_mode <= 0)
230491f0 710 _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &INTUSE(_IO_file_jumps);
acbee5f6
RM
711 else
712 _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_wfile_jumps;
713 fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
714
715 return 1;
0469311e 716 }
acbee5f6
RM
717}
718
719/* Special callback replacing the underflow callbacks if we mmap the file. */
720int
721_IO_file_underflow_mmap (_IO_FILE *fp)
722{
723 if (fp->_IO_read_ptr < fp->_IO_read_end)
724 return *(unsigned char *) fp->_IO_read_ptr;
725
726 if (__builtin_expect (mmap_remap_check (fp), 0))
727 /* We punted to the regular file functions. */
728 return _IO_UNDERFLOW (fp);
729
730 if (fp->_IO_read_ptr < fp->_IO_read_end)
731 return *(unsigned char *) fp->_IO_read_ptr;
0469311e
UD
732
733 fp->_flags |= _IO_EOF_SEEN;
734 return EOF;
735}
736
acbee5f6
RM
737static void
738decide_maybe_mmap (_IO_FILE *fp)
739{
740 /* We use the file in read-only mode. This could mean we can
741 mmap the file and use it without any copying. But not all
742 file descriptors are for mmap-able objects and on 32-bit
743 machines we don't want to map files which are too large since
744 this would require too much virtual memory. */
745 struct _G_stat64 st;
746
747 if (_IO_SYSSTAT (fp, &st) == 0
748 && S_ISREG (st.st_mode) && st.st_size != 0
749 /* Limit the file size to 1MB for 32-bit machines. */
750 && (sizeof (ptrdiff_t) > 4 || st.st_size < 1*1024*1024)
751 /* Sanity check. */
752 && (fp->_offset == _IO_pos_BAD || fp->_offset <= st.st_size))
753 {
754 /* Try to map the file. */
755 void *p;
756
757# ifdef _G_MMAP64
758 p = _G_MMAP64 (NULL, st.st_size, PROT_READ, MAP_SHARED, fp->_fileno, 0);
759# else
760 p = __mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fp->_fileno, 0);
761# endif
762 if (p != MAP_FAILED)
763 {
764 /* OK, we managed to map the file. Set the buffer up and use a
765 special jump table with simplified underflow functions which
766 never tries to read anything from the file. */
767
768 if (
769# ifdef _G_LSEEK64
770 _G_LSEEK64
771# else
772 __lseek
773# endif
774 (fp->_fileno, st.st_size, SEEK_SET) != st.st_size)
775 {
776 (void) __munmap (p, st.st_size);
777 fp->_offset = _IO_pos_BAD;
778 }
779 else
780 {
781 INTUSE(_IO_setb) (fp, p, (char *) p + st.st_size, 0);
782
783 if (fp->_offset == _IO_pos_BAD)
784 fp->_offset = 0;
785
786 _IO_setg (fp, p, p + fp->_offset, p + st.st_size);
787 fp->_offset = st.st_size;
788
789 if (fp->_mode <= 0)
790 _IO_JUMPS ((struct _IO_FILE_plus *)fp) = &_IO_file_jumps_mmap;
791 else
792 _IO_JUMPS ((struct _IO_FILE_plus *)fp) = &_IO_wfile_jumps_mmap;
793 fp->_wide_data->_wide_vtable = &_IO_wfile_jumps_mmap;
794
795 return;
796 }
797 }
798 }
799
800 /* We couldn't use mmap, so revert to the vanilla file operations. */
801
802 if (fp->_mode <= 0)
230491f0 803 _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &INTUSE(_IO_file_jumps);
acbee5f6
RM
804 else
805 _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_wfile_jumps;
806 fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
807}
808
809int
810_IO_file_underflow_maybe_mmap (_IO_FILE *fp)
811{
812 /* This is the first read attempt. Choose mmap or vanilla operations
813 and then punt to the chosen underflow routine. */
814 decide_maybe_mmap (fp);
815 return _IO_UNDERFLOW (fp);
816}
817
818
96aa2d94 819int
b259e746 820_IO_new_file_overflow (f, ch)
40a55d20
UD
821 _IO_FILE *f;
822 int ch;
96aa2d94
RM
823{
824 if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
feb3c934 825 {
c131718c 826 f->_flags |= _IO_ERR_SEEN;
feb3c934
UD
827 __set_errno (EBADF);
828 return EOF;
829 }
96aa2d94 830 /* If currently reading or no buffer allocated. */
d64b6ad0 831 if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0 || f->_IO_write_base == 0)
96aa2d94
RM
832 {
833 /* Allocate a buffer if needed. */
834 if (f->_IO_write_base == 0)
835 {
77fe0b9c 836 INTUSE(_IO_doallocbuf) (f);
96aa2d94
RM
837 _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
838 }
c6645251
UD
839 /* Otherwise must be currently reading.
840 If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
841 logically slide the buffer forwards one block (by setting the
842 read pointers to all point at the beginning of the block). This
843 makes room for subsequent output.
844 Otherwise, set the read pointers to _IO_read_end (leaving that
845 alone, so it can continue to correspond to the external position). */
846 if (f->_IO_read_ptr == f->_IO_buf_end)
847 f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
96aa2d94
RM
848 f->_IO_write_ptr = f->_IO_read_ptr;
849 f->_IO_write_base = f->_IO_write_ptr;
850 f->_IO_write_end = f->_IO_buf_end;
851 f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
852
96aa2d94 853 f->_flags |= _IO_CURRENTLY_PUTTING;
076bfcf6 854 if (f->_mode <= 0 && f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
bfcd44c3 855 f->_IO_write_end = f->_IO_write_ptr;
96aa2d94
RM
856 }
857 if (ch == EOF)
4483f2c0
RM
858 return INTUSE(_IO_do_write) (f, f->_IO_write_base,
859 f->_IO_write_ptr - f->_IO_write_base);
96aa2d94 860 if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
40a55d20 861 if (_IO_do_flush (f) == EOF)
96aa2d94
RM
862 return EOF;
863 *f->_IO_write_ptr++ = ch;
864 if ((f->_flags & _IO_UNBUFFERED)
865 || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
4483f2c0
RM
866 if (INTUSE(_IO_do_write) (f, f->_IO_write_base,
867 f->_IO_write_ptr - f->_IO_write_base) == EOF)
96aa2d94 868 return EOF;
40a55d20 869 return (unsigned char) ch;
96aa2d94 870}
77fe0b9c 871INTDEF2(_IO_new_file_overflow, _IO_file_overflow)
96aa2d94
RM
872
873int
b259e746 874_IO_new_file_sync (fp)
40a55d20 875 _IO_FILE *fp;
96aa2d94 876{
a2bde807 877 _IO_ssize_t delta;
61eb22d3
UD
878 int retval = 0;
879
96aa2d94
RM
880 /* char* ptr = cur_ptr(); */
881 if (fp->_IO_write_ptr > fp->_IO_write_base)
882 if (_IO_do_flush(fp)) return EOF;
23396375 883 delta = fp->_IO_read_ptr - fp->_IO_read_end;
96aa2d94
RM
884 if (delta != 0)
885 {
886#ifdef TODO
40a55d20
UD
887 if (_IO_in_backup (fp))
888 delta -= eGptr () - Gbase ();
96aa2d94 889#endif
dfd2257a
UD
890 _IO_off64_t new_pos = _IO_SYSSEEK (fp, delta, 1);
891 if (new_pos != (_IO_off64_t) EOF)
96aa2d94
RM
892 fp->_IO_read_end = fp->_IO_read_ptr;
893#ifdef ESPIPE
894 else if (errno == ESPIPE)
895 ; /* Ignore error from unseekable devices. */
896#endif
897 else
61eb22d3 898 retval = EOF;
96aa2d94 899 }
61eb22d3 900 if (retval != EOF)
bd355af0 901 fp->_offset = _IO_pos_BAD;
96aa2d94
RM
902 /* FIXME: Cleanup - can this be shared? */
903 /* setg(base(), ptr, ptr); */
61eb22d3 904 return retval;
96aa2d94 905}
77fe0b9c 906INTDEF2(_IO_new_file_sync, _IO_file_sync)
96aa2d94 907
acbee5f6
RM
908static int
909_IO_file_sync_mmap (_IO_FILE *fp)
910{
911 if (fp->_IO_read_ptr != fp->_IO_read_end)
912 {
913#ifdef TODO
914 if (_IO_in_backup (fp))
915 delta -= eGptr () - Gbase ();
916#endif
917 if (
918# ifdef _G_LSEEK64
919 _G_LSEEK64
920# else
921 __lseek
922# endif
923 (fp->_fileno, fp->_IO_read_ptr - fp->_IO_buf_base, SEEK_SET)
924 != fp->_IO_read_ptr - fp->_IO_buf_base)
925 {
926 fp->_flags |= _IO_ERR_SEEN;
927 return EOF;
928 }
929 }
930 fp->_offset = fp->_IO_read_ptr - fp->_IO_buf_base;
931 fp->_IO_read_end = fp->_IO_read_ptr = fp->_IO_read_base;
932 return 0;
933}
934
935
d64b6ad0 936_IO_off64_t
b259e746 937_IO_new_file_seekoff (fp, offset, dir, mode)
40a55d20 938 _IO_FILE *fp;
dfd2257a 939 _IO_off64_t offset;
40a55d20
UD
940 int dir;
941 int mode;
96aa2d94 942{
d64b6ad0 943 _IO_off64_t result;
dfd2257a 944 _IO_off64_t delta, new_offset;
96aa2d94 945 long count;
feb3c934
UD
946 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
947 offset of the underlying file must be exact. */
948 int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
949 && fp->_IO_write_base == fp->_IO_write_ptr);
96aa2d94
RM
950
951 if (mode == 0)
952 dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
953
954 /* Flush unwritten characters.
955 (This may do an unneeded write if we seek within the buffer.
956 But to be able to switch to reading, we would need to set
957 egptr to ptr. That can't be done in the current design,
958 which assumes file_ptr() is eGptr. Anyway, since we probably
959 end up flushing when we close(), it doesn't make much difference.)
960 FIXME: simulate mem-papped files. */
961
40a55d20 962 if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
77fe0b9c 963 if (INTUSE(_IO_switch_to_get_mode) (fp))
40a55d20 964 return EOF;
96aa2d94
RM
965
966 if (fp->_IO_buf_base == NULL)
967 {
00bc5db0
UD
968 /* It could be that we already have a pushback buffer. */
969 if (fp->_IO_read_base != NULL)
970 {
971 free (fp->_IO_read_base);
972 fp->_flags &= ~_IO_IN_BACKUP;
973 }
77fe0b9c 974 INTUSE(_IO_doallocbuf) (fp);
40a55d20
UD
975 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
976 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
96aa2d94
RM
977 }
978
979 switch (dir)
980 {
981 case _IO_seek_cur:
982 /* Adjust for read-ahead (bytes is buffer). */
983 offset -= fp->_IO_read_end - fp->_IO_read_ptr;
bd355af0 984 if (fp->_offset == _IO_pos_BAD)
96aa2d94
RM
985 goto dumb;
986 /* Make offset absolute, assuming current pointer is file_ptr(). */
d64b6ad0 987 offset += fp->_offset;
405550bf
UD
988 if (offset < 0)
989 {
990 __set_errno (EINVAL);
991 return EOF;
992 }
96aa2d94
RM
993
994 dir = _IO_seek_set;
995 break;
996 case _IO_seek_set:
997 break;
998 case _IO_seek_end:
999 {
dfd2257a 1000 struct _G_stat64 st;
40a55d20 1001 if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
96aa2d94
RM
1002 {
1003 offset += st.st_size;
1004 dir = _IO_seek_set;
1005 }
1006 else
1007 goto dumb;
1008 }
1009 }
1010 /* At this point, dir==_IO_seek_set. */
1011
00bc5db0
UD
1012 /* If we are only interested in the current position we've found it now. */
1013 if (mode == 0)
1014 return offset;
1015
96aa2d94 1016 /* If destination is within current buffer, optimize: */
bd355af0 1017 if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
96aa2d94
RM
1018 && !_IO_in_backup (fp))
1019 {
1020 /* Offset relative to start of main get area. */
d64b6ad0
UD
1021 _IO_off64_t rel_offset = (offset - fp->_offset
1022 + (fp->_IO_read_end - fp->_IO_read_base));
96aa2d94
RM
1023 if (rel_offset >= 0)
1024 {
1025#if 0
40a55d20
UD
1026 if (_IO_in_backup (fp))
1027 _IO_switch_to_main_get_area (fp);
96aa2d94
RM
1028#endif
1029 if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
1030 {
40a55d20
UD
1031 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
1032 fp->_IO_read_end);
1033 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
00bc5db0
UD
1034 {
1035 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
4a582094 1036 goto resync;
00bc5db0 1037 }
96aa2d94
RM
1038 }
1039#ifdef TODO
1040 /* If we have streammarkers, seek forward by reading ahead. */
40a55d20 1041 if (_IO_have_markers (fp))
96aa2d94
RM
1042 {
1043 int to_skip = rel_offset
1044 - (fp->_IO_read_ptr - fp->_IO_read_base);
40a55d20 1045 if (ignore (to_skip) != to_skip)
96aa2d94 1046 goto dumb;
00bc5db0 1047 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
4a582094 1048 goto resync;
96aa2d94
RM
1049 }
1050#endif
1051 }
1052#ifdef TODO
40a55d20 1053 if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ())
96aa2d94 1054 {
40a55d20
UD
1055 if (!_IO_in_backup (fp))
1056 _IO_switch_to_backup_area (fp);
1057 gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
00bc5db0 1058 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
4a582094 1059 goto resync;
96aa2d94
RM
1060 }
1061#endif
1062 }
1063
1064#ifdef TODO
77fe0b9c 1065 INTUSE(_IO_unsave_markers) (fp);
96aa2d94
RM
1066#endif
1067
1068 if (fp->_flags & _IO_NO_READS)
1069 goto dumb;
1070
1071 /* Try to seek to a block boundary, to improve kernel page management. */
1072 new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
1073 delta = offset - new_offset;
1074 if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
1075 {
1076 new_offset = offset;
1077 delta = 0;
1078 }
1079 result = _IO_SYSSEEK (fp, new_offset, 0);
1080 if (result < 0)
1081 return EOF;
1082 if (delta == 0)
1083 count = 0;
1084 else
1085 {
1086 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
feb3c934
UD
1087 (must_be_exact
1088 ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
96aa2d94
RM
1089 if (count < delta)
1090 {
1091 /* We weren't allowed to read, but try to seek the remainder. */
1092 offset = count == EOF ? delta : delta-count;
1093 dir = _IO_seek_cur;
1094 goto dumb;
1095 }
1096 }
40a55d20
UD
1097 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
1098 fp->_IO_buf_base + count);
1099 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
bd355af0 1100 fp->_offset = result + count;
40a55d20 1101 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
96aa2d94
RM
1102 return offset;
1103 dumb:
1104
77fe0b9c 1105 INTUSE(_IO_unsave_markers) (fp);
96aa2d94
RM
1106 result = _IO_SYSSEEK (fp, offset, dir);
1107 if (result != EOF)
d762684b
UD
1108 {
1109 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
1110 fp->_offset = result;
1111 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
1112 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
1113 }
96aa2d94 1114 return result;
4a582094
UD
1115
1116resync:
1117 /* We need to do it since it is possible that the file offset in
1118 the kernel may be changed behind our back. It may happen when
1119 we fopen a file and then do a fork. One process may access the
1120 the file and the kernel file offset will be changed. */
1121 if (fp->_offset >= 0)
1122 _IO_SYSSEEK (fp, fp->_offset, 0);
1123
1124 return offset;
96aa2d94 1125}
77fe0b9c 1126INTDEF2(_IO_new_file_seekoff, _IO_file_seekoff)
96aa2d94 1127
284749da
UD
1128_IO_off64_t
1129_IO_file_seekoff_mmap (fp, offset, dir, mode)
1130 _IO_FILE *fp;
1131 _IO_off64_t offset;
1132 int dir;
1133 int mode;
1134{
1135 _IO_off64_t result;
1136
7e93f915
RM
1137 /* If we are only interested in the current position, calculate it and
1138 return right now. This calculation does the right thing when we are
1139 using a pushback buffer, but in the usual case has the same value as
1140 (fp->_IO_read_ptr - fp->_IO_buf_base). */
284749da 1141 if (mode == 0)
78ce5a3b 1142 return fp->_offset - (fp->_IO_read_end - fp->_IO_read_ptr);
284749da
UD
1143
1144 switch (dir)
1145 {
1146 case _IO_seek_cur:
1147 /* Adjust for read-ahead (bytes is buffer). */
1148 offset += fp->_IO_read_ptr - fp->_IO_read_base;
1149 break;
1150 case _IO_seek_set:
1151 break;
1152 case _IO_seek_end:
903b3396 1153 offset += fp->_IO_buf_end - fp->_IO_buf_base;
284749da
UD
1154 break;
1155 }
1156 /* At this point, dir==_IO_seek_set. */
1157
1158 if (offset < 0)
66bff409
UD
1159 {
1160 /* No negative offsets are valid. */
1161 __set_errno (EINVAL);
1162 return EOF;
1163 }
284749da 1164
284749da
UD
1165 result = _IO_SYSSEEK (fp, offset, 0);
1166 if (result < 0)
1167 return EOF;
1168
fc77d66a
RM
1169 if (offset > fp->_IO_buf_end - fp->_IO_buf_base)
1170 /* One can fseek arbitrarily past the end of the file
1171 and it is meaningless until one attempts to read.
1172 Leave the buffer pointers in EOF state until underflow. */
1173 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_end, fp->_IO_buf_end);
1174 else
1175 /* Adjust the read pointers to match the file position,
1176 but so the next read attempt will call underflow. */
1177 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + offset,
1178 fp->_IO_buf_base + offset);
1179
66bff409 1180 fp->_offset = result;
284749da
UD
1181
1182 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
1183
1184 return offset;
1185}
1186
acbee5f6
RM
1187_IO_off64_t
1188_IO_file_seekoff_maybe_mmap (fp, offset, dir, mode)
1189 _IO_FILE *fp;
1190 _IO_off64_t offset;
1191 int dir;
1192 int mode;
1193{
1194 /* We only get here when we haven't tried to read anything yet.
1195 So there is nothing more useful for us to do here than just
1196 the underlying lseek call. */
1197
1198 _IO_off64_t result = _IO_SYSSEEK (fp, offset, dir);
1199 if (result < 0)
1200 return EOF;
1201
1202 fp->_offset = result;
1203 return result;
1204}
1205
96aa2d94 1206_IO_ssize_t
40a55d20
UD
1207_IO_file_read (fp, buf, size)
1208 _IO_FILE *fp;
1209 void *buf;
1210 _IO_ssize_t size;
96aa2d94 1211{
61eb22d3 1212 return read (fp->_fileno, buf, size);
96aa2d94 1213}
77fe0b9c 1214INTDEF(_IO_file_read)
96aa2d94 1215
d64b6ad0 1216_IO_off64_t
40a55d20
UD
1217_IO_file_seek (fp, offset, dir)
1218 _IO_FILE *fp;
dfd2257a 1219 _IO_off64_t offset;
40a55d20 1220 int dir;
96aa2d94 1221{
dfd2257a
UD
1222#ifdef _G_LSEEK64
1223 return _G_LSEEK64 (fp->_fileno, offset, dir);
1224#else
61eb22d3 1225 return lseek (fp->_fileno, offset, dir);
dfd2257a 1226#endif
96aa2d94 1227}
77fe0b9c 1228INTDEF(_IO_file_seek)
96aa2d94
RM
1229
1230int
40a55d20
UD
1231_IO_file_stat (fp, st)
1232 _IO_FILE *fp;
1233 void *st;
96aa2d94 1234{
279eb600 1235#ifdef _G_FSTAT64
dfd2257a
UD
1236 return _G_FSTAT64 (fp->_fileno, (struct _G_stat64 *) st);
1237#else
319d719d 1238 return fstat (fp->_fileno, (struct stat *) st);
dfd2257a 1239#endif
96aa2d94 1240}
77fe0b9c 1241INTDEF(_IO_file_stat)
96aa2d94 1242
0469311e
UD
1243int
1244_IO_file_close_mmap (fp)
1245 _IO_FILE *fp;
1246{
acbee5f6
RM
1247 /* In addition to closing the file descriptor we have to unmap the file. */
1248 (void) __munmap (fp->_IO_buf_base, fp->_IO_buf_end - fp->_IO_buf_base);
0469311e
UD
1249 fp->_IO_buf_base = fp->_IO_buf_end = NULL;
1250 return close (fp->_fileno);
1251}
1252
96aa2d94 1253int
40a55d20
UD
1254_IO_file_close (fp)
1255 _IO_FILE *fp;
96aa2d94 1256{
61eb22d3 1257 return close (fp->_fileno);
96aa2d94 1258}
77fe0b9c 1259INTDEF(_IO_file_close)
96aa2d94
RM
1260
1261_IO_ssize_t
b259e746 1262_IO_new_file_write (f, data, n)
40a55d20
UD
1263 _IO_FILE *f;
1264 const void *data;
1265 _IO_ssize_t n;
96aa2d94
RM
1266{
1267 _IO_ssize_t to_do = n;
1268 while (to_do > 0)
1269 {
61eb22d3 1270 _IO_ssize_t count = write (f->_fileno, data, to_do);
d64b6ad0 1271 if (count < 0)
96aa2d94 1272 {
39e16978
UD
1273 f->_flags |= _IO_ERR_SEEN;
1274 break;
96aa2d94
RM
1275 }
1276 to_do -= count;
40a55d20 1277 data = (void *) ((char *) data + count);
96aa2d94
RM
1278 }
1279 n -= to_do;
bd355af0
UD
1280 if (f->_offset >= 0)
1281 f->_offset += n;
96aa2d94
RM
1282 return n;
1283}
1284
1285_IO_size_t
b259e746 1286_IO_new_file_xsputn (f, data, n)
40a55d20
UD
1287 _IO_FILE *f;
1288 const void *data;
1289 _IO_size_t n;
96aa2d94 1290{
d64b6ad0 1291 register const char *s = (const char *) data;
96aa2d94
RM
1292 _IO_size_t to_do = n;
1293 int must_flush = 0;
1294 _IO_size_t count;
1295
1296 if (n <= 0)
1297 return 0;
1298 /* This is an optimized implementation.
1299 If the amount to be written straddles a block boundary
1300 (or the filebuf is unbuffered), use sys_write directly. */
1301
1302 /* First figure out how much space is available in the buffer. */
1303 count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
1304 if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
1305 {
1306 count = f->_IO_buf_end - f->_IO_write_ptr;
1307 if (count >= n)
40a55d20
UD
1308 {
1309 register const char *p;
96aa2d94
RM
1310 for (p = s + n; p > s; )
1311 {
40a55d20
UD
1312 if (*--p == '\n')
1313 {
1314 count = p - s + 1;
1315 must_flush = 1;
1316 break;
1317 }
96aa2d94
RM
1318 }
1319 }
1320 }
1321 /* Then fill the buffer. */
1322 if (count > 0)
1323 {
1324 if (count > to_do)
1325 count = to_do;
40a55d20
UD
1326 if (count > 20)
1327 {
86187531
UD
1328#ifdef _LIBC
1329 f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
1330#else
40a55d20 1331 memcpy (f->_IO_write_ptr, s, count);
86187531
UD
1332 f->_IO_write_ptr += count;
1333#endif
40a55d20
UD
1334 s += count;
1335 }
96aa2d94
RM
1336 else
1337 {
1338 register char *p = f->_IO_write_ptr;
40a55d20
UD
1339 register int i = (int) count;
1340 while (--i >= 0)
1341 *p++ = *s++;
86187531 1342 f->_IO_write_ptr = p;
96aa2d94 1343 }
96aa2d94
RM
1344 to_do -= count;
1345 }
1346 if (to_do + must_flush > 0)
40a55d20 1347 {
0720f75c 1348 _IO_size_t block_size, do_write;
96aa2d94 1349 /* Next flush the (full) buffer. */
5c8d1fc0 1350 if (_IO_OVERFLOW (f, EOF) == EOF)
96aa2d94
RM
1351 return n - to_do;
1352
1353 /* Try to maintain alignment: write a whole number of blocks.
1354 dont_write is what gets left over. */
1355 block_size = f->_IO_buf_end - f->_IO_buf_base;
0720f75c
UD
1356 do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
1357
1358 if (do_write)
1359 {
1360 count = new_do_write (f, s, do_write);
1361 to_do -= count;
1362 if (count < do_write)
1363 return n - to_do;
1364 }
23396375 1365
96aa2d94
RM
1366 /* Now write out the remainder. Normally, this will fit in the
1367 buffer, but it's somewhat messier for line-buffered files,
1368 so we let _IO_default_xsputn handle the general case. */
0720f75c 1369 if (to_do)
77fe0b9c 1370 to_do -= INTUSE(_IO_default_xsputn) (f, s+do_write, to_do);
96aa2d94
RM
1371 }
1372 return n - to_do;
1373}
77fe0b9c 1374INTDEF2(_IO_new_file_xsputn, _IO_file_xsputn)
96aa2d94 1375
96aa2d94 1376_IO_size_t
40a55d20
UD
1377_IO_file_xsgetn (fp, data, n)
1378 _IO_FILE *fp;
1379 void *data;
1380 _IO_size_t n;
96aa2d94 1381{
4bca4c17
UD
1382 register _IO_size_t want, have;
1383 register _IO_ssize_t count;
96aa2d94 1384 register char *s = data;
8fe0fd03
UD
1385
1386 want = n;
1387
310f9518
UD
1388 if (fp->_IO_buf_base == NULL)
1389 {
1390 /* Maybe we already have a push back pointer. */
1391 if (fp->_IO_save_base != NULL)
1392 {
1393 free (fp->_IO_save_base);
1394 fp->_flags &= ~_IO_IN_BACKUP;
1395 }
77fe0b9c 1396 INTUSE(_IO_doallocbuf) (fp);
310f9518
UD
1397 }
1398
8fe0fd03 1399 while (want > 0)
96aa2d94 1400 {
8fe0fd03
UD
1401 have = fp->_IO_read_end - fp->_IO_read_ptr;
1402 if (want <= have)
96aa2d94 1403 {
8fe0fd03
UD
1404 memcpy (s, fp->_IO_read_ptr, want);
1405 fp->_IO_read_ptr += want;
1406 want = 0;
1407 }
1408 else
1409 {
1410 if (have > 0)
96aa2d94 1411 {
279eb600
UD
1412#ifdef _LIBC
1413 s = __mempcpy (s, fp->_IO_read_ptr, have);
1414#else
8fe0fd03 1415 memcpy (s, fp->_IO_read_ptr, have);
8fe0fd03 1416 s += have;
279eb600
UD
1417#endif
1418 want -= have;
8fe0fd03 1419 fp->_IO_read_ptr += have;
96aa2d94 1420 }
8fe0fd03
UD
1421
1422 /* Check for backup and repeat */
1423 if (_IO_in_backup (fp))
96aa2d94 1424 {
8fe0fd03
UD
1425 _IO_switch_to_main_get_area (fp);
1426 continue;
1427 }
1428
1429 /* If we now want less than a buffer, underflow and repeat
1430 the copy. Otherwise, _IO_SYSREAD directly to
1431 the user buffer. */
6dd67bd5
UD
1432 if (fp->_IO_buf_base
1433 && want < (size_t) (fp->_IO_buf_end - fp->_IO_buf_base))
8fe0fd03
UD
1434 {
1435 if (__underflow (fp) == EOF)
1436 break;
1437
1438 continue;
1439 }
1440
4bca4c17
UD
1441 /* These must be set before the sysread as we might longjmp out
1442 waiting for input. */
1443 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
1444 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
1445
279eb600
UD
1446 /* Try to maintain alignment: read a whole number of blocks. */
1447 count = want;
1448 if (fp->_IO_buf_base)
1449 {
1450 _IO_size_t block_size = fp->_IO_buf_end - fp->_IO_buf_base;
1451 if (block_size >= 128)
1452 count -= want % block_size;
1453 }
1454
1455 count = _IO_SYSREAD (fp, s, count);
96aa2d94 1456 if (count <= 0)
8fe0fd03
UD
1457 {
1458 if (count == 0)
1459 fp->_flags |= _IO_EOF_SEEN;
1460 else
1461 fp->_flags |= _IO_ERR_SEEN;
1462
1463 break;
1464 }
23396375 1465
96aa2d94 1466 s += count;
8fe0fd03 1467 want -= count;
4bca4c17
UD
1468 if (fp->_offset != _IO_pos_BAD)
1469 _IO_pos_adjust (fp->_offset, count);
96aa2d94 1470 }
96aa2d94 1471 }
8fe0fd03
UD
1472
1473 return n - want;
96aa2d94 1474}
77fe0b9c 1475INTDEF(_IO_file_xsgetn)
96aa2d94 1476
284749da
UD
1477static _IO_size_t _IO_file_xsgetn_mmap __P ((_IO_FILE *, void *, _IO_size_t));
1478static _IO_size_t
1479_IO_file_xsgetn_mmap (fp, data, n)
1480 _IO_FILE *fp;
1481 void *data;
1482 _IO_size_t n;
1483{
1484 register _IO_size_t have;
1485 char *read_ptr = fp->_IO_read_ptr;
b39d5719 1486 register char *s = (char *) data;
284749da
UD
1487
1488 have = fp->_IO_read_end - fp->_IO_read_ptr;
1489
1490 if (have < n)
1491 {
b39d5719
UD
1492 if (__builtin_expect (_IO_in_backup (fp), 0))
1493 {
1494#ifdef _LIBC
1495 s = __mempcpy (s, read_ptr, have);
1496#else
1497 memcpy (s, read_ptr, have);
1498 s += have;
1499#endif
1500 n -= have;
1501 _IO_switch_to_main_get_area (fp);
1502 read_ptr = fp->_IO_read_ptr;
1503 have = fp->_IO_read_end - fp->_IO_read_ptr;
1504 }
1505
1506 if (have < n)
1507 {
acbee5f6
RM
1508 /* Check that we are mapping all of the file, in case it grew. */
1509 if (__builtin_expect (mmap_remap_check (fp), 0))
1510 /* We punted mmap, so complete with the vanilla code. */
1511 return s - (char *) data + _IO_XSGETN (fp, data, n);
1512
1513 read_ptr = fp->_IO_read_ptr;
1514 have = fp->_IO_read_end - read_ptr;
b39d5719 1515 }
284749da
UD
1516 }
1517
c4292489
UD
1518 if (have < n)
1519 fp->_flags |= _IO_EOF_SEEN;
1520
1521 if (have != 0)
284749da
UD
1522 {
1523 have = MIN (have, n);
b39d5719
UD
1524#ifdef _LIBC
1525 s = __mempcpy (s, read_ptr, have);
1526#else
1527 memcpy (s, read_ptr, have);
1528 s += have;
1529#endif
284749da
UD
1530 fp->_IO_read_ptr = read_ptr + have;
1531 }
1532
b39d5719 1533 return s - (char *) data;
284749da
UD
1534}
1535
acbee5f6
RM
1536static _IO_size_t _IO_file_xsgetn_maybe_mmap __P ((_IO_FILE *, void *,
1537 _IO_size_t));
1538static _IO_size_t
1539_IO_file_xsgetn_maybe_mmap (fp, data, n)
1540 _IO_FILE *fp;
1541 void *data;
1542 _IO_size_t n;
1543{
1544 /* We only get here if this is the first attempt to read something.
1545 Decide which operations to use and then punt to the chosen one. */
1546
1547 decide_maybe_mmap (fp);
1548 return _IO_XSGETN (fp, data, n);
1549}
1550
94b68ee9 1551#ifdef _LIBC
4483f2c0 1552# undef _IO_do_write
94b68ee9
RM
1553versioned_symbol (libc, _IO_new_do_write, _IO_do_write, GLIBC_2_1);
1554versioned_symbol (libc, _IO_new_file_attach, _IO_file_attach, GLIBC_2_1);
1555versioned_symbol (libc, _IO_new_file_close_it, _IO_file_close_it, GLIBC_2_1);
1556versioned_symbol (libc, _IO_new_file_finish, _IO_file_finish, GLIBC_2_1);
1557versioned_symbol (libc, _IO_new_file_fopen, _IO_file_fopen, GLIBC_2_1);
1558versioned_symbol (libc, _IO_new_file_init, _IO_file_init, GLIBC_2_1);
1559versioned_symbol (libc, _IO_new_file_setbuf, _IO_file_setbuf, GLIBC_2_1);
1560versioned_symbol (libc, _IO_new_file_sync, _IO_file_sync, GLIBC_2_1);
1561versioned_symbol (libc, _IO_new_file_overflow, _IO_file_overflow, GLIBC_2_1);
1562versioned_symbol (libc, _IO_new_file_seekoff, _IO_file_seekoff, GLIBC_2_1);
1563versioned_symbol (libc, _IO_new_file_underflow, _IO_file_underflow, GLIBC_2_1);
1564versioned_symbol (libc, _IO_new_file_write, _IO_file_write, GLIBC_2_1);
1565versioned_symbol (libc, _IO_new_file_xsputn, _IO_file_xsputn, GLIBC_2_1);
1566#endif
1567
40a55d20
UD
1568struct _IO_jump_t _IO_file_jumps =
1569{
96aa2d94 1570 JUMP_INIT_DUMMY,
77fe0b9c
UD
1571 JUMP_INIT(finish, INTUSE(_IO_file_finish)),
1572 JUMP_INIT(overflow, INTUSE(_IO_file_overflow)),
1573 JUMP_INIT(underflow, INTUSE(_IO_file_underflow)),
1574 JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
1575 JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
1576 JUMP_INIT(xsputn, INTUSE(_IO_file_xsputn)),
1577 JUMP_INIT(xsgetn, INTUSE(_IO_file_xsgetn)),
b259e746 1578 JUMP_INIT(seekoff, _IO_new_file_seekoff),
96aa2d94 1579 JUMP_INIT(seekpos, _IO_default_seekpos),
b259e746
UD
1580 JUMP_INIT(setbuf, _IO_new_file_setbuf),
1581 JUMP_INIT(sync, _IO_new_file_sync),
77fe0b9c
UD
1582 JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
1583 JUMP_INIT(read, INTUSE(_IO_file_read)),
b259e746 1584 JUMP_INIT(write, _IO_new_file_write),
77fe0b9c
UD
1585 JUMP_INIT(seek, INTUSE(_IO_file_seek)),
1586 JUMP_INIT(close, INTUSE(_IO_file_close)),
1587 JUMP_INIT(stat, INTUSE(_IO_file_stat)),
dfd2257a 1588 JUMP_INIT(showmanyc, _IO_default_showmanyc),
0469311e
UD
1589 JUMP_INIT(imbue, _IO_default_imbue)
1590};
100351c3 1591INTVARDEF(_IO_file_jumps)
0469311e
UD
1592
1593struct _IO_jump_t _IO_file_jumps_mmap =
1594{
1595 JUMP_INIT_DUMMY,
77fe0b9c
UD
1596 JUMP_INIT(finish, INTUSE(_IO_file_finish)),
1597 JUMP_INIT(overflow, INTUSE(_IO_file_overflow)),
0469311e 1598 JUMP_INIT(underflow, _IO_file_underflow_mmap),
77fe0b9c
UD
1599 JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
1600 JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
0469311e 1601 JUMP_INIT(xsputn, _IO_new_file_xsputn),
284749da
UD
1602 JUMP_INIT(xsgetn, _IO_file_xsgetn_mmap),
1603 JUMP_INIT(seekoff, _IO_file_seekoff_mmap),
0469311e 1604 JUMP_INIT(seekpos, _IO_default_seekpos),
bff334e0 1605 JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
acbee5f6 1606 JUMP_INIT(sync, _IO_file_sync_mmap),
77fe0b9c
UD
1607 JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
1608 JUMP_INIT(read, INTUSE(_IO_file_read)),
0469311e 1609 JUMP_INIT(write, _IO_new_file_write),
77fe0b9c 1610 JUMP_INIT(seek, INTUSE(_IO_file_seek)),
0469311e 1611 JUMP_INIT(close, _IO_file_close_mmap),
77fe0b9c 1612 JUMP_INIT(stat, INTUSE(_IO_file_stat)),
0469311e 1613 JUMP_INIT(showmanyc, _IO_default_showmanyc),
acbee5f6
RM
1614 JUMP_INIT(imbue, _IO_default_imbue)
1615};
1616
1617struct _IO_jump_t _IO_file_jumps_maybe_mmap =
1618{
1619 JUMP_INIT_DUMMY,
1620 JUMP_INIT(finish, INTUSE(_IO_file_finish)),
1621 JUMP_INIT(overflow, INTUSE(_IO_file_overflow)),
1622 JUMP_INIT(underflow, _IO_file_underflow_maybe_mmap),
1623 JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
1624 JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
1625 JUMP_INIT(xsputn, _IO_new_file_xsputn),
1626 JUMP_INIT(xsgetn, _IO_file_xsgetn_maybe_mmap),
1627 JUMP_INIT(seekoff, _IO_file_seekoff_maybe_mmap),
1628 JUMP_INIT(seekpos, _IO_default_seekpos),
1629 JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
1630 JUMP_INIT(sync, _IO_new_file_sync),
1631 JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
1632 JUMP_INIT(read, INTUSE(_IO_file_read)),
1633 JUMP_INIT(write, _IO_new_file_write),
1634 JUMP_INIT(seek, INTUSE(_IO_file_seek)),
1635 JUMP_INIT(close, _IO_file_close),
1636 JUMP_INIT(stat, INTUSE(_IO_file_stat)),
1637 JUMP_INIT(showmanyc, _IO_default_showmanyc),
dfd2257a 1638 JUMP_INIT(imbue, _IO_default_imbue)
96aa2d94 1639};