libio: Fix variable aligment in tst-ftell-active-handler
[platform/upstream/glibc.git] / libio / wfileops.c
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>.
5
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.
10
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.
15
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/>.
19
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.  */
28
29 #include <assert.h>
30 #include <libioP.h>
31 #include <wchar.h>
32 #include <gconv.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36
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
52
53
54 /* Convert TO_DO wide character from DATA to FP.
55    Then mark FP as having empty buffers. */
56 int
57 _IO_wdo_write (_IO_FILE *fp, const wchar_t *data, _IO_size_t to_do)
58 {
59   struct _IO_codecvt *cc = fp->_codecvt;
60
61   if (to_do > 0)
62     {
63       if (fp->_IO_write_end == fp->_IO_write_ptr
64           && fp->_IO_write_end != fp->_IO_write_base)
65         {
66           if (_IO_new_do_write (fp, fp->_IO_write_base,
67                                 fp->_IO_write_ptr - fp->_IO_write_base) == EOF)
68             return WEOF;
69         }
70
71       do
72         {
73           enum __codecvt_result result;
74           const wchar_t *new_data;
75           char mb_buf[MB_LEN_MAX];
76           char *write_base, *write_ptr, *buf_end;
77
78           if (fp->_IO_write_ptr - fp->_IO_write_base < sizeof (mb_buf))
79             {
80               /* Make sure we have room for at least one multibyte
81                  character.  */
82               write_ptr = write_base = mb_buf;
83               buf_end = mb_buf + sizeof (mb_buf);
84             }
85           else
86             {
87               write_ptr = fp->_IO_write_ptr;
88               write_base = fp->_IO_write_base;
89               buf_end = fp->_IO_buf_end;
90             }
91
92           /* Now convert from the internal format into the external buffer.  */
93           result = (*cc->__codecvt_do_out) (cc, &fp->_wide_data->_IO_state,
94                                             data, data + to_do, &new_data,
95                                             write_ptr,
96                                             buf_end,
97                                             &write_ptr);
98
99           /* Write out what we produced so far.  */
100           if (_IO_new_do_write (fp, write_base, write_ptr - write_base) == EOF)
101             /* Something went wrong.  */
102             return WEOF;
103
104           to_do -= new_data - data;
105
106           /* Next see whether we had problems during the conversion.  If yes,
107              we cannot go on.  */
108           if (result != __codecvt_ok
109               && (result != __codecvt_partial || new_data - data == 0))
110             break;
111
112           data = new_data;
113         }
114       while (to_do > 0);
115     }
116
117   _IO_wsetg (fp, fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base,
118              fp->_wide_data->_IO_buf_base);
119   fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr
120     = fp->_wide_data->_IO_buf_base;
121   fp->_wide_data->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
122                                    ? fp->_wide_data->_IO_buf_base
123                                    : fp->_wide_data->_IO_buf_end);
124
125   return to_do == 0 ? 0 : WEOF;
126 }
127 libc_hidden_def (_IO_wdo_write)
128
129
130 wint_t
131 _IO_wfile_underflow (_IO_FILE *fp)
132 {
133   struct _IO_codecvt *cd;
134   enum __codecvt_result status;
135   _IO_ssize_t count;
136
137   if (__glibc_unlikely (fp->_flags & _IO_NO_READS))
138     {
139       fp->_flags |= _IO_ERR_SEEN;
140       __set_errno (EBADF);
141       return WEOF;
142     }
143   if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
144     return *fp->_wide_data->_IO_read_ptr;
145
146   cd = fp->_codecvt;
147
148   /* Maybe there is something left in the external buffer.  */
149   if (fp->_IO_read_ptr < fp->_IO_read_end)
150     {
151       /* There is more in the external.  Convert it.  */
152       const char *read_stop = (const char *) fp->_IO_read_ptr;
153
154       fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
155       fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr =
156         fp->_wide_data->_IO_buf_base;
157       status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state,
158                                        fp->_IO_read_ptr, fp->_IO_read_end,
159                                        &read_stop,
160                                        fp->_wide_data->_IO_read_ptr,
161                                        fp->_wide_data->_IO_buf_end,
162                                        &fp->_wide_data->_IO_read_end);
163
164       fp->_IO_read_base = fp->_IO_read_ptr;
165       fp->_IO_read_ptr = (char *) read_stop;
166
167       /* If we managed to generate some text return the next character.  */
168       if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
169         return *fp->_wide_data->_IO_read_ptr;
170
171       if (status == __codecvt_error)
172         {
173           __set_errno (EILSEQ);
174           fp->_flags |= _IO_ERR_SEEN;
175           return WEOF;
176         }
177
178       /* Move the remaining content of the read buffer to the beginning.  */
179       memmove (fp->_IO_buf_base, fp->_IO_read_ptr,
180                fp->_IO_read_end - fp->_IO_read_ptr);
181       fp->_IO_read_end = (fp->_IO_buf_base
182                           + (fp->_IO_read_end - fp->_IO_read_ptr));
183       fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
184     }
185   else
186     fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end =
187       fp->_IO_buf_base;
188
189   if (fp->_IO_buf_base == NULL)
190     {
191       /* Maybe we already have a push back pointer.  */
192       if (fp->_IO_save_base != NULL)
193         {
194           free (fp->_IO_save_base);
195           fp->_flags &= ~_IO_IN_BACKUP;
196         }
197       _IO_doallocbuf (fp);
198
199       fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end =
200         fp->_IO_buf_base;
201     }
202
203   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end =
204     fp->_IO_buf_base;
205
206   if (fp->_wide_data->_IO_buf_base == NULL)
207     {
208       /* Maybe we already have a push back pointer.  */
209       if (fp->_wide_data->_IO_save_base != NULL)
210         {
211           free (fp->_wide_data->_IO_save_base);
212           fp->_flags &= ~_IO_IN_BACKUP;
213         }
214       _IO_wdoallocbuf (fp);
215     }
216
217   /* Flush all line buffered files before reading. */
218   /* FIXME This can/should be moved to genops ?? */
219   if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
220     {
221 #if 0
222       _IO_flush_all_linebuffered ();
223 #else
224       /* We used to flush all line-buffered stream.  This really isn't
225          required by any standard.  My recollection is that
226          traditional Unix systems did this for stdout.  stderr better
227          not be line buffered.  So we do just that here
228          explicitly.  --drepper */
229       _IO_acquire_lock (_IO_stdout);
230
231       if ((_IO_stdout->_flags & (_IO_LINKED | _IO_NO_WRITES | _IO_LINE_BUF))
232           == (_IO_LINKED | _IO_LINE_BUF))
233         _IO_OVERFLOW (_IO_stdout, EOF);
234
235       _IO_release_lock (_IO_stdout);
236 #endif
237     }
238
239   _IO_switch_to_get_mode (fp);
240
241   fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr =
242     fp->_wide_data->_IO_buf_base;
243   fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_buf_base;
244   fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr =
245     fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_base;
246
247   const char *read_ptr_copy;
248   char accbuf[MB_LEN_MAX];
249   size_t naccbuf = 0;
250  again:
251   count = _IO_SYSREAD (fp, fp->_IO_read_end,
252                        fp->_IO_buf_end - fp->_IO_read_end);
253   if (count <= 0)
254     {
255       if (count == 0 && naccbuf == 0)
256         {
257           fp->_flags |= _IO_EOF_SEEN;
258           fp->_offset = _IO_pos_BAD;
259         }
260       else
261         fp->_flags |= _IO_ERR_SEEN, count = 0;
262     }
263   fp->_IO_read_end += count;
264   if (count == 0)
265     {
266       if (naccbuf != 0)
267         /* There are some bytes in the external buffer but they don't
268            convert to anything.  */
269         __set_errno (EILSEQ);
270       return WEOF;
271     }
272   if (fp->_offset != _IO_pos_BAD)
273     _IO_pos_adjust (fp->_offset, count);
274
275   /* Now convert the read input.  */
276   fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
277   fp->_IO_read_base = fp->_IO_read_ptr;
278   const char *from = fp->_IO_read_ptr;
279   const char *to = fp->_IO_read_end;
280   size_t to_copy = count;
281   if (__glibc_unlikely (naccbuf != 0))
282     {
283       to_copy = MIN (sizeof (accbuf) - naccbuf, count);
284       to = __mempcpy (&accbuf[naccbuf], from, to_copy);
285       naccbuf += to_copy;
286       from = accbuf;
287     }
288   status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state,
289                                    from, to, &read_ptr_copy,
290                                    fp->_wide_data->_IO_read_end,
291                                    fp->_wide_data->_IO_buf_end,
292                                    &fp->_wide_data->_IO_read_end);
293
294   if (__glibc_unlikely (naccbuf != 0))
295     fp->_IO_read_ptr += MAX (0, read_ptr_copy - &accbuf[naccbuf - to_copy]);
296   else
297     fp->_IO_read_ptr = (char *) read_ptr_copy;
298   if (fp->_wide_data->_IO_read_end == fp->_wide_data->_IO_buf_base)
299     {
300       if (status == __codecvt_error)
301         {
302         out_eilseq:
303           __set_errno (EILSEQ);
304           fp->_flags |= _IO_ERR_SEEN;
305           return WEOF;
306         }
307
308       /* The read bytes make no complete character.  Try reading again.  */
309       assert (status == __codecvt_partial);
310
311       if (naccbuf == 0)
312         {
313           if (fp->_IO_read_base < fp->_IO_read_ptr)
314             {
315               /* Partially used the buffer for some input data that
316                  produces no output.  */
317               size_t avail = fp->_IO_read_end - fp->_IO_read_ptr;
318               memmove (fp->_IO_read_base, fp->_IO_read_ptr, avail);
319               fp->_IO_read_ptr = fp->_IO_read_base;
320               fp->_IO_read_end -= avail;
321               goto again;
322             }
323           naccbuf = fp->_IO_read_end - fp->_IO_read_ptr;
324           if (naccbuf >= sizeof (accbuf))
325             goto out_eilseq;
326
327           memcpy (accbuf, fp->_IO_read_ptr, naccbuf);
328         }
329       else
330         {
331           size_t used = read_ptr_copy - accbuf;
332           if (used > 0)
333             {
334               memmove (accbuf, read_ptr_copy, naccbuf - used);
335               naccbuf -= used;
336             }
337
338           if (naccbuf == sizeof (accbuf))
339             goto out_eilseq;
340         }
341
342       fp->_IO_read_ptr = fp->_IO_read_end = fp->_IO_read_base;
343
344       goto again;
345     }
346
347   return *fp->_wide_data->_IO_read_ptr;
348 }
349 libc_hidden_def (_IO_wfile_underflow)
350
351
352 static wint_t
353 _IO_wfile_underflow_mmap (_IO_FILE *fp)
354 {
355   struct _IO_codecvt *cd;
356   const char *read_stop;
357
358   if (__glibc_unlikely (fp->_flags & _IO_NO_READS))
359     {
360       fp->_flags |= _IO_ERR_SEEN;
361       __set_errno (EBADF);
362       return WEOF;
363     }
364   if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
365     return *fp->_wide_data->_IO_read_ptr;
366
367   cd = fp->_codecvt;
368
369   /* Maybe there is something left in the external buffer.  */
370   if (fp->_IO_read_ptr >= fp->_IO_read_end
371       /* No.  But maybe the read buffer is not fully set up.  */
372       && _IO_file_underflow_mmap (fp) == EOF)
373     /* Nothing available.  _IO_file_underflow_mmap has set the EOF or error
374        flags as appropriate.  */
375     return WEOF;
376
377   /* There is more in the external.  Convert it.  */
378   read_stop = (const char *) fp->_IO_read_ptr;
379
380   if (fp->_wide_data->_IO_buf_base == NULL)
381     {
382       /* Maybe we already have a push back pointer.  */
383       if (fp->_wide_data->_IO_save_base != NULL)
384         {
385           free (fp->_wide_data->_IO_save_base);
386           fp->_flags &= ~_IO_IN_BACKUP;
387         }
388       _IO_wdoallocbuf (fp);
389     }
390
391   fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
392   fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr =
393     fp->_wide_data->_IO_buf_base;
394   (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state,
395                           fp->_IO_read_ptr, fp->_IO_read_end,
396                           &read_stop,
397                           fp->_wide_data->_IO_read_ptr,
398                           fp->_wide_data->_IO_buf_end,
399                           &fp->_wide_data->_IO_read_end);
400
401   fp->_IO_read_ptr = (char *) read_stop;
402
403   /* If we managed to generate some text return the next character.  */
404   if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
405     return *fp->_wide_data->_IO_read_ptr;
406
407   /* There is some garbage at the end of the file.  */
408   __set_errno (EILSEQ);
409   fp->_flags |= _IO_ERR_SEEN;
410   return WEOF;
411 }
412
413 static wint_t
414 _IO_wfile_underflow_maybe_mmap (_IO_FILE *fp)
415 {
416   /* This is the first read attempt.  Doing the underflow will choose mmap
417      or vanilla operations and then punt to the chosen underflow routine.
418      Then we can punt to ours.  */
419   if (_IO_file_underflow_maybe_mmap (fp) == EOF)
420     return WEOF;
421
422   return _IO_WUNDERFLOW (fp);
423 }
424
425
426 wint_t
427 _IO_wfile_overflow (_IO_FILE *f, wint_t wch)
428 {
429   if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
430     {
431       f->_flags |= _IO_ERR_SEEN;
432       __set_errno (EBADF);
433       return WEOF;
434     }
435   /* If currently reading or no buffer allocated. */
436   if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
437     {
438       /* Allocate a buffer if needed. */
439       if (f->_wide_data->_IO_write_base == 0)
440         {
441           _IO_wdoallocbuf (f);
442           _IO_wsetg (f, f->_wide_data->_IO_buf_base,
443                      f->_wide_data->_IO_buf_base, f->_wide_data->_IO_buf_base);
444
445           if (f->_IO_write_base == NULL)
446             {
447               _IO_doallocbuf (f);
448               _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
449             }
450         }
451       else
452         {
453           /* Otherwise must be currently reading.  If _IO_read_ptr
454              (and hence also _IO_read_end) is at the buffer end,
455              logically slide the buffer forwards one block (by setting
456              the read pointers to all point at the beginning of the
457              block).  This makes room for subsequent output.
458              Otherwise, set the read pointers to _IO_read_end (leaving
459              that alone, so it can continue to correspond to the
460              external position). */
461           if (f->_wide_data->_IO_read_ptr == f->_wide_data->_IO_buf_end)
462             {
463               f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
464               f->_wide_data->_IO_read_end = f->_wide_data->_IO_read_ptr =
465                 f->_wide_data->_IO_buf_base;
466             }
467         }
468       f->_wide_data->_IO_write_ptr = f->_wide_data->_IO_read_ptr;
469       f->_wide_data->_IO_write_base = f->_wide_data->_IO_write_ptr;
470       f->_wide_data->_IO_write_end = f->_wide_data->_IO_buf_end;
471       f->_wide_data->_IO_read_base = f->_wide_data->_IO_read_ptr =
472         f->_wide_data->_IO_read_end;
473
474       f->_IO_write_ptr = f->_IO_read_ptr;
475       f->_IO_write_base = f->_IO_write_ptr;
476       f->_IO_write_end = f->_IO_buf_end;
477       f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
478
479       f->_flags |= _IO_CURRENTLY_PUTTING;
480       if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
481         f->_wide_data->_IO_write_end = f->_wide_data->_IO_write_ptr;
482     }
483   if (wch == WEOF)
484     return _IO_do_flush (f);
485   if (f->_wide_data->_IO_write_ptr == f->_wide_data->_IO_buf_end)
486     /* Buffer is really full */
487     if (_IO_do_flush (f) == EOF)
488       return WEOF;
489   *f->_wide_data->_IO_write_ptr++ = wch;
490   if ((f->_flags & _IO_UNBUFFERED)
491       || ((f->_flags & _IO_LINE_BUF) && wch == L'\n'))
492     if (_IO_do_flush (f) == EOF)
493       return WEOF;
494   return wch;
495 }
496 libc_hidden_def (_IO_wfile_overflow)
497
498 wint_t
499 _IO_wfile_sync (_IO_FILE *fp)
500 {
501   _IO_ssize_t delta;
502   wint_t retval = 0;
503
504   /*    char* ptr = cur_ptr(); */
505   if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)
506     if (_IO_do_flush (fp))
507       return WEOF;
508   delta = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end;
509   if (delta != 0)
510     {
511       /* We have to find out how many bytes we have to go back in the
512          external buffer.  */
513       struct _IO_codecvt *cv = fp->_codecvt;
514       _IO_off64_t new_pos;
515
516       int clen = (*cv->__codecvt_do_encoding) (cv);
517
518       if (clen > 0)
519         /* It is easy, a fixed number of input bytes are used for each
520            wide character.  */
521         delta *= clen;
522       else
523         {
524           /* We have to find out the hard way how much to back off.
525              To do this we determine how much input we needed to
526              generate the wide characters up to the current reading
527              position.  */
528           int nread;
529
530           fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
531           nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state,
532                                               fp->_IO_read_base,
533                                               fp->_IO_read_end, delta);
534           fp->_IO_read_ptr = fp->_IO_read_base + nread;
535           delta = -(fp->_IO_read_end - fp->_IO_read_base - nread);
536         }
537
538       new_pos = _IO_SYSSEEK (fp, delta, 1);
539       if (new_pos != (_IO_off64_t) EOF)
540         {
541           fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr;
542           fp->_IO_read_end = fp->_IO_read_ptr;
543         }
544 #ifdef ESPIPE
545       else if (errno == ESPIPE)
546         ; /* Ignore error from unseekable devices. */
547 #endif
548       else
549         retval = WEOF;
550     }
551   if (retval != WEOF)
552     fp->_offset = _IO_pos_BAD;
553   /* FIXME: Cleanup - can this be shared? */
554   /*    setg(base(), ptr, ptr); */
555   return retval;
556 }
557 libc_hidden_def (_IO_wfile_sync)
558
559 /* Adjust the internal buffer pointers to reflect the state in the external
560    buffer.  The content between fp->_IO_read_base and fp->_IO_read_ptr is
561    assumed to be converted and available in the range
562    fp->_wide_data->_IO_read_base and fp->_wide_data->_IO_read_end.
563
564    Returns 0 on success and -1 on error with the _IO_ERR_SEEN flag set.  */
565 static int
566 adjust_wide_data (_IO_FILE *fp, bool do_convert)
567 {
568   struct _IO_codecvt *cv = fp->_codecvt;
569
570   int clen = (*cv->__codecvt_do_encoding) (cv);
571
572   /* Take the easy way out for constant length encodings if we don't need to
573      convert.  */
574   if (!do_convert && clen > 0)
575     {
576       fp->_wide_data->_IO_read_end += ((fp->_IO_read_ptr - fp->_IO_read_base)
577                                        / clen);
578       goto done;
579     }
580
581   enum __codecvt_result status;
582   const char *read_stop = (const char *) fp->_IO_read_base;
583   do
584     {
585
586       fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
587       status = (*cv->__codecvt_do_in) (cv, &fp->_wide_data->_IO_state,
588                                        fp->_IO_read_base, fp->_IO_read_ptr,
589                                        &read_stop,
590                                        fp->_wide_data->_IO_read_base,
591                                        fp->_wide_data->_IO_buf_end,
592                                        &fp->_wide_data->_IO_read_end);
593
594       /* Should we return EILSEQ?  */
595       if (__glibc_unlikely (status == __codecvt_error))
596         {
597           fp->_flags |= _IO_ERR_SEEN;
598           return -1;
599         }
600     }
601   while (__builtin_expect (status == __codecvt_partial, 0));
602
603 done:
604   /* Now seek to _IO_read_end to behave as if we have read it all in.  */
605   fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
606
607   return 0;
608 }
609
610 /* ftell{,o} implementation for wide mode.  Don't modify any state of the file
611    pointer while we try to get the current state of the stream except in one
612    case, which is when we have unflushed writes in append mode.  */
613 static _IO_off64_t
614 do_ftell_wide (_IO_FILE *fp)
615 {
616   _IO_off64_t result, offset = 0;
617
618   /* No point looking for offsets in the buffer if it hasn't even been
619      allocated.  */
620   if (fp->_wide_data->_IO_buf_base != NULL)
621     {
622       const wchar_t *wide_read_base;
623       const wchar_t *wide_read_ptr;
624       const wchar_t *wide_read_end;
625       bool unflushed_writes = (fp->_wide_data->_IO_write_ptr
626                                > fp->_wide_data->_IO_write_base);
627
628       bool append_mode = (fp->_flags & _IO_IS_APPENDING) == _IO_IS_APPENDING;
629
630       /* When we have unflushed writes in append mode, seek to the end of the
631          file and record that offset.  This is the only time we change the file
632          stream state and it is safe since the file handle is active.  */
633       if (unflushed_writes && append_mode)
634         {
635           result = _IO_SYSSEEK (fp, 0, _IO_seek_end);
636           if (result == _IO_pos_BAD)
637             return EOF;
638           else
639             fp->_offset = result;
640         }
641
642       /* XXX For wide stream with backup store it is not very
643          reasonable to determine the offset.  The pushed-back
644          character might require a state change and we need not be
645          able to compute the initial state by reverse transformation
646          since there is no guarantee of symmetry.  So we don't even
647          try and return an error.  */
648       if (_IO_in_backup (fp))
649         {
650           if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
651             {
652               __set_errno (EINVAL);
653               return -1;
654             }
655
656           /* Nothing in the backup store, so note the backed up pointers
657              without changing the state.  */
658           wide_read_base = fp->_wide_data->_IO_save_base;
659           wide_read_ptr = wide_read_base;
660           wide_read_end = fp->_wide_data->_IO_save_end;
661         }
662       else
663         {
664           wide_read_base = fp->_wide_data->_IO_read_base;
665           wide_read_ptr = fp->_wide_data->_IO_read_ptr;
666           wide_read_end = fp->_wide_data->_IO_read_end;
667         }
668
669       struct _IO_codecvt *cv = fp->_codecvt;
670       int clen = (*cv->__codecvt_do_encoding) (cv);
671
672       if (!unflushed_writes)
673         {
674           if (clen > 0)
675             {
676               offset -= (wide_read_end - wide_read_ptr) * clen;
677               offset -= fp->_IO_read_end - fp->_IO_read_ptr;
678             }
679           else
680             {
681               int nread;
682
683               size_t delta = wide_read_ptr - wide_read_base;
684               __mbstate_t state = fp->_wide_data->_IO_last_state;
685               nread = (*cv->__codecvt_do_length) (cv, &state,
686                                                   fp->_IO_read_base,
687                                                   fp->_IO_read_end, delta);
688               offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
689             }
690         }
691       else
692         {
693           if (clen > 0)
694             offset += (fp->_wide_data->_IO_write_ptr
695                        - fp->_wide_data->_IO_write_base) * clen;
696           else
697             {
698               size_t delta = (fp->_wide_data->_IO_write_ptr
699                               - fp->_wide_data->_IO_write_base);
700
701               /* Allocate enough space for the conversion.  */
702               size_t outsize = delta * sizeof (wchar_t);
703               char *out = malloc (outsize);
704               char *outstop = out;
705               const wchar_t *in = fp->_wide_data->_IO_write_base;
706
707               enum __codecvt_result status;
708
709               __mbstate_t state = fp->_wide_data->_IO_last_state;
710               status = (*cv->__codecvt_do_out) (cv, &state,
711                                                 in, in + delta, &in,
712                                                 out, out + outsize, &outstop);
713
714               /* We don't check for __codecvt_partial because it can be
715                  returned on one of two conditions: either the output
716                  buffer is full or the input sequence is incomplete.  We
717                  take care to allocate enough buffer and our input
718                  sequences must be complete since they are accepted as
719                  wchar_t; if not, then that is an error.  */
720               if (__glibc_unlikely (status != __codecvt_ok))
721                 {
722                   free (out);
723                   return WEOF;
724                 }
725
726               offset += outstop - out;
727               free (out);
728             }
729
730           /* We don't trust _IO_read_end to represent the current file offset
731              when writing in append mode because the value would have to be
732              shifted to the end of the file during a flush.  Use the write base
733              instead, along with the new offset we got above when we did a seek
734              to the end of the file.  */
735           if (append_mode)
736             offset += fp->_IO_write_ptr - fp->_IO_write_base;
737           /* For all other modes, _IO_read_end represents the file offset.  */
738           else
739             offset += fp->_IO_write_ptr - fp->_IO_read_end;
740         }
741     }
742
743   if (fp->_offset != _IO_pos_BAD)
744     result = fp->_offset;
745   else
746     result = _IO_SYSSEEK (fp, 0, _IO_seek_cur);
747
748   if (result == EOF)
749     return result;
750
751   result += offset;
752
753   if (result < 0)
754     {
755       __set_errno (EINVAL);
756       return EOF;
757     }
758
759   return result;
760 }
761
762 _IO_off64_t
763 _IO_wfile_seekoff (_IO_FILE *fp, _IO_off64_t offset, int dir, int mode)
764 {
765   _IO_off64_t result;
766   _IO_off64_t delta, new_offset;
767   long int count;
768
769   /* Short-circuit into a separate function.  We don't want to mix any
770      functionality and we don't want to touch anything inside the FILE
771      object. */
772   if (mode == 0)
773     return do_ftell_wide (fp);
774
775   /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
776      offset of the underlying file must be exact.  */
777   int must_be_exact = ((fp->_wide_data->_IO_read_base
778                         == fp->_wide_data->_IO_read_end)
779                        && (fp->_wide_data->_IO_write_base
780                            == fp->_wide_data->_IO_write_ptr));
781
782   bool was_writing = ((fp->_wide_data->_IO_write_ptr
783                        > fp->_wide_data->_IO_write_base)
784                       || _IO_in_put_mode (fp));
785
786   /* Flush unwritten characters.
787      (This may do an unneeded write if we seek within the buffer.
788      But to be able to switch to reading, we would need to set
789      egptr to pptr.  That can't be done in the current design,
790      which assumes file_ptr() is eGptr.  Anyway, since we probably
791      end up flushing when we close(), it doesn't make much difference.)
792      FIXME: simulate mem-mapped files. */
793   if (was_writing && _IO_switch_to_wget_mode (fp))
794     return WEOF;
795
796   if (fp->_wide_data->_IO_buf_base == NULL)
797     {
798       /* It could be that we already have a pushback buffer.  */
799       if (fp->_wide_data->_IO_read_base != NULL)
800         {
801           free (fp->_wide_data->_IO_read_base);
802           fp->_flags &= ~_IO_IN_BACKUP;
803         }
804       _IO_doallocbuf (fp);
805       _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
806       _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
807       _IO_wsetp (fp, fp->_wide_data->_IO_buf_base,
808                  fp->_wide_data->_IO_buf_base);
809       _IO_wsetg (fp, fp->_wide_data->_IO_buf_base,
810                  fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base);
811     }
812
813   switch (dir)
814     {
815       struct _IO_codecvt *cv;
816       int clen;
817
818     case _IO_seek_cur:
819       /* Adjust for read-ahead (bytes is buffer).  To do this we must
820          find out which position in the external buffer corresponds to
821          the current position in the internal buffer.  */
822       cv = fp->_codecvt;
823       clen = (*cv->__codecvt_do_encoding) (cv);
824
825       if (mode != 0 || !was_writing)
826         {
827           if (clen > 0)
828             {
829               offset -= (fp->_wide_data->_IO_read_end
830                          - fp->_wide_data->_IO_read_ptr) * clen;
831               /* Adjust by readahead in external buffer.  */
832               offset -= fp->_IO_read_end - fp->_IO_read_ptr;
833             }
834           else
835             {
836               int nread;
837
838               delta = (fp->_wide_data->_IO_read_ptr
839                        - fp->_wide_data->_IO_read_base);
840               fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
841               nread = (*cv->__codecvt_do_length) (cv,
842                                                   &fp->_wide_data->_IO_state,
843                                                   fp->_IO_read_base,
844                                                   fp->_IO_read_end, delta);
845               fp->_IO_read_ptr = fp->_IO_read_base + nread;
846               fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr;
847               offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
848             }
849         }
850
851       if (fp->_offset == _IO_pos_BAD)
852         goto dumb;
853
854       /* Make offset absolute, assuming current pointer is file_ptr(). */
855       offset += fp->_offset;
856
857       dir = _IO_seek_set;
858       break;
859     case _IO_seek_set:
860       break;
861     case _IO_seek_end:
862       {
863         struct stat64 st;
864         if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
865           {
866             offset += st.st_size;
867             dir = _IO_seek_set;
868           }
869         else
870           goto dumb;
871       }
872     }
873   /* At this point, dir==_IO_seek_set. */
874
875   /* If destination is within current buffer, optimize: */
876   if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
877       && !_IO_in_backup (fp))
878     {
879       _IO_off64_t start_offset = (fp->_offset
880                                   - (fp->_IO_read_end - fp->_IO_buf_base));
881       if (offset >= start_offset && offset < fp->_offset)
882         {
883           _IO_setg (fp, fp->_IO_buf_base,
884                     fp->_IO_buf_base + (offset - start_offset),
885                     fp->_IO_read_end);
886           _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
887           _IO_wsetg (fp, fp->_wide_data->_IO_buf_base,
888                      fp->_wide_data->_IO_buf_base,
889                      fp->_wide_data->_IO_buf_base);
890           _IO_wsetp (fp, fp->_wide_data->_IO_buf_base,
891                      fp->_wide_data->_IO_buf_base);
892
893           if (adjust_wide_data (fp, false))
894             goto dumb;
895
896           _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
897           goto resync;
898         }
899     }
900
901   if (fp->_flags & _IO_NO_READS)
902     goto dumb;
903
904   /* Try to seek to a block boundary, to improve kernel page management. */
905   new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
906   delta = offset - new_offset;
907   if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
908     {
909       new_offset = offset;
910       delta = 0;
911     }
912   result = _IO_SYSSEEK (fp, new_offset, 0);
913   if (result < 0)
914     return EOF;
915   if (delta == 0)
916     count = 0;
917   else
918     {
919       count = _IO_SYSREAD (fp, fp->_IO_buf_base,
920                            (must_be_exact
921                             ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
922       if (count < delta)
923         {
924           /* We weren't allowed to read, but try to seek the remainder. */
925           offset = count == EOF ? delta : delta-count;
926           dir = _IO_seek_cur;
927           goto dumb;
928         }
929     }
930   _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
931             fp->_IO_buf_base + count);
932   _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
933   _IO_wsetg (fp, fp->_wide_data->_IO_buf_base,
934              fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base);
935   _IO_wsetp (fp, fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base);
936
937   if (adjust_wide_data (fp, true))
938     goto dumb;
939
940   fp->_offset = result + count;
941   _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
942   return offset;
943  dumb:
944
945   _IO_unsave_markers (fp);
946   result = _IO_SYSSEEK (fp, offset, dir);
947   if (result != EOF)
948     {
949       _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
950       fp->_offset = result;
951       _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
952       _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
953       _IO_wsetg (fp, fp->_wide_data->_IO_buf_base,
954                  fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base);
955       _IO_wsetp (fp, fp->_wide_data->_IO_buf_base,
956                  fp->_wide_data->_IO_buf_base);
957     }
958   return result;
959
960 resync:
961   /* We need to do it since it is possible that the file offset in
962      the kernel may be changed behind our back. It may happen when
963      we fopen a file and then do a fork. One process may access the
964      file and the kernel file offset will be changed. */
965   if (fp->_offset >= 0)
966     _IO_SYSSEEK (fp, fp->_offset, 0);
967
968   return offset;
969 }
970 libc_hidden_def (_IO_wfile_seekoff)
971
972
973 _IO_size_t
974 _IO_wfile_xsputn (_IO_FILE *f, const void *data, _IO_size_t n)
975 {
976   const wchar_t *s = (const wchar_t *) data;
977   _IO_size_t to_do = n;
978   int must_flush = 0;
979   _IO_size_t count;
980
981   if (n <= 0)
982     return 0;
983   /* This is an optimized implementation.
984      If the amount to be written straddles a block boundary
985      (or the filebuf is unbuffered), use sys_write directly. */
986
987   /* First figure out how much space is available in the buffer. */
988   count = f->_wide_data->_IO_write_end - f->_wide_data->_IO_write_ptr;
989   if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
990     {
991       count = f->_wide_data->_IO_buf_end - f->_wide_data->_IO_write_ptr;
992       if (count >= n)
993         {
994           const wchar_t *p;
995           for (p = s + n; p > s; )
996             {
997               if (*--p == L'\n')
998                 {
999                   count = p - s + 1;
1000                   must_flush = 1;
1001                   break;
1002                 }
1003             }
1004         }
1005     }
1006   /* Then fill the buffer. */
1007   if (count > 0)
1008     {
1009       if (count > to_do)
1010         count = to_do;
1011       if (count > 20)
1012         {
1013 #ifdef _LIBC
1014           f->_wide_data->_IO_write_ptr =
1015             __wmempcpy (f->_wide_data->_IO_write_ptr, s, count);
1016 #else
1017           wmemcpy (f->_wide_data->_IO_write_ptr, s, count);
1018           f->_wide_data->_IO_write_ptr += count;
1019 #endif
1020           s += count;
1021         }
1022       else
1023         {
1024           wchar_t *p = f->_wide_data->_IO_write_ptr;
1025           int i = (int) count;
1026           while (--i >= 0)
1027             *p++ = *s++;
1028           f->_wide_data->_IO_write_ptr = p;
1029         }
1030       to_do -= count;
1031     }
1032   if (to_do > 0)
1033     to_do -= _IO_wdefault_xsputn (f, s, to_do);
1034   if (must_flush
1035       && f->_wide_data->_IO_write_ptr != f->_wide_data->_IO_write_base)
1036     _IO_wdo_write (f, f->_wide_data->_IO_write_base,
1037                    f->_wide_data->_IO_write_ptr
1038                    - f->_wide_data->_IO_write_base);
1039
1040   return n - to_do;
1041 }
1042 libc_hidden_def (_IO_wfile_xsputn)
1043
1044
1045 const struct _IO_jump_t _IO_wfile_jumps =
1046 {
1047   JUMP_INIT_DUMMY,
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),
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_new_file_setbuf),
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),
1064   JUMP_INIT(stat, _IO_file_stat),
1065   JUMP_INIT(showmanyc, _IO_default_showmanyc),
1066   JUMP_INIT(imbue, _IO_default_imbue)
1067 };
1068 libc_hidden_data_def (_IO_wfile_jumps)
1069
1070
1071 const struct _IO_jump_t _IO_wfile_jumps_mmap =
1072 {
1073   JUMP_INIT_DUMMY,
1074   JUMP_INIT(finish, _IO_new_file_finish),
1075   JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
1076   JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow_mmap),
1077   JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
1078   JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
1079   JUMP_INIT(xsputn, _IO_wfile_xsputn),
1080   JUMP_INIT(xsgetn, _IO_file_xsgetn),
1081   JUMP_INIT(seekoff, _IO_wfile_seekoff),
1082   JUMP_INIT(seekpos, _IO_default_seekpos),
1083   JUMP_INIT(setbuf, _IO_file_setbuf_mmap),
1084   JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
1085   JUMP_INIT(doallocate, _IO_wfile_doallocate),
1086   JUMP_INIT(read, _IO_file_read),
1087   JUMP_INIT(write, _IO_new_file_write),
1088   JUMP_INIT(seek, _IO_file_seek),
1089   JUMP_INIT(close, _IO_file_close_mmap),
1090   JUMP_INIT(stat, _IO_file_stat),
1091   JUMP_INIT(showmanyc, _IO_default_showmanyc),
1092   JUMP_INIT(imbue, _IO_default_imbue)
1093 };
1094
1095 const struct _IO_jump_t _IO_wfile_jumps_maybe_mmap =
1096 {
1097   JUMP_INIT_DUMMY,
1098   JUMP_INIT(finish, _IO_new_file_finish),
1099   JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
1100   JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow_maybe_mmap),
1101   JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
1102   JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
1103   JUMP_INIT(xsputn, _IO_wfile_xsputn),
1104   JUMP_INIT(xsgetn, _IO_file_xsgetn),
1105   JUMP_INIT(seekoff, _IO_wfile_seekoff),
1106   JUMP_INIT(seekpos, _IO_default_seekpos),
1107   JUMP_INIT(setbuf, _IO_file_setbuf_mmap),
1108   JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
1109   JUMP_INIT(doallocate, _IO_wfile_doallocate),
1110   JUMP_INIT(read, _IO_file_read),
1111   JUMP_INIT(write, _IO_new_file_write),
1112   JUMP_INIT(seek, _IO_file_seek),
1113   JUMP_INIT(close, _IO_file_close),
1114   JUMP_INIT(stat, _IO_file_stat),
1115   JUMP_INIT(showmanyc, _IO_default_showmanyc),
1116   JUMP_INIT(imbue, _IO_default_imbue)
1117 };