Browse Source

tal/grab_file: new module

tal variant of grab_file (which uses talloc).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Rusty Russell 11 years ago
parent
commit
fbad46cd37

+ 1 - 0
Makefile-ccan

@@ -87,6 +87,7 @@ MODS_WITH_SRC := antithread \
 	str_talloc \
 	take \
 	tal \
+	tal/grab_file \
 	tal/link \
 	tal/path \
 	tal/str \

+ 1 - 0
ccan/tal/grab_file/LICENSE

@@ -0,0 +1 @@
+../../../licenses/LGPL-2.1

+ 56 - 0
ccan/tal/grab_file/_info

@@ -0,0 +1,56 @@
+#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;
+}

+ 64 - 0
ccan/tal/grab_file/grab_file.c

@@ -0,0 +1,64 @@
+/* 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;
+}

+ 60 - 0
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 <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 */

+ 37 - 0
ccan/tal/grab_file/test/run-grab.c

@@ -0,0 +1,37 @@
+/* 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 */