about summary refs log tree commit diff
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
mblaze-fc4c696e3df800dec5aa4fd6c7745b4e38dbe40a.tar.xz
mblaze-fc4c696e3df800dec5aa4fd6c7745b4e38dbe40a.zip
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;
 }