Either use mmap()
or do it yourself.
Omitting error checking, roughly:
int fd = open(filename, O_RDONLY);
struct stat sb;
fstat(fd, &sb);
char *contents = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
This is a readonly copy of the file, allocated at an address of the kernel's choosing. If you're on a 32-bit system, you may have to worry about files bigger than 2 GiB. I don't think you can portably avoid using something like fstat()
to get the file size. If you want to grow the file, you can specify a larger size than the file size, according to the POSIX specification.
If you DIY, then the first three lines are the same. Then you use:
char *contents = malloc(sb.st_size);
read(fd, contents, sb.st_size);
As noted before, all error checking was omitted in these examples; don't risk it in production-ready code.
I went digging for some more nearly production-ready code that uses mmap()
and found:
static int sqs_mapfile(const char *file)
{
int fd;
void *vp;
struct stat sb;
if (file == 0)
return(SQS_NOSQSFILE);
if ((fd = open(file, O_RDONLY, 0)) < 0)
return(SQS_OPENFAIL);
if (fstat(fd, &sb) != 0)
{
close(fd);
return(SQS_STATFAIL);
}
vp = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
if (vp == MAP_FAILED)
return(SQS_MMAPFAIL);
The 'SQS_xyz' codes are specific to the program it comes from (as is the function name). This code uses a 3-argument open()
call where a 2-argument version is sufficient.