83 lines
1.7 KiB
C
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;
|
|
}
|
|
|