commit 7489ff8613bea88efa0d5987689063773d1f9078
Author: Oswald Buddenhagen <[email protected]>
Date: Mon Dec 29 02:01:23 2014 +0100
deal sensibly with incomplete maildir directories
a directory is no mailbox unless it contains a cur/ subdir.
but if that one is present, create new/ and tmp/ if they are missing.
this makes it possible to resume interrupted maildir creations.
src/drv_maildir.c | 85 +++++++++++++++++++++-----------------------
1 files changed, 41 insertions(+), 44 deletions(-)
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index dcc5fde..fee333e 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -68,7 +68,7 @@ typedef struct maildir_message {
typedef struct maildir_store {
store_t gen;
- int uvfd, uvok, nuid, fresh;
+ int uvfd, uvok, nuid, fresh[3];
int minuid, maxuid, newuid, nexcs, *excs;
char *trash;
#ifdef USE_DB
@@ -378,47 +378,48 @@ maildir_validate( const char *box, int create,
maildir_store_t *ctx )
bl = nfsnprintf( buf, sizeof(buf) - 4, "%s/", box );
if (stat( buf, &st )) {
- if (errno == ENOENT) {
- if (create) {
- p = memrchr( buf, '/', bl - 1 );
- if (*(p + 1) == '.') {
- *p = 0;
- if ((ret = maildir_validate( buf, 1,
ctx )) != DRV_OK)
- return ret;
- *p = '/';
- }
- if (mkdir( buf, 0700 )) {
- sys_error( "Maildir error: cannot
create mailbox '%s'", buf );
- maildir_invoke_bad_callback( &ctx->gen
);
- return DRV_CANCELED;
- }
- for (i = 0; i < 3; i++) {
- memcpy( buf + bl, subdirs[i], 4 );
- if (mkdir( buf, 0700 )) {
- sys_error( "Maildir error:
cannot create directory %s", buf );
- return DRV_BOX_BAD;
- }
- }
- } else {
- error( "Maildir error: mailbox '%s' does not
exist\n", buf );
- return DRV_BOX_BAD;
- }
- } else {
- sys_error( "Maildir error: cannot access mailbox '%s'",
buf );
+ if (errno != ENOENT) {
+ sys_error( "Maildir error: cannot access mailbox '%s'",
box );
return DRV_BOX_BAD;
}
- ctx->fresh = 1;
- } else {
- for (i = 0; i < 3; i++) {
- memcpy( buf + bl, subdirs[i], 4 );
- if (stat( buf, &st ) || !S_ISDIR(st.st_mode)) {
- error( "Maildir error: '%.*s' is no valid
mailbox\n", bl, buf );
+ if (!create)
+ return DRV_BOX_BAD;
+ p = memrchr( buf, '/', bl - 1 );
+ if (*(p + 1) == '.') {
+ *p = 0;
+ if ((ret = maildir_validate( buf, 1, ctx )) != DRV_OK)
+ return ret;
+ *p = '/';
+ }
+ if (mkdir( buf, 0700 )) {
+ sys_error( "Maildir error: cannot create mailbox '%s'",
box );
+ maildir_invoke_bad_callback( &ctx->gen );
+ return DRV_CANCELED;
+ }
+ } else if (!S_ISDIR(st.st_mode)) {
+ notdir:
+ error( "Maildir error: '%s' is no valid mailbox\n", box );
+ return DRV_BOX_BAD;
+ }
+ for (i = 0; i < 3; i++) {
+ memcpy( buf + bl, subdirs[i], 4 );
+ if (stat( buf, &st )) {
+ /* We always create new/ and tmp/ if they are missing.
cur/ is the presence indicator. */
+ if (!i && !create)
+ return DRV_BOX_BAD;
+ if (mkdir( buf, 0700 )) {
+ sys_error( "Maildir error: cannot create
directory %s", buf );
return DRV_BOX_BAD;
}
+ ctx->fresh[i] = 1;
+ } else if (!S_ISDIR(st.st_mode)) {
+ goto notdir;
+ } else {
+ if (i == 2) {
+ if ((ret = maildir_clear_tmp( buf, sizeof(buf),
bl )) != DRV_OK)
+ return ret;
+ }
}
- if ((ret = maildir_clear_tmp( buf, sizeof(buf), bl )) != DRV_OK)
- return ret;
- ctx->fresh = 0;
}
return DRV_OK;
}
@@ -676,7 +677,7 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist )
sys_error( "Maildir error: cannot stat %s", buf
);
goto dfail;
}
- if (st.st_mtime == now && !(DFlags & ZERODELAY)) {
+ if (st.st_mtime == now && !(DFlags & ZERODELAY) &&
!ctx->fresh[i]) {
/* 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
@@ -948,6 +949,7 @@ maildir_select_box( store_t *gctx, const char *name )
#ifdef USE_DB
ctx->db = 0;
#endif /* USE_DB */
+ ctx->fresh[0] = ctx->fresh[1] = 0;
if (starts_with( name, -1, "INBOX", 5 ) && (!name[5] || name[5] ==
'/')) {
gctx->path = maildir_join_path( ((maildir_store_conf_t
*)gctx->conf)->inbox, name + 5 );
} else {
@@ -1088,11 +1090,6 @@ maildir_load_box( store_t *gctx, int minuid, int maxuid,
int newuid, int *excs,
ctx->excs = nfrealloc( excs, nexcs * sizeof(int) );
ctx->nexcs = nexcs;
- if (ctx->fresh) {
- ctx->gen.count = ctx->gen.recent = 0;
- goto dontscan;
- }
-
if (maildir_scan( ctx, &msglist ) != DRV_OK) {
cb( DRV_BOX_BAD, aux );
return;
@@ -1102,7 +1099,6 @@ maildir_load_box( store_t *gctx, int minuid, int maxuid,
int newuid, int *excs,
maildir_app_msg( ctx, &msgapp, msglist.ents + i );
maildir_free_scan( &msglist );
- dontscan:
cb( DRV_OK, aux );
}
@@ -1114,6 +1110,7 @@ maildir_rescan( maildir_store_t *ctx )
msglist_t msglist;
int i;
+ ctx->fresh[0] = ctx->fresh[1] = 0;
if (maildir_scan( ctx, &msglist ) != DRV_OK)
return DRV_BOX_BAD;
for (msgapp = &ctx->gen.msgs, i = 0;
------------------------------------------------------------------------------
New Year. New Location. New Benefits. New Data Center in Ashburn, VA.
GigeNET is offering a free month of service with a new server in Ashburn.
Choose from 2 high performing configs, both with 100TB of bandwidth.
Higher redundancy.Lower latency.Increased capacity.Completely compliant.
http://p.sf.net/sfu/gigenet
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel