fseek/fgetc puzzle

Darren Tucker dtucker at dtucker.net
Mon Feb 20 22:21:31 AEDT 2023

On Mon, 20 Feb 2023 at 21:57, Nathan Wagner <nw at hydaspes.if.org> wrote:
> >         printf("fputc A=%d\n", fputc('A', f));
> Is fputc() here somehow being evaluated twice?

Nope.  In the original code it's not inside a printf, and checking it
between the close and reopen confirms there's only one byte in it.  I
moved the second call outside of the printf but it didn't make a

$ cat test.c
#include <stdlib.h>
#include <stdio.h>
int main(void)
        int n;
        FILE *f = fopen("testfile", "w");
        printf("fputc A=%d\n", fputc('A', f));
        system("od -x -c testfile");

        f = fopen("testfile", "r+b");
        printf("fseek=%d\n", fseek(f, -1L, SEEK_END));
        n = fgetc(f);
        printf("c=%d\n", n);
        printf("fputc B = %d\n", fputc('B', f));
$ gcc test.c && ./a.out && od -x -c testfile
fputc A=65
0000000    0041
fputc B = 66
0000000    4141    0042
           A   A   B

> My suggestion of course fails to explain why there's only one 'B'.
> I would create the initial file separately from the test program.

The "od" call in the middle of the above example proves there's only
one byte after the first fclose.

> I don't recall, but is there a guaranteed fflush() on open file
> descriptors at program exit?

Yes I think so although I don't have a reference to hand.  But even if
it didn't, that would explain a missing "B", not an extra "A".

> Does an explicit call to fflush() do anything?

At the end of the program, no, it misbehaves as described ("AAB").
Before the last fputc, yes, it makes the program behave as expected

> > $ gcc test.c && ./a.out && od -x -c testfile
> > fputc A=65
> > fseek=0
> > c=65
> > fputc B = 66
> > 0000000    4141    0042
> >            A   A   B
> > 0000003
> FWIW, this is the same output I get on both a linux and macos box.

You get the AAB on Linux and MacOS?  Which versions?  I get AB on both
OSX High Sierra and Fedora 36.  Maybe it's sensitive to locale

Darren Tucker (dtucker at dtucker.net)
GPG key 11EAA6FA / A86E 3E07 5B19 5880 E860  37F4 9357 ECEF 11EA A6FA (new)
    Good judgement comes with experience. Unfortunately, the experience
usually comes from bad judgement.

More information about the openssh-unix-dev mailing list