isync

mailbox synchronization program
git clone https://git.code.sf.net/p/isync/isync
Log | Files | Refs | README | LICENSE

commit 05fd0b997038ee514afeb56de8d57d0f371a008b
parent c741d5ffb5273f52fda483adebf367b7d8f21da7
Author: Oswald Buddenhagen <ossi@users.sf.net>
Date:   Sat, 23 Jul 2011 16:06:32 +0200

split out drv->load() from drv->select()

Diffstat:
Msrc/drv_imap.c | 29+++++++++++++++--------------
Msrc/drv_maildir.c | 72++++++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/isync.h | 8++++----
Msrc/sync.c | 97++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
4 files changed, 121 insertions(+), 85 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c @@ -1542,28 +1542,21 @@ imap_open_store( store_conf_t *conf, } static void -imap_prepare_paths( store_t *gctx ) -{ - free_generic_messages( gctx->msgs ); - gctx->msgs = 0; -} - -static void imap_prepare_opts( store_t *gctx, int opts ) { gctx->opts = opts; } static void -imap_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs, +imap_select( store_t *gctx, int create, void (*cb)( int sts, void *aux ), void *aux ) { imap_store_t *ctx = (imap_store_t *)gctx; struct imap_cmd *cmd = new_imap_cmd(); const char *prefix; - int ret, i, j, bl; - char buf[1000]; + free_generic_messages( gctx->msgs ); + gctx->msgs = 0; if (!strcmp( gctx->name, "INBOX" )) { prefix = ""; @@ -1573,10 +1566,18 @@ imap_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs, ctx->uidnext = -1; - cmd->param.create = (gctx->opts & OPEN_CREATE) != 0; + cmd->param.create = create; cmd->param.trycreate = 1; - if ((ret = imap_exec_b( ctx, cmd, "SELECT \"%s%s\"", prefix, gctx->name )) != DRV_OK) - goto bail; + cb( imap_exec_b( ctx, cmd, "SELECT \"%s%s\"", prefix, gctx->name ), aux ); +} + +static void +imap_load( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs, + void (*cb)( int sts, void *aux ), void *aux ) +{ + imap_store_t *ctx = (imap_store_t *)gctx; + int ret, i, j, bl; + char buf[1000]; if (gctx->count) { ctx->msgapp = &gctx->msgs; @@ -1907,9 +1908,9 @@ struct driver imap_driver = { imap_own_store, imap_cancel_store, imap_list, - imap_prepare_paths, imap_prepare_opts, imap_select, + imap_load, imap_fetch_msg, imap_store_msg, imap_find_msg, diff --git a/src/drv_maildir.c b/src/drv_maildir.c @@ -745,9 +745,12 @@ maildir_app_msg( maildir_store_t *ctx, message_t ***msgapp, msg_t *entry ) } static void -maildir_prepare_paths( store_t *gctx ) +maildir_select( store_t *gctx, int create, + void (*cb)( int sts, void *aux ), void *aux ) { maildir_store_t *ctx = (maildir_store_t *)gctx; + int ret; + char uvpath[_POSIX_PATH_MAX]; maildir_cleanup( gctx ); gctx->msgs = 0; @@ -759,37 +762,8 @@ maildir_prepare_paths( store_t *gctx ) gctx->path = nfstrdup( ((maildir_store_conf_t *)gctx->conf)->inbox ); else nfasprintf( &gctx->path, "%s%s", gctx->conf->path, gctx->name ); -} - -static void -maildir_prepare_opts( store_t *gctx, int opts ) -{ - if (opts & OPEN_SETFLAGS) - opts |= OPEN_OLD; - if (opts & OPEN_EXPUNGE) - opts |= OPEN_OLD|OPEN_NEW|OPEN_FLAGS; - gctx->opts = opts; -} - -static void -maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs, - void (*cb)( int sts, void *aux ), void *aux ) -{ - maildir_store_t *ctx = (maildir_store_t *)gctx; - message_t **msgapp; - msglist_t msglist; - int i; -#ifdef USE_DB - int ret; -#endif /* USE_DB */ - char uvpath[_POSIX_PATH_MAX]; - - ctx->minuid = minuid; - ctx->maxuid = maxuid; - ctx->excs = nfrealloc( excs, nexcs * sizeof(int) ); - ctx->nexcs = nexcs; - if ((ret = maildir_validate( gctx->path, "", ctx->gen.opts & OPEN_CREATE, ctx )) != DRV_OK) { + if ((ret = maildir_validate( gctx->path, "", create, ctx )) != DRV_OK) { cb( ret, aux ); return; } @@ -854,9 +828,43 @@ maildir_select( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs, ctx->nuid = ((int *)value.data)[1]; ctx->uvok = 1; } + cb( DRV_OK, aux ); + return; } fnok: #endif /* USE_DB */ + if ((ret = maildir_uidval_lock( ctx )) != DRV_OK) { + cb( ret, aux ); + return; + } + maildir_uidval_unlock( ctx ); + + cb( DRV_OK, aux ); +} + +static void +maildir_prepare_opts( store_t *gctx, int opts ) +{ + if (opts & OPEN_SETFLAGS) + opts |= OPEN_OLD; + if (opts & OPEN_EXPUNGE) + opts |= OPEN_OLD|OPEN_NEW|OPEN_FLAGS; + gctx->opts = opts; +} + +static void +maildir_load( store_t *gctx, int minuid, int maxuid, int *excs, int nexcs, + void (*cb)( int sts, void *aux ), void *aux ) +{ + maildir_store_t *ctx = (maildir_store_t *)gctx; + message_t **msgapp; + msglist_t msglist; + int i; + + ctx->minuid = minuid; + ctx->maxuid = maxuid; + ctx->excs = nfrealloc( excs, nexcs * sizeof(int) ); + ctx->nexcs = nexcs; if (maildir_scan( ctx, &msglist ) != DRV_OK) { cb( DRV_BOX_BAD, aux ); @@ -1302,9 +1310,9 @@ struct driver maildir_driver = { maildir_own_store, maildir_disown_store, /* _cancel_, but it's the same */ maildir_list, - maildir_prepare_paths, maildir_prepare_opts, maildir_select, + maildir_load, maildir_fetch_msg, maildir_store_msg, maildir_find_msg, diff --git a/src/isync.h b/src/isync.h @@ -142,7 +142,6 @@ typedef struct message { #define OPEN_NEW (1<<1) #define OPEN_FLAGS (1<<2) #define OPEN_SIZE (1<<3) -#define OPEN_CREATE (1<<4) #define OPEN_EXPUNGE (1<<5) #define OPEN_SETFLAGS (1<<6) #define OPEN_APPEND (1<<7) @@ -208,10 +207,11 @@ struct driver { void (*cancel_store)( store_t *ctx ); void (*list)( store_t *ctx, void (*cb)( int sts, void *aux ), void *aux ); - void (*prepare_paths)( store_t *ctx ); void (*prepare_opts)( store_t *ctx, int opts ); - void (*select)( store_t *ctx, int minuid, int maxuid, int *excs, int nexcs, - void (*cb)( int sts, void *aux ), void *aux ); + void (*select)( store_t *ctx, int create, + void (*cb)( int sts, void *aux ), void *aux ); + void (*load)( 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, diff --git a/src/sync.c b/src/sync.c @@ -207,6 +207,7 @@ static int check_cancel( sync_vars_t *svars ); #define ST_CLOSED (1<<5) #define ST_SENT_CANCEL (1<<6) #define ST_CANCELED (1<<7) +#define ST_SELECTED (1<<8) #define ST_DID_EXPUNGE (1<<16) @@ -452,9 +453,13 @@ cancel_done( void *aux ) svars->state[t] |= ST_CANCELED; if (svars->state[1-t] & ST_CANCELED) { - Fclose( svars->nfp ); - Fclose( svars->jfp ); - sync_bail( svars ); + if (svars->lfd) { + Fclose( svars->nfp ); + Fclose( svars->jfp ); + sync_bail( svars ); + } else { + sync_bail2( svars ); + } } } @@ -537,21 +542,14 @@ clean_strdup( const char *s ) #define JOURNAL_VERSION "2" -static int select_box( sync_vars_t *svars, int t, int minwuid, int *mexcs, int nmexcs ); +static void box_selected( int sts, void *aux ); void sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan, void (*cb)( int sts, void *aux ), void *aux ) { sync_vars_t *svars; - sync_rec_t *srec, *nsrec; - char *s, *cmname, *csname; - FILE *jfp; - int opts[2], line, t1, t2, t3, t; - struct stat st; - struct flock lck; - char fbuf[16]; /* enlarge when support for keywords is added */ - char buf[64]; + int t; svars = nfcalloc( sizeof(*svars) ); svars->t[1] = 1; @@ -571,15 +569,44 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan, ctx[t]->uidvalidity = -1; set_bad_callback( ctx[t], store_bad, AUX ); svars->drv[t] = ctx[t]->conf->driver; - svars->drv[t]->prepare_paths( ctx[t] ); + info( "Selecting %s %s...\n", str_ms[t], ctx[t]->name ); + DRIVER_CALL(select( ctx[t], (chan->ops[t] & OP_CREATE) != 0, box_selected, AUX )); } +} + +static int load_box( sync_vars_t *svars, int t, int minwuid, int *mexcs, int nmexcs ); +static void +box_selected( int sts, void *aux ) +{ + DECL_SVARS; + sync_rec_t *srec, *nsrec; + char *s, *cmname, *csname; + store_t *ctx[2]; + channel_conf_t *chan; + FILE *jfp; + int opts[2], line, t1, t2, t3; + struct stat st; + struct flock lck; + char fbuf[16]; /* enlarge when support for keywords is added */ + char buf[64]; + + if (check_ret( sts, aux )) + return; + INIT_SVARS(aux); + ctx[0] = svars->ctx[0]; + ctx[1] = svars->ctx[1]; + svars->state[t] |= ST_SELECTED; + if (!(svars->state[1-t] & ST_SELECTED)) + return; + + chan = svars->chan; if (!strcmp( chan->sync_state ? chan->sync_state : global_sync_state, "*" )) { if (!ctx[S]->path) { error( "Error: store '%s' does not support in-box sync state\n", chan->stores[S]->name ); sbail: - free( svars ); - cb( SYNC_BAD(S), aux ); + svars->ret = SYNC_BAD(S); + sync_bail2( svars ); return; } nfasprintf( &svars->dname, "%s/." EXE "state", ctx[S]->path ); @@ -597,13 +624,11 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan, } if (!(s = strrchr( svars->dname, '/' ))) { error( "Error: invalid SyncState '%s'\n", svars->dname ); - free( svars->dname ); goto sbail; } *s = 0; if (mkdir( svars->dname, 0700 ) && errno != EEXIST) { error( "Error: cannot create SyncState directory '%s': %s\n", svars->dname, strerror(errno) ); - free( svars->dname ); goto sbail; } *s = '/'; @@ -810,6 +835,17 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan, goto bail; } } + + t1 = 0; + for (t = 0; t < 2; t++) + if (svars->uidval[t] >= 0 && svars->uidval[t] != ctx[t]->uidvalidity) { + error( "Error: UIDVALIDITY of %s changed (got %d, expected %d)\n", + str_ms[t], ctx[t]->uidvalidity, svars->uidval[t] ); + t1++; + } + if (t1) + goto bail; + if (!(svars->nfp = fopen( svars->nname, "w" ))) { error( "Error: cannot write new sync state %s\n", svars->nname ); goto bail; @@ -851,8 +887,6 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan, } else if (chan->stores[1-t]->trash && chan->stores[1-t]->trash_remote_new) opts[t] |= OPEN_NEW|OPEN_FLAGS; } - if (chan->ops[t] & OP_CREATE) - opts[t] |= OPEN_CREATE; } if ((chan->ops[S] & (OP_NEW|OP_RENEW)) && chan->max_messages) opts[S] |= OPEN_OLD|OPEN_NEW|OPEN_FLAGS; @@ -873,15 +907,15 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan, svars->drv[S]->prepare_opts( ctx[S], opts[S] ); svars->find = line != 0; - if (!svars->smaxxuid && select_box( svars, M, (ctx[M]->opts & OPEN_OLD) ? 1 : INT_MAX, 0, 0 )) + if (!svars->smaxxuid && load_box( svars, M, (ctx[M]->opts & OPEN_OLD) ? 1 : INT_MAX, 0, 0 )) return; - select_box( svars, S, (ctx[S]->opts & OPEN_OLD) ? 1 : INT_MAX, 0, 0 ); + load_box( svars, S, (ctx[S]->opts & OPEN_OLD) ? 1 : INT_MAX, 0, 0 ); } -static void box_selected( int sts, void *aux ); +static void box_loaded( int sts, void *aux ); static int -select_box( sync_vars_t *svars, int t, int minwuid, int *mexcs, int nmexcs ) +load_box( sync_vars_t *svars, int t, int minwuid, int *mexcs, int nmexcs ) { sync_rec_t *srec; int maxwuid; @@ -897,9 +931,9 @@ select_box( sync_vars_t *svars, int t, int minwuid, int *mexcs, int nmexcs ) maxwuid = srec->uid[t]; } else 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 ); - DRIVER_CALL_RET(select( svars->ctx[t], minwuid, maxwuid, mexcs, nmexcs, box_selected, AUX )); + info( "Loading %s...\n", str_ms[t] ); + debug( maxwuid == INT_MAX ? "loading %s [%d,inf]\n" : "loading %s [%d,%d]\n", str_ms[t], minwuid, maxwuid ); + DRIVER_CALL_RET(load( svars->ctx[t], minwuid, maxwuid, mexcs, nmexcs, box_loaded, AUX )); } typedef struct { @@ -911,19 +945,12 @@ static void msg_found_sel( int sts, int uid, void *aux ); static void msgs_found_sel( sync_vars_t *svars, int t ); static void -box_selected( int sts, void *aux ) +box_loaded( int sts, void *aux ) { find_vars_t *fv; sync_rec_t *srec; SVARS_CHECK_RET; - if (svars->uidval[t] >= 0 && svars->uidval[t] != svars->ctx[t]->uidvalidity) { - error( "Error: UIDVALIDITY of %s changed (got %d, expected %d)\n", - str_ms[t], svars->ctx[t]->uidvalidity, svars->uidval[t] ); - svars->ret |= SYNC_FAIL; - cancel_sync( svars ); - return; - } info( "%s: %d messages, %d recent\n", str_ms[t], svars->ctx[t]->count, svars->ctx[t]->recent ); if (svars->find) { @@ -1100,7 +1127,7 @@ msgs_found_sel( sync_vars_t *svars, int t ) for (t = 0; t < nmexcs; t++) debugn( " %d", mexcs[t] ); debug( "\n" ); - select_box( svars, M, minwuid, mexcs, nmexcs ); + load_box( svars, M, minwuid, mexcs, nmexcs ); return; }