Remove IS_IN_ldconfig
[glibc.git] / libio / wfileops.c
blob6a088b1c1559058a723a70cb3b1aa21e87ae3bd0
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. */
29 #include <assert.h>
30 #include <libioP.h>
31 #include <wchar.h>
32 #include <gconv.h>
33 #include <stdlib.h>
34 #include <string.h>
37 #ifndef _LIBC
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
51 #endif
54 /* Convert TO_DO wide character from DATA to FP.
55 Then mark FP as having empty buffers. */
56 int
57 _IO_wdo_write (fp, data, to_do)
58 _IO_FILE *fp;
59 const wchar_t *data;
60 _IO_size_t to_do;
62 struct _IO_codecvt *cc = fp->_codecvt;
64 if (to_do > 0)
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)
71 return WEOF;
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
84 character. */
85 write_ptr = write_base = mb_buf;
86 buf_end = mb_buf + sizeof (mb_buf);
88 else
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,
98 write_ptr,
99 buf_end,
100 &write_ptr);
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. */
105 return WEOF;
107 to_do -= new_data - data;
109 /* Next see whether we had problems during the conversion. If yes,
110 we cannot go on. */
111 if (result != __codecvt_ok
112 && (result != __codecvt_partial || new_data - data == 0))
113 break;
115 data = new_data;
117 while (to_do > 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)
133 wint_t
134 _IO_wfile_underflow (fp)
135 _IO_FILE *fp;
137 struct _IO_codecvt *cd;
138 enum __codecvt_result status;
139 _IO_ssize_t count;
141 if (__glibc_unlikely (fp->_flags & _IO_NO_READS))
143 fp->_flags |= _IO_ERR_SEEN;
144 __set_errno (EBADF);
145 return WEOF;
147 if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
148 return *fp->_wide_data->_IO_read_ptr;
150 cd = fp->_codecvt;
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,
163 &read_stop,
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;
179 return WEOF;
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;
189 else
190 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end =
191 fp->_IO_buf_base;
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;
201 _IO_doallocbuf (fp);
203 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end =
204 fp->_IO_buf_base;
207 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end =
208 fp->_IO_buf_base;
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))
225 #if 0
226 _IO_flush_all_linebuffered ();
227 #else
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);
240 #endif
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];
253 size_t naccbuf = 0;
254 again:
255 count = _IO_SYSREAD (fp, fp->_IO_read_end,
256 fp->_IO_buf_end - fp->_IO_read_end);
257 if (count <= 0)
259 if (count == 0 && naccbuf == 0)
260 fp->_flags |= _IO_EOF_SEEN;
261 else
262 fp->_flags |= _IO_ERR_SEEN, count = 0;
264 fp->_IO_read_end += count;
265 if (count == 0)
267 if (naccbuf != 0)
268 /* There are some bytes in the external buffer but they don't
269 convert to anything. */
270 __set_errno (EILSEQ);
271 return WEOF;
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);
286 naccbuf += to_copy;
287 from = accbuf;
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]);
297 else
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)
303 out_eilseq:
304 __set_errno (EILSEQ);
305 fp->_flags |= _IO_ERR_SEEN;
306 return WEOF;
309 /* The read bytes make no complete character. Try reading again. */
310 assert (status == __codecvt_partial);
312 if (naccbuf == 0)
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;
322 goto again;
324 naccbuf = fp->_IO_read_end - fp->_IO_read_ptr;
325 if (naccbuf >= sizeof (accbuf))
326 goto out_eilseq;
328 memcpy (accbuf, fp->_IO_read_ptr, naccbuf);
330 else
332 size_t used = read_ptr_copy - accbuf;
333 if (used > 0)
335 memmove (accbuf, read_ptr_copy, naccbuf - used);
336 naccbuf -= used;
339 if (naccbuf == sizeof (accbuf))
340 goto out_eilseq;
343 fp->_IO_read_ptr = fp->_IO_read_end = fp->_IO_read_base;
345 goto again;
348 return *fp->_wide_data->_IO_read_ptr;
350 libc_hidden_def (_IO_wfile_underflow)
353 static wint_t
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;
362 __set_errno (EBADF);
363 return WEOF;
365 if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
366 return *fp->_wide_data->_IO_read_ptr;
368 cd = fp->_codecvt;
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. */
376 return WEOF;
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,
397 &read_stop,
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;
411 return WEOF;
414 static wint_t
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)
421 return WEOF;
423 return _IO_WUNDERFLOW (fp);
427 wint_t
428 _IO_wfile_overflow (f, wch)
429 _IO_FILE *f;
430 wint_t wch;
432 if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
434 f->_flags |= _IO_ERR_SEEN;
435 __set_errno (EBADF);
436 return WEOF;
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)
444 _IO_wdoallocbuf (f);
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)
450 _IO_doallocbuf (f);
451 _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
454 else
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;
486 if (wch == WEOF)
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)
491 return WEOF;
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)
496 return WEOF;
497 return wch;
499 libc_hidden_def (_IO_wfile_overflow)
501 wint_t
502 _IO_wfile_sync (fp)
503 _IO_FILE *fp;
505 _IO_ssize_t delta;
506 wint_t retval = 0;
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))
511 return WEOF;
512 delta = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end;
513 if (delta != 0)
515 /* We have to find out how many bytes we have to go back in the
516 external buffer. */
517 struct _IO_codecvt *cv = fp->_codecvt;
518 _IO_off64_t new_pos;
520 int clen = (*cv->__codecvt_do_encoding) (cv);
522 if (clen > 0)
523 /* It is easy, a fixed number of input bytes are used for each
524 wide character. */
525 delta *= clen;
526 else
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
531 position. */
532 int nread;
534 fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
535 nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state,
536 fp->_IO_read_base,
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;
548 #ifdef ESPIPE
549 else if (errno == ESPIPE)
550 ; /* Ignore error from unseekable devices. */
551 #endif
552 else
553 retval = WEOF;
555 if (retval != WEOF)
556 fp->_offset = _IO_pos_BAD;
557 /* FIXME: Cleanup - can this be shared? */
558 /* setg(base(), ptr, ptr); */
559 return retval;
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. */
569 static int
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
577 convert. */
578 if (!do_convert && clen > 0)
580 fp->_wide_data->_IO_read_end += ((fp->_IO_read_ptr - fp->_IO_read_base)
581 / clen);
582 goto done;
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,
593 &read_stop,
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;
602 return -1;
605 while (__builtin_expect (status == __codecvt_partial, 0));
607 done:
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;
611 return 0;
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. */
617 static _IO_off64_t
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
623 allocated. */
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)
642 return EOF;
643 else
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);
658 return -1;
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;
667 else
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);
677 if (!was_writing)
679 if (clen > 0)
681 offset -= (wide_read_end - wide_read_ptr) * clen;
682 offset -= fp->_IO_read_end - fp->_IO_read_ptr;
684 else
686 int nread;
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,
691 fp->_IO_read_base,
692 fp->_IO_read_end, delta);
693 offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
696 else
698 if (clen > 0)
699 offset += (fp->_wide_data->_IO_write_ptr
700 - fp->_wide_data->_IO_write_base) * clen;
701 else
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);
709 char *outstop = out;
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,
716 in, in + delta, &in,
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))
727 free (out);
728 return WEOF;
731 offset += outstop - out;
732 free (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. */
740 if (append_mode)
741 offset += fp->_IO_write_ptr - fp->_IO_write_base;
742 /* For all other modes, _IO_read_end represents the file offset. */
743 else
744 offset += fp->_IO_write_ptr - fp->_IO_read_end;
748 if (fp->_offset != _IO_pos_BAD)
749 result = fp->_offset;
750 else
751 result = _IO_SYSSEEK (fp, 0, _IO_seek_cur);
753 if (result == EOF)
754 return result;
756 result += offset;
758 if (result < 0)
760 __set_errno (EINVAL);
761 return EOF;
764 return result;
767 _IO_off64_t
768 _IO_wfile_seekoff (fp, offset, dir, mode)
769 _IO_FILE *fp;
770 _IO_off64_t offset;
771 int dir;
772 int mode;
774 _IO_off64_t result;
775 _IO_off64_t delta, new_offset;
776 long int count;
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
780 object. */
781 if (mode == 0)
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))
803 return WEOF;
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;
813 _IO_doallocbuf (fp);
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);
822 switch (dir)
824 struct _IO_codecvt *cv;
825 int clen;
827 case _IO_seek_cur:
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. */
831 cv = fp->_codecvt;
832 clen = (*cv->__codecvt_do_encoding) (cv);
834 if (mode != 0 || !was_writing)
836 if (clen > 0)
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;
843 else
845 int nread;
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,
852 fp->_IO_read_base,
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)
861 goto dumb;
863 /* Make offset absolute, assuming current pointer is file_ptr(). */
864 offset += fp->_offset;
866 dir = _IO_seek_set;
867 break;
868 case _IO_seek_set:
869 break;
870 case _IO_seek_end:
872 struct stat64 st;
873 if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
875 offset += st.st_size;
876 dir = _IO_seek_set;
878 else
879 goto dumb;
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),
894 fp->_IO_read_end);
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))
903 goto dumb;
905 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
906 goto resync;
910 if (fp->_flags & _IO_NO_READS)
911 goto dumb;
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)
918 new_offset = offset;
919 delta = 0;
921 result = _IO_SYSSEEK (fp, new_offset, 0);
922 if (result < 0)
923 return EOF;
924 if (delta == 0)
925 count = 0;
926 else
928 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
929 (must_be_exact
930 ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
931 if (count < delta)
933 /* We weren't allowed to read, but try to seek the remainder. */
934 offset = count == EOF ? delta : delta-count;
935 dir = _IO_seek_cur;
936 goto dumb;
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))
947 goto dumb;
949 fp->_offset = result + count;
950 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
951 return offset;
952 dumb:
954 _IO_unsave_markers (fp);
955 result = _IO_SYSSEEK (fp, offset, dir);
956 if (result != EOF)
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);
967 return result;
969 resync:
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);
977 return offset;
979 libc_hidden_def (_IO_wfile_seekoff)
982 _IO_size_t
983 _IO_wfile_xsputn (f, data, n)
984 _IO_FILE *f;
985 const void *data;
986 _IO_size_t n;
988 const wchar_t *s = (const wchar_t *) data;
989 _IO_size_t to_do = n;
990 int must_flush = 0;
991 _IO_size_t count;
993 if (n <= 0)
994 return 0;
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;
1004 if (count >= n)
1006 const wchar_t *p;
1007 for (p = s + n; p > s; )
1009 if (*--p == L'\n')
1011 count = p - s + 1;
1012 must_flush = 1;
1013 break;
1018 /* Then fill the buffer. */
1019 if (count > 0)
1021 if (count > to_do)
1022 count = to_do;
1023 if (count > 20)
1025 #ifdef _LIBC
1026 f->_wide_data->_IO_write_ptr =
1027 __wmempcpy (f->_wide_data->_IO_write_ptr, s, count);
1028 #else
1029 wmemcpy (f->_wide_data->_IO_write_ptr, s, count);
1030 f->_wide_data->_IO_write_ptr += count;
1031 #endif
1032 s += count;
1034 else
1036 wchar_t *p = f->_wide_data->_IO_write_ptr;
1037 int i = (int) count;
1038 while (--i >= 0)
1039 *p++ = *s++;
1040 f->_wide_data->_IO_write_ptr = p;
1042 to_do -= count;
1044 if (to_do > 0)
1045 to_do -= _IO_wdefault_xsputn (f, s, to_do);
1046 if (must_flush
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);
1052 return n - to_do;
1054 libc_hidden_def (_IO_wfile_xsputn)
1057 const struct _IO_jump_t _IO_wfile_jumps =
1059 JUMP_INIT_DUMMY,
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 =
1085 JUMP_INIT_DUMMY,
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 =
1109 JUMP_INIT_DUMMY,
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)