#include #include #include #include #include #include #include #include "ucore/read_file.h" #define CHUNK_SZ 1024 char * uc_read_fd(int fd, size_t *length, size_t max) { char *s = NULL; char *p; struct stat statb; size_t alloc_sz; *length = 0; if (fstat(fd, &statb) == -1) { goto out_close; } if ((statb.st_mode & S_IFMT) == S_IFREG) { if (statb.st_size > (off_t)max) { errno = EMSGSIZE; goto out_close; } if (statb.st_size > SSIZE_MAX) { //otherwise we cannot detect the return value of read() alloc_sz = SSIZE_MAX; } else { alloc_sz = statb.st_size; } } 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; } char * uc_read_file(const char *f, size_t *length, size_t max) { int fd; if ((fd = open(f, O_RDONLY)) == -1) { *length = 0; return NULL; } return uc_read_fd(fd, length, max); }