/* * Flush any buffered output and EOF from zio READER object * to destination. */ int zio_flush (zio_t *zio) { int len; int rc = 0; if ((zio == NULL) || (zio->magic != ZIO_MAGIC)) return (-1); if (zio_reader (zio) && !zio->send) return (-1); zio_debug (zio, "zio_flush\n"); /* * Nothing to flush if EOF already sent to consumer: */ if (zio_eof_sent (zio)) return (0); if (zio_writer (zio)) return zio_writer_flush_all (zio); /* else zio reader: */ while (((len = zio_data_to_flush (zio)) > 0) || zio_eof (zio)) { char * buf = NULL; int n = 0; zio_debug (zio, "zio_flush: len = %d, eof = %d\n", len, zio_eof (zio)); if (len > 0) { buf = xzmalloc (len + 1); if ((n = zio_fd_read (zio, buf, len + 1)) <= 0) { if (n < 0) { zio_debug (zio, "zio_read: %s", strerror (errno)); rc = -1; } /* * We may not be able to read any data from the buffer * because we are line buffering and there is not yet * a full line in the buffer. In this case just exit * so we can buffer more data. */ free (buf); return (rc); } } zio_debug (zio, "zio_data_to_flush = %d\n", zio_data_to_flush (zio)); zio_debug (zio, "zio_flush: Sending %d (%s) [eof=%d]\n", n, buf, zio_eof(zio)); rc = zio_send (zio, buf, n); if (buf) free (buf); if (zio_eof_sent (zio)) break; } return (rc); }
/* * write data into zio buffer */ static int zio_write_data (zio_t *zio, void *buf, size_t len) { int n = 0; int ndropped = 0; /* * If buffer is empty, first try writing directly to dstfd * to avoid double-copy: */ if (zio_buffer_empty (zio)) { n = write (zio->dstfd, buf, len); if (n < 0) { if (errno == EAGAIN) n = 0; else return (-1); } /* * If we wrote everything, return early */ if (n == len) { if (zio_eof (zio)) zio_close (zio); return (len); } } /* * Otherwise, buffer any remaining data */ if ((len - n) && cbuf_write (zio->buf, buf+n, len-n, &ndropped) < 0) return (-1); return (0); }
static int zio_write_pending (zio_t *zio) { if (zio_closed (zio)) return (0); if ((zio_buffer_used (zio) > 0) || zio_eof (zio)) return (1); return (0); }
static int zio_fd_read (zio_t *zio, void *dst, int len) { assert (zio != NULL); assert (zio->magic == ZIO_MAGIC); assert (zio->buf); if (zio_line_buffered (zio) && !zio_eof (zio)) return cbuf_read_line (zio->buf, dst, len, -1); else return cbuf_read (zio->buf, dst, len); }
static int zio_eof_pending (zio_t *zio) { /* Already closed? Then EOF can't be pending */ if (zio_closed (zio)) return (0); /* * zio object has EOF pending if EOF flag is set and either the * io is unbuffered or the buffer for IO is empty. */ return (zio_eof (zio) && (!cbuf_used (zio->buf))); }
static int zio_write_internal (zio_t *zio, void *data, size_t len) { int rc; rc = zio_write_data (zio, data, len); zio_debug (zio, "zio_write: %d bytes, eof=%d\n", len, zio_eof (zio)); if (zio_write_pending (zio)) zio_writer_schedule (zio); return (rc); }
static int zio_data_to_flush (zio_t *zio) { int size; if ((size = zio_buffer_used (zio)) <= 0) return (0); /* * For unbuffered IO we will flush all data. For line buffered * IO we will read all available lines. In both cases, return * the amount of data currently waiting in the buffer. */ if (!zio_buffered (zio) || zio_line_buffered (zio)) return (size); /* For normal buffered IO, we will only flush data when availble * bytes are greater than the current buffer size, unless there * is a pending EOF */ if (zio_eof (zio) || (size <= zio->buffersize)) return (size); return (0); }