diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2020-01-22 02:13:18 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2020-01-22 02:13:18 +0000 |
commit | fdcc03929065b5bf5dd93553db219ea3e05c8c34 (patch) | |
tree | ca90dc8d9e89febdcd4160956c1b8ec098a4efc9 /lib/mesa/src/util/os_file.c | |
parent | 3c9de4a7e13712b5696750bbd59a18c848742022 (diff) |
Import Mesa 19.2.8
Diffstat (limited to 'lib/mesa/src/util/os_file.c')
-rw-r--r-- | lib/mesa/src/util/os_file.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/lib/mesa/src/util/os_file.c b/lib/mesa/src/util/os_file.c new file mode 100644 index 000000000..c670e127c --- /dev/null +++ b/lib/mesa/src/util/os_file.c @@ -0,0 +1,142 @@ +/* + * Copyright 2019 Intel Corporation + * SPDX-License-Identifier: MIT + */ + +#include "os_file.h" + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <sys/stat.h> + + +#if defined(WIN32) +#include <io.h> +#define open _open +#define fdopen _fdopen +#define O_CREAT _O_CREAT +#define O_EXCL _O_EXCL +#define O_WRONLY _O_WRONLY +#endif + + +FILE * +os_file_create_unique(const char *filename, int filemode) +{ + int fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, filemode); + if (fd == -1) + return NULL; + return fdopen(fd, "w"); +} + + +#if defined(__linux__) + +#include <fcntl.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) { + err = ret; + break; + } + + total += ret; + } while (total != len); + + return total ? (ssize_t)total : err; +} + +char * +os_read_file(const char *filename) +{ + /* Note that this also serves as a slight margin to avoid a 2x grow when + * the file is just a few bytes larger when we read it than when we + * fstat'ed it. + * The string's NULL terminator is also included in here. + */ + size_t len = 64; + + int fd = open(filename, O_RDONLY); + if (fd == -1) { + /* errno set by open() */ + return NULL; + } + + /* Pre-allocate a buffer at least the size of the file if we can read + * that information. + */ + struct stat stat; + if (fstat(fd, &stat) == 0) + len += stat.st_size; + + char *buf = malloc(len); + if (!buf) { + close(fd); + errno = -ENOMEM; + return NULL; + } + + ssize_t actually_read; + size_t offset = 0, remaining = len - 1; + while ((actually_read = readN(fd, buf + offset, remaining)) == (ssize_t)remaining) { + char *newbuf = realloc(buf, 2 * len); + if (!newbuf) { + free(buf); + close(fd); + errno = -ENOMEM; + return NULL; + } + + buf = newbuf; + len *= 2; + offset += actually_read; + remaining = len - offset - 1; + } + + close(fd); + + if (actually_read > 0) + offset += actually_read; + + /* Final resize to actual size */ + len = offset + 1; + char *newbuf = realloc(buf, len); + if (!newbuf) { + free(buf); + errno = -ENOMEM; + return NULL; + } + buf = newbuf; + + buf[offset] = '\0'; + + return buf; +} + +#else + +char * +os_read_file(const char *filename) +{ + errno = -ENOSYS; + return NULL; +} + +#endif |