shl: add shl_read_file() helper
authorDavid Herrmann <dh.herrmann@gmail.com>
Tue, 12 Mar 2013 16:16:49 +0000 (17:16 +0100)
committerDavid Herrmann <dh.herrmann@gmail.com>
Tue, 12 Mar 2013 16:16:49 +0000 (17:16 +0100)
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>
src/shl_misc.h

index 9aa1920..d90fd22 100644 (file)
@@ -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. */