summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-03-12 17:16:49 +0100
committerDavid Herrmann <dh.herrmann@gmail.com>2013-03-12 17:16:49 +0100
commite6d0d785436152a12f7ca9f159becba9fa17260d (patch)
tree92312d55eb70991344ef7ddd771dc0092ba2e3a3 /src
parentddf4126c11823b0563c03bfd13feab6d4d04ccad (diff)
shl: add shl_read_file() helper
This reads in a complete file as a string and returns it to the caller. The string is 0 terminated (which isn't guaranteed by mmap()) so this helper is needed if we have to work with APIs that don't accept buffer lengths. Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/shl_misc.h57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/shl_misc.h b/src/shl_misc.h
index 9aa1920..d90fd22 100644
--- a/src/shl_misc.h
+++ b/src/shl_misc.h
@@ -37,6 +37,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -262,6 +263,62 @@ static inline unsigned int shl_string_list_count(char **list, bool ignore_empty)
return num;
}
+/* reads a whole file into a buffer with 0-termination */
+static inline int shl_read_file(const char *path, char **out, size_t *size)
+{
+ FILE *ffile;
+ ssize_t len;
+ char *buf;
+ int ret;
+
+ if (!path || !out)
+ return -EINVAL;
+
+ errno = 0;
+
+ ffile = fopen(path, "rb");
+ if (!ffile)
+ return -errno;
+
+ if (fseek(ffile, 0, SEEK_END) != 0) {
+ ret = -errno;
+ goto err_close;
+ }
+
+ len = ftell(ffile);
+ if (len < 0) {
+ ret = -errno;
+ goto err_close;
+ }
+
+ rewind(ffile);
+
+ buf = malloc(len + 1);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto err_close;
+ }
+
+ errno = 0;
+ if (len && len != fread(buf, 1, len, ffile)) {
+ ret = errno ? -errno : -EFAULT;
+ goto err_free;
+ }
+
+ buf[len] = 0;
+ *out = buf;
+ if (size)
+ *size = len;
+ ret = 0;
+ goto err_close;
+
+err_free:
+ free(buf);
+err_close:
+ fclose(ffile);
+ return ret;
+}
+
/* TODO: xkbcommon should provide these flags!
* We currently copy them into each library API we use so we need to keep
* them in sync. Currently, they're used in uterm-input and tsm-vte. */