Update.
[glibc.git] / libio / fileops.c
blobbe65d42fb2ac254f421748be5ee1d2f40bc3c42a
1 /* Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc.
2 This file is part of the GNU IO Library.
3 Written by Per Bothner <bothner@cygnus.com>.
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2, or (at
8 your option) any later version.
10 This library is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this library; see the file COPYING. If not, write to
17 the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
20 As a special exception, if you link this library with files
21 compiled with a GNU compiler to produce an executable, this does
22 not cause the resulting executable to be covered by the GNU General
23 Public License. This exception does not however invalidate any
24 other reasons why the executable file might be covered by the GNU
25 General Public License. */
28 #ifndef _POSIX_SOURCE
29 # define _POSIX_SOURCE
30 #endif
31 #include "libioP.h"
32 #include <fcntl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <string.h>
36 #include <errno.h>
37 #ifdef __STDC__
38 #include <stdlib.h>
39 #endif
40 #ifndef errno
41 extern int errno;
42 #endif
43 #ifndef __set_errno
44 # define __set_errno(Val) errno = (Val)
45 #endif
48 #ifdef _LIBC
49 # define open(Name, Flags, Prot) __open (Name, Flags, Prot)
50 # define close(FD) __close (FD)
51 # define lseek(FD, Offset, Whence) __lseek (FD, Offset, Whence)
52 # define read(FD, Buf, NBytes) __read (FD, Buf, NBytes)
53 # define write(FD, Buf, NBytes) __write (FD, Buf, NBytes)
54 #endif
56 /* An fstream can be in at most one of put mode, get mode, or putback mode.
57 Putback mode is a variant of get mode.
59 In a filebuf, there is only one current position, instead of two
60 separate get and put pointers. In get mode, the current position
61 is that of gptr(); in put mode that of pptr().
63 The position in the buffer that corresponds to the position
64 in external file system is normally _IO_read_end, except in putback
65 mode, when it is _IO_save_end.
66 If the field _fb._offset is >= 0, it gives the offset in
67 the file as a whole corresponding to eGptr(). (?)
69 PUT MODE:
70 If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
71 and _IO_read_base are equal to each other. These are usually equal
72 to _IO_buf_base, though not necessarily if we have switched from
73 get mode to put mode. (The reason is to maintain the invariant
74 that _IO_read_end corresponds to the external file position.)
75 _IO_write_base is non-NULL and usually equal to _IO_base_base.
76 We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
77 The un-flushed character are those between _IO_write_base and _IO_write_ptr.
79 GET MODE:
80 If a filebuf is in get or putback mode, eback() != egptr().
81 In get mode, the unread characters are between gptr() and egptr().
82 The OS file position corresponds to that of egptr().
84 PUTBACK MODE:
85 Putback mode is used to remember "excess" characters that have
86 been sputbackc'd in a separate putback buffer.
87 In putback mode, the get buffer points to the special putback buffer.
88 The unread characters are the characters between gptr() and egptr()
89 in the putback buffer, as well as the area between save_gptr()
90 and save_egptr(), which point into the original reserve buffer.
91 (The pointers save_gptr() and save_egptr() are the values
92 of gptr() and egptr() at the time putback mode was entered.)
93 The OS position corresponds to that of save_egptr().
95 LINE BUFFERED OUTPUT:
96 During line buffered output, _IO_write_base==base() && epptr()==base().
97 However, ptr() may be anywhere between base() and ebuf().
98 This forces a call to filebuf::overflow(int C) on every put.
99 If there is more space in the buffer, and C is not a '\n',
100 then C is inserted, and pptr() incremented.
102 UNBUFFERED STREAMS:
103 If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
106 #define CLOSED_FILEBUF_FLAGS \
107 (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
110 void
111 _IO_new_file_init (fp)
112 _IO_FILE *fp;
114 /* POSIX.1 allows another file handle to be used to change the position
115 of our file descriptor. Hence we actually don't know the actual
116 position before we do the first fseek (and until a following fflush). */
117 fp->_offset = _IO_pos_BAD;
118 fp->_IO_file_flags |= CLOSED_FILEBUF_FLAGS;
120 _IO_link_in(fp);
121 fp->_fileno = -1;
125 _IO_new_file_close_it (fp)
126 _IO_FILE *fp;
128 int write_status, close_status;
129 if (!_IO_file_is_open (fp))
130 return EOF;
132 write_status = _IO_do_flush (fp);
134 _IO_unsave_markers(fp);
136 close_status = _IO_SYSCLOSE (fp);
138 /* Free buffer. */
139 _IO_setb (fp, NULL, NULL, 0);
140 _IO_setg (fp, NULL, NULL, NULL);
141 _IO_setp (fp, NULL, NULL);
143 _IO_un_link (fp);
144 fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
145 fp->_fileno = EOF;
146 fp->_offset = _IO_pos_BAD;
148 return close_status ? close_status : write_status;
151 void
152 _IO_new_file_finish (fp, dummy)
153 _IO_FILE *fp;
154 int dummy;
156 if (_IO_file_is_open (fp))
158 _IO_do_flush (fp);
159 if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
160 _IO_SYSCLOSE (fp);
162 _IO_default_finish (fp, 0);
165 #if defined __GNUC__ && __GNUC__ >= 2
166 __inline__
167 #endif
168 _IO_FILE *
169 _IO_file_open (fp, filename, posix_mode, prot, read_write, is32not64)
170 _IO_FILE *fp;
171 const char *filename;
172 int posix_mode;
173 int prot;
174 int read_write;
175 int is32not64;
177 int fdesc;
178 #ifdef _G_OPEN64
179 fdesc = (is32not64
180 ? open (filename, posix_mode, prot)
181 : _G_OPEN64 (filename, posix_mode, prot));
182 #else
183 fdesc = open (filename, posix_mode, prot);
184 #endif
185 if (fdesc < 0)
186 return NULL;
187 fp->_fileno = fdesc;
188 _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
189 if (read_write & _IO_IS_APPENDING)
190 if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
191 == _IO_pos_BAD && errno != ESPIPE)
192 return NULL;
193 _IO_link_in (fp);
194 return fp;
197 _IO_FILE *
198 _IO_new_file_fopen (fp, filename, mode, is32not64)
199 _IO_FILE *fp;
200 const char *filename;
201 const char *mode;
202 int is32not64;
204 int oflags = 0, omode;
205 int read_write;
206 int oprot = 0666;
207 int i;
208 if (_IO_file_is_open (fp))
209 return 0;
210 switch (*mode)
212 case 'r':
213 omode = O_RDONLY;
214 read_write = _IO_NO_WRITES;
215 break;
216 case 'w':
217 omode = O_WRONLY;
218 oflags = O_CREAT|O_TRUNC;
219 read_write = _IO_NO_READS;
220 break;
221 case 'a':
222 omode = O_WRONLY;
223 oflags = O_CREAT|O_APPEND;
224 read_write = _IO_NO_READS|_IO_IS_APPENDING;
225 break;
226 default:
227 __set_errno (EINVAL);
228 return NULL;
230 for (i = 1; i < 4; ++i)
232 switch (*++mode)
234 case '\0':
235 break;
236 case '+':
237 omode = O_RDWR;
238 read_write &= _IO_IS_APPENDING;
239 continue;
240 case 'x':
241 oflags |= O_EXCL;
242 continue;
243 case 'b':
244 default:
245 /* Ignore. */
246 continue;
248 break;
251 return _IO_file_open (fp, filename, omode|oflags, oprot, read_write,
252 is32not64);
255 _IO_FILE *
256 _IO_new_file_attach (fp, fd)
257 _IO_FILE *fp;
258 int fd;
260 if (_IO_file_is_open (fp))
261 return NULL;
262 fp->_fileno = fd;
263 fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
264 fp->_flags |= _IO_DELETE_DONT_CLOSE;
265 /* Get the current position of the file. */
266 /* We have to do that since that may be junk. */
267 fp->_offset = _IO_pos_BAD;
268 if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
269 == _IO_pos_BAD && errno != ESPIPE)
270 return NULL;
271 return fp;
274 _IO_FILE *
275 _IO_new_file_setbuf (fp, p, len)
276 _IO_FILE *fp;
277 char *p;
278 _IO_ssize_t len;
280 if (_IO_default_setbuf (fp, p, len) == NULL)
281 return NULL;
283 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
284 = fp->_IO_buf_base;
285 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
287 return fp;
290 /* Write TO_DO bytes from DATA to FP.
291 Then mark FP as having empty buffers. */
294 _IO_new_do_write (fp, data, to_do)
295 _IO_FILE *fp;
296 const char *data;
297 _IO_size_t to_do;
299 _IO_size_t count;
300 if (to_do == 0)
301 return 0;
302 if (fp->_flags & _IO_IS_APPENDING)
303 /* On a system without a proper O_APPEND implementation,
304 you would need to sys_seek(0, SEEK_END) here, but is
305 is not needed nor desirable for Unix- or Posix-like systems.
306 Instead, just indicate that offset (before and after) is
307 unpredictable. */
308 fp->_offset = _IO_pos_BAD;
309 else if (fp->_IO_read_end != fp->_IO_write_base)
311 _IO_fpos64_t new_pos
312 = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
313 if (new_pos == _IO_pos_BAD)
314 return EOF;
315 fp->_offset = new_pos;
317 count = _IO_SYSWRITE (fp, data, to_do);
318 if (fp->_cur_column)
319 fp->_cur_column = _IO_adjust_column (fp->_cur_column - 1, data, to_do) + 1;
320 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
321 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
322 fp->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
323 ? fp->_IO_buf_base : fp->_IO_buf_end);
324 return count != to_do ? EOF : 0;
328 _IO_new_file_underflow (fp)
329 _IO_FILE *fp;
331 _IO_ssize_t count;
332 #if 0
333 /* SysV does not make this test; take it out for compatibility */
334 if (fp->_flags & _IO_EOF_SEEN)
335 return (EOF);
336 #endif
338 if (fp->_flags & _IO_NO_READS)
340 __set_errno (EBADF);
341 return EOF;
343 if (fp->_IO_read_ptr < fp->_IO_read_end)
344 return *(unsigned char *) fp->_IO_read_ptr;
346 if (fp->_IO_buf_base == NULL)
348 /* Maybe we already have a push back pointer. */
349 if (fp->_IO_save_base != NULL)
351 free (fp->_IO_save_base);
352 fp->_flags &= ~_IO_IN_BACKUP;
354 _IO_doallocbuf (fp);
357 /* Flush all line buffered files before reading. */
358 /* FIXME This can/should be moved to genops ?? */
359 if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
360 _IO_flush_all_linebuffered ();
362 _IO_switch_to_get_mode (fp);
364 /* This is very tricky. We have to adjust those
365 pointers before we call _IO_SYSREAD () since
366 we may longjump () out while waiting for
367 input. Those pointers may be screwed up. H.J. */
368 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
369 fp->_IO_read_end = fp->_IO_buf_base;
370 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
371 = fp->_IO_buf_base;
373 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
374 fp->_IO_buf_end - fp->_IO_buf_base);
375 if (count <= 0)
377 if (count == 0)
378 fp->_flags |= _IO_EOF_SEEN;
379 else
380 fp->_flags |= _IO_ERR_SEEN, count = 0;
382 fp->_IO_read_end += count;
383 if (count == 0)
384 return EOF;
385 if (fp->_offset != _IO_pos_BAD)
386 _IO_pos_adjust (fp->_offset, count);
387 return *(unsigned char *) fp->_IO_read_ptr;
391 _IO_new_file_overflow (f, ch)
392 _IO_FILE *f;
393 int ch;
395 if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
397 f->_flags |= _IO_ERR_SEEN;
398 __set_errno (EBADF);
399 return EOF;
401 /* If currently reading or no buffer allocated. */
402 if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
404 /* Allocate a buffer if needed. */
405 if (f->_IO_write_base == 0)
407 _IO_doallocbuf (f);
408 _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
410 /* Otherwise must be currently reading.
411 If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
412 logically slide the buffer forwards one block (by setting the
413 read pointers to all point at the beginning of the block). This
414 makes room for subsequent output.
415 Otherwise, set the read pointers to _IO_read_end (leaving that
416 alone, so it can continue to correspond to the external position). */
417 if (f->_IO_read_ptr == f->_IO_buf_end)
418 f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
419 f->_IO_write_ptr = f->_IO_read_ptr;
420 f->_IO_write_base = f->_IO_write_ptr;
421 f->_IO_write_end = f->_IO_buf_end;
422 f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
424 f->_flags |= _IO_CURRENTLY_PUTTING;
425 if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
426 f->_IO_write_end = f->_IO_write_ptr;
428 if (ch == EOF)
429 return _IO_do_flush (f);
430 if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
431 if (_IO_do_flush (f) == EOF)
432 return EOF;
433 *f->_IO_write_ptr++ = ch;
434 if ((f->_flags & _IO_UNBUFFERED)
435 || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
436 if (_IO_do_flush (f) == EOF)
437 return EOF;
438 return (unsigned char) ch;
442 _IO_new_file_sync (fp)
443 _IO_FILE *fp;
445 _IO_ssize_t delta;
446 int retval = 0;
448 /* char* ptr = cur_ptr(); */
449 if (fp->_IO_write_ptr > fp->_IO_write_base)
450 if (_IO_do_flush(fp)) return EOF;
451 delta = fp->_IO_read_ptr - fp->_IO_read_end;
452 if (delta != 0)
454 #ifdef TODO
455 if (_IO_in_backup (fp))
456 delta -= eGptr () - Gbase ();
457 #endif
458 _IO_off64_t new_pos = _IO_SYSSEEK (fp, delta, 1);
459 if (new_pos != (_IO_off64_t) EOF)
460 fp->_IO_read_end = fp->_IO_read_ptr;
461 #ifdef ESPIPE
462 else if (errno == ESPIPE)
463 ; /* Ignore error from unseekable devices. */
464 #endif
465 else
466 retval = EOF;
468 if (retval != EOF)
469 fp->_offset = _IO_pos_BAD;
470 /* FIXME: Cleanup - can this be shared? */
471 /* setg(base(), ptr, ptr); */
472 return retval;
475 _IO_fpos64_t
476 _IO_new_file_seekoff (fp, offset, dir, mode)
477 _IO_FILE *fp;
478 _IO_off64_t offset;
479 int dir;
480 int mode;
482 _IO_fpos64_t result;
483 _IO_off64_t delta, new_offset;
484 long count;
485 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
486 offset of the underlying file must be exact. */
487 int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
488 && fp->_IO_write_base == fp->_IO_write_ptr);
490 if (mode == 0)
491 dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
493 /* Flush unwritten characters.
494 (This may do an unneeded write if we seek within the buffer.
495 But to be able to switch to reading, we would need to set
496 egptr to ptr. That can't be done in the current design,
497 which assumes file_ptr() is eGptr. Anyway, since we probably
498 end up flushing when we close(), it doesn't make much difference.)
499 FIXME: simulate mem-papped files. */
501 if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
502 if (_IO_switch_to_get_mode (fp))
503 return EOF;
505 if (fp->_IO_buf_base == NULL)
507 /* It could be that we already have a pushback buffer. */
508 if (fp->_IO_read_base != NULL)
510 free (fp->_IO_read_base);
511 fp->_flags &= ~_IO_IN_BACKUP;
513 _IO_doallocbuf (fp);
514 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
515 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
518 switch (dir)
520 case _IO_seek_cur:
521 /* Adjust for read-ahead (bytes is buffer). */
522 offset -= fp->_IO_read_end - fp->_IO_read_ptr;
523 if (fp->_offset == _IO_pos_BAD)
524 goto dumb;
525 /* Make offset absolute, assuming current pointer is file_ptr(). */
526 offset += _IO_pos_as_off (fp->_offset);
528 dir = _IO_seek_set;
529 break;
530 case _IO_seek_set:
531 break;
532 case _IO_seek_end:
534 struct _G_stat64 st;
535 if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
537 offset += st.st_size;
538 dir = _IO_seek_set;
540 else
541 goto dumb;
544 /* At this point, dir==_IO_seek_set. */
546 /* If we are only interested in the current position we've found it now. */
547 if (mode == 0)
548 return offset;
550 /* If destination is within current buffer, optimize: */
551 if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
552 && !_IO_in_backup (fp))
554 /* Offset relative to start of main get area. */
555 _IO_fpos64_t rel_offset = (offset - fp->_offset
556 + (fp->_IO_read_end - fp->_IO_read_base));
557 if (rel_offset >= 0)
559 #if 0
560 if (_IO_in_backup (fp))
561 _IO_switch_to_main_get_area (fp);
562 #endif
563 if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
565 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
566 fp->_IO_read_end);
567 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
569 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
570 return offset;
573 #ifdef TODO
574 /* If we have streammarkers, seek forward by reading ahead. */
575 if (_IO_have_markers (fp))
577 int to_skip = rel_offset
578 - (fp->_IO_read_ptr - fp->_IO_read_base);
579 if (ignore (to_skip) != to_skip)
580 goto dumb;
581 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
582 return offset;
584 #endif
586 #ifdef TODO
587 if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ())
589 if (!_IO_in_backup (fp))
590 _IO_switch_to_backup_area (fp);
591 gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
592 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
593 return offset;
595 #endif
598 #ifdef TODO
599 _IO_unsave_markers (fp);
600 #endif
602 if (fp->_flags & _IO_NO_READS)
603 goto dumb;
605 /* Try to seek to a block boundary, to improve kernel page management. */
606 new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
607 delta = offset - new_offset;
608 if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
610 new_offset = offset;
611 delta = 0;
613 result = _IO_SYSSEEK (fp, new_offset, 0);
614 if (result < 0)
615 return EOF;
616 if (delta == 0)
617 count = 0;
618 else
620 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
621 (must_be_exact
622 ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
623 if (count < delta)
625 /* We weren't allowed to read, but try to seek the remainder. */
626 offset = count == EOF ? delta : delta-count;
627 dir = _IO_seek_cur;
628 goto dumb;
631 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
632 fp->_IO_buf_base + count);
633 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
634 fp->_offset = result + count;
635 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
636 return offset;
637 dumb:
639 _IO_unsave_markers (fp);
640 result = _IO_SYSSEEK (fp, offset, dir);
641 if (result != EOF)
643 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
644 fp->_offset = result;
645 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
646 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
648 return result;
651 _IO_ssize_t
652 _IO_file_read (fp, buf, size)
653 _IO_FILE *fp;
654 void *buf;
655 _IO_ssize_t size;
657 return read (fp->_fileno, buf, size);
660 _IO_fpos64_t
661 _IO_file_seek (fp, offset, dir)
662 _IO_FILE *fp;
663 _IO_off64_t offset;
664 int dir;
666 #ifdef _G_LSEEK64
667 return _G_LSEEK64 (fp->_fileno, offset, dir);
668 #else
669 return lseek (fp->_fileno, offset, dir);
670 #endif
674 _IO_file_stat (fp, st)
675 _IO_FILE *fp;
676 void *st;
678 #ifdef _G_FSTAT64
679 return _G_FSTAT64 (fp->_fileno, (struct _G_stat64 *) st);
680 #else
681 return fstat (fp->_fileno, (struct _G_stat64 *) st);
682 #endif
686 _IO_file_close (fp)
687 _IO_FILE *fp;
689 return close (fp->_fileno);
692 _IO_ssize_t
693 _IO_new_file_write (f, data, n)
694 _IO_FILE *f;
695 const void *data;
696 _IO_ssize_t n;
698 _IO_ssize_t to_do = n;
699 while (to_do > 0)
701 _IO_ssize_t count = write (f->_fileno, data, to_do);
702 if (count == EOF)
704 f->_flags |= _IO_ERR_SEEN;
705 break;
707 to_do -= count;
708 data = (void *) ((char *) data + count);
710 n -= to_do;
711 if (f->_offset >= 0)
712 f->_offset += n;
713 return n;
716 _IO_size_t
717 _IO_new_file_xsputn (f, data, n)
718 _IO_FILE *f;
719 const void *data;
720 _IO_size_t n;
722 register const char *s = (char *) data;
723 _IO_size_t to_do = n;
724 int must_flush = 0;
725 _IO_size_t count;
727 if (n <= 0)
728 return 0;
729 /* This is an optimized implementation.
730 If the amount to be written straddles a block boundary
731 (or the filebuf is unbuffered), use sys_write directly. */
733 /* First figure out how much space is available in the buffer. */
734 count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
735 if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
737 count = f->_IO_buf_end - f->_IO_write_ptr;
738 if (count >= n)
740 register const char *p;
741 for (p = s + n; p > s; )
743 if (*--p == '\n')
745 count = p - s + 1;
746 must_flush = 1;
747 break;
752 /* Then fill the buffer. */
753 if (count > 0)
755 if (count > to_do)
756 count = to_do;
757 if (count > 20)
759 #ifdef _LIBC
760 f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
761 #else
762 memcpy (f->_IO_write_ptr, s, count);
763 f->_IO_write_ptr += count;
764 #endif
765 s += count;
767 else
769 register char *p = f->_IO_write_ptr;
770 register int i = (int) count;
771 while (--i >= 0)
772 *p++ = *s++;
773 f->_IO_write_ptr = p;
775 to_do -= count;
777 if (to_do + must_flush > 0)
779 _IO_size_t block_size, dont_write;
780 /* Next flush the (full) buffer. */
781 if (__overflow (f, EOF) == EOF)
782 return n - to_do;
784 /* Try to maintain alignment: write a whole number of blocks.
785 dont_write is what gets left over. */
786 block_size = f->_IO_buf_end - f->_IO_buf_base;
787 dont_write = block_size >= 128 ? to_do % block_size : 0;
789 count = to_do - dont_write;
790 if (_IO_new_do_write (f, s, count) == EOF)
791 return n - to_do;
792 to_do = dont_write;
794 /* Now write out the remainder. Normally, this will fit in the
795 buffer, but it's somewhat messier for line-buffered files,
796 so we let _IO_default_xsputn handle the general case. */
797 if (dont_write)
798 to_do -= _IO_default_xsputn (f, s+count, dont_write);
800 return n - to_do;
803 _IO_size_t
804 _IO_file_xsgetn (fp, data, n)
805 _IO_FILE *fp;
806 void *data;
807 _IO_size_t n;
809 register _IO_size_t want, have;
810 register _IO_ssize_t count;
811 register char *s = data;
813 want = n;
815 while (want > 0)
817 have = fp->_IO_read_end - fp->_IO_read_ptr;
818 if (want <= have)
820 memcpy (s, fp->_IO_read_ptr, want);
821 fp->_IO_read_ptr += want;
822 want = 0;
824 else
826 if (have > 0)
828 #ifdef _LIBC
829 s = __mempcpy (s, fp->_IO_read_ptr, have);
830 #else
831 memcpy (s, fp->_IO_read_ptr, have);
832 s += have;
833 #endif
834 want -= have;
835 fp->_IO_read_ptr += have;
838 /* Check for backup and repeat */
839 if (_IO_in_backup (fp))
841 _IO_switch_to_main_get_area (fp);
842 continue;
845 /* If we now want less than a buffer, underflow and repeat
846 the copy. Otherwise, _IO_SYSREAD directly to
847 the user buffer. */
848 if (fp->_IO_buf_base && want < fp->_IO_buf_end - fp->_IO_buf_base)
850 if (__underflow (fp) == EOF)
851 break;
853 continue;
856 /* These must be set before the sysread as we might longjmp out
857 waiting for input. */
858 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
859 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
861 /* Try to maintain alignment: read a whole number of blocks. */
862 count = want;
863 if (fp->_IO_buf_base)
865 _IO_size_t block_size = fp->_IO_buf_end - fp->_IO_buf_base;
866 if (block_size >= 128)
867 count -= want % block_size;
870 count = _IO_SYSREAD (fp, s, count);
871 if (count <= 0)
873 if (count == 0)
874 fp->_flags |= _IO_EOF_SEEN;
875 else
876 fp->_flags |= _IO_ERR_SEEN;
878 break;
881 s += count;
882 want -= count;
883 if (fp->_offset != _IO_pos_BAD)
884 _IO_pos_adjust (fp->_offset, count);
888 return n - want;
891 struct _IO_jump_t _IO_file_jumps =
893 JUMP_INIT_DUMMY,
894 JUMP_INIT(finish, _IO_new_file_finish),
895 JUMP_INIT(overflow, _IO_new_file_overflow),
896 JUMP_INIT(underflow, _IO_new_file_underflow),
897 JUMP_INIT(uflow, _IO_default_uflow),
898 JUMP_INIT(pbackfail, _IO_default_pbackfail),
899 JUMP_INIT(xsputn, _IO_new_file_xsputn),
900 JUMP_INIT(xsgetn, _IO_file_xsgetn),
901 JUMP_INIT(seekoff, _IO_new_file_seekoff),
902 JUMP_INIT(seekpos, _IO_default_seekpos),
903 JUMP_INIT(setbuf, _IO_new_file_setbuf),
904 JUMP_INIT(sync, _IO_new_file_sync),
905 JUMP_INIT(doallocate, _IO_file_doallocate),
906 JUMP_INIT(read, _IO_file_read),
907 JUMP_INIT(write, _IO_new_file_write),
908 JUMP_INIT(seek, _IO_file_seek),
909 JUMP_INIT(close, _IO_file_close),
910 JUMP_INIT(stat, _IO_file_stat),
911 JUMP_INIT(showmanyc, _IO_default_showmanyc),
912 JUMP_INIT(imbue, _IO_default_imbue)
916 #if defined PIC && DO_VERSIONING
917 default_symbol_version (_IO_new_do_write, _IO_do_write, GLIBC_2.1);
918 default_symbol_version (_IO_new_file_attach, _IO_file_attach, GLIBC_2.1);
919 default_symbol_version (_IO_new_file_close_it, _IO_file_close_it, GLIBC_2.1);
920 default_symbol_version (_IO_new_file_finish, _IO_file_finish, GLIBC_2.1);
921 default_symbol_version (_IO_new_file_fopen, _IO_file_fopen, GLIBC_2.1);
922 default_symbol_version (_IO_new_file_init, _IO_file_init, GLIBC_2.1);
923 default_symbol_version (_IO_new_file_setbuf, _IO_file_setbuf, GLIBC_2.1);
924 default_symbol_version (_IO_new_file_sync, _IO_file_sync, GLIBC_2.1);
925 default_symbol_version (_IO_new_file_overflow, _IO_file_overflow, GLIBC_2.1);
926 default_symbol_version (_IO_new_file_seekoff, _IO_file_seekoff, GLIBC_2.1);
927 default_symbol_version (_IO_new_file_underflow, _IO_file_underflow, GLIBC_2.1);
928 default_symbol_version (_IO_new_file_write, _IO_file_write, GLIBC_2.1);
929 default_symbol_version (_IO_new_file_xsputn, _IO_file_xsputn, GLIBC_2.1);
930 #else
931 # ifdef strong_alias
932 strong_alias (_IO_new_do_write, _IO_do_write);
933 strong_alias (_IO_new_file_attach, _IO_file_attach);
934 strong_alias (_IO_new_file_close_it, _IO_file_close_it);
935 strong_alias (_IO_new_file_finish, _IO_file_finish);
936 strong_alias (_IO_new_file_fopen, _IO_file_fopen);
937 strong_alias (_IO_new_file_init, _IO_file_init);
938 strong_alias (_IO_new_file_setbuf, _IO_file_setbuf);
939 strong_alias (_IO_new_file_sync, _IO_file_sync);
940 strong_alias (_IO_new_file_overflow, _IO_file_overflow);
941 strong_alias (_IO_new_file_seekoff, _IO_file_seekoff);
942 strong_alias (_IO_new_file_underflow, _IO_file_underflow);
943 strong_alias (_IO_new_file_write, _IO_file_write);
944 strong_alias (_IO_new_file_xsputn, _IO_file_xsputn);
945 # endif
946 #endif