fix error paths wrt sync drivers, take 2
synchronous error codes which are passed through callbacks aren't a particularly good idea, after all: latest when the callback does stuff which does not concern the caller, the return code becomes ambiguous. instead, protect the sync_vars object with a refcount when invoking driver functions from loops, as the callbacks they call could invalidate the object and we would have no way of knowing that the loop should be aborted prematurely. the upcoming async imap driver will also need a refcount to protect the cancelation marker of the imap socket dispatcher loop.
This commit is contained in:
parent
ec8f440383
commit
ea951a697f
|
@ -1554,9 +1554,9 @@ imap_prepare_opts( store_t *gctx, int opts )
|
|||
gctx->opts = opts;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
imap_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
|
||||
int (*cb)( int sts, void *aux ), void *aux )
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||
struct imap_cmd *cmd = new_imap_cmd();
|
||||
|
@ -1609,17 +1609,17 @@ imap_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
|
|||
|
||||
bail:
|
||||
free( excs );
|
||||
return cb( ret, aux );
|
||||
cb( ret, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
imap_fetch_msg( store_t *ctx, message_t *msg, msg_data_t *data,
|
||||
int (*cb)( int sts, void *aux ), void *aux )
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
struct imap_cmd *cmd = new_imap_cmd();
|
||||
cmd->param.uid = msg->uid;
|
||||
cmd->param.aux = data;
|
||||
return cb( imap_exec_m( (imap_store_t *)ctx, cmd, "UID FETCH %d (%sBODY.PEEK[])",
|
||||
cb( imap_exec_m( (imap_store_t *)ctx, cmd, "UID FETCH %d (%sBODY.PEEK[])",
|
||||
msg->uid, (msg->status & M_FLAGS) ? "" : "FLAGS " ), aux );
|
||||
}
|
||||
|
||||
|
@ -1652,9 +1652,9 @@ imap_flags_helper( imap_store_t *ctx, int uid, char what, int flags)
|
|||
return process_imap_replies( ctx ) == RESP_CANCEL ? DRV_CANCELED : DRV_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
imap_set_flags( store_t *gctx, message_t *msg, int uid, int add, int del,
|
||||
int (*cb)( int sts, void *aux ), void *aux )
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||
int ret;
|
||||
|
@ -1669,31 +1669,31 @@ imap_set_flags( store_t *gctx, message_t *msg, int uid, int add, int del,
|
|||
if ((!add || (ret = imap_flags_helper( ctx, uid, '+', add )) == DRV_OK) &&
|
||||
(!del || (ret = imap_flags_helper( ctx, uid, '-', del )) == DRV_OK))
|
||||
ret = DRV_OK;
|
||||
return cb( ret, aux );
|
||||
cb( ret, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
imap_close( store_t *ctx,
|
||||
int (*cb)( int sts, void *aux ), void *aux )
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
return cb( imap_exec_b( (imap_store_t *)ctx, 0, "CLOSE" ), aux );
|
||||
cb( imap_exec_b( (imap_store_t *)ctx, 0, "CLOSE" ), aux );
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
imap_trash_msg( store_t *gctx, message_t *msg,
|
||||
int (*cb)( int sts, void *aux ), void *aux )
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||
struct imap_cmd *cmd = new_imap_cmd();
|
||||
cmd->param.create = 1;
|
||||
cmd->param.to_trash = 1;
|
||||
return cb( imap_exec_m( ctx, cmd, "UID COPY %d \"%s%s\"",
|
||||
cb( imap_exec_m( ctx, cmd, "UID COPY %d \"%s%s\"",
|
||||
msg->uid, ctx->prefix, gctx->conf->trash ), aux );
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
||||
int (*cb)( int sts, int uid, void *aux ), void *aux )
|
||||
void (*cb)( int sts, int uid, void *aux ), void *aux )
|
||||
{
|
||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||
struct imap_cmd *cmd = new_imap_cmd();
|
||||
|
@ -1722,16 +1722,15 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
|||
box = gctx->name;
|
||||
prefix = !strcmp( box, "INBOX" ) ? "" : ctx->prefix;
|
||||
}
|
||||
ret = imap_exec_m( ctx, cmd, "APPEND \"%s%s\" %s", prefix, box, flagstr );
|
||||
if (ret != DRV_OK)
|
||||
return cb( ret, -1, aux );
|
||||
|
||||
return cb( DRV_OK, uid, aux );
|
||||
if ((ret = imap_exec_m( ctx, cmd, "APPEND \"%s%s\" %s", prefix, box, flagstr )) != DRV_OK)
|
||||
cb( ret, -1, aux );
|
||||
else
|
||||
cb( DRV_OK, uid, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
imap_find_msg( store_t *gctx, const char *tuid,
|
||||
int (*cb)( int sts, int uid, void *aux ), void *aux )
|
||||
void (*cb)( int sts, int uid, void *aux ), void *aux )
|
||||
{
|
||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||
struct imap_cmd *cmd = new_imap_cmd();
|
||||
|
@ -1741,9 +1740,9 @@ imap_find_msg( store_t *gctx, const char *tuid,
|
|||
cmd->param.aux = &uid;
|
||||
uid = -1; /* in case we get no SEARCH response at all */
|
||||
if ((ret = imap_exec_m( ctx, cmd, "UID SEARCH HEADER X-TUID %." stringify(TUIDL) "s", tuid )) != DRV_OK)
|
||||
return cb( ret, -1, aux );
|
||||
cb( ret, -1, aux );
|
||||
else
|
||||
return cb( uid <= 0 ? DRV_MSG_BAD : DRV_OK, uid, aux );
|
||||
cb( uid <= 0 ? DRV_MSG_BAD : DRV_OK, uid, aux );
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -771,9 +771,9 @@ maildir_prepare_opts( store_t *gctx, int opts )
|
|||
gctx->opts = opts;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
|
||||
int (*cb)( int sts, void *aux ), void *aux )
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
maildir_store_t *ctx = (maildir_store_t *)gctx;
|
||||
message_t **msgapp;
|
||||
|
@ -789,14 +789,17 @@ maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
|
|||
ctx->excs = nfrealloc( excs, nexcs * sizeof(int) );
|
||||
ctx->nexcs = nexcs;
|
||||
|
||||
if ((ret = maildir_validate( gctx->path, "", ctx->gen.opts & OPEN_CREATE, ctx )) != DRV_OK)
|
||||
return cb( ret, aux );
|
||||
if ((ret = maildir_validate( gctx->path, "", ctx->gen.opts & OPEN_CREATE, ctx )) != DRV_OK) {
|
||||
cb( ret, aux );
|
||||
return;
|
||||
}
|
||||
|
||||
nfsnprintf( uvpath, sizeof(uvpath), "%s/.uidvalidity", gctx->path );
|
||||
#ifndef USE_DB
|
||||
if ((ctx->uvfd = open( uvpath, O_RDWR|O_CREAT, 0600 )) < 0) {
|
||||
perror( uvpath );
|
||||
return cb( DRV_BOX_BAD, aux );
|
||||
cb( DRV_BOX_BAD, aux );
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if ((ctx->uvfd = open( uvpath, O_RDWR, 0600 )) < 0) {
|
||||
|
@ -811,7 +814,8 @@ maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
|
|||
goto fnok;
|
||||
}
|
||||
perror( uvpath );
|
||||
return cb( DRV_BOX_BAD, aux );
|
||||
cb( DRV_BOX_BAD, aux );
|
||||
return;
|
||||
}
|
||||
dbok:
|
||||
#if SEEK_SET != 0
|
||||
|
@ -823,7 +827,8 @@ maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
|
|||
bork:
|
||||
close( ctx->uvfd );
|
||||
ctx->uvfd = -1;
|
||||
return cb( DRV_BOX_BAD, aux );
|
||||
cb( DRV_BOX_BAD, aux );
|
||||
return;
|
||||
}
|
||||
if (db_create( &ctx->db, 0, 0 )) {
|
||||
fputs( "Maildir error: db_create() failed\n", stderr );
|
||||
|
@ -853,14 +858,16 @@ maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs,
|
|||
fnok:
|
||||
#endif /* USE_DB */
|
||||
|
||||
if (maildir_scan( ctx, &msglist ) != DRV_OK)
|
||||
return cb( DRV_BOX_BAD, aux );
|
||||
if (maildir_scan( ctx, &msglist ) != DRV_OK) {
|
||||
cb( DRV_BOX_BAD, aux );
|
||||
return;
|
||||
}
|
||||
msgapp = &ctx->gen.msgs;
|
||||
for (i = 0; i < msglist.nents; i++)
|
||||
maildir_app_msg( ctx, &msgapp, msglist.ents + i );
|
||||
maildir_free_scan( &msglist );
|
||||
|
||||
return cb( DRV_OK, aux );
|
||||
cb( DRV_OK, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -928,9 +935,9 @@ maildir_again( maildir_store_t *ctx, maildir_message_t *msg, const char *fn )
|
|||
return (msg->gen.status & M_DEAD) ? DRV_MSG_BAD : DRV_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
maildir_fetch_msg( store_t *gctx, message_t *gmsg, msg_data_t *data,
|
||||
int (*cb)( int sts, void *aux ), void *aux )
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
maildir_store_t *ctx = (maildir_store_t *)gctx;
|
||||
maildir_message_t *msg = (maildir_message_t *)gmsg;
|
||||
|
@ -942,8 +949,10 @@ maildir_fetch_msg( store_t *gctx, message_t *gmsg, msg_data_t *data,
|
|||
nfsnprintf( buf, sizeof(buf), "%s/%s/%s", gctx->path, subdirs[gmsg->status & M_RECENT], msg->base );
|
||||
if ((fd = open( buf, O_RDONLY )) >= 0)
|
||||
break;
|
||||
if ((ret = maildir_again( ctx, msg, buf )) != DRV_OK)
|
||||
return cb( ret, aux );
|
||||
if ((ret = maildir_again( ctx, msg, buf )) != DRV_OK) {
|
||||
cb( ret, aux );
|
||||
return;
|
||||
}
|
||||
}
|
||||
fstat( fd, &st );
|
||||
data->len = st.st_size;
|
||||
|
@ -951,12 +960,13 @@ maildir_fetch_msg( store_t *gctx, message_t *gmsg, msg_data_t *data,
|
|||
if (read( fd, data->data, data->len ) != data->len) {
|
||||
perror( buf );
|
||||
close( fd );
|
||||
return cb( DRV_MSG_BAD, aux );
|
||||
cb( DRV_MSG_BAD, aux );
|
||||
return;
|
||||
}
|
||||
close( fd );
|
||||
if (!(gmsg->status & M_FLAGS))
|
||||
data->flags = maildir_parse_flags( msg->base );
|
||||
return cb( DRV_OK, aux );
|
||||
cb( DRV_OK, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -974,9 +984,9 @@ maildir_make_flags( int flags, char *buf )
|
|||
return d;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
||||
int (*cb)( int sts, int uid, void *aux ), void *aux )
|
||||
void (*cb)( int sts, int uid, void *aux ), void *aux )
|
||||
{
|
||||
maildir_store_t *ctx = (maildir_store_t *)gctx;
|
||||
const char *prefix, *box;
|
||||
|
@ -989,14 +999,17 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
|||
if (ctx->db) {
|
||||
if ((ret = maildir_set_uid( ctx, base, &uid )) != DRV_OK) {
|
||||
free( data->data );
|
||||
return cb( ret, 0, aux );
|
||||
cb( ret, 0, aux );
|
||||
return;
|
||||
}
|
||||
} else
|
||||
#endif /* USE_DB */
|
||||
{
|
||||
if ((ret = maildir_uidval_lock( ctx )) != DRV_OK ||
|
||||
(ret = maildir_obtain_uid( ctx, &uid )) != DRV_OK)
|
||||
return cb( ret, 0, aux );
|
||||
(ret = maildir_obtain_uid( ctx, &uid )) != DRV_OK) {
|
||||
cb( ret, 0, aux );
|
||||
return;
|
||||
}
|
||||
maildir_uidval_unlock( ctx );
|
||||
nfsnprintf( base + bl, sizeof(base) - bl, ",U=%d", uid );
|
||||
}
|
||||
|
@ -1013,16 +1026,19 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
|||
if (errno != ENOENT) {
|
||||
perror( buf );
|
||||
free( data->data );
|
||||
return cb( DRV_BOX_BAD, 0, aux );
|
||||
cb( DRV_BOX_BAD, 0, aux );
|
||||
return;
|
||||
}
|
||||
if ((ret = maildir_validate( gctx->conf->path, gctx->conf->trash, gctx->opts & OPEN_CREATE, ctx )) != DRV_OK) {
|
||||
free( data->data );
|
||||
return cb( ret, 0, aux );
|
||||
cb( ret, 0, aux );
|
||||
return;
|
||||
}
|
||||
if ((fd = open( buf, O_WRONLY|O_CREAT|O_EXCL, 0600 )) < 0) {
|
||||
perror( buf );
|
||||
free( data->data );
|
||||
return cb( DRV_BOX_BAD, 0, aux );
|
||||
cb( DRV_BOX_BAD, 0, aux );
|
||||
return;
|
||||
}
|
||||
}
|
||||
ret = write( fd, data->data, data->len );
|
||||
|
@ -1033,38 +1049,43 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
|||
else
|
||||
error( "Maildir error: %s: partial write\n", buf );
|
||||
close( fd );
|
||||
return cb( DRV_BOX_BAD, 0, aux );
|
||||
cb( DRV_BOX_BAD, 0, aux );
|
||||
return;
|
||||
}
|
||||
if (close( fd ) < 0) {
|
||||
/* Quota exceeded may cause this. */
|
||||
perror( buf );
|
||||
return cb( DRV_BOX_BAD, 0, aux );
|
||||
cb( DRV_BOX_BAD, 0, aux );
|
||||
return;
|
||||
}
|
||||
/* Moving seen messages to cur/ is strictly speaking incorrect, but makes mutt happy. */
|
||||
nfsnprintf( nbuf, sizeof(nbuf), "%s%s/%s/%s%s", prefix, box, subdirs[!(data->flags & F_SEEN)], base, fbuf );
|
||||
if (rename( buf, nbuf )) {
|
||||
perror( nbuf );
|
||||
return cb( DRV_BOX_BAD, 0, aux );
|
||||
cb( DRV_BOX_BAD, 0, aux );
|
||||
return;
|
||||
}
|
||||
return cb( DRV_OK, uid, aux );
|
||||
cb( DRV_OK, uid, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
maildir_find_msg( store_t *gctx, const char *tuid,
|
||||
int (*cb)( int sts, int uid, void *aux ), void *aux )
|
||||
void (*cb)( int sts, int uid, void *aux ), void *aux )
|
||||
{
|
||||
message_t *msg;
|
||||
|
||||
/* using a hash table might turn out to be more appropriate ... */
|
||||
for (msg = gctx->msgs; msg; msg = msg->next)
|
||||
if (!(msg->status & M_DEAD) && !memcmp( ((maildir_message_t *)msg)->tuid, tuid, TUIDL ))
|
||||
return cb( DRV_OK, msg->uid, aux );
|
||||
return cb( DRV_MSG_BAD, -1, aux );
|
||||
if (!(msg->status & M_DEAD) && !memcmp( ((maildir_message_t *)msg)->tuid, tuid, TUIDL )) {
|
||||
cb( DRV_OK, msg->uid, aux );
|
||||
return;
|
||||
}
|
||||
cb( DRV_MSG_BAD, -1, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
maildir_set_flags( store_t *gctx, message_t *gmsg, int uid, int add, int del,
|
||||
int (*cb)( int sts, void *aux ), void *aux )
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
maildir_store_t *ctx = (maildir_store_t *)gctx;
|
||||
maildir_message_t *msg = (maildir_message_t *)gmsg;
|
||||
|
@ -1106,8 +1127,10 @@ maildir_set_flags( store_t *gctx, message_t *gmsg, int uid, int add, int del,
|
|||
}
|
||||
if (!rename( buf, nbuf ))
|
||||
break;
|
||||
if ((ret = maildir_again( ctx, msg, buf )) != DRV_OK)
|
||||
return cb( ret, aux );
|
||||
if ((ret = maildir_again( ctx, msg, buf )) != DRV_OK) {
|
||||
cb( ret, aux );
|
||||
return;
|
||||
}
|
||||
}
|
||||
free( msg->base );
|
||||
msg->base = nfmalloc( tl + 1 );
|
||||
|
@ -1116,7 +1139,7 @@ maildir_set_flags( store_t *gctx, message_t *gmsg, int uid, int add, int del,
|
|||
msg->gen.flags &= ~del;
|
||||
gmsg->status &= ~M_RECENT;
|
||||
|
||||
return cb( DRV_OK, aux );
|
||||
cb( DRV_OK, aux );
|
||||
}
|
||||
|
||||
#ifdef USE_DB
|
||||
|
@ -1136,9 +1159,9 @@ maildir_purge_msg( maildir_store_t *ctx, const char *name )
|
|||
}
|
||||
#endif /* USE_DB */
|
||||
|
||||
static int
|
||||
static void
|
||||
maildir_trash_msg( store_t *gctx, message_t *gmsg,
|
||||
int (*cb)( int sts, void *aux ), void *aux )
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
maildir_store_t *ctx = (maildir_store_t *)gctx;
|
||||
maildir_message_t *msg = (maildir_message_t *)gmsg;
|
||||
|
@ -1155,31 +1178,38 @@ maildir_trash_msg( store_t *gctx, message_t *gmsg,
|
|||
if (!rename( buf, nbuf ))
|
||||
break;
|
||||
if (!stat( buf, &st )) {
|
||||
if ((ret = maildir_validate( gctx->conf->path, gctx->conf->trash, 1, ctx )) != DRV_OK)
|
||||
return cb( ret, aux );
|
||||
if ((ret = maildir_validate( gctx->conf->path, gctx->conf->trash, 1, ctx )) != DRV_OK) {
|
||||
cb( ret, aux );
|
||||
return;
|
||||
}
|
||||
if (!rename( buf, nbuf ))
|
||||
break;
|
||||
if (errno != ENOENT) {
|
||||
perror( nbuf );
|
||||
return cb( DRV_BOX_BAD, aux );
|
||||
cb( DRV_BOX_BAD, aux );
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((ret = maildir_again( ctx, msg, buf )) != DRV_OK)
|
||||
return cb( ret, aux );
|
||||
if ((ret = maildir_again( ctx, msg, buf )) != DRV_OK) {
|
||||
cb( ret, aux );
|
||||
return;
|
||||
}
|
||||
}
|
||||
gmsg->status |= M_DEAD;
|
||||
gctx->count--;
|
||||
|
||||
#ifdef USE_DB
|
||||
if (ctx->db)
|
||||
return cb( maildir_purge_msg( ctx, msg->base ), aux );
|
||||
if (ctx->db) {
|
||||
cb( maildir_purge_msg( ctx, msg->base ), aux );
|
||||
return;
|
||||
}
|
||||
#endif /* USE_DB */
|
||||
return cb( DRV_OK, aux );
|
||||
cb( DRV_OK, aux );
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
maildir_close( store_t *gctx,
|
||||
int (*cb)( int sts, void *aux ), void *aux )
|
||||
void (*cb)( int sts, void *aux ), void *aux )
|
||||
{
|
||||
#ifdef USE_DB
|
||||
maildir_store_t *ctx = (maildir_store_t *)gctx;
|
||||
|
@ -1203,15 +1233,21 @@ maildir_close( store_t *gctx,
|
|||
msg->status |= M_DEAD;
|
||||
gctx->count--;
|
||||
#ifdef USE_DB
|
||||
if (ctx->db && (ret = maildir_purge_msg( ctx, ((maildir_message_t *)msg)->base )) != DRV_OK)
|
||||
return cb( ret, aux );
|
||||
if (ctx->db && (ret = maildir_purge_msg( ctx, ((maildir_message_t *)msg)->base )) != DRV_OK) {
|
||||
cb( ret, aux );
|
||||
return;
|
||||
}
|
||||
#endif /* USE_DB */
|
||||
}
|
||||
}
|
||||
if (!retry)
|
||||
return cb( DRV_OK, aux );
|
||||
if ((ret = maildir_rescan( (maildir_store_t *)gctx )) != DRV_OK)
|
||||
return cb( ret, aux );
|
||||
if (!retry) {
|
||||
cb( DRV_OK, aux );
|
||||
return;
|
||||
}
|
||||
if ((ret = maildir_rescan( (maildir_store_t *)gctx )) != DRV_OK) {
|
||||
cb( ret, aux );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
28
src/isync.h
28
src/isync.h
|
@ -210,20 +210,20 @@ struct driver {
|
|||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
void (*prepare_paths)( store_t *ctx );
|
||||
void (*prepare_opts)( store_t *ctx, int opts );
|
||||
int (*select)( store_t *ctx, int minuid, int maxuid, int *excs, int nexcs,
|
||||
int (*cb)( int sts, void *aux ), void *aux );
|
||||
int (*fetch_msg)( store_t *ctx, message_t *msg, msg_data_t *data,
|
||||
int (*cb)( int sts, void *aux ), void *aux );
|
||||
int (*store_msg)( store_t *ctx, msg_data_t *data, int to_trash,
|
||||
int (*cb)( int sts, int uid, void *aux ), void *aux );
|
||||
int (*find_msg)( store_t *ctx, const char *tuid,
|
||||
int (*cb)( int sts, int uid, void *aux ), void *aux );
|
||||
int (*set_flags)( store_t *ctx, message_t *msg, int uid, int add, int del, /* msg can be null, therefore uid as a fallback */
|
||||
int (*cb)( int sts, void *aux ), void *aux );
|
||||
int (*trash_msg)( store_t *ctx, message_t *msg, /* This may expunge the original message immediately, but it needn't to */
|
||||
int (*cb)( int sts, void *aux ), void *aux );
|
||||
int (*close)( store_t *ctx, /* IMAP-style: expunge inclusive */
|
||||
int (*cb)( int sts, void *aux ), void *aux );
|
||||
void (*select)( store_t *ctx, int minuid, int maxuid, int *excs, int nexcs,
|
||||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
void (*fetch_msg)( store_t *ctx, message_t *msg, msg_data_t *data,
|
||||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
void (*store_msg)( store_t *ctx, msg_data_t *data, int to_trash,
|
||||
void (*cb)( int sts, int uid, void *aux ), void *aux );
|
||||
void (*find_msg)( store_t *ctx, const char *tuid,
|
||||
void (*cb)( int sts, int uid, void *aux ), void *aux );
|
||||
void (*set_flags)( store_t *ctx, message_t *msg, int uid, int add, int del, /* msg can be null, therefore uid as a fallback */
|
||||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
void (*trash_msg)( store_t *ctx, message_t *msg, /* This may expunge the original message immediately, but it needn't to */
|
||||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
void (*close)( store_t *ctx, /* IMAP-style: expunge inclusive */
|
||||
void (*cb)( int sts, void *aux ), void *aux );
|
||||
void (*cancel)( store_t *ctx, /* only not yet sent commands */
|
||||
void (*cb)( void *aux ), void *aux );
|
||||
void (*commit)( store_t *ctx );
|
||||
|
|
226
src/sync.c
226
src/sync.c
|
@ -145,7 +145,7 @@ typedef struct {
|
|||
channel_conf_t *chan;
|
||||
store_t *ctx[2];
|
||||
driver_t *drv[2];
|
||||
int state[2], ret;
|
||||
int state[2], ref_count, ret;
|
||||
int find_old_total[2], find_old_done[2];
|
||||
int new_total[2], new_done[2];
|
||||
int find_new_total[2], find_new_done[2];
|
||||
|
@ -155,6 +155,26 @@ typedef struct {
|
|||
unsigned find:1;
|
||||
} sync_vars_t;
|
||||
|
||||
static void sync_ref( sync_vars_t *svars ) { ++svars->ref_count; }
|
||||
static int sync_deref( sync_vars_t *svars );
|
||||
static int deref_check_cancel( sync_vars_t *svars );
|
||||
static int check_cancel( sync_vars_t *svars );
|
||||
|
||||
#define DRIVER_CALL_RET(call) \
|
||||
do { \
|
||||
sync_ref( svars ); \
|
||||
svars->drv[t]->call; \
|
||||
return deref_check_cancel( svars ); \
|
||||
} while (0)
|
||||
|
||||
#define DRIVER_CALL(call) \
|
||||
do { \
|
||||
sync_ref( svars ); \
|
||||
svars->drv[t]->call; \
|
||||
if (deref_check_cancel( svars )) \
|
||||
return; \
|
||||
} while (0)
|
||||
|
||||
#define AUX &svars->t[t]
|
||||
#define DECL_SVARS \
|
||||
int t; \
|
||||
|
@ -192,27 +212,28 @@ typedef struct {
|
|||
|
||||
|
||||
typedef struct copy_vars {
|
||||
int (*cb)( int sts, int uid, struct copy_vars *vars );
|
||||
void (*cb)( int sts, int uid, struct copy_vars *vars );
|
||||
void *aux;
|
||||
sync_rec_t *srec; /* also ->tuid */
|
||||
message_t *msg;
|
||||
msg_data_t data;
|
||||
} copy_vars_t;
|
||||
|
||||
static int msg_fetched( int sts, void *aux );
|
||||
static void msg_fetched( int sts, void *aux );
|
||||
|
||||
static int
|
||||
copy_msg( copy_vars_t *vars )
|
||||
{
|
||||
DECL_INIT_SVARS(vars->aux);
|
||||
|
||||
t ^= 1;
|
||||
vars->data.flags = vars->msg->flags;
|
||||
return svars->drv[1-t]->fetch_msg( svars->ctx[1-t], vars->msg, &vars->data, msg_fetched, vars );
|
||||
DRIVER_CALL_RET(fetch_msg( svars->ctx[t], vars->msg, &vars->data, msg_fetched, vars ));
|
||||
}
|
||||
|
||||
static int msg_stored( int sts, int uid, void *aux );
|
||||
static void msg_stored( int sts, int uid, void *aux );
|
||||
|
||||
static int
|
||||
static void
|
||||
msg_fetched( int sts, void *aux )
|
||||
{
|
||||
copy_vars_t *vars = (copy_vars_t *)aux;
|
||||
|
@ -260,7 +281,8 @@ msg_fetched( int sts, void *aux )
|
|||
warn( "Warning: message %d from %s has incomplete header.\n",
|
||||
vars->msg->uid, str_ms[1-t] );
|
||||
free( fmap );
|
||||
return vars->cb( SYNC_NOGOOD, 0, vars );
|
||||
vars->cb( SYNC_NOGOOD, 0, vars );
|
||||
return;
|
||||
oke:
|
||||
extra += 8 + TUIDL + 1 + (tcr && (!scr || hcrs));
|
||||
}
|
||||
|
@ -327,17 +349,21 @@ msg_fetched( int sts, void *aux )
|
|||
free( fmap );
|
||||
}
|
||||
|
||||
return svars->drv[t]->store_msg( svars->ctx[t], &vars->data, !vars->srec, msg_stored, vars );
|
||||
svars->drv[t]->store_msg( svars->ctx[t], &vars->data, !vars->srec, msg_stored, vars );
|
||||
break;
|
||||
case DRV_CANCELED:
|
||||
return vars->cb( SYNC_CANCELED, 0, vars );
|
||||
vars->cb( SYNC_CANCELED, 0, vars );
|
||||
break;
|
||||
case DRV_MSG_BAD:
|
||||
return vars->cb( SYNC_NOGOOD, 0, vars );
|
||||
vars->cb( SYNC_NOGOOD, 0, vars );
|
||||
break;
|
||||
default:
|
||||
return vars->cb( SYNC_FAIL, 0, vars );
|
||||
vars->cb( SYNC_FAIL, 0, vars );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
msg_stored( int sts, int uid, void *aux )
|
||||
{
|
||||
copy_vars_t *vars = (copy_vars_t *)aux;
|
||||
|
@ -345,17 +371,21 @@ msg_stored( int sts, int uid, void *aux )
|
|||
|
||||
switch (sts) {
|
||||
case DRV_OK:
|
||||
return vars->cb( SYNC_OK, uid, vars );
|
||||
vars->cb( SYNC_OK, uid, vars );
|
||||
break;
|
||||
case DRV_CANCELED:
|
||||
return vars->cb( SYNC_CANCELED, 0, vars );
|
||||
vars->cb( SYNC_CANCELED, 0, vars );
|
||||
break;
|
||||
case DRV_MSG_BAD:
|
||||
INIT_SVARS(vars->aux);
|
||||
(void)svars;
|
||||
warn( "Warning: %s refuses to store message %d from %s.\n",
|
||||
str_ms[t], vars->msg->uid, str_ms[1-t] );
|
||||
return vars->cb( SYNC_NOGOOD, 0, vars );
|
||||
vars->cb( SYNC_NOGOOD, 0, vars );
|
||||
break;
|
||||
default:
|
||||
return vars->cb( SYNC_FAIL, 0, vars );
|
||||
vars->cb( SYNC_FAIL, 0, vars );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -433,6 +463,19 @@ store_bad( void *aux )
|
|||
cancel_sync( svars );
|
||||
}
|
||||
|
||||
static int
|
||||
deref_check_cancel( sync_vars_t *svars )
|
||||
{
|
||||
if (sync_deref( svars ))
|
||||
return -1;
|
||||
return check_cancel( svars );
|
||||
}
|
||||
|
||||
static int
|
||||
check_cancel( sync_vars_t *svars )
|
||||
{
|
||||
return (svars->state[M] | svars->state[S]) & (ST_SENT_CANCEL | ST_CANCELED);
|
||||
}
|
||||
|
||||
static int
|
||||
check_ret( int sts, void *aux )
|
||||
|
@ -454,7 +497,7 @@ check_ret( int sts, void *aux )
|
|||
#define SVARS_CHECK_RET \
|
||||
DECL_SVARS; \
|
||||
if (check_ret( sts, aux )) \
|
||||
return 1; \
|
||||
return; \
|
||||
INIT_SVARS(aux)
|
||||
|
||||
#define SVARS_CHECK_RET_VARS(type) \
|
||||
|
@ -462,7 +505,7 @@ check_ret( int sts, void *aux )
|
|||
DECL_SVARS; \
|
||||
if (check_ret( sts, vars->aux )) { \
|
||||
free( vars ); \
|
||||
return 1; \
|
||||
return; \
|
||||
} \
|
||||
INIT_SVARS(vars->aux)
|
||||
|
||||
|
@ -470,7 +513,7 @@ check_ret( int sts, void *aux )
|
|||
DECL_SVARS; \
|
||||
if (sts == SYNC_CANCELED) { \
|
||||
free( vars ); \
|
||||
return 1; \
|
||||
return; \
|
||||
} \
|
||||
INIT_SVARS(vars->aux)
|
||||
|
||||
|
@ -508,6 +551,7 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan,
|
|||
|
||||
svars = nfcalloc( sizeof(*svars) );
|
||||
svars->t[1] = 1;
|
||||
svars->ref_count = 1;
|
||||
svars->cb = cb;
|
||||
svars->aux = aux;
|
||||
svars->ctx[0] = ctx[0];
|
||||
|
@ -830,7 +874,7 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan,
|
|||
select_box( svars, S, (ctx[S]->opts & OPEN_OLD) ? 1 : INT_MAX, 0, 0 );
|
||||
}
|
||||
|
||||
static int box_selected( int sts, void *aux );
|
||||
static void box_selected( int sts, void *aux );
|
||||
|
||||
static int
|
||||
select_box( sync_vars_t *svars, int t, int minwuid, int *mexcs, int nmexcs )
|
||||
|
@ -851,7 +895,7 @@ select_box( sync_vars_t *svars, int t, int minwuid, int *mexcs, int nmexcs )
|
|||
maxwuid = 0;
|
||||
info( "Selecting %s %s...\n", str_ms[t], svars->ctx[t]->name );
|
||||
debug( maxwuid == INT_MAX ? "selecting %s [%d,inf]\n" : "selecting %s [%d,%d]\n", str_ms[t], minwuid, maxwuid );
|
||||
return svars->drv[t]->select( svars->ctx[t], minwuid, maxwuid, mexcs, nmexcs, box_selected, AUX );
|
||||
DRIVER_CALL_RET(select( svars->ctx[t], minwuid, maxwuid, mexcs, nmexcs, box_selected, AUX ));
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
@ -859,10 +903,10 @@ typedef struct {
|
|||
sync_rec_t *srec;
|
||||
} find_vars_t;
|
||||
|
||||
static int msg_found_sel( int sts, int uid, void *aux );
|
||||
static int msgs_found_sel( sync_vars_t *svars, int t );
|
||||
static void msg_found_sel( int sts, int uid, void *aux );
|
||||
static void msgs_found_sel( sync_vars_t *svars, int t );
|
||||
|
||||
static int
|
||||
static void
|
||||
box_selected( int sts, void *aux )
|
||||
{
|
||||
find_vars_t *fv;
|
||||
|
@ -874,7 +918,7 @@ box_selected( int sts, void *aux )
|
|||
str_ms[t], svars->ctx[t]->uidvalidity, svars->uidval[t] );
|
||||
svars->ret |= SYNC_FAIL;
|
||||
cancel_sync( svars );
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
info( "%s: %d messages, %d recent\n", str_ms[t], svars->ctx[t]->count, svars->ctx[t]->recent );
|
||||
|
||||
|
@ -897,16 +941,15 @@ box_selected( int sts, void *aux )
|
|||
fv = nfmalloc( sizeof(*fv) );
|
||||
fv->aux = AUX;
|
||||
fv->srec = srec;
|
||||
if (svars->drv[t]->find_msg( svars->ctx[t], srec->tuid, msg_found_sel, fv ))
|
||||
return 1;
|
||||
DRIVER_CALL(find_msg( svars->ctx[t], srec->tuid, msg_found_sel, fv ));
|
||||
}
|
||||
}
|
||||
}
|
||||
svars->state[t] |= ST_SENT_FIND_OLD;
|
||||
return msgs_found_sel( svars, t );
|
||||
msgs_found_sel( svars, t );
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
msg_found_sel( int sts, int uid, void *aux )
|
||||
{
|
||||
SVARS_CHECK_RET_VARS(find_vars_t);
|
||||
|
@ -927,7 +970,7 @@ msg_found_sel( int sts, int uid, void *aux )
|
|||
free( vars );
|
||||
svars->find_old_done[t]++;
|
||||
stats( svars );
|
||||
return msgs_found_sel( svars, t );
|
||||
msgs_found_sel( svars, t );
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
@ -936,15 +979,15 @@ typedef struct {
|
|||
int aflags, dflags;
|
||||
} flag_vars_t;
|
||||
|
||||
static int flags_set_del( int sts, void *aux );
|
||||
static int flags_set_sync( int sts, void *aux );
|
||||
static void flags_set_del( int sts, void *aux );
|
||||
static void flags_set_sync( int sts, void *aux );
|
||||
static void flags_set_sync_p2( sync_vars_t *svars, sync_rec_t *srec, int t );
|
||||
static int msgs_flags_set( sync_vars_t *svars, int t );
|
||||
static int msg_copied( int sts, int uid, copy_vars_t *vars );
|
||||
static void msg_copied( int sts, int uid, copy_vars_t *vars );
|
||||
static void msg_copied_p2( sync_vars_t *svars, sync_rec_t *srec, int t, message_t *tmsg, int uid );
|
||||
static int msgs_copied( sync_vars_t *svars, int t );
|
||||
static void msgs_copied( sync_vars_t *svars, int t );
|
||||
|
||||
static int
|
||||
static void
|
||||
msgs_found_sel( sync_vars_t *svars, int t )
|
||||
{
|
||||
sync_rec_t *srec, *nsrec = 0;
|
||||
|
@ -957,7 +1000,7 @@ msgs_found_sel( sync_vars_t *svars, int t )
|
|||
char fbuf[16]; /* enlarge when support for keywords is added */
|
||||
|
||||
if (!(svars->state[t] & ST_SENT_FIND_OLD) || svars->find_old_done[t] < svars->find_old_total[t])
|
||||
return 0;
|
||||
return;
|
||||
|
||||
/*
|
||||
* Mapping tmsg -> srec (this variant) is dog slow for new messages.
|
||||
|
@ -1053,11 +1096,12 @@ msgs_found_sel( sync_vars_t *svars, int t )
|
|||
for (t = 0; t < nmexcs; t++)
|
||||
debugn( " %d", mexcs[t] );
|
||||
debug( "\n" );
|
||||
return select_box( svars, M, minwuid, mexcs, nmexcs );
|
||||
select_box( svars, M, minwuid, mexcs, nmexcs );
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(svars->state[1-t] & ST_SENT_FIND_OLD) || svars->find_old_done[1-t] < svars->find_old_total[1-t])
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if (svars->uidval[M] < 0 || svars->uidval[S] < 0) {
|
||||
svars->uidval[M] = svars->ctx[M]->uidvalidity;
|
||||
|
@ -1113,7 +1157,7 @@ msgs_found_sel( sync_vars_t *svars, int t )
|
|||
Fprintf( svars->jfp, "# %d %d %." stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], srec->tuid );
|
||||
debug( " -> %sing message, TUID %." stringify(TUIDL) "s\n", str_hl[t], srec->tuid );
|
||||
if (copy_msg( cv ))
|
||||
return 1;
|
||||
return;
|
||||
} else {
|
||||
if (tmsg->srec) {
|
||||
debug( " -> not %sing - still too big\n", str_hl[t] );
|
||||
|
@ -1125,8 +1169,7 @@ msgs_found_sel( sync_vars_t *svars, int t )
|
|||
}
|
||||
}
|
||||
svars->state[t] |= ST_SENT_NEW;
|
||||
if (msgs_copied( svars, t ))
|
||||
return 1;
|
||||
msgs_copied( svars, t );
|
||||
}
|
||||
|
||||
debug( "synchronizing old entries\n" );
|
||||
|
@ -1164,8 +1207,7 @@ msgs_found_sel( sync_vars_t *svars, int t )
|
|||
fv = nfmalloc( sizeof(*fv) );
|
||||
fv->aux = AUX;
|
||||
fv->srec = srec;
|
||||
if (svars->drv[t]->set_flags( svars->ctx[t], srec->msg[t], srec->uid[t], F_DELETED, 0, flags_set_del, fv ))
|
||||
return 1;
|
||||
DRIVER_CALL(set_flags( svars->ctx[t], srec->msg[t], srec->uid[t], F_DELETED, 0, flags_set_del, fv ));
|
||||
} else
|
||||
debug( " not %sing delete\n", str_hl[t] );
|
||||
} else if (!srec->msg[1-t])
|
||||
|
@ -1275,8 +1317,7 @@ msgs_found_sel( sync_vars_t *svars, int t )
|
|||
fv->srec = srec;
|
||||
fv->aflags = aflags;
|
||||
fv->dflags = dflags;
|
||||
if (svars->drv[t]->set_flags( svars->ctx[t], srec->msg[t], srec->uid[t], aflags, dflags, flags_set_sync, fv ))
|
||||
return 1;
|
||||
DRIVER_CALL(set_flags( svars->ctx[t], srec->msg[t], srec->uid[t], aflags, dflags, flags_set_sync, fv ));
|
||||
} else
|
||||
flags_set_sync_p2( svars, srec, t );
|
||||
}
|
||||
|
@ -1285,12 +1326,11 @@ msgs_found_sel( sync_vars_t *svars, int t )
|
|||
svars->drv[t]->commit( svars->ctx[t] );
|
||||
svars->state[t] |= ST_SENT_FLAGS;
|
||||
if (msgs_flags_set( svars, t ))
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
msg_copied( int sts, int uid, copy_vars_t *vars )
|
||||
{
|
||||
SVARS_CHECK_CANCEL_RET;
|
||||
|
@ -1306,12 +1346,12 @@ msg_copied( int sts, int uid, copy_vars_t *vars )
|
|||
default:
|
||||
cancel_sync( svars );
|
||||
free( vars );
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
free( vars );
|
||||
svars->new_done[t]++;
|
||||
stats( svars );
|
||||
return msgs_copied( svars, t );
|
||||
msgs_copied( svars, t );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1332,17 +1372,17 @@ msg_copied_p2( sync_vars_t *svars, sync_rec_t *srec, int t, message_t *tmsg, int
|
|||
}
|
||||
}
|
||||
|
||||
static int msg_found_new( int sts, int uid, void *aux );
|
||||
static int sync_close( sync_vars_t *svars, int t );
|
||||
static void msg_found_new( int sts, int uid, void *aux );
|
||||
static void sync_close( sync_vars_t *svars, int t );
|
||||
|
||||
static int
|
||||
static void
|
||||
msgs_copied( sync_vars_t *svars, int t )
|
||||
{
|
||||
sync_rec_t *srec;
|
||||
find_vars_t *fv;
|
||||
|
||||
if (!(svars->state[t] & ST_SENT_NEW) || svars->new_done[t] < svars->new_total[t])
|
||||
return 0;
|
||||
return;
|
||||
|
||||
debug( "finding just copied messages on %s\n", str_ms[t] );
|
||||
for (srec = svars->srecs; srec; srec = srec->next) {
|
||||
|
@ -1355,15 +1395,14 @@ msgs_copied( sync_vars_t *svars, int t )
|
|||
fv = nfmalloc( sizeof(*fv) );
|
||||
fv->aux = AUX;
|
||||
fv->srec = srec;
|
||||
if (svars->drv[t]->find_msg( svars->ctx[t], srec->tuid, msg_found_new, fv ))
|
||||
return 1;
|
||||
DRIVER_CALL(find_msg( svars->ctx[t], srec->tuid, msg_found_new, fv ));
|
||||
}
|
||||
}
|
||||
svars->state[t] |= ST_SENT_FIND_NEW;
|
||||
return sync_close( svars, t );
|
||||
sync_close( svars, t );
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
msg_found_new( int sts, int uid, void *aux )
|
||||
{
|
||||
SVARS_CHECK_RET_VARS(find_vars_t);
|
||||
|
@ -1382,10 +1421,10 @@ msg_found_new( int sts, int uid, void *aux )
|
|||
free( vars );
|
||||
svars->find_new_done[t]++;
|
||||
stats( svars );
|
||||
return sync_close( svars, t );
|
||||
sync_close( svars, t );
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
flags_set_del( int sts, void *aux )
|
||||
{
|
||||
SVARS_CHECK_RET_VARS(flag_vars_t);
|
||||
|
@ -1399,10 +1438,10 @@ flags_set_del( int sts, void *aux )
|
|||
free( vars );
|
||||
svars->flags_done[t]++;
|
||||
stats( svars );
|
||||
return msgs_flags_set( svars, t );
|
||||
msgs_flags_set( svars, t );
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
flags_set_sync( int sts, void *aux )
|
||||
{
|
||||
SVARS_CHECK_RET_VARS(flag_vars_t);
|
||||
|
@ -1418,7 +1457,7 @@ flags_set_sync( int sts, void *aux )
|
|||
free( vars );
|
||||
svars->flags_done[t]++;
|
||||
stats( svars );
|
||||
return msgs_flags_set( svars, t );
|
||||
msgs_flags_set( svars, t );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1448,8 +1487,8 @@ flags_set_sync_p2( sync_vars_t *svars, sync_rec_t *srec, int t )
|
|||
}
|
||||
}
|
||||
|
||||
static int msg_trashed( int sts, void *aux );
|
||||
static int msg_rtrashed( int sts, int uid, copy_vars_t *vars );
|
||||
static void msg_trashed( int sts, void *aux );
|
||||
static void msg_rtrashed( int sts, int uid, copy_vars_t *vars );
|
||||
|
||||
static int
|
||||
msgs_flags_set( sync_vars_t *svars, int t )
|
||||
|
@ -1470,8 +1509,10 @@ msgs_flags_set( sync_vars_t *svars, int t )
|
|||
debug( "%s: trashing message %d\n", str_ms[t], tmsg->uid );
|
||||
svars->trash_total[t]++;
|
||||
stats( svars );
|
||||
if (svars->drv[t]->trash_msg( svars->ctx[t], tmsg, msg_trashed, AUX ))
|
||||
return 1;
|
||||
sync_ref( svars );
|
||||
svars->drv[t]->trash_msg( svars->ctx[t], tmsg, msg_trashed, AUX );
|
||||
if (deref_check_cancel( svars ))
|
||||
return -1;
|
||||
} else
|
||||
debug( "%s: not trashing message %d - not new\n", str_ms[t], tmsg->uid );
|
||||
} else {
|
||||
|
@ -1486,7 +1527,7 @@ msgs_flags_set( sync_vars_t *svars, int t )
|
|||
cv->srec = 0;
|
||||
cv->msg = tmsg;
|
||||
if (copy_msg( cv ))
|
||||
return 1;
|
||||
return -1;
|
||||
} else
|
||||
debug( "%s: not remote trashing message %d - too big\n", str_ms[t], tmsg->uid );
|
||||
} else
|
||||
|
@ -1495,10 +1536,11 @@ msgs_flags_set( sync_vars_t *svars, int t )
|
|||
}
|
||||
}
|
||||
svars->state[t] |= ST_SENT_TRASH;
|
||||
return sync_close( svars, t );
|
||||
sync_close( svars, t );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
msg_trashed( int sts, void *aux )
|
||||
{
|
||||
DECL_SVARS;
|
||||
|
@ -1506,14 +1548,14 @@ msg_trashed( int sts, void *aux )
|
|||
if (sts == DRV_MSG_BAD)
|
||||
sts = DRV_BOX_BAD;
|
||||
if (check_ret( sts, aux ))
|
||||
return 1;
|
||||
return;
|
||||
INIT_SVARS(aux);
|
||||
svars->trash_done[t]++;
|
||||
stats( svars );
|
||||
return sync_close( svars, t );
|
||||
sync_close( svars, t );
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
msg_rtrashed( int sts, int uid, copy_vars_t *vars )
|
||||
{
|
||||
SVARS_CHECK_CANCEL_RET;
|
||||
|
@ -1525,40 +1567,39 @@ msg_rtrashed( int sts, int uid, copy_vars_t *vars )
|
|||
default:
|
||||
cancel_sync( svars );
|
||||
free( vars );
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
free( vars );
|
||||
svars->trash_done[t]++;
|
||||
stats( svars );
|
||||
return sync_close( svars, t );
|
||||
sync_close( svars, t );
|
||||
}
|
||||
|
||||
static int box_closed( int sts, void *aux );
|
||||
static void box_closed( int sts, void *aux );
|
||||
static void box_closed_p2( sync_vars_t *svars, int t );
|
||||
|
||||
static int
|
||||
static void
|
||||
sync_close( sync_vars_t *svars, int t )
|
||||
{
|
||||
if ((~svars->state[t] & (ST_SENT_FIND_NEW|ST_SENT_TRASH)) ||
|
||||
svars->find_new_done[t] < svars->find_new_total[t] ||
|
||||
svars->trash_done[t] < svars->trash_total[t])
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if ((svars->chan->ops[t] & OP_EXPUNGE) /*&& !(svars->state[t] & ST_TRASH_BAD)*/) {
|
||||
debug( "expunging %s\n", str_ms[t] );
|
||||
return svars->drv[t]->close( svars->ctx[t], box_closed, AUX );
|
||||
}
|
||||
svars->drv[t]->close( svars->ctx[t], box_closed, AUX );
|
||||
} else {
|
||||
box_closed_p2( svars, t );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
box_closed( int sts, void *aux )
|
||||
{
|
||||
SVARS_CHECK_RET;
|
||||
svars->state[t] |= ST_DID_EXPUNGE;
|
||||
box_closed_p2( svars, t );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1655,16 +1696,23 @@ sync_bail1( sync_vars_t *svars )
|
|||
static void
|
||||
sync_bail2( sync_vars_t *svars )
|
||||
{
|
||||
void (*cb)( int sts, void *aux ) = svars->cb;
|
||||
void *aux = svars->aux;
|
||||
int ret = svars->ret;
|
||||
|
||||
free( svars->lname );
|
||||
free( svars->nname );
|
||||
free( svars->jname );
|
||||
free( svars->dname );
|
||||
free( svars );
|
||||
error( "" );
|
||||
cb( ret, aux );
|
||||
sync_deref( svars );
|
||||
}
|
||||
|
||||
static int sync_deref( sync_vars_t *svars )
|
||||
{
|
||||
if (!--svars->ref_count) {
|
||||
void (*cb)( int sts, void *aux ) = svars->cb;
|
||||
void *aux = svars->aux;
|
||||
int ret = svars->ret;
|
||||
free( svars );
|
||||
cb( ret, aux );
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user