Michael Forney wrote:
> On Fri, Feb 3, 2017 at 9:35 AM, willy <[email protected]> wrote:
> > Willy Gfn wrote:
> >> Hello,
> >>
> >> The attached patch makes tar read again from a pipe in case less bytes
> >> are read than expected.
> >> This prevent a bug where it fails to extract files correctly because
> >> not enough bytes are read from, eg, a pipe hooked to a decompression
> >> program.
> >
> > Just realised there is a bug in my patch. We should only keep reading
> > if read() returns more than 0 bytes, otherwise the functions returns.
> >
> > Updated patch attached.
>
> If there is EINTR, s will be decremented by 1 incorrectly since r will
> be -1. I think you need to move s += r to after the if (r < 0). But, I
> don't think you could even get EINTR since tar doesn't set any signal
> handlers. Maybe there is some case I don't know about though.
Here is an updated patch for it. I prefer keeping the EINTR check for
now. It doesn't harm, and in case signal handling is added someday,
this function will be ready for it.
diff --git a/tar.c b/tar.c
index 4a81f8f..35aba55 100644
--- a/tar.c
+++ b/tar.c
@@ -155,16 +155,22 @@ decomp(int fd, const char *tool, const char *flags)
static ssize_t
eread(int fd, void *buf, size_t n)
{
- ssize_t r;
+ char *tmp = buf;
+ ssize_t r, s = 0;
again:
- r = read(fd, buf, n);
+ r = read(fd, tmp + s, n - s);
if (r < 0) {
- if (errno == EINTR)
+ if (errno == EINTR || errno == EAGAIN)
goto again;
eprintf("read:");
}
- return r;
+
+ s += r;
+ if (r && s < n)
+ goto again;
+
+ return s;
}
static ssize_t