]> git.ozlabs.org Git - ccan/blob - ccan/tal/grab_file/grab_file.c
88e7c22533ad2b8d1a1b07253e5ea613e99baf14
[ccan] / ccan / tal / grab_file / grab_file.c
1 /* Licensed under LGPLv2+ - see LICENSE file for details */
2 #include "grab_file.h"
3 #include <ccan/tal/tal.h>
4 #include <ccan/noerr/noerr.h>
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9
10 void *grab_fd(const void *ctx, int fd)
11 {
12         int ret;
13         size_t max, size;
14         char *buffer;
15         struct stat st;
16
17         size = 0;
18
19         if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode))
20                 max = st.st_size;
21         else
22                 max = 16384;
23
24         buffer = tal_arr(ctx, char, max+1);
25         while ((ret = read(fd, buffer + size, max - size)) > 0) {
26                 size += ret;
27                 if (size == max) {
28                         size_t extra = max;
29                         if (extra > 1024 * 1024)
30                                 extra = 1024 * 1024;
31
32                         if (!tal_resize(&buffer, max+extra+1))
33                                 return NULL;
34
35                         max += extra;
36                 }
37         }
38         if (ret < 0)
39                 buffer = tal_free(buffer);
40         else {
41                 buffer[size] = '\0';
42                 tal_resize(&buffer, size+1);
43         }
44
45         return buffer;
46 }
47
48 void *grab_file(const void *ctx, const char *filename)
49 {
50         int fd;
51         char *buffer;
52
53         if (!filename)
54                 fd = dup(STDIN_FILENO);
55         else
56                 fd = open(filename, O_RDONLY, 0);
57
58         if (fd < 0)
59                 return NULL;
60
61         buffer = grab_fd(ctx, fd);
62         close_noerr(fd);
63         return buffer;
64 }