#include <errno.h>
#include <fcntl.h>
-void *grab_fd(const void *ctx, int fd)
+static void *grab_fd_internal(const void *ctx, int fd, bool add_nul_term)
{
int ret;
size_t max, size;
else
max = 16384;
- buffer = tal_arr(ctx, char, max+1);
+ buffer = tal_arr(ctx, char, max+add_nul_term);
while ((ret = read(fd, buffer + size, max - size)) != 0) {
if (ret < 0) {
if (errno == EINTR)
if (extra > 1024 * 1024)
extra = 1024 * 1024;
- if (!tal_resize(&buffer, max+extra+1))
+ if (!tal_resize(&buffer, max+extra+add_nul_term))
return NULL;
max += extra;
}
}
- buffer[size] = '\0';
- tal_resize(&buffer, size+1);
+ if (add_nul_term)
+ buffer[size] = '\0';
+ tal_resize(&buffer, size+add_nul_term);
return buffer;
}
-void *grab_file(const void *ctx, const char *filename)
+static void *grab_file_internal(const void *ctx, const char *filename, bool add_nul_term)
{
int fd;
char *buffer;
if (fd < 0)
return NULL;
- buffer = grab_fd(ctx, fd);
+ buffer = grab_fd_internal(ctx, fd, add_nul_term);
close_noerr(fd);
return buffer;
}
+
+void *grab_fd_raw(const void *ctx, int fd)
+{
+ return grab_fd_internal(ctx, fd, false);
+}
+
+void *grab_fd_str(const void *ctx, int fd)
+{
+ return grab_fd_internal(ctx, fd, true);
+}
+
+void *grab_file_str(const void *ctx, const char *filename)
+{
+ return grab_file_internal(ctx, filename, true);
+}
+
+void *grab_file_raw(const void *ctx, const char *filename)
+{
+ return grab_file_internal(ctx, filename, false);
+}
#ifndef CCAN_TAL_GRAB_FILE_H
#define CCAN_TAL_GRAB_FILE_H
#include <stdio.h> // For size_t
+#include <ccan/compiler/compiler.h>
/**
- * grab_fd - read all of a file descriptor into memory
+ * grab_fd_raw - read all of a file descriptor into memory WITHOUT adding a nul.
+ * @ctx: the context to tallocate from (often NULL)
+ * @fd: the file descriptor to read from
+ * @size: the (optional) size of the file
+ *
+ * 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.
+ *
+ * Note that this does *not* currently exit on EINTR, but continues
+ * reading. *
+ * Example:
+ * // Return the first line.
+ * static char *read_stdin_all(void)
+ * {
+ * return grab_fd_raw(NULL, 0);
+ * }
+ */
+void *grab_fd_raw(const void *ctx, int fd);
+
+/**
+ * grab_fd_str - read all of a file descriptor into memory with a NUL terminator.
* @ctx: the context to tallocate from (often NULL)
* @fd: the file descriptor to read from
*
* {
* char **lines, *all;
*
- * all = grab_fd(NULL, 0);
+ * all = grab_fd_str(NULL, 0);
* if (!all)
* return NULL;
* lines = tal_strsplit(NULL, all, "\n", STR_EMPTY_OK);
* return lines;
* }
*/
-void *grab_fd(const void *ctx, int fd);
+void *grab_fd_str(const void *ctx, int fd);
+
+/* Deprecated synonym for grab_fd_str */
+static inline void *grab_fd(const void *ctx, int fd)
+ WARN_DEPRECATED;
+static inline void *grab_fd(const void *ctx, int fd)
+{
+ return grab_fd_str(ctx, fd);
+}
/**
- * grab_file - read all of a file (or stdin) into memory
+ * grab_file_str - read all of a file (or stdin) into memory with a NUL terminator
* @ctx: the context to tallocate from (often NULL)
* @filename: the file to read (NULL for stdin)
*
* {
* char **lines, *all;
*
- * all = grab_file(NULL, filename);
+ * all = grab_file_str(NULL, filename);
* if (!all)
* return NULL;
* lines = tal_strsplit(NULL, all, "\n", STR_EMPTY_OK);
* return lines;
* }
*/
-void *grab_file(const void *ctx, const char *filename);
+void *grab_file_str(const void *ctx, const char *filename);
+
+/**
+ * grab_file_raw - read all of a file (or stdin) into memory WITHOUT a NUL terminator
+ * @ctx: the context to tallocate from (often NULL)
+ * @filename: the file to read (NULL for stdin)
+ * @size: the (optional) size of the file
+ *
+ * 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.
+ *
+ * Example:
+ * static char *read_file_all(const char *filename)
+ * {
+ * return grab_file_raw(NULL, filename);
+ * }
+ */
+void *grab_file_raw(const void *ctx, const char *filename);
+
+/* Deprecated synonym for grab_file_str */
+static inline void *grab_file(const void *ctx, const char *filename)
+ WARN_DEPRECATED;
+static inline void *grab_file(const void *ctx, const char *filename)
+{
+ return grab_file_str(ctx, filename);
+}
+
#endif /* CCAN_TAL_GRAB_FILE_H */
-/* This is test for grab_file() function
+/* This is test for grab_file_str() and grab_file_raw() functions
*/
#include <ccan/tal/grab_file/grab_file.h>
#include <stdlib.h>
main(void)
{
unsigned int i;
- char **split, *str;
+ char **split, *str, *raw;
int length;
struct stat st;
- str = grab_file(NULL, "test/run-grab.c");
+ plan_tests(5);
+ str = grab_file_str(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"));
+ ok1(!strcmp(split[0], "This is test for grab_file_str() and grab_file_raw() functions"));
for (i = 1; split[i]; i++)
length += strlen(split[i]);
- ok1(!strcmp(split[i-1], "/* End of grab_file() test */"));
+ ok1(!strcmp(split[i-1], "/* End of grab_file.c 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);
+
+ /* Raw does not nul term */
+ raw = grab_file_raw(str, "test/run-grab.c");
+ ok1(tal_count(raw) + 1 == tal_count(str));
+ ok1(memcmp(raw, str, tal_bytelen(raw)) == 0);
tal_free(str);
return 0;
}
-/* End of grab_file() test */
+/* End of grab_file.c test */