Remove THREAD_STATS.
[glibc.git] / libio / oldfileops.c
blob8439b97ffe82fadd13a4d6ea158998881b45d304
1 /* Copyright (C) 1993-2014 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Written by Per Bothner <bothner@cygnus.com>.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>.
19 As a special exception, if you link the code in this file with
20 files compiled with a GNU compiler to produce an executable,
21 that does not cause the resulting executable to be covered by
22 the GNU Lesser General Public License. This exception does not
23 however invalidate any other reasons why the executable file
24 might be covered by the GNU Lesser General Public License.
25 This exception applies to code released by its copyright holders
26 in files containing the exception. */
28 /* This is a compatibility file. If we don't build the libc with
29 versioning don't compile this file. */
30 #include <shlib-compat.h>
31 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
33 #ifndef _POSIX_SOURCE
34 # define _POSIX_SOURCE
35 #endif
36 #define _IO_USE_OLD_IO_FILE
37 #include "libioP.h"
38 #include <fcntl.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <string.h>
42 #include <errno.h>
43 #include <stdlib.h>
44 #ifndef errno
45 extern int errno;
46 #endif
47 #ifndef __set_errno
48 # define __set_errno(Val) errno = (Val)
49 #endif
52 #ifdef _LIBC
53 # define open(Name, Flags, Prot) __open (Name, Flags, Prot)
54 # define close(FD) __close (FD)
55 # define lseek(FD, Offset, Whence) __lseek (FD, Offset, Whence)
56 # define read(FD, Buf, NBytes) __read (FD, Buf, NBytes)
57 # define write(FD, Buf, NBytes) __write (FD, Buf, NBytes)
58 #endif
60 /* An fstream can be in at most one of put mode, get mode, or putback mode.
61 Putback mode is a variant of get mode.
63 In a filebuf, there is only one current position, instead of two
64 separate get and put pointers. In get mode, the current position
65 is that of gptr(); in put mode that of pptr().
67 The position in the buffer that corresponds to the position
68 in external file system is normally _IO_read_end, except in putback
69 mode, when it is _IO_save_end.
70 If the field _fb._offset is >= 0, it gives the offset in
71 the file as a whole corresponding to eGptr(). (?)
73 PUT MODE:
74 If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
75 and _IO_read_base are equal to each other. These are usually equal
76 to _IO_buf_base, though not necessarily if we have switched from
77 get mode to put mode. (The reason is to maintain the invariant
78 that _IO_read_end corresponds to the external file position.)
79 _IO_write_base is non-NULL and usually equal to _IO_buf_base.
80 We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
81 The un-flushed character are those between _IO_write_base and _IO_write_ptr.
83 GET MODE:
84 If a filebuf is in get or putback mode, eback() != egptr().
85 In get mode, the unread characters are between gptr() and egptr().
86 The OS file position corresponds to that of egptr().
88 PUTBACK MODE:
89 Putback mode is used to remember "excess" characters that have
90 been sputbackc'd in a separate putback buffer.
91 In putback mode, the get buffer points to the special putback buffer.
92 The unread characters are the characters between gptr() and egptr()
93 in the putback buffer, as well as the area between save_gptr()
94 and save_egptr(), which point into the original reserve buffer.
95 (The pointers save_gptr() and save_egptr() are the values
96 of gptr() and egptr() at the time putback mode was entered.)
97 The OS position corresponds to that of save_egptr().
99 LINE BUFFERED OUTPUT:
100 During line buffered output, _IO_write_base==base() && epptr()==base().
101 However, ptr() may be anywhere between base() and ebuf().
102 This forces a call to filebuf::overflow(int C) on every put.
103 If there is more space in the buffer, and C is not a '\n',
104 then C is inserted, and pptr() incremented.
106 UNBUFFERED STREAMS:
107 If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
110 #define CLOSED_FILEBUF_FLAGS \
111 (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
114 void
115 attribute_compat_text_section
116 _IO_old_file_init (fp)
117 struct _IO_FILE_plus *fp;
119 /* POSIX.1 allows another file handle to be used to change the position
120 of our file descriptor. Hence we actually don't know the actual
121 position before we do the first fseek (and until a following fflush). */
122 fp->file._old_offset = _IO_pos_BAD;
123 fp->file._IO_file_flags |= CLOSED_FILEBUF_FLAGS;
125 _IO_link_in (fp);
126 fp->file._vtable_offset = ((int) sizeof (struct _IO_FILE)
127 - (int) sizeof (struct _IO_FILE_complete));
128 fp->file._fileno = -1;
130 #if defined SHARED && defined _LIBC
131 if (__builtin_expect (&_IO_stdin_used != NULL, 1)
132 || (fp != (struct _IO_FILE_plus *) _IO_stdin
133 && fp != (struct _IO_FILE_plus *) _IO_stdout
134 && fp != (struct _IO_FILE_plus *) _IO_stderr))
135 /* The object is dynamically allocated and large enough. Initialize
136 the _mode element as well. */
137 ((struct _IO_FILE_complete *) fp)->_mode = -1;
138 #endif
142 attribute_compat_text_section
143 _IO_old_file_close_it (fp)
144 _IO_FILE *fp;
146 int write_status, close_status;
147 if (!_IO_file_is_open (fp))
148 return EOF;
150 write_status = _IO_old_do_flush (fp);
152 _IO_unsave_markers (fp);
154 close_status = ((fp->_flags2 & _IO_FLAGS2_NOCLOSE) == 0
155 ? _IO_SYSCLOSE (fp) : 0);
157 /* Free buffer. */
158 _IO_setb (fp, NULL, NULL, 0);
159 _IO_setg (fp, NULL, NULL, NULL);
160 _IO_setp (fp, NULL, NULL);
162 _IO_un_link ((struct _IO_FILE_plus *) fp);
163 fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
164 fp->_fileno = -1;
165 fp->_old_offset = _IO_pos_BAD;
167 return close_status ? close_status : write_status;
170 void
171 attribute_compat_text_section
172 _IO_old_file_finish (fp, dummy)
173 _IO_FILE *fp;
174 int dummy;
176 if (_IO_file_is_open (fp))
178 _IO_old_do_flush (fp);
179 if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
180 _IO_SYSCLOSE (fp);
182 _IO_default_finish (fp, 0);
185 _IO_FILE *
186 attribute_compat_text_section
187 _IO_old_file_fopen (fp, filename, mode)
188 _IO_FILE *fp;
189 const char *filename;
190 const char *mode;
192 int oflags = 0, omode;
193 int read_write, fdesc;
194 int oprot = 0666;
195 if (_IO_file_is_open (fp))
196 return 0;
197 switch (*mode++)
199 case 'r':
200 omode = O_RDONLY;
201 read_write = _IO_NO_WRITES;
202 break;
203 case 'w':
204 omode = O_WRONLY;
205 oflags = O_CREAT|O_TRUNC;
206 read_write = _IO_NO_READS;
207 break;
208 case 'a':
209 omode = O_WRONLY;
210 oflags = O_CREAT|O_APPEND;
211 read_write = _IO_NO_READS|_IO_IS_APPENDING;
212 break;
213 default:
214 __set_errno (EINVAL);
215 return NULL;
217 if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+'))
219 omode = O_RDWR;
220 read_write &= _IO_IS_APPENDING;
222 fdesc = open (filename, omode|oflags, oprot);
223 if (fdesc < 0)
224 return NULL;
225 fp->_fileno = fdesc;
226 _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
227 if (read_write & _IO_IS_APPENDING)
228 if (_IO_SEEKOFF (fp, (_IO_off_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
229 == _IO_pos_BAD && errno != ESPIPE)
230 return NULL;
231 _IO_link_in ((struct _IO_FILE_plus *) fp);
232 return fp;
235 _IO_FILE *
236 attribute_compat_text_section
237 _IO_old_file_attach (fp, fd)
238 _IO_FILE *fp;
239 int fd;
241 if (_IO_file_is_open (fp))
242 return NULL;
243 fp->_fileno = fd;
244 fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
245 fp->_flags |= _IO_DELETE_DONT_CLOSE;
246 /* Get the current position of the file. */
247 /* We have to do that since that may be junk. */
248 fp->_old_offset = _IO_pos_BAD;
249 if (_IO_SEEKOFF (fp, (_IO_off_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
250 == _IO_pos_BAD && errno != ESPIPE)
251 return NULL;
252 return fp;
255 _IO_FILE *
256 attribute_compat_text_section
257 _IO_old_file_setbuf (fp, p, len)
258 _IO_FILE *fp;
259 char *p;
260 _IO_ssize_t len;
262 if (_IO_default_setbuf (fp, p, len) == NULL)
263 return NULL;
265 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
266 = fp->_IO_buf_base;
267 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
269 return fp;
272 static int old_do_write (_IO_FILE *, const char *, _IO_size_t);
274 /* Write TO_DO bytes from DATA to FP.
275 Then mark FP as having empty buffers. */
278 attribute_compat_text_section
279 _IO_old_do_write (fp, data, to_do)
280 _IO_FILE *fp;
281 const char *data;
282 _IO_size_t to_do;
284 return (to_do == 0 || (_IO_size_t) old_do_write (fp, data, to_do) == to_do)
285 ? 0 : EOF;
288 static int
289 attribute_compat_text_section
290 old_do_write (fp, data, to_do)
291 _IO_FILE *fp;
292 const char *data;
293 _IO_size_t to_do;
295 _IO_size_t count;
296 if (fp->_flags & _IO_IS_APPENDING)
297 /* On a system without a proper O_APPEND implementation,
298 you would need to sys_seek(0, SEEK_END) here, but is
299 not needed nor desirable for Unix- or Posix-like systems.
300 Instead, just indicate that offset (before and after) is
301 unpredictable. */
302 fp->_old_offset = _IO_pos_BAD;
303 else if (fp->_IO_read_end != fp->_IO_write_base)
305 _IO_off_t new_pos
306 = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
307 if (new_pos == _IO_pos_BAD)
308 return 0;
309 fp->_old_offset = new_pos;
311 count = _IO_SYSWRITE (fp, data, to_do);
312 if (fp->_cur_column && count)
313 fp->_cur_column = _IO_adjust_column (fp->_cur_column - 1, data, count) + 1;
314 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
315 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
316 fp->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
317 ? fp->_IO_buf_base : fp->_IO_buf_end);
318 return count;
322 attribute_compat_text_section
323 _IO_old_file_underflow (fp)
324 _IO_FILE *fp;
326 _IO_ssize_t count;
327 #if 0
328 /* SysV does not make this test; take it out for compatibility */
329 if (fp->_flags & _IO_EOF_SEEN)
330 return (EOF);
331 #endif
333 if (fp->_flags & _IO_NO_READS)
335 fp->_flags |= _IO_ERR_SEEN;
336 __set_errno (EBADF);
337 return EOF;
339 if (fp->_IO_read_ptr < fp->_IO_read_end)
340 return *(unsigned char *) fp->_IO_read_ptr;
342 if (fp->_IO_buf_base == NULL)
344 /* Maybe we already have a push back pointer. */
345 if (fp->_IO_save_base != NULL)
347 free (fp->_IO_save_base);
348 fp->_flags &= ~_IO_IN_BACKUP;
350 _IO_doallocbuf (fp);
353 /* Flush all line buffered files before reading. */
354 /* FIXME This can/should be moved to genops ?? */
355 if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
356 _IO_flush_all_linebuffered ();
358 _IO_switch_to_get_mode (fp);
360 /* This is very tricky. We have to adjust those
361 pointers before we call _IO_SYSREAD () since
362 we may longjump () out while waiting for
363 input. Those pointers may be screwed up. H.J. */
364 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
365 fp->_IO_read_end = fp->_IO_buf_base;
366 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
367 = fp->_IO_buf_base;
369 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
370 fp->_IO_buf_end - fp->_IO_buf_base);
371 if (count <= 0)
373 if (count == 0)
374 fp->_flags |= _IO_EOF_SEEN;
375 else
376 fp->_flags |= _IO_ERR_SEEN, count = 0;
378 fp->_IO_read_end += count;
379 if (count == 0)
380 return EOF;
381 if (fp->_old_offset != _IO_pos_BAD)
382 _IO_pos_adjust (fp->_old_offset, count);
383 return *(unsigned char *) fp->_IO_read_ptr;
387 attribute_compat_text_section
388 _IO_old_file_overflow (f, ch)
389 _IO_FILE *f;
390 int ch;
392 if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
394 f->_flags |= _IO_ERR_SEEN;
395 __set_errno (EBADF);
396 return EOF;
398 /* If currently reading or no buffer allocated. */
399 if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
401 /* Allocate a buffer if needed. */
402 if (f->_IO_write_base == 0)
404 _IO_doallocbuf (f);
405 _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
407 /* Otherwise must be currently reading.
408 If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
409 logically slide the buffer forwards one block (by setting the
410 read pointers to all point at the beginning of the block). This
411 makes room for subsequent output.
412 Otherwise, set the read pointers to _IO_read_end (leaving that
413 alone, so it can continue to correspond to the external position). */
414 if (f->_IO_read_ptr == f->_IO_buf_end)
415 f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
416 f->_IO_write_ptr = f->_IO_read_ptr;
417 f->_IO_write_base = f->_IO_write_ptr;
418 f->_IO_write_end = f->_IO_buf_end;
419 f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
421 if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
422 f->_IO_write_end = f->_IO_write_ptr;
423 f->_flags |= _IO_CURRENTLY_PUTTING;
425 if (ch == EOF)
426 return _IO_old_do_flush (f);
427 if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
428 if (_IO_old_do_flush (f) == EOF)
429 return EOF;
430 *f->_IO_write_ptr++ = ch;
431 if ((f->_flags & _IO_UNBUFFERED)
432 || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
433 if (_IO_old_do_flush (f) == EOF)
434 return EOF;
435 return (unsigned char) ch;
439 attribute_compat_text_section
440 _IO_old_file_sync (fp)
441 _IO_FILE *fp;
443 _IO_ssize_t delta;
444 int retval = 0;
446 /* char* ptr = cur_ptr(); */
447 if (fp->_IO_write_ptr > fp->_IO_write_base)
448 if (_IO_old_do_flush(fp)) return EOF;
449 delta = fp->_IO_read_ptr - fp->_IO_read_end;
450 if (delta != 0)
452 #ifdef TODO
453 if (_IO_in_backup (fp))
454 delta -= eGptr () - Gbase ();
455 #endif
456 _IO_off_t new_pos = _IO_SYSSEEK (fp, delta, 1);
457 if (new_pos != (_IO_off_t) EOF)
458 fp->_IO_read_end = fp->_IO_read_ptr;
459 #ifdef ESPIPE
460 else if (errno == ESPIPE)
461 ; /* Ignore error from unseekable devices. */
462 #endif
463 else
464 retval = EOF;
466 if (retval != EOF)
467 fp->_old_offset = _IO_pos_BAD;
468 /* FIXME: Cleanup - can this be shared? */
469 /* setg(base(), ptr, ptr); */
470 return retval;
473 _IO_off64_t
474 attribute_compat_text_section
475 _IO_old_file_seekoff (fp, offset, dir, mode)
476 _IO_FILE *fp;
477 _IO_off64_t offset;
478 int dir;
479 int mode;
481 _IO_off_t result;
482 _IO_off64_t delta, new_offset;
483 long count;
484 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
485 offset of the underlying file must be exact. */
486 int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
487 && fp->_IO_write_base == fp->_IO_write_ptr);
489 if (mode == 0)
490 dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
492 /* Flush unwritten characters.
493 (This may do an unneeded write if we seek within the buffer.
494 But to be able to switch to reading, we would need to set
495 egptr to pptr. That can't be done in the current design,
496 which assumes file_ptr() is eGptr. Anyway, since we probably
497 end up flushing when we close(), it doesn't make much difference.)
498 FIXME: simulate mem-mapped files. */
500 if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
501 if (_IO_switch_to_get_mode (fp))
502 return EOF;
504 if (fp->_IO_buf_base == NULL)
506 /* It could be that we already have a pushback buffer. */
507 if (fp->_IO_read_base != NULL)
509 free (fp->_IO_read_base);
510 fp->_flags &= ~_IO_IN_BACKUP;
512 _IO_doallocbuf (fp);
513 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
514 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
517 switch (dir)
519 case _IO_seek_cur:
520 /* Adjust for read-ahead (bytes is buffer). */
521 offset -= fp->_IO_read_end - fp->_IO_read_ptr;
522 if (fp->_old_offset == _IO_pos_BAD)
523 goto dumb;
524 /* Make offset absolute, assuming current pointer is file_ptr(). */
525 offset += fp->_old_offset;
527 dir = _IO_seek_set;
528 break;
529 case _IO_seek_set:
530 break;
531 case _IO_seek_end:
533 struct stat64 st;
534 if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
536 offset += st.st_size;
537 dir = _IO_seek_set;
539 else
540 goto dumb;
543 /* At this point, dir==_IO_seek_set. */
545 /* If we are only interested in the current position we've found it now. */
546 if (mode == 0)
547 return offset;
549 /* If destination is within current buffer, optimize: */
550 if (fp->_old_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
551 && !_IO_in_backup (fp))
553 /* Offset relative to start of main get area. */
554 _IO_off_t rel_offset = (offset - fp->_old_offset
555 + (fp->_IO_read_end - fp->_IO_read_base));
556 if (rel_offset >= 0)
558 #if 0
559 if (_IO_in_backup (fp))
560 _IO_switch_to_main_get_area (fp);
561 #endif
562 if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
564 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
565 fp->_IO_read_end);
566 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
568 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
569 goto resync;
572 #ifdef TODO
573 /* If we have streammarkers, seek forward by reading ahead. */
574 if (_IO_have_markers (fp))
576 int to_skip = rel_offset
577 - (fp->_IO_read_ptr - fp->_IO_read_base);
578 if (ignore (to_skip) != to_skip)
579 goto dumb;
580 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
581 goto resync;
583 #endif
585 #ifdef TODO
586 if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ())
588 if (!_IO_in_backup (fp))
589 _IO_switch_to_backup_area (fp);
590 gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
591 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
592 goto resync;
594 #endif
597 #ifdef TODO
598 _IO_unsave_markers (fp);
599 #endif
601 if (fp->_flags & _IO_NO_READS)
602 goto dumb;
604 /* Try to seek to a block boundary, to improve kernel page management. */
605 new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
606 delta = offset - new_offset;
607 if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
609 new_offset = offset;
610 delta = 0;
612 result = _IO_SYSSEEK (fp, new_offset, 0);
613 if (result < 0)
614 return EOF;
615 if (delta == 0)
616 count = 0;
617 else
619 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
620 (must_be_exact
621 ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
622 if (count < delta)
624 /* We weren't allowed to read, but try to seek the remainder. */
625 offset = count == EOF ? delta : delta-count;
626 dir = _IO_seek_cur;
627 goto dumb;
630 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
631 fp->_IO_buf_base + count);
632 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
633 fp->_old_offset = result + count;
634 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
635 return offset;
636 dumb:
638 _IO_unsave_markers (fp);
639 result = _IO_SYSSEEK (fp, offset, dir);
640 if (result != EOF)
642 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
643 fp->_old_offset = result;
644 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
645 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
647 return result;
649 resync:
650 /* We need to do it since it is possible that the file offset in
651 the kernel may be changed behind our back. It may happen when
652 we fopen a file and then do a fork. One process may access the
653 file and the kernel file offset will be changed. */
654 if (fp->_old_offset >= 0)
655 _IO_SYSSEEK (fp, fp->_old_offset, 0);
657 return offset;
660 _IO_ssize_t
661 attribute_compat_text_section
662 _IO_old_file_write (f, data, n)
663 _IO_FILE *f;
664 const void *data;
665 _IO_ssize_t n;
667 _IO_ssize_t to_do = n;
668 while (to_do > 0)
670 _IO_ssize_t count = write (f->_fileno, data, to_do);
671 if (count == EOF)
673 f->_flags |= _IO_ERR_SEEN;
674 break;
676 to_do -= count;
677 data = (void *) ((char *) data + count);
679 n -= to_do;
680 if (f->_old_offset >= 0)
681 f->_old_offset += n;
682 return n;
685 _IO_size_t
686 attribute_compat_text_section
687 _IO_old_file_xsputn (f, data, n)
688 _IO_FILE *f;
689 const void *data;
690 _IO_size_t n;
692 const char *s = (char *) data;
693 _IO_size_t to_do = n;
694 int must_flush = 0;
695 _IO_size_t count = 0;
697 if (n <= 0)
698 return 0;
699 /* This is an optimized implementation.
700 If the amount to be written straddles a block boundary
701 (or the filebuf is unbuffered), use sys_write directly. */
703 /* First figure out how much space is available in the buffer. */
704 if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
706 count = f->_IO_buf_end - f->_IO_write_ptr;
707 if (count >= n)
709 const char *p;
710 for (p = s + n; p > s; )
712 if (*--p == '\n')
714 count = p - s + 1;
715 must_flush = 1;
716 break;
721 else if (f->_IO_write_end > f->_IO_write_ptr)
722 count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
724 /* Then fill the buffer. */
725 if (count > 0)
727 if (count > to_do)
728 count = to_do;
729 if (count > 20)
731 #ifdef _LIBC
732 f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
733 #else
734 memcpy (f->_IO_write_ptr, s, count);
735 f->_IO_write_ptr += count;
736 #endif
737 s += count;
739 else
741 char *p = f->_IO_write_ptr;
742 int i = (int) count;
743 while (--i >= 0)
744 *p++ = *s++;
745 f->_IO_write_ptr = p;
747 to_do -= count;
749 if (to_do + must_flush > 0)
751 _IO_size_t block_size, do_write;
752 /* Next flush the (full) buffer. */
753 if (__overflow (f, EOF) == EOF)
754 return to_do == 0 ? EOF : n - to_do;
756 /* Try to maintain alignment: write a whole number of blocks.
757 dont_write is what gets left over. */
758 block_size = f->_IO_buf_end - f->_IO_buf_base;
759 do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
761 if (do_write)
763 count = old_do_write (f, s, do_write);
764 to_do -= count;
765 if (count < do_write)
766 return n - to_do;
769 /* Now write out the remainder. Normally, this will fit in the
770 buffer, but it's somewhat messier for line-buffered files,
771 so we let _IO_default_xsputn handle the general case. */
772 if (to_do)
773 to_do -= _IO_default_xsputn (f, s+do_write, to_do);
775 return n - to_do;
779 const struct _IO_jump_t _IO_old_file_jumps =
781 JUMP_INIT_DUMMY,
782 JUMP_INIT(finish, _IO_old_file_finish),
783 JUMP_INIT(overflow, _IO_old_file_overflow),
784 JUMP_INIT(underflow, _IO_old_file_underflow),
785 JUMP_INIT(uflow, _IO_default_uflow),
786 JUMP_INIT(pbackfail, _IO_default_pbackfail),
787 JUMP_INIT(xsputn, _IO_old_file_xsputn),
788 JUMP_INIT(xsgetn, _IO_default_xsgetn),
789 JUMP_INIT(seekoff, _IO_old_file_seekoff),
790 JUMP_INIT(seekpos, _IO_default_seekpos),
791 JUMP_INIT(setbuf, _IO_old_file_setbuf),
792 JUMP_INIT(sync, _IO_old_file_sync),
793 JUMP_INIT(doallocate, _IO_file_doallocate),
794 JUMP_INIT(read, _IO_file_read),
795 JUMP_INIT(write, _IO_old_file_write),
796 JUMP_INIT(seek, _IO_file_seek),
797 JUMP_INIT(close, _IO_file_close),
798 JUMP_INIT(stat, _IO_file_stat)
801 compat_symbol (libc, _IO_old_do_write, _IO_do_write, GLIBC_2_0);
802 compat_symbol (libc, _IO_old_file_attach, _IO_file_attach, GLIBC_2_0);
803 compat_symbol (libc, _IO_old_file_close_it, _IO_file_close_it, GLIBC_2_0);
804 compat_symbol (libc, _IO_old_file_finish, _IO_file_finish, GLIBC_2_0);
805 compat_symbol (libc, _IO_old_file_fopen, _IO_file_fopen, GLIBC_2_0);
806 compat_symbol (libc, _IO_old_file_init, _IO_file_init, GLIBC_2_0);
807 compat_symbol (libc, _IO_old_file_setbuf, _IO_file_setbuf, GLIBC_2_0);
808 compat_symbol (libc, _IO_old_file_sync, _IO_file_sync, GLIBC_2_0);
809 compat_symbol (libc, _IO_old_file_overflow, _IO_file_overflow, GLIBC_2_0);
810 compat_symbol (libc, _IO_old_file_seekoff, _IO_file_seekoff, GLIBC_2_0);
811 compat_symbol (libc, _IO_old_file_underflow, _IO_file_underflow, GLIBC_2_0);
812 compat_symbol (libc, _IO_old_file_write, _IO_file_write, GLIBC_2_0);
813 compat_symbol (libc, _IO_old_file_xsputn, _IO_file_xsputn, GLIBC_2_0);
815 #endif