mbox-sync.c revision a205d315b0978985ba77d871f44e4a98273612e6
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen Modifying mbox can be slow, so we try to do it all at once minimizing the
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen required disk I/O. We may need to:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen - Update message flags in Status, X-Status and X-Keywords headers
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen - Write missing X-UID and X-IMAPbase headers
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen - Write missing or broken Content-Length header if there's space
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen - Expunge specified messages
7a7d2aa11e46195e2d92d6c337d7e78052a5ce67Timo Sirainen Here's how we do it:
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen - Start reading the mails mail headers from the beginning
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen - X-Keywords and X-UID headers may contain extra spaces at the end of them,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen remember how much extra each message has and offset to beginning of the
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen - If message flags are dirty and there's enough space to write them, do it
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen - If we didn't have enough space, remember how much was missing and keep
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen the total amount of them
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen - When we encounter expunged message, check if the amount of empty space in
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen previous messages plus size of expunged message is enough to cover the
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen missing space. If yes,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen - execute the rewrite plan
499fec3443374cc89fb8c83b8027c1614097d7a3Timo Sirainen - forget all the messages before the expunged message. only remember
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen how much data we still have to move to cover the expunged message
f5a7396b31762a1f876517e13ce9065820139f7cTimo Sirainen - If we encounter end of file, grow the file and execute the rewrite plan
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen Rewrite plan goes:
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen - Start from the first message that needs more space
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen - If there's expunged messages before us, we have to write over them.
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen - Move all messages after it backwards to fill it
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen - Each moved message's X-Keywords header should have n bytes extra
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen space, unless there's not enough space to do it.
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen - If there's no expunged messages, we can move data either forward or
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen backward to get it. Calculate which requires less moving. Forward
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen counting may encounter more messages which require extra space, count
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen - If we decide to move forwards and we had to go through dirty
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen messages, do the moving from last to first dirty message
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen - If we encounter end of file, grow the file enough to get the required
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen amount of space plus enough space to fill X-Keywords headers full of
cd8507179823de33d6e8242e10dbc15d136245b5Timo Sirainen/* returns -1 = error, 0 = mbox changed since previous lock, 1 = didn't */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic int mbox_sync_lock(struct mbox_sync_context *sync_ctx, int lock_type)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_assert(lock_type != F_WRLCK || !ibox->mbox_readonly);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen istream_raw_mbox_get_start_offset(sync_ctx->input);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (mbox_lock(ibox, lock_type, &sync_ctx->lock_id) <= 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sync_ctx->file_input = sync_ctx->ibox->mbox_file_stream;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sync_ctx->input = sync_ctx->ibox->mbox_stream;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* we didn't have the file open before -> it changed */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (st.st_mtime != old_st.st_mtime || st.st_size != old_st.st_size ||
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen /* same as before. we'll have to fix mbox stream to contain
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen correct from_offset, hdr_offset and body_offset. so, seek
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen to from_offset and read through the header. */
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen if (istream_raw_mbox_seek(sync_ctx->input, old_from_offset) < 0) {
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen "Message offset %s changed unexpectedly for mbox file "
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen "%s", dec2str(old_from_offset), sync_ctx->ibox->path);
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen (void)istream_raw_mbox_get_body_offset(sync_ctx->input);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainenint mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset)
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen if (istream_raw_mbox_seek(sync_ctx->input, from_offset) < 0) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen "Unexpectedly lost From-line at offset %"PRIuUOFF_T
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainenstatic int mbox_sync_grow_file(struct mbox_sync_context *sync_ctx,
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen /* put the extra space between last message's header and body */
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen file_size = i_stream_get_size(sync_ctx->file_input) + grow_size;
8305127d1074cf9a1e25dec9be2735276462079dTimo Sirainen if (file_set_size(sync_ctx->fd, file_size) < 0) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen mbox_set_syscall_error(sync_ctx->ibox, "file_set_size()");
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen if (mbox_move(sync_ctx, mail_ctx->body_offset, src_offset,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void mbox_sync_buffer_delete_old(buffer_t *syncs_buf, uint32_t uid)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen sync = buffer_get_modifyable_data(syncs_buf, &size);
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen buffer_set_used_size(syncs_buf, dest * sizeof(*sync));
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainenmbox_sync_read_next_mail(struct mbox_sync_context *sync_ctx,
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen /* get EOF */
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen (void)istream_raw_mbox_get_header_offset(sync_ctx->input);
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen istream_raw_mbox_get_start_offset(sync_ctx->input);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen istream_raw_mbox_get_header_offset(sync_ctx->input);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (mail_ctx->seq > 1 && sync_ctx->dest_first_mail) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* First message was expunged and this is the next one.
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen Skip \n header */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mbox_sync_parse_next_mail(sync_ctx->input, mail_ctx, FALSE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_assert(sync_ctx->input->v_offset != mail_ctx->from_offset);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen istream_raw_mbox_get_body_size(sync_ctx->input,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen i_assert(mail_ctx->mail.body_size < OFF_T_MAX);
18ccd19c244f49665fe03cda785efa066d2c38dfTimo Sirainen /* save the offset permanently with recent flag state */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_ctx->mail.from_offset = mail_ctx->from_offset;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((mail_ctx->mail.flags & MBOX_NONRECENT) == 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* need to add 'O' flag to Status-header */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen // FIXME: save it somewhere
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstatic int mbox_sync_buf_have_expunges(buffer_t *syncs_buf)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (i = 0; i < size; i++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (sync[i].type == MAIL_INDEX_SYNC_TYPE_EXPUNGE)
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainenstatic int mbox_sync_read_index_syncs(struct mbox_sync_context *sync_ctx,
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen struct mail_index_sync_rec *sync_rec = &sync_ctx->sync_rec;
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen if (sync_ctx->ibox->mbox_readonly || sync_ctx->index_sync_ctx == NULL)
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen mbox_sync_buffer_delete_old(sync_ctx->syncs, uid);
c4bb0320ab43ea35fa6df88fc745fdad906cee44Timo Sirainen if (sync_rec->type == MAIL_INDEX_SYNC_TYPE_EXPUNGE)
047e3bbb00e68a0d43355e11a67b2e912e06de19Timo Sirainen ret = mail_index_sync_next(sync_ctx->index_sync_ctx, sync_rec);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen *sync_expunge_r = mbox_sync_buf_have_expunges(sync_ctx->syncs);
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainenstatic void mbox_sync_apply_index_syncs(buffer_t *syncs_buf, uint8_t *flags,
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen for (i = 0; i < size; i++) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (sync[i].type != MAIL_INDEX_SYNC_TYPE_FLAGS)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_index_sync_flags_apply(&sync[i], flags, keywords);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenmbox_sync_read_index_rec(struct mbox_sync_context *sync_ctx,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen uint32_t uid, const struct mail_index_record **rec_r)
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen messages_count = mail_index_view_get_message_count(sync_ctx->sync_view);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* externally expunged message, remove from index */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_index_expunge(sync_ctx->t, sync_ctx->idx_seq);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* new UID in the middle of the mailbox - shouldn't happen */
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "mbox sync: UID inserted in the middle of mailbox %s "
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "(%u > %u)", sync_ctx->ibox->path, rec->uid, uid);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_index_mark_corrupted(sync_ctx->ibox->index);
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainenstatic int mbox_sync_get_from_offset(struct mbox_sync_context *sync_ctx,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* see if from_offset needs updating */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (mail_index_lookup_extra(sync_ctx->sync_view, seq,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenmbox_sync_update_from_offset(struct mbox_sync_context *sync_ctx,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (mbox_sync_get_from_offset(sync_ctx, sync_ctx->idx_seq,
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen mail_index_update_extra_rec(sync_ctx->t, sync_ctx->idx_seq,
d859478e8b106de6cea54f26861bd4232c92f62cTimo Sirainenstatic int mbox_sync_update_index(struct mbox_sync_context *sync_ctx,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* new message */
77d8223da3da23b731257596abefa77e4485b77dTimo Sirainen mail_index_append(sync_ctx->t, mail->uid, &sync_ctx->idx_seq);
77d8223da3da23b731257596abefa77e4485b77dTimo Sirainen mbox_flags = mail->flags & (MAIL_FLAGS_MASK^MAIL_RECENT);
77d8223da3da23b731257596abefa77e4485b77dTimo Sirainen mail_index_update_flags(sync_ctx->t, sync_ctx->idx_seq,
77d8223da3da23b731257596abefa77e4485b77dTimo Sirainen /* see if flags changed */
77d8223da3da23b731257596abefa77e4485b77dTimo Sirainen memcpy(idx_keywords, rec->keywords, INDEX_KEYWORDS_BYTE_COUNT);
77d8223da3da23b731257596abefa77e4485b77dTimo Sirainen mbox_flags = (rec->flags & ~MAIL_FLAGS_MASK) |
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen (mail->flags & (MAIL_FLAGS_MASK^MAIL_RECENT));
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_index_update_flags(sync_ctx->t, sync_ctx->idx_seq,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* update from_offsets, but not if we're going to rewrite this message.
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen rewriting would just move it anyway. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen int nocheck = rec == NULL || sync_ctx->expunged_space > 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (mbox_sync_update_from_offset(sync_ctx, mail, nocheck) < 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic int mbox_read_from_line(struct mbox_sync_mail_context *ctx)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct istream *input = ctx->sync_ctx->file_input;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const unsigned char *data;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen buffer_set_used_size(ctx->sync_ctx->from_line, 0);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen from_line_size = ctx->hdr_offset - ctx->from_offset;
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen buffer_append(ctx->sync_ctx->from_line, data, size);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenmbox_write_from_line(struct mbox_sync_mail_context *ctx, off_t move_diff)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (pwrite_full(ctx->sync_ctx->fd, str_data(str), str_len(str),
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen mbox_set_syscall_error(ctx->sync_ctx->ibox, "pwrite_full()");
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainenupdate_from_offsets(struct index_mailbox *ibox,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_index_transaction *t, buffer_t *mails_buf,
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen mails = buffer_get_modifyable_data(mails_buf, NULL);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen mail_index_update_extra_rec(t, seq1, extra_idx,
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainenstatic int mbox_sync_check_excl_lock(struct mbox_sync_context *sync_ctx)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (sync_ctx->ibox->mbox_lock_type == F_RDLCK) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if ((ret = mbox_sync_lock(sync_ctx, F_WRLCK)) < 0)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainenstatic int mbox_sync_handle_expunge(struct mbox_sync_mail_context *mail_ctx)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if ((ret = mbox_sync_check_excl_lock(mail_ctx->sync_ctx)) < 0)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen mail_ctx->mail.offset = mail_ctx->from_offset;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_ctx->body_offset - mail_ctx->from_offset +
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* expunging first message, fix space to contain next
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen message's \n header too since it will be removed. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_ctx->sync_ctx->expunged_space += mail_ctx->mail.space;
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainenstatic int mbox_sync_handle_header(struct mbox_sync_mail_context *mail_ctx)
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (sync_ctx->expunged_space > 0 && sync_ctx->need_space_seq == 0) {
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen /* move the header backwards to fill expunged space */
6469cf211a57433335641725dc236ebb2b9fdd3bTimo Sirainen if ((ret = mbox_sync_check_excl_lock(sync_ctx)) < 0)
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen /* read the From-line before rewriting overwrites it */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mbox_sync_update_header(mail_ctx, sync_ctx->syncs);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((ret = mbox_sync_try_rewrite(mail_ctx, move_diff)) < 0)
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen /* rewrite successful, write From-line to
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen new location */
f5a7396b31762a1f876517e13ce9065820139f7cTimo Sirainen if (mbox_write_from_line(mail_ctx, move_diff) < 0)
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen if ((ret = mbox_sync_check_excl_lock(sync_ctx)) < 0)
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen mbox_sync_update_header(mail_ctx, sync_ctx->syncs);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((ret = mbox_sync_try_rewrite(mail_ctx, 0)) < 0)
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen /* nothing to do */
499fec3443374cc89fb8c83b8027c1614097d7a3Timo Sirainen if (ret == 0 && sync_ctx->need_space_seq == 0) {
499fec3443374cc89fb8c83b8027c1614097d7a3Timo Sirainen /* first mail with no space to write it */
if (seq == 0)
if (min_message_count != 0) {
&expunged) < 0)
if (size == 0)
if (!expunged) {
if (ret < 0) {
return ret;
if (!expunged) {
rec) < 0)
if (!expunged) {
trailer_size) < 0)
int ret;
FALSE);
unsigned int lock_id = 0;
if (lock) {
if (lock)
if (last_commit) {
if (ret <= 0) {
if (ret < 0)
return ret;
lock_id = 0;
if (ret < 0)
if (ret < 0)
&seq,
&offset) < 0)
return ret;