buffy.c | 129 ++++++++++++++++++++++++++++++++++++++++++++------------------- 1 files changed, 90 insertions(+), 39 deletions(-)
# HG changeset patch # User Michael Elkins <[email protected]> # Date 1360173788 0 # Branch HEAD # Node ID af544d17195c25188170abbf2aa98342ad15c66c # Parent 1ea5c2a14309777bd7dbb8a348fbc3a558299ccb Check for unseen messages in the cur/ directory as well as new/. This makes the maildir detection identical to MH and IMAP. diff --git a/buffy.c b/buffy.c --- a/buffy.c +++ b/buffy.c @@ -37,6 +37,7 @@ #include <utime.h> #include <ctype.h> #include <unistd.h> +#include <errno.h> #include <stdio.h> @@ -292,53 +293,103 @@ DIR *dirp; struct dirent *de; char *p; - int rc = 0; struct stat sb; - mailbox->new = 0; + size_t j; + uint8_t changed = 0; + uint8_t recent = 0; - snprintf (path, sizeof (path), "%s/new", mailbox->path); + /* + * check the mtime on the new/ and cur/ directories to see what has changed since: + * 1) the last visit to the mailbox + * 2) since the last buffy check + */ + for (j=0; j<2; j++) + { + snprintf(path, sizeof(path), "%s/%s", mailbox->path, (j==0)?"new":"cur"); + if (stat(path, &sb) == -1) + { + dprint(1, (debugfile, "buffy_maildir_hasnew: stat(%s) errno %d: %s\n", path, errno, strerror(errno))); + mailbox->new = 0; + return 0; + } + /* check if the subdir has changed since the last scan */ + if (sb.st_mtime > BuffyDoneTime) + changed = 1; + /* check if the subdir has changed since the last visit */ + if (sb.st_mtime > mailbox->last_visited) + recent = 1; - /* when $mail_check_recent is set, if the new/ directory hasn't been modified since - * the user last exited the mailbox, then we know there is no recent mail. - */ - if (option(OPTMAILCHECKRECENT)) - { - if (stat(path, &sb) == 0 && sb.st_mtime < mailbox->last_visited) - return 0; + /* when $mark_old is set, never scan /cur */ + if (option(OPTMARKOLD)) + break; } - if ((dirp = opendir (path)) == NULL) + /* when $mail_check_recent is set, if the /new and /cur subdirs haven't been + * modified since the user last exited the mailbox, then we know there is no + * recent mail. + */ + if (recent == 0 && option(OPTMAILCHECKRECENT)) { - mailbox->magic = 0; - return 0; + mailbox->new = 0; + } + /* if neither subdir has changed, the previous status is still valid */ + else if (changed) + { + /* reset */ + mailbox->new = 0; + + /* + * loop over "new" and "cur" directories. if there is new mail in "new", + * we terminate the loop prior to scanning "cur". + */ + for (j = 0; mailbox->new == 0 && j < 2; j++) + { + snprintf(path, sizeof(path), "%s/%s", mailbox->path, (j == 0) ? "new" : "cur"); + + if ((dirp = opendir (path)) == NULL) + { + dprint(1, (debugfile, "buffy_maildir_hasnew: opendir(%s) errno %d: %s\n", path, errno, strerror(errno))); + mailbox->magic = 0; + mailbox->new = 0; + return 0; + } + + while ((de = readdir (dirp)) != NULL) + { + if (*de->d_name == '.') + continue; + + /* + * if the :info is missing (new mail) + * or + * message is unseen and not trashed (both S and T are missing) + */ + if (!(p = strstr (de->d_name, ":2,")) || (strpbrk(p+3, "ST") == NULL)) + { + if (option(OPTMAILCHECKRECENT)) + { + char msgpath[_POSIX_PATH_MAX]; + + snprintf(msgpath, sizeof(msgpath), "%s/%s", path, de->d_name); + /* ensure this message was received since leaving this mailbox */ + if (stat(msgpath, &sb) == 0 && (sb.st_ctime <= mailbox->last_visited)) + continue; + } + /* one new and undeleted message is enough */ + mailbox->new = 1; + break; + } + } + + closedir (dirp); + + /* when $mark_old is set, never scan /cur */ + if (option(OPTMARKOLD)) + break; + } } - while ((de = readdir (dirp)) != NULL) - { - if (*de->d_name == '.') - continue; - - if (!(p = strstr (de->d_name, ":2,")) || !strchr (p + 3, 'T')) - { - if (option(OPTMAILCHECKRECENT)) - { - char msgpath[_POSIX_PATH_MAX]; - - snprintf(msgpath, sizeof(msgpath), "%s/%s", path, de->d_name); - /* ensure this message was received since leaving this mailbox */ - if (stat(msgpath, &sb) == 0 && (sb.st_ctime <= mailbox->last_visited)) - continue; - } - /* one new and undeleted message is enough */ - mailbox->new = 1; - rc = 1; - break; - } - } - - closedir (dirp); - - return rc; + return mailbox->new; } /* returns 1 if mailbox has new mail */
