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