fseek/fgetc puzzle
Gert Doering
gert at greenie.muc.de
Tue Feb 21 06:15:44 AEDT 2023
Hi,
On Mon, Feb 20, 2023 at 06:29:22PM +0100, Gert Doering wrote:
> Having read the thread, the only explanation I can come up is that
> mixing fgetc()/fputc() will somehow confuse the stdio buffering.
Job nerd-sniped me into reading OpenIllumos source code, and from
my reading of
https://github.com/illumos/illumos-gate/blob/86d949f9497332fe19be6b5d711d265eb957439f/usr/src/lib/libc/port/stdio/getc.c
https://github.com/illumos/illumos-gate/blob/86d949f9497332fe19be6b5d711d265eb957439f/usr/src/lib/libc/port/stdio/_filbuf.c
the sequence
fseek(-1)
fgetc()
will leave "iop->_cnt" at 0 ("one byte read from file, one byte returned,
0 byte left in buffer"), and then
https://github.com/illumos/illumos-gate/blob/86d949f9497332fe19be6b5d711d265eb957439f/usr/src/lib/libc/port/stdio/putc.c
putc_unlocked() will add the new byte to the buffer
return (*iop->_ptr++ = (unsigned char)ch);
... but nothing actually *resets* the buffer in between.
At "now it's time to write the buffer out" time
https://github.com/illumos/illumos-gate/blob/86d949f9497332fe19be6b5d711d265eb957439f/usr/src/lib/libc/port/stdio/flush.c
fflush() -> _fflush_u() -> _xflsbuf() will do "n = iop->_ptr - iop->_base"
(which is now *2*) and will write out 2 bytes.
Having the fflush() in between seems to reset "iop->_ptr = iop->_base",
so the next fflush() after fputc() only has n = 1.
I haven't actually written a test program that prints out the various
states of iop->_ptr, _base, etc. to verify that assumption.
gert
--
"If was one thing all people took for granted, was conviction that if you
feed honest figures into a computer, honest figures come out. Never doubted
it myself till I met a computer with a sense of humor."
Robert A. Heinlein, The Moon is a Harsh Mistress
Gert Doering - Munich, Germany gert at greenie.muc.de
More information about the openssh-unix-dev
mailing list