]> granicus.if.org Git - neomutt/commitdiff
Convert context and buffy to use nanosecond timestamps.
authorKevin McCarthy <kevin@8t8.us>
Thu, 14 Jun 2018 08:17:56 +0000 (16:17 +0800)
committerRichard Russon <rich@flatcap.org>
Mon, 3 Sep 2018 01:04:32 +0000 (02:04 +0100)
The inotify interface has an unfortunate side effect of making Mutt
react too quickly to new mail.  Sometimes, the mail is only
half-delivered when the mailbox is checked.  Because Mutt is using the
stat mtime - seconds resolution - this means it won't realize there
are more messages delivered during the same second.

Nanosecond resolution fields were standardized in POSIX.1-2008, so
check for and use those if they are available.

auto.def
context.h
mailbox.c
mailbox.h
maildir/mh.c
mbox/mbox.c
mutt.h
muttlib.c
muttlib.h
mx.c
notmuch/mutt_notmuch.c

index 1c5b2bc4cb8fde11e2f40605e16be8e7573f1dda..ebd129bb39377cb6e905637c5380abba7c9481a8 100644 (file)
--- a/auto.def
+++ b/auto.def
@@ -270,6 +270,7 @@ if {1} {
     sysexits.h
 
   cc-check-functions \
+    clock_gettime \
     fgetc_unlocked \
     futimens \
     getaddrinfo \
@@ -277,12 +278,21 @@ if {1} {
     iswblank \
     mkdtemp \
     strsep \
+    utimesnsat \
     vasprintf \
     wcscasecmp
 
   cc-check-function-in-lib gethostent nsl
   cc-check-function-in-lib setsockopt socket
   cc-check-function-in-lib getaddrinfo_a anl
+
+  cc-with {-includes time.h} {
+    cc-check-types "struct timespec"
+  }
+
+  cc-with {-includes sys/stat.h} {
+    cc-check-members "struct stat.st_atim.tv_nsec"
+  }
 }
 ###############################################################################
 
index 6b02c2b8443b5e6847c630ccf369aa09dbb9ac14..6353f95e61ac0ca57efae06b22cf002f1f2b629d 100644 (file)
--- a/context.h
+++ b/context.h
@@ -56,8 +56,8 @@ struct Context
   char *path;
   char *realpath; /**< used for mailbox comparison and the sidebar */
   FILE *fp;
-  time_t atime;
-  time_t mtime;
+  struct timespec atime;
+  struct timespec mtime;
   off_t size;
   off_t vsize;
   char *pattern;                 /**< limit pattern string */
index 16a9e6f1c1f5b44c794ad2fee1cfc16d184cf424..7471fa4ed3a5f926b19529f3e14e5bfaaa8a6721 100644 (file)
--- a/mailbox.c
+++ b/mailbox.c
@@ -234,7 +234,8 @@ static int mailbox_maildir_check_dir(struct Mailbox *mailbox, const char *dir_na
    */
   if (check_new && MailCheckRecent)
   {
-    if (stat(path, &sb) == 0 && sb.st_mtime < mailbox->last_visited)
+    if (stat(path, &sb) == 0 &&
+        mutt_stat_timespec_compare(&sb, MUTT_STAT_MTIME, &mailbox->last_visited) < 0)
     {
       rc = 0;
       check_new = false;
@@ -276,8 +277,11 @@ static int mailbox_maildir_check_dir(struct Mailbox *mailbox, const char *dir_na
         {
           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))
+          if (stat(msgpath, &sb) == 0 &&
+              (mutt_stat_timespec_compare(&sb, MUTT_STAT_CTIME, &mailbox->last_visited) <= 0))
+          {
             continue;
+          }
         }
         mailbox->new = true;
         rc = 1;
@@ -337,14 +341,17 @@ static int mailbox_mbox_check(struct Mailbox *mailbox, struct stat *sb, bool che
     new_or_changed = (sb->st_size > mailbox->size);
   else
   {
-    new_or_changed = (sb->st_mtime > sb->st_atime) ||
-                     (mailbox->newly_created && (sb->st_ctime == sb->st_mtime) &&
-                      (sb->st_ctime == sb->st_atime));
+    new_or_changed =
+        (mutt_stat_compare(sb, MUTT_STAT_MTIME, sb, MUTT_STAT_ATIME) > 0) ||
+        (mailbox->newly_created &&
+         (mutt_stat_compare(sb, MUTT_STAT_CTIME, sb, MUTT_STAT_MTIME) == 0) &&
+         (mutt_stat_compare(sb, MUTT_STAT_CTIME, sb, MUTT_STAT_ATIME) == 0));
   }
 
   if (new_or_changed)
   {
-    if (!MailCheckRecent || sb->st_mtime > mailbox->last_visited)
+    if (!MailCheckRecent ||
+        (mutt_stat_timespec_compare(sb, MUTT_STAT_MTIME, &mailbox->last_visited) > 0))
     {
       rc = 1;
       mailbox->new = true;
@@ -359,7 +366,8 @@ static int mailbox_mbox_check(struct Mailbox *mailbox, struct stat *sb, bool che
   if (mailbox->newly_created && (sb->st_ctime != sb->st_mtime || sb->st_ctime != sb->st_atime))
     mailbox->newly_created = false;
 
-  if (check_stats && (mailbox->stats_last_checked < sb->st_mtime))
+  if (check_stats &&
+      (mutt_stat_timespec_compare(sb, MUTT_STAT_MTIME, &mailbox->stats_last_checked) > 0))
   {
     struct Context *ctx =
         mx_mbox_open(mailbox->path, MUTT_READONLY | MUTT_QUIET | MUTT_NOSORT | MUTT_PEEK);
@@ -531,7 +539,11 @@ static struct Mailbox *mailbox_get(const char *path)
  */
 void mutt_mailbox_cleanup(const char *path, struct stat *st)
 {
+#ifdef HAVE_UTIMENSAT
+  struct timespec ts[2];
+#else
   struct utimbuf ut;
+#endif
 
   if (CheckMboxSize)
   {
@@ -544,12 +556,30 @@ void mutt_mailbox_cleanup(const char *path, struct stat *st)
     /* fix up the times so mailbox won't get confused */
     if (st->st_mtime > st->st_atime)
     {
+#ifdef HAVE_UTIMENSAT
+      ts[0].tv_sec = 0;
+      ts[0].tv_nsec = UTIME_OMIT;
+      ts[1].tv_sec = 0;
+      ts[1].tv_nsec = UTIME_NOW;
+      utimensat(0, buf, ts, 0);
+#else
       ut.actime = st->st_atime;
       ut.modtime = time(NULL);
       utime(path, &ut);
+#endif
     }
     else
+    {
+#ifdef HAVE_UTIMENSAT
+      ts[0].tv_sec = 0;
+      ts[0].tv_nsec = UTIME_NOW;
+      ts[1].tv_sec = 0;
+      ts[1].tv_nsec = UTIME_NOW;
+      utimensat(0, buf, ts, 0);
+#else
       utime(path, NULL);
+#endif
+    }
   }
 }
 
@@ -917,7 +947,12 @@ void mutt_mailbox_setnotified(const char *path)
     return;
 
   mailbox->notified = true;
-  time(&mailbox->last_visited);
+#if HAVE_CLOCK_GETTIME
+  clock_gettime(CLOCK_REALTIME, &mailbox->last_visited);
+#else
+  mailbox->last_visited.tv_nsec = 0;
+  time(&mailbox->last_visited.tv_sec);
+#endif
 }
 
 /**
index 437a182c225a625d2fadc6c41d43b218ae2a3c10..64bc43c3f6690a098d559f88983751946afca8e8 100644 (file)
--- a/mailbox.h
+++ b/mailbox.h
@@ -56,15 +56,15 @@ struct Mailbox
   bool new; /**< mailbox has new mail */
 
   /* These next three are only set when MailCheckStats is set */
-  int msg_count;             /**< total number of messages */
-  int msg_unread;            /**< number of unread messages */
-  int msg_flagged;           /**< number of flagged messages */
+  int msg_count;   /**< total number of messages */
+  int msg_unread;  /**< number of unread messages */
+  int msg_flagged; /**< number of flagged messages */
 
   bool notified;             /**< user has been notified */
   enum MailboxType magic;    /**< mailbox type */
   bool newly_created;        /**< mbox or mmdf just popped into existence */
-  time_t last_visited;       /**< time of last exit from this mailbox */
-  time_t stats_last_checked; /**< mtime of mailbox the last time stats where checked. */
+  struct timespec last_visited; /**< time of last exit from this mailbox */
+  struct timespec stats_last_checked; /**< mtime of mailbox the last time stats where checked. */
 };
 
 /**
index 1e6109ce41b2722a0c5fe7cc3f5dc1cc5029cd15..b106ba1722d086d0b8367428975ec904c716f6eb 100644 (file)
@@ -105,7 +105,7 @@ struct MhSequences
  */
 struct MhData
 {
-  time_t mtime_cur;
+  struct timespec mtime_cur;
   mode_t mh_umask;
 };
 
@@ -300,7 +300,7 @@ static int mh_sequences_changed(struct Mailbox *b)
   if ((snprintf(path, sizeof(path), "%s/.mh_sequences", b->path) < sizeof(path)) &&
       (stat(path, &sb) == 0))
   {
-    return sb.st_mtime > b->last_visited;
+    return (mutt_stat_timespec_compare(&sb, MUTT_STAT_MTIME, &b->last_visited) > 0);
   }
   return -1;
 }
@@ -321,7 +321,7 @@ static int mh_already_notified(struct Mailbox *b, int msgno)
   if ((snprintf(path, sizeof(path), "%s/%d", b->path, msgno) < sizeof(path)) &&
       (stat(path, &sb) == 0))
   {
-    return sb.st_mtime <= b->last_visited;
+    return (mutt_stat_timespec_compare(&sb, MUTT_STAT_MTIME, &b->last_visited) <= 0);
   }
   return -1;
 }
@@ -853,20 +853,20 @@ static void maildir_update_mtime(struct Context *ctx)
   {
     snprintf(buf, sizeof(buf), "%s/%s", ctx->path, "cur");
     if (stat(buf, &st) == 0)
-      data->mtime_cur = st.st_mtime;
+      mutt_get_stat_timespec(&data->mtime_cur, &st, MUTT_STAT_MTIME);
     snprintf(buf, sizeof(buf), "%s/%s", ctx->path, "new");
   }
   else
   {
     snprintf(buf, sizeof(buf), "%s/.mh_sequences", ctx->path);
     if (stat(buf, &st) == 0)
-      data->mtime_cur = st.st_mtime;
+      mutt_get_stat_timespec(&data->mtime_cur, &st, MUTT_STAT_MTIME);
 
     mutt_str_strfcpy(buf, ctx->path, sizeof(buf));
   }
 
   if (stat(buf, &st) == 0)
-    ctx->mtime = st.st_mtime;
+    mutt_get_stat_timespec(&ctx->mtime, &st, MUTT_STAT_MTIME);
 }
 
 /**
@@ -2340,17 +2340,17 @@ static int maildir_mbox_check(struct Context *ctx, int *index_hint)
     return -1;
 
   /* determine which subdirectories need to be scanned */
-  if (st_new.st_mtime > ctx->mtime)
+  if (mutt_stat_timespec_compare(&st_new, MUTT_STAT_MTIME, &ctx->mtime) > 0)
     changed = 1;
-  if (st_cur.st_mtime > data->mtime_cur)
+  if (mutt_stat_timespec_compare(&st_cur, MUTT_STAT_MTIME, &data->mtime_cur) > 0)
     changed |= 2;
 
   if (!changed)
     return 0; /* nothing to do */
 
   /* update the modification times on the mailbox */
-  data->mtime_cur = st_cur.st_mtime;
-  ctx->mtime = st_new.st_mtime;
+  mutt_get_stat_timespec(&data->mtime_cur, &st_cur, MUTT_STAT_MTIME);
+  mutt_get_stat_timespec(&ctx->mtime, &st_new, MUTT_STAT_MTIME);
 
   /* do a fast scan of just the filenames in
    * the subdirectories that have changed.
@@ -2507,14 +2507,17 @@ static int mh_mbox_check(struct Context *ctx, int *index_hint)
   if (i == -1 && stat(buf, &st_cur) == -1)
     modified = true;
 
-  if (st.st_mtime > ctx->mtime || st_cur.st_mtime > data->mtime_cur)
+  if ((mutt_stat_timespec_compare(&st, MUTT_STAT_MTIME, &ctx->mtime) > 0) ||
+      (mutt_stat_timespec_compare(&st_cur, MUTT_STAT_MTIME, &data->mtime_cur) > 0))
+  {
     modified = true;
+  }
 
   if (!modified)
     return 0;
 
-  data->mtime_cur = st_cur.st_mtime;
-  ctx->mtime = st.st_mtime;
+  mutt_get_stat_timespec(&data->mtime_cur, &st_cur, MUTT_STAT_MTIME);
+  mutt_get_stat_timespec(&ctx->mtime, &st, MUTT_STAT_MTIME);
 
   md = NULL;
   last = &md;
index 71a6e3d360b8e9eebd33a492783f8de4559e7e78..9edfbc943d4b520aa69755493f473e89196b1086 100644 (file)
@@ -129,8 +129,8 @@ static int mmdf_parse_mailbox(struct Context *ctx)
     mutt_perror(ctx->path);
     return -1;
   }
-  ctx->atime = sb.st_atime;
-  ctx->mtime = sb.st_mtime;
+  mutt_get_stat_timespec(&ctx->atime, &sb, MUTT_STAT_ATIME);
+  mutt_get_stat_timespec(&ctx->mtime, &sb, MUTT_STAT_MTIME);
   ctx->size = sb.st_size;
 
   buf[sizeof(buf) - 1] = '\0';
@@ -291,8 +291,8 @@ static int mbox_parse_mailbox(struct Context *ctx)
   }
 
   ctx->size = sb.st_size;
-  ctx->mtime = sb.st_mtime;
-  ctx->atime = sb.st_atime;
+  mutt_get_stat_timespec(&ctx->mtime, &sb, MUTT_STAT_MTIME);
+  mutt_get_stat_timespec(&ctx->atime, &sb, MUTT_STAT_ATIME);
 
   if (!ctx->readonly)
     ctx->readonly = access(ctx->path, W_OK) ? true : false;
@@ -828,13 +828,14 @@ static int mbox_mbox_check(struct Context *ctx, int *index_hint)
 
   if (stat(ctx->path, &st) == 0)
   {
-    if (st.st_mtime == ctx->mtime && st.st_size == ctx->size)
+    if ((mutt_stat_timespec_compare(&st, MUTT_STAT_MTIME, &ctx->mtime) == 0) &&
+        st.st_size == ctx->size)
       return 0;
 
     if (st.st_size == ctx->size)
     {
       /* the file was touched, but it is still the same length, so just exit */
-      ctx->mtime = st.st_mtime;
+      mutt_get_stat_timespec(&ctx->mtime, &st, MUTT_STAT_MTIME);
       return 0;
     }
 
@@ -1386,10 +1387,17 @@ int mbox_path_probe(const char *path, const struct stat *st)
      * only the type was accessed.  This is important, because detection
      * of "new mail" depends on those times set correctly.
      */
+#ifdef HAVE_UTIMENSAT
+    struct timespec ts[2];
+    mutt_get_stat_timespec(&ts[0], &st, MUTT_STAT_ATIME);
+    mutt_get_stat_timespec(&ts[1], &st, MUTT_STAT_MTIME);
+    utimensat(0, path, ts, 0);
+#else
     struct utimbuf times;
     times.actime = st->st_atime;
     times.modtime = st->st_mtime;
     utime(path, &times);
+#endif
   }
 
   return magic;
diff --git a/mutt.h b/mutt.h
index 5acc5beba45170efb5977cafb78fbb15079b007b..21e7175a33b714c0cef4a1e2e218b29c1e279bde 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -54,6 +54,22 @@ struct Mapping;
 #define fgetc fgetc_unlocked
 #endif
 
+#ifndef HAVE_STRUCT_TIMESPEC
+struct timespec
+{
+  time_t tv_sec;
+  long tv_nsec;
+};
+#endif
+
+/* flags for mutt_get_stat_timespec */
+enum MuttStatType
+{
+  MUTT_STAT_ATIME,
+  MUTT_STAT_MTIME,
+  MUTT_STAT_CTIME
+};
+
 /* flags for mutt_enter_string_full() */
 #define MUTT_ALIAS    (1 << 0)  /**< do alias "completion" by calling up the alias-menu */
 #define MUTT_FILE     (1 << 1)  /**< do file completion */
index 045308daae39a2352fa44693c093cac2c751546c..cd01c77639ac94963fc876e825586ad92ff2bde4 100644 (file)
--- a/muttlib.c
+++ b/muttlib.c
@@ -1434,6 +1434,65 @@ void mutt_sleep(short s)
     sleep(s);
 }
 
