Files
libucore/src/ucore_read_file.c
T
2012-10-29 23:07:32 +01:00

83 lines
1.7 KiB
C

#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "ucore_read_file.h"
#define CHUNK_SZ 1024
char *
uc_read_file(const char *f, size_t *length, size_t max)
{
int fd;
char *s = NULL;
char *p;
struct stat statb;
size_t alloc_sz;
*length = 0;
if ((fd = open(f, O_RDONLY)) == -1)
return NULL;
if (fstat(fd, &statb) == -1) {
goto out_close;
}
if ((statb.st_mode & S_IFMT) == S_IFREG) {
if((size_t)statb.st_size > max) {
errno = EMSGSIZE;
goto out_close;
}
alloc_sz = (size_t) statb.st_size + 1; // + 1 to avoid one realloc
s = malloc((size_t) alloc_sz + 1); //+1 for nul terminator
} else {
alloc_sz = CHUNK_SZ;
s = malloc(alloc_sz + 1); //+1 for nul terminator
}
if (s == NULL) {
goto out_close;
}
p = s;
for(;;) {
ssize_t rc = read(fd, p, alloc_sz - (p - s));
if(rc == 0) {
*p = 0; // nul terminate. all malloc calls adds room for this byte
goto out_close;
} else if (rc == -1) {
goto out_err_free;
} else if(*length + rc > max) {
errno = EMSGSIZE;
goto out_err_free;
}
if(p + rc == s + alloc_sz) { //reached end of allocated memory, grow it.
char *tmp = realloc(s, alloc_sz + CHUNK_SZ + 1);
if(tmp == NULL) {
goto out_err_free;
}
s = tmp;
p = s + alloc_sz;
alloc_sz += CHUNK_SZ;
} else {
p += rc;
}
*length += rc;
}
out_err_free:
free(s);
s = NULL;
out_close:
close(fd);
return s;
}