mbox-save.c revision ed9782b21a020daad7fed0b765e9a39a691e7e05
c636315472e4f87313af7be30b7fbcad4b8ca8a4Stephen Gallagher/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
4b6a0d0b3d42e5fdb457f47d9adfa5e66b160256Stephen Gallagher uint32_t seq, next_uid, uid_validity, first_saved_uid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int write_error(struct mbox_save_context *ctx)
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher mbox_set_syscall_error(ctx->mbox, "write()");
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholastastatic int mbox_seek_to_end(struct mbox_save_context *ctx, uoff_t *offset)
f1828234a850dd28465425248a83a993f262918fPavel Březina return mbox_set_syscall_error(ctx->mbox, "fstat()");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (lseek(fd, st.st_size-1, SEEK_SET) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return mbox_set_syscall_error(ctx->mbox, "lseek()");
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina return mbox_set_syscall_error(ctx->mbox, "read()");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int mbox_append_lf(struct mbox_save_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (o_stream_send(ctx->output, "\n", 1) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int write_from_line(struct mbox_save_context *ctx, time_t received_date,
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose const char *line;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher from_envelope = t_strconcat(storage->ns->user->username,
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher /* save in local timezone, no matter what it was given with */
667db40da4db362d7ca0a1f7f1c4ba40fb71795aJakub Hrozek line = mbox_from_create(from_envelope, received_date);
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher if ((ret = o_stream_send_str(ctx->output, line)) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int mbox_write_content_length(struct mbox_save_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we can't seek, don't set Content-Length */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* write Content-Length headers */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str = t_strdup_printf("\nContent-Length: %s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* flush manually here so that we don't confuse seek() errors with
c7919a4fe41133cc466aa3d9431bfceee5784e7bJan Cholasta buffer flushing errors */
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek if (o_stream_seek(ctx->output, ctx->extra_hdr_offset +
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return mbox_set_syscall_error(ctx->mbox, "o_stream_seek()");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (o_stream_send(ctx->output, str, len) < 0 ||
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek if (o_stream_seek(ctx->output, end_offset) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return mbox_set_syscall_error(ctx->mbox, "o_stream_seek()");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void mbox_save_init_sync(struct mbox_transaction_context *t)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mbox_mailbox *mbox = (struct mbox_mailbox *)t->ictx.ibox;
3b1df539835367cb81cd5ff0f9959947d5642e55Stephen Gallagher struct mbox_save_context *ctx = t->save_ctx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* open a new view to get the header. this is required if we just
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher synced the mailbox so we can get updated next_uid. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (void)mail_index_refresh(mbox->ibox.index);
667db40da4db362d7ca0a1f7f1c4ba40fb71795aJakub Hrozekstatic void status_flags_append(string_t *str, enum mail_flags flags,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = 0; flags_list[i].chr != 0; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void mbox_save_append_flag_headers(string_t *str, enum mail_flags flags)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* write the Status: header always. It always gets added soon anyway. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher status_flags_append(str, flags, mbox_status_flags);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher status_flags_append(str, flags, mbox_xstatus_flags);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghermbox_save_append_keyword_headers(struct mbox_save_context *ctx,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned char space[MBOX_HEADER_PADDING+1 +
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher sizeof("Content-Length: \n")-1 + MAX_INT_STRLEN];
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const ARRAY_TYPE(keywords) *keyword_names_list;
bfbf5cb0f00c60c0f000f56c282377b13b9a89abSumit Bose const char *const *keyword_names;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher unsigned int i, count, keyword_names_count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher keyword_names_list = mail_index_get_keywords(ctx->mbox->ibox.index);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher keyword_names = array_get(keyword_names_list, &keyword_names_count);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher count = keywords == NULL ? 0 : keywords->count;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce for (i = 0; i < count; i++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(keywords->idx[i] < keyword_names_count);
0ef783e186ef1c9f60e61a4e8e54c44cb366fdfePavel Březina str_append(ctx->headers, keyword_names[keywords->idx[i]]);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_append_n(ctx->headers, space, sizeof(space));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->space_end_idx = str_len(ctx->headers);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghermbox_save_init_file(struct mbox_save_context *ctx,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mbox_transaction_context *t, bool want_mail)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail_storage *storage = &mbox->storage->storage;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_storage_set_error(storage, MAIL_ERROR_PERM,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "Read-only mbox");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if ((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS) != 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* first appended mail in this transaction */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* FIXME: we shouldn't fail here. it's just
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher a locking issue that should be possible to
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "Can't copy mails inside same mailbox");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mbox_lock(mbox, F_WRLCK, &t->mbox_lock_id) <= 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* update mbox_sync_dirty state */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = mbox_sync_has_changed_full(mbox, TRUE, &empty);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we're not required to assign UIDs for the appended
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mails immediately. do it only if it doesn't require
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!ctx->synced && (want_mail || empty)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we'll need to assign UID for the mail immediately. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* the syncing above could have changed the append offset */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mbox_seek_to_end(ctx, &ctx->append_offset) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->output = o_stream_create_fd_file(mbox->mbox_fd,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void save_header_callback(struct message_header_line *hdr,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool *matched, struct mbox_save_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we can't allow From_-lines in headers. there's no
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher legitimate reason for allowing them in any case,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher so just drop them. */
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher mbox_md5_continue(ctx->mbox_md5_ctx, hdr);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void mbox_save_x_delivery_id(struct mbox_save_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buf = buffer_create_dynamic(pool_datastack_create(), 256);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher buffer_append(buf, &ioloop_time, sizeof(ioloop_time));
d844aab866ae237844360cea70e2dccdc90c783dStephen Gallagher buffer_append(buf, &ioloop_timeval.tv_usec,
ef39c0adcb61b16f9edc7beb4cdc8f3b0d5a8f15Stephen Gallagher randbuf = buffer_append_space_unsafe(buf, MBOX_DELIVERY_ID_RAND_BYTES);
8c3a4809b3420657289b42f028a1c9019b112991Stephen Gallagher random_fill_weak(randbuf, MBOX_DELIVERY_ID_RAND_BYTES);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher md5_get_digest(buf->data, buf->used, md5_result);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher base64_encode(md5_result, sizeof(md5_result), str);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->x_delivery_id_header = i_strdup(str_c(str));
4c11f752e1f10cf5740d53a3206bb795e9e34fe8Jan Zelenystatic struct istream *
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghermbox_save_get_input_stream(struct mbox_save_context *ctx, struct istream *input)
1a7d1977037864e52858058777af8ff8401547ddJan Cholasta struct istream *filter, *ret, *cache_input, *streams[3];
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* filter out unwanted headers and keep track of headers' MD5 sum */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher filter = i_stream_create_header_filter(input, HEADER_FILTER_EXCLUDE |
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) != 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we're using MD5 sums to generate POP3 UIDLs.
65e8f538ad35ba7d86cd9e60a3d86aec34537027Stephen Gallagher clients don't like it much if there are duplicates,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher so make sure that there can't be any by appending
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher our own X-Delivery-ID header. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher streams[0] = i_stream_create_from_data(hdr, strlen(hdr));
1a853121ca2ba8ede6df429ee76942131ffb0f65Jan Zeleny /* convert linefeeds to wanted format */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_stream_create_crlf(filter) : i_stream_create_lf(filter);
65e8f538ad35ba7d86cd9e60a3d86aec34537027Stephen Gallagher /* caching creates a tee stream */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher cache_input = index_mail_cache_parse_init(ctx->mail, ret);
b6dfbf81c61d4431aaa81687ec53e892f8b71edbSumit Bosembox_save_alloc(struct mailbox_transaction_context *_t)
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek struct mbox_mailbox *mbox = (struct mbox_mailbox *)t->ictx.ibox;
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek i_assert((t->ictx.flags & MAILBOX_TRANSACTION_FLAG_EXTERNAL) != 0);
374bf54785365273b20690bd3792c25a44738041Pavel Březina ctx = t->save_ctx = i_new(struct mbox_save_context, 1);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher ctx->headers = str_new(default_pool, 512);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagherint mbox_save_begin(struct mail_save_context *_ctx, struct istream *input)
87c07559af5cfcd2752295ef7c425bd3205f426fStephen Gallagher struct mbox_save_context *ctx = (struct mbox_save_context *)_ctx;
87c07559af5cfcd2752295ef7c425bd3205f426fStephen Gallagher (struct mbox_transaction_context *)_ctx->transaction;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher /* FIXME: we could write timezone_offset to From-line.. */
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny if (mbox_save_init_file(ctx, t, _ctx->dest_mail != NULL) < 0) {
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher save_flags = (_ctx->flags & ~MAIL_RECENT) | MAIL_RECENT;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher /* writing the first mail. Insert X-IMAPbase as well. */
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher str_printfa(ctx->headers, "X-IMAPbase: %u %010u\n",
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher str_printfa(ctx->headers, "X-UID: %u\n", ctx->next_uid);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher mail_index_append(ctx->trans, ctx->next_uid, &ctx->seq);
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_REPLACE,
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher mail_index_update_ext(ctx->trans, ctx->seq,
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek /* parse and cache the mail headers as we read it */
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher mbox_save_append_flag_headers(ctx->headers, save_flags);
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher mbox_save_append_keyword_headers(ctx, _ctx->keywords);
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher i_assert(ctx->mbox->mbox_lock_type == F_WRLCK);
b6dfbf81c61d4431aaa81687ec53e892f8b71edbSumit Bose if (write_from_line(ctx, _ctx->received_date, _ctx->from_envelope) < 0)
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose ctx->input = mbox_save_get_input_stream(ctx, input);
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bosestatic int mbox_save_body_input(struct mbox_save_context *ctx)
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher const unsigned char *data;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher data = i_stream_get_data(ctx->input, &size);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (o_stream_send(ctx->output, data, size) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int mbox_save_body(struct mbox_save_context *ctx)
ef39c0adcb61b16f9edc7beb4cdc8f3b0d5a8f15Stephen Gallagher while ((ret = i_stream_read(ctx->input)) != -1) {
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce /* i_stream_read() may have returned 0 at EOF
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher because of this parser */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_cache_parse_continue(ctx->mail);
d844aab866ae237844360cea70e2dccdc90c783dStephen Gallagher /* if mail doesn't end with LF, we'll do that.
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher otherwise some mbox parsers don't like the result.
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher this makes it impossible to save a mail that doesn't
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher end with LF though. */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina if (o_stream_send_str(ctx->output, linefeed) < 0)
41ef946f3f74a46b9e26118116e4811e259b30efPavel Březinaint mbox_save_continue(struct mail_save_context *_ctx)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina struct mbox_save_context *ctx = (struct mbox_save_context *)_ctx;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina const unsigned char *data;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* writing body */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek while ((ret = i_stream_read(ctx->input)) > 0) {
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta for (i = 0; i < size; i++) {
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta /* end of headers. we don't need to worry about
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta CRs because they're dropped */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* found end of headers. write the rest of them
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (not including the finishing empty line) */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (o_stream_send(ctx->output, data, i) < 0)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (o_stream_send(ctx->output, data, size) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher hdr.middle = (const unsigned char *)hdr.name +
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher hdr.value_len = strlen((const char *)hdr.value);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mbox_md5_continue(ctx->mbox_md5_ctx, &hdr);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mbox_md5_finish(ctx->mbox_md5_ctx, hdr_md5_sum);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher mail_index_update_ext(ctx->trans, ctx->seq,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* append our own headers and ending empty line */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->extra_hdr_offset = ctx->output->offset;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (o_stream_send(ctx->output, str_data(ctx->headers),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* write body */
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return ctx->input->eof ? 0 : mbox_save_body(ctx);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint mbox_save_finish(struct mail_save_context *_ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mbox_save_context *ctx = (struct mbox_save_context *)_ctx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* make sure everything is written */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher index_mail_cache_parse_deinit(ctx->mail, ctx->ctx.received_date,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ctx->failed && ctx->mail_offset != (uoff_t)-1) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* saving this mail failed - truncate back to beginning of it */
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny if (ftruncate(ctx->mbox->mbox_fd, (off_t)ctx->mail_offset) < 0)
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny mbox_set_syscall_error(ctx->mbox, "ftruncate()");
f1828234a850dd28465425248a83a993f262918fPavel Březinavoid mbox_save_cancel(struct mail_save_context *_ctx)
f1828234a850dd28465425248a83a993f262918fPavel Březina struct mbox_save_context *ctx = (struct mbox_save_context *)_ctx;
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozekstatic void mbox_transaction_save_deinit(struct mbox_save_context *ctx)
558998ce664055a75595371118f818084d8f2b23Jan Cholastaint mbox_transaction_save_commit(struct mbox_save_context *ctx)
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta (struct mbox_transaction_context *)ctx->ctx.transaction;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher offsetof(struct mail_index_header, next_uid),
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher &ctx->next_uid, sizeof(ctx->next_uid), FALSE);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (ret == 0 && ctx->orig_atime != st.st_atime) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* try to set atime back to its original value */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!ctx->synced && mbox->mbox_fd != -1 &&
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher !mbox->mbox_writeonly && !mbox->ibox.fsync_disable) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mbox_set_syscall_error(mbox, "fdatasync()");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid mbox_transaction_save_rollback(struct mbox_save_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ctx->append_offset != (uoff_t)-1 && mbox->mbox_fd != -1) {
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher i_assert(mbox->mbox_lock_type == F_WRLCK);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* failed, truncate file back to original size.
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher output stream needs to be flushed before truncating
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher so unref() won't write anything. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ftruncate(mbox->mbox_fd, (off_t)ctx->append_offset) < 0)