]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/wfileops.c
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / libio / wfileops.c
CommitLineData
04277e02 1/* Copyright (C) 1993-2019 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 17 License along with the GNU C Library; if not, see
5a82c748 18 <https://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
9964a145 39_IO_wdo_write (FILE *fp, const wchar_t *data, 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. */
09e1b0e3
FW
75 result = __libio_codecvt_out (cc, &fp->_wide_data->_IO_state,
76 data, data + to_do, &new_data,
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
9964a145 113_IO_wfile_underflow (FILE *fp)
d64b6ad0
UD
114{
115 struct _IO_codecvt *cd;
116 enum __codecvt_result status;
9964a145 117 ssize_t count;
d64b6ad0 118
2cc7bad0
ZW
119 /* C99 requires EOF to be "sticky". */
120 if (fp->_flags & _IO_EOF_SEEN)
121 return WEOF;
122
a1ffb40e 123 if (__glibc_unlikely (fp->_flags & _IO_NO_READS))
d64b6ad0 124 {
58034572 125 fp->_flags |= _IO_ERR_SEEN;
d64b6ad0
UD
126 __set_errno (EBADF);
127 return WEOF;
128 }
129 if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
130 return *fp->_wide_data->_IO_read_ptr;
131
cd8b7ff9 132 cd = fp->_codecvt;
d64b6ad0
UD
133
134 /* Maybe there is something left in the external buffer. */
135 if (fp->_IO_read_ptr < fp->_IO_read_end)
136 {
5e473a71
UD
137 /* There is more in the external. Convert it. */
138 const char *read_stop = (const char *) fp->_IO_read_ptr;
d64b6ad0 139
5e473a71 140 fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
0469311e
UD
141 fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr =
142 fp->_wide_data->_IO_buf_base;
09e1b0e3
FW
143 status = __libio_codecvt_in (cd, &fp->_wide_data->_IO_state,
144 fp->_IO_read_ptr, fp->_IO_read_end,
145 &read_stop,
146 fp->_wide_data->_IO_read_ptr,
147 fp->_wide_data->_IO_buf_end,
148 &fp->_wide_data->_IO_read_end);
5e473a71 149
eb35b097 150 fp->_IO_read_base = fp->_IO_read_ptr;
5e473a71
UD
151 fp->_IO_read_ptr = (char *) read_stop;
152
153 /* If we managed to generate some text return the next character. */
154 if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
155 return *fp->_wide_data->_IO_read_ptr;
156
157 if (status == __codecvt_error)
d64b6ad0 158 {
5e473a71
UD
159 __set_errno (EILSEQ);
160 fp->_flags |= _IO_ERR_SEEN;
161 return WEOF;
d64b6ad0
UD
162 }
163
164 /* Move the remaining content of the read buffer to the beginning. */
165 memmove (fp->_IO_buf_base, fp->_IO_read_ptr,
166 fp->_IO_read_end - fp->_IO_read_ptr);
167 fp->_IO_read_end = (fp->_IO_buf_base
168 + (fp->_IO_read_end - fp->_IO_read_ptr));
169 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
170 }
171 else
172 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end =
173 fp->_IO_buf_base;
174
d64b6ad0
UD
175 if (fp->_IO_buf_base == NULL)
176 {
177 /* Maybe we already have a push back pointer. */
178 if (fp->_IO_save_base != NULL)
179 {
180 free (fp->_IO_save_base);
181 fp->_flags &= ~_IO_IN_BACKUP;
182 }
d18ea0c5 183 _IO_doallocbuf (fp);
a756bab8
UD
184
185 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end =
186 fp->_IO_buf_base;
d64b6ad0
UD
187 }
188
a756bab8
UD
189 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end =
190 fp->_IO_buf_base;
191
d64b6ad0
UD
192 if (fp->_wide_data->_IO_buf_base == NULL)
193 {
194 /* Maybe we already have a push back pointer. */
195 if (fp->_wide_data->_IO_save_base != NULL)
196 {
197 free (fp->_wide_data->_IO_save_base);
198 fp->_flags &= ~_IO_IN_BACKUP;
199 }
d18ea0c5 200 _IO_wdoallocbuf (fp);
d64b6ad0
UD
201 }
202
d64b6ad0 203 /* FIXME This can/should be moved to genops ?? */
2e425022 204 if (fp->_flags & (_IO_LINE_BUF | _IO_UNBUFFERED))
3d759cb8 205 {
3d759cb8
UD
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 */
5f10701f 211 _IO_acquire_lock (stdout);
3d759cb8 212
5f10701f 213 if ((stdout->_flags & (_IO_LINKED | _IO_NO_WRITES | _IO_LINE_BUF))
3d759cb8 214 == (_IO_LINKED | _IO_LINE_BUF))
5f10701f 215 _IO_OVERFLOW (stdout, EOF);
3d759cb8 216
5f10701f 217 _IO_release_lock (stdout);
3d759cb8 218 }
d64b6ad0 219
d18ea0c5 220 _IO_switch_to_get_mode (fp);
d64b6ad0 221
d64b6ad0
UD
222 fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr =
223 fp->_wide_data->_IO_buf_base;
224 fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_buf_base;
225 fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr =
226 fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_base;
227
82f2e9c6
UD
228 const char *read_ptr_copy;
229 char accbuf[MB_LEN_MAX];
230 size_t naccbuf = 0;
d64b6ad0
UD
231 again:
232 count = _IO_SYSREAD (fp, fp->_IO_read_end,
233 fp->_IO_buf_end - fp->_IO_read_end);
234 if (count <= 0)
235 {
82f2e9c6 236 if (count == 0 && naccbuf == 0)
fe8b4d98
SP
237 {
238 fp->_flags |= _IO_EOF_SEEN;
239 fp->_offset = _IO_pos_BAD;
240 }
d64b6ad0
UD
241 else
242 fp->_flags |= _IO_ERR_SEEN, count = 0;
243 }
244 fp->_IO_read_end += count;
245 if (count == 0)
246 {
82f2e9c6 247 if (naccbuf != 0)
d64b6ad0 248 /* There are some bytes in the external buffer but they don't
aaddc98c 249 convert to anything. */
d64b6ad0
UD
250 __set_errno (EILSEQ);
251 return WEOF;
252 }
253 if (fp->_offset != _IO_pos_BAD)
254 _IO_pos_adjust (fp->_offset, count);
255
256 /* Now convert the read input. */
257 fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
258 fp->_IO_read_base = fp->_IO_read_ptr;
82f2e9c6
UD
259 const char *from = fp->_IO_read_ptr;
260 const char *to = fp->_IO_read_end;
261 size_t to_copy = count;
a1ffb40e 262 if (__glibc_unlikely (naccbuf != 0))
82f2e9c6
UD
263 {
264 to_copy = MIN (sizeof (accbuf) - naccbuf, count);
265 to = __mempcpy (&accbuf[naccbuf], from, to_copy);
266 naccbuf += to_copy;
267 from = accbuf;
268 }
09e1b0e3
FW
269 status = __libio_codecvt_in (cd, &fp->_wide_data->_IO_state,
270 from, to, &read_ptr_copy,
271 fp->_wide_data->_IO_read_end,
272 fp->_wide_data->_IO_buf_end,
273 &fp->_wide_data->_IO_read_end);
d64b6ad0 274
a1ffb40e 275 if (__glibc_unlikely (naccbuf != 0))
82f2e9c6
UD
276 fp->_IO_read_ptr += MAX (0, read_ptr_copy - &accbuf[naccbuf - to_copy]);
277 else
278 fp->_IO_read_ptr = (char *) read_ptr_copy;
d64b6ad0
UD
279 if (fp->_wide_data->_IO_read_end == fp->_wide_data->_IO_buf_base)
280 {
82f2e9c6 281 if (status == __codecvt_error)
d64b6ad0 282 {
82f2e9c6 283 out_eilseq:
d64b6ad0
UD
284 __set_errno (EILSEQ);
285 fp->_flags |= _IO_ERR_SEEN;
286 return WEOF;
287 }
288
289 /* The read bytes make no complete character. Try reading again. */
290 assert (status == __codecvt_partial);
82f2e9c6
UD
291
292 if (naccbuf == 0)
293 {
a71433e7
UD
294 if (fp->_IO_read_base < fp->_IO_read_ptr)
295 {
296 /* Partially used the buffer for some input data that
297 produces no output. */
298 size_t avail = fp->_IO_read_end - fp->_IO_read_ptr;
299 memmove (fp->_IO_read_base, fp->_IO_read_ptr, avail);
300 fp->_IO_read_ptr = fp->_IO_read_base;
301 fp->_IO_read_end -= avail;
302 goto again;
303 }
82f2e9c6
UD
304 naccbuf = fp->_IO_read_end - fp->_IO_read_ptr;
305 if (naccbuf >= sizeof (accbuf))
306 goto out_eilseq;
307
308 memcpy (accbuf, fp->_IO_read_ptr, naccbuf);
309 }
a71433e7
UD
310 else
311 {
312 size_t used = read_ptr_copy - accbuf;
313 if (used > 0)
314 {
315 memmove (accbuf, read_ptr_copy, naccbuf - used);
316 naccbuf -= used;
317 }
318
319 if (naccbuf == sizeof (accbuf))
320 goto out_eilseq;
321 }
82f2e9c6
UD
322
323 fp->_IO_read_ptr = fp->_IO_read_end = fp->_IO_read_base;
324
d64b6ad0
UD
325 goto again;
326 }
327
328 return *fp->_wide_data->_IO_read_ptr;
329}
d18ea0c5 330libc_hidden_def (_IO_wfile_underflow)
d64b6ad0
UD
331
332
0469311e 333static wint_t
9964a145 334_IO_wfile_underflow_mmap (FILE *fp)
0469311e
UD
335{
336 struct _IO_codecvt *cd;
284749da 337 const char *read_stop;
0469311e 338
a1ffb40e 339 if (__glibc_unlikely (fp->_flags & _IO_NO_READS))
0469311e
UD
340 {
341 fp->_flags |= _IO_ERR_SEEN;
342 __set_errno (EBADF);
343 return WEOF;
344 }
345 if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
346 return *fp->_wide_data->_IO_read_ptr;
347
348 cd = fp->_codecvt;
349
350 /* Maybe there is something left in the external buffer. */
284749da
UD
351 if (fp->_IO_read_ptr >= fp->_IO_read_end
352 /* No. But maybe the read buffer is not fully set up. */
353 && _IO_file_underflow_mmap (fp) == EOF)
acbee5f6
RM
354 /* Nothing available. _IO_file_underflow_mmap has set the EOF or error
355 flags as appropriate. */
356 return WEOF;
284749da
UD
357
358 /* There is more in the external. Convert it. */
359 read_stop = (const char *) fp->_IO_read_ptr;
0469311e 360
284749da
UD
361 if (fp->_wide_data->_IO_buf_base == NULL)
362 {
363 /* Maybe we already have a push back pointer. */
364 if (fp->_wide_data->_IO_save_base != NULL)
0469311e 365 {
284749da
UD
366 free (fp->_wide_data->_IO_save_base);
367 fp->_flags &= ~_IO_IN_BACKUP;
0469311e 368 }
d18ea0c5 369 _IO_wdoallocbuf (fp);
284749da 370 }
0469311e 371
284749da
UD
372 fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state;
373 fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr =
374 fp->_wide_data->_IO_buf_base;
09e1b0e3
FW
375 __libio_codecvt_in (cd, &fp->_wide_data->_IO_state,
376 fp->_IO_read_ptr, fp->_IO_read_end,
377 &read_stop,
378 fp->_wide_data->_IO_read_ptr,
379 fp->_wide_data->_IO_buf_end,
380 &fp->_wide_data->_IO_read_end);
0469311e 381
284749da 382 fp->_IO_read_ptr = (char *) read_stop;
0469311e 383
284749da
UD
384 /* If we managed to generate some text return the next character. */
385 if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end)
386 return *fp->_wide_data->_IO_read_ptr;
0469311e 387
284749da
UD
388 /* There is some garbage at the end of the file. */
389 __set_errno (EILSEQ);
390 fp->_flags |= _IO_ERR_SEEN;
0469311e
UD
391 return WEOF;
392}
393
acbee5f6 394static wint_t
9964a145 395_IO_wfile_underflow_maybe_mmap (FILE *fp)
acbee5f6
RM
396{
397 /* This is the first read attempt. Doing the underflow will choose mmap
398 or vanilla operations and then punt to the chosen underflow routine.
399 Then we can punt to ours. */
400 if (_IO_file_underflow_maybe_mmap (fp) == EOF)
401 return WEOF;
402
403 return _IO_WUNDERFLOW (fp);
404}
405
0469311e 406
d64b6ad0 407wint_t
9964a145 408_IO_wfile_overflow (FILE *f, wint_t wch)
d64b6ad0
UD
409{
410 if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
411 {
412 f->_flags |= _IO_ERR_SEEN;
413 __set_errno (EBADF);
414 return WEOF;
415 }
416 /* If currently reading or no buffer allocated. */
417 if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
418 {
419 /* Allocate a buffer if needed. */
420 if (f->_wide_data->_IO_write_base == 0)
421 {
d18ea0c5 422 _IO_wdoallocbuf (f);
cc683f7e 423 _IO_free_wbackup_area (f);
d64b6ad0
UD
424 _IO_wsetg (f, f->_wide_data->_IO_buf_base,
425 f->_wide_data->_IO_buf_base, f->_wide_data->_IO_buf_base);
9c38a689
UD
426
427 if (f->_IO_write_base == NULL)
428 {
d18ea0c5 429 _IO_doallocbuf (f);
9c38a689
UD
430 _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
431 }
d64b6ad0
UD
432 }
433 else
434 {
435 /* Otherwise must be currently reading. If _IO_read_ptr
436 (and hence also _IO_read_end) is at the buffer end,
437 logically slide the buffer forwards one block (by setting
438 the read pointers to all point at the beginning of the
439 block). This makes room for subsequent output.
440 Otherwise, set the read pointers to _IO_read_end (leaving
441 that alone, so it can continue to correspond to the
442 external position). */
443 if (f->_wide_data->_IO_read_ptr == f->_wide_data->_IO_buf_end)
444 {
445 f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
446 f->_wide_data->_IO_read_end = f->_wide_data->_IO_read_ptr =
447 f->_wide_data->_IO_buf_base;
448 }
449 }
450 f->_wide_data->_IO_write_ptr = f->_wide_data->_IO_read_ptr;
451 f->_wide_data->_IO_write_base = f->_wide_data->_IO_write_ptr;
452 f->_wide_data->_IO_write_end = f->_wide_data->_IO_buf_end;
453 f->_wide_data->_IO_read_base = f->_wide_data->_IO_read_ptr =
454 f->_wide_data->_IO_read_end;
455
9c38a689
UD
456 f->_IO_write_ptr = f->_IO_read_ptr;
457 f->_IO_write_base = f->_IO_write_ptr;
458 f->_IO_write_end = f->_IO_buf_end;
459 f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
460
d64b6ad0 461 f->_flags |= _IO_CURRENTLY_PUTTING;
2e425022 462 if (f->_flags & (_IO_LINE_BUF | _IO_UNBUFFERED))
d64b6ad0
UD
463 f->_wide_data->_IO_write_end = f->_wide_data->_IO_write_ptr;
464 }
465 if (wch == WEOF)
466 return _IO_do_flush (f);
9c38a689 467 if (f->_wide_data->_IO_write_ptr == f->_wide_data->_IO_buf_end)
d64b6ad0 468 /* Buffer is really full */
6dd67bd5 469 if (_IO_do_flush (f) == EOF)
d64b6ad0
UD
470 return WEOF;
471 *f->_wide_data->_IO_write_ptr++ = wch;
472 if ((f->_flags & _IO_UNBUFFERED)
473 || ((f->_flags & _IO_LINE_BUF) && wch == L'\n'))
6dd67bd5 474 if (_IO_do_flush (f) == EOF)
d64b6ad0
UD
475 return WEOF;
476 return wch;
477}
d18ea0c5 478libc_hidden_def (_IO_wfile_overflow)
d64b6ad0
UD
479
480wint_t
9964a145 481_IO_wfile_sync (FILE *fp)
d64b6ad0 482{
9964a145 483 ssize_t delta;
d64b6ad0
UD
484 wint_t retval = 0;
485
486 /* char* ptr = cur_ptr(); */
487 if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)
488 if (_IO_do_flush (fp))
489 return WEOF;
490 delta = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_end;
491 if (delta != 0)
492 {
493 /* We have to find out how many bytes we have to go back in the
494 external buffer. */
cd8b7ff9 495 struct _IO_codecvt *cv = fp->_codecvt;
9964a145 496 off64_t new_pos;
d64b6ad0 497
09e1b0e3 498 int clen = __libio_codecvt_encoding (cv);
d64b6ad0
UD
499
500 if (clen > 0)
501 /* It is easy, a fixed number of input bytes are used for each
502 wide character. */
503 delta *= clen;
504 else
505 {
506 /* We have to find out the hard way how much to back off.
aaddc98c
MP
507 To do this we determine how much input we needed to
508 generate the wide characters up to the current reading
509 position. */
d64b6ad0 510 int nread;
32ff3975
AS
511 size_t wnread = (fp->_wide_data->_IO_read_ptr
512 - fp->_wide_data->_IO_read_base);
d64b6ad0 513 fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
09e1b0e3
FW
514 nread = __libio_codecvt_length (cv, &fp->_wide_data->_IO_state,
515 fp->_IO_read_base,
516 fp->_IO_read_end, wnread);
d64b6ad0
UD
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);
9964a145 522 if (new_pos != (off64_t) EOF)
d64b6ad0
UD
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
9964a145 547adjust_wide_data (FILE *fp, bool do_convert)
4573c6b0
SP
548{
549 struct _IO_codecvt *cv = fp->_codecvt;
550
09e1b0e3 551 int clen = __libio_codecvt_encoding (cv);
4573c6b0
SP
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;
09e1b0e3
FW
568 status = __libio_codecvt_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);
4573c6b0
SP
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. */
9964a145
ZW
594static off64_t
595do_ftell_wide (FILE *fp)
d64b6ad0 596{
9964a145 597 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 650 struct _IO_codecvt *cv = fp->_codecvt;
09e1b0e3 651 int clen = __libio_codecvt_encoding (cv);
000232b9 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;
09e1b0e3
FW
666 nread = __libio_codecvt_length (cv, &state,
667 fp->_IO_read_base,
668 fp->_IO_read_end, delta);
000232b9
SP
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;
09e1b0e3
FW
691 status = __libio_codecvt_out (cv, &state, in, in + delta, &in,
692 out, out + outsize, &outstop);
000232b9
SP
693
694 /* We don't check for __codecvt_partial because it can be
695 returned on one of two conditions: either the output
696 buffer is full or the input sequence is incomplete. We
697 take care to allocate enough buffer and our input
698 sequences must be complete since they are accepted as
699 wchar_t; if not, then that is an error. */
700 if (__glibc_unlikely (status != __codecvt_ok))
545583d6
SP
701 {
702 free (out);
703 return WEOF;
704 }
000232b9
SP
705
706 offset += outstop - out;
984c0ea9 707 free (out);
000232b9
SP
708 }
709
2482ae43
SP
710 /* We don't trust _IO_read_end to represent the current file offset
711 when writing in append mode because the value would have to be
712 shifted to the end of the file during a flush. Use the write base
713 instead, along with the new offset we got above when we did a seek
714 to the end of the file. */
715 if (append_mode)
716 offset += fp->_IO_write_ptr - fp->_IO_write_base;
717 /* For all other modes, _IO_read_end represents the file offset. */
718 else
719 offset += fp->_IO_write_ptr - fp->_IO_read_end;
000232b9 720 }
40a982a9 721 }
d64b6ad0 722
ea33158c 723 if (fp->_offset != _IO_pos_BAD)
fa3cd248
SP
724 result = fp->_offset;
725 else
ea33158c 726 result = _IO_SYSSEEK (fp, 0, _IO_seek_cur);
000232b9
SP
727
728 if (result == EOF)
729 return result;
730
731 result += offset;
732
ea33158c
SP
733 if (result < 0)
734 {
735 __set_errno (EINVAL);
736 return EOF;
737 }
738
000232b9
SP
739 return result;
740}
741
9964a145
ZW
742off64_t
743_IO_wfile_seekoff (FILE *fp, off64_t offset, int dir, int mode)
000232b9 744{
9964a145
ZW
745 off64_t result;
746 off64_t delta, new_offset;
000232b9
SP
747 long int count;
748
749 /* Short-circuit into a separate function. We don't want to mix any
750 functionality and we don't want to touch anything inside the FILE
751 object. */
752 if (mode == 0)
753 return do_ftell_wide (fp);
754
755 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
756 offset of the underlying file must be exact. */
757 int must_be_exact = ((fp->_wide_data->_IO_read_base
758 == fp->_wide_data->_IO_read_end)
759 && (fp->_wide_data->_IO_write_base
760 == fp->_wide_data->_IO_write_ptr));
761
762 bool was_writing = ((fp->_wide_data->_IO_write_ptr
763 > fp->_wide_data->_IO_write_base)
764 || _IO_in_put_mode (fp));
765
d64b6ad0
UD
766 /* Flush unwritten characters.
767 (This may do an unneeded write if we seek within the buffer.
768 But to be able to switch to reading, we would need to set
1ffb8c90 769 egptr to pptr. That can't be done in the current design,
d64b6ad0
UD
770 which assumes file_ptr() is eGptr. Anyway, since we probably
771 end up flushing when we close(), it doesn't make much difference.)
40a982a9 772 FIXME: simulate mem-mapped files. */
000232b9 773 if (was_writing && _IO_switch_to_wget_mode (fp))
adb26fae 774 return WEOF;
d64b6ad0
UD
775
776 if (fp->_wide_data->_IO_buf_base == NULL)
777 {
778 /* It could be that we already have a pushback buffer. */
779 if (fp->_wide_data->_IO_read_base != NULL)
780 {
781 free (fp->_wide_data->_IO_read_base);
782 fp->_flags &= ~_IO_IN_BACKUP;
783 }
d18ea0c5 784 _IO_doallocbuf (fp);
d64b6ad0
UD
785 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
786 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
787 _IO_wsetp (fp, fp->_wide_data->_IO_buf_base,
788 fp->_wide_data->_IO_buf_base);
789 _IO_wsetg (fp, fp->_wide_data->_IO_buf_base,
790 fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base);
791 }
792
793 switch (dir)
794 {
795 struct _IO_codecvt *cv;
796 int clen;
797
798 case _IO_seek_cur:
799 /* Adjust for read-ahead (bytes is buffer). To do this we must
aaddc98c
MP
800 find out which position in the external buffer corresponds to
801 the current position in the internal buffer. */
cd8b7ff9 802 cv = fp->_codecvt;
09e1b0e3 803 clen = __libio_codecvt_encoding (cv);
d64b6ad0 804
adb26fae 805 if (mode != 0 || !was_writing)
5d2e6976 806 {
adb26fae
SP
807 if (clen > 0)
808 {
809 offset -= (fp->_wide_data->_IO_read_end
810 - fp->_wide_data->_IO_read_ptr) * clen;
811 /* Adjust by readahead in external buffer. */
812 offset -= fp->_IO_read_end - fp->_IO_read_ptr;
813 }
814 else
815 {
816 int nread;
817
adb26fae
SP
818 delta = (fp->_wide_data->_IO_read_ptr
819 - fp->_wide_data->_IO_read_base);
820 fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
09e1b0e3
FW
821 nread = __libio_codecvt_length (cv,
822 &fp->_wide_data->_IO_state,
823 fp->_IO_read_base,
824 fp->_IO_read_end, delta);
adb26fae
SP
825 fp->_IO_read_ptr = fp->_IO_read_base + nread;
826 fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr;
827 offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
828 }
5d2e6976 829 }
d64b6ad0
UD
830
831 if (fp->_offset == _IO_pos_BAD)
000232b9 832 goto dumb;
adb26fae 833
d64b6ad0
UD
834 /* Make offset absolute, assuming current pointer is file_ptr(). */
835 offset += fp->_offset;
836
837 dir = _IO_seek_set;
838 break;
839 case _IO_seek_set:
840 break;
841 case _IO_seek_end:
842 {
c8450f70 843 struct stat64 st;
d64b6ad0
UD
844 if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
845 {
846 offset += st.st_size;
847 dir = _IO_seek_set;
848 }
849 else
850 goto dumb;
851 }
852 }
cc683f7e
AZ
853
854 _IO_free_wbackup_area (fp);
855
d64b6ad0
UD
856 /* At this point, dir==_IO_seek_set. */
857
d64b6ad0
UD
858 /* If destination is within current buffer, optimize: */
859 if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
860 && !_IO_in_backup (fp))
861 {
9964a145
ZW
862 off64_t start_offset = (fp->_offset
863 - (fp->_IO_read_end - fp->_IO_buf_base));
d840539e 864 if (offset >= start_offset && offset < fp->_offset)
d64b6ad0 865 {
d840539e
AS
866 _IO_setg (fp, fp->_IO_buf_base,
867 fp->_IO_buf_base + (offset - start_offset),
868 fp->_IO_read_end);
869 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
5d2e6976
AS
870 _IO_wsetg (fp, fp->_wide_data->_IO_buf_base,
871 fp->_wide_data->_IO_buf_base,
872 fp->_wide_data->_IO_buf_base);
873 _IO_wsetp (fp, fp->_wide_data->_IO_buf_base,
874 fp->_wide_data->_IO_buf_base);
4573c6b0
SP
875
876 if (adjust_wide_data (fp, false))
877 goto dumb;
878
d64b6ad0
UD
879 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
880 goto resync;
881 }
d64b6ad0
UD
882 }
883
d64b6ad0
UD
884 if (fp->_flags & _IO_NO_READS)
885 goto dumb;
886
887 /* Try to seek to a block boundary, to improve kernel page management. */
888 new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
889 delta = offset - new_offset;
890 if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
891 {
892 new_offset = offset;
893 delta = 0;
894 }
895 result = _IO_SYSSEEK (fp, new_offset, 0);
896 if (result < 0)
897 return EOF;
898 if (delta == 0)
899 count = 0;
900 else
901 {
902 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
903 (must_be_exact
904 ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
905 if (count < delta)
906 {
907 /* We weren't allowed to read, but try to seek the remainder. */
908 offset = count == EOF ? delta : delta-count;
909 dir = _IO_seek_cur;
910 goto dumb;
911 }
912 }
913 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
914 fp->_IO_buf_base + count);
915 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
5d2e6976
AS
916 _IO_wsetg (fp, fp->_wide_data->_IO_buf_base,
917 fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base);
918 _IO_wsetp (fp, fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base);
4573c6b0
SP
919
920 if (adjust_wide_data (fp, true))
921 goto dumb;
922
d64b6ad0
UD
923 fp->_offset = result + count;
924 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
925 return offset;
926 dumb:
927
d18ea0c5 928 _IO_unsave_markers (fp);
d64b6ad0
UD
929 result = _IO_SYSSEEK (fp, offset, dir);
930 if (result != EOF)
931 {
932 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
933 fp->_offset = result;
934 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
935 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
40a982a9
UD
936 _IO_wsetg (fp, fp->_wide_data->_IO_buf_base,
937 fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base);
938 _IO_wsetp (fp, fp->_wide_data->_IO_buf_base,
939 fp->_wide_data->_IO_buf_base);
d64b6ad0
UD
940 }
941 return result;
942
943resync:
944 /* We need to do it since it is possible that the file offset in
945 the kernel may be changed behind our back. It may happen when
946 we fopen a file and then do a fork. One process may access the
ded5b9b7 947 file and the kernel file offset will be changed. */
d64b6ad0
UD
948 if (fp->_offset >= 0)
949 _IO_SYSSEEK (fp, fp->_offset, 0);
950
951 return offset;
952}
d18ea0c5 953libc_hidden_def (_IO_wfile_seekoff)
d64b6ad0
UD
954
955
9964a145
ZW
956size_t
957_IO_wfile_xsputn (FILE *f, const void *data, size_t n)
d64b6ad0 958{
2e09a79a 959 const wchar_t *s = (const wchar_t *) data;
9964a145 960 size_t to_do = n;
d64b6ad0 961 int must_flush = 0;
9964a145 962 size_t count;
d64b6ad0
UD
963
964 if (n <= 0)
965 return 0;
966 /* This is an optimized implementation.
967 If the amount to be written straddles a block boundary
968 (or the filebuf is unbuffered), use sys_write directly. */
969
970 /* First figure out how much space is available in the buffer. */
971 count = f->_wide_data->_IO_write_end - f->_wide_data->_IO_write_ptr;
972 if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
973 {
974 count = f->_wide_data->_IO_buf_end - f->_wide_data->_IO_write_ptr;
975 if (count >= n)
976 {
2e09a79a 977 const wchar_t *p;
d64b6ad0
UD
978 for (p = s + n; p > s; )
979 {
980 if (*--p == L'\n')
981 {
982 count = p - s + 1;
983 must_flush = 1;
984 break;
985 }
986 }
987 }
988 }
989 /* Then fill the buffer. */
990 if (count > 0)
991 {
992 if (count > to_do)
993 count = to_do;
994 if (count > 20)
995 {
d64b6ad0
UD
996 f->_wide_data->_IO_write_ptr =
997 __wmempcpy (f->_wide_data->_IO_write_ptr, s, count);
d64b6ad0
UD
998 s += count;
999 }
1000 else
1001 {
2e09a79a
JM
1002 wchar_t *p = f->_wide_data->_IO_write_ptr;
1003 int i = (int) count;
d64b6ad0
UD
1004 while (--i >= 0)
1005 *p++ = *s++;
1006 f->_wide_data->_IO_write_ptr = p;
1007 }
1008 to_do -= count;
1009 }
1010 if (to_do > 0)
d18ea0c5 1011 to_do -= _IO_wdefault_xsputn (f, s, to_do);
d64b6ad0
UD
1012 if (must_flush
1013 && f->_wide_data->_IO_write_ptr != f->_wide_data->_IO_write_base)
d18ea0c5
AS
1014 _IO_wdo_write (f, f->_wide_data->_IO_write_base,
1015 f->_wide_data->_IO_write_ptr
1016 - f->_wide_data->_IO_write_base);
d64b6ad0
UD
1017
1018 return n - to_do;
1019}
d18ea0c5 1020libc_hidden_def (_IO_wfile_xsputn)
d64b6ad0
UD
1021
1022
db3476af 1023const struct _IO_jump_t _IO_wfile_jumps libio_vtable =
d64b6ad0
UD
1024{
1025 JUMP_INIT_DUMMY,
1026 JUMP_INIT(finish, _IO_new_file_finish),
d18ea0c5
AS
1027 JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
1028 JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow),
1029 JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
1030 JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
1031 JUMP_INIT(xsputn, _IO_wfile_xsputn),
1032 JUMP_INIT(xsgetn, _IO_file_xsgetn),
1033 JUMP_INIT(seekoff, _IO_wfile_seekoff),
d64b6ad0
UD
1034 JUMP_INIT(seekpos, _IO_default_seekpos),
1035 JUMP_INIT(setbuf, _IO_new_file_setbuf),
d18ea0c5 1036 JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
d64b6ad0 1037 JUMP_INIT(doallocate, _IO_wfile_doallocate),
d18ea0c5 1038 JUMP_INIT(read, _IO_file_read),
d64b6ad0 1039 JUMP_INIT(write, _IO_new_file_write),
d18ea0c5
AS
1040 JUMP_INIT(seek, _IO_file_seek),
1041 JUMP_INIT(close, _IO_file_close),
1042 JUMP_INIT(stat, _IO_file_stat),
d64b6ad0
UD
1043 JUMP_INIT(showmanyc, _IO_default_showmanyc),
1044 JUMP_INIT(imbue, _IO_default_imbue)
1045};
15a686af 1046libc_hidden_data_def (_IO_wfile_jumps)
0469311e
UD
1047
1048
db3476af 1049const struct _IO_jump_t _IO_wfile_jumps_mmap libio_vtable =
0469311e
UD
1050{
1051 JUMP_INIT_DUMMY,
1052 JUMP_INIT(finish, _IO_new_file_finish),
d18ea0c5 1053 JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
0469311e 1054 JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow_mmap),
d18ea0c5
AS
1055 JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
1056 JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
1057 JUMP_INIT(xsputn, _IO_wfile_xsputn),
1058 JUMP_INIT(xsgetn, _IO_file_xsgetn),
1059 JUMP_INIT(seekoff, _IO_wfile_seekoff),
0469311e 1060 JUMP_INIT(seekpos, _IO_default_seekpos),
bff334e0 1061 JUMP_INIT(setbuf, _IO_file_setbuf_mmap),
d18ea0c5 1062 JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
0469311e 1063 JUMP_INIT(doallocate, _IO_wfile_doallocate),
d18ea0c5 1064 JUMP_INIT(read, _IO_file_read),
0469311e 1065 JUMP_INIT(write, _IO_new_file_write),
d18ea0c5 1066 JUMP_INIT(seek, _IO_file_seek),
0469311e 1067 JUMP_INIT(close, _IO_file_close_mmap),
d18ea0c5 1068 JUMP_INIT(stat, _IO_file_stat),
0469311e
UD
1069 JUMP_INIT(showmanyc, _IO_default_showmanyc),
1070 JUMP_INIT(imbue, _IO_default_imbue)
1071};
acbee5f6 1072
db3476af 1073const struct _IO_jump_t _IO_wfile_jumps_maybe_mmap libio_vtable =
acbee5f6
RM
1074{
1075 JUMP_INIT_DUMMY,
1076 JUMP_INIT(finish, _IO_new_file_finish),
d18ea0c5 1077 JUMP_INIT(overflow, (_IO_overflow_t) _IO_wfile_overflow),
acbee5f6 1078 JUMP_INIT(underflow, (_IO_underflow_t) _IO_wfile_underflow_maybe_mmap),
d18ea0c5
AS
1079 JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),
1080 JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wdefault_pbackfail),
1081 JUMP_INIT(xsputn, _IO_wfile_xsputn),
1082 JUMP_INIT(xsgetn, _IO_file_xsgetn),
1083 JUMP_INIT(seekoff, _IO_wfile_seekoff),
acbee5f6
RM
1084 JUMP_INIT(seekpos, _IO_default_seekpos),
1085 JUMP_INIT(setbuf, _IO_file_setbuf_mmap),
d18ea0c5 1086 JUMP_INIT(sync, (_IO_sync_t) _IO_wfile_sync),
acbee5f6 1087 JUMP_INIT(doallocate, _IO_wfile_doallocate),
d18ea0c5 1088 JUMP_INIT(read, _IO_file_read),
acbee5f6 1089 JUMP_INIT(write, _IO_new_file_write),
d18ea0c5
AS
1090 JUMP_INIT(seek, _IO_file_seek),
1091 JUMP_INIT(close, _IO_file_close),
1092 JUMP_INIT(stat, _IO_file_stat),
acbee5f6
RM
1093 JUMP_INIT(showmanyc, _IO_default_showmanyc),
1094 JUMP_INIT(imbue, _IO_default_imbue)
1095};