
Ack, I glossed over the fileno() call in our file_truncate(). It's usually a Very Bad Idea to mix stream I/O and lower-level I/O operations without flushing your pants off, but I'm having a hard time thinking of a specific reason for doing so in the truncate case. Better safe than trying to out-think all possible implementations, though!
I think the fflush() is there for the following case: a file is opened for update, some data is written that overwrites some bytes in the middle but not yet flushed, and then the file is truncated to that position. Since ftruncate works on the file descriptor, you'd want the data flushed before truncating, otherwise things just get too complicated.
I suppose that clarifies my immediately preceding
ftruncate() isn't a standard C function,
<wink>?
I somehow misread what you wrote as "is a standard C function".
I just realize that I have always worked under the assumption that fflush() after a read is a no-op; I just checked the 89 std and it says it is undefined. (I must have picked up that misunderstanding from some platform-specific man page.) This can be fixed by doing a ftell() followed by an fseek() call; this is required to flush the buffer if there was unwritten output data in the buffer, and is always allowed.
That's what I was hoping to avoid, but I don't care anymore: after staring it some more, I'm convinced that the current file_truncate() endures a ridiculous amount of complexity trying to gain a tiny bit of speed in what has to be a rare operation.
Right. --Guido van Rossum (home page: http://www.python.org/~guido/)