1 /* Copyright (C) 1993,95,97,98,99,2000,2001,2002 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Written by Ulrich Drepper <drepper@cygnus.com>.
4 Based on the single byte version by Per Bothner <bothner@cygnus.com>.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 As a special exception, if you link the code in this file with
22 files compiled with a GNU compiler to produce an executable,
23 that does not cause the resulting executable to be covered by
24 the GNU Lesser General Public License. This exception does not
25 however invalidate any other reasons why the executable file
26 might be covered by the GNU Lesser General Public License.
27 This exception applies to code released by its copyright holders
28 in files containing the exception. */
40 # define _IO_new_do_write _IO_do_write
41 # define _IO_new_file_attach _IO_file_attach
42 # define _IO_new_file_close_it _IO_file_close_it
43 # define _IO_new_file_finish _IO_file_finish
44 # define _IO_new_file_fopen _IO_file_fopen
45 # define _IO_new_file_init _IO_file_init
46 # define _IO_new_file_setbuf _IO_file_setbuf
47 # define _IO_new_file_sync _IO_file_sync
48 # define _IO_new_file_overflow _IO_file_overflow
49 # define _IO_new_file_seekoff _IO_file_seekoff
50 # define _IO_new_file_underflow _IO_file_underflow
51 # define _IO_new_file_write _IO_file_write
52 # define _IO_new_file_xsputn _IO_file_xsputn
56 /* Convert TO_DO wide character from DATA to FP.
57 Then mark FP as having empty buffers. */
59 _IO_wdo_write (fp
, data
, to_do
)
64 struct _IO_codecvt
*cc
= fp
->_codecvt
;
68 if (fp
->_IO_write_end
== fp
->_IO_write_ptr
69 && fp
->_IO_write_end
!= fp
->_IO_write_base
)
71 if (_IO_new_do_write (fp
, fp
->_IO_write_base
,
72 fp
->_IO_write_ptr
- fp
->_IO_write_base
) == EOF
)
78 enum __codecvt_result result
;
79 const wchar_t *new_data
;
81 /* Now convert from the internal format into the external buffer. */
82 result
= (*cc
->__codecvt_do_out
) (cc
, &fp
->_wide_data
->_IO_state
,
83 data
, data
+ to_do
, &new_data
,
88 /* Write out what we produced so far. */
89 if (_IO_new_do_write (fp
, fp
->_IO_write_base
,
90 fp
->_IO_write_ptr
- fp
->_IO_write_base
) == EOF
)
91 /* Something went wrong. */
94 to_do
-= new_data
- data
;
96 /* Next see whether we had problems during the conversion. If yes,
98 if (result
!= __codecvt_ok
99 && (result
!= __codecvt_partial
|| new_data
- data
== 0))
107 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
,
108 fp
->_wide_data
->_IO_buf_base
);
109 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
110 = fp
->_wide_data
->_IO_buf_base
;
111 fp
->_wide_data
->_IO_write_end
= ((fp
->_flags
& (_IO_LINE_BUF
+_IO_UNBUFFERED
))
112 ? fp
->_wide_data
->_IO_buf_base
113 : fp
->_wide_data
->_IO_buf_end
);
115 return to_do
== 0 ? 0 : WEOF
;
117 INTDEF(_IO_wdo_write
)
121 _IO_wfile_underflow (fp
)
124 struct _IO_codecvt
*cd
;
125 enum __codecvt_result status
;
128 const char *read_ptr_copy
;
130 if (__builtin_expect (fp
->_flags
& _IO_NO_READS
, 0))
132 fp
->_flags
|= _IO_ERR_SEEN
;
136 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
137 return *fp
->_wide_data
->_IO_read_ptr
;
141 /* Maybe there is something left in the external buffer. */
142 if (fp
->_IO_read_ptr
< fp
->_IO_read_end
)
144 /* There is more in the external. Convert it. */
145 const char *read_stop
= (const char *) fp
->_IO_read_ptr
;
147 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
148 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
=
149 fp
->_wide_data
->_IO_buf_base
;
150 status
= (*cd
->__codecvt_do_in
) (cd
, &fp
->_wide_data
->_IO_state
,
151 fp
->_IO_read_ptr
, fp
->_IO_read_end
,
153 fp
->_wide_data
->_IO_read_ptr
,
154 fp
->_wide_data
->_IO_buf_end
,
155 &fp
->_wide_data
->_IO_read_end
);
157 fp
->_IO_read_ptr
= (char *) read_stop
;
159 /* If we managed to generate some text return the next character. */
160 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
161 return *fp
->_wide_data
->_IO_read_ptr
;
163 if (status
== __codecvt_error
)
165 __set_errno (EILSEQ
);
166 fp
->_flags
|= _IO_ERR_SEEN
;
170 /* Move the remaining content of the read buffer to the beginning. */
171 memmove (fp
->_IO_buf_base
, fp
->_IO_read_ptr
,
172 fp
->_IO_read_end
- fp
->_IO_read_ptr
);
173 fp
->_IO_read_end
= (fp
->_IO_buf_base
174 + (fp
->_IO_read_end
- fp
->_IO_read_ptr
));
175 fp
->_IO_read_base
= fp
->_IO_read_ptr
= fp
->_IO_buf_base
;
178 fp
->_IO_read_base
= fp
->_IO_read_ptr
= fp
->_IO_read_end
=
181 if (fp
->_IO_buf_base
== NULL
)
183 /* Maybe we already have a push back pointer. */
184 if (fp
->_IO_save_base
!= NULL
)
186 free (fp
->_IO_save_base
);
187 fp
->_flags
&= ~_IO_IN_BACKUP
;
189 INTUSE(_IO_doallocbuf
) (fp
);
191 fp
->_IO_read_base
= fp
->_IO_read_ptr
= fp
->_IO_read_end
=
195 fp
->_IO_write_base
= fp
->_IO_write_ptr
= fp
->_IO_write_end
=
198 if (fp
->_wide_data
->_IO_buf_base
== NULL
)
200 /* Maybe we already have a push back pointer. */
201 if (fp
->_wide_data
->_IO_save_base
!= NULL
)
203 free (fp
->_wide_data
->_IO_save_base
);
204 fp
->_flags
&= ~_IO_IN_BACKUP
;
206 INTUSE(_IO_wdoallocbuf
) (fp
);
209 /* Flush all line buffered files before reading. */
210 /* FIXME This can/should be moved to genops ?? */
211 if (fp
->_flags
& (_IO_LINE_BUF
|_IO_UNBUFFERED
))
214 INTUSE(_IO_flush_all_linebuffered
) ();
216 /* We used to flush all line-buffered stream. This really isn't
217 required by any standard. My recollection is that
218 traditional Unix systems did this for stdout. stderr better
219 not be line buffered. So we do just that here
220 explicitly. --drepper */
221 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile
,
223 _IO_flockfile (_IO_stdout
);
225 if ((_IO_stdout
->_flags
& (_IO_LINKED
| _IO_NO_WRITES
| _IO_LINE_BUF
))
226 == (_IO_LINKED
| _IO_LINE_BUF
))
227 _IO_OVERFLOW (_IO_stdout
, EOF
);
229 _IO_funlockfile (_IO_stdout
);
230 _IO_cleanup_region_end (0);
234 INTUSE(_IO_switch_to_get_mode
) (fp
);
236 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
=
237 fp
->_wide_data
->_IO_buf_base
;
238 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_buf_base
;
239 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
=
240 fp
->_wide_data
->_IO_write_end
= fp
->_wide_data
->_IO_buf_base
;
244 count
= _IO_SYSREAD (fp
, fp
->_IO_read_end
,
245 fp
->_IO_buf_end
- fp
->_IO_read_end
);
248 if (count
== 0 && tries
== 0)
249 fp
->_flags
|= _IO_EOF_SEEN
;
251 fp
->_flags
|= _IO_ERR_SEEN
, count
= 0;
253 fp
->_IO_read_end
+= count
;
257 /* There are some bytes in the external buffer but they don't
258 convert to anything. */
259 __set_errno (EILSEQ
);
262 if (fp
->_offset
!= _IO_pos_BAD
)
263 _IO_pos_adjust (fp
->_offset
, count
);
265 /* Now convert the read input. */
266 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
267 fp
->_IO_read_base
= fp
->_IO_read_ptr
;
268 status
= (*cd
->__codecvt_do_in
) (cd
, &fp
->_wide_data
->_IO_state
,
269 fp
->_IO_read_ptr
, fp
->_IO_read_end
,
271 fp
->_wide_data
->_IO_read_end
,
272 fp
->_wide_data
->_IO_buf_end
,
273 &fp
->_wide_data
->_IO_read_end
);
275 fp
->_IO_read_ptr
= (char *) read_ptr_copy
;
276 if (fp
->_wide_data
->_IO_read_end
== fp
->_wide_data
->_IO_buf_base
)
278 if (status
== __codecvt_error
|| fp
->_IO_read_end
== fp
->_IO_buf_end
)
280 __set_errno (EILSEQ
);
281 fp
->_flags
|= _IO_ERR_SEEN
;
285 /* The read bytes make no complete character. Try reading again. */
286 assert (status
== __codecvt_partial
);
291 return *fp
->_wide_data
->_IO_read_ptr
;
293 INTDEF(_IO_wfile_underflow
)
298 _IO_wfile_underflow_mmap (_IO_FILE
*fp
)
300 struct _IO_codecvt
*cd
;
301 enum __codecvt_result status
;
302 const char *read_stop
;
304 if (__builtin_expect (fp
->_flags
& _IO_NO_READS
, 0))
306 fp
->_flags
|= _IO_ERR_SEEN
;
310 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
311 return *fp
->_wide_data
->_IO_read_ptr
;
315 /* Maybe there is something left in the external buffer. */
316 if (fp
->_IO_read_ptr
>= fp
->_IO_read_end
317 /* No. But maybe the read buffer is not fully set up. */
318 && _IO_file_underflow_mmap (fp
) == EOF
)
319 /* Nothing available. _IO_file_underflow_mmap has set the EOF or error
320 flags as appropriate. */
323 /* There is more in the external. Convert it. */
324 read_stop
= (const char *) fp
->_IO_read_ptr
;
326 if (fp
->_wide_data
->_IO_buf_base
== NULL
)
328 /* Maybe we already have a push back pointer. */
329 if (fp
->_wide_data
->_IO_save_base
!= NULL
)
331 free (fp
->_wide_data
->_IO_save_base
);
332 fp
->_flags
&= ~_IO_IN_BACKUP
;
334 INTUSE(_IO_wdoallocbuf
) (fp
);
337 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
338 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
=
339 fp
->_wide_data
->_IO_buf_base
;
340 status
= (*cd
->__codecvt_do_in
) (cd
, &fp
->_wide_data
->_IO_state
,
341 fp
->_IO_read_ptr
, fp
->_IO_read_end
,
343 fp
->_wide_data
->_IO_read_ptr
,
344 fp
->_wide_data
->_IO_buf_end
,
345 &fp
->_wide_data
->_IO_read_end
);
347 fp
->_IO_read_ptr
= (char *) read_stop
;
349 /* If we managed to generate some text return the next character. */
350 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
351 return *fp
->_wide_data
->_IO_read_ptr
;
353 /* There is some garbage at the end of the file. */
354 __set_errno (EILSEQ
);
355 fp
->_flags
|= _IO_ERR_SEEN
;
360 _IO_wfile_underflow_maybe_mmap (_IO_FILE
*fp
)
362 /* This is the first read attempt. Doing the underflow will choose mmap
363 or vanilla operations and then punt to the chosen underflow routine.
364 Then we can punt to ours. */
365 if (_IO_file_underflow_maybe_mmap (fp
) == EOF
)
368 return _IO_WUNDERFLOW (fp
);
374 _IO_wfile_overflow (f
, wch
)
378 if (f
->_flags
& _IO_NO_WRITES
) /* SET ERROR */
380 f
->_flags
|= _IO_ERR_SEEN
;
384 /* If currently reading or no buffer allocated. */
385 if ((f
->_flags
& _IO_CURRENTLY_PUTTING
) == 0)
387 /* Allocate a buffer if needed. */
388 if (f
->_wide_data
->_IO_write_base
== 0)
390 INTUSE(_IO_wdoallocbuf
) (f
);
391 _IO_wsetg (f
, f
->_wide_data
->_IO_buf_base
,
392 f
->_wide_data
->_IO_buf_base
, f
->_wide_data
->_IO_buf_base
);
394 if (f
->_IO_write_base
== NULL
)
396 INTUSE(_IO_doallocbuf
) (f
);
397 _IO_setg (f
, f
->_IO_buf_base
, f
->_IO_buf_base
, f
->_IO_buf_base
);
402 /* Otherwise must be currently reading. If _IO_read_ptr
403 (and hence also _IO_read_end) is at the buffer end,
404 logically slide the buffer forwards one block (by setting
405 the read pointers to all point at the beginning of the
406 block). This makes room for subsequent output.
407 Otherwise, set the read pointers to _IO_read_end (leaving
408 that alone, so it can continue to correspond to the
409 external position). */
410 if (f
->_wide_data
->_IO_read_ptr
== f
->_wide_data
->_IO_buf_end
)
412 f
->_IO_read_end
= f
->_IO_read_ptr
= f
->_IO_buf_base
;
413 f
->_wide_data
->_IO_read_end
= f
->_wide_data
->_IO_read_ptr
=
414 f
->_wide_data
->_IO_buf_base
;
417 f
->_wide_data
->_IO_write_ptr
= f
->_wide_data
->_IO_read_ptr
;
418 f
->_wide_data
->_IO_write_base
= f
->_wide_data
->_IO_write_ptr
;
419 f
->_wide_data
->_IO_write_end
= f
->_wide_data
->_IO_buf_end
;
420 f
->_wide_data
->_IO_read_base
= f
->_wide_data
->_IO_read_ptr
=
421 f
->_wide_data
->_IO_read_end
;
423 f
->_IO_write_ptr
= f
->_IO_read_ptr
;
424 f
->_IO_write_base
= f
->_IO_write_ptr
;
425 f
->_IO_write_end
= f
->_IO_buf_end
;
426 f
->_IO_read_base
= f
->_IO_read_ptr
= f
->_IO_read_end
;
428 f
->_flags
|= _IO_CURRENTLY_PUTTING
;
429 if (f
->_flags
& (_IO_LINE_BUF
+_IO_UNBUFFERED
))
430 f
->_wide_data
->_IO_write_end
= f
->_wide_data
->_IO_write_ptr
;
433 return _IO_do_flush (f
);
434 if (f
->_wide_data
->_IO_write_ptr
== f
->_wide_data
->_IO_buf_end
)
435 /* Buffer is really full */
436 if (_IO_do_flush (f
) == EOF
)
438 *f
->_wide_data
->_IO_write_ptr
++ = wch
;
439 if ((f
->_flags
& _IO_UNBUFFERED
)
440 || ((f
->_flags
& _IO_LINE_BUF
) && wch
== L
'\n'))
441 if (_IO_do_flush (f
) == EOF
)
445 INTDEF(_IO_wfile_overflow
)
454 /* char* ptr = cur_ptr(); */
455 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_write_base
)
456 if (_IO_do_flush (fp
))
458 delta
= fp
->_wide_data
->_IO_read_ptr
- fp
->_wide_data
->_IO_read_end
;
461 /* We have to find out how many bytes we have to go back in the
463 struct _IO_codecvt
*cv
= fp
->_codecvt
;
466 int clen
= (*cv
->__codecvt_do_encoding
) (cv
);
469 /* It is easy, a fixed number of input bytes are used for each
474 /* We have to find out the hard way how much to back off.
475 To do this we determine how much input we needed to
476 generate the wide characters up to the current reading
480 fp
->_wide_data
->_IO_state
= fp
->_wide_data
->_IO_last_state
;
481 nread
= (*cv
->__codecvt_do_length
) (cv
, &fp
->_wide_data
->_IO_state
,
483 fp
->_IO_read_end
, delta
);
484 fp
->_IO_read_ptr
= fp
->_IO_read_base
+ nread
;
485 delta
= -(fp
->_IO_read_end
- fp
->_IO_read_base
- nread
);
488 new_pos
= _IO_SYSSEEK (fp
, delta
, 1);
489 if (new_pos
!= (_IO_off64_t
) EOF
)
491 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_read_ptr
;
492 fp
->_IO_read_end
= fp
->_IO_read_ptr
;
495 else if (errno
== ESPIPE
)
496 ; /* Ignore error from unseekable devices. */
502 fp
->_offset
= _IO_pos_BAD
;
503 /* FIXME: Cleanup - can this be shared? */
504 /* setg(base(), ptr, ptr); */
507 INTDEF(_IO_wfile_sync
)
510 _IO_wfile_seekoff (fp
, offset
, dir
, mode
)
517 _IO_off64_t delta
, new_offset
;
519 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
520 offset of the underlying file must be exact. */
521 int must_be_exact
= ((fp
->_wide_data
->_IO_read_base
522 == fp
->_wide_data
->_IO_read_end
)
523 && (fp
->_wide_data
->_IO_write_base
524 == fp
->_wide_data
->_IO_write_ptr
));
528 /* XXX For wide stream with backup store it is not very
529 reasonable to determine the offset. The pushed-back
530 character might require a state change and we need not be
531 able to compute the initial state by reverse transformation
532 since there is no guarantee of symmetry. So we don't even
533 try and return an error. */
534 if (_IO_in_backup (fp
))
536 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
538 __set_errno (EINVAL
);
542 /* There is no more data in the backup buffer. We can
544 INTUSE(_IO_switch_to_main_wget_area
) (fp
);
547 dir
= _IO_seek_cur
, offset
= 0; /* Don't move any pointers. */
550 /* Flush unwritten characters.
551 (This may do an unneeded write if we seek within the buffer.
552 But to be able to switch to reading, we would need to set
553 egptr to ptr. That can't be done in the current design,
554 which assumes file_ptr() is eGptr. Anyway, since we probably
555 end up flushing when we close(), it doesn't make much difference.)
556 FIXME: simulate mem-mapped files. */
558 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_write_base
559 || _IO_in_put_mode (fp
))
560 if (INTUSE(_IO_switch_to_wget_mode
) (fp
))
563 if (fp
->_wide_data
->_IO_buf_base
== NULL
)
565 /* It could be that we already have a pushback buffer. */
566 if (fp
->_wide_data
->_IO_read_base
!= NULL
)
568 free (fp
->_wide_data
->_IO_read_base
);
569 fp
->_flags
&= ~_IO_IN_BACKUP
;
571 INTUSE(_IO_doallocbuf
) (fp
);
572 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
573 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
574 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
,
575 fp
->_wide_data
->_IO_buf_base
);
576 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
577 fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
582 struct _IO_codecvt
*cv
;
586 /* Adjust for read-ahead (bytes is buffer). To do this we must
587 find out which position in the external buffer corresponds to
588 the current position in the internal buffer. */
590 clen
= (*cv
->__codecvt_do_encoding
) (cv
);
593 offset
-= (fp
->_wide_data
->_IO_read_end
594 - fp
->_wide_data
->_IO_read_ptr
) * clen
;
599 delta
= fp
->_wide_data
->_IO_read_ptr
- fp
->_wide_data
->_IO_read_base
;
600 fp
->_wide_data
->_IO_state
= fp
->_wide_data
->_IO_last_state
;
601 nread
= (*cv
->__codecvt_do_length
) (cv
, &fp
->_wide_data
->_IO_state
,
603 fp
->_IO_read_end
, delta
);
604 fp
->_IO_read_ptr
= fp
->_IO_read_base
+ nread
;
605 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_read_ptr
;
606 offset
-= fp
->_IO_read_end
- fp
->_IO_read_base
- nread
;
609 if (fp
->_offset
== _IO_pos_BAD
)
611 /* Make offset absolute, assuming current pointer is file_ptr(). */
612 offset
+= fp
->_offset
;
621 if (_IO_SYSSTAT (fp
, &st
) == 0 && S_ISREG (st
.st_mode
))
623 offset
+= st
.st_size
;
630 /* At this point, dir==_IO_seek_set. */
632 /* If we are only interested in the current position we've found it now. */
636 /* If destination is within current buffer, optimize: */
637 if (fp
->_offset
!= _IO_pos_BAD
&& fp
->_IO_read_base
!= NULL
638 && !_IO_in_backup (fp
))
640 /* Offset relative to start of main get area. */
641 _IO_off64_t rel_offset
= (offset
- fp
->_offset
642 + (fp
->_IO_read_end
- fp
->_IO_buf_base
));
646 if (_IO_in_backup (fp
))
647 _IO_switch_to_main_get_area (fp
);
649 if (rel_offset
<= fp
->_IO_read_end
- fp
->_IO_buf_base
)
651 enum __codecvt_result status
;
652 struct _IO_codecvt
*cd
= fp
->_codecvt
;
653 const char *read_ptr_copy
;
655 fp
->_IO_read_ptr
= fp
->_IO_read_base
+ rel_offset
;
656 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
658 /* Now set the pointer for the internal buffer. This
659 might be an iterative process. Though the read
660 pointer is somewhere in the current external buffer
661 this does not mean we can convert this whole buffer
662 at once fitting in the internal buffer. */
663 fp
->_wide_data
->_IO_state
= fp
->_wide_data
->_IO_last_state
;
664 read_ptr_copy
= fp
->_IO_read_base
;
665 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_base
;
668 wchar_t buffer
[1024];
670 status
= (*cd
->__codecvt_do_in
) (cd
,
671 &fp
->_wide_data
->_IO_state
,
678 / sizeof (buffer
[0])),
680 if (status
!= __codecvt_ok
&& status
!= __codecvt_partial
)
682 fp
->_flags
|= _IO_ERR_SEEN
;
686 while (read_ptr_copy
!= fp
->_IO_read_ptr
);
688 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_base
;
690 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
694 /* If we have streammarkers, seek forward by reading ahead. */
695 if (_IO_have_markers (fp
))
697 int to_skip
= rel_offset
698 - (fp
->_IO_read_ptr
- fp
->_IO_read_base
);
699 if (ignore (to_skip
) != to_skip
)
701 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
707 if (rel_offset
< 0 && rel_offset
>= Bbase () - Bptr ())
709 if (!_IO_in_backup (fp
))
710 _IO_switch_to_backup_area (fp
);
711 gbump (fp
->_IO_read_end
+ rel_offset
- fp
->_IO_read_ptr
);
712 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
719 INTUSE(_IO_unsave_markers
) (fp
);
722 if (fp
->_flags
& _IO_NO_READS
)
725 /* Try to seek to a block boundary, to improve kernel page management. */
726 new_offset
= offset
& ~(fp
->_IO_buf_end
- fp
->_IO_buf_base
- 1);
727 delta
= offset
- new_offset
;
728 if (delta
> fp
->_IO_buf_end
- fp
->_IO_buf_base
)
733 result
= _IO_SYSSEEK (fp
, new_offset
, 0);
740 count
= _IO_SYSREAD (fp
, fp
->_IO_buf_base
,
742 ? delta
: fp
->_IO_buf_end
- fp
->_IO_buf_base
));
745 /* We weren't allowed to read, but try to seek the remainder. */
746 offset
= count
== EOF
? delta
: delta
-count
;
751 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
+ delta
,
752 fp
->_IO_buf_base
+ count
);
753 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
754 fp
->_offset
= result
+ count
;
755 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
759 INTUSE(_IO_unsave_markers
) (fp
);
760 result
= _IO_SYSSEEK (fp
, offset
, dir
);
763 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
764 fp
->_offset
= result
;
765 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
766 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
767 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
768 fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
769 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
,
770 fp
->_wide_data
->_IO_buf_base
);
775 /* We need to do it since it is possible that the file offset in
776 the kernel may be changed behind our back. It may happen when
777 we fopen a file and then do a fork. One process may access the
778 the file and the kernel file offset will be changed. */
779 if (fp
->_offset
>= 0)
780 _IO_SYSSEEK (fp
, fp
->_offset
, 0);
784 INTDEF(_IO_wfile_seekoff
)
788 _IO_wfile_xsputn (f
, data
, n
)
793 register const wchar_t *s
= (const wchar_t *) data
;
794 _IO_size_t to_do
= n
;
800 /* This is an optimized implementation.
801 If the amount to be written straddles a block boundary
802 (or the filebuf is unbuffered), use sys_write directly. */
804 /* First figure out how much space is available in the buffer. */
805 count
= f
->_wide_data
->_IO_write_end
- f
->_wide_data
->_IO_write_ptr
;
806 if ((f
->_flags
& _IO_LINE_BUF
) && (f
->_flags
& _IO_CURRENTLY_PUTTING
))
808 count
= f
->_wide_data
->_IO_buf_end
- f
->_wide_data
->_IO_write_ptr
;
811 register const wchar_t *p
;
812 for (p
= s
+ n
; p
> s
; )
823 /* Then fill the buffer. */
831 f
->_wide_data
->_IO_write_ptr
=
832 __wmempcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
834 wmemcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
835 f
->_wide_data
->_IO_write_ptr
+= count
;
841 register wchar_t *p
= f
->_wide_data
->_IO_write_ptr
;
842 register int i
= (int) count
;
845 f
->_wide_data
->_IO_write_ptr
= p
;
850 to_do
-= INTUSE(_IO_wdefault_xsputn
) (f
, s
, to_do
);
852 && f
->_wide_data
->_IO_write_ptr
!= f
->_wide_data
->_IO_write_base
)
853 INTUSE(_IO_wdo_write
) (f
, f
->_wide_data
->_IO_write_base
,
854 f
->_wide_data
->_IO_write_ptr
855 - f
->_wide_data
->_IO_write_base
);
859 INTDEF(_IO_wfile_xsputn
)
862 struct _IO_jump_t _IO_wfile_jumps
=
865 JUMP_INIT(finish
, _IO_new_file_finish
),
866 JUMP_INIT(overflow
, (_IO_overflow_t
) INTUSE(_IO_wfile_overflow
)),
867 JUMP_INIT(underflow
, (_IO_underflow_t
) INTUSE(_IO_wfile_underflow
)),
868 JUMP_INIT(uflow
, (_IO_underflow_t
) INTUSE(_IO_wdefault_uflow
)),
869 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) INTUSE(_IO_wdefault_pbackfail
)),
870 JUMP_INIT(xsputn
, INTUSE(_IO_wfile_xsputn
)),
871 JUMP_INIT(xsgetn
, INTUSE(_IO_file_xsgetn
)),
872 JUMP_INIT(seekoff
, INTUSE(_IO_wfile_seekoff
)),
873 JUMP_INIT(seekpos
, _IO_default_seekpos
),
874 JUMP_INIT(setbuf
, _IO_new_file_setbuf
),
875 JUMP_INIT(sync
, (_IO_sync_t
) INTUSE(_IO_wfile_sync
)),
876 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
877 JUMP_INIT(read
, INTUSE(_IO_file_read
)),
878 JUMP_INIT(write
, _IO_new_file_write
),
879 JUMP_INIT(seek
, INTUSE(_IO_file_seek
)),
880 JUMP_INIT(close
, INTUSE(_IO_file_close
)),
881 JUMP_INIT(stat
, INTUSE(_IO_file_stat
)),
882 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
883 JUMP_INIT(imbue
, _IO_default_imbue
)
885 INTVARDEF(_IO_wfile_jumps
)
889 struct _IO_jump_t _IO_wfile_jumps_mmap
=
892 JUMP_INIT(finish
, _IO_new_file_finish
),
893 JUMP_INIT(overflow
, (_IO_overflow_t
) INTUSE(_IO_wfile_overflow
)),
894 JUMP_INIT(underflow
, (_IO_underflow_t
) _IO_wfile_underflow_mmap
),
895 JUMP_INIT(uflow
, (_IO_underflow_t
) INTUSE(_IO_wdefault_uflow
)),
896 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) INTUSE(_IO_wdefault_pbackfail
)),
897 JUMP_INIT(xsputn
, INTUSE(_IO_wfile_xsputn
)),
898 JUMP_INIT(xsgetn
, INTUSE(_IO_file_xsgetn
)),
899 JUMP_INIT(seekoff
, INTUSE(_IO_wfile_seekoff
)),
900 JUMP_INIT(seekpos
, _IO_default_seekpos
),
901 JUMP_INIT(setbuf
, _IO_file_setbuf_mmap
),
902 JUMP_INIT(sync
, (_IO_sync_t
) INTUSE(_IO_wfile_sync
)),
903 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
904 JUMP_INIT(read
, INTUSE(_IO_file_read
)),
905 JUMP_INIT(write
, _IO_new_file_write
),
906 JUMP_INIT(seek
, INTUSE(_IO_file_seek
)),
907 JUMP_INIT(close
, _IO_file_close_mmap
),
908 JUMP_INIT(stat
, INTUSE(_IO_file_stat
)),
909 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
910 JUMP_INIT(imbue
, _IO_default_imbue
)
913 struct _IO_jump_t _IO_wfile_jumps_maybe_mmap
=
916 JUMP_INIT(finish
, _IO_new_file_finish
),
917 JUMP_INIT(overflow
, (_IO_overflow_t
) INTUSE(_IO_wfile_overflow
)),
918 JUMP_INIT(underflow
, (_IO_underflow_t
) _IO_wfile_underflow_maybe_mmap
),
919 JUMP_INIT(uflow
, (_IO_underflow_t
) INTUSE(_IO_wdefault_uflow
)),
920 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) INTUSE(_IO_wdefault_pbackfail
)),
921 JUMP_INIT(xsputn
, INTUSE(_IO_wfile_xsputn
)),
922 JUMP_INIT(xsgetn
, INTUSE(_IO_file_xsgetn
)),
923 JUMP_INIT(seekoff
, INTUSE(_IO_wfile_seekoff
)),
924 JUMP_INIT(seekpos
, _IO_default_seekpos
),
925 JUMP_INIT(setbuf
, _IO_file_setbuf_mmap
),
926 JUMP_INIT(sync
, (_IO_sync_t
) INTUSE(_IO_wfile_sync
)),
927 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
928 JUMP_INIT(read
, INTUSE(_IO_file_read
)),
929 JUMP_INIT(write
, _IO_new_file_write
),
930 JUMP_INIT(seek
, INTUSE(_IO_file_seek
)),
931 JUMP_INIT(close
, INTUSE(_IO_file_close
)),
932 JUMP_INIT(stat
, INTUSE(_IO_file_stat
)),
933 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
934 JUMP_INIT(imbue
, _IO_default_imbue
)