0

My computer recently got shut down abruptly. When I powered it back on, I found out that some of the binary files I had written when the computer was running last time got corrupted. I investigated this, found that this is because data written using fwrite is not guaranteed to be written to disk immediately. I was told that in order to save my data without the risk of losing it in case of another abrupt power outage, I should make use of fsync function. But it looks like it is Unix/Linux only facility located in unistd.h. I am on Windows, how do I do the equivalent of fsync on Windows?

I want to protect data written using a simple program as follows -

void WriteBinFile(float var1, float var2, float var3)
{
    FILE *fp;
    fopen_s(&fp, "filename.dat", "wb");
    fwrite((void*)&var1, sizeof(float), 1, fp);
    fwrite((void*)&var2, sizeof(float), 1, fp);
    fwrite((void*)&var3, sizeof(float), 1, fp);
    // fsync(fp) ??? No such function exists on Windows. Here I want a facility to write data to disk in non-volatile manner.
    fclose(fp);
}

P.S. Why I don't have a UPS is a long and an uninteresting story.Also, I am on Windows 8.1 and using Visual Studio 2013. Also, the files that were affected due to the abrupt power outage contained 0s. Some of them were full of 0s and some of them were only partially full of 0s. I did not write 0s to the file, so this was definitely a consequence of the power outage

BЈовић
  • 62,405
  • 41
  • 173
  • 273
The Vivandiere
  • 3,059
  • 3
  • 28
  • 50

3 Answers3

0

For those who stop reading after the first paragraph, there are three steps following.

  1. Call fflush(fp). This will flush all of the data out of the C stdio buffers and into the operating system buffers.

  2. Use How do I get the file HANDLE from the fopen FILE structure?

  3. Then call FlushFileBuffers on the HANDLE. This will flush all of the data out of the Windows OS buffers and onto the disk.

Community
  • 1
  • 1
Zan Lynx
  • 53,022
  • 10
  • 79
  • 131
  • Thanks. Do you know if `fflush(fp)` also works for this? – The Vivandiere Sep 14 '15 at 23:29
  • @FirstJens: I forget to mention fflush at first until I saw it in Joshua's answer. It is needed to get the data out of the buffer built into C's stdio functions. After that you need FlushFileBuffers to get the data out of the operating system buffers. – Zan Lynx Sep 14 '15 at 23:30
  • Thanks. I am reading through the code now. It is quite dense. – The Vivandiere Sep 14 '15 at 23:35
  • Wow, two downvotes without a single explanatory comment. – Zan Lynx Sep 16 '15 at 17:46
  • `fflush()` does not correspond to `fsync()`. The former is a C library function that flushes buffers out of the application into the kernel: the latter is a system call that flushes buffers out of the kernel onto the disk. On systems that have them both you would need to use them both to accomplish the OP's objective. The Windows equivalent to `fsync()` is `FlushFileBuffer()`. – user207421 Sep 30 '15 at 22:41
  • 1
    @EJP: It seems your comment just restated my answer? – Zan Lynx Oct 01 '15 at 16:18
-1

What you are looking for is FlushFileBuffers. In your case, FlushFileBuffers(fileno(fd)).

Another useful idiom in Windows is given by close(dup(fd)), or in your case close(dup(fileno(fp))). This flushes the directory entry, so that the file size is correct for a growing file. Otherwise the directory is only updated when the file is closed.

user207421
  • 305,947
  • 44
  • 307
  • 483
-4

I could be wrong, but I believe that fflush(fp); should do the trick.

Joshua Green
  • 1,517
  • 1
  • 10
  • 14
  • While not wrong, this only affects the C runtime buffering. Windows may have another level (it does have it). – deviantfan Sep 14 '15 at 23:27