Preallocating a file

B

Billy Mays

I'm trying to preallocate a file for later writing, and I have a small
segment of code that does it:

/***************************************/
#include <stdio.h>

int main(int argc, char ** argv)
{
FILE * f;
char zero = 0;
f = fopen("test.bin", "wb");
fseek(f, (1<<20) - 1, SEEK_SET);
fwrite(&zero, sizeof(char), 1, f);
fclose(f);
return 0;
}
/***************************************/

Is this the correct approach? Can I guarantee that the space that is
skipped over with always be zero bytes ('\0') ? Is this portable or
even specified in the C standard?
 
K

Keith Thompson

Billy Mays said:
I'm trying to preallocate a file for later writing, and I have a small
segment of code that does it:

/***************************************/
#include <stdio.h>

int main(int argc, char ** argv)
{
FILE * f;
char zero = 0;
f = fopen("test.bin", "wb");
fseek(f, (1<<20) - 1, SEEK_SET);
fwrite(&zero, sizeof(char), 1, f);
fclose(f);
return 0;
}
/***************************************/

Is this the correct approach? Can I guarantee that the space that is
skipped over with always be zero bytes ('\0') ? Is this portable or
even specified in the C standard?

The C standard says nothing about this.

On some systems, the skipped space will appear to contain zero bytes,
but they won't actually be stored -- which means that "preallocating"
like this doesn't guarantee that you won't run out of space when you
try to write to the file. On others, the space might actually be
allocated and filled with zero bytes or even garbage, or the feek()
call might fail (you should definitely check whether it succeeded
before proceeding).

What exactly are you trying to accomplish?
 
A

Alan Curry

I'm trying to preallocate a file for later writing, and I have a small
segment of code that does it:
[...]
fseek(f, (1<<20) - 1, SEEK_SET);
fwrite(&zero, sizeof(char), 1, f);

In a typical unix implementation, this doesn't preallocate the skipped-over
space. It creates a sparse file, which will return zeros when that region is
read back, but no blocks are allocated there.
 
B

Billy Mays

What exactly are you trying to accomplish?

My program is going to take in blocks from the network and write them to
the appropriate offset of a file, kind of a p2p program. I was thinking
that if the file contents were already filled, I could jump to any
portion of the file and write in a block from the network.

This program has a high chance that I will have to run it on Windows, so
I would prefer not to use fallocate (though I did look at it before
posting here).
 
E

Eric Sosman

My program is going to take in blocks from the network and write them to
the appropriate offset of a file, kind of a p2p program. I was thinking
that if the file contents were already filled, I could jump to any
portion of the file and write in a block from the network.

This program has a high chance that I will have to run it on Windows, so
I would prefer not to use fallocate (though I did look at it before
posting here).

The only pure-C way to allocate space for a file is to write
to all the bytes you want allocated. Even then, I'd suggest not
writing zero bytes throughout, as some clever file system might
notice the fact and create a "sparse" file for you on the sly. (And
you just don't want to think about file systems that do automatic
compression and de-duplication ...)

Your best bet, I think, is to segregate the pre-allocation into
its own function, and write different versions for different platforms:
Use fallocate() or posix_fallocate() or mkfile() if they're available,
or a Windows-specific equivalent (if there is one), and fall back on
the write-until-you're-blue-in-the-face strategy on platforms where
you can't find an alternative.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top