I'm writing a program, some kind of database. While I was reading manual of fclose(3)
I found that it calls fflush(3)
to flush FILE*
buffers to disk (actually to OS buffer, but it doesn't matter right now, we can always call fsync(2)
).
Because I'm writing a DB it is obvious that I want to prevent data loss. If there is no disk space and fflush(3)
in fclose(3)
fails — we will lose our data, because
using
FILE*
after an error infclose()
will cause undefined behavior
So I thought about explicit use of fflush(3)
before fclose(3)
, warn user about low disk space and recall fflush(3)
after a while.
I've read the C standard and thought this was a good idea. In practice, after failed fflush
the second call would always return 0 (no error), but would actually do nothing. fsync
didn't help me (I thought data might be saved in RAM).
How can I prevent data loss in such a situation? Maybe there are some rules of thumb.
Here is my test code:
#include <stdio.h>
int main()
{
FILE *a = fopen("/tmp/1", "wb")
if ( !a )
perror("fopen");
if ( fwrite("test", 1, 4, a) != 4 )
perror("fwrite"); // always OK, cause data is buffered
while( fflush(a) ) // ...second call will always return 0!
{
perror("fflush"); // if there is no disk space, I will get this perror, but ...
}
if ( fclose(a) ) // always ok, because calls only close(2)
perror("fclose");
return 0;
}