|
|
|
@ -273,6 +273,82 @@ maildir_validate( const char *prefix, const char *box, int create )
|
|
|
|
|
return DRV_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef USE_DB |
|
|
|
|
static void |
|
|
|
|
make_key( DBT *tkey, char *name ) |
|
|
|
|
{ |
|
|
|
|
char *u = strpbrk( name, ":," ); |
|
|
|
|
tkey->data = name; |
|
|
|
|
tkey->size = u ? (size_t)(u - name) : strlen( name ); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
maildir_set_uid( maildir_store_t *ctx, const char *name, int *uid ) |
|
|
|
|
{ |
|
|
|
|
int ret, uv[2]; |
|
|
|
|
|
|
|
|
|
if (uid) |
|
|
|
|
*uid = ++ctx->nuid; |
|
|
|
|
key.data = (void *)"UIDVALIDITY"; |
|
|
|
|
key.size = 11; |
|
|
|
|
uv[0] = ctx->gen.uidvalidity; |
|
|
|
|
uv[1] = ctx->nuid; |
|
|
|
|
value.data = uv; |
|
|
|
|
value.size = sizeof(uv); |
|
|
|
|
if ((ret = ctx->db->put( ctx->db, 0, &key, &value, 0 ))) { |
|
|
|
|
tbork: |
|
|
|
|
ctx->db->err( ctx->db, ret, "Maildir error: db->put()" ); |
|
|
|
|
bork: |
|
|
|
|
ctx->db->close( ctx->db, 0 ); |
|
|
|
|
ctx->db = 0; |
|
|
|
|
return DRV_BOX_BAD; |
|
|
|
|
} |
|
|
|
|
if (uid) { |
|
|
|
|
make_key( &key, (char *)name ); |
|
|
|
|
value.data = uid; |
|
|
|
|
value.size = sizeof(*uid); |
|
|
|
|
if ((ret = ctx->db->put( ctx->db, 0, &key, &value, 0 ))) |
|
|
|
|
goto tbork; |
|
|
|
|
} |
|
|
|
|
if ((ret = ctx->db->sync( ctx->db, 0 ))) { |
|
|
|
|
ctx->db->err( ctx->db, ret, "Maildir error: db->sync()" ); |
|
|
|
|
goto bork; |
|
|
|
|
} |
|
|
|
|
return DRV_OK; |
|
|
|
|
} |
|
|
|
|
#endif /* USE_DB */ |
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
maildir_store_uid( maildir_store_t *ctx ) |
|
|
|
|
{ |
|
|
|
|
int n; |
|
|
|
|
char buf[128]; |
|
|
|
|
|
|
|
|
|
n = sprintf( buf, "%d\n%d\n", ctx->gen.uidvalidity, ctx->nuid ); |
|
|
|
|
lseek( ctx->uvfd, 0, SEEK_SET ); |
|
|
|
|
if (write( ctx->uvfd, buf, n ) != n || ftruncate( ctx->uvfd, n )) { |
|
|
|
|
fprintf( stderr, "Maildir error: cannot write UIDVALIDITY.\n" ); |
|
|
|
|
return DRV_BOX_BAD; |
|
|
|
|
} |
|
|
|
|
return DRV_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
maildir_init_uid( maildir_store_t *ctx, const char *msg ) |
|
|
|
|
{ |
|
|
|
|
info( "Maildir notice: %s.\n", msg ? msg : "cannot read UIDVALIDITY, creating new" ); |
|
|
|
|
ctx->gen.uidvalidity = time( 0 ); |
|
|
|
|
ctx->nuid = 0; |
|
|
|
|
ctx->uvok = 0; |
|
|
|
|
#ifdef USE_DB |
|
|
|
|
if (ctx->db) { |
|
|
|
|
ctx->db->truncate( ctx->db, 0, 0 /* &u_int32_t_dummy */, 0 ); |
|
|
|
|
return maildir_set_uid( ctx, 0, 0 ); |
|
|
|
|
} |
|
|
|
|
#endif /* USE_DB */ |
|
|
|
|
return maildir_store_uid( ctx ); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
maildir_uidval_lock( maildir_store_t *ctx ) |
|
|
|
|
{ |
|
|
|
@ -297,10 +373,7 @@ maildir_uidval_lock( maildir_store_t *ctx )
|
|
|
|
|
lseek( ctx->uvfd, 0, SEEK_SET ); |
|
|
|
|
if ((n = read( ctx->uvfd, buf, sizeof(buf) )) <= 0 || |
|
|
|
|
(buf[n] = 0, sscanf( buf, "%d\n%d", &ctx->gen.uidvalidity, &ctx->nuid ) != 2)) { |
|
|
|
|
info( "Maildir notice: cannot read UIDVALIDITY, creating new.\n" ); |
|
|
|
|
ctx->gen.uidvalidity = time( 0 ); |
|
|
|
|
ctx->nuid = 0; |
|
|
|
|
ctx->uvok = 0; |
|
|
|
|
return maildir_init_uid( ctx, 0 ); |
|
|
|
|
} else |
|
|
|
|
ctx->uvok = 1; |
|
|
|
|
return DRV_OK; |
|
|
|
@ -318,61 +391,10 @@ maildir_uidval_unlock( maildir_store_t *ctx )
|
|
|
|
|
static int |
|
|
|
|
maildir_obtain_uid( maildir_store_t *ctx, int *uid ) |
|
|
|
|
{ |
|
|
|
|
int n; |
|
|
|
|
char buf[128]; |
|
|
|
|
|
|
|
|
|
*uid = ++ctx->nuid; |
|
|
|
|
n = sprintf( buf, "%d\n%d\n", ctx->gen.uidvalidity, ctx->nuid ); |
|
|
|
|
lseek( ctx->uvfd, 0, SEEK_SET ); |
|
|
|
|
if (write( ctx->uvfd, buf, n ) != n || ftruncate( ctx->uvfd, n )) { |
|
|
|
|
fprintf( stderr, "Maildir error: cannot write UIDVALIDITY.\n" ); |
|
|
|
|
return DRV_BOX_BAD; |
|
|
|
|
} |
|
|
|
|
return DRV_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef USE_DB |
|
|
|
|
static void |
|
|
|
|
make_key( DBT *tkey, char *name ) |
|
|
|
|
{ |
|
|
|
|
char *u = strpbrk( name, ":," ); |
|
|
|
|
tkey->data = name; |
|
|
|
|
tkey->size = u ? (size_t)(u - name) : strlen( name ); |
|
|
|
|
return maildir_store_uid( ctx ); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
maildir_set_uid( maildir_store_t *ctx, const char *name, int *uid ) |
|
|
|
|
{ |
|
|
|
|
int ret, uv[2]; |
|
|
|
|
|
|
|
|
|
*uid = ++ctx->nuid; |
|
|
|
|
key.data = (void *)"UIDVALIDITY"; |
|
|
|
|
key.size = 11; |
|
|
|
|
uv[0] = ctx->gen.uidvalidity; |
|
|
|
|
uv[1] = ctx->nuid; |
|
|
|
|
value.data = uv; |
|
|
|
|
value.size = sizeof(uv); |
|
|
|
|
if ((ret = ctx->db->put( ctx->db, 0, &key, &value, 0 ))) { |
|
|
|
|
tbork: |
|
|
|
|
ctx->db->err( ctx->db, ret, "Maildir error: db->put()" ); |
|
|
|
|
bork: |
|
|
|
|
ctx->db->close( ctx->db, 0 ); |
|
|
|
|
ctx->db = 0; |
|
|
|
|
return DRV_BOX_BAD; |
|
|
|
|
} |
|
|
|
|
make_key( &key, (char *)name ); |
|
|
|
|
value.data = uid; |
|
|
|
|
value.size = sizeof(*uid); |
|
|
|
|
if ((ret = ctx->db->put( ctx->db, 0, &key, &value, 0 ))) |
|
|
|
|
goto tbork; |
|
|
|
|
if ((ret = ctx->db->sync( ctx->db, 0 ))) { |
|
|
|
|
ctx->db->err( ctx->db, ret, "Maildir error: db->sync()" ); |
|
|
|
|
goto bork; |
|
|
|
|
} |
|
|
|
|
return DRV_OK; |
|
|
|
|
} |
|
|
|
|
#endif /* USE_DB */ |
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
maildir_compare( const void *l, const void *r ) |
|
|
|
|
{ |
|
|
|
@ -578,14 +600,10 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist )
|
|
|
|
|
entry = &msglist->ents[i]; |
|
|
|
|
if (entry->uid != INT_MAX) { |
|
|
|
|
if (uid == entry->uid) { |
|
|
|
|
info( "Maildir notice: duplicate UID; changing UIDVALIDITY.\n" ); |
|
|
|
|
ctx->gen.uidvalidity = time( 0 ); |
|
|
|
|
ctx->nuid = 0; |
|
|
|
|
ctx->uvok = 0; |
|
|
|
|
#ifdef USE_DB |
|
|
|
|
if (ctx->db) |
|
|
|
|
ctx->db->truncate( ctx->db, 0, 0 /* &u_int32_t_dummy */, 0 ); |
|
|
|
|
#endif /* USE_DB */ |
|
|
|
|
if ((ret = maildir_init_uid( ctx, "duplicate UID; changing UIDVALIDITY" )) != DRV_OK) { |
|
|
|
|
maildir_free_scan( msglist ); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
maildir_free_scan( msglist ); |
|
|
|
|
goto again; |
|
|
|
|
} |
|
|
|
@ -641,6 +659,7 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist )
|
|
|
|
|
entry->size = st.st_size; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
ctx->uvok = 1; |
|
|
|
|
} |
|
|
|
|
#ifdef USE_DB |
|
|
|
|
if (!ctx->db) |
|
|
|
@ -768,10 +787,8 @@ maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs )
|
|
|
|
|
ctx->db->err( ctx->db, ret, "Maildir error: db->get()" ); |
|
|
|
|
goto dbork; |
|
|
|
|
} |
|
|
|
|
info( "Maildir notice: cannot read UIDVALIDITY, creating new.\n" ); |
|
|
|
|
ctx->gen.uidvalidity = time( 0 ); |
|
|
|
|
ctx->nuid = 0; |
|
|
|
|
ctx->uvok = 0; |
|
|
|
|
if (maildir_init_uid( ctx, 0 ) != DRV_OK) |
|
|
|
|
goto dbork; |
|
|
|
|
} else { |
|
|
|
|
ctx->gen.uidvalidity = ((int *)value.data)[0]; |
|
|
|
|
ctx->nuid = ((int *)value.data)[1]; |
|
|
|
@ -1049,8 +1066,10 @@ maildir_trash_msg( store_t *gctx, message_t *gmsg )
|
|
|
|
|
return ret; |
|
|
|
|
if (!rename( buf, nbuf )) |
|
|
|
|
break; |
|
|
|
|
perror( nbuf ); |
|
|
|
|
return DRV_BOX_BAD; |
|
|
|
|
if (errno != ENOENT) { |
|
|
|
|
perror( nbuf ); |
|
|
|
|
return DRV_BOX_BAD; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if ((ret = maildir_again( ctx, msg, buf )) != DRV_OK) |
|
|
|
|
return ret; |
|
|
|
|