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