3

I am currently writing a implementation of DOD5220.22-M. The piece of code below is for writing binary zero to a file until the disk is completely full.

So the problem is using statvfs, it detects 3800158208 bytes (around 3.82gb) of writable space. However, the write process will stop at 3.77gb, and it will just stuck there forever. The drive is formatted to APFS just before this operation, so it is completely empty.

As you can see, I try to use stream.fail() to detect such error but this does not seems to work at all. System is MacOS running g++8 with C++17

What am I missing? Is the statvfs detecting more writable space than there are or am I doing something wrong?

Also is there a way that I can write without checking stream.fail() every iteration?

Thanks in advance.

{
statvfs("/Volumes/SECUREERASE", &space); // get space
size =  space.f_frsize * space.f_bavail;
char zero = 0;
    for (int i = 0; i < size; ++i){ // while space left, write
        file.write(&zero, sizeof(char));
        if(file.fail()){
            break;
        }
    }
}
kc12345
  • 67
  • 9
  • 1
    IDK what's wrong but it seems sensible to try something lower level for this kind of operation. Have you tried the POSIX functions, open, write, close etc? – john Feb 15 '19 at 06:57
  • That's a good idea john, I measured a 2 second decrease per 3gb write using fwrite(). Thanks! Unfortunately, the problem still exist; – kc12345 Feb 15 '19 at 07:31
  • 1
    I didn't mean `fwrite` (which is a C function) I meant the POSIX function `write` https://pubs.opengroup.org/onlinepubs/007904875/functions/write.html. Just a suggestion though, I don't know if it will help or not. – john Feb 15 '19 at 07:52
  • Thanks for the suggestion @john. It actually solved my problem! I believe it was the buffer that was causing all the problem. When using write, I set my own buffer to 4mb and write to disk size/4mb times and it's working flawlessly. Also it is much much faster. That was an awesome suggestion. Thanks again. – kc12345 Feb 15 '19 at 09:05

1 Answers1

0

After taking @john's advice and use POSIX write and setting my own buffer to 4MB and write to disk size/4MB time, the problem was solved. Here's the code

int file = open("run1",O_WRONLY);

char zero[4000000] = {0};
for (long unsigned int i = 0; i < (size/4000000); ++i) { // while space left, write
    write(file,&zero, sizeof(zero)* sizeof(char));
}

While I'm still not sure about what exactly caused my problem, I can assume with confidence that it has something to do with fstream default buffer size. Maybe the buffer was greater than space remain therefore cannot be written to file, however that does not explain why stream.fail() didn't catch it. Still the problem is fixed.

kc12345
  • 67
  • 9
  • Now that I think of it, a write failure would show as `file.bad()` not `file.fail()` which is for conversion errors and the like. – john Feb 15 '19 at 09:50
  • I tried both of them and all failed. I think that fail() is just a bad() + failbit. – kc12345 Feb 15 '19 at 10:37