int attribute_compat_text_section _IO_old_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)) _IO_flush_all_linebuffered (); _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) return EOF; if (fp->_old_offset != _IO_pos_BAD) _IO_pos_adjust (fp->_old_offset, count); return *(unsigned char *) fp->_IO_read_ptr; }
_IO_size_t _IO_file_xsgetn (_IO_FILE *fp, void *data, _IO_size_t n) { _IO_size_t want, have; _IO_ssize_t count; char *s = data; want = n; 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); } while (want > 0) { have = fp->_IO_read_end - fp->_IO_read_ptr; if (want <= have) { memcpy (s, fp->_IO_read_ptr, want); fp->_IO_read_ptr += want; want = 0; } else { if (have > 0) { #ifdef _LIBC s = __mempcpy (s, fp->_IO_read_ptr, have); #else memcpy (s, fp->_IO_read_ptr, have); s += have; #endif want -= have; fp->_IO_read_ptr += have; } /* Check for backup and repeat */ if (_IO_in_backup (fp)) { _IO_switch_to_main_get_area (fp); continue; } /* If we now want less than a buffer, underflow and repeat the copy. Otherwise, _IO_SYSREAD directly to the user buffer. */ if (fp->_IO_buf_base && want < (size_t) (fp->_IO_buf_end - fp->_IO_buf_base)) { if (__underflow (fp) == EOF) break; continue; } /* These must be set before the sysread as we might longjmp out waiting for input. */ _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base); _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base); /* Try to maintain alignment: read a whole number of blocks. */ count = want; if (fp->_IO_buf_base) { _IO_size_t block_size = fp->_IO_buf_end - fp->_IO_buf_base; if (block_size >= 128) count -= want % block_size; } count = _IO_SYSREAD (fp, s, count); if (count <= 0) { if (count == 0) fp->_flags |= _IO_EOF_SEEN; else fp->_flags |= _IO_ERR_SEEN; break; } s += count; want -= count; if (fp->_offset != _IO_pos_BAD) _IO_pos_adjust (fp->_offset, count); } } return n - want; }
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; }
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; }