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