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