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