diff options
Diffstat (limited to 'src/maildir-scan.cc')
-rw-r--r-- | src/maildir-scan.cc | 191 |
1 files changed, 95 insertions, 96 deletions
diff --git a/src/maildir-scan.cc b/src/maildir-scan.cc index 4628d5b..2f3a9b4 100644 --- a/src/maildir-scan.cc +++ b/src/maildir-scan.cc @@ -4,16 +4,17 @@ * @author Andreas Aardal Hanssen * @date 2002-2005 * ----------------------------------------------------------------- **/ -#include <fcntl.h> -#include <dirent.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> - #include "iodevice.h" #include "iofactory.h" #include "maildir.h" +#include <errno.h> + +#include <dirent.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <unistd.h> + using namespace Binc; using namespace ::std; @@ -22,11 +23,9 @@ Lock::Lock(const string &path) lock = (path == "" ? "." : path) + "/bincimap-scan-lock"; int lockfd = -1; - while ((lockfd = ::open(lock.c_str(), - O_CREAT | O_WRONLY | O_EXCL, 0666)) == -1) { + while ((lockfd = ::open(lock.c_str(), O_CREAT | O_WRONLY | O_EXCL, 0666)) == -1) { if (errno != EEXIST) { - bincWarning << "unable to lock mailbox: " << lock - << ", " << string(strerror(errno)) << endl; + bincWarning << "unable to lock mailbox: " << lock << ", " << string(strerror(errno)) << endl; return; } @@ -34,14 +33,15 @@ Lock::Lock(const string &path) bincWarning << "waiting for mailbox lock " << lock << "." << endl; if (lstat(lock.c_str(), &mystat) == 0) { if ((time(0) - mystat.st_ctime) > 300) { - if (unlink(lock.c_str()) == 0) continue; - else bincWarning << "failed to force mailbox lock: " << lock - << ", " << string(strerror(errno)) << endl; + if (unlink(lock.c_str()) == 0) + continue; + else + bincWarning << "failed to force mailbox lock: " << lock << ", " << string(strerror(errno)) + << endl; } } else { if (errno != ENOENT) { - string err = "invalid lock " + lock + ": " - + strerror(errno); + string err = "invalid lock " + lock + ": " + strerror(errno); bincWarning << err << endl; return; } @@ -58,8 +58,7 @@ Lock::~Lock() { // remove the lock if (unlink(lock.c_str()) != 0) - bincWarning << "failed to unlock mailbox: " << lock << ", " - << strerror(errno) << endl; + bincWarning << "failed to unlock mailbox: " << lock << ", " << strerror(errno) << endl; } //------------------------------------------------------------------------ @@ -77,8 +76,7 @@ Maildir::ScanResult Maildir::scan(bool forceScan) if (firstscan || forceScan) { struct stat oldstat; if (stat(newpath.c_str(), &oldstat) != 0) { - setLastError("Invalid Mailbox, " + newpath + ": " - + string(strerror(errno))); + setLastError("Invalid Mailbox, " + newpath + ": " + string(strerror(errno))); return PermanentError; } @@ -86,8 +84,7 @@ Maildir::ScanResult Maildir::scan(bool forceScan) old_new_st_ctime = oldstat.st_ctime; if (stat(curpath.c_str(), &oldstat) != 0) { - setLastError("Invalid Mailbox, " + curpath + ": " - + string(strerror(errno))); + setLastError("Invalid Mailbox, " + curpath + ": " + string(strerror(errno))); return PermanentError; } @@ -106,14 +103,12 @@ Maildir::ScanResult Maildir::scan(bool forceScan) struct stat oldnewstat; struct stat oldbincimapcachestat; if (stat(newpath.c_str(), &oldnewstat) != 0) { - setLastError("Invalid Mailbox, " + newpath + ": " - + string(strerror(errno))); + setLastError("Invalid Mailbox, " + newpath + ": " + string(strerror(errno))); return PermanentError; } if (stat(curpath.c_str(), &oldcurstat) != 0) { - setLastError("Invalid Mailbox, " + curpath + ": " - + string(strerror(errno))); + setLastError("Invalid Mailbox, " + curpath + ": " + string(strerror(errno))); return PermanentError; } @@ -122,12 +117,11 @@ Maildir::ScanResult Maildir::scan(bool forceScan) oldbincimapcachestat.st_mtime = 0; } - if (oldnewstat.st_mtime == old_new_st_mtime - && oldnewstat.st_ctime == old_new_st_ctime - && oldcurstat.st_mtime == old_cur_st_mtime - && oldcurstat.st_ctime == old_cur_st_ctime + if (oldnewstat.st_mtime == old_new_st_mtime && oldnewstat.st_ctime == old_new_st_ctime + && oldcurstat.st_mtime == old_cur_st_mtime && oldcurstat.st_ctime == old_cur_st_ctime && oldbincimapcachestat.st_mtime == old_bincimap_cache_st_mtime - && oldbincimapcachestat.st_ctime == old_bincimap_cache_st_ctime) { + && oldbincimapcachestat.st_ctime == old_bincimap_cache_st_ctime) + { return Success; } @@ -148,21 +142,21 @@ Maildir::ScanResult Maildir::scan(bool forceScan) // changes to the depot across Binc IMAP instances that can not be // communicated via the depot itself. switch (readCache()) { - case NoCache: - case Error: + case NoCache: + case Error: // An error with reading the cache files when it's not the first // time we scan the depot is treated as an error. - if (!firstscan && !readOnly) { - old_cur_st_mtime = (time_t) 0; - old_cur_st_ctime = (time_t) 0; - old_new_st_mtime = (time_t) 0; - old_new_st_ctime = (time_t) 0; - return TemporaryError; - } - mailboxchanged = true; - break; - default: - break; + if (!firstscan && !readOnly) { + old_cur_st_mtime = (time_t)0; + old_cur_st_ctime = (time_t)0; + old_new_st_mtime = (time_t)0; + old_new_st_ctime = (time_t)0; + return TemporaryError; + } + mailboxchanged = true; + break; + default: + break; } // open new/ directory @@ -185,9 +179,7 @@ Maildir::ScanResult Maildir::scan(bool forceScan) // start with a dot. Do not try to extract information from unique // names." - The Maildir spec from cr.yp.to string filename = pdirent->d_name; - if (filename[0] == '.' - || filename.find(':') != string::npos - || filename.find('/') != string::npos) + if (filename[0] == '.' || filename.find(':') != string::npos || filename.find('/') != string::npos) continue; string fullfilename = newpath + filename; @@ -201,24 +193,23 @@ Maildir::ScanResult Maildir::scan(bool forceScan) if (stat(fullfilename.c_str(), &mystat) != 0) { if (errno == ENOENT) { // prevent looping due to stale symlinks - if (lstat(fullfilename.c_str(), &mystat) == 0) { - bincWarning << "dangling symlink: " << fullfilename << endl; + if (lstat(fullfilename.c_str(), &mystat) == 0) { + bincWarning << "dangling symlink: " << fullfilename << endl; continue; } - // a rare race between readdir and stat force us to restart the scan. + // a rare race between readdir and stat force us to restart the scan. closedir(pdir); if ((pdir = opendir(newpath.c_str())) == 0) { string reason = "Warning: opendir(\"" + newpath + "\") == 0 ("; - reason += strerror(errno); - reason += ")"; + reason += strerror(errno); + reason += ")"; setLastError(reason); return PermanentError; } } else - bincWarning << "junk in Maildir: \"" << fullfilename << "\": " - << strerror(errno); + bincWarning << "junk in Maildir: \"" << fullfilename << "\": " << strerror(errno); continue; } @@ -233,27 +224,26 @@ Maildir::ScanResult Maildir::scan(bool forceScan) bool ours = false; for (; newIt != newMessages.end(); ++newIt) { if ((filename == (*newIt).getUnique()) - && ((*newIt).getInternalFlags() & MaildirMessage::Committed)) { + && ((*newIt).getInternalFlags() & MaildirMessage::Committed)) + { ours = true; break; } } if (!ours && ::time(0) <= mystat.st_mtime) { - old_cur_st_mtime = (time_t) 0; - old_cur_st_ctime = (time_t) 0; - old_new_st_mtime = (time_t) 0; - old_new_st_ctime = (time_t) 0; + old_cur_st_mtime = (time_t)0; + old_cur_st_ctime = (time_t)0; + old_new_st_mtime = (time_t)0; + old_new_st_ctime = (time_t)0; continue; } // move files from new/ to cur/ string newName = curpath + pdirent->d_name; - if (rename((newpath + pdirent->d_name).c_str(), - (newName + ":2,").c_str()) != 0) { - bincWarning << "error moving messages from new to cur: skipping " - << newpath - << pdirent->d_name << ": " << strerror(errno) << endl; + if (rename((newpath + pdirent->d_name).c_str(), (newName + ":2,").c_str()) != 0) { + bincWarning << "error moving messages from new to cur: skipping " << newpath << pdirent->d_name + << ": " << strerror(errno) << endl; continue; } } @@ -263,8 +253,7 @@ Maildir::ScanResult Maildir::scan(bool forceScan) // Now, assume all known messages were expunged and have them prove // otherwise. { - Mailbox::iterator i = begin(SequenceSet::all(), - INCLUDE_EXPUNGED | SQNR_MODE); + Mailbox::iterator i = begin(SequenceSet::all(), INCLUDE_EXPUNGED | SQNR_MODE); for (; i != end(); ++i) (*i).setExpunged(); } @@ -274,8 +263,8 @@ Maildir::ScanResult Maildir::scan(bool forceScan) if ((pdir = opendir(curpath.c_str())) == 0) { string reason = "Maildir::scan::opendir(\"" + curpath + "\") == 0 ("; - reason += strerror(errno); - reason += ")"; + reason += strerror(errno); + reason += ")"; setLastError(reason); return PermanentError; @@ -299,22 +288,33 @@ Maildir::ScanResult Maildir::scan(bool forceScan) if ((pos = filename.find(':')) != string::npos) { uniquename = filename.substr(0, pos); string tmp = filename.substr(pos); - if ((pos = tmp.find("2,")) != string::npos) - standard = tmp.substr(pos + 2); + if ((pos = tmp.find("2,")) != string::npos) standard = tmp.substr(pos + 2); } else uniquename = filename; unsigned char mflags = Message::F_NONE; - for (string::const_iterator i = standard.begin(); - i != standard.end(); ++i) { + for (string::const_iterator i = standard.begin(); i != standard.end(); ++i) { switch (*i) { - case 'R': mflags |= Message::F_ANSWERED; break; - case 'S': mflags |= Message::F_SEEN; break; - case 'T': mflags |= Message::F_DELETED; break; - case 'D': mflags |= Message::F_DRAFT; break; - case 'F': mflags |= Message::F_FLAGGED; break; - case 'P': mflags |= Message::F_PASSED; break; - default: break; + case 'R': + mflags |= Message::F_ANSWERED; + break; + case 'S': + mflags |= Message::F_SEEN; + break; + case 'T': + mflags |= Message::F_DELETED; + break; + case 'D': + mflags |= Message::F_DRAFT; + break; + case 'F': + mflags |= Message::F_FLAGGED; + break; + case 'P': + mflags |= Message::F_PASSED; + break; + default: + break; } } @@ -325,31 +325,31 @@ Maildir::ScanResult Maildir::scan(bool forceScan) if (stat(fullfilename.c_str(), &mystat) != 0) { if (errno == ENOENT) { // prevent looping due to stale symlinks - if (lstat(fullfilename.c_str(), &mystat) == 0) { - bincWarning << "dangling symlink: " << fullfilename << endl; + if (lstat(fullfilename.c_str(), &mystat) == 0) { + bincWarning << "dangling symlink: " << fullfilename << endl; continue; } - // a rare race between readdir and stat force us to restart - // the scan. + // a rare race between readdir and stat force us to restart + // the scan. index.clearFileNames(); closedir(pdir); if ((pdir = opendir(newpath.c_str())) == 0) { string reason = "Warning: opendir(\"" + newpath + "\") == 0 ("; - reason += strerror(errno); - reason += ")"; + reason += strerror(errno); + reason += ")"; setLastError(reason); return PermanentError; } } - + continue; } mailboxchanged = true; } - + index.insert(uniquename, 0, filename); // If we have this message in memory already.. @@ -382,7 +382,7 @@ Maildir::ScanResult Maildir::scan(bool forceScan) m.setInternalDate(mystat.st_mtime); m.setStdFlag((mflags | Message::F_RECENT) & ~Message::F_EXPUNGED); m.setUnique(uniquename); - tempMessageMap.insert(make_pair((unsigned int) mystat.st_mtime, m)); + tempMessageMap.insert(make_pair((unsigned int)mystat.st_mtime, m)); mailboxchanged = true; } @@ -432,8 +432,7 @@ Maildir::ScanResult Maildir::scan(bool forceScan) if (firstscan) { unsigned int lastuid = 0; - Mailbox::iterator ii - = begin(SequenceSet::all(), INCLUDE_EXPUNGED | SQNR_MODE); + Mailbox::iterator ii = begin(SequenceSet::all(), INCLUDE_EXPUNGED | SQNR_MODE); for (; ii != end(); ++ii) { MaildirMessage &message = (MaildirMessage &)*ii; message.clearInternalFlag(MaildirMessage::JustArrived); @@ -442,19 +441,19 @@ Maildir::ScanResult Maildir::scan(bool forceScan) lastuid = message.getUID(); else { bincWarning << "UID values are not strictly ascending in this" - " mailbox: " << path << ". This is usually caused by " - << "access from a broken accessor. Bumping UIDVALIDITY." - << endl; + " mailbox: " + << path << ". This is usually caused by " + << "access from a broken accessor. Bumping UIDVALIDITY." << endl; setLastError("An error occurred while scanning the mailbox. " "Please contact your system administrator."); if (!readOnly) { bumpUidValidity(path); - old_cur_st_mtime = (time_t) 0; - old_cur_st_ctime = (time_t) 0; - old_new_st_mtime = (time_t) 0; - old_new_st_ctime = (time_t) 0; + old_cur_st_mtime = (time_t)0; + old_cur_st_ctime = (time_t)0; + old_new_st_mtime = (time_t)0; + old_new_st_ctime = (time_t)0; return TemporaryError; } else { return PermanentError; |