diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2013-03-12 17:16:49 +0100 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2013-03-12 17:16:49 +0100 |
commit | e6d0d785436152a12f7ca9f159becba9fa17260d (patch) | |
tree | 92312d55eb70991344ef7ddd771dc0092ba2e3a3 /src | |
parent | ddf4126c11823b0563c03bfd13feab6d4d04ccad (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.h | 57 |
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. */ |