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)
261 fp
->_flags
|= _IO_EOF_SEEN
;
262 fp
->_offset
= _IO_pos_BAD
;
265 fp
->_flags
|= _IO_ERR_SEEN
, count
= 0;
267 fp
->_IO_read_end
+= count
;
271 /* There are some bytes in the external buffer but they don't
272 convert to anything. */
273 __set_errno (EILSEQ
);
276 if (fp
->_offset
!= _IO_pos_BAD
)
277 _IO_pos_adjust (fp
->_offset
, count
);
279 /* Now convert the read input. */
280 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
281 fp
->_IO_read_base
= fp
->_IO_read_ptr
;
282 const char *from
= fp
->_IO_read_ptr
;
283 const char *to
= fp
->_IO_read_end
;
284 size_t to_copy
= count
;
285 if (__glibc_unlikely (naccbuf
!= 0))
287 to_copy
= MIN (sizeof (accbuf
) - naccbuf
, count
);
288 to
= __mempcpy (&accbuf
[naccbuf
], from
, to_copy
);
292 status
= (*cd
->__codecvt_do_in
) (cd
, &fp
->_wide_data
->_IO_state
,
293 from
, to
, &read_ptr_copy
,
294 fp
->_wide_data
->_IO_read_end
,
295 fp
->_wide_data
->_IO_buf_end
,
296 &fp
->_wide_data
->_IO_read_end
);
298 if (__glibc_unlikely (naccbuf
!= 0))
299 fp
->_IO_read_ptr
+= MAX (0, read_ptr_copy
- &accbuf
[naccbuf
- to_copy
]);
301 fp
->_IO_read_ptr
= (char *) read_ptr_copy
;
302 if (fp
->_wide_data
->_IO_read_end
== fp
->_wide_data
->_IO_buf_base
)
304 if (status
== __codecvt_error
)
307 __set_errno (EILSEQ
);
308 fp
->_flags
|= _IO_ERR_SEEN
;
312 /* The read bytes make no complete character. Try reading again. */
313 assert (status
== __codecvt_partial
);
317 if (fp
->_IO_read_base
< fp
->_IO_read_ptr
)
319 /* Partially used the buffer for some input data that
320 produces no output. */
321 size_t avail
= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
322 memmove (fp
->_IO_read_base
, fp
->_IO_read_ptr
, avail
);
323 fp
->_IO_read_ptr
= fp
->_IO_read_base
;
324 fp
->_IO_read_end
-= avail
;
327 naccbuf
= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
328 if (naccbuf
>= sizeof (accbuf
))
331 memcpy (accbuf
, fp
->_IO_read_ptr
, naccbuf
);
335 size_t used
= read_ptr_copy
- accbuf
;
338 memmove (accbuf
, read_ptr_copy
, naccbuf
- used
);
342 if (naccbuf
== sizeof (accbuf
))
346 fp
->_IO_read_ptr
= fp
->_IO_read_end
= fp
->_IO_read_base
;
351 return *fp
->_wide_data
->_IO_read_ptr
;
353 libc_hidden_def (_IO_wfile_underflow
)
357 _IO_wfile_underflow_mmap (_IO_FILE
*fp
)
359 struct _IO_codecvt
*cd
;
360 const char *read_stop
;
362 if (__glibc_unlikely (fp
->_flags
& _IO_NO_READS
))
364 fp
->_flags
|= _IO_ERR_SEEN
;
368 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
369 return *fp
->_wide_data
->_IO_read_ptr
;
373 /* Maybe there is something left in the external buffer. */
374 if (fp
->_IO_read_ptr
>= fp
->_IO_read_end
375 /* No. But maybe the read buffer is not fully set up. */
376 && _IO_file_underflow_mmap (fp
) == EOF
)
377 /* Nothing available. _IO_file_underflow_mmap has set the EOF or error
378 flags as appropriate. */
381 /* There is more in the external. Convert it. */
382 read_stop
= (const char *) fp
->_IO_read_ptr
;
384 if (fp
->_wide_data
->_IO_buf_base
== NULL
)
386 /* Maybe we already have a push back pointer. */
387 if (fp
->_wide_data
->_IO_save_base
!= NULL
)
389 free (fp
->_wide_data
->_IO_save_base
);
390 fp
->_flags
&= ~_IO_IN_BACKUP
;
392 _IO_wdoallocbuf (fp
);
395 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
396 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
=
397 fp
->_wide_data
->_IO_buf_base
;
398 (*cd
->__codecvt_do_in
) (cd
, &fp
->_wide_data
->_IO_state
,
399 fp
->_IO_read_ptr
, fp
->_IO_read_end
,
401 fp
->_wide_data
->_IO_read_ptr
,
402 fp
->_wide_data
->_IO_buf_end
,
403 &fp
->_wide_data
->_IO_read_end
);
405 fp
->_IO_read_ptr
= (char *) read_stop
;
407 /* If we managed to generate some text return the next character. */
408 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
409 return *fp
->_wide_data
->_IO_read_ptr
;
411 /* There is some garbage at the end of the file. */
412 __set_errno (EILSEQ
);
413 fp
->_flags
|= _IO_ERR_SEEN
;
418 _IO_wfile_underflow_maybe_mmap (_IO_FILE
*fp
)
420 /* This is the first read attempt. Doing the underflow will choose mmap
421 or vanilla operations and then punt to the chosen underflow routine.
422 Then we can punt to ours. */
423 if (_IO_file_underflow_maybe_mmap (fp
) == EOF
)
426 return _IO_WUNDERFLOW (fp
);
431 _IO_wfile_overflow (f
, wch
)
435 if (f
->_flags
& _IO_NO_WRITES
) /* SET ERROR */
437 f
->_flags
|= _IO_ERR_SEEN
;
441 /* If currently reading or no buffer allocated. */
442 if ((f
->_flags
& _IO_CURRENTLY_PUTTING
) == 0)
444 /* Allocate a buffer if needed. */
445 if (f
->_wide_data
->_IO_write_base
== 0)
448 _IO_wsetg (f
, f
->_wide_data
->_IO_buf_base
,
449 f
->_wide_data
->_IO_buf_base
, f
->_wide_data
->_IO_buf_base
);
451 if (f
->_IO_write_base
== NULL
)
454 _IO_setg (f
, f
->_IO_buf_base
, f
->_IO_buf_base
, f
->_IO_buf_base
);
459 /* Otherwise must be currently reading. If _IO_read_ptr
460 (and hence also _IO_read_end) is at the buffer end,
461 logically slide the buffer forwards one block (by setting
462 the read pointers to all point at the beginning of the
463 block). This makes room for subsequent output.
464 Otherwise, set the read pointers to _IO_read_end (leaving
465 that alone, so it can continue to correspond to the
466 external position). */
467 if (f
->_wide_data
->_IO_read_ptr
== f
->_wide_data
->_IO_buf_end
)
469 f
->_IO_read_end
= f
->_IO_read_ptr
= f
->_IO_buf_base
;
470 f
->_wide_data
->_IO_read_end
= f
->_wide_data
->_IO_read_ptr
=
471 f
->_wide_data
->_IO_buf_base
;
474 f
->_wide_data
->_IO_write_ptr
= f
->_wide_data
->_IO_read_ptr
;
475 f
->_wide_data
->_IO_write_base
= f
->_wide_data
->_IO_write_ptr
;
476 f
->_wide_data
->_IO_write_end
= f
->_wide_data
->_IO_buf_end
;
477 f
->_wide_data
->_IO_read_base
= f
->_wide_data
->_IO_read_ptr
=
478 f
->_wide_data
->_IO_read_end
;
480 f
->_IO_write_ptr
= f
->_IO_read_ptr
;
481 f
->_IO_write_base
= f
->_IO_write_ptr
;
482 f
->_IO_write_end
= f
->_IO_buf_end
;
483 f
->_IO_read_base
= f
->_IO_read_ptr
= f
->_IO_read_end
;
485 f
->_flags
|= _IO_CURRENTLY_PUTTING
;
486 if (f
->_flags
& (_IO_LINE_BUF
+_IO_UNBUFFERED
))
487 f
->_wide_data
->_IO_write_end
= f
->_wide_data
->_IO_write_ptr
;
490 return _IO_do_flush (f
);
491 if (f
->_wide_data
->_IO_write_ptr
== f
->_wide_data
->_IO_buf_end
)
492 /* Buffer is really full */
493 if (_IO_do_flush (f
) == EOF
)
495 *f
->_wide_data
->_IO_write_ptr
++ = wch
;
496 if ((f
->_flags
& _IO_UNBUFFERED
)
497 || ((f
->_flags
& _IO_LINE_BUF
) && wch
== L
'\n'))
498 if (_IO_do_flush (f
) == EOF
)
502 libc_hidden_def (_IO_wfile_overflow
)
511 /* char* ptr = cur_ptr(); */
512 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_write_base
)
513 if (_IO_do_flush (fp
))
515 delta
= fp
->_wide_data
->_IO_read_ptr
- fp
->_wide_data
->_IO_read_end
;
518 /* We have to find out how many bytes we have to go back in the
520 struct _IO_codecvt
*cv
= fp
->_codecvt
;
523 int clen
= (*cv
->__codecvt_do_encoding
) (cv
);
526 /* It is easy, a fixed number of input bytes are used for each
531 /* We have to find out the hard way how much to back off.
532 To do this we determine how much input we needed to
533 generate the wide characters up to the current reading
537 fp
->_wide_data
->_IO_state
= fp
->_wide_data
->_IO_last_state
;
538 nread
= (*cv
->__codecvt_do_length
) (cv
, &fp
->_wide_data
->_IO_state
,
540 fp
->_IO_read_end
, delta
);
541 fp
->_IO_read_ptr
= fp
->_IO_read_base
+ nread
;
542 delta
= -(fp
->_IO_read_end
- fp
->_IO_read_base
- nread
);
545 new_pos
= _IO_SYSSEEK (fp
, delta
, 1);
546 if (new_pos
!= (_IO_off64_t
) EOF
)
548 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_read_ptr
;
549 fp
->_IO_read_end
= fp
->_IO_read_ptr
;
552 else if (errno
== ESPIPE
)
553 ; /* Ignore error from unseekable devices. */
559 fp
->_offset
= _IO_pos_BAD
;
560 /* FIXME: Cleanup - can this be shared? */
561 /* setg(base(), ptr, ptr); */
564 libc_hidden_def (_IO_wfile_sync
)
566 /* Adjust the internal buffer pointers to reflect the state in the external
567 buffer. The content between fp->_IO_read_base and fp->_IO_read_ptr is
568 assumed to be converted and available in the range
569 fp->_wide_data->_IO_read_base and fp->_wide_data->_IO_read_end.
571 Returns 0 on success and -1 on error with the _IO_ERR_SEEN flag set. */
573 adjust_wide_data (_IO_FILE
*fp
, bool do_convert
)
575 struct _IO_codecvt
*cv
= fp
->_codecvt
;
577 int clen
= (*cv
->__codecvt_do_encoding
) (cv
);
579 /* Take the easy way out for constant length encodings if we don't need to
581 if (!do_convert
&& clen
> 0)
583 fp
->_wide_data
->_IO_read_end
+= ((fp
->_IO_read_ptr
- fp
->_IO_read_base
)
588 enum __codecvt_result status
;
589 const char *read_stop
= (const char *) fp
->_IO_read_base
;
593 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
594 status
= (*cv
->__codecvt_do_in
) (cv
, &fp
->_wide_data
->_IO_state
,
595 fp
->_IO_read_base
, fp
->_IO_read_ptr
,
597 fp
->_wide_data
->_IO_read_base
,
598 fp
->_wide_data
->_IO_buf_end
,
599 &fp
->_wide_data
->_IO_read_end
);
601 /* Should we return EILSEQ? */
602 if (__glibc_unlikely (status
== __codecvt_error
))
604 fp
->_flags
|= _IO_ERR_SEEN
;
608 while (__builtin_expect (status
== __codecvt_partial
, 0));
611 /* Now seek to _IO_read_end to behave as if we have read it all in. */
612 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
617 /* ftell{,o} implementation for wide mode. Don't modify any state of the file
618 pointer while we try to get the current state of the stream except in one
619 case, which is when we have unflushed writes in append mode. */
621 do_ftell_wide (_IO_FILE
*fp
)
623 _IO_off64_t result
, offset
= 0;
625 /* No point looking for offsets in the buffer if it hasn't even been
627 if (fp
->_wide_data
->_IO_buf_base
!= NULL
)
629 const wchar_t *wide_read_base
;
630 const wchar_t *wide_read_ptr
;
631 const wchar_t *wide_read_end
;
632 bool unflushed_writes
= (fp
->_wide_data
->_IO_write_ptr
633 > fp
->_wide_data
->_IO_write_base
);
635 bool append_mode
= (fp
->_flags
& _IO_IS_APPENDING
) == _IO_IS_APPENDING
;
637 /* When we have unflushed writes in append mode, seek to the end of the
638 file and record that offset. This is the only time we change the file
639 stream state and it is safe since the file handle is active. */
640 if (unflushed_writes
&& append_mode
)
642 result
= _IO_SYSSEEK (fp
, 0, _IO_seek_end
);
643 if (result
== _IO_pos_BAD
)
646 fp
->_offset
= result
;
649 /* XXX For wide stream with backup store it is not very
650 reasonable to determine the offset. The pushed-back
651 character might require a state change and we need not be
652 able to compute the initial state by reverse transformation
653 since there is no guarantee of symmetry. So we don't even
654 try and return an error. */
655 if (_IO_in_backup (fp
))
657 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
659 __set_errno (EINVAL
);
663 /* Nothing in the backup store, so note the backed up pointers
664 without changing the state. */
665 wide_read_base
= fp
->_wide_data
->_IO_save_base
;
666 wide_read_ptr
= wide_read_base
;
667 wide_read_end
= fp
->_wide_data
->_IO_save_end
;
671 wide_read_base
= fp
->_wide_data
->_IO_read_base
;
672 wide_read_ptr
= fp
->_wide_data
->_IO_read_ptr
;
673 wide_read_end
= fp
->_wide_data
->_IO_read_end
;
676 struct _IO_codecvt
*cv
= fp
->_codecvt
;
677 int clen
= (*cv
->__codecvt_do_encoding
) (cv
);
679 if (!unflushed_writes
)
683 offset
-= (wide_read_end
- wide_read_ptr
) * clen
;
684 offset
-= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
690 size_t delta
= wide_read_ptr
- wide_read_base
;
691 __mbstate_t state
= fp
->_wide_data
->_IO_last_state
;
692 nread
= (*cv
->__codecvt_do_length
) (cv
, &state
,
694 fp
->_IO_read_end
, delta
);
695 offset
-= fp
->_IO_read_end
- fp
->_IO_read_base
- nread
;
701 offset
+= (fp
->_wide_data
->_IO_write_ptr
702 - fp
->_wide_data
->_IO_write_base
) * clen
;
705 size_t delta
= (fp
->_wide_data
->_IO_write_ptr
706 - fp
->_wide_data
->_IO_write_base
);
708 /* Allocate enough space for the conversion. */
709 size_t outsize
= delta
* sizeof (wchar_t);
710 char *out
= malloc (outsize
);
712 const wchar_t *in
= fp
->_wide_data
->_IO_write_base
;
714 enum __codecvt_result status
;
716 __mbstate_t state
= fp
->_wide_data
->_IO_last_state
;
717 status
= (*cv
->__codecvt_do_out
) (cv
, &state
,
719 out
, out
+ outsize
, &outstop
);
721 /* We don't check for __codecvt_partial because it can be
722 returned on one of two conditions: either the output
723 buffer is full or the input sequence is incomplete. We
724 take care to allocate enough buffer and our input
725 sequences must be complete since they are accepted as
726 wchar_t; if not, then that is an error. */
727 if (__glibc_unlikely (status
!= __codecvt_ok
))
733 offset
+= outstop
- out
;
737 /* We don't trust _IO_read_end to represent the current file offset
738 when writing in append mode because the value would have to be
739 shifted to the end of the file during a flush. Use the write base
740 instead, along with the new offset we got above when we did a seek
741 to the end of the file. */
743 offset
+= fp
->_IO_write_ptr
- fp
->_IO_write_base
;
744 /* For all other modes, _IO_read_end represents the file offset. */
746 offset
+= fp
->_IO_write_ptr
- fp
->_IO_read_end
;
750 if (fp
->_offset
!= _IO_pos_BAD
)
751 result
= fp
->_offset
;
753 result
= _IO_SYSSEEK (fp
, 0, _IO_seek_cur
);
762 __set_errno (EINVAL
);
770 _IO_wfile_seekoff (fp
, offset
, dir
, mode
)
777 _IO_off64_t delta
, new_offset
;
780 /* Short-circuit into a separate function. We don't want to mix any
781 functionality and we don't want to touch anything inside the FILE
784 return do_ftell_wide (fp
);
786 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
787 offset of the underlying file must be exact. */
788 int must_be_exact
= ((fp
->_wide_data
->_IO_read_base
789 == fp
->_wide_data
->_IO_read_end
)
790 && (fp
->_wide_data
->_IO_write_base
791 == fp
->_wide_data
->_IO_write_ptr
));
793 bool was_writing
= ((fp
->_wide_data
->_IO_write_ptr
794 > fp
->_wide_data
->_IO_write_base
)
795 || _IO_in_put_mode (fp
));
797 /* Flush unwritten characters.
798 (This may do an unneeded write if we seek within the buffer.
799 But to be able to switch to reading, we would need to set
800 egptr to pptr. That can't be done in the current design,
801 which assumes file_ptr() is eGptr. Anyway, since we probably
802 end up flushing when we close(), it doesn't make much difference.)
803 FIXME: simulate mem-mapped files. */
804 if (was_writing
&& _IO_switch_to_wget_mode (fp
))
807 if (fp
->_wide_data
->_IO_buf_base
== NULL
)
809 /* It could be that we already have a pushback buffer. */
810 if (fp
->_wide_data
->_IO_read_base
!= NULL
)
812 free (fp
->_wide_data
->_IO_read_base
);
813 fp
->_flags
&= ~_IO_IN_BACKUP
;
816 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
817 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
818 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
,
819 fp
->_wide_data
->_IO_buf_base
);
820 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
821 fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
826 struct _IO_codecvt
*cv
;
830 /* Adjust for read-ahead (bytes is buffer). To do this we must
831 find out which position in the external buffer corresponds to
832 the current position in the internal buffer. */
834 clen
= (*cv
->__codecvt_do_encoding
) (cv
);
836 if (mode
!= 0 || !was_writing
)
840 offset
-= (fp
->_wide_data
->_IO_read_end
841 - fp
->_wide_data
->_IO_read_ptr
) * clen
;
842 /* Adjust by readahead in external buffer. */
843 offset
-= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
849 delta
= (fp
->_wide_data
->_IO_read_ptr
850 - fp
->_wide_data
->_IO_read_base
);
851 fp
->_wide_data
->_IO_state
= fp
->_wide_data
->_IO_last_state
;
852 nread
= (*cv
->__codecvt_do_length
) (cv
,
853 &fp
->_wide_data
->_IO_state
,
855 fp
->_IO_read_end
, delta
);
856 fp
->_IO_read_ptr
= fp
->_IO_read_base
+ nread
;
857 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_read_ptr
;
858 offset
-= fp
->_IO_read_end
- fp
->_IO_read_base
- nread
;
862 if (fp
->_offset
== _IO_pos_BAD
)
865 /* Make offset absolute, assuming current pointer is file_ptr(). */
866 offset
+= fp
->_offset
;
875 if (_IO_SYSSTAT (fp
, &st
) == 0 && S_ISREG (st
.st_mode
))
877 offset
+= st
.st_size
;
884 /* At this point, dir==_IO_seek_set. */
886 /* If destination is within current buffer, optimize: */
887 if (fp
->_offset
!= _IO_pos_BAD
&& fp
->_IO_read_base
!= NULL
888 && !_IO_in_backup (fp
))
890 _IO_off64_t start_offset
= (fp
->_offset
891 - (fp
->_IO_read_end
- fp
->_IO_buf_base
));
892 if (offset
>= start_offset
&& offset
< fp
->_offset
)
894 _IO_setg (fp
, fp
->_IO_buf_base
,
895 fp
->_IO_buf_base
+ (offset
- start_offset
),
897 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
898 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
899 fp
->_wide_data
->_IO_buf_base
,
900 fp
->_wide_data
->_IO_buf_base
);
901 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
,
902 fp
->_wide_data
->_IO_buf_base
);
904 if (adjust_wide_data (fp
, false))
907 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
912 if (fp
->_flags
& _IO_NO_READS
)
915 /* Try to seek to a block boundary, to improve kernel page management. */
916 new_offset
= offset
& ~(fp
->_IO_buf_end
- fp
->_IO_buf_base
- 1);
917 delta
= offset
- new_offset
;
918 if (delta
> fp
->_IO_buf_end
- fp
->_IO_buf_base
)
923 result
= _IO_SYSSEEK (fp
, new_offset
, 0);
930 count
= _IO_SYSREAD (fp
, fp
->_IO_buf_base
,
932 ? delta
: fp
->_IO_buf_end
- fp
->_IO_buf_base
));
935 /* We weren't allowed to read, but try to seek the remainder. */
936 offset
= count
== EOF
? delta
: delta
-count
;
941 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
+ delta
,
942 fp
->_IO_buf_base
+ count
);
943 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
944 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
945 fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
946 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
948 if (adjust_wide_data (fp
, true))
951 fp
->_offset
= result
+ count
;
952 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
956 _IO_unsave_markers (fp
);
957 result
= _IO_SYSSEEK (fp
, offset
, dir
);
960 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
961 fp
->_offset
= result
;
962 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
963 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
964 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
965 fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
966 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
,
967 fp
->_wide_data
->_IO_buf_base
);
972 /* We need to do it since it is possible that the file offset in
973 the kernel may be changed behind our back. It may happen when
974 we fopen a file and then do a fork. One process may access the
975 file and the kernel file offset will be changed. */
976 if (fp
->_offset
>= 0)
977 _IO_SYSSEEK (fp
, fp
->_offset
, 0);
981 libc_hidden_def (_IO_wfile_seekoff
)
985 _IO_wfile_xsputn (f
, data
, n
)
990 const wchar_t *s
= (const wchar_t *) data
;
991 _IO_size_t to_do
= n
;
997 /* This is an optimized implementation.
998 If the amount to be written straddles a block boundary
999 (or the filebuf is unbuffered), use sys_write directly. */
1001 /* First figure out how much space is available in the buffer. */
1002 count
= f
->_wide_data
->_IO_write_end
- f
->_wide_data
->_IO_write_ptr
;
1003 if ((f
->_flags
& _IO_LINE_BUF
) && (f
->_flags
& _IO_CURRENTLY_PUTTING
))
1005 count
= f
->_wide_data
->_IO_buf_end
- f
->_wide_data
->_IO_write_ptr
;
1009 for (p
= s
+ n
; p
> s
; )
1020 /* Then fill the buffer. */
1028 f
->_wide_data
->_IO_write_ptr
=
1029 __wmempcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
1031 wmemcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
1032 f
->_wide_data
->_IO_write_ptr
+= count
;
1038 wchar_t *p
= f
->_wide_data
->_IO_write_ptr
;
1039 int i
= (int) count
;
1042 f
->_wide_data
->_IO_write_ptr
= p
;
1047 to_do
-= _IO_wdefault_xsputn (f
, s
, to_do
);
1049 && f
->_wide_data
->_IO_write_ptr
!= f
->_wide_data
->_IO_write_base
)
1050 _IO_wdo_write (f
, f
->_wide_data
->_IO_write_base
,
1051 f
->_wide_data
->_IO_write_ptr
1052 - f
->_wide_data
->_IO_write_base
);
1056 libc_hidden_def (_IO_wfile_xsputn
)
1059 const struct _IO_jump_t _IO_wfile_jumps
=
1062 JUMP_INIT(finish
, _IO_new_file_finish
),
1063 JUMP_INIT(overflow
, (_IO_overflow_t
) _IO_wfile_overflow
),
1064 JUMP_INIT(underflow
, (_IO_underflow_t
) _IO_wfile_underflow
),
1065 JUMP_INIT(uflow
, (_IO_underflow_t
) _IO_wdefault_uflow
),
1066 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) _IO_wdefault_pbackfail
),
1067 JUMP_INIT(xsputn
, _IO_wfile_xsputn
),
1068 JUMP_INIT(xsgetn
, _IO_file_xsgetn
),
1069 JUMP_INIT(seekoff
, _IO_wfile_seekoff
),
1070 JUMP_INIT(seekpos
, _IO_default_seekpos
),
1071 JUMP_INIT(setbuf
, _IO_new_file_setbuf
),
1072 JUMP_INIT(sync
, (_IO_sync_t
) _IO_wfile_sync
),
1073 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
1074 JUMP_INIT(read
, _IO_file_read
),
1075 JUMP_INIT(write
, _IO_new_file_write
),
1076 JUMP_INIT(seek
, _IO_file_seek
),
1077 JUMP_INIT(close
, _IO_file_close
),
1078 JUMP_INIT(stat
, _IO_file_stat
),
1079 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
1080 JUMP_INIT(imbue
, _IO_default_imbue
)
1082 libc_hidden_data_def (_IO_wfile_jumps
)
1085 const struct _IO_jump_t _IO_wfile_jumps_mmap
=
1088 JUMP_INIT(finish
, _IO_new_file_finish
),
1089 JUMP_INIT(overflow
, (_IO_overflow_t
) _IO_wfile_overflow
),
1090 JUMP_INIT(underflow
, (_IO_underflow_t
) _IO_wfile_underflow_mmap
),
1091 JUMP_INIT(uflow
, (_IO_underflow_t
) _IO_wdefault_uflow
),
1092 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) _IO_wdefault_pbackfail
),
1093 JUMP_INIT(xsputn
, _IO_wfile_xsputn
),
1094 JUMP_INIT(xsgetn
, _IO_file_xsgetn
),
1095 JUMP_INIT(seekoff
, _IO_wfile_seekoff
),
1096 JUMP_INIT(seekpos
, _IO_default_seekpos
),
1097 JUMP_INIT(setbuf
, _IO_file_setbuf_mmap
),
1098 JUMP_INIT(sync
, (_IO_sync_t
) _IO_wfile_sync
),
1099 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
1100 JUMP_INIT(read
, _IO_file_read
),
1101 JUMP_INIT(write
, _IO_new_file_write
),
1102 JUMP_INIT(seek
, _IO_file_seek
),
1103 JUMP_INIT(close
, _IO_file_close_mmap
),
1104 JUMP_INIT(stat
, _IO_file_stat
),
1105 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
1106 JUMP_INIT(imbue
, _IO_default_imbue
)
1109 const struct _IO_jump_t _IO_wfile_jumps_maybe_mmap
=
1112 JUMP_INIT(finish
, _IO_new_file_finish
),
1113 JUMP_INIT(overflow
, (_IO_overflow_t
) _IO_wfile_overflow
),
1114 JUMP_INIT(underflow
, (_IO_underflow_t
) _IO_wfile_underflow_maybe_mmap
),
1115 JUMP_INIT(uflow
, (_IO_underflow_t
) _IO_wdefault_uflow
),
1116 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) _IO_wdefault_pbackfail
),
1117 JUMP_INIT(xsputn
, _IO_wfile_xsputn
),
1118 JUMP_INIT(xsgetn
, _IO_file_xsgetn
),
1119 JUMP_INIT(seekoff
, _IO_wfile_seekoff
),
1120 JUMP_INIT(seekpos
, _IO_default_seekpos
),
1121 JUMP_INIT(setbuf
, _IO_file_setbuf_mmap
),
1122 JUMP_INIT(sync
, (_IO_sync_t
) _IO_wfile_sync
),
1123 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
1124 JUMP_INIT(read
, _IO_file_read
),
1125 JUMP_INIT(write
, _IO_new_file_write
),
1126 JUMP_INIT(seek
, _IO_file_seek
),
1127 JUMP_INIT(close
, _IO_file_close
),
1128 JUMP_INIT(stat
, _IO_file_stat
),
1129 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
1130 JUMP_INIT(imbue
, _IO_default_imbue
)