wint_t __woverflow (FILE *f, wint_t wch) { if (f->_mode == 0) _IO_fwide (f, 1); return _IO_OVERFLOW (f, wch); }
int __overflow (_IO_FILE *f, int ch) { /* This is a single-byte stream. */ if (f->_mode == 0) _IO_fwide (f, -1); return _IO_OVERFLOW (f, ch); }
int _IO_flush_all_lockp (int do_lock) { int result = 0; struct _IO_FILE *fp; int last_stamp; #ifdef _IO_MTSAFE_IO __libc_cleanup_region_start (do_lock, flush_cleanup, NULL); if (do_lock) _IO_lock_lock (list_all_lock); #endif last_stamp = _IO_list_all_stamp; fp = (_IO_FILE *) _IO_list_all; while (fp != NULL) { run_fp = fp; if (do_lock) _IO_flockfile (fp); if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base) #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T || (_IO_vtable_offset (fp) == 0 && fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)) #endif ) && _IO_OVERFLOW (fp, EOF) == EOF) result = EOF; if (do_lock) _IO_funlockfile (fp); run_fp = NULL; if (last_stamp != _IO_list_all_stamp) { /* Something was added to the list. Start all over again. */ fp = (_IO_FILE *) _IO_list_all; last_stamp = _IO_list_all_stamp; } else fp = fp->_chain; } #ifdef _IO_MTSAFE_IO if (do_lock) _IO_lock_unlock (list_all_lock); __libc_cleanup_region_end (0); #endif return result; }
_IO_size_t _IO_default_xsputn (_IO_FILE *f, const void *data, _IO_size_t n) { const char *s = (char *) data; _IO_size_t more = n; if (more <= 0) return 0; for (;;) { /* Space available. */ if (f->_IO_write_ptr < f->_IO_write_end) { _IO_size_t count = f->_IO_write_end - f->_IO_write_ptr; if (count > more) count = more; if (count > 20) { #ifdef _LIBC f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count); #else memcpy (f->_IO_write_ptr, s, count); f->_IO_write_ptr += count; #endif s += count; } else if (count) { char *p = f->_IO_write_ptr; _IO_ssize_t i; for (i = count; --i >= 0; ) *p++ = *s++; f->_IO_write_ptr = p; } more -= count; } if (more == 0 || _IO_OVERFLOW (f, (unsigned char) *s++) == EOF) break; more--; } return n - more; }
int _IO_switch_to_get_mode (_IO_FILE *fp) { if (fp->_IO_write_ptr > fp->_IO_write_base) if (_IO_OVERFLOW (fp, EOF) == EOF) return EOF; if (_IO_in_backup (fp)) fp->_IO_read_base = fp->_IO_backup_base; else { fp->_IO_read_base = fp->_IO_buf_base; if (fp->_IO_write_ptr > fp->_IO_read_end) fp->_IO_read_end = fp->_IO_write_ptr; } fp->_IO_read_ptr = fp->_IO_write_ptr; fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_read_ptr; fp->_flags &= ~_IO_CURRENTLY_PUTTING; return 0; }
void _IO_flush_all_linebuffered (void) { struct _IO_FILE *fp; int last_stamp; #ifdef _IO_MTSAFE_IO _IO_cleanup_region_start_noarg (flush_cleanup); _IO_lock_lock (list_all_lock); #endif last_stamp = _IO_list_all_stamp; fp = (_IO_FILE *) _IO_list_all; while (fp != NULL) { run_fp = fp; _IO_flockfile (fp); if ((fp->_flags & _IO_NO_WRITES) == 0 && fp->_flags & _IO_LINE_BUF) _IO_OVERFLOW (fp, EOF); _IO_funlockfile (fp); run_fp = NULL; if (last_stamp != _IO_list_all_stamp) { /* Something was added to the list. Start all over again. */ fp = (_IO_FILE *) _IO_list_all; last_stamp = _IO_list_all_stamp; } else fp = fp->_chain; } #ifdef _IO_MTSAFE_IO _IO_lock_unlock (list_all_lock); _IO_cleanup_region_end (0); #endif }
int _IO_new_file_underflow (_IO_FILE *fp) { _IO_ssize_t count; #if 0 /* SysV does not make this test; take it out for compatibility */ if (fp->_flags & _IO_EOF_SEEN) return (EOF); #endif if (fp->_flags & _IO_NO_READS) { fp->_flags |= _IO_ERR_SEEN; __set_errno (EBADF); return EOF; } if (fp->_IO_read_ptr < fp->_IO_read_end) return *(unsigned char *) fp->_IO_read_ptr; if (fp->_IO_buf_base == NULL) { /* Maybe we already have a push back pointer. */ if (fp->_IO_save_base != NULL) { free (fp->_IO_save_base); fp->_flags &= ~_IO_IN_BACKUP; } _IO_doallocbuf (fp); } /* Flush all line buffered files before reading. */ /* FIXME This can/should be moved to genops ?? */ if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED)) { #if 0 _IO_flush_all_linebuffered (); #else /* We used to flush all line-buffered stream. This really isn't required by any standard. My recollection is that traditional Unix systems did this for stdout. stderr better not be line buffered. So we do just that here explicitly. --drepper */ _IO_acquire_lock (_IO_stdout); if ((_IO_stdout->_flags & (_IO_LINKED | _IO_NO_WRITES | _IO_LINE_BUF)) == (_IO_LINKED | _IO_LINE_BUF)) _IO_OVERFLOW (_IO_stdout, EOF); _IO_release_lock (_IO_stdout); #endif } _IO_switch_to_get_mode (fp); /* This is very tricky. We have to adjust those pointers before we call _IO_SYSREAD () since we may longjump () out while waiting for input. Those pointers may be screwed up. H.J. */ fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base; fp->_IO_read_end = fp->_IO_buf_base; fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_buf_base; count = _IO_SYSREAD (fp, fp->_IO_buf_base, fp->_IO_buf_end - fp->_IO_buf_base); if (count <= 0) { if (count == 0) fp->_flags |= _IO_EOF_SEEN; else fp->_flags |= _IO_ERR_SEEN, count = 0; } fp->_IO_read_end += count; if (count == 0) { /* If a stream is read to EOF, the calling application may switch active handles. As a result, our offset cache would no longer be valid, so unset it. */ fp->_offset = _IO_pos_BAD; return EOF; } if (fp->_offset != _IO_pos_BAD) _IO_pos_adjust (fp->_offset, count); return *(unsigned char *) fp->_IO_read_ptr; }
_IO_size_t _IO_new_file_xsputn (_IO_FILE *f, const void *data, _IO_size_t n) { const char *s = (const char *) data; _IO_size_t to_do = n; int must_flush = 0; _IO_size_t count = 0; if (n <= 0) return 0; /* This is an optimized implementation. If the amount to be written straddles a block boundary (or the filebuf is unbuffered), use sys_write directly. */ /* First figure out how much space is available in the buffer. */ if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING)) { count = f->_IO_buf_end - f->_IO_write_ptr; if (count >= n) { const char *p; for (p = s + n; p > s; ) { if (*--p == '\n') { count = p - s + 1; must_flush = 1; break; } } } } else if (f->_IO_write_end > f->_IO_write_ptr) count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */ /* Then fill the buffer. */ if (count > 0) { if (count > to_do) count = to_do; #ifdef _LIBC f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count); #else memcpy (f->_IO_write_ptr, s, count); f->_IO_write_ptr += count; #endif s += count; to_do -= count; } if (to_do + must_flush > 0) { _IO_size_t block_size, do_write; /* Next flush the (full) buffer. */ if (_IO_OVERFLOW (f, EOF) == EOF) /* If nothing else has to be written we must not signal the caller that everything has been written. */ return to_do == 0 ? EOF : n - to_do; /* Try to maintain alignment: write a whole number of blocks. */ block_size = f->_IO_buf_end - f->_IO_buf_base; do_write = to_do - (block_size >= 128 ? to_do % block_size : 0); if (do_write) { count = new_do_write (f, s, do_write); to_do -= count; if (count < do_write) return n - to_do; } /* Now write out the remainder. Normally, this will fit in the buffer, but it's somewhat messier for line-buffered files, so we let _IO_default_xsputn handle the general case. */ if (to_do) to_do -= _IO_default_xsputn (f, s+do_write, to_do); } return n - to_do; }
wint_t _IO_wfile_underflow (_IO_FILE *fp) { struct _IO_codecvt *cd; enum __codecvt_result status; _IO_ssize_t count; if (__glibc_unlikely (fp->_flags & _IO_NO_READS)) { fp->_flags |= _IO_ERR_SEEN; __set_errno (EBADF); return WEOF; } if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) return *fp->_wide_data->_IO_read_ptr; cd = fp->_codecvt; /* Maybe there is something left in the external buffer. */ if (fp->_IO_read_ptr < fp->_IO_read_end) { /* There is more in the external. Convert it. */ const char *read_stop = (const char *) fp->_IO_read_ptr; fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_buf_base; status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, fp->_IO_read_ptr, fp->_IO_read_end, &read_stop, fp->_wide_data->_IO_read_ptr, fp->_wide_data->_IO_buf_end, &fp->_wide_data->_IO_read_end); fp->_IO_read_base = fp->_IO_read_ptr; fp->_IO_read_ptr = (char *) read_stop; /* If we managed to generate some text return the next character. */ if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) return *fp->_wide_data->_IO_read_ptr; if (status == __codecvt_error) { __set_errno (EILSEQ); fp->_flags |= _IO_ERR_SEEN; return WEOF; } /* Move the remaining content of the read buffer to the beginning. */ memmove (fp->_IO_buf_base, fp->_IO_read_ptr, fp->_IO_read_end - fp->_IO_read_ptr); fp->_IO_read_end = (fp->_IO_buf_base + (fp->_IO_read_end - fp->_IO_read_ptr)); fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base; } else fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = fp->_IO_buf_base; if (fp->_IO_buf_base == NULL) { /* Maybe we already have a push back pointer. */ if (fp->_IO_save_base != NULL) { free (fp->_IO_save_base); fp->_flags &= ~_IO_IN_BACKUP; } _IO_doallocbuf (fp); fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = fp->_IO_buf_base; } fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_buf_base; if (fp->_wide_data->_IO_buf_base == NULL) { /* Maybe we already have a push back pointer. */ if (fp->_wide_data->_IO_save_base != NULL) { free (fp->_wide_data->_IO_save_base); fp->_flags &= ~_IO_IN_BACKUP; } _IO_wdoallocbuf (fp); } /* Flush all line buffered files before reading. */ /* FIXME This can/should be moved to genops ?? */ if (fp->_flags & (_IO_LINE_BUF | _IO_UNBUFFERED)) { #if 0 _IO_flush_all_linebuffered (); #else /* We used to flush all line-buffered stream. This really isn't required by any standard. My recollection is that traditional Unix systems did this for stdout. stderr better not be line buffered. So we do just that here explicitly. --drepper */ _IO_acquire_lock (_IO_stdout); if ((_IO_stdout->_flags & (_IO_LINKED | _IO_NO_WRITES | _IO_LINE_BUF)) == (_IO_LINKED | _IO_LINE_BUF)) _IO_OVERFLOW (_IO_stdout, EOF); _IO_release_lock (_IO_stdout); #endif } _IO_switch_to_get_mode (fp); fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_buf_base; fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_buf_base; fp->_wide_data->_IO_write_base = fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_end = fp->_wide_data->_IO_buf_base; const char *read_ptr_copy; char accbuf[MB_LEN_MAX]; size_t naccbuf = 0; again: count = _IO_SYSREAD (fp, fp->_IO_read_end, fp->_IO_buf_end - fp->_IO_read_end); if (count <= 0) { if (count == 0 && naccbuf == 0) { fp->_flags |= _IO_EOF_SEEN; fp->_offset = _IO_pos_BAD; } else fp->_flags |= _IO_ERR_SEEN, count = 0; } fp->_IO_read_end += count; if (count == 0) { if (naccbuf != 0) /* There are some bytes in the external buffer but they don't convert to anything. */ __set_errno (EILSEQ); return WEOF; } if (fp->_offset != _IO_pos_BAD) _IO_pos_adjust (fp->_offset, count); /* Now convert the read input. */ fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; fp->_IO_read_base = fp->_IO_read_ptr; const char *from = fp->_IO_read_ptr; const char *to = fp->_IO_read_end; size_t to_copy = count; if (__glibc_unlikely (naccbuf != 0)) { to_copy = MIN (sizeof (accbuf) - naccbuf, count); to = __mempcpy (&accbuf[naccbuf], from, to_copy); naccbuf += to_copy; from = accbuf; } status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, from, to, &read_ptr_copy, fp->_wide_data->_IO_read_end, fp->_wide_data->_IO_buf_end, &fp->_wide_data->_IO_read_end); if (__glibc_unlikely (naccbuf != 0)) fp->_IO_read_ptr += MAX (0, read_ptr_copy - &accbuf[naccbuf - to_copy]); else fp->_IO_read_ptr = (char *) read_ptr_copy; if (fp->_wide_data->_IO_read_end == fp->_wide_data->_IO_buf_base) { if (status == __codecvt_error) { out_eilseq: __set_errno (EILSEQ); fp->_flags |= _IO_ERR_SEEN; return WEOF; } /* The read bytes make no complete character. Try reading again. */ assert (status == __codecvt_partial); if (naccbuf == 0) { if (fp->_IO_read_base < fp->_IO_read_ptr) { /* Partially used the buffer for some input data that produces no output. */ size_t avail = fp->_IO_read_end - fp->_IO_read_ptr; memmove (fp->_IO_read_base, fp->_IO_read_ptr, avail); fp->_IO_read_ptr = fp->_IO_read_base; fp->_IO_read_end -= avail; goto again; } naccbuf = fp->_IO_read_end - fp->_IO_read_ptr; if (naccbuf >= sizeof (accbuf)) goto out_eilseq; memcpy (accbuf, fp->_IO_read_ptr, naccbuf); } else { size_t used = read_ptr_copy - accbuf; if (used > 0) { memmove (accbuf, read_ptr_copy, naccbuf - used); naccbuf -= used; } if (naccbuf == sizeof (accbuf)) goto out_eilseq; } fp->_IO_read_ptr = fp->_IO_read_end = fp->_IO_read_base; goto again; } return *fp->_wide_data->_IO_read_ptr; }