1 /* Copyright (C) 1993-2014 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, see
18 <http://www.gnu.org/licenses/>.
20 As a special exception, if you link the code in this file with
21 files compiled with a GNU compiler to produce an executable,
22 that does not cause the resulting executable to be covered by
23 the GNU Lesser General Public License. This exception does not
24 however invalidate any other reasons why the executable file
25 might be covered by the GNU Lesser General Public License.
26 This exception applies to code released by its copyright holders
27 in files containing the exception. */
38 # define _IO_new_do_write _IO_do_write
39 # define _IO_new_file_attach _IO_file_attach
40 # define _IO_new_file_close_it _IO_file_close_it
41 # define _IO_new_file_finish _IO_file_finish
42 # define _IO_new_file_fopen _IO_file_fopen
43 # define _IO_new_file_init _IO_file_init
44 # define _IO_new_file_setbuf _IO_file_setbuf
45 # define _IO_new_file_sync _IO_file_sync
46 # define _IO_new_file_overflow _IO_file_overflow
47 # define _IO_new_file_seekoff _IO_file_seekoff
48 # define _IO_new_file_underflow _IO_file_underflow
49 # define _IO_new_file_write _IO_file_write
50 # define _IO_new_file_xsputn _IO_file_xsputn
54 /* Convert TO_DO wide character from DATA to FP.
55 Then mark FP as having empty buffers. */
57 _IO_wdo_write (fp
, data
, to_do
)
62 struct _IO_codecvt
*cc
= fp
->_codecvt
;
66 if (fp
->_IO_write_end
== fp
->_IO_write_ptr
67 && fp
->_IO_write_end
!= fp
->_IO_write_base
)
69 if (_IO_new_do_write (fp
, fp
->_IO_write_base
,
70 fp
->_IO_write_ptr
- fp
->_IO_write_base
) == EOF
)
76 enum __codecvt_result result
;
77 const wchar_t *new_data
;
78 char mb_buf
[MB_LEN_MAX
];
79 char *write_base
, *write_ptr
, *buf_end
;
81 if (fp
->_IO_write_ptr
- fp
->_IO_write_base
< sizeof (mb_buf
))
83 /* Make sure we have room for at least one multibyte
85 write_ptr
= write_base
= mb_buf
;
86 buf_end
= mb_buf
+ sizeof (mb_buf
);
90 write_ptr
= fp
->_IO_write_ptr
;
91 write_base
= fp
->_IO_write_base
;
92 buf_end
= fp
->_IO_buf_end
;
95 /* Now convert from the internal format into the external buffer. */
96 result
= (*cc
->__codecvt_do_out
) (cc
, &fp
->_wide_data
->_IO_state
,
97 data
, data
+ to_do
, &new_data
,
102 /* Write out what we produced so far. */
103 if (_IO_new_do_write (fp
, write_base
, write_ptr
- write_base
) == EOF
)
104 /* Something went wrong. */
107 to_do
-= new_data
- data
;
109 /* Next see whether we had problems during the conversion. If yes,
111 if (result
!= __codecvt_ok
112 && (result
!= __codecvt_partial
|| new_data
- data
== 0))
120 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
,
121 fp
->_wide_data
->_IO_buf_base
);
122 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
123 = fp
->_wide_data
->_IO_buf_base
;
124 fp
->_wide_data
->_IO_write_end
= ((fp
->_flags
& (_IO_LINE_BUF
+_IO_UNBUFFERED
))
125 ? fp
->_wide_data
->_IO_buf_base
126 : fp
->_wide_data
->_IO_buf_end
);
128 return to_do
== 0 ? 0 : WEOF
;
130 libc_hidden_def (_IO_wdo_write
)
134 _IO_wfile_underflow (fp
)
137 struct _IO_codecvt
*cd
;
138 enum __codecvt_result status
;
141 if (__glibc_unlikely (fp
->_flags
& _IO_NO_READS
))
143 fp
->_flags
|= _IO_ERR_SEEN
;
147 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
148 return *fp
->_wide_data
->_IO_read_ptr
;
152 /* Maybe there is something left in the external buffer. */
153 if (fp
->_IO_read_ptr
< fp
->_IO_read_end
)
155 /* There is more in the external. Convert it. */
156 const char *read_stop
= (const char *) fp
->_IO_read_ptr
;
158 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
159 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
=
160 fp
->_wide_data
->_IO_buf_base
;
161 status
= (*cd
->__codecvt_do_in
) (cd
, &fp
->_wide_data
->_IO_state
,
162 fp
->_IO_read_ptr
, fp
->_IO_read_end
,
164 fp
->_wide_data
->_IO_read_ptr
,
165 fp
->_wide_data
->_IO_buf_end
,
166 &fp
->_wide_data
->_IO_read_end
);
168 fp
->_IO_read_base
= fp
->_IO_read_ptr
;
169 fp
->_IO_read_ptr
= (char *) read_stop
;
171 /* If we managed to generate some text return the next character. */
172 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
173 return *fp
->_wide_data
->_IO_read_ptr
;
175 if (status
== __codecvt_error
)
177 __set_errno (EILSEQ
);
178 fp
->_flags
|= _IO_ERR_SEEN
;
182 /* Move the remaining content of the read buffer to the beginning. */
183 memmove (fp
->_IO_buf_base
, fp
->_IO_read_ptr
,
184 fp
->_IO_read_end
- fp
->_IO_read_ptr
);
185 fp
->_IO_read_end
= (fp
->_IO_buf_base
186 + (fp
->_IO_read_end
- fp
->_IO_read_ptr
));
187 fp
->_IO_read_base
= fp
->_IO_read_ptr
= fp
->_IO_buf_base
;
190 fp
->_IO_read_base
= fp
->_IO_read_ptr
= fp
->_IO_read_end
=
193 if (fp
->_IO_buf_base
== NULL
)
195 /* Maybe we already have a push back pointer. */
196 if (fp
->_IO_save_base
!= NULL
)
198 free (fp
->_IO_save_base
);
199 fp
->_flags
&= ~_IO_IN_BACKUP
;
203 fp
->_IO_read_base
= fp
->_IO_read_ptr
= fp
->_IO_read_end
=
207 fp
->_IO_write_base
= fp
->_IO_write_ptr
= fp
->_IO_write_end
=
210 if (fp
->_wide_data
->_IO_buf_base
== NULL
)
212 /* Maybe we already have a push back pointer. */
213 if (fp
->_wide_data
->_IO_save_base
!= NULL
)
215 free (fp
->_wide_data
->_IO_save_base
);
216 fp
->_flags
&= ~_IO_IN_BACKUP
;
218 _IO_wdoallocbuf (fp
);
221 /* Flush all line buffered files before reading. */
222 /* FIXME This can/should be moved to genops ?? */
223 if (fp
->_flags
& (_IO_LINE_BUF
|_IO_UNBUFFERED
))
226 _IO_flush_all_linebuffered ();
228 /* We used to flush all line-buffered stream. This really isn't
229 required by any standard. My recollection is that
230 traditional Unix systems did this for stdout. stderr better
231 not be line buffered. So we do just that here
232 explicitly. --drepper */
233 _IO_acquire_lock (_IO_stdout
);
235 if ((_IO_stdout
->_flags
& (_IO_LINKED
| _IO_NO_WRITES
| _IO_LINE_BUF
))
236 == (_IO_LINKED
| _IO_LINE_BUF
))
237 _IO_OVERFLOW (_IO_stdout
, EOF
);
239 _IO_release_lock (_IO_stdout
);
243 _IO_switch_to_get_mode (fp
);
245 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
=
246 fp
->_wide_data
->_IO_buf_base
;
247 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_buf_base
;
248 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
=
249 fp
->_wide_data
->_IO_write_end
= fp
->_wide_data
->_IO_buf_base
;
251 const char *read_ptr_copy
;
252 char accbuf
[MB_LEN_MAX
];
255 count
= _IO_SYSREAD (fp
, fp
->_IO_read_end
,
256 fp
->_IO_buf_end
- fp
->_IO_read_end
);
259 if (count
== 0 && naccbuf
== 0)
260 fp
->_flags
|= _IO_EOF_SEEN
;
262 fp
->_flags
|= _IO_ERR_SEEN
, count
= 0;
264 fp
->_IO_read_end
+= count
;
268 /* There are some bytes in the external buffer but they don't
269 convert to anything. */
270 __set_errno (EILSEQ
);
273 if (fp
->_offset
!= _IO_pos_BAD
)
274 _IO_pos_adjust (fp
->_offset
, count
);
276 /* Now convert the read input. */
277 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
278 fp
->_IO_read_base
= fp
->_IO_read_ptr
;
279 const char *from
= fp
->_IO_read_ptr
;
280 const char *to
= fp
->_IO_read_end
;
281 size_t to_copy
= count
;
282 if (__glibc_unlikely (naccbuf
!= 0))
284 to_copy
= MIN (sizeof (accbuf
) - naccbuf
, count
);
285 to
= __mempcpy (&accbuf
[naccbuf
], from
, to_copy
);
289 status
= (*cd
->__codecvt_do_in
) (cd
, &fp
->_wide_data
->_IO_state
,
290 from
, to
, &read_ptr_copy
,
291 fp
->_wide_data
->_IO_read_end
,
292 fp
->_wide_data
->_IO_buf_end
,
293 &fp
->_wide_data
->_IO_read_end
);
295 if (__glibc_unlikely (naccbuf
!= 0))
296 fp
->_IO_read_ptr
+= MAX (0, read_ptr_copy
- &accbuf
[naccbuf
- to_copy
]);
298 fp
->_IO_read_ptr
= (char *) read_ptr_copy
;
299 if (fp
->_wide_data
->_IO_read_end
== fp
->_wide_data
->_IO_buf_base
)
301 if (status
== __codecvt_error
)
304 __set_errno (EILSEQ
);
305 fp
->_flags
|= _IO_ERR_SEEN
;
309 /* The read bytes make no complete character. Try reading again. */
310 assert (status
== __codecvt_partial
);
314 if (fp
->_IO_read_base
< fp
->_IO_read_ptr
)
316 /* Partially used the buffer for some input data that
317 produces no output. */
318 size_t avail
= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
319 memmove (fp
->_IO_read_base
, fp
->_IO_read_ptr
, avail
);
320 fp
->_IO_read_ptr
= fp
->_IO_read_base
;
321 fp
->_IO_read_end
-= avail
;
324 naccbuf
= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
325 if (naccbuf
>= sizeof (accbuf
))
328 memcpy (accbuf
, fp
->_IO_read_ptr
, naccbuf
);
332 size_t used
= read_ptr_copy
- accbuf
;
335 memmove (accbuf
, read_ptr_copy
, naccbuf
- used
);
339 if (naccbuf
== sizeof (accbuf
))
343 fp
->_IO_read_ptr
= fp
->_IO_read_end
= fp
->_IO_read_base
;
348 return *fp
->_wide_data
->_IO_read_ptr
;
350 libc_hidden_def (_IO_wfile_underflow
)
354 _IO_wfile_underflow_mmap (_IO_FILE
*fp
)
356 struct _IO_codecvt
*cd
;
357 const char *read_stop
;
359 if (__glibc_unlikely (fp
->_flags
& _IO_NO_READS
))
361 fp
->_flags
|= _IO_ERR_SEEN
;
365 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
366 return *fp
->_wide_data
->_IO_read_ptr
;
370 /* Maybe there is something left in the external buffer. */
371 if (fp
->_IO_read_ptr
>= fp
->_IO_read_end
372 /* No. But maybe the read buffer is not fully set up. */
373 && _IO_file_underflow_mmap (fp
) == EOF
)
374 /* Nothing available. _IO_file_underflow_mmap has set the EOF or error
375 flags as appropriate. */
378 /* There is more in the external. Convert it. */
379 read_stop
= (const char *) fp
->_IO_read_ptr
;
381 if (fp
->_wide_data
->_IO_buf_base
== NULL
)
383 /* Maybe we already have a push back pointer. */
384 if (fp
->_wide_data
->_IO_save_base
!= NULL
)
386 free (fp
->_wide_data
->_IO_save_base
);
387 fp
->_flags
&= ~_IO_IN_BACKUP
;
389 _IO_wdoallocbuf (fp
);
392 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
393 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
=
394 fp
->_wide_data
->_IO_buf_base
;
395 (*cd
->__codecvt_do_in
) (cd
, &fp
->_wide_data
->_IO_state
,
396 fp
->_IO_read_ptr
, fp
->_IO_read_end
,
398 fp
->_wide_data
->_IO_read_ptr
,
399 fp
->_wide_data
->_IO_buf_end
,
400 &fp
->_wide_data
->_IO_read_end
);
402 fp
->_IO_read_ptr
= (char *) read_stop
;
404 /* If we managed to generate some text return the next character. */
405 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
406 return *fp
->_wide_data
->_IO_read_ptr
;
408 /* There is some garbage at the end of the file. */
409 __set_errno (EILSEQ
);
410 fp
->_flags
|= _IO_ERR_SEEN
;
415 _IO_wfile_underflow_maybe_mmap (_IO_FILE
*fp
)
417 /* This is the first read attempt. Doing the underflow will choose mmap
418 or vanilla operations and then punt to the chosen underflow routine.
419 Then we can punt to ours. */
420 if (_IO_file_underflow_maybe_mmap (fp
) == EOF
)
423 return _IO_WUNDERFLOW (fp
);
428 _IO_wfile_overflow (f
, wch
)
432 if (f
->_flags
& _IO_NO_WRITES
) /* SET ERROR */
434 f
->_flags
|= _IO_ERR_SEEN
;
438 /* If currently reading or no buffer allocated. */
439 if ((f
->_flags
& _IO_CURRENTLY_PUTTING
) == 0)
441 /* Allocate a buffer if needed. */
442 if (f
->_wide_data
->_IO_write_base
== 0)
445 _IO_wsetg (f
, f
->_wide_data
->_IO_buf_base
,
446 f
->_wide_data
->_IO_buf_base
, f
->_wide_data
->_IO_buf_base
);
448 if (f
->_IO_write_base
== NULL
)
451 _IO_setg (f
, f
->_IO_buf_base
, f
->_IO_buf_base
, f
->_IO_buf_base
);
456 /* Otherwise must be currently reading. If _IO_read_ptr
457 (and hence also _IO_read_end) is at the buffer end,
458 logically slide the buffer forwards one block (by setting
459 the read pointers to all point at the beginning of the
460 block). This makes room for subsequent output.
461 Otherwise, set the read pointers to _IO_read_end (leaving
462 that alone, so it can continue to correspond to the
463 external position). */
464 if (f
->_wide_data
->_IO_read_ptr
== f
->_wide_data
->_IO_buf_end
)
466 f
->_IO_read_end
= f
->_IO_read_ptr
= f
->_IO_buf_base
;
467 f
->_wide_data
->_IO_read_end
= f
->_wide_data
->_IO_read_ptr
=
468 f
->_wide_data
->_IO_buf_base
;
471 f
->_wide_data
->_IO_write_ptr
= f
->_wide_data
->_IO_read_ptr
;
472 f
->_wide_data
->_IO_write_base
= f
->_wide_data
->_IO_write_ptr
;
473 f
->_wide_data
->_IO_write_end
= f
->_wide_data
->_IO_buf_end
;
474 f
->_wide_data
->_IO_read_base
= f
->_wide_data
->_IO_read_ptr
=
475 f
->_wide_data
->_IO_read_end
;
477 f
->_IO_write_ptr
= f
->_IO_read_ptr
;
478 f
->_IO_write_base
= f
->_IO_write_ptr
;
479 f
->_IO_write_end
= f
->_IO_buf_end
;
480 f
->_IO_read_base
= f
->_IO_read_ptr
= f
->_IO_read_end
;
482 f
->_flags
|= _IO_CURRENTLY_PUTTING
;
483 if (f
->_flags
& (_IO_LINE_BUF
+_IO_UNBUFFERED
))
484 f
->_wide_data
->_IO_write_end
= f
->_wide_data
->_IO_write_ptr
;
487 return _IO_do_flush (f
);
488 if (f
->_wide_data
->_IO_write_ptr
== f
->_wide_data
->_IO_buf_end
)
489 /* Buffer is really full */
490 if (_IO_do_flush (f
) == EOF
)
492 *f
->_wide_data
->_IO_write_ptr
++ = wch
;
493 if ((f
->_flags
& _IO_UNBUFFERED
)
494 || ((f
->_flags
& _IO_LINE_BUF
) && wch
== L
'\n'))
495 if (_IO_do_flush (f
) == EOF
)
499 libc_hidden_def (_IO_wfile_overflow
)
508 /* char* ptr = cur_ptr(); */
509 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_write_base
)
510 if (_IO_do_flush (fp
))
512 delta
= fp
->_wide_data
->_IO_read_ptr
- fp
->_wide_data
->_IO_read_end
;
515 /* We have to find out how many bytes we have to go back in the
517 struct _IO_codecvt
*cv
= fp
->_codecvt
;
520 int clen
= (*cv
->__codecvt_do_encoding
) (cv
);
523 /* It is easy, a fixed number of input bytes are used for each
528 /* We have to find out the hard way how much to back off.
529 To do this we determine how much input we needed to
530 generate the wide characters up to the current reading
534 fp
->_wide_data
->_IO_state
= fp
->_wide_data
->_IO_last_state
;
535 nread
= (*cv
->__codecvt_do_length
) (cv
, &fp
->_wide_data
->_IO_state
,
537 fp
->_IO_read_end
, delta
);
538 fp
->_IO_read_ptr
= fp
->_IO_read_base
+ nread
;
539 delta
= -(fp
->_IO_read_end
- fp
->_IO_read_base
- nread
);
542 new_pos
= _IO_SYSSEEK (fp
, delta
, 1);
543 if (new_pos
!= (_IO_off64_t
) EOF
)
545 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_read_ptr
;
546 fp
->_IO_read_end
= fp
->_IO_read_ptr
;
549 else if (errno
== ESPIPE
)
550 ; /* Ignore error from unseekable devices. */
556 fp
->_offset
= _IO_pos_BAD
;
557 /* FIXME: Cleanup - can this be shared? */
558 /* setg(base(), ptr, ptr); */
561 libc_hidden_def (_IO_wfile_sync
)
563 /* Adjust the internal buffer pointers to reflect the state in the external
564 buffer. The content between fp->_IO_read_base and fp->_IO_read_ptr is
565 assumed to be converted and available in the range
566 fp->_wide_data->_IO_read_base and fp->_wide_data->_IO_read_end.
568 Returns 0 on success and -1 on error with the _IO_ERR_SEEN flag set. */
570 adjust_wide_data (_IO_FILE
*fp
, bool do_convert
)
572 struct _IO_codecvt
*cv
= fp
->_codecvt
;
574 int clen
= (*cv
->__codecvt_do_encoding
) (cv
);
576 /* Take the easy way out for constant length encodings if we don't need to
578 if (!do_convert
&& clen
> 0)
580 fp
->_wide_data
->_IO_read_end
+= ((fp
->_IO_read_ptr
- fp
->_IO_read_base
)
585 enum __codecvt_result status
;
586 const char *read_stop
= (const char *) fp
->_IO_read_base
;
590 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
591 status
= (*cv
->__codecvt_do_in
) (cv
, &fp
->_wide_data
->_IO_state
,
592 fp
->_IO_read_base
, fp
->_IO_read_ptr
,
594 fp
->_wide_data
->_IO_read_base
,
595 fp
->_wide_data
->_IO_buf_end
,
596 &fp
->_wide_data
->_IO_read_end
);
598 /* Should we return EILSEQ? */
599 if (__glibc_unlikely (status
== __codecvt_error
))
601 fp
->_flags
|= _IO_ERR_SEEN
;
605 while (__builtin_expect (status
== __codecvt_partial
, 0));
608 /* Now seek to _IO_read_end to behave as if we have read it all in. */
609 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
614 /* ftell{,o} implementation for wide mode. Don't modify any state of the file
615 pointer while we try to get the current state of the stream except in one
616 case, which is when we have unflushed writes in append mode. */
618 do_ftell_wide (_IO_FILE
*fp
)
620 _IO_off64_t result
, offset
= 0;
622 /* No point looking for offsets in the buffer if it hasn't even been
624 if (fp
->_wide_data
->_IO_buf_base
!= NULL
)
626 const wchar_t *wide_read_base
;
627 const wchar_t *wide_read_ptr
;
628 const wchar_t *wide_read_end
;
629 bool was_writing
= ((fp
->_wide_data
->_IO_write_ptr
630 > fp
->_wide_data
->_IO_write_base
)
631 || _IO_in_put_mode (fp
));
633 bool append_mode
= (fp
->_flags
& _IO_IS_APPENDING
) == _IO_IS_APPENDING
;
635 /* When we have unflushed writes in append mode, seek to the end of the
636 file and record that offset. This is the only time we change the file
637 stream state and it is safe since the file handle is active. */
638 if (was_writing
&& append_mode
)
640 result
= _IO_SYSSEEK (fp
, 0, _IO_seek_end
);
641 if (result
== _IO_pos_BAD
)
644 fp
->_offset
= result
;
647 /* XXX For wide stream with backup store it is not very
648 reasonable to determine the offset. The pushed-back
649 character might require a state change and we need not be
650 able to compute the initial state by reverse transformation
651 since there is no guarantee of symmetry. So we don't even
652 try and return an error. */
653 if (_IO_in_backup (fp
))
655 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
657 __set_errno (EINVAL
);
661 /* Nothing in the backup store, so note the backed up pointers
662 without changing the state. */
663 wide_read_base
= fp
->_wide_data
->_IO_save_base
;
664 wide_read_ptr
= wide_read_base
;
665 wide_read_end
= fp
->_wide_data
->_IO_save_end
;
669 wide_read_base
= fp
->_wide_data
->_IO_read_base
;
670 wide_read_ptr
= fp
->_wide_data
->_IO_read_ptr
;
671 wide_read_end
= fp
->_wide_data
->_IO_read_end
;
674 struct _IO_codecvt
*cv
= fp
->_codecvt
;
675 int clen
= (*cv
->__codecvt_do_encoding
) (cv
);
681 offset
-= (wide_read_end
- wide_read_ptr
) * clen
;
682 offset
-= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
688 size_t delta
= wide_read_ptr
- wide_read_base
;
689 __mbstate_t state
= fp
->_wide_data
->_IO_last_state
;
690 nread
= (*cv
->__codecvt_do_length
) (cv
, &state
,
692 fp
->_IO_read_end
, delta
);
693 offset
-= fp
->_IO_read_end
- fp
->_IO_read_base
- nread
;
699 offset
+= (fp
->_wide_data
->_IO_write_ptr
700 - fp
->_wide_data
->_IO_write_base
) * clen
;
703 size_t delta
= (fp
->_wide_data
->_IO_write_ptr
704 - fp
->_wide_data
->_IO_write_base
);
706 /* Allocate enough space for the conversion. */
707 size_t outsize
= delta
* sizeof (wchar_t);
708 char *out
= malloc (outsize
);
710 const wchar_t *in
= fp
->_wide_data
->_IO_write_base
;
712 enum __codecvt_result status
;
714 __mbstate_t state
= fp
->_wide_data
->_IO_last_state
;
715 status
= (*cv
->__codecvt_do_out
) (cv
, &state
,
717 out
, out
+ outsize
, &outstop
);
719 /* We don't check for __codecvt_partial because it can be
720 returned on one of two conditions: either the output
721 buffer is full or the input sequence is incomplete. We
722 take care to allocate enough buffer and our input
723 sequences must be complete since they are accepted as
724 wchar_t; if not, then that is an error. */
725 if (__glibc_unlikely (status
!= __codecvt_ok
))
731 offset
+= outstop
- out
;
735 /* We don't trust _IO_read_end to represent the current file offset
736 when writing in append mode because the value would have to be
737 shifted to the end of the file during a flush. Use the write base
738 instead, along with the new offset we got above when we did a seek
739 to the end of the file. */
741 offset
+= fp
->_IO_write_ptr
- fp
->_IO_write_base
;
742 /* For all other modes, _IO_read_end represents the file offset. */
744 offset
+= fp
->_IO_write_ptr
- fp
->_IO_read_end
;
748 if (fp
->_offset
!= _IO_pos_BAD
)
749 result
= fp
->_offset
;
751 result
= _IO_SYSSEEK (fp
, 0, _IO_seek_cur
);
760 __set_errno (EINVAL
);
768 _IO_wfile_seekoff (fp
, offset
, dir
, mode
)
775 _IO_off64_t delta
, new_offset
;
778 /* Short-circuit into a separate function. We don't want to mix any
779 functionality and we don't want to touch anything inside the FILE
782 return do_ftell_wide (fp
);
784 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
785 offset of the underlying file must be exact. */
786 int must_be_exact
= ((fp
->_wide_data
->_IO_read_base
787 == fp
->_wide_data
->_IO_read_end
)
788 && (fp
->_wide_data
->_IO_write_base
789 == fp
->_wide_data
->_IO_write_ptr
));
791 bool was_writing
= ((fp
->_wide_data
->_IO_write_ptr
792 > fp
->_wide_data
->_IO_write_base
)
793 || _IO_in_put_mode (fp
));
795 /* Flush unwritten characters.
796 (This may do an unneeded write if we seek within the buffer.
797 But to be able to switch to reading, we would need to set
798 egptr to pptr. That can't be done in the current design,
799 which assumes file_ptr() is eGptr. Anyway, since we probably
800 end up flushing when we close(), it doesn't make much difference.)
801 FIXME: simulate mem-mapped files. */
802 if (was_writing
&& _IO_switch_to_wget_mode (fp
))
805 if (fp
->_wide_data
->_IO_buf_base
== NULL
)
807 /* It could be that we already have a pushback buffer. */
808 if (fp
->_wide_data
->_IO_read_base
!= NULL
)
810 free (fp
->_wide_data
->_IO_read_base
);
811 fp
->_flags
&= ~_IO_IN_BACKUP
;
814 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
815 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
816 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
,
817 fp
->_wide_data
->_IO_buf_base
);
818 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
819 fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
824 struct _IO_codecvt
*cv
;
828 /* Adjust for read-ahead (bytes is buffer). To do this we must
829 find out which position in the external buffer corresponds to
830 the current position in the internal buffer. */
832 clen
= (*cv
->__codecvt_do_encoding
) (cv
);
834 if (mode
!= 0 || !was_writing
)
838 offset
-= (fp
->_wide_data
->_IO_read_end
839 - fp
->_wide_data
->_IO_read_ptr
) * clen
;
840 /* Adjust by readahead in external buffer. */
841 offset
-= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
847 delta
= (fp
->_wide_data
->_IO_read_ptr
848 - fp
->_wide_data
->_IO_read_base
);
849 fp
->_wide_data
->_IO_state
= fp
->_wide_data
->_IO_last_state
;
850 nread
= (*cv
->__codecvt_do_length
) (cv
,
851 &fp
->_wide_data
->_IO_state
,
853 fp
->_IO_read_end
, delta
);
854 fp
->_IO_read_ptr
= fp
->_IO_read_base
+ nread
;
855 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_read_ptr
;
856 offset
-= fp
->_IO_read_end
- fp
->_IO_read_base
- nread
;
860 if (fp
->_offset
== _IO_pos_BAD
)
863 /* Make offset absolute, assuming current pointer is file_ptr(). */
864 offset
+= fp
->_offset
;
873 if (_IO_SYSSTAT (fp
, &st
) == 0 && S_ISREG (st
.st_mode
))
875 offset
+= st
.st_size
;
882 /* At this point, dir==_IO_seek_set. */
884 /* If destination is within current buffer, optimize: */
885 if (fp
->_offset
!= _IO_pos_BAD
&& fp
->_IO_read_base
!= NULL
886 && !_IO_in_backup (fp
))
888 _IO_off64_t start_offset
= (fp
->_offset
889 - (fp
->_IO_read_end
- fp
->_IO_buf_base
));
890 if (offset
>= start_offset
&& offset
< fp
->_offset
)
892 _IO_setg (fp
, fp
->_IO_buf_base
,
893 fp
->_IO_buf_base
+ (offset
- start_offset
),
895 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
896 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
897 fp
->_wide_data
->_IO_buf_base
,
898 fp
->_wide_data
->_IO_buf_base
);
899 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
,
900 fp
->_wide_data
->_IO_buf_base
);
902 if (adjust_wide_data (fp
, false))
905 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
910 if (fp
->_flags
& _IO_NO_READS
)
913 /* Try to seek to a block boundary, to improve kernel page management. */
914 new_offset
= offset
& ~(fp
->_IO_buf_end
- fp
->_IO_buf_base
- 1);
915 delta
= offset
- new_offset
;
916 if (delta
> fp
->_IO_buf_end
- fp
->_IO_buf_base
)
921 result
= _IO_SYSSEEK (fp
, new_offset
, 0);
928 count
= _IO_SYSREAD (fp
, fp
->_IO_buf_base
,
930 ? delta
: fp
->_IO_buf_end
- fp
->_IO_buf_base
));
933 /* We weren't allowed to read, but try to seek the remainder. */
934 offset
= count
== EOF
? delta
: delta
-count
;
939 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
+ delta
,
940 fp
->_IO_buf_base
+ count
);
941 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
942 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
943 fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
944 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
946 if (adjust_wide_data (fp
, true))
949 fp
->_offset
= result
+ count
;
950 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
954 _IO_unsave_markers (fp
);
955 result
= _IO_SYSSEEK (fp
, offset
, dir
);
958 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
959 fp
->_offset
= result
;
960 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
961 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
962 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
963 fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
964 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
,
965 fp
->_wide_data
->_IO_buf_base
);
970 /* We need to do it since it is possible that the file offset in
971 the kernel may be changed behind our back. It may happen when
972 we fopen a file and then do a fork. One process may access the
973 file and the kernel file offset will be changed. */
974 if (fp
->_offset
>= 0)
975 _IO_SYSSEEK (fp
, fp
->_offset
, 0);
979 libc_hidden_def (_IO_wfile_seekoff
)
983 _IO_wfile_xsputn (f
, data
, n
)
988 const wchar_t *s
= (const wchar_t *) data
;
989 _IO_size_t to_do
= n
;
995 /* This is an optimized implementation.
996 If the amount to be written straddles a block boundary
997 (or the filebuf is unbuffered), use sys_write directly. */
999 /* First figure out how much space is available in the buffer. */
1000 count
= f
->_wide_data
->_IO_write_end
- f
->_wide_data
->_IO_write_ptr
;
1001 if ((f
->_flags
& _IO_LINE_BUF
) && (f
->_flags
& _IO_CURRENTLY_PUTTING
))
1003 count
= f
->_wide_data
->_IO_buf_end
- f
->_wide_data
->_IO_write_ptr
;
1007 for (p
= s
+ n
; p
> s
; )
1018 /* Then fill the buffer. */
1026 f
->_wide_data
->_IO_write_ptr
=
1027 __wmempcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
1029 wmemcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
1030 f
->_wide_data
->_IO_write_ptr
+= count
;
1036 wchar_t *p
= f
->_wide_data
->_IO_write_ptr
;
1037 int i
= (int) count
;
1040 f
->_wide_data
->_IO_write_ptr
= p
;
1045 to_do
-= _IO_wdefault_xsputn (f
, s
, to_do
);
1047 && f
->_wide_data
->_IO_write_ptr
!= f
->_wide_data
->_IO_write_base
)
1048 _IO_wdo_write (f
, f
->_wide_data
->_IO_write_base
,
1049 f
->_wide_data
->_IO_write_ptr
1050 - f
->_wide_data
->_IO_write_base
);
1054 libc_hidden_def (_IO_wfile_xsputn
)
1057 const struct _IO_jump_t _IO_wfile_jumps
=
1060 JUMP_INIT(finish
, _IO_new_file_finish
),
1061 JUMP_INIT(overflow
, (_IO_overflow_t
) _IO_wfile_overflow
),
1062 JUMP_INIT(underflow
, (_IO_underflow_t
) _IO_wfile_underflow
),
1063 JUMP_INIT(uflow
, (_IO_underflow_t
) _IO_wdefault_uflow
),
1064 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) _IO_wdefault_pbackfail
),
1065 JUMP_INIT(xsputn
, _IO_wfile_xsputn
),
1066 JUMP_INIT(xsgetn
, _IO_file_xsgetn
),
1067 JUMP_INIT(seekoff
, _IO_wfile_seekoff
),
1068 JUMP_INIT(seekpos
, _IO_default_seekpos
),
1069 JUMP_INIT(setbuf
, _IO_new_file_setbuf
),
1070 JUMP_INIT(sync
, (_IO_sync_t
) _IO_wfile_sync
),
1071 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
1072 JUMP_INIT(read
, _IO_file_read
),
1073 JUMP_INIT(write
, _IO_new_file_write
),
1074 JUMP_INIT(seek
, _IO_file_seek
),
1075 JUMP_INIT(close
, _IO_file_close
),
1076 JUMP_INIT(stat
, _IO_file_stat
),
1077 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
1078 JUMP_INIT(imbue
, _IO_default_imbue
)
1080 libc_hidden_data_def (_IO_wfile_jumps
)
1083 const struct _IO_jump_t _IO_wfile_jumps_mmap
=
1086 JUMP_INIT(finish
, _IO_new_file_finish
),
1087 JUMP_INIT(overflow
, (_IO_overflow_t
) _IO_wfile_overflow
),
1088 JUMP_INIT(underflow
, (_IO_underflow_t
) _IO_wfile_underflow_mmap
),
1089 JUMP_INIT(uflow
, (_IO_underflow_t
) _IO_wdefault_uflow
),
1090 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) _IO_wdefault_pbackfail
),
1091 JUMP_INIT(xsputn
, _IO_wfile_xsputn
),
1092 JUMP_INIT(xsgetn
, _IO_file_xsgetn
),
1093 JUMP_INIT(seekoff
, _IO_wfile_seekoff
),
1094 JUMP_INIT(seekpos
, _IO_default_seekpos
),
1095 JUMP_INIT(setbuf
, _IO_file_setbuf_mmap
),
1096 JUMP_INIT(sync
, (_IO_sync_t
) _IO_wfile_sync
),
1097 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
1098 JUMP_INIT(read
, _IO_file_read
),
1099 JUMP_INIT(write
, _IO_new_file_write
),
1100 JUMP_INIT(seek
, _IO_file_seek
),
1101 JUMP_INIT(close
, _IO_file_close_mmap
),
1102 JUMP_INIT(stat
, _IO_file_stat
),
1103 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
1104 JUMP_INIT(imbue
, _IO_default_imbue
)
1107 const struct _IO_jump_t _IO_wfile_jumps_maybe_mmap
=
1110 JUMP_INIT(finish
, _IO_new_file_finish
),
1111 JUMP_INIT(overflow
, (_IO_overflow_t
) _IO_wfile_overflow
),
1112 JUMP_INIT(underflow
, (_IO_underflow_t
) _IO_wfile_underflow_maybe_mmap
),
1113 JUMP_INIT(uflow
, (_IO_underflow_t
) _IO_wdefault_uflow
),
1114 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) _IO_wdefault_pbackfail
),
1115 JUMP_INIT(xsputn
, _IO_wfile_xsputn
),
1116 JUMP_INIT(xsgetn
, _IO_file_xsgetn
),
1117 JUMP_INIT(seekoff
, _IO_wfile_seekoff
),
1118 JUMP_INIT(seekpos
, _IO_default_seekpos
),
1119 JUMP_INIT(setbuf
, _IO_file_setbuf_mmap
),
1120 JUMP_INIT(sync
, (_IO_sync_t
) _IO_wfile_sync
),
1121 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
1122 JUMP_INIT(read
, _IO_file_read
),
1123 JUMP_INIT(write
, _IO_new_file_write
),
1124 JUMP_INIT(seek
, _IO_file_seek
),
1125 JUMP_INIT(close
, _IO_file_close
),
1126 JUMP_INIT(stat
, _IO_file_stat
),
1127 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
1128 JUMP_INIT(imbue
, _IO_default_imbue
)