On a file opened for read & write (r+ or w+), a write() system call does
not honor a prior fseek(), but writes its data at the file position that
was in effect before the fseek().
Problem found in Linux 6.2 (Zoot), kernel 2.2.14-6.1.1smp, duplicated in
Linux 7.0 (Guinness), kernel 2.2.16-22.
I have a small test program which demonstrates the problem nicely. Can
send it via e-mail or ftp if you wish. The gist of it is:
fwrite() 20 integers.
fseek() back into the middle of that.
write() another integer.
The value put out by the final write() should appear in the middle of the
data file when the program is done. In fact, it gets put at the end of
I ran this program on HP-UX and AIX to verify that Linux's behavior is
indeed different from "standard" UNIX.
There is a work-around, but I called the severity "high" because a data
file can be corrupted by this problem.
If you mean test like:
FILE *f = fopen ("/tmp/xxx", "w+");
for (i = 0; i < 20; i++)
fwrite ("244", 3, 1, f);
fseek (f, 15, SEEK_SET);
write (fileno (f), "355", 3);
then there is really no guarantee that fseek will move the underlying file
where it explicitely states that:
If the most recent operation, other than ftell(), on a given stream is
fflush(), the file offset in the underlying open file description will be
adjusted to reflect the location specified by fseek().
There is nothing about underlying file descriptor unless you call fflush
before it. And indeed, if I add fflush (f) in the above example either right
before the fseek or right after the fseek, 355 will be present at offset 15
(otherwise it can wind up at offset 60).
So in my eyes you just rely on undefined behaviour.