]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.9-20110130
authorWietse Venema <wietse@porcupine.org>
Sun, 30 Jan 2011 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:37:09 +0000 (06:37 +0000)
12 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/WISHLIST
postfix/html/postconf.5.html
postfix/man/man5/postconf.5
postfix/proto/postconf.proto
postfix/src/global/mail_version.h
postfix/src/global/smtp_stream.c
postfix/src/util/vbuf.c
postfix/src/util/vbuf.h
postfix/src/util/vstream.c
postfix/src/util/vstream.h

index 67300977634707128c524cc9f333df5ff4bcd746..28e43204619e8f2f6573a685d4b442ab9289e029 100644 (file)
@@ -16535,3 +16535,13 @@ Apologies for any names omitted.
        and made available as optional patch for earlier releases.
        Further refinements have only dimishing returns and can
        evolve in the 2.9 release cycle.  File: util/vstream.c.
+
+20110128
+
+       Infrastructure: separate VSTREAM flags for read or write
+       errors. Files: util/vbuf.[hc], util/vstream.[hc].
+
+       Cleanup: after write error, the smtp_stream routines now
+       disable further network writes. This eliminates the need
+       for clumsy code to avoid unwanted I/O while shutting down
+       a TLS engine or closing a VSTREAM.  File: util/smtp_stream.c.
index a9634df6775f8ae5ea6c0da4cca459af39a88e46..e807d43c6ccddf4c4c798785995fb1c2d67bd296 100644 (file)
@@ -13,3 +13,10 @@ specifies the release date of a stable release or snapshot release.
 
 If you upgrade from Postfix 2.7 or earlier, read RELEASE_NOTES-2.8
 before proceeding.
+
+Incompatible changes with snapshot 20110130
+===========================================
+
+The VSTREAM error flags are now split into separate read and write
+error flags. As a result of this change, all programs that use
+VSTREAMs MUST be recompiled.
index 80d381fd521de86f726591b6321c8a930ed31a7c..0f4a67c8d76246fd1c588b52fa2c5174d17b2e81 100644 (file)
@@ -9,6 +9,8 @@ Wish list:
        Don't forget Apple's code donation for fetching mail from
        IMAP server.
 
+       propagate alias owner from pcre, regexp, etc. databases.
+
        vstream_peek_len() and vstream_peek_data() to count the
        unread data and to access it, respectively. vstream_peek_data()
        can access the saved read buffer if a double-buffered stream
@@ -102,9 +104,16 @@ Wish list:
 
        IF/ENDIF support for CIDR tables.
 
-       Make postconf aware of magical suffixes (the ones that
-       combine with transport names) and show them in "postconf
-       -n" output. Making this work with "postconf -d" is trickier.
+       Make postconf aware of local_, smtp_, etc. parameter names
+       that have prefixes derived from mail delivery transport
+       names.  Unfortunately, it is wrong to assume that all "unix"
+       master.cf entries are delivery agents (though it may be OK
+       for postconf to peek in master.cf when given a parameter
+       with an unknown prefix). This requires a new main.cf parameter
+       that lists all known mail delivery transport names. postconf
+       can safely ignore names that don't exist in master.cf, and
+       qmgr_transport_create() can safely warn about a name that
+       isn't listed in that new main.cf parameter.
 
        Need a regular expression table to translate address
        verification responses into hard/soft/accept reply codes.
index a6a0397f5907ed04131dd97109ec75100278bc46..4bfcf456b4d543330488f34d2ec4fe4c7e6e060a 100644 (file)
@@ -6435,8 +6435,8 @@ or <a href="postconf.5.html#reject_non_fqdn_recipient">reject_non_fqdn_recipient
 does not arrive via the Postfix <a href="smtpd.8.html">smtpd(8)</a> server. This includes local
 submission via the <a href="sendmail.1.html">sendmail(1)</a> command line, new mail that arrives
 via the Postfix <a href="qmqpd.8.html">qmqpd(8)</a> server, and old mail that is re-injected
-into the queue with "postsuper -r".  See the <a href="MILTER_README.html">MILTER_README</a> document
-for details.  </p>
+into the queue with "postsuper -r".  Specify space or comma as
+separator. See the <a href="MILTER_README.html">MILTER_README</a> document for details.  </p>
 
 <p> This feature is available in Postfix 2.3 and later. </p>
 
