@ -68,7 +68,7 @@ typedef struct maildir_message {
typedef struct maildir_store {
typedef struct maildir_store {
store_t gen ;
store_t gen ;
int uvfd , uvok , nuid , fresh ;
int uvfd , uvok , nuid , fresh [ 3 ] ;
int minuid , maxuid , newuid , nexcs , * excs ;
int minuid , maxuid , newuid , nexcs , * excs ;
char * trash ;
char * trash ;
# ifdef USE_DB
# 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 ) ;
bl = nfsnprintf ( buf , sizeof ( buf ) - 4 , " %s/ " , box ) ;
if ( stat ( buf , & st ) ) {
if ( stat ( buf , & st ) ) {
if ( errno = = ENOENT ) {
if ( errno ! = ENOENT ) {
if ( create ) {
sys_error ( " Maildir error: cannot access mailbox '%s' " , box ) ;
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 ) ;
return DRV_BOX_BAD ;
return DRV_BOX_BAD ;
}
}
ctx - > fresh = 1 ;
if ( ! create )
} else {
return DRV_BOX_BAD ;
for ( i = 0 ; i < 3 ; i + + ) {
p = memrchr ( buf , ' / ' , bl - 1 ) ;
memcpy ( buf + bl , subdirs [ i ] , 4 ) ;
if ( * ( p + 1 ) = = ' . ' ) {
if ( stat ( buf , & st ) | | ! S_ISDIR ( st . st_mode ) ) {
* p = 0 ;
error ( " Maildir error: '%.*s' is no valid mailbox \n " , bl , buf ) ;
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 ;
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 ;
return DRV_OK ;
}
}
@ -676,7 +677,7 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist )
sys_error ( " Maildir error: cannot stat %s " , buf ) ;
sys_error ( " Maildir error: cannot stat %s " , buf ) ;
goto dfail ;
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
/* If the modification happened during this second, we wouldn't be able to
* tell if there were further modifications during this second . So wait .
* 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
* 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
# ifdef USE_DB
ctx - > db = 0 ;
ctx - > db = 0 ;
# endif /* USE_DB */
# endif /* USE_DB */
ctx - > fresh [ 0 ] = ctx - > fresh [ 1 ] = 0 ;
if ( starts_with ( name , - 1 , " INBOX " , 5 ) & & ( ! name [ 5 ] | | name [ 5 ] = = ' / ' ) ) {
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 ) ;
gctx - > path = maildir_join_path ( ( ( maildir_store_conf_t * ) gctx - > conf ) - > inbox , name + 5 ) ;
} else {
} 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 - > excs = nfrealloc ( excs , nexcs * sizeof ( int ) ) ;
ctx - > nexcs = nexcs ;
ctx - > nexcs = nexcs ;
if ( ctx - > fresh ) {
ctx - > gen . count = ctx - > gen . recent = 0 ;
goto dontscan ;
}
if ( maildir_scan ( ctx , & msglist ) ! = DRV_OK ) {
if ( maildir_scan ( ctx , & msglist ) ! = DRV_OK ) {
cb ( DRV_BOX_BAD , aux ) ;
cb ( DRV_BOX_BAD , aux ) ;
return ;
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_app_msg ( ctx , & msgapp , msglist . ents + i ) ;
maildir_free_scan ( & msglist ) ;
maildir_free_scan ( & msglist ) ;
dontscan :
cb ( DRV_OK , aux ) ;
cb ( DRV_OK , aux ) ;
}
}
@ -1114,6 +1110,7 @@ maildir_rescan( maildir_store_t *ctx )
msglist_t msglist ;
msglist_t msglist ;
int i ;
int i ;
ctx - > fresh [ 0 ] = ctx - > fresh [ 1 ] = 0 ;
if ( maildir_scan ( ctx , & msglist ) ! = DRV_OK )
if ( maildir_scan ( ctx , & msglist ) ! = DRV_OK )
return DRV_BOX_BAD ;
return DRV_BOX_BAD ;
for ( msgapp = & ctx - > gen . msgs , i = 0 ;
for ( msgapp = & ctx - > gen . msgs , i = 0 ;