ov2k
ov2k

Reputation: 415

fseek/fsetpos may discard stream buffer?

In the C standard for fopen regarding files opened in update mode (C11 7.21.5.3/7), output followed by input requires an intervening call to fflush or a file positioning function (fseek, fsetpos, or rewind). However, none of the file positioning functions are required to do anything regarding the output buffer.

The POSIX standard maintains the same requirement for fopen and update mode. As with the C standard, fsetpos is not required to do anything with the output buffer. However, fseek is required to write the buffer to file.

In the case of both C and POSIX, a conforming implementation seems free to discard the write buffer when fsetpos is called, and C seems to allow fseek to do the same. My first question is whether I've missed something relevant in the standards. The implication here is that a portable application must call fflush (or fseek/rewind in the case of POSIX) to ensure buffered output is actually written before switching from output to input.

Obviously, discarding the write buffer goes against the intent of all of the write functions, and I'm not aware of any implementation that does this or anything comparably counter-intuitive. I'm also aware of my limited awareness, so my second question is whether there are any conforming implementations that don't ensure the buffered content eventually gets written in the proper place.

For context, the GNU documentation maintains the same requirement for fopen and update mode. As with C and POSIX, fsetpos says nothing about the output buffer, but my testing suggests my version does flush the buffer. However, fseek may either flush the buffer or remember enough about it to ensure its contents eventually get written properly.

TL;DR: Does C or POSIX disallow fsetpos from discarding the write buffer? Are there implementations that do this?

EDIT: Nobody has yet presented credible evidence that either standard prohibits fsetpos from discarding the write buffer. Similarly, nobody has mentioned any implementations that do this. However, this is not mentioned in the list of portability issues in the C standard (Annex J), suggesting it is an oversight and not an obscure portability concern. Furthermore, as mentioned by R.., there is no prohibition preventing completely unrelated functions from discarding buffers.

Upvotes: 1

Views: 346

Answers (3)

ov2k
ov2k

Reputation: 415

The C standard does not seem to explicitly prohibit fsetpos (or any other function) from discarding the buffer, which seems to be an arguably pedantic deficiency. However, the C99 Rationale document (7.19.5.3) states that fsetpos, fseek, rewind, and fflush "assure that the I/O buffer has been flushed". It's not clear why such text was not included in the standard, although one could speculate about GNU and write-back caches and whether forcing disk I/O on seek operations is desirable.

In practice, this means that one should be able to assume writing, then seeking, then reading will return the expected data. Given that at least one implementation (GNU) may not always flush when seeking, though, one should not assume the data will have reached the kernel (let alone the underlying device) without an explicit flush request.

Upvotes: 0

Florian Weimer
Florian Weimer

Reputation: 33747

I don't see anything requiring the flush in the fsetpos case, beyond this remark in the Errors section (twice):

or the stream's buffer needed to be flushed,

This looks like an omission in POSIX. Please file a clarification request in the Austin Group issue tracker.

Upvotes: 1

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215547

I don't see where you're getting that idea from. POSIX goes into a little bit more detail than the C standard about buffering behavior because it has to deal with interactions of stdio FILE streams with other means of accessing the same files. But there is nothing in the C standard that suggests the implementation is allowed to lose output when you call fsetpos. Logically the data has already been written.

Further, the specification (C11 7.21.9.3, ¶2) for fsetpos reads:

If a read or write error occurs, the error indicator for the stream is set and fsetpos fails.

The only plausible reason a write error could occur is some sort of write operation, and the only plausible write operation is flushing pending output.

Upvotes: 1

Related Questions