tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: possible bug in fseek of buffered files shared between processes (example uses stdin)



On Tue, Nov 2, 2021 at 8:54 AM Rhialto <rhialto%falu.nl@localhost> wrote:
>
> This can never work in the presence of buffering (which is likely
> allowed by the C Standard, but I didn't look that up), because not all
> input is seekable. This variant "fails" equally on Linux, MacOS and
> NetBSD:
>
> $ printf "1\n2\n3\n" | ( head -1; head -1; cat )
> 1

Apologies for not clarifying that, but the example on the gist[1]
explicitly avoids the possibility of using a pipe (which as you said,
could be a type of file that can't seek, even if the standard doesn't
identify it as such) as a source by opening an fd and using that,
instead.

Note that the failure in this case can be "fixed" by instead calling
lseek directly, removing the buffer or skipping this early return in
src/lib/libc/stdio/fseeko.c (lines 210 to 228), and that I am showing
below (might be mangled by copy and paste):

/*
* If the target offset is within the current buffer,
* simply adjust the pointers, clear EOF, undo ungetc(),
* and return.  (If the buffer was modified, we have to
* skip this; see fgetln.c.)
*/
if ((fp->_flags & __SMOD) == 0 &&
    target >= curoff && target < curoff + (off_t)n) {
int o = (int)(target - curoff);

fp->_p = fp->_bf._base + o;
_DIAGASSERT(__type_fit(int, n - o));
fp->_r = (int)(n - o);
if (HASUB(fp))
FREEUB(fp);
fp->_flags &= ~__SEOF;
FUNLOCKFILE(fp);
return 0;
}

Carlo

[1] https://gist.github.com/carenas/7c13147ef10365bec2595c9e87102ae7


Home | Main Index | Thread Index | Old Index