diff options
author | Christian Göttsche <cgzones@googlemail.com> | 2020-11-25 12:42:36 +0100 |
---|---|---|
committer | BenBE <BenBE@geshi.org> | 2020-12-02 20:39:36 +0100 |
commit | f7a89529330044f4e2a38e85a88ec90f839ae64e (patch) | |
tree | 23b187477ea294d9a0f7d0557c3a51acdd0cbdd0 /XUtils.c | |
parent | 1d8192c10b4e149c7f9126f00534f6a8488d10c4 (diff) |
Add xReadfile wrapper for reading small to medium size files
Inspired by proposed Linux syscall
Avoid file descriptor leaks like 4af8c63f
Diffstat (limited to 'XUtils.c')
-rw-r--r-- | XUtils.c | 50 |
1 files changed, 50 insertions, 0 deletions
@@ -10,6 +10,7 @@ in the source distribution for its full text. #include "XUtils.h" #include <assert.h> +#include <errno.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> @@ -210,3 +211,52 @@ char* xStrndup(const char* str, size_t len) { } return data; } + +static ssize_t readfd_internal(int fd, void* buffer, size_t count) { + if (!count) { + close(fd); + return -EINVAL; + } + + ssize_t alreadyRead = 0; + count--; // reserve one for null-terminator + + for (;;) { + ssize_t res = read(fd, buffer, count); + if (res == -1) { + if (errno == EINTR) + continue; + + close(fd); + return -errno; + } + + if (res > 0) { + buffer = ((char*)buffer) + res; + count -= (size_t)res; + alreadyRead += res; + } + + if (count == 0 || res == 0) { + close(fd); + *((char*)buffer) = '\0'; + return alreadyRead; + } + } +} + +ssize_t xReadfile(const char* pathname, void* buffer, size_t count) { + int fd = open(pathname, O_RDONLY); + if (fd < 0) + return -errno; + + return readfd_internal(fd, buffer, count); +} + +ssize_t xReadfileat(openat_arg_t dirfd, const char* pathname, void* buffer, size_t count) { + int fd = Compat_openat(dirfd, pathname, O_RDONLY); + if (fd < 0) + return -errno; + + return readfd_internal(fd, buffer, count); +} |