aboutsummaryrefslogtreecommitdiff
path: root/blaze822.c
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2016-07-26 19:39:27 +0200
committerChristian Neukirchen <chneukirchen@gmail.com>2016-07-26 19:39:27 +0200
commitfc4c696e3df800dec5aa4fd6c7745b4e38dbe40a (patch)
treec65aa7567164d2e20a07d853d2d930474124e0ff /blaze822.c
parent68e5c8773d5eccf47e10caaebab4793f9dc2ac77 (diff)
downloadmblaze-fc4c696e3df800dec5aa4fd6c7745b4e38dbe40a.tar.gz
blaze822: blaze822_file: allow unknown file size (e.g. pipes)
Diffstat (limited to 'blaze822.c')
-rw-r--r--blaze822.c57
1 files changed, 48 insertions, 9 deletions
diff --git a/blaze822.c b/blaze822.c
index 373ec90..ef28383 100644
--- a/blaze822.c
+++ b/blaze822.c
@@ -453,6 +453,9 @@ blaze822_chdr(struct message *mesg, const char *chdr)
struct message *
blaze822_file(char *file)
{
+ char *buf = 0;
+ ssize_t rd = 0, n;
+
int fd = open(file, O_RDONLY);
if (fd < 0)
return 0;
@@ -461,26 +464,62 @@ blaze822_file(char *file)
if (fstat(fd, &st) < 0)
goto error;
- size_t s = st.st_size;
-
- char *buf = malloc(s+1);
- if (read(fd, buf, s) < 0) {
- // XXX handle short reads?
- perror("read");
- goto error;
+ if (S_ISFIFO(st.st_mode)) { // unbounded read, grow buffer
+ ssize_t bufalloc = 16384;
+ buf = malloc(bufalloc);
+ if (!buf)
+ goto error;
+
+ do {
+ if (bufalloc <= rd) {
+ bufalloc *= 2;
+ buf = realloc(buf, bufalloc);
+ if (!buf)
+ goto error;
+ }
+ if ((n = read(fd, buf + rd, 16384)) < 0) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ perror("read");
+ goto error;
+ }
+ }
+ rd += n;
+ } while (n > 0);
+ } else { // file size known
+ ssize_t s = st.st_size;
+
+ buf = malloc(s+1);
+ if (!buf)
+ goto error;
+
+ do {
+ if ((n = read(fd, buf + rd, s - rd)) < 0) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ perror("read");
+ goto error;
+ }
+ }
+ rd += n;
+ } while (rd < s && n > 0);
}
+
close(fd);
- buf[s] = 0;
+ buf[rd] = 0;
// XXX duplicate header in ram...
- struct message *mesg = blaze822_mem(buf, s);
+ struct message *mesg = blaze822_mem(buf, rd);
if (mesg)
mesg->bodychunk = buf;
return mesg;
error:
close(fd);
+ free(buf);
return 0;
}