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