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 */ 

Reply via email to