diff options
author | Eric Engestrom <[email protected]> | 2019-01-28 15:44:12 +0000 |
---|---|---|
committer | Eric Engestrom <[email protected]> | 2019-04-30 15:40:33 +0000 |
commit | 316964709e21286c2af54e3afb3089d0fcce87c1 (patch) | |
tree | 851710be1d62d2448238837c787cd37ba379111b /src/util/os_file.c | |
parent | 2fae99bcbd00392daf44d1bc570553ac70730d36 (diff) |
util: add os_read_file() helper
readN() taken from igt.
os_read_file() inspired by igt_sysfs_get()
Signed-off-by: Eric Engestrom <[email protected]>
Reviewed-by: Jason Ekstrand <[email protected]>
Diffstat (limited to 'src/util/os_file.c')
-rw-r--r-- | src/util/os_file.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/src/util/os_file.c b/src/util/os_file.c new file mode 100644 index 00000000000..cee9d22c8ec --- /dev/null +++ b/src/util/os_file.c @@ -0,0 +1,129 @@ +/* + * Copyright 2019 Intel Corporation + * SPDX-License-Identifier: MIT + */ + +#include "os_file.h" + +#include <errno.h> + +#if defined(__linux__) + +#include <fcntl.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <unistd.h> + + +static ssize_t +readN(int fd, char *buf, size_t len) +{ + int err = -ENODATA; + size_t total = 0; + do { + ssize_t ret = read(fd, buf + total, len - total); + + if (ret < 0) + ret = -errno; + + if (ret == -EINTR || ret == -EAGAIN) + continue; + + if (ret <= 0) + break; + + total += ret; + } while (total != len); + + return total ? total : err; +} + +static char * +read_grow(int fd) +{ + size_t len = 64; + + char *buf = malloc(len); + if (!buf) { + close(fd); + errno = -ENOMEM; + return NULL; + } + + ssize_t read; + size_t offset = 0, remaining = len - 1; + while ((read = readN(fd, buf + offset, remaining)) == remaining) { + char *newbuf = realloc(buf, 2 * len); + if (!newbuf) { + free(buf); + close(fd); + errno = -ENOMEM; + return NULL; + } + + buf = newbuf; + len *= 2; + offset += read; + remaining = len - offset - 1; + } + + close(fd); + + if (read > 0) + offset += read; + + buf[offset] = '\0'; + + return buf; +} + +char * +os_read_file(const char *filename) +{ + size_t len = 0; + + int fd = open(filename, O_RDONLY); + if (fd == -1) { + /* errno set by open() */ + return NULL; + } + + struct stat stat; + if (fstat(fd, &stat) == 0) + len = stat.st_size; + + if (!len) + return read_grow(fd); + + /* add NULL terminator */ + len++; + + char *buf = malloc(len); + if (!buf) { + close(fd); + errno = -ENOMEM; + return NULL; + } + + ssize_t read = readN(fd, buf, len - 1); + + close(fd); + + if (read == -1) + return NULL; + + buf[read] = '\0'; + + return buf; +} + +#else + +char * +os_read_file(const char *filename) +{ + errno = -ENOSYS; + return NULL; +} + +#endif |