tal variant of grab_file (which uses talloc).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
str_talloc \
take \
tal \
+ tal/grab_file \
tal/link \
tal/path \
tal/str \
--- /dev/null
+../../../licenses/LGPL-2.1
\ No newline at end of file
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+
+/**
+ * tal/grab_file - file helper routines
+ *
+ * This contains simple functions for getting the contents of a file.
+ *
+ * Example:
+ * #include <err.h>
+ * #include <stdio.h>
+ * #include <string.h>
+ * #include <ccan/tal/grab_file/grab_file.h>
+ * #include <ccan/tal/tal.h> // 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 <rusty@rustcorp.com.au>
+ */
+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;
+}
--- /dev/null
+/* Licensed under LGPLv2+ - see LICENSE file for details */
+#include "grab_file.h"
+#include <ccan/tal/tal.h>
+#include <ccan/noerr/noerr.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+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;
+}
--- /dev/null
+/* Licensed under LGPLv2+ - see LICENSE file for details */
+#ifndef CCAN_TAL_GRAB_FILE_H
+#define CCAN_TAL_GRAB_FILE_H
+#include <stdio.h> // 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 <ccan/tal/str/str.h>
+ * #include <ccan/tal/tal.h>
+ * ...
+ * // 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 */
--- /dev/null
+/* This is test for grab_file() function
+ */
+#include <ccan/tal/grab_file/grab_file.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <sys/stat.h>
+#include <ccan/tal/grab_file/grab_file.c>
+#include <ccan/tap/tap.h>
+#include <ccan/tal/str/str.h>
+
+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 */