From fbad46cd37018923bf0a7de2df37e35e90792c32 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 10 Jun 2014 13:06:12 +0930 Subject: [PATCH] tal/grab_file: new module tal variant of grab_file (which uses talloc). Signed-off-by: Rusty Russell --- Makefile-ccan | 1 + ccan/tal/grab_file/LICENSE | 1 + ccan/tal/grab_file/_info | 56 ++++++++++++++++++++++++++ ccan/tal/grab_file/grab_file.c | 64 ++++++++++++++++++++++++++++++ ccan/tal/grab_file/grab_file.h | 60 ++++++++++++++++++++++++++++ ccan/tal/grab_file/test/run-grab.c | 37 +++++++++++++++++ 6 files changed, 219 insertions(+) create mode 120000 ccan/tal/grab_file/LICENSE create mode 100644 ccan/tal/grab_file/_info create mode 100644 ccan/tal/grab_file/grab_file.c create mode 100644 ccan/tal/grab_file/grab_file.h create mode 100644 ccan/tal/grab_file/test/run-grab.c diff --git a/Makefile-ccan b/Makefile-ccan index b0c062d9..adfba03e 100644 --- a/Makefile-ccan +++ b/Makefile-ccan @@ -87,6 +87,7 @@ MODS_WITH_SRC := antithread \ str_talloc \ take \ tal \ + tal/grab_file \ tal/link \ tal/path \ tal/str \ diff --git a/ccan/tal/grab_file/LICENSE b/ccan/tal/grab_file/LICENSE new file mode 120000 index 00000000..4d0b239e --- /dev/null +++ b/ccan/tal/grab_file/LICENSE @@ -0,0 +1 @@ +../../../licenses/LGPL-2.1 \ No newline at end of file diff --git a/ccan/tal/grab_file/_info b/ccan/tal/grab_file/_info new file mode 100644 index 00000000..3b323d33 --- /dev/null +++ b/ccan/tal/grab_file/_info @@ -0,0 +1,56 @@ +#include +#include +#include "config.h" + +/** + * tal/grab_file - file helper routines + * + * This contains simple functions for getting the contents of a file. + * + * Example: + * #include + * #include + * #include + * #include + * #include // for tal_free + * + * int main(int argc, char *argv[]) + * { + * char *file; + * + * file = grab_file(NULL, argv[1]); + * if (!file) + * err(1, "Could not read file %s", argv[1]); + * if (strlen(file)+1 != tal_count(file)) + * printf("File contains NUL characters\n"); + * else if (tal_count(file) == 1) + * printf("File contains nothing\n"); + * else if (strchr(file, '\n')) + * printf("File contains multiple lines\n"); + * else + * printf("File contains one line\n"); + * tal_free(file); + * + * return 0; + * } + * + * License: LGPL (v2.1 or any later version) + * Author: Rusty Russell + */ +int main(int argc, char *argv[]) +{ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) { + printf("ccan/tal\n"); + printf("ccan/noerr\n"); + return 0; + } + if (strcmp(argv[1], "testdepends") == 0) { + printf("ccan/tal/str\n"); + return 0; + } + + return 1; +} diff --git a/ccan/tal/grab_file/grab_file.c b/ccan/tal/grab_file/grab_file.c new file mode 100644 index 00000000..88e7c225 --- /dev/null +++ b/ccan/tal/grab_file/grab_file.c @@ -0,0 +1,64 @@ +/* Licensed under LGPLv2+ - see LICENSE file for details */ +#include "grab_file.h" +#include +#include +#include +#include +#include +#include + +void *grab_fd(const void *ctx, int fd) +{ + int ret; + size_t max, size; + char *buffer; + struct stat st; + + size = 0; + + if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) + max = st.st_size; + else + max = 16384; + + buffer = tal_arr(ctx, char, max+1); + while ((ret = read(fd, buffer + size, max - size)) > 0) { + size += ret; + if (size == max) { + size_t extra = max; + if (extra > 1024 * 1024) + extra = 1024 * 1024; + + if (!tal_resize(&buffer, max+extra+1)) + return NULL; + + max += extra; + } + } + if (ret < 0) + buffer = tal_free(buffer); + else { + buffer[size] = '\0'; + tal_resize(&buffer, size+1); + } + + return buffer; +} + +void *grab_file(const void *ctx, const char *filename) +{ + int fd; + char *buffer; + + if (!filename) + fd = dup(STDIN_FILENO); + else + fd = open(filename, O_RDONLY, 0); + + if (fd < 0) + return NULL; + + buffer = grab_fd(ctx, fd); + close_noerr(fd); + return buffer; +} diff --git a/ccan/tal/grab_file/grab_file.h b/ccan/tal/grab_file/grab_file.h new file mode 100644 index 00000000..03bf32a7 --- /dev/null +++ b/ccan/tal/grab_file/grab_file.h @@ -0,0 +1,60 @@ +/* Licensed under LGPLv2+ - see LICENSE file for details */ +#ifndef CCAN_TAL_GRAB_FILE_H +#define CCAN_TAL_GRAB_FILE_H +#include // For size_t + +/** + * grab_fd - read all of a file descriptor into memory + * @ctx: the context to tallocate from (often NULL) + * @fd: the file descriptor to read from + * + * This function reads from the given file descriptor until no more + * input is available. The content is talloced off @ctx, and the + * tal_count() is the size in bytes plus one: for convenience, the + * byte after the end of the content will always be NUL. + * + * Example: + * #include + * #include + * ... + * // Return all of standard input, as lines. + * static char **read_stdin_as_lines(void) + * { + * char **lines, *all; + * + * all = grab_fd(NULL, 0); + * if (!all) + * return NULL; + * lines = tal_strsplit(NULL, all, "\n", STR_EMPTY_OK); + * tal_free(all); + * return lines; + * } + */ +void *grab_fd(const void *ctx, int fd); + +/** + * grab_file - read all of a file (or stdin) into memory + * @ctx: the context to tallocate from (often NULL) + * @filename: the file to read (NULL for stdin) + * + * This function reads from the given file until no more input is + * available. The content is talloced off @ctx, and the tal_count() + * is the size in bytes plus one: for convenience, the byte after the + * end of the content will always be NUL. + * + * Example: + * // Return all of a given file, as lines. + * static char **read_file_as_lines(const char *filename) + * { + * char **lines, *all; + * + * all = grab_file(NULL, filename); + * if (!all) + * return NULL; + * lines = tal_strsplit(NULL, all, "\n", STR_EMPTY_OK); + * tal_free(all); + * return lines; + * } + */ +void *grab_file(const void *ctx, const char *filename); +#endif /* CCAN_TAL_GRAB_FILE_H */ diff --git a/ccan/tal/grab_file/test/run-grab.c b/ccan/tal/grab_file/test/run-grab.c new file mode 100644 index 00000000..b258230e --- /dev/null +++ b/ccan/tal/grab_file/test/run-grab.c @@ -0,0 +1,37 @@ +/* This is test for grab_file() function + */ +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + unsigned int i; + char **split, *str; + int length; + struct stat st; + + str = grab_file(NULL, "test/run-grab.c"); + split = tal_strsplit(str, str, "\n", STR_EMPTY_OK); + length = strlen(split[0]); + ok1(!strcmp(split[0], "/* This is test for grab_file() function")); + for (i = 1; split[i]; i++) + length += strlen(split[i]); + ok1(!strcmp(split[i-1], "/* End of grab_file() test */")); + if (stat("test/run-grab.c", &st) != 0) + /* FIXME: ditto */ + if (stat("ccan/tal/grab_file/test/run-grab.c", &st) != 0) + err(1, "Could not stat self"); + ok1(st.st_size == length + i); + tal_free(str); + + return 0; +} + +/* End of grab_file() test */ -- 2.39.2