Example #1
0
static int maildir_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r)
{
	struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box;
	struct index_mail *mail = (struct index_mail *)_mail;
	struct index_mail_data *data = &mail->data;
	struct message_size hdr_size, body_size;
	struct istream *input;
	uoff_t old_offset;

	if (maildir_uidlist_is_read(mbox->uidlist) ||
	    (_mail->box->flags & MAILBOX_FLAG_POP3_SESSION) != 0) {
		/* try to get the size from uidlist. this is especially useful
		   with pop3 to avoid unnecessarily opening the cache file. */
		if (maildir_quick_size_lookup(mail, TRUE,
					      &data->virtual_size) < 0)
			return -1;
	}

	if (data->virtual_size == (uoff_t)-1) {
		if (index_mail_get_cached_virtual_size(mail, size_r)) {
			i_assert(mail->data.virtual_size != (uoff_t)-1);
			maildir_handle_size_caching(mail, TRUE, TRUE);
			return 0;
		}
		if (maildir_quick_size_lookup(mail, TRUE,
					      &data->virtual_size) < 0)
			return -1;
	}
	if (data->virtual_size != (uoff_t)-1) {
		data->dont_cache_fetch_fields |= MAIL_FETCH_VIRTUAL_SIZE;
		*size_r = data->virtual_size;
		return 0;
	}

	/* fallback to reading the file */
	old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
	if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0)
		return -1;
	i_stream_seek(data->stream, old_offset);

	maildir_handle_size_caching(mail, FALSE, TRUE);
	*size_r = data->virtual_size;
	return 0;
}
Example #2
0
static int maildir_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
{
	struct index_mail *mail = (struct index_mail *)_mail;
	struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box;
	struct index_mail_data *data = &mail->data;
	struct stat st;
	struct message_size hdr_size, body_size;
	struct istream *input;
	const char *path;
	int ret;

	if (maildir_uidlist_is_read(mbox->uidlist) ||
	    (_mail->box->flags & MAILBOX_FLAG_POP3_SESSION) != 0) {
		/* try to get the size from uidlist (see virtual size above) */
		if (maildir_quick_size_lookup(mail, FALSE,
					      &data->physical_size) < 0)
			return -1;
	}

	if (data->physical_size == (uoff_t)-1) {
		if (index_mail_get_physical_size(_mail, size_r) == 0) {
			i_assert(mail->data.physical_size != (uoff_t)-1);
			maildir_handle_size_caching(mail, TRUE, FALSE);
			return 0;
		}
		if (maildir_quick_size_lookup(mail, FALSE,
					      &data->physical_size) < 0)
			return -1;
	}
	if (data->physical_size != (uoff_t)-1) {
		data->dont_cache_fetch_fields |= MAIL_FETCH_PHYSICAL_SIZE;
		*size_r = data->physical_size;
		return 0;
	}

	if (mail->mail.v.istream_opened != NULL) {
		/* we can't use stat(), because this may be a mail that some
		   plugin has changed (e.g. zlib). need to do it the slow
		   way. */
		if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0)
			return -1;
		st.st_size = hdr_size.physical_size + body_size.physical_size;
	} else if (!_mail->saving) {
		ret = maildir_file_do(mbox, _mail->uid, do_stat, &st);
		if (ret <= 0) {
			if (ret == 0)
				mail_set_expunged(_mail);
			return -1;
		}
	} else {
		/* saved mail which hasn't been committed yet */
		path = maildir_save_file_get_path(_mail->transaction,
						  _mail->seq);
		if (stat(path, &st) < 0) {
			mail_storage_set_critical(_mail->box->storage,
						  "stat(%s) failed: %m", path);
			return -1;
		}
	}

	data->physical_size = st.st_size;
	maildir_handle_size_caching(mail, FALSE, FALSE);
	*size_r = st.st_size;
	return 0;
}