1 /* Copyright (C) 1993-2017 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. */
36 /* Convert TO_DO wide character from DATA to FP.
37 Then mark FP as having empty buffers. */
39 _IO_wdo_write (_IO_FILE
*fp
, const wchar_t *data
, _IO_size_t to_do
)
41 struct _IO_codecvt
*cc
= fp
->_codecvt
;
45 if (fp
->_IO_write_end
== fp
->_IO_write_ptr
46 && fp
->_IO_write_end
!= fp
->_IO_write_base
)
48 if (_IO_new_do_write (fp
, fp
->_IO_write_base
,
49 fp
->_IO_write_ptr
- fp
->_IO_write_base
) == EOF
)
55 enum __codecvt_result result
;
56 const wchar_t *new_data
;
57 char mb_buf
[MB_LEN_MAX
];
58 char *write_base
, *write_ptr
, *buf_end
;
60 if (fp
->_IO_write_ptr
- fp
->_IO_write_base
< sizeof (mb_buf
))
62 /* Make sure we have room for at least one multibyte
64 write_ptr
= write_base
= mb_buf
;
65 buf_end
= mb_buf
+ sizeof (mb_buf
);
69 write_ptr
= fp
->_IO_write_ptr
;
70 write_base
= fp
->_IO_write_base
;
71 buf_end
= fp
->_IO_buf_end
;
74 /* Now convert from the internal format into the external buffer. */
75 result
= (*cc
->__codecvt_do_out
) (cc
, &fp
->_wide_data
->_IO_state
,
76 data
, data
+ to_do
, &new_data
,
81 /* Write out what we produced so far. */
82 if (_IO_new_do_write (fp
, write_base
, write_ptr
- write_base
) == EOF
)
83 /* Something went wrong. */
86 to_do
-= new_data
- data
;
88 /* Next see whether we had problems during the conversion. If yes,
90 if (result
!= __codecvt_ok
91 && (result
!= __codecvt_partial
|| new_data
- data
== 0))
99 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
,
100 fp
->_wide_data
->_IO_buf_base
);
101 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
102 = fp
->_wide_data
->_IO_buf_base
;
103 fp
->_wide_data
->_IO_write_end
= ((fp
->_flags
& (_IO_LINE_BUF
| _IO_UNBUFFERED
))
104 ? fp
->_wide_data
->_IO_buf_base
105 : fp
->_wide_data
->_IO_buf_end
);
107 return to_do
== 0 ? 0 : WEOF
;
109 libc_hidden_def (_IO_wdo_write
)
113 _IO_wfile_underflow (_IO_FILE
*fp
)
115 struct _IO_codecvt
*cd
;
116 enum __codecvt_result status
;
119 if (__glibc_unlikely (fp
->_flags
& _IO_NO_READS
))
121 fp
->_flags
|= _IO_ERR_SEEN
;
125 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
126 return *fp
->_wide_data
->_IO_read_ptr
;
130 /* Maybe there is something left in the external buffer. */
131 if (fp
->_IO_read_ptr
< fp
->_IO_read_end
)
133 /* There is more in the external. Convert it. */
134 const char *read_stop
= (const char *) fp
->_IO_read_ptr
;
136 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
137 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
=
138 fp
->_wide_data
->_IO_buf_base
;
139 status
= (*cd
->__codecvt_do_in
) (cd
, &fp
->_wide_data
->_IO_state
,
140 fp
->_IO_read_ptr
, fp
->_IO_read_end
,
142 fp
->_wide_data
->_IO_read_ptr
,
143 fp
->_wide_data
->_IO_buf_end
,
144 &fp
->_wide_data
->_IO_read_end
);
146 fp
->_IO_read_base
= fp
->_IO_read_ptr
;
147 fp
->_IO_read_ptr
= (char *) read_stop
;
149 /* If we managed to generate some text return the next character. */
150 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
151 return *fp
->_wide_data
->_IO_read_ptr
;
153 if (status
== __codecvt_error
)
155 __set_errno (EILSEQ
);
156 fp
->_flags
|= _IO_ERR_SEEN
;
160 /* Move the remaining content of the read buffer to the beginning. */
161 memmove (fp
->_IO_buf_base
, fp
->_IO_read_ptr
,
162 fp
->_IO_read_end
- fp
->_IO_read_ptr
);
163 fp
->_IO_read_end
= (fp
->_IO_buf_base
164 + (fp
->_IO_read_end
- fp
->_IO_read_ptr
));
165 fp
->_IO_read_base
= fp
->_IO_read_ptr
= fp
->_IO_buf_base
;
168 fp
->_IO_read_base
= fp
->_IO_read_ptr
= fp
->_IO_read_end
=
171 if (fp
->_IO_buf_base
== NULL
)
173 /* Maybe we already have a push back pointer. */
174 if (fp
->_IO_save_base
!= NULL
)
176 free (fp
->_IO_save_base
);
177 fp
->_flags
&= ~_IO_IN_BACKUP
;
181 fp
->_IO_read_base
= fp
->_IO_read_ptr
= fp
->_IO_read_end
=
185 fp
->_IO_write_base
= fp
->_IO_write_ptr
= fp
->_IO_write_end
=
188 if (fp
->_wide_data
->_IO_buf_base
== NULL
)
190 /* Maybe we already have a push back pointer. */
191 if (fp
->_wide_data
->_IO_save_base
!= NULL
)
193 free (fp
->_wide_data
->_IO_save_base
);
194 fp
->_flags
&= ~_IO_IN_BACKUP
;
196 _IO_wdoallocbuf (fp
);
199 /* Flush all line buffered files before reading. */
200 /* FIXME This can/should be moved to genops ?? */
201 if (fp
->_flags
& (_IO_LINE_BUF
| _IO_UNBUFFERED
))
204 _IO_flush_all_linebuffered ();
206 /* We used to flush all line-buffered stream. This really isn't
207 required by any standard. My recollection is that
208 traditional Unix systems did this for stdout. stderr better
209 not be line buffered. So we do just that here
210 explicitly. --drepper */
211 _IO_acquire_lock (_IO_stdout
);
213 if ((_IO_stdout
->_flags
& (_IO_LINKED
| _IO_NO_WRITES
| _IO_LINE_BUF
))
214 == (_IO_LINKED
| _IO_LINE_BUF
))
215 _IO_OVERFLOW (_IO_stdout
, EOF
);
217 _IO_release_lock (_IO_stdout
);
221 _IO_switch_to_get_mode (fp
);
223 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
=
224 fp
->_wide_data
->_IO_buf_base
;
225 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_buf_base
;
226 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
=
227 fp
->_wide_data
->_IO_write_end
= fp
->_wide_data
->_IO_buf_base
;
229 const char *read_ptr_copy
;
230 char accbuf
[MB_LEN_MAX
];
233 count
= _IO_SYSREAD (fp
, fp
->_IO_read_end
,
234 fp
->_IO_buf_end
- fp
->_IO_read_end
);
237 if (count
== 0 && naccbuf
== 0)
239 fp
->_flags
|= _IO_EOF_SEEN
;
240 fp
->_offset
= _IO_pos_BAD
;
243 fp
->_flags
|= _IO_ERR_SEEN
, count
= 0;
245 fp
->_IO_read_end
+= count
;
249 /* There are some bytes in the external buffer but they don't
250 convert to anything. */
251 __set_errno (EILSEQ
);
254 if (fp
->_offset
!= _IO_pos_BAD
)
255 _IO_pos_adjust (fp
->_offset
, count
);
257 /* Now convert the read input. */
258 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
259 fp
->_IO_read_base
= fp
->_IO_read_ptr
;
260 const char *from
= fp
->_IO_read_ptr
;
261 const char *to
= fp
->_IO_read_end
;
262 size_t to_copy
= count
;
263 if (__glibc_unlikely (naccbuf
!= 0))
265 to_copy
= MIN (sizeof (accbuf
) - naccbuf
, count
);
266 to
= __mempcpy (&accbuf
[naccbuf
], from
, to_copy
);
270 status
= (*cd
->__codecvt_do_in
) (cd
, &fp
->_wide_data
->_IO_state
,
271 from
, to
, &read_ptr_copy
,
272 fp
->_wide_data
->_IO_read_end
,
273 fp
->_wide_data
->_IO_buf_end
,
274 &fp
->_wide_data
->_IO_read_end
);
276 if (__glibc_unlikely (naccbuf
!= 0))
277 fp
->_IO_read_ptr
+= MAX (0, read_ptr_copy
- &accbuf
[naccbuf
- to_copy
]);
279 fp
->_IO_read_ptr
= (char *) read_ptr_copy
;
280 if (fp
->_wide_data
->_IO_read_end
== fp
->_wide_data
->_IO_buf_base
)
282 if (status
== __codecvt_error
)
285 __set_errno (EILSEQ
);
286 fp
->_flags
|= _IO_ERR_SEEN
;
290 /* The read bytes make no complete character. Try reading again. */
291 assert (status
== __codecvt_partial
);
295 if (fp
->_IO_read_base
< fp
->_IO_read_ptr
)
297 /* Partially used the buffer for some input data that
298 produces no output. */
299 size_t avail
= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
300 memmove (fp
->_IO_read_base
, fp
->_IO_read_ptr
, avail
);
301 fp
->_IO_read_ptr
= fp
->_IO_read_base
;
302 fp
->_IO_read_end
-= avail
;
305 naccbuf
= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
306 if (naccbuf
>= sizeof (accbuf
))
309 memcpy (accbuf
, fp
->_IO_read_ptr
, naccbuf
);
313 size_t used
= read_ptr_copy
- accbuf
;
316 memmove (accbuf
, read_ptr_copy
, naccbuf
- used
);
320 if (naccbuf
== sizeof (accbuf
))
324 fp
->_IO_read_ptr
= fp
->_IO_read_end
= fp
->_IO_read_base
;
329 return *fp
->_wide_data
->_IO_read_ptr
;
331 libc_hidden_def (_IO_wfile_underflow
)
335 _IO_wfile_underflow_mmap (_IO_FILE
*fp
)
337 struct _IO_codecvt
*cd
;
338 const char *read_stop
;
340 if (__glibc_unlikely (fp
->_flags
& _IO_NO_READS
))
342 fp
->_flags
|= _IO_ERR_SEEN
;
346 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
347 return *fp
->_wide_data
->_IO_read_ptr
;
351 /* Maybe there is something left in the external buffer. */
352 if (fp
->_IO_read_ptr
>= fp
->_IO_read_end
353 /* No. But maybe the read buffer is not fully set up. */
354 && _IO_file_underflow_mmap (fp
) == EOF
)
355 /* Nothing available. _IO_file_underflow_mmap has set the EOF or error
356 flags as appropriate. */
359 /* There is more in the external. Convert it. */
360 read_stop
= (const char *) fp
->_IO_read_ptr
;
362 if (fp
->_wide_data
->_IO_buf_base
== NULL
)
364 /* Maybe we already have a push back pointer. */
365 if (fp
->_wide_data
->_IO_save_base
!= NULL
)
367 free (fp
->_wide_data
->_IO_save_base
);
368 fp
->_flags
&= ~_IO_IN_BACKUP
;
370 _IO_wdoallocbuf (fp
);
373 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
374 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
=
375 fp
->_wide_data
->_IO_buf_base
;
376 (*cd
->__codecvt_do_in
) (cd
, &fp
->_wide_data
->_IO_state
,
377 fp
->_IO_read_ptr
, fp
->_IO_read_end
,
379 fp
->_wide_data
->_IO_read_ptr
,
380 fp
->_wide_data
->_IO_buf_end
,
381 &fp
->_wide_data
->_IO_read_end
);
383 fp
->_IO_read_ptr
= (char *) read_stop
;
385 /* If we managed to generate some text return the next character. */
386 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
387 return *fp
->_wide_data
->_IO_read_ptr
;
389 /* There is some garbage at the end of the file. */
390 __set_errno (EILSEQ
);
391 fp
->_flags
|= _IO_ERR_SEEN
;
396 _IO_wfile_underflow_maybe_mmap (_IO_FILE
*fp
)
398 /* This is the first read attempt. Doing the underflow will choose mmap
399 or vanilla operations and then punt to the chosen underflow routine.
400 Then we can punt to ours. */
401 if (_IO_file_underflow_maybe_mmap (fp
) == EOF
)
404 return _IO_WUNDERFLOW (fp
);
409 _IO_wfile_overflow (_IO_FILE
*f
, wint_t wch
)
411 if (f
->_flags
& _IO_NO_WRITES
) /* SET ERROR */
413 f
->_flags
|= _IO_ERR_SEEN
;
417 /* If currently reading or no buffer allocated. */
418 if ((f
->_flags
& _IO_CURRENTLY_PUTTING
) == 0)
420 /* Allocate a buffer if needed. */
421 if (f
->_wide_data
->_IO_write_base
== 0)
424 _IO_free_wbackup_area (f
);
425 _IO_wsetg (f
, f
->_wide_data
->_IO_buf_base
,
426 f
->_wide_data
->_IO_buf_base
, f
->_wide_data
->_IO_buf_base
);
428 if (f
->_IO_write_base
== NULL
)
431 _IO_setg (f
, f
->_IO_buf_base
, f
->_IO_buf_base
, f
->_IO_buf_base
);
436 /* Otherwise must be currently reading. If _IO_read_ptr
437 (and hence also _IO_read_end) is at the buffer end,
438 logically slide the buffer forwards one block (by setting
439 the read pointers to all point at the beginning of the
440 block). This makes room for subsequent output.
441 Otherwise, set the read pointers to _IO_read_end (leaving
442 that alone, so it can continue to correspond to the
443 external position). */
444 if (f
->_wide_data
->_IO_read_ptr
== f
->_wide_data
->_IO_buf_end
)
446 f
->_IO_read_end
= f
->_IO_read_ptr
= f
->_IO_buf_base
;
447 f
->_wide_data
->_IO_read_end
= f
->_wide_data
->_IO_read_ptr
=
448 f
->_wide_data
->_IO_buf_base
;
451 f
->_wide_data
->_IO_write_ptr
= f
->_wide_data
->_IO_read_ptr
;
452 f
->_wide_data
->_IO_write_base
= f
->_wide_data
->_IO_write_ptr
;
453 f
->_wide_data
->_IO_write_end
= f
->_wide_data
->_IO_buf_end
;
454 f
->_wide_data
->_IO_read_base
= f
->_wide_data
->_IO_read_ptr
=
455 f
->_wide_data
->_IO_read_end
;
457 f
->_IO_write_ptr
= f
->_IO_read_ptr
;
458 f
->_IO_write_base
= f
->_IO_write_ptr
;
459 f
->_IO_write_end
= f
->_IO_buf_end
;
460 f
->_IO_read_base
= f
->_IO_read_ptr
= f
->_IO_read_end
;
462 f
->_flags
|= _IO_CURRENTLY_PUTTING
;
463 if (f
->_flags
& (_IO_LINE_BUF
| _IO_UNBUFFERED
))
464 f
->_wide_data
->_IO_write_end
= f
->_wide_data
->_IO_write_ptr
;
467 return _IO_do_flush (f
);
468 if (f
->_wide_data
->_IO_write_ptr
== f
->_wide_data
->_IO_buf_end
)
469 /* Buffer is really full */
470 if (_IO_do_flush (f
) == EOF
)
472 *f
->_wide_data
->_IO_write_ptr
++ = wch
;
473 if ((f
->_flags
& _IO_UNBUFFERED
)
474 || ((f
->_flags
& _IO_LINE_BUF
) && wch
== L
'\n'))
475 if (_IO_do_flush (f
) == EOF
)
479 libc_hidden_def (_IO_wfile_overflow
)
482 _IO_wfile_sync (_IO_FILE
*fp
)
487 /* char* ptr = cur_ptr(); */
488 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_write_base
)
489 if (_IO_do_flush (fp
))
491 delta
= fp
->_wide_data
->_IO_read_ptr
- fp
->_wide_data
->_IO_read_end
;
494 /* We have to find out how many bytes we have to go back in the
496 struct _IO_codecvt
*cv
= fp
->_codecvt
;
499 int clen
= (*cv
->__codecvt_do_encoding
) (cv
);
502 /* It is easy, a fixed number of input bytes are used for each
507 /* We have to find out the hard way how much to back off.
508 To do this we determine how much input we needed to
509 generate the wide characters up to the current reading
513 fp
->_wide_data
->_IO_state
= fp
->_wide_data
->_IO_last_state
;
514 nread
= (*cv
->__codecvt_do_length
) (cv
, &fp
->_wide_data
->_IO_state
,
516 fp
->_IO_read_end
, delta
);
517 fp
->_IO_read_ptr
= fp
->_IO_read_base
+ nread
;
518 delta
= -(fp
->_IO_read_end
- fp
->_IO_read_base
- nread
);
521 new_pos
= _IO_SYSSEEK (fp
, delta
, 1);
522 if (new_pos
!= (_IO_off64_t
) EOF
)
524 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_read_ptr
;
525 fp
->_IO_read_end
= fp
->_IO_read_ptr
;
527 else if (errno
== ESPIPE
)
528 ; /* Ignore error from unseekable devices. */
533 fp
->_offset
= _IO_pos_BAD
;
534 /* FIXME: Cleanup - can this be shared? */
535 /* setg(base(), ptr, ptr); */
538 libc_hidden_def (_IO_wfile_sync
)
540 /* Adjust the internal buffer pointers to reflect the state in the external
541 buffer. The content between fp->_IO_read_base and fp->_IO_read_ptr is
542 assumed to be converted and available in the range
543 fp->_wide_data->_IO_read_base and fp->_wide_data->_IO_read_end.
545 Returns 0 on success and -1 on error with the _IO_ERR_SEEN flag set. */
547 adjust_wide_data (_IO_FILE
*fp
, bool do_convert
)
549 struct _IO_codecvt
*cv
= fp
->_codecvt
;
551 int clen
= (*cv
->__codecvt_do_encoding
) (cv
);
553 /* Take the easy way out for constant length encodings if we don't need to
555 if (!do_convert
&& clen
> 0)
557 fp
->_wide_data
->_IO_read_end
+= ((fp
->_IO_read_ptr
- fp
->_IO_read_base
)
562 enum __codecvt_result status
;
563 const char *read_stop
= (const char *) fp
->_IO_read_base
;
567 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
568 status
= (*cv
->__codecvt_do_in
) (cv
, &fp
->_wide_data
->_IO_state
,
569 fp
->_IO_read_base
, fp
->_IO_read_ptr
,
571 fp
->_wide_data
->_IO_read_base
,
572 fp
->_wide_data
->_IO_buf_end
,
573 &fp
->_wide_data
->_IO_read_end
);
575 /* Should we return EILSEQ? */
576 if (__glibc_unlikely (status
== __codecvt_error
))
578 fp
->_flags
|= _IO_ERR_SEEN
;
582 while (__builtin_expect (status
== __codecvt_partial
, 0));
585 /* Now seek to _IO_read_end to behave as if we have read it all in. */
586 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
591 /* ftell{,o} implementation for wide mode. Don't modify any state of the file
592 pointer while we try to get the current state of the stream except in one
593 case, which is when we have unflushed writes in append mode. */
595 do_ftell_wide (_IO_FILE
*fp
)
597 _IO_off64_t result
, offset
= 0;
599 /* No point looking for offsets in the buffer if it hasn't even been
601 if (fp
->_wide_data
->_IO_buf_base
!= NULL
)
603 const wchar_t *wide_read_base
;
604 const wchar_t *wide_read_ptr
;
605 const wchar_t *wide_read_end
;
606 bool unflushed_writes
= (fp
->_wide_data
->_IO_write_ptr
607 > fp
->_wide_data
->_IO_write_base
);
609 bool append_mode
= (fp
->_flags
& _IO_IS_APPENDING
) == _IO_IS_APPENDING
;
611 /* When we have unflushed writes in append mode, seek to the end of the
612 file and record that offset. This is the only time we change the file
613 stream state and it is safe since the file handle is active. */
614 if (unflushed_writes
&& append_mode
)
616 result
= _IO_SYSSEEK (fp
, 0, _IO_seek_end
);
617 if (result
== _IO_pos_BAD
)
620 fp
->_offset
= result
;
623 /* XXX For wide stream with backup store it is not very
624 reasonable to determine the offset. The pushed-back
625 character might require a state change and we need not be
626 able to compute the initial state by reverse transformation
627 since there is no guarantee of symmetry. So we don't even
628 try and return an error. */
629 if (_IO_in_backup (fp
))
631 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
633 __set_errno (EINVAL
);
637 /* Nothing in the backup store, so note the backed up pointers
638 without changing the state. */
639 wide_read_base
= fp
->_wide_data
->_IO_save_base
;
640 wide_read_ptr
= wide_read_base
;
641 wide_read_end
= fp
->_wide_data
->_IO_save_end
;
645 wide_read_base
= fp
->_wide_data
->_IO_read_base
;
646 wide_read_ptr
= fp
->_wide_data
->_IO_read_ptr
;
647 wide_read_end
= fp
->_wide_data
->_IO_read_end
;
650 struct _IO_codecvt
*cv
= fp
->_codecvt
;
651 int clen
= (*cv
->__codecvt_do_encoding
) (cv
);
653 if (!unflushed_writes
)
657 offset
-= (wide_read_end
- wide_read_ptr
) * clen
;
658 offset
-= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
664 size_t delta
= wide_read_ptr
- wide_read_base
;
665 __mbstate_t state
= fp
->_wide_data
->_IO_last_state
;
666 nread
= (*cv
->__codecvt_do_length
) (cv
, &state
,
668 fp
->_IO_read_end
, delta
);
669 offset
-= fp
->_IO_read_end
- fp
->_IO_read_base
- nread
;
675 offset
+= (fp
->_wide_data
->_IO_write_ptr
676 - fp
->_wide_data
->_IO_write_base
) * clen
;
679 size_t delta
= (fp
->_wide_data
->_IO_write_ptr
680 - fp
->_wide_data
->_IO_write_base
);
682 /* Allocate enough space for the conversion. */
683 size_t outsize
= delta
* sizeof (wchar_t);
684 char *out
= malloc (outsize
);
686 const wchar_t *in
= fp
->_wide_data
->_IO_write_base
;
688 enum __codecvt_result status
;
690 __mbstate_t state
= fp
->_wide_data
->_IO_last_state
;
691 status
= (*cv
->__codecvt_do_out
) (cv
, &state
,
693 out
, out
+ outsize
, &outstop
);
695 /* We don't check for __codecvt_partial because it can be
696 returned on one of two conditions: either the output
697 buffer is full or the input sequence is incomplete. We
698 take care to allocate enough buffer and our input
699 sequences must be complete since they are accepted as
700 wchar_t; if not, then that is an error. */
701 if (__glibc_unlikely (status
!= __codecvt_ok
))
707 offset
+= outstop
- out
;
711 /* We don't trust _IO_read_end to represent the current file offset
712 when writing in append mode because the value would have to be
713 shifted to the end of the file during a flush. Use the write base
714 instead, along with the new offset we got above when we did a seek
715 to the end of the file. */
717 offset
+= fp
->_IO_write_ptr
- fp
->_IO_write_base
;
718 /* For all other modes, _IO_read_end represents the file offset. */
720 offset
+= fp
->_IO_write_ptr
- fp
->_IO_read_end
;
724 if (fp
->_offset
!= _IO_pos_BAD
)
725 result
= fp
->_offset
;
727 result
= _IO_SYSSEEK (fp
, 0, _IO_seek_cur
);
736 __set_errno (EINVAL
);
744 _IO_wfile_seekoff (_IO_FILE
*fp
, _IO_off64_t offset
, int dir
, int mode
)
747 _IO_off64_t delta
, new_offset
;
750 /* Short-circuit into a separate function. We don't want to mix any
751 functionality and we don't want to touch anything inside the FILE
754 return do_ftell_wide (fp
);
756 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
757 offset of the underlying file must be exact. */
758 int must_be_exact
= ((fp
->_wide_data
->_IO_read_base
759 == fp
->_wide_data
->_IO_read_end
)
760 && (fp
->_wide_data
->_IO_write_base
761 == fp
->_wide_data
->_IO_write_ptr
));
763 bool was_writing
= ((fp
->_wide_data
->_IO_write_ptr
764 > fp
->_wide_data
->_IO_write_base
)
765 || _IO_in_put_mode (fp
));
767 /* Flush unwritten characters.
768 (This may do an unneeded write if we seek within the buffer.
769 But to be able to switch to reading, we would need to set
770 egptr to pptr. That can't be done in the current design,
771 which assumes file_ptr() is eGptr. Anyway, since we probably
772 end up flushing when we close(), it doesn't make much difference.)
773 FIXME: simulate mem-mapped files. */
774 if (was_writing
&& _IO_switch_to_wget_mode (fp
))
777 if (fp
->_wide_data
->_IO_buf_base
== NULL
)
779 /* It could be that we already have a pushback buffer. */
780 if (fp
->_wide_data
->_IO_read_base
!= NULL
)
782 free (fp
->_wide_data
->_IO_read_base
);
783 fp
->_flags
&= ~_IO_IN_BACKUP
;
786 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
787 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
788 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
,
789 fp
->_wide_data
->_IO_buf_base
);
790 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
791 fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
796 struct _IO_codecvt
*cv
;
800 /* Adjust for read-ahead (bytes is buffer). To do this we must
801 find out which position in the external buffer corresponds to
802 the current position in the internal buffer. */
804 clen
= (*cv
->__codecvt_do_encoding
) (cv
);
806 if (mode
!= 0 || !was_writing
)
810 offset
-= (fp
->_wide_data
->_IO_read_end
811 - fp
->_wide_data
->_IO_read_ptr
) * clen
;
812 /* Adjust by readahead in external buffer. */
813 offset
-= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
819 delta
= (fp
->_wide_data
->_IO_read_ptr
820 - fp
->_wide_data
->_IO_read_base
);
821 fp
->_wide_data
->_IO_state
= fp
->_wide_data
->_IO_last_state
;
822 nread
= (*cv
->__codecvt_do_length
) (cv
,
823 &fp
->_wide_data
->_IO_state
,
825 fp
->_IO_read_end
, delta
);
826 fp
->_IO_read_ptr
= fp
->_IO_read_base
+ nread
;
827 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_read_ptr
;
828 offset
-= fp
->_IO_read_end
- fp
->_IO_read_base
- nread
;
832 if (fp
->_offset
== _IO_pos_BAD
)
835 /* Make offset absolute, assuming current pointer is file_ptr(). */
836 offset
+= fp
->_offset
;
845 if (_IO_SYSSTAT (fp
, &st
) == 0 && S_ISREG (st
.st_mode
))
847 offset
+= st
.st_size
;
855 _IO_free_wbackup_area (fp
);
857 /* At this point, dir==_IO_seek_set. */
859 /* If destination is within current buffer, optimize: */
860 if (fp
->_offset
!= _IO_pos_BAD
&& fp
->_IO_read_base
!= NULL
861 && !_IO_in_backup (fp
))
863 _IO_off64_t start_offset
= (fp
->_offset
864 - (fp
->_IO_read_end
- fp
->_IO_buf_base
));
865 if (offset
>= start_offset
&& offset
< fp
->_offset
)
867 _IO_setg (fp
, fp
->_IO_buf_base
,
868 fp
->_IO_buf_base
+ (offset
- start_offset
),
870 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
871 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
872 fp
->_wide_data
->_IO_buf_base
,
873 fp
->_wide_data
->_IO_buf_base
);
874 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
,
875 fp
->_wide_data
->_IO_buf_base
);
877 if (adjust_wide_data (fp
, false))
880 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
885 if (fp
->_flags
& _IO_NO_READS
)
888 /* Try to seek to a block boundary, to improve kernel page management. */
889 new_offset
= offset
& ~(fp
->_IO_buf_end
- fp
->_IO_buf_base
- 1);
890 delta
= offset
- new_offset
;
891 if (delta
> fp
->_IO_buf_end
- fp
->_IO_buf_base
)
896 result
= _IO_SYSSEEK (fp
, new_offset
, 0);
903 count
= _IO_SYSREAD (fp
, fp
->_IO_buf_base
,
905 ? delta
: fp
->_IO_buf_end
- fp
->_IO_buf_base
));
908 /* We weren't allowed to read, but try to seek the remainder. */
909 offset
= count
== EOF
? delta
: delta
-count
;
914 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
+ delta
,
915 fp
->_IO_buf_base
+ count
);
916 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
917 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
918 fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
919 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
921 if (adjust_wide_data (fp
, true))
924 fp
->_offset
= result
+ count
;
925 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
929 _IO_unsave_markers (fp
);
930 result
= _IO_SYSSEEK (fp
, offset
, dir
);
933 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
934 fp
->_offset
= result
;
935 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
936 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
937 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
938 fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
939 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
,
940 fp
->_wide_data
->_IO_buf_base
);
945 /* We need to do it since it is possible that the file offset in
946 the kernel may be changed behind our back. It may happen when
947 we fopen a file and then do a fork. One process may access the
948 file and the kernel file offset will be changed. */
949 if (fp
->_offset
>= 0)
950 _IO_SYSSEEK (fp
, fp
->_offset
, 0);
954 libc_hidden_def (_IO_wfile_seekoff
)
958 _IO_wfile_xsputn (_IO_FILE
*f
, const void *data
, _IO_size_t n
)
960 const wchar_t *s
= (const wchar_t *) data
;
961 _IO_size_t to_do
= n
;
967 /* This is an optimized implementation.
968 If the amount to be written straddles a block boundary
969 (or the filebuf is unbuffered), use sys_write directly. */
971 /* First figure out how much space is available in the buffer. */
972 count
= f
->_wide_data
->_IO_write_end
- f
->_wide_data
->_IO_write_ptr
;
973 if ((f
->_flags
& _IO_LINE_BUF
) && (f
->_flags
& _IO_CURRENTLY_PUTTING
))
975 count
= f
->_wide_data
->_IO_buf_end
- f
->_wide_data
->_IO_write_ptr
;
979 for (p
= s
+ n
; p
> s
; )
990 /* Then fill the buffer. */
997 f
->_wide_data
->_IO_write_ptr
=
998 __wmempcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
1003 wchar_t *p
= f
->_wide_data
->_IO_write_ptr
;
1004 int i
= (int) count
;
1007 f
->_wide_data
->_IO_write_ptr
= p
;
1012 to_do
-= _IO_wdefault_xsputn (f
, s
, to_do
);
1014 && f
->_wide_data
->_IO_write_ptr
!= f
->_wide_data
->_IO_write_base
)
1015 _IO_wdo_write (f
, f
->_wide_data
->_IO_write_base
,
1016 f
->_wide_data
->_IO_write_ptr
1017 - f
->_wide_data
->_IO_write_base
);
1021 libc_hidden_def (_IO_wfile_xsputn
)
1024 const struct _IO_jump_t _IO_wfile_jumps libio_vtable
=
1027 JUMP_INIT(finish
, _IO_new_file_finish
),
1028 JUMP_INIT(overflow
, (_IO_overflow_t
) _IO_wfile_overflow
),
1029 JUMP_INIT(underflow
, (_IO_underflow_t
) _IO_wfile_underflow
),
1030 JUMP_INIT(uflow
, (_IO_underflow_t
) _IO_wdefault_uflow
),
1031 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) _IO_wdefault_pbackfail
),
1032 JUMP_INIT(xsputn
, _IO_wfile_xsputn
),
1033 JUMP_INIT(xsgetn
, _IO_file_xsgetn
),
1034 JUMP_INIT(seekoff
, _IO_wfile_seekoff
),
1035 JUMP_INIT(seekpos
, _IO_default_seekpos
),
1036 JUMP_INIT(setbuf
, _IO_new_file_setbuf
),
1037 JUMP_INIT(sync
, (_IO_sync_t
) _IO_wfile_sync
),
1038 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
1039 JUMP_INIT(read
, _IO_file_read
),
1040 JUMP_INIT(write
, _IO_new_file_write
),
1041 JUMP_INIT(seek
, _IO_file_seek
),
1042 JUMP_INIT(close
, _IO_file_close
),
1043 JUMP_INIT(stat
, _IO_file_stat
),
1044 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
1045 JUMP_INIT(imbue
, _IO_default_imbue
)
1047 libc_hidden_data_def (_IO_wfile_jumps
)
1050 const struct _IO_jump_t _IO_wfile_jumps_mmap libio_vtable
=
1053 JUMP_INIT(finish
, _IO_new_file_finish
),
1054 JUMP_INIT(overflow
, (_IO_overflow_t
) _IO_wfile_overflow
),
1055 JUMP_INIT(underflow
, (_IO_underflow_t
) _IO_wfile_underflow_mmap
),
1056 JUMP_INIT(uflow
, (_IO_underflow_t
) _IO_wdefault_uflow
),
1057 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) _IO_wdefault_pbackfail
),
1058 JUMP_INIT(xsputn
, _IO_wfile_xsputn
),
1059 JUMP_INIT(xsgetn
, _IO_file_xsgetn
),
1060 JUMP_INIT(seekoff
, _IO_wfile_seekoff
),
1061 JUMP_INIT(seekpos
, _IO_default_seekpos
),
1062 JUMP_INIT(setbuf
, _IO_file_setbuf_mmap
),
1063 JUMP_INIT(sync
, (_IO_sync_t
) _IO_wfile_sync
),
1064 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
1065 JUMP_INIT(read
, _IO_file_read
),
1066 JUMP_INIT(write
, _IO_new_file_write
),
1067 JUMP_INIT(seek
, _IO_file_seek
),
1068 JUMP_INIT(close
, _IO_file_close_mmap
),
1069 JUMP_INIT(stat
, _IO_file_stat
),
1070 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
1071 JUMP_INIT(imbue
, _IO_default_imbue
)
1074 const struct _IO_jump_t _IO_wfile_jumps_maybe_mmap libio_vtable
=
1077 JUMP_INIT(finish
, _IO_new_file_finish
),
1078 JUMP_INIT(overflow
, (_IO_overflow_t
) _IO_wfile_overflow
),
1079 JUMP_INIT(underflow
, (_IO_underflow_t
) _IO_wfile_underflow_maybe_mmap
),
1080 JUMP_INIT(uflow
, (_IO_underflow_t
) _IO_wdefault_uflow
),
1081 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) _IO_wdefault_pbackfail
),
1082 JUMP_INIT(xsputn
, _IO_wfile_xsputn
),
1083 JUMP_INIT(xsgetn
, _IO_file_xsgetn
),
1084 JUMP_INIT(seekoff
, _IO_wfile_seekoff
),
1085 JUMP_INIT(seekpos
, _IO_default_seekpos
),
1086 JUMP_INIT(setbuf
, _IO_file_setbuf_mmap
),
1087 JUMP_INIT(sync
, (_IO_sync_t
) _IO_wfile_sync
),
1088 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
1089 JUMP_INIT(read
, _IO_file_read
),
1090 JUMP_INIT(write
, _IO_new_file_write
),
1091 JUMP_INIT(seek
, _IO_file_seek
),
1092 JUMP_INIT(close
, _IO_file_close
),
1093 JUMP_INIT(stat
, _IO_file_stat
),
1094 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
1095 JUMP_INIT(imbue
, _IO_default_imbue
)