/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include #include #include #include #include #include #include #include #include #include /* Note: We set _fillsize to 512, and use that for reading instead of _bufsize, for performance reasons. We double _fillsize each time we read here, and reset it to 512 each time we call fseek. That way, we don't waste time reading data we won't use, or doing lots of small reads we could optimize. If we do lots of seeking, we'll end up maintaining small read sizes, but if we don't seek, we'll eventually read blocks as large as the transfer buffer. */ int _filbuf(FILE *f) { int fillsize; size_t size; char c; if (f->_flag & _IORW) f->_flag |= _IOREAD; if (!(f->_flag & _IOREAD)) { f->_flag |= _IOERR; return EOF; } if (f->_flag & (_IOSTRG | _IOEOF)) return EOF; f->_flag &= ~_IOUNGETC; if (f->_base == NULL && !(f->_flag & _IONBF)) { size = __tb_size; if ((f->_base = (char *)malloc(size)) == NULL) { f->_flag |= _IONBF; f->_flag &= ~(_IOFBF | _IOLBF); } else { f->_flag |= _IOMYBUF; f->_bufsiz = size; f->_fillsize = 512; } } if (f->_flag & _IONBF) f->_base = &c; if (f == stdin) { if (stdout->_flag & _IOLBF) fflush(stdout); if (stderr->_flag & _IOLBF) fflush(stderr); } /* don't read too much! */ if (f->_fillsize > f->_bufsiz) f->_fillsize = f->_bufsiz; /* This next bit makes it so that the cumulative amount read always aligns with file cluster boundaries; i.e. 512, then 2048 (512+1536), then 4096 (2048+2048) etc. */ fillsize = f->_fillsize; if (fillsize == 1024 && f->_bufsiz >= 1536) fillsize = 1536; size = f->_flag & _IONBF ? 1 : fillsize; /* If termios hooked this handle, let it process the request. Note that we only call the termios hook for the handles which are marked by getc or fread to be hooked by termios. This is because termios converts CR+LF to NL for text-mode handles, and thus getc and fread must know to treat the hooked handles as if they were binary, i.e. not to strip away CR characters. */ if ((f->_flag & _IOTERM) == 0 || __libc_read_termios_hook == NULL || __libc_read_termios_hook(fileno(f), f->_base, size, &f->_cnt) == 0) { f->_cnt = _read(fileno(f), f->_base, size); if (__is_text_file(f) && f->_cnt > 0) { /* truncate text file at Ctrl-Z */ char *cz = (char *)memchr(f->_base, 0x1A, (size_t)f->_cnt); if (cz) { int newcnt = cz - f->_base; lseek(fileno(f), -(f->_cnt - newcnt), SEEK_CUR); f->_cnt = newcnt; } } } /* Read more next time, if we don't seek */ if (f->_fillsize < f->_bufsiz) f->_fillsize *= 2; f->_ptr = f->_base; if (f->_flag & _IONBF) f->_base = NULL; if (--f->_cnt < 0) { if (f->_cnt == -1) { f->_flag |= _IOEOF; if (f->_flag & _IORW) f->_flag &= ~_IOREAD; } else f->_flag |= _IOERR; f->_cnt = 0; return EOF; } return *f->_ptr++ & 0377; }