@@ -12654,8 +12654,8 @@ always allows up to 100 junk commands by default.  </p>
 (default: empty)</b></DT><DD>
 
 <p> A list of Milter (mail filter) applications for new mail that
-arrives via the Postfix <a href="smtpd.8.html">smtpd(8)</a> server.  See the <a href="MILTER_README.html">MILTER_README</a>
-document for details.  </p>
+arrives via the Postfix <a href="smtpd.8.html">smtpd(8)</a> server. Specify space or comma as
+separator. See the <a href="MILTER_README.html">MILTER_README</a> document for details.  </p>
 
 <p> This feature is available in Postfix 2.3 and later. </p>
 
index e1dae684a7d16eec83a43df27ea73a7ef3b0e0c9..24616c234bcee63c120f898af3f1e8f8fd4582da 100644 (file)
@@ -3624,8 +3624,8 @@ A list of Milter (mail filter) applications for new mail that
 does not arrive via the Postfix \fBsmtpd\fR(8) server. This includes local
 submission via the \fBsendmail\fR(1) command line, new mail that arrives
 via the Postfix \fBqmqpd\fR(8) server, and old mail that is re-injected
-into the queue with "postsuper -r".  See the MILTER_README document
-for details.
+into the queue with "postsuper -r".  Specify space or comma as
+separator. See the MILTER_README document for details.
 .PP
 This feature is available in Postfix 2.3 and later.
 .SH notify_classes (default: resource, software)
@@ -7893,8 +7893,8 @@ overload to just 1. With Postfix 2.5 and earlier, the SMTP server
 always allows up to 100 junk commands by default.
 .SH smtpd_milters (default: empty)
 A list of Milter (mail filter) applications for new mail that
-arrives via the Postfix \fBsmtpd\fR(8) server.  See the MILTER_README
-document for details.
+arrives via the Postfix \fBsmtpd\fR(8) server. Specify space or comma as
+separator. See the MILTER_README document for details.
 .PP
 This feature is available in Postfix 2.3 and later.
 .SH smtpd_noop_commands (default: empty)
index d583da7fc4047b306e06765efdfecebd960b6c6f..d712ee499dc1188774c2e9b3205b312a764a33e9 100644 (file)
@@ -10716,8 +10716,8 @@ smtp_tls_fingerprint_cert_match =
 %PARAM smtpd_milters
 
 <p> A list of Milter (mail filter) applications for new mail that
-arrives via the Postfix smtpd(8) server.  See the MILTER_README
-document for details.  </p>
+arrives via the Postfix smtpd(8) server. Specify space or comma as
+separator. See the MILTER_README document for details.  </p>
 
 <p> This feature is available in Postfix 2.3 and later. </p>
 
@@ -10727,8 +10727,8 @@ document for details.  </p>
 does not arrive via the Postfix smtpd(8) server. This includes local
 submission via the sendmail(1) command line, new mail that arrives
 via the Postfix qmqpd(8) server, and old mail that is re-injected
-into the queue with "postsuper -r".  See the MILTER_README document
-for details.  </p>
+into the queue with "postsuper -r".  Specify space or comma as
+separator. See the MILTER_README document for details.  </p>
 
 <p> This feature is available in Postfix 2.3 and later. </p>
 
index f4530001190b06c4b1a3f35933d7dafd24af9042..a4f7c72300b288a6d997b66a671c1f0be355eac6 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20110126"
+#define MAIL_RELEASE_DATE      "20110130"
 #define MAIL_VERSION_NUMBER    "2.9"
 
 #ifdef SNAPSHOT
index b404244dd941014ba5be2802859a8ed15f60ad0b..7c5d19ad9d24abc02afec7f742923ba74409192d 100644 (file)
@@ -90,6 +90,9 @@
 /* .ad
 /*     In case of error, a vstream_longjmp() call is performed to the
 /*     context specified with vstream_setjmp().
+/*     After write error, further writes to the socket are disabled.
+/*     This eliminates the need for clumsy code to avoid unwanted
+/*     I/O while shutting down a TLS engine or closing a VSTREAM.
 /*     Error codes passed along with vstream_longjmp() are:
 /* .IP SMTP_ERR_EOF
 /*     An I/O error happened, or the peer has disconnected unexpectedly.
@@ -163,12 +166,23 @@ static void smtp_timeout_reset(VSTREAM *stream)
                    VSTREAM_CTL_END);
 }
 
-/* smtp_timeout_detect - test the per-stream timeout flag */
+/* smtp_longjmp - raise an exception */
 
