Update.
[glibc.git] / libio / oldfileops.c
blob8998ee9b0d0042f68346273937238d3ae4629f2a
1 /* Copyright (C) 1993,95,97,98,99,2000,2002 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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA.
20 As a special exception, if you link the code in this file with
21 files compiled with a GNU compiler to produce an executable,
22 that does not cause the resulting executable to be covered by
23 the GNU Lesser General Public License. This exception does not
24 however invalidate any other reasons why the executable file
25 might be covered by the GNU Lesser General Public License.
26 This exception applies to code released by its copyright holders
27 in files containing the exception. */
29 /* This is a compatibility file. If we don't build the libc with
30 versioning don't compile this file. */
31 #include <shlib-compat.h>
32 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
34 #ifndef _POSIX_SOURCE
35 # define _POSIX_SOURCE
36 #endif
37 #define _IO_USE_OLD_IO_FILE
38 #include "libioP.h"
39 #include <fcntl.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <string.h>
43 #include <errno.h>
44 #ifdef __STDC__
45 #include <stdlib.h>
46 #endif
47 #ifndef errno
48 extern int errno;
49 #endif
50 #ifndef __set_errno
51 # define __set_errno(Val) errno = (Val)
52 #endif
55 #ifdef _LIBC
56 # define open(Name, Flags, Prot) __open (Name, Flags, Prot)
57 # define close(FD) __close (FD)
58 # define lseek(FD, Offset, Whence) __lseek (FD, Offset, Whence)
59 # define read(FD, Buf, NBytes) __read (FD, Buf, NBytes)
60 # define write(FD, Buf, NBytes) __write (FD, Buf, NBytes)
61 #endif
63 /* An fstream can be in at most one of put mode, get mode, or putback mode.
64 Putback mode is a variant of get mode.
66 In a filebuf, there is only one current position, instead of two
67 separate get and put pointers. In get mode, the current position
68 is that of gptr(); in put mode that of pptr().
70 The position in the buffer that corresponds to the position
71 in external file system is normally _IO_read_end, except in putback
72 mode, when it is _IO_save_end.
73 If the field _fb._offset is >= 0, it gives the offset in
74 the file as a whole corresponding to eGptr(). (?)
76 PUT MODE:
77 If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
78 and _IO_read_base are equal to each other. These are usually equal
79 to _IO_buf_base, though not necessarily if we have switched from
80 get mode to put mode. (The reason is to maintain the invariant
81 that _IO_read_end corresponds to the external file position.)
82 _IO_write_base is non-NULL and usually equal to _IO_base_base.
83 We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
84 The un-flushed character are those between _IO_write_base and _IO_write_ptr.
86 GET MODE:
87 If a filebuf is in get or putback mode, eback() != egptr().
88 In get mode, the unread characters are between gptr() and egptr().
89 The OS file position corresponds to that of egptr().
91 PUTBACK MODE:
92 Putback mode is used to remember "excess" characters that have
93 been sputbackc'd in a separate putback buffer.
94 In putback mode, the get buffer points to the special putback buffer.
95 The unread characters are the characters between gptr() and egptr()
96 in the putback buffer, as well as the area between save_gptr()
97 and save_egptr(), which point into the original reserve buffer.
98 (The pointers save_gptr() and save_egptr() are the values
99 of gptr() and egptr() at the time putback mode was entered.)
100 The OS position corresponds to that of save_egptr().
102 LINE BUFFERED OUTPUT:
103 During line buffered output, _IO_write_base==base() && epptr()==base().
104 However, ptr() may be anywhere between base() and ebuf().
105 This forces a call to filebuf::overflow(int C) on every put.
106 If there is more space in the buffer, and C is not a '\n',
107 then C is inserted, and pptr() incremented.
109 UNBUFFERED STREAMS:
110 If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
113 #define CLOSED_FILEBUF_FLAGS \
114 (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
117 void
118 _IO_old_file_init (fp)
119 struct _IO_FILE_plus *fp;
121 /* POSIX.1 allows another file handle to be used to change the position
122 of our file descriptor. Hence we actually don't know the actual
123 position before we do the first fseek (and until a following fflush). */
124 fp->file._old_offset = _IO_pos_BAD;
125 fp->file._IO_file_flags |= CLOSED_FILEBUF_FLAGS;
127 INTUSE(_IO_link_in) (fp);
128 fp->file._vtable_offset = ((int) sizeof (struct _IO_FILE)
129 - (int) sizeof (struct _IO_FILE_complete));
130 fp->file._fileno = -1;
134 _IO_old_file_close_it (fp)
135 _IO_FILE *fp;
137 int write_status, close_status;
138 if (!_IO_file_is_open (fp))
139 return EOF;
141 write_status = _IO_old_do_flush (fp);
143 INTUSE(_IO_unsave_markers) (fp);
145 close_status = _IO_SYSCLOSE (fp);
147 /* Free buffer. */
148 INTUSE(_IO_setb) (fp, NULL, NULL, 0);
149 _IO_setg (fp, NULL, NULL, NULL);
150 _IO_setp (fp, NULL, NULL);
152 INTUSE(_IO_un_link) ((struct _IO_FILE_plus *) fp);
153 fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
154 fp->_fileno = -1;
155 fp->_old_offset = _IO_pos_BAD;
157 return close_status ? close_status : write_status;
160 void
161 _IO_old_file_finish (fp, dummy)
162 _IO_FILE *fp;
163 int dummy;
165 if (_IO_file_is_open (fp))
167 _IO_old_do_flush (fp);
168 if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
169 _IO_SYSCLOSE (fp);
171 INTUSE(_IO_default_finish) (fp, 0);
174 _IO_FILE *
175 _IO_old_file_fopen (fp, filename, mode)
176 _IO_FILE *fp;
177 const char *filename;
178 const char *mode;
180 int oflags = 0, omode;
181 int read_write, fdesc;
182 int oprot = 0666;
183 if (_IO_file_is_open (fp))
184 return 0;
185 switch (*mode++)
187 case 'r':
188 omode = O_RDONLY;
189 read_write = _IO_NO_WRITES;
190 break;
191 case 'w':
192 omode = O_WRONLY;
193 oflags = O_CREAT|O_TRUNC;
194 read_write = _IO_NO_READS;
195 break;
196 case 'a':
197 omode = O_WRONLY;
198 oflags = O_CREAT|O_APPEND;
199 read_write = _IO_NO_READS|_IO_IS_APPENDING;
200 break;
201 default:
202 __set_errno (EINVAL);
203 return NULL;
205 if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+'))
207 omode = O_RDWR;
208 read_write &= _IO_IS_APPENDING;
210 fdesc = open (filename, omode|oflags, oprot);
211 if (fdesc < 0)
212 return NULL;
213 fp->_fileno = fdesc;
214 _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
215 if (read_write & _IO_IS_APPENDING)
216 if (_IO_SEEKOFF (fp, (_IO_off_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
217 == _IO_pos_BAD && errno != ESPIPE)
218 return NULL;
219 INTUSE(_IO_link_in) ((struct _IO_FILE_plus *) fp);
220 return fp;
223 _IO_FILE *
224 _IO_old_file_attach (fp, fd)
225 _IO_FILE *fp;
226 int fd;
228 if (_IO_file_is_open (fp))
229 return NULL;
230 fp->_fileno = fd;
231 fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
232 fp->_flags |= _IO_DELETE_DONT_CLOSE;
233 /* Get the current position of the file. */
234 /* We have to do that since that may be junk. */
235 fp->_old_offset = _IO_pos_BAD;
236 if (_IO_SEEKOFF (fp, (_IO_off_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
237 == _IO_pos_BAD && errno != ESPIPE)
238 return NULL;
239 return fp;
242 _IO_FILE *
243 _IO_old_file_setbuf (fp, p, len)
244 _IO_FILE *fp;
245 char *p;
246 _IO_ssize_t len;
248 if (_IO_default_setbuf (fp, p, len) == NULL)
249 return NULL;
251 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
252 = fp->_IO_buf_base;
253 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
255 return fp;
258 static int old_do_write __P ((_IO_FILE *, const char *, _IO_size_t));
260 /* Write TO_DO bytes from DATA to FP.
261 Then mark FP as having empty buffers. */
264 _IO_old_do_write (fp, data, to_do)
265 _IO_FILE *fp;
266 const char *data;
267 _IO_size_t to_do;
269 return (to_do == 0 || old_do_write (fp, data, to_do) == to_do)
270 ? 0 : EOF;
273 static
275 old_do_write (fp, data, to_do)
276 _IO_FILE *fp;
277 const char *data;
278 _IO_size_t to_do;
280 _IO_size_t count;
281 if (fp->_flags & _IO_IS_APPENDING)
282 /* On a system without a proper O_APPEND implementation,
283 you would need to sys_seek(0, SEEK_END) here, but is
284 is not needed nor desirable for Unix- or Posix-like systems.
285 Instead, just indicate that offset (before and after) is
286 unpredictable. */
287 fp->_old_offset = _IO_pos_BAD;
288 else if (fp->_IO_read_end != fp->_IO_write_base)
290 _IO_off_t new_pos
291 = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
292 if (new_pos == _IO_pos_BAD)
293 return 0;
294 fp->_old_offset = new_pos;
296 count = _IO_SYSWRITE (fp, data, to_do);
297 if (fp->_cur_column && count)
298 fp->_cur_column = INTUSE(_IO_adjust_column) (fp->_cur_column - 1, data,
299 count) + 1;
300 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
301 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
302 fp->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
303 ? fp->_IO_buf_base : fp->_IO_buf_end);
304 return count;
308 _IO_old_file_underflow (fp)
309 _IO_FILE *fp;
311 _IO_ssize_t count;
312 #if 0
313 /* SysV does not make this test; take it out for compatibility */
314 if (fp->_flags & _IO_EOF_SEEN)
315 return (EOF);
316 #endif
318 if (fp->_flags & _IO_NO_READS)
320 fp->_flags |= _IO_ERR_SEEN;
321 __set_errno (EBADF);
322 return EOF;
324 if (fp->_IO_read_ptr < fp->_IO_read_end)
325 return *(unsigned char *) fp->_IO_read_ptr;
327 if (fp->_IO_buf_base == NULL)
329 /* Maybe we already have a push back pointer. */
330 if (fp->_IO_save_base != NULL)
332 free (fp->_IO_save_base);
333 fp->_flags &= ~_IO_IN_BACKUP;
335 INTUSE(_IO_doallocbuf) (fp);
338 /* Flush all line buffered files before reading. */
339 /* FIXME This can/should be moved to genops ?? */
340 if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
341 INTUSE(_IO_flush_all_linebuffered) ();
343 INTUSE(_IO_switch_to_get_mode) (fp);
345 /* This is very tricky. We have to adjust those
346 pointers before we call _IO_SYSREAD () since
347 we may longjump () out while waiting for
348 input. Those pointers may be screwed up. H.J. */
349 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
350 fp->_IO_read_end = fp->_IO_buf_base;
351 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
352 = fp->_IO_buf_base;
354 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
355 fp->_IO_buf_end - fp->_IO_buf_base);
356 if (count <= 0)
358 if (count == 0)
359 fp->_flags |= _IO_EOF_SEEN;
360 else
361 fp->_flags |= _IO_ERR_SEEN, count = 0;
363 fp->_IO_read_end += count;
364 if (count == 0)
365 return EOF;
366 if (fp->_old_offset != _IO_pos_BAD)
367 _IO_pos_adjust (fp->_old_offset, count);
368 return *(unsigned char *) fp->_IO_read_ptr;
372 _IO_old_file_overflow (f, ch)
373 _IO_FILE *f;
374 int ch;
376 if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
378 f->_flags |= _IO_ERR_SEEN;
379 __set_errno (EBADF);
380 return EOF;
382 /* If currently reading or no buffer allocated. */
383 if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
385 /* Allocate a buffer if needed. */
386 if (f->_IO_write_base == 0)
388 INTUSE(_IO_doallocbuf) (f);
389 _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
391 /* Otherwise must be currently reading.
392 If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
393 logically slide the buffer forwards one block (by setting the
394 read pointers to all point at the beginning of the block). This
395 makes room for subsequent output.
396 Otherwise, set the read pointers to _IO_read_end (leaving that
397 alone, so it can continue to correspond to the external position). */
398 if (f->_IO_read_ptr == f->_IO_buf_end)
399 f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
400 f->_IO_write_ptr = f->_IO_read_ptr;
401 f->_IO_write_base = f->_IO_write_ptr;
402 f->_IO_write_end = f->_IO_buf_end;
403 f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
405 if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
406 f->_IO_write_end = f->_IO_write_ptr;
407 f->_flags |= _IO_CURRENTLY_PUTTING;
409 if (ch == EOF)
410 return _IO_old_do_flush (f);
411 if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
412 if (_IO_old_do_flush (f) == EOF)
413 return EOF;
414 *f->_IO_write_ptr++ = ch;
415 if ((f->_flags & _IO_UNBUFFERED)
416 || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
417 if (_IO_old_do_flush (f) == EOF)
418 return EOF;
419 return (unsigned char) ch;
423 _IO_old_file_sync (fp)
424 _IO_FILE *fp;
426 _IO_ssize_t delta;
427 int retval = 0;
429 /* char* ptr = cur_ptr(); */
430 if (fp->_IO_write_ptr > fp->_IO_write_base)
431 if (_IO_old_do_flush(fp)) return EOF;
432 delta = fp->_IO_read_ptr - fp->_IO_read_end;
433 if (delta != 0)
435 #ifdef TODO
436 if (_IO_in_backup (fp))
437 delta -= eGptr () - Gbase ();
438 #endif
439 _IO_off_t new_pos = _IO_SYSSEEK (fp, delta, 1);
440 if (new_pos != (_IO_off_t) EOF)
441 fp->_IO_read_end = fp->_IO_read_ptr;
442 #ifdef ESPIPE
443 else if (errno == ESPIPE)
444 ; /* Ignore error from unseekable devices. */
445 #endif
446 else
447 retval = EOF;
449 if (retval != EOF)
450 fp->_old_offset = _IO_pos_BAD;
451 /* FIXME: Cleanup - can this be shared? */
452 /* setg(base(), ptr, ptr); */
453 return retval;
456 _IO_off64_t
457 _IO_old_file_seekoff (fp, offset, dir, mode)
458 _IO_FILE *fp;
459 _IO_off64_t offset;
460 int dir;
461 int mode;
463 _IO_off_t result;
464 _IO_off64_t delta, new_offset;
465 long count;
466 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
467 offset of the underlying file must be exact. */
468 int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
469 && fp->_IO_write_base == fp->_IO_write_ptr);
471 if (mode == 0)
472 dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
474 /* Flush unwritten characters.
475 (This may do an unneeded write if we seek within the buffer.
476 But to be able to switch to reading, we would need to set
477 egptr to ptr. That can't be done in the current design,
478 which assumes file_ptr() is eGptr. Anyway, since we probably
479 end up flushing when we close(), it doesn't make much difference.)
480 FIXME: simulate mem-papped files. */
482 if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
483 if (INTUSE(_IO_switch_to_get_mode) (fp))
484 return EOF;
486 if (fp->_IO_buf_base == NULL)
488 /* It could be that we already have a pushback buffer. */
489 if (fp->_IO_read_base != NULL)
491 free (fp->_IO_read_base);
492 fp->_flags &= ~_IO_IN_BACKUP;
494 INTUSE(_IO_doallocbuf) (fp);
495 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
496 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
499 switch (dir)
501 case _IO_seek_cur:
502 /* Adjust for read-ahead (bytes is buffer). */
503 offset -= fp->_IO_read_end - fp->_IO_read_ptr;
504 if (fp->_old_offset == _IO_pos_BAD)
505 goto dumb;
506 /* Make offset absolute, assuming current pointer is file_ptr(). */
507 offset += fp->_old_offset;
509 dir = _IO_seek_set;
510 break;
511 case _IO_seek_set:
512 break;
513 case _IO_seek_end:
515 struct _G_stat64 st;
516 if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
518 offset += st.st_size;
519 dir = _IO_seek_set;
521 else
522 goto dumb;
525 /* At this point, dir==_IO_seek_set. */
527 /* If we are only interested in the current position we've found it now. */
528 if (mode == 0)
529 return offset;
531 /* If destination is within current buffer, optimize: */
532 if (fp->_old_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
533 && !_IO_in_backup (fp))
535 /* Offset relative to start of main get area. */
536 _IO_off_t rel_offset = (offset - fp->_old_offset
537 + (fp->_IO_read_end - fp->_IO_read_base));
538 if (rel_offset >= 0)
540 #if 0
541 if (_IO_in_backup (fp))
542 _IO_switch_to_main_get_area (fp);
543 #endif
544 if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
546 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
547 fp->_IO_read_end);
548 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
550 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
551 goto resync;
554 #ifdef TODO
555 /* If we have streammarkers, seek forward by reading ahead. */
556 if (_IO_have_markers (fp))
558 int to_skip = rel_offset
559 - (fp->_IO_read_ptr - fp->_IO_read_base);
560 if (ignore (to_skip) != to_skip)
561 goto dumb;
562 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
563 goto resync;
565 #endif
567 #ifdef TODO
568 if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ())
570 if (!_IO_in_backup (fp))
571 _IO_switch_to_backup_area (fp);
572 gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
573 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
574 goto resync;
576 #endif
579 #ifdef TODO
580 INTUSE(_IO_unsave_markers) (fp);
581 #endif
583 if (fp->_flags & _IO_NO_READS)
584 goto dumb;
586 /* Try to seek to a block boundary, to improve kernel page management. */
587 new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
588 delta = offset - new_offset;
589 if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
591 new_offset = offset;
592 delta = 0;
594 result = _IO_SYSSEEK (fp, new_offset, 0);
595 if (result < 0)
596 return EOF;
597 if (delta == 0)
598 count = 0;
599 else
601 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
602 (must_be_exact
603 ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
604 if (count < delta)
606 /* We weren't allowed to read, but try to seek the remainder. */
607 offset = count == EOF ? delta : delta-count;
608 dir = _IO_seek_cur;
609 goto dumb;
612 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
613 fp->_IO_buf_base + count);
614 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
615 fp->_old_offset = result + count;
616 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
617 return offset;
618 dumb:
620 INTUSE(_IO_unsave_markers) (fp);
621 result = _IO_SYSSEEK (fp, offset, dir);
622 if (result != EOF)
624 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
625 fp->_old_offset = result;
626 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
627 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
629 return result;
631 resync:
632 /* We need to do it since it is possible that the file offset in
633 the kernel may be changed behind our back. It may happen when
634 we fopen a file and then do a fork. One process may access the
635 the file and the kernel file offset will be changed. */
636 if (fp->_old_offset >= 0)
637 _IO_SYSSEEK (fp, fp->_old_offset, 0);
639 return offset;
642 _IO_ssize_t
643 _IO_old_file_write (f, data, n)
644 _IO_FILE *f;
645 const void *data;
646 _IO_ssize_t n;
648 _IO_ssize_t to_do = n;
649 while (to_do > 0)
651 _IO_ssize_t count = write (f->_fileno, data, to_do);
652 if (count == EOF)
654 f->_flags |= _IO_ERR_SEEN;
655 break;
657 to_do -= count;
658 data = (void *) ((char *) data + count);
660 n -= to_do;
661 if (f->_old_offset >= 0)
662 f->_old_offset += n;
663 return n;
666 _IO_size_t
667 _IO_old_file_xsputn (f, data, n)
668 _IO_FILE *f;
669 const void *data;
670 _IO_size_t n;
672 register const char *s = (char *) data;
673 _IO_size_t to_do = n;
674 int must_flush = 0;
675 _IO_size_t count;
677 if (n <= 0)
678 return 0;
679 /* This is an optimized implementation.
680 If the amount to be written straddles a block boundary
681 (or the filebuf is unbuffered), use sys_write directly. */
683 /* First figure out how much space is available in the buffer. */
684 count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
685 if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
687 count = f->_IO_buf_end - f->_IO_write_ptr;
688 if (count >= n)
690 register const char *p;
691 for (p = s + n; p > s; )
693 if (*--p == '\n')
695 count = p - s + 1;
696 must_flush = 1;
697 break;
702 /* Then fill the buffer. */
703 if (count > 0)
705 if (count > to_do)
706 count = to_do;
707 if (count > 20)
709 #ifdef _LIBC
710 f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
711 #else
712 memcpy (f->_IO_write_ptr, s, count);
713 f->_IO_write_ptr += count;
714 #endif
715 s += count;
717 else
719 register char *p = f->_IO_write_ptr;
720 register int i = (int) count;
721 while (--i >= 0)
722 *p++ = *s++;
723 f->_IO_write_ptr = p;
725 to_do -= count;
727 if (to_do + must_flush > 0)
729 _IO_size_t block_size, do_write;
730 /* Next flush the (full) buffer. */
731 if (__overflow (f, EOF) == EOF)
732 return n - to_do;
734 /* Try to maintain alignment: write a whole number of blocks.
735 dont_write is what gets left over. */
736 block_size = f->_IO_buf_end - f->_IO_buf_base;
737 do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
739 if (do_write)
741 count = old_do_write (f, s, do_write);
742 to_do -= count;
743 if (count < do_write)
744 return n - to_do;
747 /* Now write out the remainder. Normally, this will fit in the
748 buffer, but it's somewhat messier for line-buffered files,
749 so we let _IO_default_xsputn handle the general case. */
750 if (to_do)
751 to_do -= INTUSE(_IO_default_xsputn) (f, s+do_write, to_do);
753 return n - to_do;
757 struct _IO_jump_t _IO_old_file_jumps =
759 JUMP_INIT_DUMMY,
760 JUMP_INIT(finish, _IO_old_file_finish),
761 JUMP_INIT(overflow, _IO_old_file_overflow),
762 JUMP_INIT(underflow, _IO_old_file_underflow),
763 JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
764 JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
765 JUMP_INIT(xsputn, _IO_old_file_xsputn),
766 JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
767 JUMP_INIT(seekoff, _IO_old_file_seekoff),
768 JUMP_INIT(seekpos, _IO_default_seekpos),
769 JUMP_INIT(setbuf, _IO_old_file_setbuf),
770 JUMP_INIT(sync, _IO_old_file_sync),
771 JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
772 JUMP_INIT(read, INTUSE(_IO_file_read)),
773 JUMP_INIT(write, _IO_old_file_write),
774 JUMP_INIT(seek, INTUSE(_IO_file_seek)),
775 JUMP_INIT(close, INTUSE(_IO_file_close)),
776 JUMP_INIT(stat, INTUSE(_IO_file_stat))
779 compat_symbol (libc, _IO_old_do_write, _IO_do_write, GLIBC_2_0);
780 compat_symbol (libc, _IO_old_file_attach, _IO_file_attach, GLIBC_2_0);
781 compat_symbol (libc, _IO_old_file_close_it, _IO_file_close_it, GLIBC_2_0);
782 compat_symbol (libc, _IO_old_file_finish, _IO_file_finish, GLIBC_2_0);
783 compat_symbol (libc, _IO_old_file_fopen, _IO_file_fopen, GLIBC_2_0);
784 compat_symbol (libc, _IO_old_file_init, _IO_file_init, GLIBC_2_0);
785 compat_symbol (libc, _IO_old_file_setbuf, _IO_file_setbuf, GLIBC_2_0);
786 compat_symbol (libc, _IO_old_file_sync, _IO_file_sync, GLIBC_2_0);
787 compat_symbol (libc, _IO_old_file_overflow, _IO_file_overflow, GLIBC_2_0);
788 compat_symbol (libc, _IO_old_file_seekoff, _IO_file_seekoff, GLIBC_2_0);
789 compat_symbol (libc, _IO_old_file_underflow, _IO_file_underflow, GLIBC_2_0);
790 compat_symbol (libc, _IO_old_file_write, _IO_file_write, GLIBC_2_0);
791 compat_symbol (libc, _IO_old_file_xsputn, _IO_file_xsputn, GLIBC_2_0);
793 #endif