#include #include #include #include #include #include #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; }