-static void smtp_timeout_detect(VSTREAM *stream)
+static NORETURN smtp_longjmp(VSTREAM *stream, int err, const char *context)
 {
-    if (vstream_ftimeout(stream))
-       vstream_longjmp(stream, SMTP_ERR_TIME);
+
+    /*
+     * If we failed to write, don't bang our head against the wall another
+     * time when closing the stream. In the case of SMTP over TLS, poisoning
+     * the socket with shutdown() is more robust than purging the VSTREAM
+     * buffer or replacing the write function pointer with dummy_write().
+     */
+    if (msg_verbose)
+       msg_info("%s: %s", context, err == SMTP_ERR_TIME ? "timeout" : "EOF");
+    if (vstream_wr_error(stream)
+       && shutdown(vstream_fileno(stream), SHUT_WR) < 0)
+       msg_warn("shutdown: %m");
+    vstream_longjmp(stream, err);
 }
 
 /* smtp_timeout_setup - configure timeout trap */
@@ -193,16 +207,14 @@ void    smtp_flush(VSTREAM *stream)
      */
     smtp_timeout_reset(stream);
     err = vstream_fflush(stream);
-    smtp_timeout_detect(stream);
 
     /*
      * See if there was a problem.
      */
-    if (err != 0) {
-       if (msg_verbose)
-           msg_info("smtp_flush: EOF");
-       vstream_longjmp(stream, SMTP_ERR_EOF);
-    }
+    if (vstream_ftimeout(stream))
+       smtp_longjmp(stream, SMTP_ERR_TIME, "smtp_flush");
+    if (err != 0)
+       smtp_longjmp(stream, SMTP_ERR_EOF, "smtp_flush");
 }
 
 /* smtp_vprintf - write one line to SMTP peer */
@@ -218,16 +230,14 @@ void    smtp_vprintf(VSTREAM *stream, const char *fmt, va_list ap)
     vstream_vfprintf(stream, fmt, ap);
     vstream_fputs("\r\n", stream);
     err = vstream_ferror(stream);
-    smtp_timeout_detect(stream);
 
     /*
      * See if there was a problem.
      */
-    if (err != 0) {
-       if (msg_verbose)
-           msg_info("smtp_vprintf: EOF");
-       vstream_longjmp(stream, SMTP_ERR_EOF);
-    }
+    if (vstream_ftimeout(stream))
+       smtp_longjmp(stream, SMTP_ERR_TIME, "smtp_vprintf");
+    if (err != 0)
+       smtp_longjmp(stream, SMTP_ERR_EOF, "smtp_vprintf");
 }
 
 /* smtp_printf - write one line to SMTP peer */
@@ -252,16 +262,14 @@ int     smtp_fgetc(VSTREAM *stream)
      */
     smtp_timeout_reset(stream);
     ch = VSTREAM_GETC(stream);
-    smtp_timeout_detect(stream);
 
     /*
      * See if there was a problem.
      */
-    if (vstream_feof(stream) || vstream_ferror(stream)) {
-       if (msg_verbose)
-           msg_info("smtp_fgetc: EOF");
-       vstream_longjmp(stream, SMTP_ERR_EOF);
-    }
+    if (vstream_ftimeout(stream))
+       smtp_longjmp(stream, SMTP_ERR_TIME, "smtp_fgetc");
+    if (vstream_feof(stream) || vstream_ferror(stream))
+       smtp_longjmp(stream, SMTP_ERR_EOF, "smtp_fgetc");
     return (ch);
 }
 
@@ -321,17 +329,15 @@ int     smtp_get(VSTRING *vp, VSTREAM *stream, ssize_t bound)
     default:
        break;
     }
-    smtp_timeout_detect(stream);
 
     /*
      * EOF is bad, whether or not it happens in the middle of a record. Don't
      * allow data that was truncated because of EOF.
      */
