bool cmd_idle(struct client_command_context *cmd) { struct client *client = cmd->client; struct cmd_idle_context *ctx; ctx = p_new(cmd->pool, struct cmd_idle_context, 1); ctx->cmd = cmd; ctx->client = client; idle_add_keepalive_timeout(ctx); if (client->mailbox != NULL) mailbox_notify_changes(client->mailbox, idle_callback, ctx); client_send_line(client, "+ idling"); io_remove(&client->io); client->io = io_add(i_stream_get_fd(client->input), IO_READ, idle_client_input, ctx); cmd->func = cmd_idle_continue; cmd->context = ctx; /* check immediately if there are changes. if they came before we added mailbox-notifier, we wouldn't see them otherwise. */ if (client->mailbox != NULL) idle_sync_now(client->mailbox, ctx); return idle_client_handle_input(ctx, FALSE); }
static int o_stream_temp_dup_istream(struct temp_ostream *outstream, struct istream *instream) { uoff_t in_size; off_t ret; if (!instream->readable_fd || i_stream_get_fd(instream) == -1) return 0; if (i_stream_get_size(instream, TRUE, &in_size) <= 0) { if (outstream->dupstream != NULL) return o_stream_temp_dup_cancel(outstream); return 0; } if (outstream->dupstream == NULL) { outstream->dupstream = instream; outstream->dupstream_start_offset = instream->v_offset; i_stream_ref(outstream->dupstream); } else { if (outstream->dupstream != instream || outstream->dupstream_offset != instream->v_offset || outstream->dupstream_offset > in_size) return o_stream_temp_dup_cancel(outstream); } ret = in_size - instream->v_offset; i_stream_seek(instream, in_size); outstream->dupstream_offset = instream->v_offset; return ret; }
struct istream * http_server_request_get_payload_input(struct http_server_request *req, bool blocking) { struct http_server_istream *hsristream; struct istream *payload = req->req.payload; i_assert(req->payload_input == NULL); hsristream = i_new(struct http_server_istream, 1); hsristream->req = req; hsristream->istream.max_buffer_size = payload->real_stream->max_buffer_size; hsristream->istream.stream_size_passthrough = TRUE; hsristream->istream.read = http_server_istream_read; hsristream->istream.switch_ioloop = http_server_istream_switch_ioloop; hsristream->istream.iostream.destroy = http_server_istream_destroy; hsristream->istream.istream.readable_fd = FALSE; hsristream->istream.istream.blocking = blocking; hsristream->istream.istream.seekable = FALSE; req->payload_input = i_stream_create (&hsristream->istream, payload, i_stream_get_fd(payload)); i_stream_unref(&req->req.payload); return req->payload_input; }
static bool cmd_putscript_start (struct client_command_context *cmd, const char *scriptname) { struct cmd_putscript_context *ctx; struct client *client = cmd->client; ctx = p_new(cmd->pool, struct cmd_putscript_context, 1); ctx->cmd = cmd; ctx->client = client; ctx->storage = client->storage; ctx->scriptname = scriptname; io_remove(&client->io); client->io = io_add(i_stream_get_fd(client->input), IO_READ, client_input_putscript, client); /* putscript is special because we're only waiting on client input, not client output, so disable the standard output handler until we're finished */ o_stream_unset_flush_callback(client->output); ctx->save_parser = managesieve_parser_create (client->input, client->set->managesieve_max_line_length); cmd->func = cmd_putscript_continue_parsing; cmd->context = ctx; return cmd_putscript_continue_parsing(cmd); }
struct istream *tee_i_stream_create_child(struct tee_istream *tee) { struct tee_child_istream *tstream; struct istream *ret, *input = tee->input; tstream = i_new(struct tee_child_istream, 1); tstream->tee = tee; tstream->istream.max_buffer_size = input->real_stream->max_buffer_size; tstream->istream.iostream.close = i_stream_tee_close; tstream->istream.iostream.destroy = i_stream_tee_destroy; tstream->istream.iostream.set_max_buffer_size = i_stream_tee_set_max_buffer_size; tstream->istream.read = i_stream_tee_read; tstream->istream.stat = i_stream_tee_stat; tstream->istream.sync = i_stream_tee_sync; tstream->next = tee->children; tee->children = tstream; ret = i_stream_create(&tstream->istream, input, i_stream_get_fd(input)); i_stream_set_name(&tstream->istream.istream, i_stream_get_name(input)); /* we keep the reference in tee stream, no need for extra references */ i_stream_unref(&input); return ret; }
struct istream * i_stream_create_rawlog(struct istream *input, const char *rawlog_path, int rawlog_fd, enum iostream_rawlog_flags flags) { struct rawlog_istream *rstream; i_assert(rawlog_path != NULL); i_assert(rawlog_fd != -1); rstream = i_new(struct rawlog_istream, 1); rstream->istream.max_buffer_size = input->real_stream->max_buffer_size; rstream->istream.stream_size_passthrough = TRUE; rstream->riostream.rawlog_path = i_strdup(rawlog_path); rstream->riostream.rawlog_fd = rawlog_fd; iostream_rawlog_init(&rstream->riostream, flags, TRUE); rstream->istream.read = i_stream_rawlog_read; rstream->istream.iostream.close = i_stream_rawlog_close; rstream->istream.iostream.destroy = i_stream_rawlog_destroy; rstream->istream.istream.readable_fd = input->readable_fd; rstream->istream.istream.blocking = input->blocking; rstream->istream.istream.seekable = input->seekable; return i_stream_create(&rstream->istream, input, i_stream_get_fd(input)); }
struct istream *i_stream_create_lzma(struct istream *input, bool log_errors) { struct lzma_istream *zstream; zstream = i_new(struct lzma_istream, 1); zstream->eof_offset = (uoff_t)-1; zstream->stream_size = (uoff_t)-1; zstream->log_errors = log_errors; i_stream_lzma_init(zstream); zstream->istream.iostream.close = i_stream_lzma_close; zstream->istream.max_buffer_size = input->real_stream->max_buffer_size; zstream->istream.read = i_stream_lzma_read; zstream->istream.seek = i_stream_lzma_seek; zstream->istream.stat = i_stream_lzma_stat; zstream->istream.sync = i_stream_lzma_sync; zstream->istream.istream.readable_fd = FALSE; zstream->istream.istream.blocking = input->blocking; zstream->istream.istream.seekable = input->seekable; return i_stream_create(&zstream->istream, input, i_stream_get_fd(input)); }
void connection_init_from_streams(struct connection_list *list, struct connection *conn, const char *name, struct istream *input, struct ostream *output) { i_assert(name != NULL); conn->list = list; conn->name = i_strdup(name); conn->fd_in = i_stream_get_fd(input); conn->fd_out = o_stream_get_fd(output); i_assert(conn->fd_in >= 0); i_assert(conn->fd_out >= 0); i_assert(conn->io == NULL); i_assert(conn->input == NULL); i_assert(conn->output == NULL); i_assert(conn->to == NULL); conn->input = input; i_stream_ref(conn->input); i_stream_set_name(conn->input, conn->name); conn->output = output; o_stream_ref(conn->output); o_stream_set_no_error_handling(conn->output, TRUE); o_stream_set_name(conn->output, conn->name); conn->io = io_add_istream(conn->input, *list->v.input, conn); DLLIST_PREPEND(&list->connections, conn); list->connections_count++; if (list->v.client_connected != NULL) list->v.client_connected(conn, TRUE); }
void login_proxy_detach(struct login_proxy *proxy) { struct client *client = proxy->client; const unsigned char *data; size_t size; i_assert(proxy->client_fd == -1); i_assert(proxy->server_input != NULL); i_assert(proxy->server_output != NULL); if (proxy->to != NULL) timeout_remove(&proxy->to); proxy->client_fd = i_stream_get_fd(client->input); proxy->client_input = client->input; proxy->client_output = client->output; i_stream_set_persistent_buffers(client->input, FALSE); o_stream_set_max_buffer_size(client->output, (size_t)-1); o_stream_set_flush_callback(client->output, proxy_client_output, proxy); client->input = NULL; client->output = NULL; /* send all pending client input to proxy */ data = i_stream_get_data(proxy->client_input, &size); if (size != 0) o_stream_nsend(proxy->server_output, data, size); /* from now on, just do dummy proxying */ io_remove(&proxy->server_io); proxy->server_io = io_add(proxy->server_fd, IO_READ, server_input, proxy); proxy->client_io = io_add_istream(proxy->client_input, proxy_client_input, proxy); o_stream_set_flush_callback(proxy->server_output, server_output, proxy); i_stream_destroy(&proxy->server_input); if (proxy->notify_refresh_secs != 0) { proxy->to_notify = timeout_add(proxy->notify_refresh_secs * 1000, login_proxy_notify, proxy); } proxy->callback = NULL; if (login_proxy_ipc_server == NULL) { login_proxy_ipc_server = ipc_server_init(LOGIN_PROXY_IPC_PATH, LOGIN_PROXY_IPC_NAME, login_proxy_ipc_cmd); } DLLIST_REMOVE(&login_proxies_pending, proxy); DLLIST_PREPEND(&login_proxies, proxy); client->fd = -1; client->login_proxy = NULL; }
struct istream *iostream_temp_finish(struct ostream **output, size_t max_buffer_size) { struct temp_ostream *tstream = (struct temp_ostream *)(*output)->real_stream; struct istream *input, *input2; uoff_t abs_offset, size; const char *for_path; int fd; if (tstream->name[0] == '\0') for_path = ""; else for_path = t_strdup_printf(" for %s", tstream->name); if (tstream->dupstream != NULL && !tstream->dupstream->closed) { abs_offset = i_stream_get_absolute_offset(tstream->dupstream) - tstream->dupstream->v_offset + tstream->dupstream_start_offset; size = tstream->dupstream_offset - tstream->dupstream_start_offset; fd = dup(i_stream_get_fd(tstream->dupstream)); if (fd == -1) input = i_stream_create_error_str(errno, "dup() failed: %m"); else { input2 = i_stream_create_fd_autoclose(&fd, max_buffer_size); i_stream_seek(input2, abs_offset); input = i_stream_create_limit(input2, size); i_stream_unref(&input2); } i_stream_set_name(input, t_strdup_printf( "(Temp file in %s%s, from %s)", tstream->temp_path_prefix, for_path, i_stream_get_name(tstream->dupstream))); i_stream_unref(&tstream->dupstream); } else if (tstream->dupstream != NULL) { /* return the original failed stream. */ input = tstream->dupstream; } else if (tstream->fd != -1) { int fd = tstream->fd; input = i_stream_create_fd_autoclose(&tstream->fd, max_buffer_size); i_stream_set_name(input, t_strdup_printf( "(Temp file fd %d in %s%s, %"PRIuUOFF_T" bytes)", fd, tstream->temp_path_prefix, for_path, tstream->fd_size)); } else { input = i_stream_create_from_data(tstream->buf->data, tstream->buf->used); i_stream_set_name(input, t_strdup_printf( "(Temp buffer in %s%s, %"PRIuSIZE_T" bytes)", tstream->temp_path_prefix, for_path, tstream->buf->used)); i_stream_add_destroy_callback(input, iostream_temp_buf_destroyed, tstream->buf); tstream->buf = NULL; } o_stream_destroy(output); return input; }
static int maildir_mail_stat(struct mail *mail, struct stat *st_r) { struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box; struct index_mail *imail = (struct index_mail *)mail; const char *path; int fd, ret; if (mail->lookup_abort == MAIL_LOOKUP_ABORT_NOT_IN_CACHE) { mail_set_aborted(mail); return -1; } if (imail->data.access_part != 0 && imail->data.stream == NULL) { /* we're going to open the mail anyway */ struct istream *input; (void)mail_get_stream(mail, NULL, NULL, &input); } if (imail->data.stream != NULL && (fd = i_stream_get_fd(imail->data.stream)) != -1) { mail->transaction->stats.fstat_lookup_count++; if (fstat(fd, st_r) < 0) { mail_storage_set_critical(mail->box->storage, "fstat(%s) failed: %m", i_stream_get_name(imail->data.stream)); return -1; } } else if (!mail->saving) { mail->transaction->stats.stat_lookup_count++; ret = maildir_file_do(mbox, mail->uid, do_stat, st_r); if (ret <= 0) { if (ret == 0) mail_set_expunged(mail); return -1; } } else { mail->transaction->stats.stat_lookup_count++; path = maildir_save_file_get_path(mail->transaction, mail->seq); if (stat(path, st_r) < 0) { mail_storage_set_critical(mail->box->storage, "stat(%s) failed: %m", path); return -1; } } return 0; }
struct istream *i_stream_create_qp_decoder(struct istream *input) { struct qp_decoder_istream *bstream; bstream = i_new(struct qp_decoder_istream, 1); bstream->istream.max_buffer_size = input->real_stream->max_buffer_size; bstream->istream.read = i_stream_qp_decoder_read; bstream->istream.seek = i_stream_qp_decoder_seek; bstream->istream.istream.readable_fd = FALSE; bstream->istream.istream.blocking = input->blocking; bstream->istream.istream.seekable = input->seekable; return i_stream_create(&bstream->istream, input, i_stream_get_fd(input)); }
bool cmd_append(struct client_command_context *cmd) { struct client *client = cmd->client; struct cmd_append_context *ctx; const char *mailbox; if (client->syncing) { /* if transaction is created while its view is synced, appends aren't allowed for it. */ cmd->state = CLIENT_COMMAND_STATE_WAIT_UNAMBIGUITY; return FALSE; } /* <mailbox> */ if (!client_read_string_args(cmd, 1, &mailbox)) return FALSE; /* we keep the input locked all the time */ client->input_lock = cmd; ctx = p_new(cmd->pool, struct cmd_append_context, 1); ctx->cmd = cmd; ctx->client = client; ctx->started = ioloop_time; if (client_open_save_dest_box(cmd, mailbox, &ctx->box) < 0) ctx->failed = TRUE; else { ctx->t = mailbox_transaction_begin(ctx->box, MAILBOX_TRANSACTION_FLAG_EXTERNAL | MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS); } io_remove(&client->io); client->io = io_add(i_stream_get_fd(client->input), IO_READ, client_input_append, cmd); /* append is special because we're only waiting on client input, not client output, so disable the standard output handler until we're finished */ o_stream_unset_flush_callback(client->output); ctx->save_parser = imap_parser_create(client->input, client->output, client->set->imap_max_line_length); cmd->func = cmd_append_parse_new_msg; cmd->context = ctx; return cmd_append_parse_new_msg(cmd); }
struct istream *i_stream_create_nonuls(struct istream *input, char replace_chr) { struct nonuls_istream *nstream; nstream = i_new(struct nonuls_istream, 1); nstream->istream.max_buffer_size = input->real_stream->max_buffer_size; nstream->istream.stream_size_passthrough = TRUE; nstream->istream.read = i_stream_nonuls_read; nstream->istream.istream.readable_fd = FALSE; nstream->istream.istream.blocking = input->blocking; nstream->istream.istream.seekable = FALSE; nstream->replace_chr = replace_chr; return i_stream_create(&nstream->istream, input, i_stream_get_fd(input)); }
struct istream * http_transfer_chunked_istream_create(struct istream *input) { struct http_transfer_chunked_istream *tcstream; tcstream = i_new(struct http_transfer_chunked_istream, 1); tcstream->istream.max_buffer_size = input->real_stream->max_buffer_size; tcstream->istream.iostream.destroy = http_transfer_chunked_istream_destroy; tcstream->istream.read = http_transfer_chunked_istream_read; tcstream->istream.istream.readable_fd = FALSE; tcstream->istream.istream.blocking = input->blocking; tcstream->istream.istream.seekable = FALSE; return i_stream_create(&tcstream->istream, input, i_stream_get_fd(input)); }
struct istream *i_stream_create_dot(struct istream *input, bool send_last_lf) { struct dot_istream *dstream; dstream = i_new(struct dot_istream, 1); dstream->istream.max_buffer_size = input->real_stream->max_buffer_size; dstream->istream.read = i_stream_dot_read; dstream->istream.istream.readable_fd = FALSE; dstream->istream.istream.blocking = input->blocking; dstream->istream.istream.seekable = FALSE; dstream->send_last_lf = send_last_lf; dstream->state = 2; dstream->state_no_cr = TRUE; dstream->state_no_lf = TRUE; return i_stream_create(&dstream->istream, input, i_stream_get_fd(input)); }
struct istream *openssl_i_stream_create_ssl(struct ssl_iostream *ssl_io) { struct ssl_istream *sstream; ssl_io->refcount++; sstream = i_new(struct ssl_istream, 1); sstream->ssl_io = ssl_io; sstream->istream.iostream.close = i_stream_ssl_close; sstream->istream.iostream.destroy = i_stream_ssl_destroy; sstream->istream.max_buffer_size = ssl_io->plain_input->real_stream->max_buffer_size; sstream->istream.read = i_stream_ssl_read; sstream->istream.istream.readable_fd = FALSE; return i_stream_create(&sstream->istream, NULL, i_stream_get_fd(ssl_io->plain_input)); }
struct istream *i_stream_create_mail_stats_counter(struct mail_private *mail, struct istream *input) { struct mail_stats_istream *mstream; mstream = i_new(struct mail_stats_istream, 1); mstream->mail = mail; mstream->istream.max_buffer_size = input->real_stream->max_buffer_size; mstream->istream.parent = input; mstream->istream.read = i_stream_mail_stats_read_mail_stats; mstream->istream.seek = i_stream_mail_stats_seek; mstream->istream.stat = i_stream_mail_stats_stat; mstream->istream.istream.blocking = input->blocking; mstream->istream.istream.seekable = input->seekable; return i_stream_create(&mstream->istream, input, i_stream_get_fd(input)); }
struct istream *i_stream_create_limit(struct istream *input, uoff_t v_size) { struct limit_istream *lstream; lstream = i_new(struct limit_istream, 1); lstream->v_size = v_size; lstream->istream.max_buffer_size = input->real_stream->max_buffer_size; lstream->istream.iostream.destroy = i_stream_limit_destroy; lstream->istream.read = i_stream_limit_read; lstream->istream.stat = i_stream_limit_stat; lstream->istream.get_size = i_stream_limit_get_size; lstream->istream.istream.readable_fd = input->readable_fd; lstream->istream.istream.blocking = input->blocking; lstream->istream.istream.seekable = input->seekable; return i_stream_create(&lstream->istream, input, i_stream_get_fd(input)); }
static struct istream *quoted_string_istream_create (struct managesieve_parser *parser) { struct quoted_string_istream *qsstream; qsstream = i_new(struct quoted_string_istream, 1); qsstream->parser = parser; qsstream->istream.max_buffer_size = parser->input->real_stream->max_buffer_size; qsstream->istream.read = quoted_string_istream_read; qsstream->istream.stat = quoted_string_istream_stat; qsstream->istream.istream.readable_fd = FALSE; qsstream->istream.istream.blocking = parser->input->blocking; qsstream->istream.istream.seekable = FALSE; return i_stream_create(&qsstream->istream, parser->input, i_stream_get_fd(parser->input)); }
struct istream *i_stream_create_mail(struct mail *mail, struct istream *input, bool input_has_body) { struct mail_istream *mstream; mstream = i_new(struct mail_istream, 1); mstream->mail = mail; mstream->input_has_body = input_has_body; mstream->expected_size = (uoff_t)-1; (void)i_stream_mail_try_get_cached_size(mstream); mstream->istream.max_buffer_size = input->real_stream->max_buffer_size; mstream->istream.stream_size_passthrough = TRUE; mstream->istream.read = i_stream_mail_read; mstream->istream.istream.blocking = input->blocking; mstream->istream.istream.seekable = input->seekable; return i_stream_create(&mstream->istream, input, i_stream_get_fd(input)); }
struct istream * i_stream_create_hash(struct istream *input, const struct hash_method *method, void *hash_context) { struct hash_istream *hstream; hstream = i_new(struct hash_istream, 1); hstream->istream.max_buffer_size = input->real_stream->max_buffer_size; hstream->istream.stream_size_passthrough = TRUE; hstream->istream.read = i_stream_hash_read; hstream->istream.seek = i_stream_hash_seek; hstream->istream.istream.blocking = input->blocking; hstream->istream.istream.seekable = input->seekable; hstream->method = method; hstream->hash_context = hash_context; return i_stream_create(&hstream->istream, input, i_stream_get_fd(input)); }
static struct decrypt_istream *i_stream_create_decrypt_common(struct istream *input) { struct decrypt_istream *dstream; dstream = i_new(struct decrypt_istream, 1); dstream->istream.max_buffer_size = input->real_stream->max_buffer_size; dstream->istream.read = i_stream_decrypt_read; dstream->istream.iostream.close = i_stream_decrypt_close; dstream->istream.iostream.destroy = i_stream_decrypt_destroy; dstream->istream.istream.readable_fd = FALSE; dstream->istream.istream.blocking = input->blocking; dstream->istream.istream.seekable = FALSE; dstream->buf = buffer_create_dynamic(default_pool, 512); (void)i_stream_create(&dstream->istream, input, i_stream_get_fd(input)); return dstream; }
struct istream * i_stream_create_metawrap(struct istream *input, metawrap_callback_t *callback, void *context) { struct metawrap_istream *mstream; mstream = i_new(struct metawrap_istream, 1); mstream->istream.max_buffer_size = input->real_stream->max_buffer_size; mstream->istream.read = i_stream_metawrap_read; mstream->istream.seek = i_stream_metawrap_seek; mstream->istream.stat = input->seekable ? i_stream_metawrap_stat : NULL; mstream->istream.istream.readable_fd = input->readable_fd; mstream->istream.istream.blocking = input->blocking; mstream->istream.istream.seekable = input->seekable; mstream->in_metadata = TRUE; mstream->callback = callback; mstream->context = context; return i_stream_create(&mstream->istream, input, i_stream_get_fd(input)); }
struct istream * i_stream_create_base64_encoder(struct istream *input, unsigned int chars_per_line, bool crlf) { struct base64_encoder_istream *bstream; i_assert(chars_per_line % 4 == 0); bstream = i_new(struct base64_encoder_istream, 1); bstream->chars_per_line = chars_per_line; bstream->crlf = crlf; bstream->istream.max_buffer_size = input->real_stream->max_buffer_size; bstream->istream.read = i_stream_base64_encoder_read; bstream->istream.seek = i_stream_base64_encoder_seek; bstream->istream.istream.readable_fd = FALSE; bstream->istream.istream.blocking = input->blocking; bstream->istream.istream.seekable = input->seekable; return i_stream_create(&bstream->istream, input, i_stream_get_fd(input)); }
struct istream * i_stream_create_failure_at(struct istream *input, uoff_t failure_offset, const char *error_string) { struct failure_at_istream *fstream; fstream = i_new(struct failure_at_istream, 1); fstream->istream.max_buffer_size = input->real_stream->max_buffer_size; fstream->istream.stream_size_passthrough = TRUE; fstream->istream.read = i_stream_failure_at_read; fstream->istream.iostream.destroy = i_stream_failure_at_destroy; fstream->istream.istream.readable_fd = input->readable_fd; fstream->istream.istream.blocking = input->blocking; fstream->istream.istream.seekable = input->seekable; fstream->error_string = i_strdup(error_string); fstream->failure_offset = failure_offset; return i_stream_create(&fstream->istream, input, i_stream_get_fd(input)); }
struct istream *i_stream_create_lz4(struct istream *input, bool log_errors) { struct lz4_istream *zstream; zstream = i_new(struct lz4_istream, 1); zstream->stream_size = (uoff_t)-1; zstream->log_errors = log_errors; zstream->istream.iostream.close = i_stream_lz4_close; zstream->istream.max_buffer_size = input->real_stream->max_buffer_size; zstream->istream.read = i_stream_lz4_read; zstream->istream.seek = i_stream_lz4_seek; zstream->istream.stat = i_stream_lz4_stat; zstream->istream.sync = i_stream_lz4_sync; zstream->istream.istream.readable_fd = FALSE; zstream->istream.istream.blocking = input->blocking; zstream->istream.istream.seekable = input->seekable; zstream->chunk_buf = buffer_create_dynamic(default_pool, 1024); return i_stream_create(&zstream->istream, input, i_stream_get_fd(input)); }
struct istream * i_stream_create_attachment_extractor(struct istream *input, struct istream_attachment_settings *set, void *context) { struct attachment_istream *astream; i_assert(set->min_size > 0); i_assert(set->hash_format != NULL); i_assert(set->open_attachment_ostream != NULL); i_assert(set->close_attachment_ostream != NULL); astream = i_new(struct attachment_istream, 1); astream->part.temp_fd = -1; astream->set = *set; astream->context = context; astream->retry_read = TRUE; /* make sure the caller doesn't try to double-free this */ set->hash_format = NULL; astream->istream.max_buffer_size = input->real_stream->max_buffer_size; astream->istream.read = i_stream_attachment_extractor_read; astream->istream.iostream.close = i_stream_attachment_extractor_close; astream->istream.istream.readable_fd = FALSE; astream->istream.istream.blocking = input->blocking; astream->istream.istream.seekable = FALSE; astream->pool = pool_alloconly_create("istream attachment", 1024); astream->parser = message_parser_init(astream->pool, input, 0, MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS | MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES); return i_stream_create(&astream->istream, input, i_stream_get_fd(input)); }
static bool o_stream_temp_dup_istream(struct temp_ostream *outstream, struct istream *instream, enum ostream_send_istream_result *res_r) { uoff_t in_size; if (!instream->readable_fd || i_stream_get_fd(instream) == -1) return FALSE; if (i_stream_get_size(instream, TRUE, &in_size) <= 0) { if (outstream->dupstream != NULL) return o_stream_temp_dup_cancel(outstream, res_r); return FALSE; } i_assert(instream->v_offset <= in_size); if (outstream->dupstream == NULL) { outstream->dupstream = instream; outstream->dupstream_start_offset = instream->v_offset; i_stream_ref(outstream->dupstream); } else { if (outstream->dupstream != instream || outstream->dupstream_offset != instream->v_offset || outstream->dupstream_offset > in_size) return o_stream_temp_dup_cancel(outstream, res_r); } i_stream_seek(instream, in_size); /* we should be at EOF now. o_stream_send_istream() asserts if eof isn't set. */ instream->eof = TRUE; outstream->dupstream_offset = instream->v_offset; outstream->ostream.ostream.offset = outstream->dupstream_offset - outstream->dupstream_start_offset; *res_r = OSTREAM_SEND_ISTREAM_RESULT_FINISHED; return TRUE; }
struct istream * i_stream_create_rawlog_from_stream(struct istream *input, struct ostream *rawlog_output, enum iostream_rawlog_flags flags) { struct rawlog_istream *rstream; rstream = i_new(struct rawlog_istream, 1); rstream->istream.max_buffer_size = input->real_stream->max_buffer_size; rstream->istream.stream_size_passthrough = TRUE; rstream->riostream.rawlog_output = rawlog_output; iostream_rawlog_init(&rstream->riostream, flags, TRUE); rstream->istream.read = i_stream_rawlog_read; rstream->istream.iostream.close = i_stream_rawlog_close; rstream->istream.iostream.destroy = i_stream_rawlog_destroy; rstream->istream.istream.readable_fd = input->readable_fd; rstream->istream.istream.blocking = input->blocking; rstream->istream.istream.seekable = input->seekable; return i_stream_create(&rstream->istream, input, i_stream_get_fd(input)); }