From 59781de0c0512ed3c862bef5735d569b2adcd4a3 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Wed, 20 Jan 2016 16:48:01 -0600 Subject: First stab at making readfileat() realloc() in a loop to read long files. --- lib/lib.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'lib/lib.c') diff --git a/lib/lib.c b/lib/lib.c index 955960ca..b0ac4715 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -447,22 +447,38 @@ off_t fdlength(int fd) // note: for existing buffers use len = size-1, will set buf[len] = 0 char *readfileat(int dirfd, char *name, char *ibuf, off_t *plen) { - off_t len = *plen-!!ibuf; + off_t len, rlen; int fd; - char *buf; + char *buf, *rbuf; + + // Unsafe to probe for size with a supplied buffer, don't ever do that. + if (CFG_TOYBOX_DEBUG && (ibuf ? !*plen : *plen)) error_exit("bad readfileat"); if (-1 == (fd = openat(dirfd, name, O_RDONLY))) return 0; - if (!len) { - len = fdlength(fd); - // proc files don't report a length, so try 1 page minimum. - if (len<4096) len = 4096; - } + + // If we dunno the length, probe it. If we can't probe, start with 1 page. + if (!*plen) { + if ((len = fdlength(fd))>0) *plen = len; + else len = 4096; + } else len = *plen-1; + if (!ibuf) buf = xmalloc(len+1); else buf = ibuf; - *plen = len = readall(fd, buf, len); + for (rbuf = buf;;) { + rlen = readall(fd, rbuf, len); + if (*plen || rlen