static ssize_t i_stream_metawrap_read(struct istream_private *stream) { struct metawrap_istream *mstream = (struct metawrap_istream *)stream; int ret; i_stream_seek(stream->parent, mstream->start_offset + stream->istream.v_offset); if (mstream->in_metadata) { ret = metadata_header_read(mstream); i_assert(stream->istream.v_offset == 0); mstream->start_offset = stream->parent->v_offset; if (ret <= 0) return ret; /* this stream is kind of silently skipping over the metadata */ stream->abs_start_offset += mstream->start_offset; mstream->in_metadata = FALSE; if (mstream->pending_seek != 0) { i_stream_seek(&stream->istream, mstream->pending_seek); return i_stream_read(&stream->istream); } } /* after metadata header it's all just passthrough */ return i_stream_read_copy_from_parent(&stream->istream); }
static ssize_t i_stream_hash_read(struct istream_private *stream) { struct hash_istream *hstream = (struct hash_istream *)stream; const unsigned char *data; size_t size; uoff_t skip; ssize_t ret; i_stream_seek(stream->parent, stream->parent_start_offset + stream->istream.v_offset); ret = i_stream_read_copy_from_parent(&stream->istream); if (ret > 0 && hstream->hash_context != NULL) { data = i_stream_get_data(&stream->istream, &size); i_assert((size_t)ret <= size); i_assert(stream->istream.v_offset <= hstream->high_offset); skip = hstream->high_offset - stream->istream.v_offset; if (skip < (size_t)size) { hstream->high_offset += (size-skip); hstream->method->loop(hstream->hash_context, data+skip, size-skip); } } else if (ret < 0) { /* we finished hashing it. don't access it anymore, because the memory pointed by the hash may be freed before the istream itself */ hstream->hash_context = NULL; } return ret; }
static void http_server_istream_read_any(struct http_server_istream *hsristream) { struct istream_private *stream = &hsristream->istream; struct http_server *server = hsristream->req->server; ssize_t ret; if ((ret=i_stream_read_copy_from_parent (&stream->istream)) > 0) { hsristream->read_status = ret; io_loop_stop(server->ioloop); } }
static ssize_t i_stream_fs_file_read(struct istream_private *stream) { struct fs_file_istream *fstream = (struct fs_file_istream *)stream; struct istream *input; if (fstream->istream.parent == NULL) { input = fs_read_stream(fstream->file, i_stream_get_max_buffer_size(&stream->istream)); i_stream_init_parent(stream, input); i_stream_unref(&input); } i_stream_seek(stream->parent, stream->parent_start_offset + stream->istream.v_offset); return i_stream_read_copy_from_parent(&stream->istream); }
static ssize_t i_stream_mail_read(struct istream_private *stream) { struct mail_istream *mstream = (struct mail_istream *)stream; size_t size; ssize_t ret; i_stream_seek(stream->parent, stream->parent_start_offset + stream->istream.v_offset); ret = i_stream_read_copy_from_parent(&stream->istream); size = i_stream_get_data_size(&stream->istream); if (ret > 0) { mstream->mail->transaction->stats.files_read_bytes += ret; if (!mstream->files_read_increased) { mstream->files_read_increased = TRUE; mstream->mail->transaction->stats.files_read_count++; } if (mstream->expected_size < stream->istream.v_offset + size) { i_stream_mail_set_size_corrupted(mstream, size); return -1; } } else if (ret == -1 && stream->istream.eof) { if (!mstream->input_has_body) { /* trying to read past the header, but this stream doesn't have the body */ return -1; } if (stream->istream.stream_errno != 0) { if (stream->istream.stream_errno == ENOENT) { /* update mail's expunged-flag if needed */ index_mail_refresh_expunged(mstream->mail); } return -1; } if (i_stream_mail_try_get_cached_size(mstream) && mstream->expected_size > stream->istream.v_offset + size) { i_stream_mail_set_size_corrupted(mstream, size); return -1; } } return ret; }
static ssize_t i_stream_mail_stats_read_mail_stats(struct istream_private *stream) { struct mail_stats_istream *mstream = (struct mail_stats_istream *)stream; ssize_t ret; i_stream_seek(stream->parent, stream->parent_start_offset + stream->istream.v_offset); ret = i_stream_read_copy_from_parent(&stream->istream); if (ret > 0) { mstream->mail->stats_files_read_bytes += ret; if (!mstream->files_read_increased) { mstream->files_read_increased = TRUE; mstream->mail->stats_files_read_count++; } } return ret; }
static ssize_t i_stream_failure_at_read(struct istream_private *stream) { struct failure_at_istream *fstream = (struct failure_at_istream *)stream; uoff_t new_offset; ssize_t ret; i_stream_seek(stream->parent, stream->parent_start_offset + stream->istream.v_offset); ret = i_stream_read_copy_from_parent(&stream->istream); new_offset = stream->istream.v_offset + (stream->pos - stream->skip); if (ret >= 0 && new_offset >= fstream->failure_offset) { if (stream->istream.v_offset >= fstream->failure_offset) { /* we already passed the wanted failure offset, return error immediately. */ stream->pos = stream->skip; stream->istream.stream_errno = errno = EIO; io_stream_set_error(&stream->iostream, "%s", fstream->error_string); ret = -1; } else { /* return data up to the wanted failure offset and on the next read() call return failure */ size_t new_pos = fstream->failure_offset - stream->istream.v_offset + stream->skip; i_assert(new_pos >= stream->skip && stream->pos >= new_pos); ret -= stream->pos - new_pos; stream->pos = new_pos; } } else if (ret < 0 && stream->istream.stream_errno == 0 && fstream->failure_offset == (uoff_t)-1) { /* failure at EOF */ stream->istream.stream_errno = errno = EIO; io_stream_set_error(&stream->iostream, "%s", fstream->error_string); } return ret; }
static ssize_t http_server_istream_read(struct istream_private *stream) { struct http_server_istream *hsristream = (struct http_server_istream *)stream; struct http_server_request *req = hsristream->req; struct http_server *server; struct http_server_connection *conn; bool blocking = stream->istream.blocking; ssize_t ret; if (req == NULL) { /* request already gone (we shouldn't get here) */ stream->istream.stream_errno = EINVAL; return -1; } i_stream_seek(stream->parent, stream->parent_start_offset + stream->istream.v_offset); server = hsristream->req->server; conn = hsristream->req->conn; ret = i_stream_read_copy_from_parent(&stream->istream); if (ret == 0 && blocking) { struct ioloop *prev_ioloop = current_ioloop; struct io *io; http_server_connection_ref(conn); http_server_request_ref(req); i_assert(server->ioloop == NULL); server->ioloop = io_loop_create(); http_server_connection_switch_ioloop(conn); if (blocking && req->req.expect_100_continue && !req->sent_100_continue) http_server_connection_trigger_responses(conn); hsristream->read_status = 0; io = io_add_istream(&stream->istream, http_server_istream_read_any, hsristream); while (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED && hsristream->read_status == 0) { io_loop_run(server->ioloop); } io_remove(&io); io_loop_set_current(prev_ioloop); http_server_connection_switch_ioloop(conn); io_loop_set_current(server->ioloop); io_loop_destroy(&server->ioloop); ret = hsristream->read_status; if (!http_server_request_unref(&req)) hsristream->req = NULL; http_server_connection_unref(&conn); } return ret; }