1 /* Copyright (C) 1993-2018 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 (FILE *fp
, const wchar_t *data
, 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 (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 /* FIXME This can/should be moved to genops ?? */
200 if (fp
->_flags
& (_IO_LINE_BUF
| _IO_UNBUFFERED
))
202 /* We used to flush all line-buffered stream. This really isn't
203 required by any standard. My recollection is that
204 traditional Unix systems did this for stdout. stderr better
205 not be line buffered. So we do just that here
206 explicitly. --drepper */
207 _IO_acquire_lock (_IO_stdout
);
209 if ((_IO_stdout
->_flags
& (_IO_LINKED
| _IO_NO_WRITES
| _IO_LINE_BUF
))
210 == (_IO_LINKED
| _IO_LINE_BUF
))
211 _IO_OVERFLOW (_IO_stdout
, EOF
);
213 _IO_release_lock (_IO_stdout
);
216 _IO_switch_to_get_mode (fp
);
218 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
=
219 fp
->_wide_data
->_IO_buf_base
;
220 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_buf_base
;
221 fp
->_wide_data
->_IO_write_base
= fp
->_wide_data
->_IO_write_ptr
=
222 fp
->_wide_data
->_IO_write_end
= fp
->_wide_data
->_IO_buf_base
;
224 const char *read_ptr_copy
;
225 char accbuf
[MB_LEN_MAX
];
228 count
= _IO_SYSREAD (fp
, fp
->_IO_read_end
,
229 fp
->_IO_buf_end
- fp
->_IO_read_end
);
232 if (count
== 0 && naccbuf
== 0)
234 fp
->_flags
|= _IO_EOF_SEEN
;
235 fp
->_offset
= _IO_pos_BAD
;
238 fp
->_flags
|= _IO_ERR_SEEN
, count
= 0;
240 fp
->_IO_read_end
+= count
;
244 /* There are some bytes in the external buffer but they don't
245 convert to anything. */
246 __set_errno (EILSEQ
);
249 if (fp
->_offset
!= _IO_pos_BAD
)
250 _IO_pos_adjust (fp
->_offset
, count
);
252 /* Now convert the read input. */
253 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
254 fp
->_IO_read_base
= fp
->_IO_read_ptr
;
255 const char *from
= fp
->_IO_read_ptr
;
256 const char *to
= fp
->_IO_read_end
;
257 size_t to_copy
= count
;
258 if (__glibc_unlikely (naccbuf
!= 0))
260 to_copy
= MIN (sizeof (accbuf
) - naccbuf
, count
);
261 to
= __mempcpy (&accbuf
[naccbuf
], from
, to_copy
);
265 status
= (*cd
->__codecvt_do_in
) (cd
, &fp
->_wide_data
->_IO_state
,
266 from
, to
, &read_ptr_copy
,
267 fp
->_wide_data
->_IO_read_end
,
268 fp
->_wide_data
->_IO_buf_end
,
269 &fp
->_wide_data
->_IO_read_end
);
271 if (__glibc_unlikely (naccbuf
!= 0))
272 fp
->_IO_read_ptr
+= MAX (0, read_ptr_copy
- &accbuf
[naccbuf
- to_copy
]);
274 fp
->_IO_read_ptr
= (char *) read_ptr_copy
;
275 if (fp
->_wide_data
->_IO_read_end
== fp
->_wide_data
->_IO_buf_base
)
277 if (status
== __codecvt_error
)
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
);
290 if (fp
->_IO_read_base
< fp
->_IO_read_ptr
)
292 /* Partially used the buffer for some input data that
293 produces no output. */
294 size_t avail
= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
295 memmove (fp
->_IO_read_base
, fp
->_IO_read_ptr
, avail
);
296 fp
->_IO_read_ptr
= fp
->_IO_read_base
;
297 fp
->_IO_read_end
-= avail
;
300 naccbuf
= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
301 if (naccbuf
>= sizeof (accbuf
))
304 memcpy (accbuf
, fp
->_IO_read_ptr
, naccbuf
);
308 size_t used
= read_ptr_copy
- accbuf
;
311 memmove (accbuf
, read_ptr_copy
, naccbuf
- used
);
315 if (naccbuf
== sizeof (accbuf
))
319 fp
->_IO_read_ptr
= fp
->_IO_read_end
= fp
->_IO_read_base
;
324 return *fp
->_wide_data
->_IO_read_ptr
;
326 libc_hidden_def (_IO_wfile_underflow
)
330 _IO_wfile_underflow_mmap (FILE *fp
)
332 struct _IO_codecvt
*cd
;
333 const char *read_stop
;
335 if (__glibc_unlikely (fp
->_flags
& _IO_NO_READS
))
337 fp
->_flags
|= _IO_ERR_SEEN
;
341 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
342 return *fp
->_wide_data
->_IO_read_ptr
;
346 /* Maybe there is something left in the external buffer. */
347 if (fp
->_IO_read_ptr
>= fp
->_IO_read_end
348 /* No. But maybe the read buffer is not fully set up. */
349 && _IO_file_underflow_mmap (fp
) == EOF
)
350 /* Nothing available. _IO_file_underflow_mmap has set the EOF or error
351 flags as appropriate. */
354 /* There is more in the external. Convert it. */
355 read_stop
= (const char *) fp
->_IO_read_ptr
;
357 if (fp
->_wide_data
->_IO_buf_base
== NULL
)
359 /* Maybe we already have a push back pointer. */
360 if (fp
->_wide_data
->_IO_save_base
!= NULL
)
362 free (fp
->_wide_data
->_IO_save_base
);
363 fp
->_flags
&= ~_IO_IN_BACKUP
;
365 _IO_wdoallocbuf (fp
);
368 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
369 fp
->_wide_data
->_IO_read_base
= fp
->_wide_data
->_IO_read_ptr
=
370 fp
->_wide_data
->_IO_buf_base
;
371 (*cd
->__codecvt_do_in
) (cd
, &fp
->_wide_data
->_IO_state
,
372 fp
->_IO_read_ptr
, fp
->_IO_read_end
,
374 fp
->_wide_data
->_IO_read_ptr
,
375 fp
->_wide_data
->_IO_buf_end
,
376 &fp
->_wide_data
->_IO_read_end
);
378 fp
->_IO_read_ptr
= (char *) read_stop
;
380 /* If we managed to generate some text return the next character. */
381 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
382 return *fp
->_wide_data
->_IO_read_ptr
;
384 /* There is some garbage at the end of the file. */
385 __set_errno (EILSEQ
);
386 fp
->_flags
|= _IO_ERR_SEEN
;
391 _IO_wfile_underflow_maybe_mmap (FILE *fp
)
393 /* This is the first read attempt. Doing the underflow will choose mmap
394 or vanilla operations and then punt to the chosen underflow routine.
395 Then we can punt to ours. */
396 if (_IO_file_underflow_maybe_mmap (fp
) == EOF
)
399 return _IO_WUNDERFLOW (fp
);
404 _IO_wfile_overflow (FILE *f
, wint_t wch
)
406 if (f
->_flags
& _IO_NO_WRITES
) /* SET ERROR */
408 f
->_flags
|= _IO_ERR_SEEN
;
412 /* If currently reading or no buffer allocated. */
413 if ((f
->_flags
& _IO_CURRENTLY_PUTTING
) == 0)
415 /* Allocate a buffer if needed. */
416 if (f
->_wide_data
->_IO_write_base
== 0)
419 _IO_free_wbackup_area (f
);
420 _IO_wsetg (f
, f
->_wide_data
->_IO_buf_base
,
421 f
->_wide_data
->_IO_buf_base
, f
->_wide_data
->_IO_buf_base
);
423 if (f
->_IO_write_base
== NULL
)
426 _IO_setg (f
, f
->_IO_buf_base
, f
->_IO_buf_base
, f
->_IO_buf_base
);
431 /* Otherwise must be currently reading. If _IO_read_ptr
432 (and hence also _IO_read_end) is at the buffer end,
433 logically slide the buffer forwards one block (by setting
434 the read pointers to all point at the beginning of the
435 block). This makes room for subsequent output.
436 Otherwise, set the read pointers to _IO_read_end (leaving
437 that alone, so it can continue to correspond to the
438 external position). */
439 if (f
->_wide_data
->_IO_read_ptr
== f
->_wide_data
->_IO_buf_end
)
441 f
->_IO_read_end
= f
->_IO_read_ptr
= f
->_IO_buf_base
;
442 f
->_wide_data
->_IO_read_end
= f
->_wide_data
->_IO_read_ptr
=
443 f
->_wide_data
->_IO_buf_base
;
446 f
->_wide_data
->_IO_write_ptr
= f
->_wide_data
->_IO_read_ptr
;
447 f
->_wide_data
->_IO_write_base
= f
->_wide_data
->_IO_write_ptr
;
448 f
->_wide_data
->_IO_write_end
= f
->_wide_data
->_IO_buf_end
;
449 f
->_wide_data
->_IO_read_base
= f
->_wide_data
->_IO_read_ptr
=
450 f
->_wide_data
->_IO_read_end
;
452 f
->_IO_write_ptr
= f
->_IO_read_ptr
;
453 f
->_IO_write_base
= f
->_IO_write_ptr
;
454 f
->_IO_write_end
= f
->_IO_buf_end
;
455 f
->_IO_read_base
= f
->_IO_read_ptr
= f
->_IO_read_end
;
457 f
->_flags
|= _IO_CURRENTLY_PUTTING
;
458 if (f
->_flags
& (_IO_LINE_BUF
| _IO_UNBUFFERED
))
459 f
->_wide_data
->_IO_write_end
= f
->_wide_data
->_IO_write_ptr
;
462 return _IO_do_flush (f
);
463 if (f
->_wide_data
->_IO_write_ptr
== f
->_wide_data
->_IO_buf_end
)
464 /* Buffer is really full */
465 if (_IO_do_flush (f
) == EOF
)
467 *f
->_wide_data
->_IO_write_ptr
++ = wch
;
468 if ((f
->_flags
& _IO_UNBUFFERED
)
469 || ((f
->_flags
& _IO_LINE_BUF
) && wch
== L
'\n'))
470 if (_IO_do_flush (f
) == EOF
)
474 libc_hidden_def (_IO_wfile_overflow
)
477 _IO_wfile_sync (FILE *fp
)
482 /* char* ptr = cur_ptr(); */
483 if (fp
->_wide_data
->_IO_write_ptr
> fp
->_wide_data
->_IO_write_base
)
484 if (_IO_do_flush (fp
))
486 delta
= fp
->_wide_data
->_IO_read_ptr
- fp
->_wide_data
->_IO_read_end
;
489 /* We have to find out how many bytes we have to go back in the
491 struct _IO_codecvt
*cv
= fp
->_codecvt
;
494 int clen
= (*cv
->__codecvt_do_encoding
) (cv
);
497 /* It is easy, a fixed number of input bytes are used for each
502 /* We have to find out the hard way how much to back off.
503 To do this we determine how much input we needed to
504 generate the wide characters up to the current reading
508 fp
->_wide_data
->_IO_state
= fp
->_wide_data
->_IO_last_state
;
509 nread
= (*cv
->__codecvt_do_length
) (cv
, &fp
->_wide_data
->_IO_state
,
511 fp
->_IO_read_end
, delta
);
512 fp
->_IO_read_ptr
= fp
->_IO_read_base
+ nread
;
513 delta
= -(fp
->_IO_read_end
- fp
->_IO_read_base
- nread
);
516 new_pos
= _IO_SYSSEEK (fp
, delta
, 1);
517 if (new_pos
!= (off64_t
) EOF
)
519 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_read_ptr
;
520 fp
->_IO_read_end
= fp
->_IO_read_ptr
;
522 else if (errno
== ESPIPE
)
523 ; /* Ignore error from unseekable devices. */
528 fp
->_offset
= _IO_pos_BAD
;
529 /* FIXME: Cleanup - can this be shared? */
530 /* setg(base(), ptr, ptr); */
533 libc_hidden_def (_IO_wfile_sync
)
535 /* Adjust the internal buffer pointers to reflect the state in the external
536 buffer. The content between fp->_IO_read_base and fp->_IO_read_ptr is
537 assumed to be converted and available in the range
538 fp->_wide_data->_IO_read_base and fp->_wide_data->_IO_read_end.
540 Returns 0 on success and -1 on error with the _IO_ERR_SEEN flag set. */
542 adjust_wide_data (FILE *fp
, bool do_convert
)
544 struct _IO_codecvt
*cv
= fp
->_codecvt
;
546 int clen
= (*cv
->__codecvt_do_encoding
) (cv
);
548 /* Take the easy way out for constant length encodings if we don't need to
550 if (!do_convert
&& clen
> 0)
552 fp
->_wide_data
->_IO_read_end
+= ((fp
->_IO_read_ptr
- fp
->_IO_read_base
)
557 enum __codecvt_result status
;
558 const char *read_stop
= (const char *) fp
->_IO_read_base
;
562 fp
->_wide_data
->_IO_last_state
= fp
->_wide_data
->_IO_state
;
563 status
= (*cv
->__codecvt_do_in
) (cv
, &fp
->_wide_data
->_IO_state
,
564 fp
->_IO_read_base
, fp
->_IO_read_ptr
,
566 fp
->_wide_data
->_IO_read_base
,
567 fp
->_wide_data
->_IO_buf_end
,
568 &fp
->_wide_data
->_IO_read_end
);
570 /* Should we return EILSEQ? */
571 if (__glibc_unlikely (status
== __codecvt_error
))
573 fp
->_flags
|= _IO_ERR_SEEN
;
577 while (__builtin_expect (status
== __codecvt_partial
, 0));
580 /* Now seek to _IO_read_end to behave as if we have read it all in. */
581 fp
->_wide_data
->_IO_read_ptr
= fp
->_wide_data
->_IO_read_end
;
586 /* ftell{,o} implementation for wide mode. Don't modify any state of the file
587 pointer while we try to get the current state of the stream except in one
588 case, which is when we have unflushed writes in append mode. */
590 do_ftell_wide (FILE *fp
)
592 off64_t result
, offset
= 0;
594 /* No point looking for offsets in the buffer if it hasn't even been
596 if (fp
->_wide_data
->_IO_buf_base
!= NULL
)
598 const wchar_t *wide_read_base
;
599 const wchar_t *wide_read_ptr
;
600 const wchar_t *wide_read_end
;
601 bool unflushed_writes
= (fp
->_wide_data
->_IO_write_ptr
602 > fp
->_wide_data
->_IO_write_base
);
604 bool append_mode
= (fp
->_flags
& _IO_IS_APPENDING
) == _IO_IS_APPENDING
;
606 /* When we have unflushed writes in append mode, seek to the end of the
607 file and record that offset. This is the only time we change the file
608 stream state and it is safe since the file handle is active. */
609 if (unflushed_writes
&& append_mode
)
611 result
= _IO_SYSSEEK (fp
, 0, _IO_seek_end
);
612 if (result
== _IO_pos_BAD
)
615 fp
->_offset
= result
;
618 /* XXX For wide stream with backup store it is not very
619 reasonable to determine the offset. The pushed-back
620 character might require a state change and we need not be
621 able to compute the initial state by reverse transformation
622 since there is no guarantee of symmetry. So we don't even
623 try and return an error. */
624 if (_IO_in_backup (fp
))
626 if (fp
->_wide_data
->_IO_read_ptr
< fp
->_wide_data
->_IO_read_end
)
628 __set_errno (EINVAL
);
632 /* Nothing in the backup store, so note the backed up pointers
633 without changing the state. */
634 wide_read_base
= fp
->_wide_data
->_IO_save_base
;
635 wide_read_ptr
= wide_read_base
;
636 wide_read_end
= fp
->_wide_data
->_IO_save_end
;
640 wide_read_base
= fp
->_wide_data
->_IO_read_base
;
641 wide_read_ptr
= fp
->_wide_data
->_IO_read_ptr
;
642 wide_read_end
= fp
->_wide_data
->_IO_read_end
;
645 struct _IO_codecvt
*cv
= fp
->_codecvt
;
646 int clen
= (*cv
->__codecvt_do_encoding
) (cv
);
648 if (!unflushed_writes
)
652 offset
-= (wide_read_end
- wide_read_ptr
) * clen
;
653 offset
-= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
659 size_t delta
= wide_read_ptr
- wide_read_base
;
660 __mbstate_t state
= fp
->_wide_data
->_IO_last_state
;
661 nread
= (*cv
->__codecvt_do_length
) (cv
, &state
,
663 fp
->_IO_read_end
, delta
);
664 offset
-= fp
->_IO_read_end
- fp
->_IO_read_base
- nread
;
670 offset
+= (fp
->_wide_data
->_IO_write_ptr
671 - fp
->_wide_data
->_IO_write_base
) * clen
;
674 size_t delta
= (fp
->_wide_data
->_IO_write_ptr
675 - fp
->_wide_data
->_IO_write_base
);
677 /* Allocate enough space for the conversion. */
678 size_t outsize
= delta
* sizeof (wchar_t);
679 char *out
= malloc (outsize
);
681 const wchar_t *in
= fp
->_wide_data
->_IO_write_base
;
683 enum __codecvt_result status
;
685 __mbstate_t state
= fp
->_wide_data
->_IO_last_state
;
686 status
= (*cv
->__codecvt_do_out
) (cv
, &state
,
688 out
, out
+ outsize
, &outstop
);
690 /* We don't check for __codecvt_partial because it can be
691 returned on one of two conditions: either the output
692 buffer is full or the input sequence is incomplete. We
693 take care to allocate enough buffer and our input
694 sequences must be complete since they are accepted as
695 wchar_t; if not, then that is an error. */
696 if (__glibc_unlikely (status
!= __codecvt_ok
))
702 offset
+= outstop
- out
;
706 /* We don't trust _IO_read_end to represent the current file offset
707 when writing in append mode because the value would have to be
708 shifted to the end of the file during a flush. Use the write base
709 instead, along with the new offset we got above when we did a seek
710 to the end of the file. */
712 offset
+= fp
->_IO_write_ptr
- fp
->_IO_write_base
;
713 /* For all other modes, _IO_read_end represents the file offset. */
715 offset
+= fp
->_IO_write_ptr
- fp
->_IO_read_end
;
719 if (fp
->_offset
!= _IO_pos_BAD
)
720 result
= fp
->_offset
;
722 result
= _IO_SYSSEEK (fp
, 0, _IO_seek_cur
);
731 __set_errno (EINVAL
);
739 _IO_wfile_seekoff (FILE *fp
, off64_t offset
, int dir
, int mode
)
742 off64_t delta
, new_offset
;
745 /* Short-circuit into a separate function. We don't want to mix any
746 functionality and we don't want to touch anything inside the FILE
749 return do_ftell_wide (fp
);
751 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
752 offset of the underlying file must be exact. */
753 int must_be_exact
= ((fp
->_wide_data
->_IO_read_base
754 == fp
->_wide_data
->_IO_read_end
)
755 && (fp
->_wide_data
->_IO_write_base
756 == fp
->_wide_data
->_IO_write_ptr
));
758 bool was_writing
= ((fp
->_wide_data
->_IO_write_ptr
759 > fp
->_wide_data
->_IO_write_base
)
760 || _IO_in_put_mode (fp
));
762 /* Flush unwritten characters.
763 (This may do an unneeded write if we seek within the buffer.
764 But to be able to switch to reading, we would need to set
765 egptr to pptr. That can't be done in the current design,
766 which assumes file_ptr() is eGptr. Anyway, since we probably
767 end up flushing when we close(), it doesn't make much difference.)
768 FIXME: simulate mem-mapped files. */
769 if (was_writing
&& _IO_switch_to_wget_mode (fp
))
772 if (fp
->_wide_data
->_IO_buf_base
== NULL
)
774 /* It could be that we already have a pushback buffer. */
775 if (fp
->_wide_data
->_IO_read_base
!= NULL
)
777 free (fp
->_wide_data
->_IO_read_base
);
778 fp
->_flags
&= ~_IO_IN_BACKUP
;
781 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
782 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
783 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
,
784 fp
->_wide_data
->_IO_buf_base
);
785 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
786 fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
791 struct _IO_codecvt
*cv
;
795 /* Adjust for read-ahead (bytes is buffer). To do this we must
796 find out which position in the external buffer corresponds to
797 the current position in the internal buffer. */
799 clen
= (*cv
->__codecvt_do_encoding
) (cv
);
801 if (mode
!= 0 || !was_writing
)
805 offset
-= (fp
->_wide_data
->_IO_read_end
806 - fp
->_wide_data
->_IO_read_ptr
) * clen
;
807 /* Adjust by readahead in external buffer. */
808 offset
-= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
814 delta
= (fp
->_wide_data
->_IO_read_ptr
815 - fp
->_wide_data
->_IO_read_base
);
816 fp
->_wide_data
->_IO_state
= fp
->_wide_data
->_IO_last_state
;
817 nread
= (*cv
->__codecvt_do_length
) (cv
,
818 &fp
->_wide_data
->_IO_state
,
820 fp
->_IO_read_end
, delta
);
821 fp
->_IO_read_ptr
= fp
->_IO_read_base
+ nread
;
822 fp
->_wide_data
->_IO_read_end
= fp
->_wide_data
->_IO_read_ptr
;
823 offset
-= fp
->_IO_read_end
- fp
->_IO_read_base
- nread
;
827 if (fp
->_offset
== _IO_pos_BAD
)
830 /* Make offset absolute, assuming current pointer is file_ptr(). */
831 offset
+= fp
->_offset
;
840 if (_IO_SYSSTAT (fp
, &st
) == 0 && S_ISREG (st
.st_mode
))
842 offset
+= st
.st_size
;
850 _IO_free_wbackup_area (fp
);
852 /* At this point, dir==_IO_seek_set. */
854 /* If destination is within current buffer, optimize: */
855 if (fp
->_offset
!= _IO_pos_BAD
&& fp
->_IO_read_base
!= NULL
856 && !_IO_in_backup (fp
))
858 off64_t start_offset
= (fp
->_offset
859 - (fp
->_IO_read_end
- fp
->_IO_buf_base
));
860 if (offset
>= start_offset
&& offset
< fp
->_offset
)
862 _IO_setg (fp
, fp
->_IO_buf_base
,
863 fp
->_IO_buf_base
+ (offset
- start_offset
),
865 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
866 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
867 fp
->_wide_data
->_IO_buf_base
,
868 fp
->_wide_data
->_IO_buf_base
);
869 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
,
870 fp
->_wide_data
->_IO_buf_base
);
872 if (adjust_wide_data (fp
, false))
875 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
880 if (fp
->_flags
& _IO_NO_READS
)
883 /* Try to seek to a block boundary, to improve kernel page management. */
884 new_offset
= offset
& ~(fp
->_IO_buf_end
- fp
->_IO_buf_base
- 1);
885 delta
= offset
- new_offset
;
886 if (delta
> fp
->_IO_buf_end
- fp
->_IO_buf_base
)
891 result
= _IO_SYSSEEK (fp
, new_offset
, 0);
898 count
= _IO_SYSREAD (fp
, fp
->_IO_buf_base
,
900 ? delta
: fp
->_IO_buf_end
- fp
->_IO_buf_base
));
903 /* We weren't allowed to read, but try to seek the remainder. */
904 offset
= count
== EOF
? delta
: delta
-count
;
909 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
+ delta
,
910 fp
->_IO_buf_base
+ count
);
911 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
912 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
913 fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
914 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
916 if (adjust_wide_data (fp
, true))
919 fp
->_offset
= result
+ count
;
920 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
924 _IO_unsave_markers (fp
);
925 result
= _IO_SYSSEEK (fp
, offset
, dir
);
928 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
929 fp
->_offset
= result
;
930 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
931 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
932 _IO_wsetg (fp
, fp
->_wide_data
->_IO_buf_base
,
933 fp
->_wide_data
->_IO_buf_base
, fp
->_wide_data
->_IO_buf_base
);
934 _IO_wsetp (fp
, fp
->_wide_data
->_IO_buf_base
,
935 fp
->_wide_data
->_IO_buf_base
);
940 /* We need to do it since it is possible that the file offset in
941 the kernel may be changed behind our back. It may happen when
942 we fopen a file and then do a fork. One process may access the
943 file and the kernel file offset will be changed. */
944 if (fp
->_offset
>= 0)
945 _IO_SYSSEEK (fp
, fp
->_offset
, 0);
949 libc_hidden_def (_IO_wfile_seekoff
)
953 _IO_wfile_xsputn (FILE *f
, const void *data
, size_t n
)
955 const wchar_t *s
= (const wchar_t *) data
;
962 /* This is an optimized implementation.
963 If the amount to be written straddles a block boundary
964 (or the filebuf is unbuffered), use sys_write directly. */
966 /* First figure out how much space is available in the buffer. */
967 count
= f
->_wide_data
->_IO_write_end
- f
->_wide_data
->_IO_write_ptr
;
968 if ((f
->_flags
& _IO_LINE_BUF
) && (f
->_flags
& _IO_CURRENTLY_PUTTING
))
970 count
= f
->_wide_data
->_IO_buf_end
- f
->_wide_data
->_IO_write_ptr
;
974 for (p
= s
+ n
; p
> s
; )
985 /* Then fill the buffer. */
992 f
->_wide_data
->_IO_write_ptr
=
993 __wmempcpy (f
->_wide_data
->_IO_write_ptr
, s
, count
);
998 wchar_t *p
= f
->_wide_data
->_IO_write_ptr
;
1002 f
->_wide_data
->_IO_write_ptr
= p
;
1007 to_do
-= _IO_wdefault_xsputn (f
, s
, to_do
);
1009 && f
->_wide_data
->_IO_write_ptr
!= f
->_wide_data
->_IO_write_base
)
1010 _IO_wdo_write (f
, f
->_wide_data
->_IO_write_base
,
1011 f
->_wide_data
->_IO_write_ptr
1012 - f
->_wide_data
->_IO_write_base
);
1016 libc_hidden_def (_IO_wfile_xsputn
)
1019 const struct _IO_jump_t _IO_wfile_jumps libio_vtable
=
1022 JUMP_INIT(finish
, _IO_new_file_finish
),
1023 JUMP_INIT(overflow
, (_IO_overflow_t
) _IO_wfile_overflow
),
1024 JUMP_INIT(underflow
, (_IO_underflow_t
) _IO_wfile_underflow
),
1025 JUMP_INIT(uflow
, (_IO_underflow_t
) _IO_wdefault_uflow
),
1026 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) _IO_wdefault_pbackfail
),
1027 JUMP_INIT(xsputn
, _IO_wfile_xsputn
),
1028 JUMP_INIT(xsgetn
, _IO_file_xsgetn
),
1029 JUMP_INIT(seekoff
, _IO_wfile_seekoff
),
1030 JUMP_INIT(seekpos
, _IO_default_seekpos
),
1031 JUMP_INIT(setbuf
, _IO_new_file_setbuf
),
1032 JUMP_INIT(sync
, (_IO_sync_t
) _IO_wfile_sync
),
1033 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
1034 JUMP_INIT(read
, _IO_file_read
),
1035 JUMP_INIT(write
, _IO_new_file_write
),
1036 JUMP_INIT(seek
, _IO_file_seek
),
1037 JUMP_INIT(close
, _IO_file_close
),
1038 JUMP_INIT(stat
, _IO_file_stat
),
1039 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
1040 JUMP_INIT(imbue
, _IO_default_imbue
)
1042 libc_hidden_data_def (_IO_wfile_jumps
)
1045 const struct _IO_jump_t _IO_wfile_jumps_mmap libio_vtable
=
1048 JUMP_INIT(finish
, _IO_new_file_finish
),
1049 JUMP_INIT(overflow
, (_IO_overflow_t
) _IO_wfile_overflow
),
1050 JUMP_INIT(underflow
, (_IO_underflow_t
) _IO_wfile_underflow_mmap
),
1051 JUMP_INIT(uflow
, (_IO_underflow_t
) _IO_wdefault_uflow
),
1052 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) _IO_wdefault_pbackfail
),
1053 JUMP_INIT(xsputn
, _IO_wfile_xsputn
),
1054 JUMP_INIT(xsgetn
, _IO_file_xsgetn
),
1055 JUMP_INIT(seekoff
, _IO_wfile_seekoff
),
1056 JUMP_INIT(seekpos
, _IO_default_seekpos
),
1057 JUMP_INIT(setbuf
, _IO_file_setbuf_mmap
),
1058 JUMP_INIT(sync
, (_IO_sync_t
) _IO_wfile_sync
),
1059 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
1060 JUMP_INIT(read
, _IO_file_read
),
1061 JUMP_INIT(write
, _IO_new_file_write
),
1062 JUMP_INIT(seek
, _IO_file_seek
),
1063 JUMP_INIT(close
, _IO_file_close_mmap
),
1064 JUMP_INIT(stat
, _IO_file_stat
),
1065 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
1066 JUMP_INIT(imbue
, _IO_default_imbue
)
1069 const struct _IO_jump_t _IO_wfile_jumps_maybe_mmap libio_vtable
=
1072 JUMP_INIT(finish
, _IO_new_file_finish
),
1073 JUMP_INIT(overflow
, (_IO_overflow_t
) _IO_wfile_overflow
),
1074 JUMP_INIT(underflow
, (_IO_underflow_t
) _IO_wfile_underflow_maybe_mmap
),
1075 JUMP_INIT(uflow
, (_IO_underflow_t
) _IO_wdefault_uflow
),
1076 JUMP_INIT(pbackfail
, (_IO_pbackfail_t
) _IO_wdefault_pbackfail
),
1077 JUMP_INIT(xsputn
, _IO_wfile_xsputn
),
1078 JUMP_INIT(xsgetn
, _IO_file_xsgetn
),
1079 JUMP_INIT(seekoff
, _IO_wfile_seekoff
),
1080 JUMP_INIT(seekpos
, _IO_default_seekpos
),
1081 JUMP_INIT(setbuf
, _IO_file_setbuf_mmap
),
1082 JUMP_INIT(sync
, (_IO_sync_t
) _IO_wfile_sync
),
1083 JUMP_INIT(doallocate
, _IO_wfile_doallocate
),
1084 JUMP_INIT(read
, _IO_file_read
),
1085 JUMP_INIT(write
, _IO_new_file_write
),
1086 JUMP_INIT(seek
, _IO_file_seek
),
1087 JUMP_INIT(close
, _IO_file_close
),
1088 JUMP_INIT(stat
, _IO_file_stat
),
1089 JUMP_INIT(showmanyc
, _IO_default_showmanyc
),
1090 JUMP_INIT(imbue
, _IO_default_imbue
)