blob: f899a2ac5e2ae33b5cac5beca59727bd65056743 [file] [log] [blame]
/*
* readfile.c
*
* Read the entire contents of a file into malloc'd storage. This
* is mostly useful for things like /proc files where we can't just
* fstat() to get the length and then mmap().
*
* Returns the number of bytes read, or -1 on error.
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
ssize_t freadfile(FILE *f, char **pp)
{
size_t bs; /* Decent starting point... */
size_t bf; /* Bytes free */
size_t bu = 0; /* Bytes used */
char *buffer, *nb;
size_t rv;
int old_errno = errno;
bs = BUFSIZ; /* A guess as good as any */
bf = bs;
buffer = malloc(bs);
if (!buffer)
return -1;
for (;;) {
errno = 0;
while (bf && (rv = _fread(buffer + bu, bf, f))) {
bu += rv;
bf -= rv;
}
if (errno && errno != EINTR && errno != EAGAIN) {
/* error */
free(buffer);
return -1;
}
if (bf) {
/* Hit EOF, no error */
/* Try to free superfluous memory */
if ((nb = realloc(buffer, bu + 1)))
buffer = nb;
/* Null-terminate result for good measure */
buffer[bu] = '\0';
*pp = buffer;
errno = old_errno;
return bu;
}
/* Double the size of the buffer */
bf += bs;
bs += bs;
if (!(nb = realloc(buffer, bs))) {
/* out of memory error */
free(buffer);
return -1;
}
buffer = nb;
}
}
ssize_t readfile(const char *filename, char **pp)
{
FILE *f = fopen(filename, "r");
ssize_t rv;
if (!f)
return -1;
rv = freadfile(f, pp);
fclose(f);
return rv;
}