commit d34a9b7468bc53b4a55d1b553676ba3ba5638c35 Author: Oswald Buddenhagen <o...@kde.org> Date: Sat Aug 25 15:29:16 2012 +0200
deal with concurrent maildir modifications during listing files may be renamed (due to new -> cur transition or flag changes), which may lead to two effects if ignored: - we see both the old and the new name, so we report a spurious duplicate UID - we see neither name, so we report a spurious deletion as countermeasure, record and compare directory modification times. upon mismatch, we just start over - as usual. src/drv_maildir.c | 38 ++++++++++++++++++++++++++++++++++++++ src/isync.h | 1 + src/main.c | 3 +++ src/run-tests.pl | 2 +- 4 files changed, 43 insertions(+), 1 deletions(-) diff --git a/src/drv_maildir.c b/src/drv_maildir.c index 9d4a00e..24aae2d 100644 --- a/src/drv_maildir.c +++ b/src/drv_maildir.c @@ -507,6 +507,7 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist ) #endif /* USE_DB */ msg_t *entry; int i, j, uid, bl, fnl, ret; + time_t now, stamps[2]; struct stat st; char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX]; @@ -536,11 +537,32 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist ) } #endif /* USE_DB */ bl = nfsnprintf( buf, sizeof(buf) - 4, "%s/", ctx->gen.path ); + restat: + now = time( 0 ); + for (i = 0; i < 2; i++) { + memcpy( buf + bl, subdirs[i], 4 ); + if (stat( buf, &st )) { + sys_error( "Maildir error: cannot stat %s", buf ); + goto dfail; + } + if (st.st_mtime == now && !(DFlags & ZERODELAY)) { + /* If the modification happened during this second, we wouldn't be able to + * tell if there were further modifications during this second. So wait. + * This has the nice side effect that we wait for "batches" of changes to + * complete. On the downside, it can potentially block indefinitely. */ + info( "Maildir notice: sleeping due to recent directory modification.\n" ); + sleep( 1 ); /* FIXME: should make this async */ + goto restat; + } + stamps[i] = st.st_mtime; + } for (i = 0; i < 2; i++) { memcpy( buf + bl, subdirs[i], 4 ); if (!(d = opendir( buf ))) { sys_error( "Maildir error: cannot list %s", buf ); + rfail: maildir_free_scan( msglist ); + dfail: #ifdef USE_DB if (ctx->db) tdb->close( tdb, 0 ); @@ -600,6 +622,22 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist ) } closedir( d ); } + for (i = 0; i < 2; i++) { + memcpy( buf + bl, subdirs[i], 4 ); + if (stat( buf, &st )) { + sys_error( "Maildir error: cannot re-stat %s", buf ); + goto rfail; + } + if (st.st_mtime != stamps[i]) { + /* Somebody messed with the mailbox since we started listing it. */ +#ifdef USE_DB + if (ctx->db) + tdb->close( tdb, 0 ); +#endif /* USE_DB */ + maildir_free_scan( msglist ); + goto again; + } + } #ifdef USE_DB if (ctx->db) { if ((ret = ctx->db->cursor( ctx->db, 0, &dbc, 0 ))) diff --git a/src/isync.h b/src/isync.h index fa7d082..a39ab21 100644 --- a/src/isync.h +++ b/src/isync.h @@ -395,6 +395,7 @@ void cram( const char *challenge, const char *user, const char *pass, #define QUIET 8 #define VERYQUIET 16 #define KEEPJOURNAL 32 +#define ZERODELAY 64 extern int DFlags; diff --git a/src/main.c b/src/main.c index 85e3699..71470e6 100644 --- a/src/main.c +++ b/src/main.c @@ -437,6 +437,9 @@ main( int argc, char **argv ) case 'J': DFlags |= KEEPJOURNAL; break; + case 'Z': + DFlags |= ZERODELAY; + break; case 'v': version(); case 'h': diff --git a/src/run-tests.pl b/src/run-tests.pl index f2b4736..842e6e6 100755 --- a/src/run-tests.pl +++ b/src/run-tests.pl @@ -282,7 +282,7 @@ sub killcfg() sub runsync($) { # open FILE, "valgrind -q --log-fd=3 ../mbsync ".shift()." -c .mbsyncrc test 3>&2 2>&1 |"; - open FILE, "../mbsync -D ".shift()." -c .mbsyncrc test 2>&1 |"; + open FILE, "../mbsync -D -Z ".shift()." -c .mbsyncrc test 2>&1 |"; my @out = <FILE>; close FILE or push(@out, $! ? "*** error closing mbsync: $!\n" : "*** mbsync exited with signal ".($?&127).", code ".($?>>8)."\n"); return $?, @out; ------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ _______________________________________________ isync-devel mailing list isync-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/isync-devel