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,
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. */
29 # define _POSIX_SOURCE
33 #include <sys/types.h>
41 # include "../wcsmbs/wcsmbsload.h"
42 # include <shlib-compat.h>
48 # define __set_errno(Val) errno = (Val)
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)
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
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(). (?)
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.
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().
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.
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)
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
;
139 fp
->file
._fileno
= -1;
143 _IO_new_file_close_it (fp
)
146 int write_status
, close_status
;
147 if (!_IO_file_is_open (fp
))
150 write_status
= _IO_do_flush (fp
);
152 _IO_unsave_markers(fp
);
154 close_status
= _IO_SYSCLOSE (fp
);
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
166 _IO_wsetb (fp
, NULL
, NULL
, 0);
167 _IO_wsetg (fp
, NULL
, NULL
, NULL
);
168 _IO_wsetp (fp
, NULL
, NULL
);
172 _IO_un_link ((struct _IO_FILE_plus
*) fp
);
173 fp
->_flags
= _IO_MAGIC
|CLOSED_FILEBUF_FLAGS
;
175 fp
->_offset
= _IO_pos_BAD
;
177 return close_status
? close_status
: write_status
;
181 _IO_new_file_finish (fp
, dummy
)
185 if (_IO_file_is_open (fp
))
188 if (!(fp
->_flags
& _IO_DELETE_DONT_CLOSE
))
191 _IO_default_finish (fp
, 0);
194 #if defined __GNUC__ && __GNUC__ >= 2
198 _IO_file_open (fp
, filename
, posix_mode
, prot
, read_write
, is32not64
)
200 const char *filename
;
209 ? open (filename
, posix_mode
, prot
)
210 : _G_OPEN64 (filename
, posix_mode
, prot
));
212 fdesc
= open (filename
, posix_mode
, prot
);
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
)
222 _IO_link_in ((struct _IO_FILE_plus
*) fp
);
227 _IO_new_file_fopen (fp
, filename
, mode
, is32not64
)
229 const char *filename
;
233 int oflags
= 0, omode
;
242 if (_IO_file_is_open (fp
))
248 read_write
= _IO_NO_WRITES
;
252 oflags
= O_CREAT
|O_TRUNC
;
253 read_write
= _IO_NO_READS
;
257 oflags
= O_CREAT
|O_APPEND
;
258 read_write
= _IO_NO_READS
|_IO_IS_APPENDING
;
261 __set_errno (EINVAL
);
264 for (i
= 1; i
< 4; ++i
)
272 read_write
&= _IO_IS_APPENDING
;
285 result
= _IO_file_open (fp
, filename
, omode
|oflags
, oprot
, read_write
,
290 /* Test whether the mode string specifies the conversion. */
291 cs
= strstr (mode
, ",ccs=");
294 /* Yep. Load the appropriate conversions and set the orientation
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
304 _IO_new_fclose (result
);
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. */
332 #endif /* GNU libc */
338 _IO_new_file_attach (fp
, fd
)
342 if (_IO_file_is_open (fp
))
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
)
357 _IO_new_file_setbuf (fp
, p
, len
)
362 if (_IO_default_setbuf (fp
, p
, len
) == NULL
)
365 fp
->_IO_write_base
= fp
->_IO_write_ptr
= fp
->_IO_write_end
367 _IO_setg (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
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
)
383 return (to_do
== 0 || new_do_write (fp
, data
, to_do
) == to_do
) ? 0 : EOF
;
388 new_do_write (fp
, data
, to_do
)
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
400 fp
->_offset
= _IO_pos_BAD
;
401 else if (fp
->_IO_read_end
!= fp
->_IO_write_base
)
404 = _IO_SYSSEEK (fp
, fp
->_IO_write_base
- fp
->_IO_read_end
, 1);
405 if (new_pos
== _IO_pos_BAD
)
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
);
421 _IO_new_file_underflow (fp
)
426 /* SysV does not make this test; take it out for compatibility */
427 if (fp
->_flags
& _IO_EOF_SEEN
)
431 if (fp
->_flags
& _IO_NO_READS
)
433 fp
->_flags
|= _IO_ERR_SEEN
;
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
;
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
467 count
= _IO_SYSREAD (fp
, fp
->_IO_buf_base
,
468 fp
->_IO_buf_end
- fp
->_IO_buf_base
);
472 fp
->_flags
|= _IO_EOF_SEEN
;
474 fp
->_flags
|= _IO_ERR_SEEN
, count
= 0;
476 fp
->_IO_read_end
+= count
;
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
)
489 if (f
->_flags
& _IO_NO_WRITES
) /* SET ERROR */
491 f
->_flags
|= _IO_ERR_SEEN
;
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)
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
;
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
)
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
)
534 return (unsigned char) ch
;
538 _IO_new_file_sync (fp
)
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
;
551 if (_IO_in_backup (fp
))
552 delta
-= eGptr () - Gbase ();
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
;
558 else if (errno
== ESPIPE
)
559 ; /* Ignore error from unseekable devices. */
565 fp
->_offset
= _IO_pos_BAD
;
566 /* FIXME: Cleanup - can this be shared? */
567 /* setg(base(), ptr, ptr); */
572 _IO_new_file_seekoff (fp
, offset
, dir
, mode
)
579 _IO_off64_t delta
, new_offset
;
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
);
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
))
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
;
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
);
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
)
621 /* Make offset absolute, assuming current pointer is file_ptr(). */
622 offset
+= fp
->_offset
;
631 if (_IO_SYSSTAT (fp
, &st
) == 0 && S_ISREG (st
.st_mode
))
633 offset
+= st
.st_size
;
640 /* At this point, dir==_IO_seek_set. */
642 /* If we are only interested in the current position we've found it now. */
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
));
656 if (_IO_in_backup (fp
))
657 _IO_switch_to_main_get_area (fp
);
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
,
663 _IO_setp (fp
, fp
->_IO_buf_base
, fp
->_IO_buf_base
);
665 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
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
)
677 _IO_mask_flags (fp
, 0, _IO_EOF_SEEN
);
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
);
695 _IO_unsave_markers (fp
);
698 if (fp
->_flags
& _IO_NO_READS
)
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
)
709 result
= _IO_SYSSEEK (fp
, new_offset
, 0);
716 count
= _IO_SYSREAD (fp
, fp
->_IO_buf_base
,
718 ? delta
: fp
->_IO_buf_end
- fp
->_IO_buf_base
));
721 /* We weren't allowed to read, but try to seek the remainder. */
722 offset
= count
== EOF
? delta
: delta
-count
;
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
);
735 _IO_unsave_markers (fp
);
736 result
= _IO_SYSSEEK (fp
, offset
, dir
);
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
);
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);
758 _IO_file_read (fp
, buf
, size
)
763 return read (fp
->_fileno
, buf
, size
);
767 _IO_file_seek (fp
, offset
, dir
)
773 return _G_LSEEK64 (fp
->_fileno
, offset
, dir
);
775 return lseek (fp
->_fileno
, offset
, dir
);
780 _IO_file_stat (fp
, st
)
785 return _G_FSTAT64 (fp
->_fileno
, (struct _G_stat64
*) st
);
787 return fstat (fp
->_fileno
, (struct stat
*) st
);
795 return close (fp
->_fileno
);
799 _IO_new_file_write (f
, data
, n
)
804 _IO_ssize_t to_do
= n
;
807 _IO_ssize_t count
= write (f
->_fileno
, data
, to_do
);
810 f
->_flags
|= _IO_ERR_SEEN
;
814 data
= (void *) ((char *) data
+ count
);
823 _IO_new_file_xsputn (f
, data
, n
)
828 register const char *s
= (const char *) data
;
829 _IO_size_t to_do
= n
;
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
;
846 register const char *p
;
847 for (p
= s
+ n
; p
> s
; )
858 /* Then fill the buffer. */
866 f
->_IO_write_ptr
= __mempcpy (f
->_IO_write_ptr
, s
, count
);
868 memcpy (f
->_IO_write_ptr
, s
, count
);
869 f
->_IO_write_ptr
+= count
;
875 register char *p
= f
->_IO_write_ptr
;
876 register int i
= (int) count
;
879 f
->_IO_write_ptr
= p
;
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
)
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);
897 count
= new_do_write (f
, s
, do_write
);
899 if (count
< do_write
)
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. */
907 to_do
-= _IO_default_xsputn (f
, s
+do_write
, to_do
);
913 _IO_file_xsgetn (fp
, data
, n
)
918 register _IO_size_t want
, have
;
919 register _IO_ssize_t count
;
920 register char *s
= data
;
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
;
937 have
= fp
->_IO_read_end
- fp
->_IO_read_ptr
;
940 memcpy (s
, fp
->_IO_read_ptr
, want
);
941 fp
->_IO_read_ptr
+= want
;
949 s
= __mempcpy (s
, fp
->_IO_read_ptr
, have
);
951 memcpy (s
, fp
->_IO_read_ptr
, 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
);
965 /* If we now want less than a buffer, underflow and repeat
966 the copy. Otherwise, _IO_SYSREAD directly to
968 if (fp
->_IO_buf_base
&& want
< fp
->_IO_buf_end
- fp
->_IO_buf_base
)
970 if (__underflow (fp
) == EOF
)
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. */
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
);
994 fp
->_flags
|= _IO_EOF_SEEN
;
996 fp
->_flags
|= _IO_ERR_SEEN
;
1003 if (fp
->_offset
!= _IO_pos_BAD
)
1004 _IO_pos_adjust (fp
->_offset
, count
);
1011 struct _IO_jump_t _IO_file_jumps
=
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
)
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
);