2 Copyright (C) 1993, 1995 Free Software Foundation
4 This file is part of the GNU IO Library. This library is free
5 software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option)
10 This 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
13 GNU 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 the Free
17 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 As a special exception, if you link this library with files
20 compiled with a GNU compiler to produce an executable, this does not cause
21 the resulting executable to be covered by the GNU General Public License.
22 This exception does not however invalidate any other reasons why
23 the executable file might be covered by the GNU General Public License. */
25 /* written by Per Bothner (bothner@cygnus.com) */
30 #include <sys/types.h>
38 /* An fstream can be in at most one of put mode, get mode, or putback mode.
39 Putback mode is a variant of get mode.
41 In a filebuf, there is only one current position, instead of two
42 separate get and put pointers. In get mode, the current posistion
43 is that of gptr(); in put mode that of pptr().
45 The position in the buffer that corresponds to the position
46 in external file system is normally _IO_read_end, except in putback
47 mode, when it is _IO_save_end.
48 If the field _fb._offset is >= 0, it gives the offset in
49 the file as a whole corresponding to eGptr(). (?)
52 If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
53 and _IO_read_base are equal to each other. These are usually equal
54 to _IO_buf_base, though not necessarily if we have switched from
55 get mode to put mode. (The reason is to maintain the invariant
56 that _IO_read_end corresponds to the external file position.)
57 _IO_write_base is non-NULL and usually equal to _IO_base_base.
58 We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
59 The un-flushed character are those between _IO_write_base and _IO_write_ptr.
62 If a filebuf is in get or putback mode, eback() != egptr().
63 In get mode, the unread characters are between gptr() and egptr().
64 The OS file position corresponds to that of egptr().
67 Putback mode is used to remember "excess" characters that have
68 been sputbackc'd in a separate putback buffer.
69 In putback mode, the get buffer points to the special putback buffer.
70 The unread characters are the characters between gptr() and egptr()
71 in the putback buffer, as well as the area between save_gptr()
72 and save_egptr(), which point into the original reserve buffer.
73 (The pointers save_gptr() and save_egptr() are the values
74 of gptr() and egptr() at the time putback mode was entered.)
75 The OS position corresponds to that of save_egptr().
78 During line buffered output, _IO_write_base==base() && epptr()==base().
79 However, ptr() may be anywhere between base() and ebuf().
80 This forces a call to filebuf::overflow(int C) on every put.
81 If there is more space in the buffer, and C is not a '\n',
82 then C is inserted, and pptr() incremented.
85 If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
88 #define CLOSED_FILEBUF_FLAGS \
89 (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
93 DEFUN(_IO_file_init, (fp),
94 register _IO_FILE *fp)
96 /* POSIX.1 allows another file handle to be used to change the position
97 of our file descriptor. Hence we actually don't know the actual
98 position before we do the first fseek (and until a following fflush). */
99 fp->_offset = _IO_pos_BAD;
100 fp->_IO_file_flags |= CLOSED_FILEBUF_FLAGS;
107 DEFUN(_IO_file_close_it, (fp),
108 register _IO_FILE* fp)
110 int write_status, close_status;
111 if (!_IO_file_is_open(fp))
114 write_status = _IO_do_flush (fp);
116 _IO_unsave_markers(fp);
118 close_status = _IO_SYSCLOSE (fp);
121 _IO_setb(fp, NULL, NULL, 0);
122 _IO_setg(fp, NULL, NULL, NULL);
123 _IO_setp(fp, NULL, NULL);
126 fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
128 fp->_offset = _IO_pos_BAD;
130 return close_status ? close_status : write_status;
134 DEFUN(_IO_file_finish, (fp),
135 register _IO_FILE* fp)
137 if (_IO_file_is_open(fp))
140 if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
143 _IO_default_finish(fp);
147 DEFUN(_IO_file_fopen, (fp, filename, mode),
148 register _IO_FILE *fp AND const char *filename AND const char *mode)
150 int oflags = 0, omode;
151 int read_write, fdesc;
153 if (_IO_file_is_open (fp))
158 read_write = _IO_NO_WRITES;
162 oflags = O_CREAT|O_TRUNC;
163 read_write = _IO_NO_READS;
167 oflags = O_CREAT|O_APPEND;
168 read_write = _IO_NO_READS|_IO_IS_APPENDING;
174 if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+')) {
176 read_write &= _IO_IS_APPENDING;
178 fdesc = open(filename, omode|oflags, oprot);
182 _IO_mask_flags(fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
183 if (read_write & _IO_IS_APPENDING)
184 if (_IO_SEEKOFF (fp, (_IO_off_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
192 DEFUN(_IO_file_attach, (fp, fd),
193 _IO_FILE *fp AND int fd)
195 if (_IO_file_is_open(fp))
198 fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
199 fp->_flags |= _IO_DELETE_DONT_CLOSE;
200 fp->_offset = _IO_pos_BAD;
205 DEFUN(_IO_file_setbuf, (fp, p, len),
206 register _IO_FILE *fp AND char* p AND _IO_ssize_t len)
208 if (_IO_default_setbuf(fp, p, len) == NULL)
211 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
213 _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
218 /* Write TO_DO bytes from DATA to FP.
219 Then mark FP as having empty buffers. */
222 DEFUN(_IO_do_write, (fp, data, to_do),
223 register _IO_FILE *fp AND const char* data AND _IO_size_t to_do)
230 if (fp->_flags & _IO_IS_APPENDING)
231 /* On a system without a proper O_APPEND implementation,
232 you would need to sys_seek(0, SEEK_END) here, but is
233 is not needed nor desirable for Unix- or Posix-like systems.
234 Instead, just indicate that offset (before and after) is
236 fp->_offset = _IO_pos_BAD;
237 else if (fp->_IO_read_end != fp->_IO_write_base)
240 = _IO_SYSSEEK(fp, fp->_IO_write_base - fp->_IO_read_end, 1);
241 if (new_pos == _IO_pos_BAD)
243 fp->_offset = new_pos;
245 count = _IO_SYSWRITE (fp, data, to_do);
248 = _IO_adjust_column (fp->_cur_column - 1, data, to_do) + 1;
250 _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
251 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
252 fp->_IO_write_end = (fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED)) ? fp->_IO_buf_base
254 return count != to_do ? EOF : 0;
258 DEFUN(_IO_file_underflow, (fp),
259 register _IO_FILE *fp)
263 /* SysV does not make this test; take it out for compatibility */
264 if (fp->_flags & _IO_EOF_SEEN)
268 if (fp->_flags & _IO_NO_READS)
270 if (fp->_IO_read_ptr < fp->_IO_read_end)
271 return *(unsigned char*)fp->_IO_read_ptr;
273 if (fp->_IO_buf_base == NULL)
276 /* Flush all line buffered files before reading. */
277 /* FIXME This can/should be moved to genops ?? */
278 if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
279 _IO_flush_all_linebuffered();
281 _IO_switch_to_get_mode(fp);
283 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
284 fp->_IO_buf_end - fp->_IO_buf_base);
288 fp->_flags |= _IO_EOF_SEEN;
290 fp->_flags |= _IO_ERR_SEEN, count = 0;
292 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
293 fp->_IO_read_end = fp->_IO_buf_base + count;
294 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
298 if (fp->_offset != _IO_pos_BAD)
299 _IO_pos_adjust(fp->_offset, count);
300 return *(unsigned char*)fp->_IO_read_ptr;
304 DEFUN(_IO_file_overflow, (f, ch),
305 register _IO_FILE* f AND int ch)
307 if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
309 /* If currently reading or no buffer allocated. */
310 if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
312 /* Allocate a buffer if needed. */
313 if (f->_IO_write_base == 0)
316 _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
318 /* Otherwise must be currently reading.
319 If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
320 logically slide the buffer forwards one block (by setting the
321 read pointers to all point at the beginning of the block). This
322 makes room for subsequent output.
323 Otherwise, set the read pointers to _IO_read_end (leaving that
324 alone, so it can continue to correspond to the external position). */
325 if (f->_IO_read_ptr == f->_IO_buf_end)
326 f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
327 f->_IO_write_ptr = f->_IO_read_ptr;
328 f->_IO_write_base = f->_IO_write_ptr;
329 f->_IO_write_end = f->_IO_buf_end;
330 f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
332 if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
333 f->_IO_write_end = f->_IO_write_ptr;
334 f->_flags |= _IO_CURRENTLY_PUTTING;
337 return _IO_do_flush(f);
338 if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
339 if (_IO_do_flush(f) == EOF)
341 *f->_IO_write_ptr++ = ch;
342 if ((f->_flags & _IO_UNBUFFERED)
343 || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
344 if (_IO_do_flush(f) == EOF)
346 return (unsigned char)ch;
350 DEFUN(_IO_file_sync, (fp),
351 register _IO_FILE* fp)
354 /* char* ptr = cur_ptr(); */
355 if (fp->_IO_write_ptr > fp->_IO_write_base)
356 if (_IO_do_flush(fp)) return EOF;
357 delta = fp->_IO_read_ptr - fp->_IO_read_end;
361 if (_IO_in_backup(fp))
362 delta -= eGptr() - Gbase();
364 _IO_off_t new_pos = _IO_SYSSEEK (fp, delta, 1);
365 if (new_pos != (_IO_off_t)EOF)
366 fp->_IO_read_end = fp->_IO_read_ptr;
368 else if (errno == ESPIPE)
369 ; /* Ignore error from unseekable devices. */
374 fp->_offset = _IO_pos_BAD;
375 /* FIXME: Cleanup - can this be shared? */
376 /* setg(base(), ptr, ptr); */
381 DEFUN(_IO_file_seekoff, (fp, offset, dir, mode),
382 register _IO_FILE *fp AND _IO_off_t offset AND int dir AND int mode)
385 _IO_off_t delta, new_offset;
389 dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
391 /* Flush unwritten characters.
392 (This may do an unneeded write if we seek within the buffer.
393 But to be able to switch to reading, we would need to set
394 egptr to ptr. That can't be done in the current design,
395 which assumes file_ptr() is eGptr. Anyway, since we probably
396 end up flushing when we close(), it doesn't make much difference.)
397 FIXME: simulate mem-papped files. */
399 if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode(fp))
400 if (_IO_switch_to_get_mode(fp)) return EOF;
402 if (fp->_IO_buf_base == NULL)
405 _IO_setp(fp, fp->_IO_buf_base, fp->_IO_buf_base);
406 _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
412 /* Adjust for read-ahead (bytes is buffer). */
413 offset -= fp->_IO_read_end - fp->_IO_read_ptr;
414 if (fp->_offset == _IO_pos_BAD)
416 /* Make offset absolute, assuming current pointer is file_ptr(). */
417 offset += _IO_pos_as_off(fp->_offset);
426 if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG(st.st_mode))
428 offset += st.st_size;
435 /* At this point, dir==_IO_seek_set. */
437 /* If destination is within current buffer, optimize: */
438 if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
439 && !_IO_in_backup (fp))
441 /* Offset relative to start of main get area. */
442 _IO_pos_t rel_offset = offset - fp->_offset
443 + (fp->_IO_read_end - fp->_IO_read_base);
447 if (_IO_in_backup(fp))
448 _IO_switch_to_main_get_area(fp);
450 if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
452 _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
454 _IO_setp(fp, fp->_IO_buf_base, fp->_IO_buf_base);
458 /* If we have streammarkers, seek forward by reading ahead. */
459 if (_IO_have_markers(fp))
461 int to_skip = rel_offset
462 - (fp->_IO_read_ptr - fp->_IO_read_base);
463 if (ignore(to_skip) != to_skip)
470 if (rel_offset < 0 && rel_offset >= Bbase() - Bptr())
472 if (!_IO_in_backup(fp))
473 _IO_switch_to_backup_area(fp);
474 gbump(fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
481 _IO_unsave_markers(fp);
484 if (fp->_flags & _IO_NO_READS)
487 /* Try to seek to a block boundary, to improve kernel page management. */
488 new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
489 delta = offset - new_offset;
490 if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
495 result = _IO_SYSSEEK (fp, new_offset, 0);
502 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
503 fp->_IO_buf_end - fp->_IO_buf_base);
506 /* We weren't allowed to read, but try to seek the remainder. */
507 offset = count == EOF ? delta : delta-count;
512 _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base+delta, fp->_IO_buf_base+count);
513 _IO_setp(fp, fp->_IO_buf_base, fp->_IO_buf_base);
514 fp->_offset = result + count;
515 _IO_mask_flags(fp, 0, _IO_EOF_SEEN);
519 _IO_unsave_markers(fp);
520 result = _IO_SYSSEEK (fp, offset, dir);
522 _IO_mask_flags(fp, 0, _IO_EOF_SEEN);
523 fp->_offset = result;
524 _IO_setg(fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
525 _IO_setp(fp, fp->_IO_buf_base, fp->_IO_buf_base);
530 DEFUN(_IO_file_read, (fp, buf, size),
531 register _IO_FILE* fp AND void* buf AND _IO_ssize_t size)
535 _IO_ssize_t count = _IO_read(fp->_fileno, buf, size);
537 if (count == -1 && errno == EINTR)
545 DEFUN(_IO_file_seek, (fp, offset, dir),
546 _IO_FILE *fp AND _IO_off_t offset AND int dir)
548 return _IO_lseek(fp->_fileno, offset, dir);
552 DEFUN(_IO_file_stat, (fp, st),
553 _IO_FILE *fp AND void* st)
555 return _IO_fstat(fp->_fileno, (struct stat*)st);
559 DEFUN(_IO_file_close, (fp),
562 return _IO_close(fp->_fileno);
566 DEFUN(_IO_file_write, (f, data, n),
567 register _IO_FILE* f AND const void* data AND _IO_ssize_t n)
569 _IO_ssize_t to_do = n;
572 _IO_ssize_t count = _IO_write(f->_fileno, data, to_do);
581 f->_flags |= _IO_ERR_SEEN;
586 data = (void*)((char*)data + count);
595 DEFUN(_IO_file_xsputn, (f, data, n),
596 _IO_FILE *f AND const void *data AND _IO_size_t n)
598 register const char *s = (char*) data;
599 _IO_size_t to_do = n;
605 /* This is an optimized implementation.
606 If the amount to be written straddles a block boundary
607 (or the filebuf is unbuffered), use sys_write directly. */
609 /* First figure out how much space is available in the buffer. */
610 count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
611 if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
613 count = f->_IO_buf_end - f->_IO_write_ptr;
615 { register const char *p;
616 for (p = s + n; p > s; )
626 /* Then fill the buffer. */
632 memcpy(f->_IO_write_ptr, s, count);
637 register char *p = f->_IO_write_ptr;
638 register int i = (int)count;
639 while (--i >= 0) *p++ = *s++;
641 f->_IO_write_ptr += count;
644 if (to_do + must_flush > 0)
645 { _IO_size_t block_size, dont_write;
646 /* Next flush the (full) buffer. */
647 if (__overflow(f, EOF) == EOF)
650 /* Try to maintain alignment: write a whole number of blocks.
651 dont_write is what gets left over. */
652 block_size = f->_IO_buf_end - f->_IO_buf_base;
653 dont_write = block_size >= 128 ? to_do % block_size : 0;
655 count = to_do - dont_write;
656 if (_IO_do_write(f, s, count) == EOF)
660 /* Now write out the remainder. Normally, this will fit in the
661 buffer, but it's somewhat messier for line-buffered files,
662 so we let _IO_default_xsputn handle the general case. */
664 to_do -= _IO_default_xsputn(f, s+count, dont_write);
670 /* Work in progress */
672 DEFUN(_IO_file_xsgetn, (fp, data, n),
673 _IO_FILE *fp AND void *data AND _IO_size_t n)
675 register _IO_size_t more = n;
676 register char *s = data;
679 _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr; /* Data available. */
686 memcpy(s, fp->_IO_read_ptr, count);
688 fp->_IO_read_ptr += count;
694 register char *p = fp->_IO_read_ptr;
695 register int i = (int)count;
696 while (--i >= 0) *s++ = *p++;
697 fp->_IO_read_ptr = p;
702 if (! _IO_in put_mode (fp)
703 && ! _IO_have_markers (fp) && ! IO_have_backup (fp))
705 /* This is an optimization of _IO_file_underflow */
706 if (fp->_flags & _IO_NO_READS)
708 /* If we're reading a lot of data, don't bother allocating
709 a buffer. But if we're only reading a bit, perhaps we should ??*/
710 if (count <= 512 && fp->_IO_buf_base == NULL)
712 if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
713 _IO_flush_all_linebuffered();
715 _IO_switch_to_get_mode(fp); ???;
716 count = _IO_SYSREAD (fp, s, more);
720 fp->_flags |= _IO_EOF_SEEN;
722 fp->_flags |= _IO_ERR_SEEN, count = 0;
729 if (more == 0 || __underflow(fp) == EOF)
736 struct _IO_jump_t _IO_file_jumps = {
738 JUMP_INIT(finish, _IO_file_finish),
739 JUMP_INIT(overflow, _IO_file_overflow),
740 JUMP_INIT(underflow, _IO_file_underflow),
741 JUMP_INIT(uflow, _IO_default_uflow),
742 JUMP_INIT(pbackfail, _IO_default_pbackfail),
743 JUMP_INIT(xsputn, _IO_file_xsputn),
744 JUMP_INIT(xsgetn, _IO_default_xsgetn),
745 JUMP_INIT(seekoff, _IO_file_seekoff),
746 JUMP_INIT(seekpos, _IO_default_seekpos),
747 JUMP_INIT(setbuf, _IO_file_setbuf),
748 JUMP_INIT(sync, _IO_file_sync),
749 JUMP_INIT(doallocate, _IO_file_doallocate),
750 JUMP_INIT(read, _IO_file_read),
751 JUMP_INIT(write, _IO_file_write),
752 JUMP_INIT(seek, _IO_file_seek),
753 JUMP_INIT(close, _IO_file_close),
754 JUMP_INIT(stat, _IO_file_stat)