int json_parser_deinit(struct json_parser **_parser, const char **error_r) { struct json_parser *parser = *_parser; *_parser = NULL; if (parser->error != NULL) { /* actual parser error */ *error_r = parser->error; } else if (parser->input->stream_errno != 0) { *error_r = t_strdup_printf("read(%s) failed: %m", i_stream_get_name(parser->input)); } else if (parser->data == parser->end && !i_stream_have_bytes_left(parser->input) && parser->state != JSON_STATE_DONE) { *error_r = "Missing '}'"; } else { *error_r = NULL; } i_stream_unref(&parser->input); array_free(&parser->nesting); str_free(&parser->value); i_free(parser); return *error_r != NULL ? -1 : 0; }
static int server_connection_send_cmd_input_more(struct server_connection *conn) { off_t ret; /* ostream-dot writes only up to max buffer size, so keep it non-zero */ o_stream_set_max_buffer_size(conn->cmd_output, IO_BLOCK_SIZE); ret = o_stream_send_istream(conn->cmd_output, conn->cmd_input); o_stream_set_max_buffer_size(conn->cmd_output, (size_t)-1); if (ret >= 0 && i_stream_have_bytes_left(conn->cmd_input)) { o_stream_set_flush_pending(conn->cmd_output, TRUE); return 0; } if (conn->cmd_input->stream_errno != 0) { i_error("read(%s) failed: %s", i_stream_get_name(conn->cmd_input), i_stream_get_error(conn->cmd_input)); } else if (conn->cmd_output->stream_errno != 0 || o_stream_flush(conn->cmd_output) < 0) { i_error("write(%s) failed: %s", o_stream_get_name(conn->cmd_output), o_stream_get_error(conn->cmd_output)); } i_stream_destroy(&conn->cmd_input); o_stream_destroy(&conn->cmd_output); return ret < 0 ? -1 : 1; }
static int program_client_program_output(struct program_client *pclient) { struct istream *input = pclient->input; struct ostream *output = pclient->program_output; const unsigned char *data; size_t size; int ret = 0; if ((ret = o_stream_flush(output)) <= 0) { if (ret < 0) program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO); return ret; } if ( input != NULL && output != NULL ) { do { while ( (data=i_stream_get_data(input, &size)) != NULL ) { ssize_t sent; if ( (sent=o_stream_send(output, data, size)) < 0 ) { program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO); return -1; } if ( sent == 0 ) return 0; i_stream_skip(input, sent); } } while ( (ret=i_stream_read(input)) > 0 ); if ( ret == 0 ) return 1; if ( ret < 0 ) { if ( !input->eof ) { program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO); return -1; } else if ( !i_stream_have_bytes_left(input) ) { i_stream_unref(&pclient->input); input = NULL; if ( (ret = o_stream_flush(output)) <= 0 ) { if ( ret < 0 ) program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO); return ret; } } } } if ( input == NULL ) { if ( !program_client_input_pending(pclient) ) { program_client_disconnect(pclient, FALSE); } else if (program_client_close_output(pclient) < 0) { program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO); } } return 1; }
bool i_stream_is_eof(struct istream *stream) { const struct istream_private *_stream = stream->real_stream; if (_stream->skip == _stream->pos) (void)i_stream_read(stream); return !i_stream_have_bytes_left(stream); }
static int o_stream_mail_filter_flush(struct ostream_private *stream) { struct mail_filter_ostream *mstream = (struct mail_filter_ostream *)stream; const unsigned char *data; size_t size; ssize_t ret; if (mstream->ext_out == NULL) { /* connect failed */ return -1; } if (mstream->flushed) return 0; if (shutdown(mstream->fd, SHUT_WR) < 0) i_error("ext-filter: shutdown() failed: %m"); while ((ret = i_stream_read_data(mstream->ext_in, &data, &size, 0)) > 0) { ret = o_stream_send(stream->parent, data, size); if (ret != (ssize_t)size) { i_assert(ret < 0); o_stream_copy_error_from_parent(stream); return -1; } i_stream_skip(mstream->ext_in, size); } i_assert(ret == -1); if (!i_stream_have_bytes_left(mstream->ext_in) && mstream->ext_in->v_offset == 0) { /* EOF without any input -> assume the script is repoting failure. pretty ugly way, but currently there's no error reporting channel. */ stream->ostream.stream_errno = EIO; return -1; } if (mstream->ext_in->stream_errno != 0) { stream->ostream.stream_errno = mstream->ext_in->stream_errno; return -1; } ret = o_stream_flush(stream->parent); if (ret < 0) o_stream_copy_error_from_parent(stream); else mstream->flushed = TRUE; return ret; }
static int fetch_stream_continue(struct imap_fetch_context *ctx) { struct imap_fetch_state *state = &ctx->state; const char *disconnect_reason; off_t ret; o_stream_set_max_buffer_size(ctx->client->output, 0); ret = o_stream_send_istream(ctx->client->output, state->cur_input); o_stream_set_max_buffer_size(ctx->client->output, (size_t)-1); if (ret > 0) { state->cur_offset += ret; if (ctx->state.cur_stats_sizep != NULL) *ctx->state.cur_stats_sizep += ret; } if (state->cur_offset != state->cur_size) { /* unfinished */ if (state->cur_input->stream_errno != 0) { fetch_read_error(ctx, &disconnect_reason); client_disconnect(ctx->client, disconnect_reason); return -1; } if (!i_stream_have_bytes_left(state->cur_input)) { /* Input stream gave less data than expected */ i_error("read(%s): FETCH %s for mailbox %s UID %u " "got too little data: " "%"PRIuUOFF_T" vs %"PRIuUOFF_T, i_stream_get_name(state->cur_input), state->cur_human_name, mailbox_get_vname(state->cur_mail->box), state->cur_mail->uid, state->cur_offset, state->cur_size); mail_set_cache_corrupted(state->cur_mail, state->cur_size_field); client_disconnect(ctx->client, "FETCH failed"); return -1; } if (ret < 0) { /* client probably disconnected */ return -1; } o_stream_set_flush_pending(ctx->client->output, TRUE); return 0; } return 1; }
static int fetch_stream_send_direct(struct imap_fetch_context *ctx) { off_t ret; o_stream_set_max_buffer_size(ctx->client->output, 0); ret = o_stream_send_istream(ctx->client->output, ctx->cur_input); o_stream_set_max_buffer_size(ctx->client->output, (size_t)-1); if (ret < 0) return -1; ctx->cur_offset += ret; if (ctx->cur_append_eoh && ctx->cur_offset + 2 == ctx->cur_size) { /* Netscape missing EOH workaround. */ if (o_stream_send(ctx->client->output, "\r\n", 2) < 0) return -1; ctx->cur_offset += 2; ctx->cur_append_eoh = FALSE; } if (ctx->cur_offset != ctx->cur_size) { /* unfinished */ if (!i_stream_have_bytes_left(ctx->cur_input)) { /* Input stream gave less data than expected */ i_error("FETCH %s for mailbox %s UID %u " "got too little data (copying): " "%"PRIuUOFF_T" vs %"PRIuUOFF_T, ctx->cur_name, mailbox_get_vname(ctx->mail->box), ctx->mail->uid, ctx->cur_offset, ctx->cur_size); mail_set_cache_corrupted(ctx->mail, ctx->cur_size_field); client_disconnect(ctx->client, "FETCH failed"); return -1; } o_stream_set_flush_pending(ctx->client->output, TRUE); return 0; } return 1; }
static bool cmd_getscript_continue(struct client_command_context *cmd) { struct client *client = cmd->client; struct cmd_getscript_context *ctx = cmd->context; off_t ret; ret = o_stream_send_istream(client->output, ctx->script_stream); if ( ret < 0 ) { sieve_storage_set_critical(ctx->storage, "o_stream_send_istream(%s) failed: %m", sieve_script_filename(ctx->script)); ctx->failed = TRUE; return cmd_getscript_finish(ctx); } ctx->script_offset += ret; if ( ctx->script_offset != ctx->script_size && !ctx->failed ) { /* unfinished */ if ( !i_stream_have_bytes_left(ctx->script_stream) ) { /* Input stream gave less data than expected */ sieve_storage_set_critical(ctx->storage, "GETSCRIPT for SCRIPT %s got too little data: " "%"PRIuUOFF_T" vs %"PRIuUOFF_T, sieve_script_name(ctx->script), ctx->script_offset, ctx->script_size); client_disconnect(ctx->client, "GETSCRIPT failed"); ctx->failed = TRUE; return cmd_getscript_finish(ctx); } return FALSE; } return cmd_getscript_finish(ctx); }
static ssize_t i_stream_mail_filter_read(struct istream_private *stream) { struct mail_filter_istream *mstream = (struct mail_filter_istream *)stream; ssize_t ret; if (mstream->ext_in == NULL) { stream->istream.stream_errno = EIO; return -1; } while ((ret = i_stream_mail_filter_read_once(mstream)) == 0) { if (!stream->istream.blocking) break; } if (ret == -1 && !i_stream_have_bytes_left(&stream->istream) && stream->istream.v_offset == 0) { /* EOF without any input -> assume the script is repoting failure. pretty ugly way, but currently there's no error reporting channel. */ stream->istream.stream_errno = EIO; } return ret; }
bool http_request_parser_pending_payload(struct http_request_parser *parser) { if (parser->parser.payload == NULL) return FALSE; return i_stream_have_bytes_left(parser->parser.payload); }
static int script_client_script_output(struct script_client *sclient) { struct istream *input = sclient->input; struct ostream *output = sclient->script_output; const unsigned char *data; size_t size; int ret = 0; if ((ret = o_stream_flush(output)) <= 0) { if (ret < 0) script_client_fail(sclient, SCRIPT_CLIENT_ERROR_IO); return ret; } if ( input != NULL && output != NULL ) { do { while ( (data=i_stream_get_data(input, &size)) != NULL ) { ssize_t sent; if ( (sent=o_stream_send(output, data, size)) < 0 ) { script_client_fail(sclient, SCRIPT_CLIENT_ERROR_IO); return -1; } if ( sent == 0 ) return 0; i_stream_skip(input, sent); } } while ( (ret=i_stream_read(input)) > 0 ); if ( ret == 0 ) { // FIXME: not supposed to happen; returning 0 will poll the input stream return 0; } if ( ret < 0 ) { if ( !input->eof ) { script_client_fail(sclient, SCRIPT_CLIENT_ERROR_IO); return -1; } else if ( !i_stream_have_bytes_left(input) ) { i_stream_unref(&sclient->input); input = NULL; if ( (ret = o_stream_flush(output)) <= 0 ) { if ( ret < 0 ) script_client_fail(sclient, SCRIPT_CLIENT_ERROR_IO); return ret; } } } } if ( input == NULL ) { o_stream_unref(&sclient->script_output); if ( sclient->script_input == NULL ) { script_client_disconnect(sclient, FALSE); } else { sclient->close_output(sclient); } return 0; } return 1; }
static int cmd_append_catenate_mpurl(struct client_command_context *cmd, const char *caturl, struct imap_msgpart_url *mpurl) { struct cmd_append_context *ctx = cmd->context; struct imap_msgpart_open_result mpresult; uoff_t newsize; const char *error; int ret; /* catenate URL */ ret = imap_msgpart_url_read_part(mpurl, &mpresult, &error); if (ret < 0) { client_send_box_error(cmd, ctx->box); return -1; } if (ret == 0) { /* invalid url, abort */ client_send_tagline(cmd, t_strdup_printf("NO [BADURL %s] %s.", caturl, error)); return -1; } if (mpresult.size == 0) { /* empty input */ return 0; } newsize = ctx->cat_msg_size + mpresult.size; if (newsize < ctx->cat_msg_size) { client_send_tagline(cmd, "NO [TOOBIG] Composed message grows too big."); return -1; } ctx->cat_msg_size = newsize; /* add this input stream to chain */ i_stream_chain_append(ctx->catchain, mpresult.input); /* save by reading the chain stream */ while (!i_stream_is_eof(mpresult.input)) { ret = i_stream_read(mpresult.input); i_assert(ret != 0); /* we can handle only blocking input here */ if (mailbox_save_continue(ctx->save_ctx) < 0 || ret == -1) break; } if (mpresult.input->stream_errno != 0) { errno = mpresult.input->stream_errno; mail_storage_set_critical(ctx->box->storage, "read(%s) failed: %s (for CATENATE URL %s)", i_stream_get_name(mpresult.input), i_stream_get_error(mpresult.input), caturl); client_send_box_error(cmd, ctx->box); ret = -1; } else if (!mpresult.input->eof) { /* save failed */ client_send_box_error(cmd, ctx->box); ret = -1; } else { /* all the input must be consumed, so istream-chain's read() unreferences the stream and we can free its parent mail */ i_assert(!i_stream_have_bytes_left(mpresult.input)); ret = 0; } return ret; }
bool i_stream_is_eof(struct istream *stream) { if (i_stream_get_data_size(stream) == 0) (void)i_stream_read(stream); return !i_stream_have_bytes_left(stream); }