-    if (vstream_feof(stream) || vstream_ferror(stream)) {
-       if (msg_verbose)
-           msg_info("smtp_get: EOF");
-       vstream_longjmp(stream, SMTP_ERR_EOF);
-    }
+    if (vstream_ftimeout(stream))
+       smtp_longjmp(stream, SMTP_ERR_TIME, "smtp_get");
+    if (vstream_feof(stream) || vstream_ferror(stream))
+       smtp_longjmp(stream, SMTP_ERR_EOF, "smtp_get");
     return (last_char);
 }
 
@@ -350,16 +356,14 @@ void    smtp_fputs(const char *cp, ssize_t todo, VSTREAM *stream)
     smtp_timeout_reset(stream);
     err = (vstream_fwrite(stream, cp, todo) != todo
           || vstream_fputs("\r\n", stream) == VSTREAM_EOF);
-    smtp_timeout_detect(stream);
 
     /*
      * See if there was a problem.
      */
-    if (err != 0) {
-       if (msg_verbose)
-           msg_info("smtp_fputs: EOF");
-       vstream_longjmp(stream, SMTP_ERR_EOF);
-    }
+    if (vstream_ftimeout(stream))
+       smtp_longjmp(stream, SMTP_ERR_TIME, "smtp_fputs");
+    if (err != 0)
+       smtp_longjmp(stream, SMTP_ERR_EOF, "smtp_fputs");
 }
 
 /* smtp_fwrite - write one string to SMTP peer */
@@ -376,16 +380,14 @@ void    smtp_fwrite(const char *cp, ssize_t todo, VSTREAM *stream)
      */
     smtp_timeout_reset(stream);
     err = (vstream_fwrite(stream, cp, todo) != todo);
-    smtp_timeout_detect(stream);
 
     /*
      * See if there was a problem.
      */
-    if (err != 0) {
-       if (msg_verbose)
-           msg_info("smtp_fwrite: EOF");
-       vstream_longjmp(stream, SMTP_ERR_EOF);
-    }
+    if (vstream_ftimeout(stream))
+       smtp_longjmp(stream, SMTP_ERR_TIME, "smtp_fwrite");
+    if (err != 0)
+       smtp_longjmp(stream, SMTP_ERR_EOF, "smtp_fwrite");
 }
 
 /* smtp_fputc - write to SMTP peer */
@@ -399,14 +401,12 @@ void    smtp_fputc(int ch, VSTREAM *stream)
      */
     smtp_timeout_reset(stream);
     stat = VSTREAM_PUTC(ch, stream);
-    smtp_timeout_detect(stream);
 
     /*
      * See if there was a problem.
      */
-    if (stat == VSTREAM_EOF) {
-       if (msg_verbose)
-           msg_info("smtp_fputc: EOF");
-       vstream_longjmp(stream, SMTP_ERR_EOF);
-    }
+    if (vstream_ftimeout(stream))
+       smtp_longjmp(stream, SMTP_ERR_TIME, "smtp_fputc");
+    if (stat == VSTREAM_EOF)
+       smtp_longjmp(stream, SMTP_ERR_EOF, "smtp_fputc");
 }
