22 lock = (path ==
"" ?
"." : path) +
"/bincimap-scan-lock";
25 while ((lockfd = ::open(lock.c_str(),
26 O_CREAT | O_WRONLY | O_EXCL, 0666)) == -1) {
27 if (errno != EEXIST) {
29 <<
", " << string(strerror(errno)) << endl;
34 bincWarning <<
"waiting for mailbox lock " << lock <<
"." << endl;
35 if (lstat(lock.c_str(), &mystat) == 0) {
36 if ((time(0) - mystat.st_ctime) > 300) {
37 if (unlink(lock.c_str()) == 0)
continue;
38 else bincWarning <<
"failed to force mailbox lock: " << lock
39 <<
", " << string(strerror(errno)) << endl;
42 if (errno != ENOENT) {
43 string err =
"invalid lock " + lock +
": "
60 if (unlink(lock.c_str()) != 0)
61 bincWarning <<
"failed to unlock mailbox: " << lock <<
", "
62 << strerror(errno) << endl;
72 const string newpath = path +
"/new/";
73 const string curpath = path +
"/cur/";
74 const string cachepath = path +
"/bincimap-cache";
77 if (firstscan || forceScan) {
79 if (stat(newpath.c_str(), &oldstat) != 0) {
81 +
string(strerror(errno)));
85 old_new_st_mtime = oldstat.st_mtime;
86 old_new_st_ctime = oldstat.st_ctime;
88 if (stat(curpath.c_str(), &oldstat) != 0) {
90 +
string(strerror(errno)));
94 old_cur_st_mtime = oldstat.st_mtime;
95 old_cur_st_ctime = oldstat.st_ctime;
97 if (stat(cachepath.c_str(), &oldstat) == 0) {
98 old_bincimap_cache_st_mtime = oldstat.st_mtime;
99 old_bincimap_cache_st_ctime = oldstat.st_ctime;
101 old_bincimap_cache_st_mtime = 0;
102 old_bincimap_cache_st_ctime = 0;
105 struct stat oldcurstat;
106 struct stat oldnewstat;
107 struct stat oldbincimapcachestat;
108 if (stat(newpath.c_str(), &oldnewstat) != 0) {
110 +
string(strerror(errno)));
114 if (stat(curpath.c_str(), &oldcurstat) != 0) {
116 +
string(strerror(errno)));
120 if (stat(cachepath.c_str(), &oldbincimapcachestat) != 0) {
121 oldbincimapcachestat.st_ctime = 0;
122 oldbincimapcachestat.st_mtime = 0;
125 if (oldnewstat.st_mtime == old_new_st_mtime
126 && oldnewstat.st_ctime == old_new_st_ctime
127 && oldcurstat.st_mtime == old_cur_st_mtime
128 && oldcurstat.st_ctime == old_cur_st_ctime
129 && oldbincimapcachestat.st_mtime == old_bincimap_cache_st_mtime
130 && oldbincimapcachestat.st_ctime == old_bincimap_cache_st_ctime) {
134 old_bincimap_cache_st_mtime = oldbincimapcachestat.st_mtime;
135 old_bincimap_cache_st_ctime = oldbincimapcachestat.st_ctime;
136 old_cur_st_mtime = oldcurstat.st_mtime;
137 old_cur_st_ctime = oldcurstat.st_ctime;
138 old_new_st_mtime = oldnewstat.st_mtime;
139 old_new_st_ctime = oldnewstat.st_ctime;
156 old_cur_st_mtime = (time_t) 0;
157 old_cur_st_ctime = (time_t) 0;
158 old_new_st_mtime = (time_t) 0;
159 old_new_st_ctime = (time_t) 0;
162 mailboxchanged =
true;
169 DIR *pdir = opendir(newpath.c_str());
171 string reason =
"failed to open \"" + newpath +
"\" (";
172 reason += strerror(errno);
180 struct dirent *pdirent;
181 while ((pdirent = readdir(pdir)) != 0) {
187 string filename = pdirent->d_name;
188 if (filename[0] ==
'.'
189 || filename.find(
':') != string::npos
190 || filename.find(
'/') != string::npos)
193 string fullfilename = newpath + filename;
201 if (stat(fullfilename.c_str(), &mystat) != 0) {
202 if (errno == ENOENT) {
204 if (lstat(fullfilename.c_str(), &mystat) == 0) {
205 bincWarning <<
"dangling symlink: " << fullfilename << endl;
212 if ((pdir = opendir(newpath.c_str())) == 0) {
213 string reason =
"Warning: opendir(\"" + newpath +
"\") == 0 (";
214 reason += strerror(errno);
220 bincWarning <<
"junk in Maildir: \"" << fullfilename <<
"\": "
232 vector<MaildirMessage>::const_iterator newIt = newMessages.begin();
234 for (; newIt != newMessages.end(); ++newIt) {
235 if ((filename == (*newIt).getUnique())
242 if (!ours && ::time(0) <= mystat.st_mtime) {
243 old_cur_st_mtime = (time_t) 0;
244 old_cur_st_ctime = (time_t) 0;
245 old_new_st_mtime = (time_t) 0;
246 old_new_st_ctime = (time_t) 0;
251 string newName = curpath + pdirent->d_name;
252 if (rename((newpath + pdirent->d_name).c_str(),
253 (newName +
":2,").c_str()) != 0) {
254 bincWarning <<
"error moving messages from new to cur: skipping "
256 << pdirent->d_name <<
": " << strerror(errno) << endl;
268 for (; i !=
end(); ++i)
275 if ((pdir = opendir(curpath.c_str())) == 0) {
276 string reason =
"Maildir::scan::opendir(\"" + curpath +
"\") == 0 (";
277 reason += strerror(errno);
289 multimap<unsigned int, MaildirMessage> tempMessageMap;
292 while ((pdirent = readdir(pdir)) != 0) {
293 string filename = pdirent->d_name;
294 if (filename[0] ==
'.')
continue;
298 string::size_type pos;
299 if ((pos = filename.find(
':')) != string::npos) {
300 uniquename = filename.substr(0, pos);
301 string tmp = filename.substr(pos);
302 if ((pos = tmp.find(
"2,")) != string::npos)
303 standard = tmp.substr(pos + 2);
305 uniquename = filename;
308 for (string::const_iterator i = standard.begin();
309 i != standard.end(); ++i) {
323 if (!message || message->getInternalDate() == 0) {
324 string fullfilename = curpath + filename;
325 if (stat(fullfilename.c_str(), &mystat) != 0) {
326 if (errno == ENOENT) {
328 if (lstat(fullfilename.c_str(), &mystat) == 0) {
329 bincWarning <<
"dangling symlink: " << fullfilename << endl;
338 if ((pdir = opendir(newpath.c_str())) == 0) {
339 string reason =
"Warning: opendir(\"" + newpath +
"\") == 0 (";
340 reason += strerror(errno);
350 mailboxchanged =
true;
353 index.
insert(uniquename, 0, filename);
357 if (message->getInternalDate() == 0) {
358 mailboxchanged =
true;
359 message->setInternalDate(mystat.st_mtime);
363 message->setUnExpunged();
368 int oldflags = message->getStdFlags();
369 message->resetStdFlags();
385 tempMessageMap.insert(make_pair((
unsigned int) mystat.st_mtime, m));
387 mailboxchanged =
true;
394 int readonlyuidnext = uidnext;
395 multimap<unsigned int, MaildirMessage>::iterator i = tempMessageMap.begin();
396 while (i != tempMessageMap.end()) {
397 i->second.setUID(
readOnly ? readonlyuidnext++ : uidnext++);
398 multimap<unsigned int, MaildirMessage>::iterator itmp = i;
401 tempMessageMap.erase(i);
403 mailboxchanged =
true;
407 tempMessageMap.clear();
412 while (jj !=
end()) {
416 mailboxchanged =
true;
433 unsigned int lastuid = 0;
437 for (; ii !=
end(); ++ii) {
441 if (lastuid < message.
getUID())
442 lastuid = message.
getUID();
444 bincWarning <<
"UID values are not strictly ascending in this"
445 " mailbox: " << path <<
". This is usually caused by "
446 <<
"access from a broken accessor. Bumping UIDVALIDITY."
449 setLastError(
"An error occurred while scanning the mailbox. "
450 "Please contact your system administrator.");
454 old_cur_st_mtime = (time_t) 0;
455 old_cur_st_ctime = (time_t) 0;
456 old_new_st_mtime = (time_t) 0;
457 old_new_st_ctime = (time_t) 0;
470 mailboxchanged =
false;
Lock(const std::string &path)
void setLastError(const std::string &error) const
void bumpUidValidity(const std::string &) const
void add(MaildirMessage &m)
Mailbox::iterator end(void) const
ScanResult scan(bool forceScan=false)
ReadCacheResult readCache(void)
Mailbox::iterator begin(const SequenceSet &bset, unsigned int mod=INCLUDE_EXPUNGED|SQNR_MODE) const
MaildirMessage * get(const std::string &id)
void clearFileNames(void)
void insert(const std::string &unique, unsigned int uid, const std::string &fileName="")
The MaildirMessage class provides an interface for IMAP messages.
void setUnique(const std::string &s_in)
void setInternalDate(time_t internaldate)
unsigned char getInternalFlags(void) const
void setFlagsUnchanged(void)
void setUID(unsigned int uid)
unsigned int getUID(void) const
void setSize(unsigned int size)
bool isExpunged(void) const
void clearInternalFlag(unsigned char flags)
void setStdFlag(unsigned char flags)
static SequenceSet & all(void)
Declaration of the IODevice class.
Declaration of the IOFactory class.
Declaration of the Maildir class.