Fix grab_file on other than regular files.
[ccan] / ccan / grab_file / grab_file.c
index 6f2c9fe17e9473f5c3a84d423e30fb35e01283bd..68a3b7cde32e483ba5cd8af768be15132a2ced13 100644 (file)
@@ -1,6 +1,6 @@
 #include "grab_file.h"
-#include "talloc/talloc.h"
-#include "noerr/noerr.h"
+#include <ccan/talloc/talloc.h>
+#include <ccan/noerr/noerr.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -9,18 +9,33 @@
 void *grab_fd(const void *ctx, int fd, size_t *size)
 {
        int ret;
-       size_t max = 16384, s;
+       size_t max, s;
        char *buffer;
+       struct stat st;
 
        if (!size)
                size = &s;
        *size = 0;
 
+       if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode))
+               max = st.st_size;
+       else
+               max = 16384;
+
        buffer = talloc_array(ctx, char, max+1);
        while ((ret = read(fd, buffer + *size, max - *size)) > 0) {
                *size += ret;
-               if (*size == max)
-                       buffer = talloc_realloc(ctx, buffer, char, max*=2 + 1);
+               if (*size == max) {
+                       buffer = talloc_realloc(ctx, buffer, char, max*2+1);
+                       if (!buffer) {
+                               buffer = talloc_realloc(ctx, buffer, char,
+                                                       max + 1024*1024 + 1);
+                               if (!buffer)
+                                       return NULL;
+                               max += 1024*1024;
+                       } else
+                               max *= 2;
+               }
        }
        if (ret < 0) {
                talloc_free(buffer);