mbox-sync.c revision 100e980900f652c9114997d7153e010e0639effe
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (C) 2002 Timo Sirainen */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "lib.h"
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen#include "mbox-index.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "mbox-lock.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "mail-index-util.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include <stdlib.h>
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen#include <unistd.h>
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include <fcntl.h>
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen#include <sys/stat.h>
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic uoff_t get_indexed_mbox_size(MailIndex *index)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen MailIndexRecord *rec;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen uoff_t offset, hdr_size, body_size;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (index->lock_type == MAIL_LOCK_UNLOCK) {
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen if (!mail_index_set_lock(index, MAIL_LOCK_SHARED))
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return 0;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen
5afc76d0215c5f7631dec06ef864d59f0686a0a8Timo Sirainen /* get the last record */
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen rec = index->header->messages_count == 0 ? NULL :
12d38e76ba7f70d6219c89ec7416fea0d5de7e02Timo Sirainen index->lookup(index, index->header->messages_count);
b624773984e35dd894db8dff976c1a2114c70782Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen offset = 0;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (rec != NULL) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* get the offset + size of last message, which tells the
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen last known mbox file size */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (mbox_mail_get_location(index, rec, &offset,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen &hdr_size, &body_size))
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen offset += hdr_size + body_size;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
3a7113e3e2dac0e333e1a3f62af7d682896f59c6Timo Sirainen
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen if (offset > OFF_T_MAX) {
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen /* too large to fit in off_t */
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen return 0;
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen }
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return offset;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic int mbox_lock_and_sync_full(MailIndex *index,
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen MailLockType data_lock_type)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen MailLockType lock_type;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* syncing needs exclusive index lock and shared
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen mbox lock, but if we'd want exclusive mbox lock
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen we need to set it here already */
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen if (index->lock_type == MAIL_LOCK_SHARED)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen (void)mail_index_set_lock(index, MAIL_LOCK_UNLOCK);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen return FALSE;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen if (index->mbox_lock_type == MAIL_LOCK_UNLOCK) {
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen lock_type = data_lock_type == MAIL_LOCK_EXCLUSIVE ?
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen MAIL_LOCK_EXCLUSIVE : MAIL_LOCK_SHARED;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen if (!mbox_lock(index, lock_type))
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen return FALSE;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen }
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen return mbox_sync_full(index);
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen}
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenint mbox_index_sync(MailIndex *index, MailLockType data_lock_type,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen int *changes)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct stat st;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen time_t index_mtime;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen uoff_t filesize;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen i_assert(index->lock_type != MAIL_LOCK_SHARED);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (changes != NULL)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *changes = FALSE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (index->fd == -1) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* anon-mmaped */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen index_mtime = index->file_sync_stamp;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen } else {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (fstat(index->fd, &st) < 0)
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen return index_set_syscall_error(index, "fstat()");
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen index_mtime = st.st_mtime;
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (stat(index->mbox_path, &st) < 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return mbox_set_syscall_error(index, "stat()");
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen filesize = st.st_size;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen if (index->mbox_dev != st.st_dev || index->mbox_ino != st.st_ino) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* mbox file was overwritten, close it if it was open */
83d2e37f065eabe38dc92db485c5ca39ee43ce05Timo Sirainen index->mbox_dev = st.st_dev;
83d2e37f065eabe38dc92db485c5ca39ee43ce05Timo Sirainen index->mbox_ino = st.st_ino;
83d2e37f065eabe38dc92db485c5ca39ee43ce05Timo Sirainen index->mbox_size = (uoff_t)-1;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen mbox_file_close_fd(index);
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (index_mtime != st.st_mtime || index->mbox_size != filesize) {
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen mbox_file_close_inbuf(index);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen index->mbox_size = get_indexed_mbox_size(index);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (index->file_sync_stamp == 0 &&
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen index->mbox_size == filesize+1) {
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen /* just opened the mailbox, and the file size is same
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen as we expected. don't bother checking it any
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen further. the +1 comes from the extra \n at end. */
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen } else {
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen if (changes != NULL)
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen *changes = TRUE;
3a7113e3e2dac0e333e1a3f62af7d682896f59c6Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (!mbox_lock_and_sync_full(index, data_lock_type))
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return FALSE;
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen }
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen index->file_sync_stamp = st.st_mtime;
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen }
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen /* we need some index lock to be able to lock mbox */
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen if (index->lock_type == MAIL_LOCK_UNLOCK) {
d6bffcdf187c155dccc04fb4267b4f82ce59347dTimo Sirainen if (!index->set_lock(index, MAIL_LOCK_SHARED))
c0757c70cfd2c9b44de3504b753a4d2f38690ef0Timo Sirainen return FALSE;
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen }
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen if (data_lock_type == MAIL_LOCK_UNLOCK) {
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen if (!mbox_unlock(index))
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen return FALSE;
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen } else {
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen if (!mbox_lock(index, data_lock_type))
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen return FALSE;
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen }
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen index->mbox_sync_counter = index->mbox_lock_counter;
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen return TRUE;
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen}
a138ac12134564b151f00fdef86fba9cd9ba8af0Timo Sirainen