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