X-Git-Url: https://git.distorted.org.uk/~mdw/fwd/blobdiff_plain/3eb9f39e442691de1337ac2978ae18b73dff1d4c..bdbbfcd4eb2f6e15270f558342630d964cb9f418:/chan.c diff --git a/chan.c b/chan.c index ad44891..2e483cd 100644 --- a/chan.c +++ b/chan.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: chan.c,v 1.4 1999/08/31 17:42:49 mdw Exp $ + * $Id: chan.c,v 1.6 2003/10/31 13:56:14 mdw Exp $ * * Channel management * @@ -29,6 +29,14 @@ /*----- Revision history --------------------------------------------------* * * $Log: chan.c,v $ + * Revision 1.6 2003/10/31 13:56:14 mdw + * Fix data corruption in channel\! + * + * Revision 1.5 2000/07/19 17:55:43 mdw + * (writechan): Pointless tweak: when the buffer is empty, reset the start + * pointer to the beginning. This saves doing slightly trickier + * @writev(2)@ calls when loading is light. + * * Revision 1.4 1999/08/31 17:42:49 mdw * Use `sel_force' to avoid a `select' call between reads and writes. * @@ -64,6 +72,12 @@ #include "chan.h" #include "fw.h" +#ifdef CHAN_DEBUG +# define D(x) x +#else +# define D(x) +#endif + /*----- Main code ---------------------------------------------------------*/ /* --- @writechan@ --- * @@ -90,16 +104,22 @@ static void writechan(int fd, unsigned mode, void *vp) /* --- Do the write --- */ - if (base + len <= CHAN_BUFSZ) + D( printf("writechan %d: base = %u, len = %u; ", fd, base, len); ) + if (base + len <= CHAN_BUFSZ) { + D( printf("%u:%u", base, len); ) w = write(fd, c->buf + base, len); - else { + } else { struct iovec iov[2]; iov[0].iov_base = c->buf + base; iov[0].iov_len = CHAN_BUFSZ - base; iov[1].iov_base = c->buf; iov[1].iov_len = len - iov[0].iov_len; + D( printf("%u:%u, %u:%u", + base, CHAN_BUFSZ - base, + 0, len + base - CHAN_BUFSZ); ) w = writev(fd, iov, 2); } + D( printf("; returned %d\n", w); ) /* --- Sift through the results --- */ @@ -113,14 +133,18 @@ static void writechan(int fd, unsigned mode, void *vp) else if (c->len == CHAN_BUFSZ && !(c->f & CHANF_CLOSE)) sel_addfile(&c->r); c->len -= w; + c->base += w; } if (c->len == 0) sel_rmfile(&c->w); /* --- Close the output end if necessary --- */ - if (c->len == 0 && (c->f & CHANF_CLOSE)) - c->func(c->p); + if (c->len == 0) { + c->base = 0; + if (c->f & CHANF_CLOSE) + c->func(c->p); + } return; /* --- Force a close if an error occurred --- */ @@ -145,21 +169,30 @@ static void readchan(int fd, unsigned mode, void *vp) { chan *c = vp; int r; - unsigned base = (c->base + c->len) & (CHAN_BUFSZ - 1); - unsigned len = CHAN_BUFSZ - c->len; + unsigned base = c->base; + unsigned len = c->len; /* --- Do the read --- */ - if (base + len <= CHAN_BUFSZ) - r = read(fd, c->buf + base, len); - else { + D( printf("readchan %d: base = %u, len = %u; ", fd, base, len); ) + if (base == 0) { + D( printf("%u:%u", len, CHAN_BUFSZ - len); ) + r = read(fd, c->buf + len, CHAN_BUFSZ - len); + } else if (base + len >= CHAN_BUFSZ) { + D( printf("%u:%u", base + len - CHAN_BUFSZ, CHAN_BUFSZ - len); ) + r = read(fd, c->buf + base + len - CHAN_BUFSZ, CHAN_BUFSZ - len); + } else { struct iovec iov[2]; - iov[0].iov_base = c->buf + base; - iov[0].iov_len = CHAN_BUFSZ - base; + iov[0].iov_base = c->buf + base + len; + iov[0].iov_len = CHAN_BUFSZ - base - len; iov[1].iov_base = c->buf; - iov[1].iov_len = len - iov[0].iov_len; + iov[1].iov_len = base; + D( printf("%u:%u, %u:%u", + base + len, CHAN_BUFSZ - base - len, + 0, base); ) r = readv(fd, iov, 2); } + D( printf("; returned %d\n", r); ) /* --- Sift through the results --- */