summaryrefslogtreecommitdiffstats
path: root/XUtils.c
diff options
context:
space:
mode:
authorChristian Göttsche <cgzones@googlemail.com>2020-11-25 12:42:36 +0100
committerBenBE <BenBE@geshi.org>2020-12-02 20:39:36 +0100
commitf7a89529330044f4e2a38e85a88ec90f839ae64e (patch)
tree23b187477ea294d9a0f7d0557c3a51acdd0cbdd0 /XUtils.c
parent1d8192c10b4e149c7f9126f00534f6a8488d10c4 (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.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/XUtils.c b/XUtils.c
index dcc8b390..23ec39e7 100644
--- a/XUtils.c
+++ b/XUtils.c
@@ -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);
+}

© 2014-2024 Faster IT GmbH | imprint | privacy policy