From: Kevin McCarthy Date: Mon, 14 Nov 2016 04:02:35 +0000 (-0800) Subject: Create mx_ops.sync operation. Refactor compress to use the mx_ops.sync. X-Git-Tag: neomutt-20170225~32^2~72 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1c7e0b44faa633d7a8a3389cbdb1fccc9996ea72;p=neomutt Create mx_ops.sync operation. Refactor compress to use the mx_ops.sync. Change compress.sync_mailbox() to lock the compressed mailbox around both the tempfile sync and compress operations. This will prevent changes made inbetween the two syncs from being overwritten. Thanks to Damien Riegel for his original patch refactoring mx_ops.sync, which this patch is partially based upon. --- diff --git a/compress.c b/compress.c index 681fffcf4..b7fb06eda 100644 --- a/compress.c +++ b/compress.c @@ -816,18 +816,18 @@ mutt_comp_can_read (const char *path) } /** - * mutt_comp_sync - Save changes to the compressed mailbox file + * sync_mailbox - Save changes to the compressed mailbox file * @ctx: Mailbox to sync * - * Changes in Mutt only affect the tmp file. Calling mutt_comp_sync() + * Changes in Mutt only affect the tmp file. Calling sync_mailbox() * will commit them to the compressed file. * * Returns: * 0: Success * -1: Failure */ -int -mutt_comp_sync (CONTEXT *ctx) +static int +sync_mailbox (CONTEXT *ctx, int *index_hint) { if (!ctx) return -1; @@ -842,22 +842,36 @@ mutt_comp_sync (CONTEXT *ctx) return -1; } - /* TODO: need to refactor sync so we can lock around the - * path sync as well as the compress operation */ + struct mx_ops *ops = ci->child_ops; + if (!ops) + return -1; + if (!lock_realpath (ctx, 1)) { mutt_error (_("Unable to lock mailbox!")); return -1; } - int rc = execute_command (ctx, ci->close, _("Compressing %s")); + /* TODO: check if mailbox changed first! */ + + int rc = ops->sync (ctx, index_hint); + if (rc != 0) + { + unlock_realpath (ctx); + return rc; + } + + rc = execute_command (ctx, ci->close, _("Compressing %s")); if (rc == 0) + { + unlock_realpath (ctx); return -1; - - unlock_realpath (ctx); + } store_size (ctx); + unlock_realpath (ctx); + return 0; } @@ -894,6 +908,7 @@ struct mx_ops mx_comp_ops = .open_append = open_append_mailbox, .close = close_mailbox, .check = check_mailbox, + .sync = sync_mailbox, .open_msg = open_message, .close_msg = close_message, .commit_msg = commit_message, diff --git a/compress.h b/compress.h index f525c70b3..0c545ee43 100644 --- a/compress.h +++ b/compress.h @@ -23,7 +23,6 @@ void mutt_free_compress_info (CONTEXT *ctx); int mutt_comp_can_append (CONTEXT *ctx); int mutt_comp_can_read (const char *path); -int mutt_comp_sync (CONTEXT *ctx); int mutt_comp_valid_command (const char *cmd); extern struct mx_ops mx_comp_ops; diff --git a/imap/imap.c b/imap/imap.c index 729284dba..89bbdb848 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -2188,4 +2188,5 @@ struct mx_ops mx_imap_ops = { .commit_msg = imap_commit_message, .open_new_msg = imap_open_new_message, .check = imap_check_mailbox_reopen, + .sync = NULL, /* imap syncing is handled by imap_sync_mailbox */ }; diff --git a/mbox.c b/mbox.c index 13fc3d626..37f426d8e 100644 --- a/mbox.c +++ b/mbox.c @@ -802,7 +802,7 @@ void mbox_reset_atime (CONTEXT *ctx, struct stat *st) * 0 success * -1 failure */ -int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint) +static int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint) { char tempfile[_POSIX_PATH_MAX]; char buf[32]; @@ -817,6 +817,7 @@ int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint) FILE *fp = NULL; progress_t progress; char msgbuf[STRING]; + BUFFY *tmp = NULL; /* sort message by their position in the mailbox on disk */ if (Sort != SORT_ORDER) @@ -1114,6 +1115,13 @@ int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint) unlink (tempfile); /* remove partial copy of the mailbox */ mutt_unblock_signals (); + if (option(OPTCHECKMBOXSIZE)) + { + tmp = mutt_find_mailbox (ctx->path); + if (tmp && tmp->new == 0) + mutt_update_mailbox (tmp); + } + return (0); /* signal success */ bail: /* Come here in case of disaster */ @@ -1354,6 +1362,7 @@ struct mx_ops mx_mbox_ops = { .commit_msg = mbox_commit_message, .open_new_msg = mbox_open_new_message, .check = mbox_check_mailbox, + .sync = mbox_sync_mailbox, }; struct mx_ops mx_mmdf_ops = { @@ -1365,4 +1374,5 @@ struct mx_ops mx_mmdf_ops = { .commit_msg = mmdf_commit_message, .open_new_msg = mbox_open_new_message, .check = mbox_check_mailbox, + .sync = mbox_sync_mailbox, }; diff --git a/mh.c b/mh.c index 371656af4..41493f91a 100644 --- a/mh.c +++ b/mh.c @@ -2536,6 +2536,7 @@ struct mx_ops mx_maildir_ops = { .commit_msg = maildir_commit_message, .open_new_msg = maildir_open_new_message, .check = maildir_check_mailbox, + .sync = mh_sync_mailbox, }; struct mx_ops mx_mh_ops = { @@ -2547,4 +2548,5 @@ struct mx_ops mx_mh_ops = { .commit_msg = mh_commit_message, .open_new_msg = mh_open_new_message, .check = mh_check_mailbox, + .sync = mh_sync_mailbox, }; diff --git a/mutt.h b/mutt.h index c63a1eeb1..98b77ffac 100644 --- a/mutt.h +++ b/mutt.h @@ -908,6 +908,7 @@ struct mx_ops int (*open_append) (struct _context *, int flags); int (*close) (struct _context *); int (*check) (struct _context *ctx, int *index_hint); + int (*sync) (struct _context *ctx, int *index_hint); int (*open_msg) (struct _context *, struct _message *, int msgno); int (*close_msg) (struct _context *, struct _message *); int (*commit_msg) (struct _context *, struct _message *); diff --git a/mx.c b/mx.c index 033ee181b..a96193775 100644 --- a/mx.c +++ b/mx.c @@ -682,56 +682,13 @@ void mx_fastclose_mailbox (CONTEXT *ctx) /* save changes to disk */ static int sync_mailbox (CONTEXT *ctx, int *index_hint) { - BUFFY *tmp = NULL; - int rc = -1; + if (!ctx->mx_ops || !ctx->mx_ops->sync) + return -1; if (!ctx->quiet) mutt_message (_("Writing %s..."), ctx->path); - switch (ctx->magic) - { - case MUTT_MBOX: - case MUTT_MMDF: - rc = mbox_sync_mailbox (ctx, index_hint); - if (option(OPTCHECKMBOXSIZE)) - tmp = mutt_find_mailbox (ctx->path); - break; - - case MUTT_MH: - case MUTT_MAILDIR: - rc = mh_sync_mailbox (ctx, index_hint); - break; - -#ifdef USE_IMAP - case MUTT_IMAP: - /* extra argument means EXPUNGE */ - rc = imap_sync_mailbox (ctx, 1, index_hint); - break; -#endif /* USE_IMAP */ - -#ifdef USE_POP - case MUTT_POP: - rc = pop_sync_mailbox (ctx, index_hint); - break; -#endif /* USE_POP */ - } - -#if 0 - if (!ctx->quiet && !ctx->shutup && rc == -1) - mutt_error ( _("Could not synchronize mailbox %s!"), ctx->path); -#endif - - if (tmp && tmp->new == 0) - mutt_update_mailbox (tmp); - -#ifdef USE_COMPRESSED - /* If everything went well, the mbox handler saved the changes to our - * temporary file. Next, mutt_comp_sync() will compress the temporary file. */ - if ((rc == 0) && ctx->compress_info) - return mutt_comp_sync (ctx); -#endif - - return rc; + return ctx->mx_ops->sync (ctx, index_hint); } /* move deleted mails to the trash folder */ diff --git a/mx.h b/mx.h index 6b3c535ea..f5563d82a 100644 --- a/mx.h +++ b/mx.h @@ -47,7 +47,6 @@ WHERE short DefaultMagic INITVAL (MUTT_MBOX); #define MMDF_SEP "\001\001\001\001\n" #define MAXLOCKATTEMPT 5 -int mbox_sync_mailbox (CONTEXT *, int *); int mbox_lock_mailbox (CONTEXT *, int, int); int mbox_parse_mailbox (CONTEXT *); int mmdf_parse_mailbox (CONTEXT *); @@ -55,7 +54,6 @@ void mbox_unlock_mailbox (CONTEXT *); int mbox_check_empty (const char *); void mbox_reset_atime (CONTEXT *, struct stat *); -int mh_sync_mailbox (CONTEXT *, int *); int mh_check_empty (const char *); int maildir_check_empty (const char *); diff --git a/pop.c b/pop.c index 294d71d8d..81f739af9 100644 --- a/pop.c +++ b/pop.c @@ -664,7 +664,7 @@ static int pop_close_message (CONTEXT *ctx, MESSAGE *msg) } /* update POP mailbox - delete messages from server */ -int pop_sync_mailbox (CONTEXT *ctx, int *index_hint) +static int pop_sync_mailbox (CONTEXT *ctx, int *index_hint) { int i, j, ret = 0; char buf[LONG_STRING]; @@ -944,4 +944,5 @@ struct mx_ops mx_pop_ops = { .check = pop_check_mailbox, .commit_msg = NULL, .open_new_msg = NULL, + .sync = pop_sync_mailbox, }; diff --git a/pop.h b/pop.h index 53454c678..55e99eecc 100644 --- a/pop.h +++ b/pop.h @@ -105,7 +105,6 @@ void pop_logout (CONTEXT *); void pop_error (POP_DATA *, char *); /* pop.c */ -int pop_sync_mailbox (CONTEXT *, int *); int pop_close_mailbox (CONTEXT *); void pop_fetch_mail (void);