tal/grab_file: new module
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 10 Jun 2014 03:36:12 +0000 (13:06 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 10 Jun 2014 03:36:12 +0000 (13:06 +0930)
tal variant of grab_file (which uses talloc).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Makefile-ccan
ccan/tal/grab_file/LICENSE [new symlink]
ccan/tal/grab_file/_info [new file with mode: 0644]
ccan/tal/grab_file/grab_file.c [new file with mode: 0644]
ccan/tal/grab_file/grab_file.h [new file with mode: 0644]
ccan/tal/grab_file/test/run-grab.c [new file with mode: 0644]

index b0c062d9b7c554aa99868869c8490487a2c45f1e..adfba03eb76b4cdcdc0d1ff921fe9153f576e3a6 100644 (file)
@@ -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 (symlink)
index 0000000..4d0b239
--- /dev/null
@@ -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 (file)
index 0000000..3b323d3
--- /dev/null
@@ -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;
+}
diff --git a/ccan/tal/grab_file/grab_file.c b/ccan/tal/grab_file/grab_file.c
new file mode 100644 (file)
index 0000000..88e7c22
--- /dev/null
@@ -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;
+}
diff --git a/ccan/tal/grab_file/grab_file.h b/ccan/tal/grab_file/grab_file.h
new file mode 100644 (file)
index 0000000..03bf32a
--- /dev/null
@@ -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 */
diff --git a/ccan/tal/grab_file/test/run-grab.c b/ccan/tal/grab_file/test/run-grab.c
new file mode 100644 (file)
index 0000000..b258230
--- /dev/null
@@ -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 */