maildir-sync.c revision d77c309fccbc6a7594f8cb08fb01009fa613c568
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (C) 2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/*
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Here's a description of how we handle Maildir synchronization and
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen it's problems:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen We want to be as efficient as we can. The most efficient way to
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen check if changes have occured is to stat() the new/ and cur/
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen directories and uidlist file - if their mtimes haven't changed,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen there's no changes and we don't need to do anything.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Problem 1: Multiple changes can happen within a single second -
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen nothing guarantees that once we synced it, someone else didn't just
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen then make a modification. Such modifications wouldn't get noticed
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen until a new modification occured later.
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen Problem 2: Syncing cur/ directory is much more costly than syncing
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen new/. Moving mails from new/ to cur/ will always change mtime of
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen cur/ causing us to sync it as well.
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen Problem 3: We may not be able to move mail from new/ to cur/
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen because we're out of quota, or simply because we're accessing a
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen read-only mailbox.
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen MAILDIR_SYNC_SECS
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen -----------------
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen Several checks below use MAILDIR_SYNC_SECS, which should be maximum
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen clock drift between all computers accessing the maildir (eg. via
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen NFS), rounded up to next second. Our default is 1 second, since
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen everyone should be using NTP.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Note that setting it to 0 works only if there's only one computer
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen accessing the maildir. It's practically impossible to make two
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen clocks _exactly_ synchronized.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen It might be possible to only use file server's clock by looking at
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen the atime field, but I don't know how well that would actually work.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cur directory
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen -------------
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen We have dirty_cur_time variable which is set to cur/ directory's
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mtime when it's >= time() - MAILDIR_SYNC_SECS and we _think_ we have
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen synchronized the directory.
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen When dirty_cur_time is non-zero, we don't synchronize the cur/
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen directory until
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen a) cur/'s mtime changes
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen b) opening a mail fails with ENOENT
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen c) time() > dirty_cur_time + MAILDIR_SYNC_SECS
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen This allows us to modify the maildir multiple times without having
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen to sync it at every change. The sync will eventually be done to
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen make sure we didn't miss any external changes.
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen The dirty_cur_time is set when:
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen - we change message flags
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen - we expunge messages
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen - we move mail from new/ to cur/
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen - we sync cur/ directory and it's mtime is >= time() - MAILDIR_SYNC_SECS
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen It's unset when we do the final syncing, ie. when mtime is
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen older than time() - MAILDIR_SYNC_SECS.
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen new directory
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen -------------
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen If new/'s mtime is >= time() - MAILDIR_SYNC_SECS, always synchronize
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen it. dirty_cur_time-like feature might save us a few syncs, but
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen that might break a client which saves a mail in one connection and
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen tries to fetch it in another one. new/ directory is almost always
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen empty, so syncing it should be very fast anyway. Actually this can
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen still happen if we sync only new/ dir while another client is also
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen moving mails from it to cur/ - it takes us a while to see them.
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen That's pretty unlikely to happen however, and only way to fix it
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen would be to always synchronize cur/ after new/.
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen Normally we move all mails from new/ to cur/ whenever we sync it. If
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen it's not possible for some reason, we mark the mail with "probably
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen exists in new/ directory" flag.
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen If rename() still fails because of ENOSPC or EDQUOT, we still save
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen the flag changes in index with dirty-flag on. When moving the mail
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen to cur/ directory, or when we notice it's already moved there, we
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen apply the flag changes to the filename, rename it and remove the
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen dirty flag. If there's dirty flags, this should be tried every time
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen after expunge or when closing the mailbox.
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen uidlist
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen -------
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen This file contains UID <-> filename mappings. It's updated only when
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen new mail arrives, so it may contain filenames that have already been
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen deleted. Updating is done by getting uidlist.lock file, writing the
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen whole uidlist into it and rename()ing it over the old uidlist. This
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen means there's no need to lock the file for reading.
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen Whenever uidlist is rewritten, it's mtime must be larger than the old
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen one's. Use utime() before rename() if needed. Note that inode checking
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen wouldn't have been sufficient as inode numbers can be reused.
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen This file is usually read the first time you need to know filename for
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen given UID. After that it's not re-read unless new mails come that we
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen don't know about.
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen broken clients
6288d3611eda14a017dae9927b73f46afb646c96Timo Sirainen --------------
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen Originally the middle identifier in Maildir filename was specified
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen only as <process id>_<delivery counter>. That however created a
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen problem with randomized PIDs which made it possible that the same
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen PID was reused within one second.
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen So if within one second a mail was delivered, MUA moved it to cur/
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen and another mail was delivered by a new process using same PID as
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen the first one, we likely ended up overwriting the first mail when
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen the second mail was moved over it.
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen Nowadays everyone should be giving a bit more specific identifier,
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen for example include microseconds in it which Dovecot does.
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen There's a simple way to prevent this from happening in some cases:
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen Don't move the mail from new/ to cur/ if it's mtime is >= time() -
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen MAILDIR_SYNC_SECS. The second delivery's link() call then fails
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen because the file is already in new/, and it will then use a
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen different filename. There's a few problems with this however:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen - it requires extra stat() call which is unneeded extra I/O
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen - another MUA might still move the mail to cur/
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen - if first file's flags are modified by either Dovecot or another
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen MUA, it's moved to cur/ (you _could_ just do the dirty-flagging
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen but that'd be ugly)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
2e937ed8585299b2e879a28314902a5f644813d2Timo Sirainen Because this is useful only for very few people and it requires
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen extra I/O, I decided not to implement this. It should be however
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen quite easy to do since we need to be able to deal with files in new/
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen in any case.
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen It's also possible to never accidentally overwrite a mail by using
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen link() + unlink() rather than rename(). This however isn't very
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen good idea as it introduces potential race conditions when multiple
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen clients are accessing the mailbox:
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen Trying to move the same mail from new/ to cur/ at the same time:
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen a) Client 1 uses slightly different filename than client 2,
c3412ddeb9abc13f99d3caf50faf76cd99f7e9d2Timo Sirainen for example one sets read-flag on but the other doesn't.
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen You have the same mail duplicated now.
6f25019b337e27600159b596824da08732965576Timo Sirainen
6f25019b337e27600159b596824da08732965576Timo Sirainen b) Client 3 sees the mail between Client 1's and 2's link() calls
6f25019b337e27600159b596824da08732965576Timo Sirainen and changes it's flag. You have the same mail duplicated now.
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen And it gets worse when they're unlink()ing in cur/ directory:
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen c) Client 1 changes mails's flag and client 2 changes it back
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen between 1's link() and unlink(). The mail is now expunged.
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen d) If you try to deal with the duplicates by unlink()ing another
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen one of them, you might end up unlinking both of them.
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen So, what should we do then if we notice a duplicate? First of all,
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen it might not be a duplicate at all, readdir() might have just
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen returned it twice because it was just renamed. What we should do is
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen create a completely new base name for it and rename() it to that.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen If the call fails with ENOENT, it only means that it wasn't a
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen duplicate after all.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen*/
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen#include "lib.h"
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen#include "ioloop.h"
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen#include "buffer.h"
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen#include "hash.h"
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen#include "str.h"
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen#include "maildir-storage.h"
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen#include "maildir-uidlist.h"
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen#include <stdio.h>
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen#include <stddef.h>
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen#include <unistd.h>
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen#include <dirent.h>
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen#include <sys/stat.h>
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen#define MAILDIR_SYNC_SECS 1
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen#define MAILDIR_FILENAME_FLAG_FOUND 128
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstruct maildir_sync_context {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct index_mailbox *ibox;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const char *new_dir, *cur_dir;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int partial;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen};
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainenstruct maildir_index_sync_context {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen struct index_mailbox *ibox;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen struct mail_index_view *view;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen struct mail_index_sync_ctx *sync_ctx;
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen struct mail_index_transaction *trans;
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen struct mail_index_sync_rec sync_rec;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen uint32_t seq;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int have_dirty, last_dirty;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen};
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int maildir_expunge(struct index_mailbox *ibox, const char *path,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen void *context __attr_unused__)
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (unlink(path) == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ibox->dirty_cur_time = ioloop_time;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 1;
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen }
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen if (errno == ENOENT)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen return 0;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen mail_storage_set_critical(ibox->box.storage,
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen "unlink(%s) failed: %m", path);
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen return -1;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen}
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int maildir_sync_flags(struct index_mailbox *ibox, const char *path,
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen void *context)
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen{
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen struct maildir_index_sync_context *ctx = context;
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen const char *newpath;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen enum mail_flags flags;
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen uint8_t flags8;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen keywords_mask_t keywords;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ctx->last_dirty = FALSE;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen (void)maildir_filename_get_flags(path, &flags, keywords);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen flags8 = flags;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_index_sync_flags_apply(&ctx->sync_rec, &flags8, keywords);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen newpath = maildir_filename_set_flags(path, flags8, keywords);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen if (rename(path, newpath) == 0) {
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen ibox->dirty_cur_time = ioloop_time;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen return 1;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen }
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen if (errno == ENOENT)
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen return 0;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (ENOSPACE(errno) || errno == EACCES) {
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen memset(keywords, 0, sizeof(keywords));
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen mail_index_update_flags(ctx->trans, ctx->seq, MODIFY_ADD,
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen MAIL_INDEX_MAIL_FLAG_DIRTY, keywords);
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen ctx->last_dirty = TRUE;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen return 1;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_storage_set_critical(ibox->box.storage,
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen "rename(%s, %s) failed: %m", path, newpath);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return -1;
f0f9c8e94abac18f8acd91b9e724c4c32863723aTimo Sirainen}
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainenstatic int maildir_sync_record(struct index_mailbox *ibox,
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen struct maildir_index_sync_context *ctx)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen{
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen struct mail_index_sync_rec *sync_rec = &ctx->sync_rec;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen struct mail_index_view *view = ctx->view;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen const struct mail_index_record *rec;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen uint32_t seq, seq1, seq2, uid;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen switch (sync_rec->type) {
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen case MAIL_INDEX_SYNC_TYPE_APPEND:
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen break;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* make it go through sequences to avoid looping through huge
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen holes in UID range */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mail_index_lookup_uid_range(view, sync_rec->uid1,
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen sync_rec->uid2,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen &seq1, &seq2) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen if (seq1 == 0)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen break;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen for (seq = seq1; seq <= seq2; seq++) {
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen if (mail_index_lookup_uid(view, seq, &uid) < 0)
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen return -1;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (maildir_file_do(ibox, uid, maildir_expunge,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen NULL) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
8af07808ba203f8709e2ff9eaf2291e1c4a4d53dTimo Sirainen }
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen break;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen case MAIL_INDEX_SYNC_TYPE_FLAGS:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mail_index_lookup_uid_range(view, sync_rec->uid1,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_rec->uid2,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen &seq1, &seq2) < 0)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return -1;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (seq1 == 0)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen break;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen for (ctx->seq = seq1; ctx->seq <= seq2; ctx->seq++) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (mail_index_lookup_uid(view, ctx->seq, &uid) < 0)
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen return -1;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (maildir_file_do(ibox, uid,
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen maildir_sync_flags, ctx) < 0)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return -1;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (!ctx->last_dirty) {
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen /* if this flag was dirty, drop it */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (mail_index_lookup(view, ctx->seq, &rec) < 0)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return -1;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) {
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen keywords_mask_t keywords;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen memset(keywords, 0, sizeof(keywords));
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen mail_index_update_flags(ctx->trans,
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen ctx->seq, MODIFY_REMOVE,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen MAIL_INDEX_MAIL_FLAG_DIRTY,
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen keywords);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen }
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen }
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen }
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen break;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen }
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen return 0;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen}
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenint maildir_sync_last_commit(struct index_mailbox *ibox)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen{
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen struct maildir_index_sync_context ctx;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen const struct mail_index_header *hdr;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen uint32_t seq;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen uoff_t offset;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen int ret;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ibox->commit_log_file_seq == 0)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return 0;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen memset(&ctx, 0, sizeof(ctx));
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ctx.ibox = ibox;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ret = mail_index_sync_begin(ibox->index, &ctx.sync_ctx, &ctx.view,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ibox->commit_log_file_seq,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ibox->commit_log_file_offset);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ret > 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (mail_index_get_header(ctx.view, &hdr) == 0 &&
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen (hdr->flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != 0)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ctx.have_dirty = TRUE;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ctx.trans = mail_index_transaction_begin(ctx.view, FALSE);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen while ((ret = mail_index_sync_next(ctx.sync_ctx,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen &ctx.sync_rec)) > 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (maildir_sync_record(ibox, &ctx) < 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ret = -1;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen break;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (mail_index_transaction_commit(ctx.trans, &seq, &offset) < 0)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ret = -1;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (mail_index_sync_end(ctx.sync_ctx) < 0)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ret = -1;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ret == 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ibox->commit_log_file_seq = 0;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ibox->commit_log_file_offset = 0;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen } else {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_storage_set_index_error(ibox);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return ret;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen}
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic struct maildir_sync_context *
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenmaildir_sync_context_new(struct index_mailbox *ibox)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen{
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen struct maildir_sync_context *ctx;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ctx = t_new(struct maildir_sync_context, 1);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ctx->ibox = ibox;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ctx->new_dir = t_strconcat(ibox->path, "/new", NULL);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ctx->cur_dir = t_strconcat(ibox->path, "/cur", NULL);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return ctx;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen}
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic void maildir_sync_deinit(struct maildir_sync_context *ctx)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen{
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ctx->uidlist_sync_ctx != NULL)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen (void)maildir_uidlist_sync_deinit(ctx->uidlist_sync_ctx);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen}
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic int maildir_fix_duplicate(struct index_mailbox *ibox, const char *dir,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen const char *old_fname)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen{
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen const char *new_fname, *old_path, *new_path;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen int ret = 0;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen t_push();
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
7e6749d69b9d3f87e598b8dc3346b82f3cb3b8e7Timo Sirainen old_path = t_strconcat(dir, "/", old_fname, NULL);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen new_fname = maildir_generate_tmp_filename(&ioloop_timeval);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen new_path = t_strconcat(ibox->path, "/new/", new_fname, NULL);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (rename(old_path, new_path) == 0) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen i_warning("Fixed duplicate in %s: %s -> %s",
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen ibox->path, old_fname, new_fname);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else if (errno != ENOENT) {
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen mail_storage_set_critical(ibox->box.storage,
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen "rename(%s, %s) failed: %m", old_path, new_path);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ret = -1;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen t_pop();
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return ret;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen}
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen
5d98a279f2726a8c38ef1e8e3c54d6c62d523a65Timo Sirainenstatic int maildir_scan_dir(struct maildir_sync_context *ctx, int new_dir)
5d98a279f2726a8c38ef1e8e3c54d6c62d523a65Timo Sirainen{
5d98a279f2726a8c38ef1e8e3c54d6c62d523a65Timo Sirainen struct mail_storage *storage = ctx->ibox->box.storage;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen const char *dir;
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen DIR *dirp;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen string_t *src, *dest;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct dirent *dp;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen enum maildir_uidlist_rec_flag flags;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int move_new, ret = 1;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen dir = new_dir ? ctx->new_dir : ctx->cur_dir;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen dirp = opendir(dir);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (dirp == NULL) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen mail_storage_set_critical(storage,
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen "opendir(%s) failed: %m", dir);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return -1;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen t_push();
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen src = t_str_new(1024);
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen dest = t_str_new(1024);
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen move_new = new_dir && !mailbox_is_readonly(&ctx->ibox->box) &&
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen !ctx->ibox->keep_recent;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen while ((dp = readdir(dirp)) != NULL) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (dp->d_name[0] == '.')
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen continue;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ret = maildir_uidlist_sync_next_pre(ctx->uidlist_sync_ctx,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen dp->d_name);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ret == 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen /* new file and we couldn't lock uidlist, check this
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen later in next sync. */
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (new_dir)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ctx->ibox->last_new_mtime = 0;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen else
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ctx->ibox->dirty_cur_time = ioloop_time;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen continue;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (ret < 0)
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen break;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen flags = 0;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (move_new) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen str_truncate(src, 0);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen str_truncate(dest, 0);
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen str_printfa(src, "%s/%s", ctx->new_dir, dp->d_name);
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen str_printfa(dest, "%s/%s", ctx->cur_dir, dp->d_name);
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen if (strchr(dp->d_name, ':') == NULL)
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen str_append(dest, ":2,");
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen if (rename(str_c(src), str_c(dest)) == 0) {
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen /* we moved it - it's \Recent for us */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ctx->ibox->dirty_cur_time = ioloop_time;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen flags |= MAILDIR_UIDLIST_REC_FLAG_MOVED |
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen MAILDIR_UIDLIST_REC_FLAG_RECENT;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen } else if (ENOTFOUND(errno)) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen /* someone else moved it already */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen flags |= MAILDIR_UIDLIST_REC_FLAG_MOVED;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else if (ENOSPACE(errno)) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* not enough disk space, leave here */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen flags |= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR |
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen MAILDIR_UIDLIST_REC_FLAG_RECENT;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen move_new = FALSE;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen } else {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen flags |= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR |
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen MAILDIR_UIDLIST_REC_FLAG_RECENT;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_storage_set_critical(storage,
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen "rename(%s, %s) failed: %m",
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen str_c(src), str_c(dest));
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen } else if (new_dir) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen flags |= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR |
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen MAILDIR_UIDLIST_REC_FLAG_RECENT;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ret = maildir_uidlist_sync_next(ctx->uidlist_sync_ctx,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen dp->d_name, flags);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (ret <= 0) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (ret < 0)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen break;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* possibly duplicate - try fixing it */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (maildir_fix_duplicate(ctx->ibox,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen dir, dp->d_name) < 0) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ret = -1;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen break;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (closedir(dirp) < 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_storage_set_critical(storage,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen "closedir(%s) failed: %m", dir);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen t_pop();
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return ret < 0 ? -1 : 0;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen}
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainenstatic int maildir_sync_quick_check(struct maildir_sync_context *ctx,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen int *new_changed_r, int *cur_changed_r)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen{
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen struct index_mailbox *ibox = ctx->ibox;
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen struct stat st;
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen time_t new_mtime, cur_mtime;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen *new_changed_r = *cur_changed_r = FALSE;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen if (stat(ctx->new_dir, &st) < 0) {
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen mail_storage_set_critical(ibox->box.storage,
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen "stat(%s) failed: %m", ctx->new_dir);
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen return -1;
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen new_mtime = st.st_mtime;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (stat(ctx->cur_dir, &st) < 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_storage_set_critical(ibox->box.storage,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen "stat(%s) failed: %m", ctx->cur_dir);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return -1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen cur_mtime = st.st_mtime;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (ibox->dirty_cur_time == 0) {
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen /* cur stamp is kept in index, we don't have to sync if
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen someone else has done it and updated the index. make sure
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen we have a fresh index with latest sync_stamp. */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen struct mail_index_view *view;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen const struct mail_index_header *hdr;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (mail_index_refresh(ibox->index) < 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_storage_set_index_error(ibox);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return -1;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen view = mail_index_view_open(ibox->index);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if (mail_index_get_header(view, &hdr) < 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_index_view_close(view);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_storage_set_index_error(ibox);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return -1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen ibox->last_cur_mtime = hdr->sync_stamp;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_index_view_close(view);
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (new_mtime != ibox->last_new_mtime ||
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen new_mtime >= ibox->last_new_sync_time - MAILDIR_SYNC_SECS) {
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen *new_changed_r = TRUE;
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen ibox->last_new_mtime = new_mtime;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen ibox->last_new_sync_time = ioloop_time;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (cur_mtime != ibox->last_cur_mtime ||
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen (ibox->dirty_cur_time != 0 &&
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ioloop_time - ibox->dirty_cur_time > MAILDIR_SYNC_SECS)) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* cur/ changed, or delayed cur/ check */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen *cur_changed_r = TRUE;
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen ibox->last_cur_mtime = cur_mtime;
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen ibox->dirty_cur_time =
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen cur_mtime >= ioloop_time - MAILDIR_SYNC_SECS ?
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen cur_mtime : 0;
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen }
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return 0;
3021a062b16ff0138408be6107d6bcd0ced280b9Timo Sirainen}
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainenstatic int maildir_sync_index(struct maildir_sync_context *ctx)
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen{
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen struct index_mailbox *ibox = ctx->ibox;
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen struct maildir_index_sync_context sync_ctx;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen struct maildir_uidlist_iter_ctx *iter;
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen struct mail_index_transaction *trans;
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen struct mail_index_view *view;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const struct mail_index_header *hdr;
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen const struct mail_index_record *rec;
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen uint32_t seq, uid;
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen enum maildir_uidlist_rec_flag uflags;
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen const char *filename;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_flags flags;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen keywords_mask_t keywords;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen uint32_t uid_validity, next_uid;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen int ret;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen memset(&sync_ctx, 0, sizeof(sync_ctx));
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen sync_ctx.ibox = ibox;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen if (mail_index_sync_begin(ibox->index, &sync_ctx.sync_ctx, &view,
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen (uint32_t)-1, (uoff_t)-1) <= 0) {
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen mail_storage_set_index_error(ibox);
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen sync_ctx.view = view;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = mail_index_get_header(view, &hdr);
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen i_assert(ret == 0); /* view is locked, can't happen */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen uid_validity = maildir_uidlist_get_uid_validity(ibox->uidlist);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (uid_validity != hdr->uid_validity &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uid_validity != 0 && hdr->uid_validity != 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* uidvalidity changed and mailbox isn't being initialized,
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen index must be rebuilt */
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen mail_storage_set_critical(ibox->box.storage,
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen "Maildir %s sync: UIDVALIDITY changed (%u -> %u)",
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen ibox->path, hdr->uid_validity, uid_validity);
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen mail_index_mark_corrupted(ibox->index);
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen (void)mail_index_sync_end(sync_ctx.sync_ctx);
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen trans = mail_index_transaction_begin(view, FALSE);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.trans = trans;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen seq = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen iter = maildir_uidlist_iter_init(ibox->uidlist);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen while (maildir_uidlist_iter_next(iter, &uid, &uflags, &filename)) {
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen maildir_filename_get_flags(filename, &flags, keywords);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RECENT) != 0 &&
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen (uflags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0 &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (uflags & MAILDIR_UIDLIST_REC_FLAG_MOVED) == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* mail is recent for next session as well */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen flags |= MAIL_RECENT;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen __again:
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen seq++;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) {
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen /* partial syncing */
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen continue;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen }
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen if (seq > hdr->messages_count) {
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen if (uid < hdr->next_uid) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* most likely a race condition: we read the
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen maildir, then someone else expunged messages
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen and committed changes to index. so, this
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen message shouldn't actually exist. mark it
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen racy and check in next sync.
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
60d3fa9883237e896a8704275b6116fa46f7ffdaTimo Sirainen the difference between this and the later
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen check is that this one happens when messages
659fe5d24825b160cae512538088020d97a60239Timo Sirainen are expunged from the end */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if ((uflags &
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen MAILDIR_UIDLIST_REC_FLAG_RACING) != 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_storage_set_critical(
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen ibox->box.storage,
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen "Maildir %s sync: "
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen "UID < next_uid "
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "(%u < %u, file = %s)",
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ibox->path, uid, hdr->next_uid,
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen filename);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_mark_corrupted(ibox->index);
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen ret = -1;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen break;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen }
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen ibox->dirty_cur_time = ioloop_time;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen maildir_uidlist_add_flags(ibox->uidlist,
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen filename,
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen MAILDIR_UIDLIST_REC_FLAG_RACING);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen seq--;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen continue;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen }
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mail_index_append(trans, uid, &seq);
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mail_index_update_flags(trans, seq, MODIFY_REPLACE,
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen flags, keywords);
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen continue;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mail_index_lookup(view, seq, &rec) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen break;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (rec->uid < uid) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* expunged */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_expunge(trans, seq);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen goto __again;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (rec->uid > uid) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* most likely a race condition: we read the
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen maildir, then someone else expunged messages and
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen committed changes to index. so, this message
36816b5af1472ae76a1909ae3cf29fd614b2ebfcTimo Sirainen shouldn't actually exist. mark it racy and check
829c036d4ddfbd9ea49bd8a7c54e3057177d346eTimo Sirainen in next sync. */
36816b5af1472ae76a1909ae3cf29fd614b2ebfcTimo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RACING) != 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_storage_set_critical(ibox->box.storage,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "Maildir %s sync: UID inserted in the "
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "middle of mailbox "
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen "(%u > %u, file = %s)",
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen ibox->path, rec->uid, uid, filename);
8d5991f5c4a8840bf1ea754093dbec505564ab78Timo Sirainen mail_index_mark_corrupted(ibox->index);
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen ret = -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen break;
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ibox->dirty_cur_time = ioloop_time;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen maildir_uidlist_add_flags(ibox->uidlist, filename,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen MAILDIR_UIDLIST_REC_FLAG_RACING);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen seq--;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen continue;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen /* we haven't been able to update maildir with this
f5b4979e2780c4df112a300967d647e2fdd73511Timo Sirainen record's flag changes. don't sync them. */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen continue;
2cb565cd978aafd5714792b5161889986d49e431Timo Sirainen }
2cb565cd978aafd5714792b5161889986d49e431Timo Sirainen
343a527f805ca5cce78496b959d6def70e5d0cd4Timo Sirainen if (((uint8_t)flags & ~MAIL_RECENT) !=
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen (rec->flags & (MAIL_FLAGS_MASK^MAIL_RECENT)) ||
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen memcmp(keywords, rec->keywords,
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen INDEX_KEYWORDS_BYTE_COUNT) != 0) {
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen /* FIXME: this is wrong if there's pending changes in
f5b4979e2780c4df112a300967d647e2fdd73511Timo Sirainen transaction log already. it gets fixed in next sync
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen however.. */
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen mail_index_update_flags(trans, seq, MODIFY_REPLACE,
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen flags, keywords);
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen } else if ((flags & MAIL_RECENT) == 0 &&
6e4cd4ba520bc22ce375de378f4751136ebcf75aTimo Sirainen (rec->flags & MAIL_RECENT) != 0) {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen /* just remove recent flag */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen memset(keywords, 0, sizeof(keywords));
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen mail_index_update_flags(trans, seq, MODIFY_REMOVE,
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen MAIL_RECENT, keywords);
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen }
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen }
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen maildir_uidlist_iter_deinit(iter);
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (!ctx->partial) {
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen /* expunge the rest */
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen for (seq++; seq <= hdr->messages_count; seq++)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_expunge(trans, seq);
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen }
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen /* now, sync the index */
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen while ((ret = mail_index_sync_next(sync_ctx.sync_ctx,
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen &sync_ctx.sync_rec)) > 0) {
8d5991f5c4a8840bf1ea754093dbec505564ab78Timo Sirainen if (maildir_sync_record(ibox, &sync_ctx) < 0) {
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen ret = -1;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen break;
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen }
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen }
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen if (ibox->dirty_cur_time == 0 &&
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen ibox->last_cur_mtime != (time_t)hdr->sync_stamp) {
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen uint32_t sync_stamp = ibox->last_cur_mtime;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen mail_index_update_header(trans,
c9a03c8a03a782488981f81bd7c6b5e01ff55f06Timo Sirainen offsetof(struct mail_index_header, sync_stamp),
829c036d4ddfbd9ea49bd8a7c54e3057177d346eTimo Sirainen &sync_stamp, sizeof(sync_stamp));
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen }
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen if (hdr->uid_validity == 0) {
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen /* get the initial uidvalidity */
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (maildir_uidlist_update(ibox->uidlist) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = -1;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen uid_validity = maildir_uidlist_get_uid_validity(ibox->uidlist);
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (uid_validity == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uid_validity = ioloop_time;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen maildir_uidlist_set_uid_validity(ibox->uidlist,
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen uid_validity);
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen }
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen } else if (uid_validity == 0) {
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen maildir_uidlist_set_uid_validity(ibox->uidlist,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen hdr->uid_validity);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen if (uid_validity != hdr->uid_validity && uid_validity != 0) {
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen mail_index_update_header(trans,
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen offsetof(struct mail_index_header, uid_validity),
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen &uid_validity, sizeof(uid_validity));
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen next_uid = maildir_uidlist_get_next_uid(ibox->uidlist);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (next_uid != 0 && hdr->next_uid != next_uid) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_header(trans,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen offsetof(struct mail_index_header, next_uid),
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen &next_uid, sizeof(next_uid));
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (ret < 0)
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen mail_index_transaction_rollback(trans);
343a527f805ca5cce78496b959d6def70e5d0cd4Timo Sirainen else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint32_t seq;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uoff_t offset;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mail_index_transaction_commit(trans, &seq, &offset) < 0)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen ret = -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen else if (seq != 0) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen ibox->commit_log_file_seq = seq;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen ibox->commit_log_file_offset = offset;
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mail_index_sync_end(sync_ctx.sync_ctx) < 0)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen ret = -1;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
e5afebd2df1d4990f7bec2a839260ff2e6d78168Timo Sirainen if (ret == 0) {
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen ibox->commit_log_file_seq = 0;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen ibox->commit_log_file_offset = 0;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen } else {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail_storage_set_index_error(ibox);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return ret;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen}
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenstatic int maildir_sync_context(struct maildir_sync_context *ctx)
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen{
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen int ret, new_changed, cur_changed;
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (maildir_sync_quick_check(ctx, &new_changed, &cur_changed) < 0)
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen return -1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen if (!new_changed && !cur_changed)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return 0;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen ctx->partial = !cur_changed;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen ctx->uidlist_sync_ctx =
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen maildir_uidlist_sync_init(ctx->ibox->uidlist, ctx->partial);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* we have to lock uidlist immediately, otherwise there's race
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen conditions with other processes who might write older maildir
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen file list into uidlist.
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen alternative would be to lock it when new files are found, but
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen the directory scans _must_ be restarted then */
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen if (maildir_uidlist_try_lock(ctx->ibox->uidlist) < 0)
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen return -1;
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen if (maildir_scan_dir(ctx, TRUE) < 0)
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen return -1;
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen if (cur_changed) {
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen if (maildir_scan_dir(ctx, FALSE) < 0)
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen return -1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* finish uidlist syncing, but keep it still locked */
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen if (maildir_uidlist_sync_finish(ctx->uidlist_sync_ctx)) {
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen if (maildir_sync_index(ctx) < 0)
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen return -1;
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen ret = maildir_uidlist_sync_deinit(ctx->uidlist_sync_ctx);
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen ctx->uidlist_sync_ctx = NULL;
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return ret;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen}
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainenstatic int maildir_sync_context_readonly(struct maildir_sync_context *ctx)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen{
a10e5606a9e93f49cf13b3a35c8dc3f5d6ab5909Timo Sirainen int ret;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen ctx->uidlist_sync_ctx =
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen maildir_uidlist_sync_init(ctx->ibox->uidlist, FALSE);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen if (maildir_scan_dir(ctx, TRUE) < 0)
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen return -1;
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen if (maildir_scan_dir(ctx, FALSE) < 0)
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen return -1;
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen ret = maildir_uidlist_sync_deinit(ctx->uidlist_sync_ctx);
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen ctx->uidlist_sync_ctx = NULL;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen return ret;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen}
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenint maildir_storage_sync_readonly(struct index_mailbox *ibox)
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen{
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen struct maildir_sync_context *ctx;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen int ret;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen ctx = maildir_sync_context_new(ibox);
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen ret = maildir_sync_context_readonly(ctx);
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen maildir_sync_deinit(ctx);
a10e5606a9e93f49cf13b3a35c8dc3f5d6ab5909Timo Sirainen return ret;
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen}
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainenint maildir_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags)
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen{
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen struct index_mailbox *ibox = (struct index_mailbox *)box;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen struct maildir_sync_context *ctx;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen int ret;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FAST) == 0 ||
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen ibox->sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <= ioloop_time) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ibox->sync_last_check = ioloop_time;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen ctx = maildir_sync_context_new(ibox);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = maildir_sync_context(ctx);
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen maildir_sync_deinit(ctx);
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (ret < 0)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return -1;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return index_storage_sync(box, flags);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen}
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen