* posix/execl.c: Fix last argument of memcpy. Reported by Brian
[glibc.git] / libio / fileops.c
blobf67eeefe6e5085d661b248586475b871fd018177
1 /* Copyright (C) 1993, 1995, 1997-2000, 2001 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. */
30 #ifndef _POSIX_SOURCE
31 # define _POSIX_SOURCE
32 #endif
33 #include "libioP.h"
34 #include <assert.h>
35 #include <fcntl.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <string.h>
39 #include <errno.h>
40 #include <unistd.h>
41 #ifdef __STDC__
42 #include <stdlib.h>
43 #endif
44 #if _LIBC
45 # include "../wcsmbs/wcsmbsload.h"
46 # include "../iconv/gconv_charset.h"
47 # include "../iconv/gconv_int.h"
48 # include <shlib-compat.h>
49 #endif
50 #ifndef errno
51 extern int errno;
52 #endif
53 #ifndef __set_errno
54 # define __set_errno(Val) errno = (Val)
55 #endif
58 #ifdef _LIBC
59 # define open(Name, Flags, Prot) __open (Name, Flags, Prot)
60 # define close(FD) __close (FD)
61 # define lseek(FD, Offset, Whence) __lseek (FD, Offset, Whence)
62 # define read(FD, Buf, NBytes) __read (FD, Buf, NBytes)
63 # define write(FD, Buf, NBytes) __write (FD, Buf, NBytes)
64 #else
65 # define _IO_new_do_write _IO_do_write
66 # define _IO_new_file_attach _IO_file_attach
67 # define _IO_new_file_close_it _IO_file_close_it
68 # define _IO_new_file_finish _IO_file_finish
69 # define _IO_new_file_fopen _IO_file_fopen
70 # define _IO_new_file_init _IO_file_init
71 # define _IO_new_file_setbuf _IO_file_setbuf
72 # define _IO_new_file_sync _IO_file_sync
73 # define _IO_new_file_overflow _IO_file_overflow
74 # define _IO_new_file_seekoff _IO_file_seekoff
75 # define _IO_new_file_underflow _IO_file_underflow
76 # define _IO_new_file_write _IO_file_write
77 # define _IO_new_file_xsputn _IO_file_xsputn
78 #endif
81 #ifdef _LIBC
82 extern struct __gconv_trans_data __libio_translit;
83 #endif
86 /* An fstream can be in at most one of put mode, get mode, or putback mode.
87 Putback mode is a variant of get mode.
89 In a filebuf, there is only one current position, instead of two
90 separate get and put pointers. In get mode, the current position
91 is that of gptr(); in put mode that of pptr().
93 The position in the buffer that corresponds to the position
94 in external file system is normally _IO_read_end, except in putback
95 mode, when it is _IO_save_end.
96 If the field _fb._offset is >= 0, it gives the offset in
97 the file as a whole corresponding to eGptr(). (?)
99 PUT MODE:
100 If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
101 and _IO_read_base are equal to each other. These are usually equal
102 to _IO_buf_base, though not necessarily if we have switched from
103 get mode to put mode. (The reason is to maintain the invariant
104 that _IO_read_end corresponds to the external file position.)
105 _IO_write_base is non-NULL and usually equal to _IO_base_base.
106 We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
107 The un-flushed character are those between _IO_write_base and _IO_write_ptr.
109 GET MODE:
110 If a filebuf is in get or putback mode, eback() != egptr().
111 In get mode, the unread characters are between gptr() and egptr().
112 The OS file position corresponds to that of egptr().
114 PUTBACK MODE:
115 Putback mode is used to remember "excess" characters that have
116 been sputbackc'd in a separate putback buffer.
117 In putback mode, the get buffer points to the special putback buffer.
118 The unread characters are the characters between gptr() and egptr()
119 in the putback buffer, as well as the area between save_gptr()
120 and save_egptr(), which point into the original reserve buffer.
121 (The pointers save_gptr() and save_egptr() are the values
122 of gptr() and egptr() at the time putback mode was entered.)
123 The OS position corresponds to that of save_egptr().
125 LINE BUFFERED OUTPUT:
126 During line buffered output, _IO_write_base==base() && epptr()==base().
127 However, ptr() may be anywhere between base() and ebuf().
128 This forces a call to filebuf::overflow(int C) on every put.
129 If there is more space in the buffer, and C is not a '\n',
130 then C is inserted, and pptr() incremented.
132 UNBUFFERED STREAMS:
133 If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
136 #define CLOSED_FILEBUF_FLAGS \
137 (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
140 void
141 _IO_new_file_init (fp)
142 struct _IO_FILE_plus *fp;
144 /* POSIX.1 allows another file handle to be used to change the position
145 of our file descriptor. Hence we actually don't know the actual
146 position before we do the first fseek (and until a following fflush). */
147 fp->file._offset = _IO_pos_BAD;
148 fp->file._IO_file_flags |= CLOSED_FILEBUF_FLAGS;
150 _IO_link_in (fp);
151 fp->file._fileno = -1;
155 _IO_new_file_close_it (fp)
156 _IO_FILE *fp;
158 int write_status, close_status;
159 if (!_IO_file_is_open (fp))
160 return EOF;
162 write_status = _IO_do_flush (fp);
164 _IO_unsave_markers(fp);
166 close_status = _IO_SYSCLOSE (fp);
168 /* Free buffer. */
169 if (fp->_mode <= 0)
171 _IO_setb (fp, NULL, NULL, 0);
172 _IO_setg (fp, NULL, NULL, NULL);
173 _IO_setp (fp, NULL, NULL);
175 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
176 else
178 _IO_wsetb (fp, NULL, NULL, 0);
179 _IO_wsetg (fp, NULL, NULL, NULL);
180 _IO_wsetp (fp, NULL, NULL);
182 #endif
184 _IO_un_link ((struct _IO_FILE_plus *) fp);
185 fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
186 fp->_fileno = -1;
187 fp->_offset = _IO_pos_BAD;
189 return close_status ? close_status : write_status;
192 void
193 _IO_new_file_finish (fp, dummy)
194 _IO_FILE *fp;
195 int dummy;
197 if (_IO_file_is_open (fp))
199 _IO_do_flush (fp);
200 if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
201 _IO_SYSCLOSE (fp);
203 _IO_default_finish (fp, 0);
206 #if defined __GNUC__ && __GNUC__ >= 2
207 __inline__
208 #endif
209 _IO_FILE *
210 _IO_file_open (fp, filename, posix_mode, prot, read_write, is32not64)
211 _IO_FILE *fp;
212 const char *filename;
213 int posix_mode;
214 int prot;
215 int read_write;
216 int is32not64;
218 int fdesc;
219 #ifdef _G_OPEN64
220 fdesc = (is32not64
221 ? open (filename, posix_mode, prot)
222 : _G_OPEN64 (filename, posix_mode, prot));
223 #else
224 fdesc = open (filename, posix_mode, prot);
225 #endif
226 if (fdesc < 0)
227 return NULL;
228 fp->_fileno = fdesc;
229 _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
230 if (read_write & _IO_IS_APPENDING)
231 if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
232 == _IO_pos_BAD && errno != ESPIPE)
233 return NULL;
234 _IO_link_in ((struct _IO_FILE_plus *) fp);
235 return fp;
238 _IO_FILE *
239 _IO_new_file_fopen (fp, filename, mode, is32not64)
240 _IO_FILE *fp;
241 const char *filename;
242 const char *mode;
243 int is32not64;
245 int oflags = 0, omode;
246 int read_write;
247 int oprot = 0666;
248 int i;
249 _IO_FILE *result;
250 #ifdef _LIBC
251 const char *cs;
252 const char *last_recognized;
253 #endif
255 if (_IO_file_is_open (fp))
256 return 0;
257 switch (*mode)
259 case 'r':
260 omode = O_RDONLY;
261 read_write = _IO_NO_WRITES;
262 break;
263 case 'w':
264 omode = O_WRONLY;
265 oflags = O_CREAT|O_TRUNC;
266 read_write = _IO_NO_READS;
267 break;
268 case 'a':
269 omode = O_WRONLY;
270 oflags = O_CREAT|O_APPEND;
271 read_write = _IO_NO_READS|_IO_IS_APPENDING;
272 break;
273 default:
274 __set_errno (EINVAL);
275 return NULL;
277 #ifdef _LIBC
278 last_recognized = mode;
279 #endif
280 for (i = 1; i < 4; ++i)
282 switch (*++mode)
284 case '\0':
285 break;
286 case '+':
287 omode = O_RDWR;
288 read_write &= _IO_IS_APPENDING;
289 #ifdef _LIBC
290 last_recognized = mode;
291 #endif
292 continue;
293 case 'x':
294 oflags |= O_EXCL;
295 #ifdef _LIBC
296 last_recognized = mode;
297 #endif
298 continue;
299 case 'b':
300 #ifdef _LIBC
301 last_recognized = mode;
302 #endif
303 default:
304 /* Ignore. */
305 continue;
307 break;
310 result = _IO_file_open (fp, filename, omode|oflags, oprot, read_write,
311 is32not64);
314 #ifdef _LIBC
315 if (result != NULL)
317 /* Test whether the mode string specifies the conversion. */
318 cs = strstr (last_recognized + 1, ",ccs=");
319 if (cs != NULL)
321 /* Yep. Load the appropriate conversions and set the orientation
322 to wide. */
323 struct gconv_fcts fcts;
324 struct _IO_codecvt *cc;
325 char *endp = __strchrnul (cs + 5, ',');
326 char ccs[endp - (cs + 5) + 3];
328 *((char *) __mempcpy (ccs, cs + 5, endp - (cs + 5))) = '\0';
329 strip (ccs, ccs);
331 if (__wcsmbs_named_conv (&fcts, ccs[2] == '\0'
332 ? upstr (ccs, cs + 5) : ccs) != 0)
334 /* Something went wrong, we cannot load the conversion modules.
335 This means we cannot proceed since the user explicitly asked
336 for these. */
337 __set_errno (EINVAL);
338 return NULL;
341 assert (fcts.towc_nsteps == 1);
342 assert (fcts.tomb_nsteps == 1);
344 fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
345 fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_base;
347 /* Clear the state. We start all over again. */
348 memset (&fp->_wide_data->_IO_state, '\0', sizeof (__mbstate_t));
349 memset (&fp->_wide_data->_IO_last_state, '\0', sizeof (__mbstate_t));
351 cc = fp->_codecvt = &fp->_wide_data->_codecvt;
353 /* The functions are always the same. */
354 *cc = __libio_codecvt;
356 cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps;
357 cc->__cd_in.__cd.__steps = fcts.towc;
359 cc->__cd_in.__cd.__data[0].__invocation_counter = 0;
360 cc->__cd_in.__cd.__data[0].__internal_use = 1;
361 cc->__cd_in.__cd.__data[0].__flags = __GCONV_IS_LAST;
362 cc->__cd_in.__cd.__data[0].__statep = &result->_wide_data->_IO_state;
364 /* XXX For now no transliteration. */
365 cc->__cd_in.__cd.__data[0].__trans = NULL;
367 cc->__cd_out.__cd.__nsteps = fcts.tomb_nsteps;
368 cc->__cd_out.__cd.__steps = fcts.tomb;
370 cc->__cd_out.__cd.__data[0].__invocation_counter = 0;
371 cc->__cd_out.__cd.__data[0].__internal_use = 1;
372 cc->__cd_out.__cd.__data[0].__flags = __GCONV_IS_LAST;
373 cc->__cd_out.__cd.__data[0].__statep =
374 &result->_wide_data->_IO_state;
376 /* And now the transliteration. */
377 cc->__cd_out.__cd.__data[0].__trans = &__libio_translit;
379 /* Set the mode now. */
380 result->_mode = 1;
382 /* We don't need the step data structure anymore. */
383 __gconv_release_cache (fcts.towc, fcts.towc_nsteps);
384 __gconv_release_cache (fcts.tomb, fcts.tomb_nsteps);
387 #endif /* GNU libc */
389 return result;
392 _IO_FILE *
393 _IO_new_file_attach (fp, fd)
394 _IO_FILE *fp;
395 int fd;
397 if (_IO_file_is_open (fp))
398 return NULL;
399 fp->_fileno = fd;
400 fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
401 fp->_flags |= _IO_DELETE_DONT_CLOSE;
402 /* Get the current position of the file. */
403 /* We have to do that since that may be junk. */
404 fp->_offset = _IO_pos_BAD;
405 if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
406 == _IO_pos_BAD && errno != ESPIPE)
407 return NULL;
408 return fp;
411 _IO_FILE *
412 _IO_new_file_setbuf (fp, p, len)
413 _IO_FILE *fp;
414 char *p;
415 _IO_ssize_t len;
417 if (_IO_default_setbuf (fp, p, len) == NULL)
418 return NULL;
420 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
421 = fp->_IO_buf_base;
422 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
424 return fp;
427 static int new_do_write __P ((_IO_FILE *, const char *, _IO_size_t));
429 /* Write TO_DO bytes from DATA to FP.
430 Then mark FP as having empty buffers. */
433 _IO_new_do_write (fp, data, to_do)
434 _IO_FILE *fp;
435 const char *data;
436 _IO_size_t to_do;
438 return (to_do == 0 || new_do_write (fp, data, to_do) == to_do) ? 0 : EOF;
441 static
443 new_do_write (fp, data, to_do)
444 _IO_FILE *fp;
445 const char *data;
446 _IO_size_t to_do;
448 _IO_size_t count;
449 if (fp->_flags & _IO_IS_APPENDING)
450 /* On a system without a proper O_APPEND implementation,
451 you would need to sys_seek(0, SEEK_END) here, but is
452 is not needed nor desirable for Unix- or Posix-like systems.
453 Instead, just indicate that offset (before and after) is
454 unpredictable. */
455 fp->_offset = _IO_pos_BAD;
456 else if (fp->_IO_read_end != fp->_IO_write_base)
458 _IO_off64_t new_pos
459 = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
460 if (new_pos == _IO_pos_BAD)
461 return 0;
462 fp->_offset = new_pos;
464 count = _IO_SYSWRITE (fp, data, to_do);
465 if (fp->_cur_column && count)
466 fp->_cur_column = _IO_adjust_column (fp->_cur_column - 1, data, count) + 1;
467 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
468 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
469 fp->_IO_write_end = (fp->_mode <= 0
470 && (fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
471 ? fp->_IO_buf_base : fp->_IO_buf_end);
472 return count;
476 _IO_new_file_underflow (fp)
477 _IO_FILE *fp;
479 _IO_ssize_t count;
480 #if 0
481 /* SysV does not make this test; take it out for compatibility */
482 if (fp->_flags & _IO_EOF_SEEN)
483 return (EOF);
484 #endif
486 if (fp->_flags & _IO_NO_READS)
488 fp->_flags |= _IO_ERR_SEEN;
489 __set_errno (EBADF);
490 return EOF;
492 if (fp->_IO_read_ptr < fp->_IO_read_end)
493 return *(unsigned char *) fp->_IO_read_ptr;
495 if (fp->_IO_buf_base == NULL)
497 /* Maybe we already have a push back pointer. */
498 if (fp->_IO_save_base != NULL)
500 free (fp->_IO_save_base);
501 fp->_flags &= ~_IO_IN_BACKUP;
503 _IO_doallocbuf (fp);
506 /* Flush all line buffered files before reading. */
507 /* FIXME This can/should be moved to genops ?? */
508 if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
510 #if 0
511 _IO_flush_all_linebuffered ();
512 #else
513 /* We used to flush all line-buffered stream. This really isn't
514 required by any standard. My recollection is that
515 traditional Unix systems did this for stdout. stderr better
516 not be line buffered. So we do just that here
517 explicitly. --drepper */
518 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
519 _IO_stdout);
520 _IO_flockfile (_IO_stdout);
522 if ((_IO_stdout->_flags & (_IO_LINKED | _IO_NO_WRITES | _IO_LINE_BUF))
523 == (_IO_LINKED | _IO_LINE_BUF))
524 _IO_OVERFLOW (_IO_stdout, EOF);
526 _IO_funlockfile (_IO_stdout);
527 _IO_cleanup_region_end (0);
528 #endif
531 _IO_switch_to_get_mode (fp);
533 /* This is very tricky. We have to adjust those
534 pointers before we call _IO_SYSREAD () since
535 we may longjump () out while waiting for
536 input. Those pointers may be screwed up. H.J. */
537 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
538 fp->_IO_read_end = fp->_IO_buf_base;
539 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
540 = fp->_IO_buf_base;
542 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
543 fp->_IO_buf_end - fp->_IO_buf_base);
544 if (count <= 0)
546 if (count == 0)
547 fp->_flags |= _IO_EOF_SEEN;
548 else
549 fp->_flags |= _IO_ERR_SEEN, count = 0;
551 fp->_IO_read_end += count;
552 if (count == 0)
553 return EOF;
554 if (fp->_offset != _IO_pos_BAD)
555 _IO_pos_adjust (fp->_offset, count);
556 return *(unsigned char *) fp->_IO_read_ptr;
560 _IO_new_file_overflow (f, ch)
561 _IO_FILE *f;
562 int ch;
564 if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
566 f->_flags |= _IO_ERR_SEEN;
567 __set_errno (EBADF);
568 return EOF;
570 /* If currently reading or no buffer allocated. */
571 if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0 || f->_IO_write_base == 0)
573 /* Allocate a buffer if needed. */
574 if (f->_IO_write_base == 0)
576 _IO_doallocbuf (f);
577 _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
579 /* Otherwise must be currently reading.
580 If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
581 logically slide the buffer forwards one block (by setting the
582 read pointers to all point at the beginning of the block). This
583 makes room for subsequent output.
584 Otherwise, set the read pointers to _IO_read_end (leaving that
585 alone, so it can continue to correspond to the external position). */
586 if (f->_IO_read_ptr == f->_IO_buf_end)
587 f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
588 f->_IO_write_ptr = f->_IO_read_ptr;
589 f->_IO_write_base = f->_IO_write_ptr;
590 f->_IO_write_end = f->_IO_buf_end;
591 f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
593 f->_flags |= _IO_CURRENTLY_PUTTING;
594 if (f->_mode <= 0 && f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
595 f->_IO_write_end = f->_IO_write_ptr;
597 if (ch == EOF)
598 return _IO_new_do_write(f, f->_IO_write_base,
599 f->_IO_write_ptr - f->_IO_write_base);
600 if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
601 if (_IO_do_flush (f) == EOF)
602 return EOF;
603 *f->_IO_write_ptr++ = ch;
604 if ((f->_flags & _IO_UNBUFFERED)
605 || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
606 if (_IO_new_do_write(f, f->_IO_write_base,
607 f->_IO_write_ptr - f->_IO_write_base) == EOF)
608 return EOF;
609 return (unsigned char) ch;
613 _IO_new_file_sync (fp)
614 _IO_FILE *fp;
616 _IO_ssize_t delta;
617 int retval = 0;
619 /* char* ptr = cur_ptr(); */
620 if (fp->_IO_write_ptr > fp->_IO_write_base)
621 if (_IO_do_flush(fp)) return EOF;
622 delta = fp->_IO_read_ptr - fp->_IO_read_end;
623 if (delta != 0)
625 #ifdef TODO
626 if (_IO_in_backup (fp))
627 delta -= eGptr () - Gbase ();
628 #endif
629 _IO_off64_t new_pos = _IO_SYSSEEK (fp, delta, 1);
630 if (new_pos != (_IO_off64_t) EOF)
631 fp->_IO_read_end = fp->_IO_read_ptr;
632 #ifdef ESPIPE
633 else if (errno == ESPIPE)
634 ; /* Ignore error from unseekable devices. */
635 #endif
636 else
637 retval = EOF;
639 if (retval != EOF)
640 fp->_offset = _IO_pos_BAD;
641 /* FIXME: Cleanup - can this be shared? */
642 /* setg(base(), ptr, ptr); */
643 return retval;
646 _IO_off64_t
647 _IO_new_file_seekoff (fp, offset, dir, mode)
648 _IO_FILE *fp;
649 _IO_off64_t offset;
650 int dir;
651 int mode;
653 _IO_off64_t result;
654 _IO_off64_t delta, new_offset;
655 long count;
656 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
657 offset of the underlying file must be exact. */
658 int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
659 && fp->_IO_write_base == fp->_IO_write_ptr);
661 if (mode == 0)
662 dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
664 /* Flush unwritten characters.
665 (This may do an unneeded write if we seek within the buffer.
666 But to be able to switch to reading, we would need to set
667 egptr to ptr. That can't be done in the current design,
668 which assumes file_ptr() is eGptr. Anyway, since we probably
669 end up flushing when we close(), it doesn't make much difference.)
670 FIXME: simulate mem-papped files. */
672 if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
673 if (_IO_switch_to_get_mode (fp))
674 return EOF;
676 if (fp->_IO_buf_base == NULL)
678 /* It could be that we already have a pushback buffer. */
679 if (fp->_IO_read_base != NULL)
681 free (fp->_IO_read_base);
682 fp->_flags &= ~_IO_IN_BACKUP;
684 _IO_doallocbuf (fp);
685 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
686 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
689 switch (dir)
691 case _IO_seek_cur:
692 /* Adjust for read-ahead (bytes is buffer). */
693 offset -= fp->_IO_read_end - fp->_IO_read_ptr;
694 if (fp->_offset == _IO_pos_BAD)
695 goto dumb;
696 /* Make offset absolute, assuming current pointer is file_ptr(). */
697 offset += fp->_offset;
699 dir = _IO_seek_set;
700 break;
701 case _IO_seek_set:
702 break;
703 case _IO_seek_end:
705 struct _G_stat64 st;
706 if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
708 offset += st.st_size;
709 dir = _IO_seek_set;
711 else
712 goto dumb;
715 /* At this point, dir==_IO_seek_set. */
717 /* If we are only interested in the current position we've found it now. */
718 if (mode == 0)
719 return offset;
721 /* If destination is within current buffer, optimize: */
722 if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
723 && !_IO_in_backup (fp))
725 /* Offset relative to start of main get area. */
726 _IO_off64_t rel_offset = (offset - fp->_offset
727 + (fp->_IO_read_end - fp->_IO_read_base));
728 if (rel_offset >= 0)
730 #if 0
731 if (_IO_in_backup (fp))
732 _IO_switch_to_main_get_area (fp);
733 #endif
734 if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
736 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
737 fp->_IO_read_end);
738 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
740 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
741 goto resync;
744 #ifdef TODO
745 /* If we have streammarkers, seek forward by reading ahead. */
746 if (_IO_have_markers (fp))
748 int to_skip = rel_offset
749 - (fp->_IO_read_ptr - fp->_IO_read_base);
750 if (ignore (to_skip) != to_skip)
751 goto dumb;
752 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
753 goto resync;
755 #endif
757 #ifdef TODO
758 if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ())
760 if (!_IO_in_backup (fp))
761 _IO_switch_to_backup_area (fp);
762 gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
763 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
764 goto resync;
766 #endif
769 #ifdef TODO
770 _IO_unsave_markers (fp);
771 #endif
773 if (fp->_flags & _IO_NO_READS)
774 goto dumb;
776 /* Try to seek to a block boundary, to improve kernel page management. */
777 new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
778 delta = offset - new_offset;
779 if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
781 new_offset = offset;
782 delta = 0;
784 result = _IO_SYSSEEK (fp, new_offset, 0);
785 if (result < 0)
786 return EOF;
787 if (delta == 0)
788 count = 0;
789 else
791 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
792 (must_be_exact
793 ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
794 if (count < delta)
796 /* We weren't allowed to read, but try to seek the remainder. */
797 offset = count == EOF ? delta : delta-count;
798 dir = _IO_seek_cur;
799 goto dumb;
802 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
803 fp->_IO_buf_base + count);
804 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
805 fp->_offset = result + count;
806 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
807 return offset;
808 dumb:
810 _IO_unsave_markers (fp);
811 result = _IO_SYSSEEK (fp, offset, dir);
812 if (result != EOF)
814 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
815 fp->_offset = result;
816 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
817 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
819 return result;
821 resync:
822 /* We need to do it since it is possible that the file offset in
823 the kernel may be changed behind our back. It may happen when
824 we fopen a file and then do a fork. One process may access the
825 the file and the kernel file offset will be changed. */
826 if (fp->_offset >= 0)
827 _IO_SYSSEEK (fp, fp->_offset, 0);
829 return offset;
832 _IO_ssize_t
833 _IO_file_read (fp, buf, size)
834 _IO_FILE *fp;
835 void *buf;
836 _IO_ssize_t size;
838 return read (fp->_fileno, buf, size);
841 _IO_off64_t
842 _IO_file_seek (fp, offset, dir)
843 _IO_FILE *fp;
844 _IO_off64_t offset;
845 int dir;
847 #ifdef _G_LSEEK64
848 return _G_LSEEK64 (fp->_fileno, offset, dir);
849 #else
850 return lseek (fp->_fileno, offset, dir);
851 #endif
855 _IO_file_stat (fp, st)
856 _IO_FILE *fp;
857 void *st;
859 #ifdef _G_FSTAT64
860 return _G_FSTAT64 (fp->_fileno, (struct _G_stat64 *) st);
861 #else
862 return fstat (fp->_fileno, (struct stat *) st);
863 #endif
867 _IO_file_close (fp)
868 _IO_FILE *fp;
870 return close (fp->_fileno);
873 _IO_ssize_t
874 _IO_new_file_write (f, data, n)
875 _IO_FILE *f;
876 const void *data;
877 _IO_ssize_t n;
879 _IO_ssize_t to_do = n;
880 while (to_do > 0)
882 _IO_ssize_t count = write (f->_fileno, data, to_do);
883 if (count < 0)
885 f->_flags |= _IO_ERR_SEEN;
886 break;
888 to_do -= count;
889 data = (void *) ((char *) data + count);
891 n -= to_do;
892 if (f->_offset >= 0)
893 f->_offset += n;
894 return n;
897 _IO_size_t
898 _IO_new_file_xsputn (f, data, n)
899 _IO_FILE *f;
900 const void *data;
901 _IO_size_t n;
903 register const char *s = (const char *) data;
904 _IO_size_t to_do = n;
905 int must_flush = 0;
906 _IO_size_t count;
908 if (n <= 0)
909 return 0;
910 /* This is an optimized implementation.
911 If the amount to be written straddles a block boundary
912 (or the filebuf is unbuffered), use sys_write directly. */
914 /* First figure out how much space is available in the buffer. */
915 count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
916 if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
918 count = f->_IO_buf_end - f->_IO_write_ptr;
919 if (count >= n)
921 register const char *p;
922 for (p = s + n; p > s; )
924 if (*--p == '\n')
926 count = p - s + 1;
927 must_flush = 1;
928 break;
933 /* Then fill the buffer. */
934 if (count > 0)
936 if (count > to_do)
937 count = to_do;
938 if (count > 20)
940 #ifdef _LIBC
941 f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
942 #else
943 memcpy (f->_IO_write_ptr, s, count);
944 f->_IO_write_ptr += count;
945 #endif
946 s += count;
948 else
950 register char *p = f->_IO_write_ptr;
951 register int i = (int) count;
952 while (--i >= 0)
953 *p++ = *s++;
954 f->_IO_write_ptr = p;
956 to_do -= count;
958 if (to_do + must_flush > 0)
960 _IO_size_t block_size, do_write;
961 /* Next flush the (full) buffer. */
962 if (_IO_OVERFLOW (f, EOF) == EOF)
963 return n - to_do;
965 /* Try to maintain alignment: write a whole number of blocks.
966 dont_write is what gets left over. */
967 block_size = f->_IO_buf_end - f->_IO_buf_base;
968 do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
970 if (do_write)
972 count = new_do_write (f, s, do_write);
973 to_do -= count;
974 if (count < do_write)
975 return n - to_do;
978 /* Now write out the remainder. Normally, this will fit in the
979 buffer, but it's somewhat messier for line-buffered files,
980 so we let _IO_default_xsputn handle the general case. */
981 if (to_do)
982 to_do -= _IO_default_xsputn (f, s+do_write, to_do);
984 return n - to_do;
987 _IO_size_t
988 _IO_file_xsgetn (fp, data, n)
989 _IO_FILE *fp;
990 void *data;
991 _IO_size_t n;
993 register _IO_size_t want, have;
994 register _IO_ssize_t count;
995 register char *s = data;
997 want = n;
999 if (fp->_IO_buf_base == NULL)
1001 /* Maybe we already have a push back pointer. */
1002 if (fp->_IO_save_base != NULL)
1004 free (fp->_IO_save_base);
1005 fp->_flags &= ~_IO_IN_BACKUP;
1007 _IO_doallocbuf (fp);
1010 while (want > 0)
1012 have = fp->_IO_read_end - fp->_IO_read_ptr;
1013 if (want <= have)
1015 memcpy (s, fp->_IO_read_ptr, want);
1016 fp->_IO_read_ptr += want;
1017 want = 0;
1019 else
1021 if (have > 0)
1023 #ifdef _LIBC
1024 s = __mempcpy (s, fp->_IO_read_ptr, have);
1025 #else
1026 memcpy (s, fp->_IO_read_ptr, have);
1027 s += have;
1028 #endif
1029 want -= have;
1030 fp->_IO_read_ptr += have;
1033 /* Check for backup and repeat */
1034 if (_IO_in_backup (fp))
1036 _IO_switch_to_main_get_area (fp);
1037 continue;
1040 /* If we now want less than a buffer, underflow and repeat
1041 the copy. Otherwise, _IO_SYSREAD directly to
1042 the user buffer. */
1043 if (fp->_IO_buf_base && want < fp->_IO_buf_end - fp->_IO_buf_base)
1045 if (__underflow (fp) == EOF)
1046 break;
1048 continue;
1051 /* These must be set before the sysread as we might longjmp out
1052 waiting for input. */
1053 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
1054 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
1056 /* Try to maintain alignment: read a whole number of blocks. */
1057 count = want;
1058 if (fp->_IO_buf_base)
1060 _IO_size_t block_size = fp->_IO_buf_end - fp->_IO_buf_base;
1061 if (block_size >= 128)
1062 count -= want % block_size;
1065 count = _IO_SYSREAD (fp, s, count);
1066 if (count <= 0)
1068 if (count == 0)
1069 fp->_flags |= _IO_EOF_SEEN;
1070 else
1071 fp->_flags |= _IO_ERR_SEEN;
1073 break;
1076 s += count;
1077 want -= count;
1078 if (fp->_offset != _IO_pos_BAD)
1079 _IO_pos_adjust (fp->_offset, count);
1083 return n - want;
1086 struct _IO_jump_t _IO_file_jumps =
1088 JUMP_INIT_DUMMY,
1089 JUMP_INIT(finish, _IO_new_file_finish),
1090 JUMP_INIT(overflow, _IO_new_file_overflow),
1091 JUMP_INIT(underflow, _IO_new_file_underflow),
1092 JUMP_INIT(uflow, _IO_default_uflow),
1093 JUMP_INIT(pbackfail, _IO_default_pbackfail),
1094 JUMP_INIT(xsputn, _IO_new_file_xsputn),
1095 JUMP_INIT(xsgetn, _IO_file_xsgetn),
1096 JUMP_INIT(seekoff, _IO_new_file_seekoff),
1097 JUMP_INIT(seekpos, _IO_default_seekpos),
1098 JUMP_INIT(setbuf, _IO_new_file_setbuf),
1099 JUMP_INIT(sync, _IO_new_file_sync),
1100 JUMP_INIT(doallocate, _IO_file_doallocate),
1101 JUMP_INIT(read, _IO_file_read),
1102 JUMP_INIT(write, _IO_new_file_write),
1103 JUMP_INIT(seek, _IO_file_seek),
1104 JUMP_INIT(close, _IO_file_close),
1105 JUMP_INIT(stat, _IO_file_stat),
1106 JUMP_INIT(showmanyc, _IO_default_showmanyc),
1107 JUMP_INIT(imbue, _IO_default_imbue)
1110 #ifdef _LIBC
1111 versioned_symbol (libc, _IO_new_do_write, _IO_do_write, GLIBC_2_1);
1112 versioned_symbol (libc, _IO_new_file_attach, _IO_file_attach, GLIBC_2_1);
1113 versioned_symbol (libc, _IO_new_file_close_it, _IO_file_close_it, GLIBC_2_1);
1114 versioned_symbol (libc, _IO_new_file_finish, _IO_file_finish, GLIBC_2_1);
1115 versioned_symbol (libc, _IO_new_file_fopen, _IO_file_fopen, GLIBC_2_1);
1116 versioned_symbol (libc, _IO_new_file_init, _IO_file_init, GLIBC_2_1);
1117 versioned_symbol (libc, _IO_new_file_setbuf, _IO_file_setbuf, GLIBC_2_1);
1118 versioned_symbol (libc, _IO_new_file_sync, _IO_file_sync, GLIBC_2_1);
1119 versioned_symbol (libc, _IO_new_file_overflow, _IO_file_overflow, GLIBC_2_1);
1120 versioned_symbol (libc, _IO_new_file_seekoff, _IO_file_seekoff, GLIBC_2_1);
1121 versioned_symbol (libc, _IO_new_file_underflow, _IO_file_underflow, GLIBC_2_1);
1122 versioned_symbol (libc, _IO_new_file_write, _IO_file_write, GLIBC_2_1);
1123 versioned_symbol (libc, _IO_new_file_xsputn, _IO_file_xsputn, GLIBC_2_1);
1124 #endif