index 22eaffbc5f7580f4bf3ba7b4306212b2ae150f51..c82a4492d4058892a983b5aa994a9327de5a547c 100644 (file)
 /*
 /*     int     vbuf_clearerr(bp)
 /*     VBUF    *bp;
+/*
+/*     int     vbuf_rd_err(bp)
+/*     VBUF    *bp;
+/*
+/*     int     vbuf_wr_err(bp)
+/*     VBUF    *bp;
+/*
+/*     int     vbuf_rd_timeout(bp)
+/*     VBUF    *bp;
+/*
+/*     int     vbuf_wr_timeout(bp)
+/*     VBUF    *bp;
 /* DESCRIPTION
 /*     This module implements a buffer with read/write primitives that
 /*     automatically handle buffer-empty or buffer-full conditions.
 /*
 /*     vbuf_timeout() is a macro that returns non-zero if a timeout error
 /*     condition was detected while reading or writing the buffer. The
-/*     error status can be reset by calling vbuf_clearerr().
+/*     error status can be reset by calling vbuf_clearerr(). 
 /*
 /*     vbuf_err() is a macro that returns non-zero if a non-EOF error
 /*     (including timeout) condition was detected while reading or writing
 /*     the buffer. The error status can be reset by calling vbuf_clearerr().
 /*
+/*     The vbuf_rd_mumble() and vbuf_wr_mumble() macros report on
+/*     read and write error conditions, respectively.
+/*
 /*     vbuf_eof() is a macro that returns non-zero if an end-of-file
 /*     condition was detected while reading or writing the buffer. The error
 /*     status can be reset by calling vbuf_clearerr().
 int     vbuf_unget(VBUF *bp, int ch)
 {
     if ((ch & 0xff) != ch || -bp->cnt >= bp->len) {
-       bp->flags |= VBUF_FLAG_ERR;
+       bp->flags |= VBUF_FLAG_RD_ERR;          /* This error affects reads! */
        return (VBUF_EOF);
     } else {
        bp->cnt--;
index 6052b4ed7542c8044c733eab048157de782c56ab..d81ce057317a2adcbcd9f57c0e8341833a84230a 100644 (file)
@@ -59,11 +59,20 @@ struct VBUF {
  /*
   * Buffer status management.
   */
-#define        VBUF_FLAG_ERR   (1<<0)          /* some I/O error */
-#define VBUF_FLAG_EOF  (1<<1)          /* end of data */
-#define VBUF_FLAG_TIMEOUT (1<<2)       /* timeout error */
+#define VBUF_FLAG_RD_ERR       (1<<0)  /* read error */
+#define VBUF_FLAG_WR_ERR       (1<<1)  /* write error */
+#define VBUF_FLAG_ERR          (VBUF_FLAG_RD_ERR | VBUF_FLAG_WR_ERR)
+#define VBUF_FLAG_EOF          (1<<2)  /* end of data */
+#define VBUF_FLAG_RD_TIMEOUT   (1<<3)  /* read timeout */
+#define VBUF_FLAG_WR_TIMEOUT   (1<<4)  /* write timeout */
+#define VBUF_FLAG_TIMEOUT      (VBUF_FLAG_RD_TIMEOUT | VBUF_FLAG_WR_TIMEOUT)
 #define VBUF_FLAG_BAD  (VBUF_FLAG_ERR | VBUF_FLAG_EOF | VBUF_FLAG_TIMEOUT)
-#define VBUF_FLAG_FIXED        (1<<3)          /* fixed-size buffer */
+#define VBUF_FLAG_FIXED                (1<<5)  /* fixed-size buffer */
+
+#define vbuf_rd_error(v) ((v)->flags & (VBUF_FLAG_RD_ERR | VBUF_FLAG_RD_TIMEOUT))
+#define vbuf_wr_error(v) ((v)->flags & (VBUF_FLAG_WR_ERR | VBUF_FLAG_WR_TIMEOUT))
+#define vbuf_rd_timeout(v)     ((v)->flags & VBUF_FLAG_RD_TIMEOUT)
+#define vbuf_wr_timeout(v)     ((v)->flags & VBUF_FLAG_WR_TIMEOUT)
 
 #define vbuf_error(v)  ((v)->flags & (VBUF_FLAG_ERR | VBUF_FLAG_TIMEOUT))
 #define vbuf_eof(v)    ((v)->flags & VBUF_FLAG_EOF)
index 2c45683af384c5a28246b7a20bf6b7b602924636..2e1f0a0682cd77125ba417947be128c7023c0fc1 100644 (file)
 /*
 /*     struct timeval vstream_ftimeval(stream)
 /*     VSTREAM *stream;
+/*
+/*     int     vstream_rd_error(stream)
+/*     VSTREAM *stream;
+/*
+/*     int     vstream_wr_error(stream)
+/*     VSTREAM *stream;
+/*
+/*     int     vstream_rd_timeout(stream)
+/*     VSTREAM *stream;
+/*
+/*     int     vstream_wr_timeout(stream)
+/*     VSTREAM *stream;
 /* DESCRIPTION
 /*     The \fIvstream\fR module implements light-weight buffered I/O
 /*     similar to the standard I/O routines.
 /*
 /*     vstream_ftimeval() is like vstream_ftime() but returns more
 /*     detail.
+/*
+/*     vstream_rd_mumble() and vstream_wr_mumble() report on
+/*     read and write error conditions, respectively.
 /* DIAGNOSTICS
 /*     Panics: interface violations. Fatal errors: out of memory.
 /* SEE ALSO
@@ -657,7 +672,7 @@ static int vstream_fflush_some(VSTREAM *stream, ssize_t to_flush)
        if (bp->flags & VSTREAM_FLAG_DEADLINE) {
            timeout = stream->time_limit.tv_sec + (stream->time_limit.tv_usec > 0);
            if (timeout <= 0) {
-               bp->flags |= (VSTREAM_FLAG_ERR | VSTREAM_FLAG_TIMEOUT);
+               bp->flags |= (VSTREAM_FLAG_WR_ERR | VSTREAM_FLAG_WR_TIMEOUT);
                errno = ETIMEDOUT;
                return (VSTREAM_EOF);
            }
@@ -668,18 +683,19 @@ static int vstream_fflush_some(VSTREAM *stream, ssize_t to_flush)
        } else
            timeout = stream->timeout;
        if ((n = stream->write_fn(stream->fd, data, len, timeout, stream->context)) <= 0) {
-           bp->flags |= VSTREAM_FLAG_ERR;
+           bp->flags |= VSTREAM_FLAG_WR_ERR;
            if (errno == ETIMEDOUT) {
-               bp->flags |= VSTREAM_FLAG_TIMEOUT;
+               bp->flags |= VSTREAM_FLAG_WR_TIMEOUT;
                stream->time_limit.tv_sec = stream->time_limit.tv_usec = 0;
            }
            return (VSTREAM_EOF);
        }
-       if (timeout)
+       if (timeout) {
            GETTIMEOFDAY(&stream->iotime);
-       if (bp->flags & VSTREAM_FLAG_DEADLINE) {
-           VSTREAM_SUB_TIME(elapsed, stream->iotime, before);
-           VSTREAM_SUB_TIME(stream->time_limit, stream->time_limit, elapsed);
+           if (bp->flags & VSTREAM_FLAG_DEADLINE) {
+               VSTREAM_SUB_TIME(elapsed, stream->iotime, before);
+               VSTREAM_SUB_TIME(stream->time_limit, stream->time_limit, elapsed);
+           }
        }
        if (msg_verbose > 2 && stream != VSTREAM_ERR && n != to_flush)
            msg_info("%s: %d flushed %ld/%ld", myname, stream->fd,
@@ -808,7 +824,7 @@ static int vstream_buf_get_ready(VBUF *bp)
     if (bp->flags & VSTREAM_FLAG_DEADLINE) {
        timeout = stream->time_limit.tv_sec + (stream->time_limit.tv_usec > 0);
        if (timeout <= 0) {
-           bp->flags |= (VSTREAM_FLAG_ERR | VSTREAM_FLAG_TIMEOUT);
+           bp->flags |= (VSTREAM_FLAG_RD_ERR | VSTREAM_FLAG_RD_TIMEOUT);
            errno = ETIMEDOUT;
            return (VSTREAM_EOF);
        }
@@ -817,9 +833,9 @@ static int vstream_buf_get_ready(VBUF *bp)
        timeout = stream->timeout;
     switch (n = stream->read_fn(stream->fd, bp->data, bp->len, timeout, stream->context)) {
     case -1:
-       bp->flags |= VSTREAM_FLAG_ERR;
+       bp->flags |= VSTREAM_FLAG_RD_ERR;
        if (errno == ETIMEDOUT) {
-           bp->flags |= VSTREAM_FLAG_TIMEOUT;
+           bp->flags |= VSTREAM_FLAG_RD_TIMEOUT;
            stream->time_limit.tv_sec = stream->time_limit.tv_usec = 0;
        }
        return (VSTREAM_EOF);
@@ -827,11 +843,12 @@ static int vstream_buf_get_ready(VBUF *bp)
        bp->flags |= VSTREAM_FLAG_EOF;
        return (VSTREAM_EOF);
     default:
-       if (timeout)
+       if (timeout) {
            GETTIMEOFDAY(&stream->iotime);
-       if (bp->flags & VSTREAM_FLAG_DEADLINE) {
-           VSTREAM_SUB_TIME(elapsed, stream->iotime, before);
-           VSTREAM_SUB_TIME(stream->time_limit, stream->time_limit, elapsed);
+           if (bp->flags & VSTREAM_FLAG_DEADLINE) {
+               VSTREAM_SUB_TIME(elapsed, stream->iotime, before);
+               VSTREAM_SUB_TIME(stream->time_limit, stream->time_limit, elapsed);
+           }
        }
        if (msg_verbose > 2)
            msg_info("%s: fd %d got %ld", myname, stream->fd, (long) n);
@@ -940,7 +957,7 @@ static int vstream_buf_space(VBUF *bp, ssize_t want)
        if ((shortage = (want - bp->cnt)) > 0) {
            if ((bp->flags & VSTREAM_FLAG_FIXED)
                || shortage > __MAXINT__(ssize_t) -bp->len - stream->req_bufsize) {
-               bp->flags |= VSTREAM_FLAG_ERR;
+               bp->flags |= VSTREAM_FLAG_WR_ERR;
            } else {
                incr = VSTREAM_ROUNDUP(shortage, stream->req_bufsize);
                vstream_buf_alloc(bp, bp->len + incr);
@@ -1057,7 +1074,8 @@ off_t   vstream_fseek(VSTREAM *stream, off_t offset, int whence)
      * Update the cached file seek position.
      */
     if ((stream->offset = lseek(stream->fd, offset, whence)) < 0) {
-       bp->flags |= VSTREAM_FLAG_NSEEK;
+       if (errno == ESPIPE)
+           bp->flags |= VSTREAM_FLAG_NSEEK;
     } else {
        bp->flags |= VSTREAM_FLAG_SEEK;
     }
index fb7d05854d826c63220627eeb12bd285a14c74ca..20b983e633ea365bcc3a7f4263776b19cd91ad9f 100644 (file)
@@ -66,6 +66,11 @@ extern VSTREAM vstream_fstd[];               /* pre-defined streams */
 #define VSTREAM_OUT            (&vstream_fstd[1])
 #define VSTREAM_ERR            (&vstream_fstd[2])
 
+#define VSTREAM_FLAG_RD_ERR    VBUF_FLAG_RD_ERR        /* read error */
+#define VSTREAM_FLAG_WR_ERR    VBUF_FLAG_WR_ERR        /* write error */
+#define VSTREAM_FLAG_RD_TIMEOUT        VBUF_FLAG_RD_TIMEOUT    /* read timeout */
+#define VSTREAM_FLAG_WR_TIMEOUT        VBUF_FLAG_WR_TIMEOUT    /* write timeout */
+
 #define        VSTREAM_FLAG_ERR        VBUF_FLAG_ERR   /* some I/O error */
 #define VSTREAM_FLAG_EOF       VBUF_FLAG_EOF   /* end of file */
 #define VSTREAM_FLAG_TIMEOUT   VBUF_FLAG_TIMEOUT       /* timeout error */
@@ -109,8 +114,12 @@ extern int vstream_fdclose(VSTREAM *);
 #define vstream_fileno(vp)     ((vp)->fd)
 #define vstream_req_bufsize(vp)        ((const ssize_t) ((vp)->req_bufsize))
 #define vstream_context(vp)    ((vp)->context)
+#define vstream_rd_error(vp)   vbuf_rd_error(&(vp)->buf)
+#define vstream_wr_error(vp)   vbuf_wr_error(&(vp)->buf)
 #define vstream_ferror(vp)     vbuf_error(&(vp)->buf)
 #define vstream_feof(vp)       vbuf_eof(&(vp)->buf)
+#define vstream_rd_timeout(vp) vbuf_rd_timeout(&(vp)->buf)
+#define vstream_wr_timeout(vp) vbuf_wr_timeout(&(vp)->buf)
 #define vstream_ftimeout(vp)   vbuf_timeout(&(vp)->buf)
 #define vstream_clearerr(vp)   vbuf_clearerr(&(vp)->buf)
 #define VSTREAM_PATH(vp)       ((vp)->path ? (const char *) (vp)->path : "unknown_stream")