+int mutt_timespec_compare(struct timespec *a, struct timespec *b)
+{
+  if (a->tv_sec < b->tv_sec)
+    return -1;
+  if (a->tv_sec > b->tv_sec)
+    return 1;
+
+  if (a->tv_nsec < b->tv_nsec)
+    return -1;
+  if (a->tv_nsec > b->tv_nsec)
+    return 1;
+  return 0;
+}
+
+void mutt_get_stat_timespec(struct timespec *dest, struct stat *sb, enum MuttStatType type)
+{
+  dest->tv_nsec = 0;
+
+  switch (type)
+  {
+    case MUTT_STAT_ATIME:
+      dest->tv_sec = sb->st_atime;
+#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
+      dest->tv_nsec = sb->st_atim.tv_nsec;
+#endif
+      break;
+    case MUTT_STAT_MTIME:
+      dest->tv_sec = sb->st_mtime;
+#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+      dest->tv_nsec = sb->st_mtim.tv_nsec;
+#endif
+      break;
+    case MUTT_STAT_CTIME:
+      dest->tv_sec = sb->st_ctime;
+#ifdef HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC
+      dest->tv_nsec = sb->st_ctim.tv_nsec;
+#endif
+      break;
+  }
+}
+
+int mutt_stat_timespec_compare(struct stat *sba, enum MuttStatType type, struct timespec *b)
+{
+  struct timespec a;
+
+  mutt_get_stat_timespec(&a, sba, type);
+  return mutt_timespec_compare(&a, b);
+}
+
+int mutt_stat_compare(struct stat *sba, enum MuttStatType sba_type,
+                      struct stat *sbb, enum MuttStatType sbb_type)
+{
+  struct timespec a, b;
+
+  mutt_get_stat_timespec(&a, sba, sba_type);
+  mutt_get_stat_timespec(&b, sbb, sbb_type);
+  return mutt_timespec_compare(&a, &b);
+}
+
 /**
  * mutt_make_version - Generate the NeoMutt version string
  * @retval ptr Version string
index ad5b17a12736ce2ca52dbcfa8cc91efd484d1da2..4fed3c50f730a8d5d653cc0a62337916eaef1dca 100644 (file)
--- a/muttlib.h
+++ b/muttlib.h
@@ -27,6 +27,7 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
+#include "mutt.h"
 #include "format_flags.h"
 
 struct Address;
@@ -65,6 +66,11 @@ int         mutt_save_confirm(const char *s, struct stat *st);
 void        mutt_save_path(char *d, size_t dsize, struct Address *a);
 void        mutt_sleep(short s);
 
+int mutt_timespec_compare(struct timespec *a, struct timespec *b);
+void mutt_get_stat_timespec(struct timespec *dest, struct stat *sb, enum MuttStatType type);
+int mutt_stat_timespec_compare(struct stat *sba, enum MuttStatType type, struct timespec *b);
+int mutt_stat_compare(struct stat *sba, enum MuttStatType sba_type, struct stat *sbb, enum MuttStatType sbb_type);
+
 #define mutt_mktemp(a, b)               mutt_mktemp_pfx_sfx(a, b, "neomutt", NULL)
 #define mutt_mktemp_pfx_sfx(a, b, c, d) mutt_mktemp_full(a, b, c, d, __FILE__, __LINE__)
 
diff --git a/mx.c b/mx.c
index b6e17c655c570f3f98b687ffd76968041024d6f4..57599e08a8f2d94cb2d14e5dc34caa574f4ca9e6 100644 (file)
--- a/mx.c
+++ b/mx.c
@@ -341,17 +341,27 @@ struct Context *mx_mbox_open(const char *path, int flags)
  */
 void mx_fastclose_mailbox(struct Context *ctx)
 {
+#ifdef HAVE_UTIMENSAT
+  struct timespec ts[2];
+#else
   struct utimbuf ut;
+#endif /* HAVE_UTIMENSAT */
 
   if (!ctx)
     return;
 
   /* fix up the times so mailbox won't get confused */
-  if (ctx->peekonly && ctx->path && (ctx->mtime > ctx->atime))
+  if (ctx->peekonly && ctx->path && (mutt_timespec_compare(&ctx->mtime, &ctx->atime) > 0))
   {
-    ut.actime = ctx->atime;
-    ut.modtime = ctx->mtime;
+#ifdef HAVE_UTIMENSAT
+    ts[0] = ctx->atime;
+    ts[1] = ctx->mtime;
+    utimensat(0, ctx->path, ts, 0);
+#else
+    ut.actime = ctx->atime.tv_sec;
+    ut.modtime = ctx->mtime.tv_sec;
     utime(ctx->path, &ut);
+#endif /* HAVE_UTIMENSAT */
   }
 
   /* never announce that a mailbox we've just left has new mail. #3290
index 135a1ecae31f3903e6aff674f2a2611379f83b04..c749464c6bb62189c6ff089a929e99118f8f8709 100644 (file)
@@ -1866,7 +1866,8 @@ int nm_read_entire_thread(struct Context *ctx, struct Header *h)
   notmuch_query_set_sort(q, NOTMUCH_SORT_NEWEST_FIRST);
 
   read_threads_query(ctx, q, true, 0);
-  ctx->mtime = time(NULL);
+  ctx->mtime.tv_sec = time(NULL);
+  ctx->mtime.tv_nsec = 0;
   rc = 0;
 
   if (ctx->msgcount > data->oldmsgcount)
@@ -2076,7 +2077,10 @@ done:
   if (!is_longrun(data))
     release_db(data);
   if (hdr->changed)
-    ctx->mtime = time(NULL);
+  {
+    ctx->mtime.tv_sec = time(NULL);
+    ctx->mtime.tv_nsec = 0;
+  }
   mutt_debug(1, "nm: tags modify done [rc=%d]\n", rc);
   return rc;
 }
@@ -2179,7 +2183,8 @@ int nm_update_filename(struct Context *ctx, const char *old, const char *new,
 
   if (!is_longrun(data))
     release_db(data);
-  ctx->mtime = time(NULL);
+  ctx->mtime.tv_sec = time(NULL);
+  ctx->mtime.tv_nsec = 0;
   return rc;
 }
 
@@ -2472,7 +2477,8 @@ static int nm_mbox_open(struct Context *ctx)
   if (!is_longrun(data))
     release_db(data);
 
-  ctx->mtime = time(NULL);
+  ctx->mtime.tv_sec = time(NULL);
+  ctx->mtime.tv_nsec = 0;
 
   mx_update_context(ctx, ctx->msgcount);
   data->oldmsgcount = 0;
@@ -2526,7 +2532,7 @@ static int nm_mbox_check(struct Context *ctx, int *index_hint)
   if (!data || (get_database_mtime(data, &mtime) != 0))
     return -1;
 
-  if (ctx->mtime >= mtime)
+  if (ctx->mtime.tv_sec >= mtime)
   {
     mutt_debug(2, "nm: check unnecessary (db=%lu ctx=%lu)\n", mtime, ctx->mtime);
     return 0;
@@ -2621,7 +2627,8 @@ done:
   if (!is_longrun(data))
     release_db(data);
 
-  ctx->mtime = time(NULL);
+  ctx->mtime.tv_sec = time(NULL);
+  ctx->mtime.tv_nsec = 0;
 
   mutt_debug(1, "nm: ... check done [count=%d, new_flags=%d, occult=%d]\n",
              ctx->msgcount, new_flags, occult);
@@ -2709,7 +2716,10 @@ static int nm_mbox_sync(struct Context *ctx, int *index_hint)
   if (!is_longrun(data))
     release_db(data);
   if (changed)
-    ctx->mtime = time(NULL);
+  {
+    ctx->mtime.tv_sec = time(NULL);
+    ctx->mtime.tv_nsec = 0;
+  }
 
   mutt_debug(1, "nm: .... sync done [rc=%d]\n", rc);
   return rc;