2002-11-21 Phil Edwards <pme@gcc.gnu.org>
[official-gcc.git] / libstdc++-v3 / libio / fileops.c
bloba830b5cd4395a02470067011cf079e10dcdbae98
1 /* Copyright (C) 1993, 1995, 1997-1999, 2000 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 #if _LIBC
41 # include "../wcsmbs/wcsmbsload.h"
42 # include <shlib-compat.h>
43 #endif
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 #else
59 # define _IO_new_do_write _IO_do_write
60 # define _IO_new_file_attach _IO_file_attach
61 # define _IO_new_file_close_it _IO_file_close_it
62 # define _IO_new_file_finish _IO_file_finish
63 # define _IO_new_file_fopen _IO_file_fopen
64 # define _IO_new_file_init _IO_file_init
65 # define _IO_new_file_setbuf _IO_file_setbuf
66 # define _IO_new_file_sync _IO_file_sync
67 # define _IO_new_file_overflow _IO_file_overflow
68 # define _IO_new_file_seekoff _IO_file_seekoff
69 # define _IO_new_file_underflow _IO_file_underflow
70 # define _IO_new_file_write _IO_file_write
71 # define _IO_new_file_xsputn _IO_file_xsputn
72 #endif
74 /* An fstream can be in at most one of put mode, get mode, or putback mode.
75 Putback mode is a variant of get mode.
77 In a filebuf, there is only one current position, instead of two
78 separate get and put pointers. In get mode, the current position
79 is that of gptr(); in put mode that of pptr().
81 The position in the buffer that corresponds to the position
82 in external file system is normally _IO_read_end, except in putback
83 mode, when it is _IO_save_end.
84 If the field _fb._offset is >= 0, it gives the offset in
85 the file as a whole corresponding to eGptr(). (?)
87 PUT MODE:
88 If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
89 and _IO_read_base are equal to each other. These are usually equal
90 to _IO_buf_base, though not necessarily if we have switched from
91 get mode to put mode. (The reason is to maintain the invariant
92 that _IO_read_end corresponds to the external file position.)
93 _IO_write_base is non-NULL and usually equal to _IO_base_base.
94 We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
95 The un-flushed character are those between _IO_write_base and _IO_write_ptr.
97 GET MODE:
98 If a filebuf is in get or putback mode, eback() != egptr().
99 In get mode, the unread characters are between gptr() and egptr().
100 The OS file position corresponds to that of egptr().
102 PUTBACK MODE:
103 Putback mode is used to remember "excess" characters that have
104 been sputbackc'd in a separate putback buffer.
105 In putback mode, the get buffer points to the special putback buffer.
106 The unread characters are the characters between gptr() and egptr()
107 in the putback buffer, as well as the area between save_gptr()
108 and save_egptr(), which point into the original reserve buffer.
109 (The pointers save_gptr() and save_egptr() are the values
110 of gptr() and egptr() at the time putback mode was entered.)
111 The OS position corresponds to that of save_egptr().
113 LINE BUFFERED OUTPUT:
114 During line buffered output, _IO_write_base==base() && epptr()==base().
115 However, ptr() may be anywhere between base() and ebuf().
116 This forces a call to filebuf::overflow(int C) on every put.
117 If there is more space in the buffer, and C is not a '\n',
118 then C is inserted, and pptr() incremented.
120 UNBUFFERED STREAMS:
121 If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
124 #define CLOSED_FILEBUF_FLAGS \
125 (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
128 void
129 _IO_new_file_init (fp)
130 struct _IO_FILE_plus *fp;
132 /* POSIX.1 allows another file handle to be used to change the position
133 of our file descriptor. Hence we actually don't know the actual
134 position before we do the first fseek (and until a following fflush). */
135 fp->file._offset = _IO_pos_BAD;
136 fp->file._IO_file_flags |= CLOSED_FILEBUF_FLAGS;
138 _IO_link_in (fp);
139 fp->file._fileno = -1;
143 _IO_new_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_do_flush (fp);
152 _IO_unsave_markers(fp);
154 close_status = _IO_SYSCLOSE (fp);
156 /* Free buffer. */
157 if (fp->_mode <= 0)
159 _IO_setb (fp, NULL, NULL, 0);
160 _IO_setg (fp, NULL, NULL, NULL);
161 _IO_setp (fp, NULL, NULL);
163 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
164 else
166 _IO_wsetb (fp, NULL, NULL, 0);
167 _IO_wsetg (fp, NULL, NULL, NULL);
168 _IO_wsetp (fp, NULL, NULL);
170 #endif
172 _IO_un_link ((struct _IO_FILE_plus *) fp);
173 fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
174 fp->_fileno = -1;
175 fp->_offset = _IO_pos_BAD;
177 return close_status ? close_status : write_status;
180 void
181 _IO_new_file_finish (fp, dummy)
182 _IO_FILE *fp;
183 int dummy;
185 if (_IO_file_is_open (fp))
187 _IO_do_flush (fp);
188 if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
189 _IO_SYSCLOSE (fp);
191 _IO_default_finish (fp, 0);
194 #if defined __GNUC__ && __GNUC__ >= 2
195 __inline__
196 #endif
197 _IO_FILE *
198 _IO_file_open (fp, filename, posix_mode, prot, read_write, is32not64)
199 _IO_FILE *fp;
200 const char *filename;
201 int posix_mode;
202 int prot;
203 int read_write;
204 int is32not64;
206 int fdesc;
207 #ifdef _G_OPEN64
208 fdesc = (is32not64
209 ? open (filename, posix_mode, prot)
210 : _G_OPEN64 (filename, posix_mode, prot));
211 #else
212 fdesc = open (filename, posix_mode, prot);
213 #endif
214 if (fdesc < 0)
215 return NULL;
216 fp->_fileno = fdesc;
217 _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
218 if (read_write & _IO_IS_APPENDING)
219 if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
220 == _IO_pos_BAD && errno != ESPIPE)
221 return NULL;
222 _IO_link_in ((struct _IO_FILE_plus *) fp);
223 return fp;
226 _IO_FILE *
227 _IO_new_file_fopen (fp, filename, mode, is32not64)
228 _IO_FILE *fp;
229 const char *filename;
230 const char *mode;
231 int is32not64;
233 int oflags = 0, omode;
234 int read_write;
235 int oprot = 0666;
236 int i;
237 _IO_FILE *result;
238 #if _LIBC
239 const char *cs;
240 #endif
242 if (_IO_file_is_open (fp))
243 return 0;
244 switch (*mode)
246 case 'r':
247 omode = O_RDONLY;
248 read_write = _IO_NO_WRITES;
249 break;
250 case 'w':
251 omode = O_WRONLY;
252 oflags = O_CREAT|O_TRUNC;
253 read_write = _IO_NO_READS;
254 break;
255 case 'a':
256 omode = O_WRONLY;
257 oflags = O_CREAT|O_APPEND;
258 read_write = _IO_NO_READS|_IO_IS_APPENDING;
259 break;
260 default:
261 __set_errno (EINVAL);
262 return NULL;
264 for (i = 1; i < 4; ++i)
266 switch (*++mode)
268 case '\0':
269 break;
270 case '+':
271 omode = O_RDWR;
272 read_write &= _IO_IS_APPENDING;
273 continue;
274 case 'x':
275 oflags |= O_EXCL;
276 continue;
277 case 'b':
278 default:
279 /* Ignore. */
280 continue;
282 break;
285 result = _IO_file_open (fp, filename, omode|oflags, oprot, read_write,
286 is32not64);
289 #if _LIBC
290 /* Test whether the mode string specifies the conversion. */
291 cs = strstr (mode, ",ccs=");
292 if (cs != NULL)
294 /* Yep. Load the appropriate conversions and set the orientation
295 to wide. */
296 struct gconv_fcts fcts;
297 struct _IO_codecvt *cc;
299 if (! _IO_CHECK_WIDE (fp) || __wcsmbs_named_conv (&fcts, cs + 5) != 0)
301 /* Something went wrong, we cannot load the conversion modules.
302 This means we cannot proceed since the user explicitly asked
303 for these. */
304 _IO_new_fclose (result);
305 return NULL;
308 cc = fp->_codecvt = &fp->_wide_data->_codecvt;
310 /* The functions are always the same. */
311 *cc = __libio_codecvt;
313 cc->__cd_in.__cd.__nsteps = 1; /* Only one step allowed. */
314 cc->__cd_in.__cd.__steps = fcts.towc;
316 cc->__cd_in.__cd.__data[0].__invocation_counter = 0;
317 cc->__cd_in.__cd.__data[0].__internal_use = 1;
318 cc->__cd_in.__cd.__data[0].__flags = __GCONV_IS_LAST;
319 cc->__cd_in.__cd.__data[0].__statep = &result->_wide_data->_IO_state;
321 cc->__cd_out.__cd.__nsteps = 1; /* Only one step allowed. */
322 cc->__cd_out.__cd.__steps = fcts.tomb;
324 cc->__cd_out.__cd.__data[0].__invocation_counter = 0;
325 cc->__cd_out.__cd.__data[0].__internal_use = 1;
326 cc->__cd_out.__cd.__data[0].__flags = __GCONV_IS_LAST;
327 cc->__cd_out.__cd.__data[0].__statep = &result->_wide_data->_IO_state;
329 /* Set the mode now. */
330 result->_mode = 1;
332 #endif /* GNU libc */
334 return result;
337 _IO_FILE *
338 _IO_new_file_attach (fp, fd)
339 _IO_FILE *fp;
340 int fd;
342 if (_IO_file_is_open (fp))
343 return NULL;
344 fp->_fileno = fd;
345 fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
346 fp->_flags |= _IO_DELETE_DONT_CLOSE;
347 /* Get the current position of the file. */
348 /* We have to do that since that may be junk. */
349 fp->_offset = _IO_pos_BAD;
350 if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
351 == _IO_pos_BAD && errno != ESPIPE)
352 return NULL;
353 return fp;
356 _IO_FILE *
357 _IO_new_file_setbuf (fp, p, len)
358 _IO_FILE *fp;
359 char *p;
360 _IO_ssize_t len;
362 if (_IO_default_setbuf (fp, p, len) == NULL)
363 return NULL;
365 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
366 = fp->_IO_buf_base;
367 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
369 return fp;
372 static int new_do_write __P ((_IO_FILE *, const char *, _IO_size_t));
374 /* Write TO_DO bytes from DATA to FP.
375 Then mark FP as having empty buffers. */
378 _IO_new_do_write (fp, data, to_do)
379 _IO_FILE *fp;
380 const char *data;
381 _IO_size_t to_do;
383 return (to_do == 0 || new_do_write (fp, data, to_do) == to_do) ? 0 : EOF;
386 static
388 new_do_write (fp, data, to_do)
389 _IO_FILE *fp;
390 const char *data;
391 _IO_size_t to_do;
393 _IO_size_t count;
394 if (fp->_flags & _IO_IS_APPENDING)
395 /* On a system without a proper O_APPEND implementation,
396 you would need to sys_seek(0, SEEK_END) here, but is
397 is not needed nor desirable for Unix- or Posix-like systems.
398 Instead, just indicate that offset (before and after) is
399 unpredictable. */
400 fp->_offset = _IO_pos_BAD;
401 else if (fp->_IO_read_end != fp->_IO_write_base)
403 _IO_off64_t new_pos
404 = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
405 if (new_pos == _IO_pos_BAD)
406 return 0;
407 fp->_offset = new_pos;
409 count = _IO_SYSWRITE (fp, data, to_do);
410 if (fp->_cur_column && count)
411 fp->_cur_column = _IO_adjust_column (fp->_cur_column - 1, data, count) + 1;
412 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
413 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
414 fp->_IO_write_end = (fp->_mode < 0
415 && (fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
416 ? fp->_IO_buf_base : fp->_IO_buf_end);
417 return count;
421 _IO_new_file_underflow (fp)
422 _IO_FILE *fp;
424 _IO_ssize_t count;
425 #if 0
426 /* SysV does not make this test; take it out for compatibility */
427 if (fp->_flags & _IO_EOF_SEEN)
428 return (EOF);
429 #endif
431 if (fp->_flags & _IO_NO_READS)
433 fp->_flags |= _IO_ERR_SEEN;
434 __set_errno (EBADF);
435 return EOF;
437 if (fp->_IO_read_ptr < fp->_IO_read_end)
438 return *(unsigned char *) fp->_IO_read_ptr;
440 if (fp->_IO_buf_base == NULL)
442 /* Maybe we already have a push back pointer. */
443 if (fp->_IO_save_base != NULL)
445 free (fp->_IO_save_base);
446 fp->_flags &= ~_IO_IN_BACKUP;
448 _IO_doallocbuf (fp);
451 /* Flush all line buffered files before reading. */
452 /* FIXME This can/should be moved to genops ?? */
453 if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
454 _IO_flush_all_linebuffered ();
456 _IO_switch_to_get_mode (fp);
458 /* This is very tricky. We have to adjust those
459 pointers before we call _IO_SYSREAD () since
460 we may longjump () out while waiting for
461 input. Those pointers may be screwed up. H.J. */
462 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
463 fp->_IO_read_end = fp->_IO_buf_base;
464 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
465 = fp->_IO_buf_base;
467 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
468 fp->_IO_buf_end - fp->_IO_buf_base);
469 if (count <= 0)
471 if (count == 0)
472 fp->_flags |= _IO_EOF_SEEN;
473 else
474 fp->_flags |= _IO_ERR_SEEN, count = 0;
476 fp->_IO_read_end += count;
477 if (count == 0)
478 return EOF;
479 if (fp->_offset != _IO_pos_BAD)
480 _IO_pos_adjust (fp->_offset, count);
481 return *(unsigned char *) fp->_IO_read_ptr;
485 _IO_new_file_overflow (f, ch)
486 _IO_FILE *f;
487 int ch;
489 if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
491 f->_flags |= _IO_ERR_SEEN;
492 __set_errno (EBADF);
493 return EOF;
495 /* If currently reading or no buffer allocated. */
496 if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0 || f->_IO_write_base == 0)
498 /* Allocate a buffer if needed. */
499 if (f->_IO_write_base == 0)
501 _IO_doallocbuf (f);
502 _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
504 /* Otherwise must be currently reading.
505 If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
506 logically slide the buffer forwards one block (by setting the
507 read pointers to all point at the beginning of the block). This
508 makes room for subsequent output.
509 Otherwise, set the read pointers to _IO_read_end (leaving that
510 alone, so it can continue to correspond to the external position). */
511 if (f->_IO_read_ptr == f->_IO_buf_end)
512 f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
513 f->_IO_write_ptr = f->_IO_read_ptr;
514 f->_IO_write_base = f->_IO_write_ptr;
515 f->_IO_write_end = f->_IO_buf_end;
516 f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
518 f->_flags |= _IO_CURRENTLY_PUTTING;
519 if (f->_mode < 0 && f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
520 f->_IO_write_end = f->_IO_write_ptr;
522 if (ch == EOF)
523 return _IO_new_do_write(f, f->_IO_write_base,
524 f->_IO_write_ptr - f->_IO_write_base);
525 if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
526 if (_IO_do_flush (f) == EOF)
527 return EOF;
528 *f->_IO_write_ptr++ = ch;
529 if ((f->_flags & _IO_UNBUFFERED)
530 || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
531 if (_IO_new_do_write(f, f->_IO_write_base,
532 f->_IO_write_ptr - f->_IO_write_base) == EOF)
533 return EOF;
534 return (unsigned char) ch;
538 _IO_new_file_sync (fp)
539 _IO_FILE *fp;
541 _IO_ssize_t delta;
542 int retval = 0;
544 /* char* ptr = cur_ptr(); */
545 if (fp->_IO_write_ptr > fp->_IO_write_base)
546 if (_IO_do_flush(fp)) return EOF;
547 delta = fp->_IO_read_ptr - fp->_IO_read_end;
548 if (delta != 0)
550 #ifdef TODO
551 if (_IO_in_backup (fp))
552 delta -= eGptr () - Gbase ();
553 #endif
554 _IO_off64_t new_pos = _IO_SYSSEEK (fp, delta, 1);
555 if (new_pos != (_IO_off64_t) EOF)
556 fp->_IO_read_end = fp->_IO_read_ptr;
557 #ifdef ESPIPE
558 else if (errno == ESPIPE)
559 ; /* Ignore error from unseekable devices. */
560 #endif
561 else
562 retval = EOF;
564 if (retval != EOF)
565 fp->_offset = _IO_pos_BAD;
566 /* FIXME: Cleanup - can this be shared? */
567 /* setg(base(), ptr, ptr); */
568 return retval;
571 _IO_off64_t
572 _IO_new_file_seekoff (fp, offset, dir, mode)
573 _IO_FILE *fp;
574 _IO_off64_t offset;
575 int dir;
576 int mode;
578 _IO_off64_t result;
579 _IO_off64_t delta, new_offset;
580 long count;
581 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
582 offset of the underlying file must be exact. */
583 int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
584 && fp->_IO_write_base == fp->_IO_write_ptr);
586 if (mode == 0)
587 dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
589 /* Flush unwritten characters.
590 (This may do an unneeded write if we seek within the buffer.
591 But to be able to switch to reading, we would need to set
592 egptr to ptr. That can't be done in the current design,
593 which assumes file_ptr() is eGptr. Anyway, since we probably
594 end up flushing when we close(), it doesn't make much difference.)
595 FIXME: simulate mem-papped files. */
597 if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
598 if (_IO_switch_to_get_mode (fp))
599 return EOF;
601 if (fp->_IO_buf_base == NULL)
603 /* It could be that we already have a pushback buffer. */
604 if (fp->_IO_read_base != NULL)
606 free (fp->_IO_read_base);
607 fp->_flags &= ~_IO_IN_BACKUP;
609 _IO_doallocbuf (fp);
610 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
611 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
614 switch (dir)
616 case _IO_seek_cur:
617 /* Adjust for read-ahead (bytes is buffer). */
618 offset -= fp->_IO_read_end - fp->_IO_read_ptr;
619 if (fp->_offset == _IO_pos_BAD)
620 goto dumb;
621 /* Make offset absolute, assuming current pointer is file_ptr(). */
622 offset += fp->_offset;
624 dir = _IO_seek_set;
625 break;
626 case _IO_seek_set:
627 break;
628 case _IO_seek_end:
630 struct _G_stat64 st;
631 if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
633 offset += st.st_size;
634 dir = _IO_seek_set;
636 else
637 goto dumb;
640 /* At this point, dir==_IO_seek_set. */
642 /* If we are only interested in the current position we've found it now. */
643 if (mode == 0)
644 return offset;
646 /* If destination is within current buffer, optimize: */
647 if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
648 && !_IO_in_backup (fp))
650 /* Offset relative to start of main get area. */
651 _IO_off64_t rel_offset = (offset - fp->_offset
652 + (fp->_IO_read_end - fp->_IO_read_base));
653 if (rel_offset >= 0)
655 #if 0
656 if (_IO_in_backup (fp))
657 _IO_switch_to_main_get_area (fp);
658 #endif
659 if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
661 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
662 fp->_IO_read_end);
663 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
665 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
666 goto resync;
669 #ifdef TODO
670 /* If we have streammarkers, seek forward by reading ahead. */
671 if (_IO_have_markers (fp))
673 int to_skip = rel_offset
674 - (fp->_IO_read_ptr - fp->_IO_read_base);
675 if (ignore (to_skip) != to_skip)
676 goto dumb;
677 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
678 goto resync;
680 #endif
682 #ifdef TODO
683 if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ())
685 if (!_IO_in_backup (fp))
686 _IO_switch_to_backup_area (fp);
687 gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
688 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
689 goto resync;
691 #endif
694 #ifdef TODO
695 _IO_unsave_markers (fp);
696 #endif
698 if (fp->_flags & _IO_NO_READS)
699 goto dumb;
701 /* Try to seek to a block boundary, to improve kernel page management. */
702 new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
703 delta = offset - new_offset;
704 if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
706 new_offset = offset;
707 delta = 0;
709 result = _IO_SYSSEEK (fp, new_offset, 0);
710 if (result < 0)
711 return EOF;
712 if (delta == 0)
713 count = 0;
714 else
716 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
717 (must_be_exact
718 ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
719 if (count < delta)
721 /* We weren't allowed to read, but try to seek the remainder. */
722 offset = count == EOF ? delta : delta-count;
723 dir = _IO_seek_cur;
724 goto dumb;
727 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
728 fp->_IO_buf_base + count);
729 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
730 fp->_offset = result + count;
731 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
732 return offset;
733 dumb:
735 _IO_unsave_markers (fp);
736 result = _IO_SYSSEEK (fp, offset, dir);
737 if (result != EOF)
739 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
740 fp->_offset = result;
741 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
742 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
744 return result;
746 resync:
747 /* We need to do it since it is possible that the file offset in
748 the kernel may be changed behind our back. It may happen when
749 we fopen a file and then do a fork. One process may access the
750 the file and the kernel file offset will be changed. */
751 if (fp->_offset >= 0)
752 _IO_SYSSEEK (fp, fp->_offset, 0);
754 return offset;
757 _IO_ssize_t
758 _IO_file_read (fp, buf, size)
759 _IO_FILE *fp;
760 void *buf;
761 _IO_ssize_t size;
763 return read (fp->_fileno, buf, size);
766 _IO_off64_t
767 _IO_file_seek (fp, offset, dir)
768 _IO_FILE *fp;
769 _IO_off64_t offset;
770 int dir;
772 #ifdef _G_LSEEK64
773 return _G_LSEEK64 (fp->_fileno, offset, dir);
774 #else
775 return lseek (fp->_fileno, offset, dir);
776 #endif
780 _IO_file_stat (fp, st)
781 _IO_FILE *fp;
782 void *st;
784 #ifdef _G_FSTAT64
785 return _G_FSTAT64 (fp->_fileno, (struct _G_stat64 *) st);
786 #else
787 return fstat (fp->_fileno, (struct stat *) st);
788 #endif
792 _IO_file_close (fp)
793 _IO_FILE *fp;
795 return close (fp->_fileno);
798 _IO_ssize_t
799 _IO_new_file_write (f, data, n)
800 _IO_FILE *f;
801 const void *data;
802 _IO_ssize_t n;
804 _IO_ssize_t to_do = n;
805 while (to_do > 0)
807 _IO_ssize_t count = write (f->_fileno, data, to_do);
808 if (count < 0)
810 f->_flags |= _IO_ERR_SEEN;
811 break;
813 to_do -= count;
814 data = (void *) ((char *) data + count);
816 n -= to_do;
817 if (f->_offset >= 0)
818 f->_offset += n;
819 return n;
822 _IO_size_t
823 _IO_new_file_xsputn (f, data, n)
824 _IO_FILE *f;
825 const void *data;
826 _IO_size_t n;
828 register const char *s = (const char *) data;
829 _IO_size_t to_do = n;
830 int must_flush = 0;
831 _IO_size_t count;
833 if (n <= 0)
834 return 0;
835 /* This is an optimized implementation.
836 If the amount to be written straddles a block boundary
837 (or the filebuf is unbuffered), use sys_write directly. */
839 /* First figure out how much space is available in the buffer. */
840 count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
841 if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
843 count = f->_IO_buf_end - f->_IO_write_ptr;
844 if (count >= n)
846 register const char *p;
847 for (p = s + n; p > s; )
849 if (*--p == '\n')
851 count = p - s + 1;
852 must_flush = 1;
853 break;
858 /* Then fill the buffer. */
859 if (count > 0)
861 if (count > to_do)
862 count = to_do;
863 if (count > 20)
865 #ifdef _LIBC
866 f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
867 #else
868 memcpy (f->_IO_write_ptr, s, count);
869 f->_IO_write_ptr += count;
870 #endif
871 s += count;
873 else
875 register char *p = f->_IO_write_ptr;
876 register int i = (int) count;
877 while (--i >= 0)
878 *p++ = *s++;
879 f->_IO_write_ptr = p;
881 to_do -= count;
883 if (to_do + must_flush > 0)
885 _IO_size_t block_size, do_write;
886 /* Next flush the (full) buffer. */
887 if (_IO_OVERFLOW (f, EOF) == EOF)
888 return n - to_do;
890 /* Try to maintain alignment: write a whole number of blocks.
891 dont_write is what gets left over. */
892 block_size = f->_IO_buf_end - f->_IO_buf_base;
893 do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
895 if (do_write)
897 count = new_do_write (f, s, do_write);
898 to_do -= count;
899 if (count < do_write)
900 return n - to_do;
903 /* Now write out the remainder. Normally, this will fit in the
904 buffer, but it's somewhat messier for line-buffered files,
905 so we let _IO_default_xsputn handle the general case. */
906 if (to_do)
907 to_do -= _IO_default_xsputn (f, s+do_write, to_do);
909 return n - to_do;
912 _IO_size_t
913 _IO_file_xsgetn (fp, data, n)
914 _IO_FILE *fp;
915 void *data;
916 _IO_size_t n;
918 register _IO_size_t want, have;
919 register _IO_ssize_t count;
920 register char *s = data;
922 want = n;
924 if (fp->_IO_buf_base == NULL)
926 /* Maybe we already have a push back pointer. */
927 if (fp->_IO_save_base != NULL)
929 free (fp->_IO_save_base);
930 fp->_flags &= ~_IO_IN_BACKUP;
932 _IO_doallocbuf (fp);
935 while (want > 0)
937 have = fp->_IO_read_end - fp->_IO_read_ptr;
938 if (want <= have)
940 memcpy (s, fp->_IO_read_ptr, want);
941 fp->_IO_read_ptr += want;
942 want = 0;
944 else
946 if (have > 0)
948 #ifdef _LIBC
949 s = __mempcpy (s, fp->_IO_read_ptr, have);
950 #else
951 memcpy (s, fp->_IO_read_ptr, have);
952 s += have;
953 #endif
954 want -= have;
955 fp->_IO_read_ptr += have;
958 /* Check for backup and repeat */
959 if (_IO_in_backup (fp))
961 _IO_switch_to_main_get_area (fp);
962 continue;
965 /* If we now want less than a buffer, underflow and repeat
966 the copy. Otherwise, _IO_SYSREAD directly to
967 the user buffer. */
968 if (fp->_IO_buf_base && want < fp->_IO_buf_end - fp->_IO_buf_base)
970 if (__underflow (fp) == EOF)
971 break;
973 continue;
976 /* These must be set before the sysread as we might longjmp out
977 waiting for input. */
978 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
979 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
981 /* Try to maintain alignment: read a whole number of blocks. */
982 count = want;
983 if (fp->_IO_buf_base)
985 _IO_size_t block_size = fp->_IO_buf_end - fp->_IO_buf_base;
986 if (block_size >= 128)
987 count -= want % block_size;
990 count = _IO_SYSREAD (fp, s, count);
991 if (count <= 0)
993 if (count == 0)
994 fp->_flags |= _IO_EOF_SEEN;
995 else
996 fp->_flags |= _IO_ERR_SEEN;
998 break;
1001 s += count;
1002 want -= count;
1003 if (fp->_offset != _IO_pos_BAD)
1004 _IO_pos_adjust (fp->_offset, count);
1008 return n - want;
1011 struct _IO_jump_t _IO_file_jumps =
1013 JUMP_INIT_DUMMY,
1014 JUMP_INIT(finish, _IO_new_file_finish),
1015 JUMP_INIT(overflow, _IO_new_file_overflow),
1016 JUMP_INIT(underflow, _IO_new_file_underflow),
1017 JUMP_INIT(uflow, _IO_default_uflow),
1018 JUMP_INIT(pbackfail, _IO_default_pbackfail),
1019 JUMP_INIT(xsputn, _IO_new_file_xsputn),
1020 JUMP_INIT(xsgetn, _IO_file_xsgetn),
1021 JUMP_INIT(seekoff, _IO_new_file_seekoff),
1022 JUMP_INIT(seekpos, _IO_default_seekpos),
1023 JUMP_INIT(setbuf, _IO_new_file_setbuf),
1024 JUMP_INIT(sync, _IO_new_file_sync),
1025 JUMP_INIT(doallocate, _IO_file_doallocate),
1026 JUMP_INIT(read, _IO_file_read),
1027 JUMP_INIT(write, _IO_new_file_write),
1028 JUMP_INIT(seek, _IO_file_seek),
1029 JUMP_INIT(close, _IO_file_close),
1030 JUMP_INIT(stat, _IO_file_stat),
1031 JUMP_INIT(showmanyc, _IO_default_showmanyc),
1032 JUMP_INIT(imbue, _IO_default_imbue)
1035 #ifdef _LIBC
1036 versioned_symbol (libc, _IO_new_do_write, _IO_do_write, GLIBC_2_1);
1037 versioned_symbol (libc, _IO_new_file_attach, _IO_file_attach, GLIBC_2_1);
1038 versioned_symbol (libc, _IO_new_file_close_it, _IO_file_close_it, GLIBC_2_1);
1039 versioned_symbol (libc, _IO_new_file_finish, _IO_file_finish, GLIBC_2_1);
1040 versioned_symbol (libc, _IO_new_file_fopen, _IO_file_fopen, GLIBC_2_1);
1041 versioned_symbol (libc, _IO_new_file_init, _IO_file_init, GLIBC_2_1);
1042 versioned_symbol (libc, _IO_new_file_setbuf, _IO_file_setbuf, GLIBC_2_1);
1043 versioned_symbol (libc, _IO_new_file_sync, _IO_file_sync, GLIBC_2_1);
1044 versioned_symbol (libc, _IO_new_file_overflow, _IO_file_overflow, GLIBC_2_1);
1045 versioned_symbol (libc, _IO_new_file_seekoff, _IO_file_seekoff, GLIBC_2_1);
1046 versioned_symbol (libc, _IO_new_file_underflow, _IO_file_underflow, GLIBC_2_1);
1047 versioned_symbol (libc, _IO_new_file_write, _IO_file_write, GLIBC_2_1);
1048 versioned_symbol (libc, _IO_new_file_xsputn, _IO_file_xsputn, GLIBC_2_1);
1049 #endif