isync

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

commit 118fdc4f18c20aab4f2f2e22f8812b49a4a7096a
parent 4b3768806278a70db696ba52645dc1b6eb8de58a
Author: Oswald Buddenhagen <ossi@users.sf.net>
Date:   Sat,  5 Aug 2017 21:20:34 +0200

Merge branch '1.2'

Conflicts:
	configure.ac
	src/mbsync.1

Diffstat:
Msrc/mbsync.1 | 9+++++++++
Msrc/socket.c | 48++++++++++++++++++++++++++++++++++++------------
2 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/src/mbsync.1 b/src/mbsync.1 @@ -248,6 +248,7 @@ Define the Maildir Store \fIname\fR, opening a section for its parameters. Use the \fBalternative\fR UID storage scheme for mailboxes in this Store. This does not affect mailboxes that do already have a UID storage scheme; use \fBmdconvert\fR to change it. +See \fBRECOMMENDATIONS\fR below. (Default: \fBno\fR) .. .TP @@ -711,6 +712,14 @@ you should not use \fBmbsync\fR's \fBTrash\fR option at all. .P Use of the \fBTrash\fR option with M$ Exchange 2013 requires the use of \fBDisableExtension MOVE\fR due to a server bug. +.P +When using the more efficient default UID mapping scheme, it is important +that the MUA renames files when moving them between Maildir folders. +Mutt always does that, while mu4e needs to be configured to do it: +.br +.in +4 +(setq mu4e-change-filenames-when-moving t) +.in -4 .. .SH INHERENT PROBLEMS Changes done after \fBmbsync\fR has retrieved the message list will not be diff --git a/src/socket.c b/src/socket.c @@ -305,6 +305,14 @@ static void start_tls_p3( conn_t *conn, int ok ) static void z_fake_cb( void * ); +static const char * +z_err_msg( int code, z_streamp strm ) +{ + /* zlib's consistency in populating z_stream->msg is somewhat + * less than stellar. zError() is undocumented. */ + return strm->msg ? strm->msg : zError( code ); +} + void socket_start_deflate( conn_t *conn ) { @@ -316,7 +324,7 @@ socket_start_deflate( conn_t *conn ) -15 /* Use raw deflate */ ); if (result != Z_OK) { - error( "Fatal: Cannot initialize decompression: %s\n", conn->in_z->msg ); + error( "Fatal: Cannot initialize decompression: %s\n", z_err_msg( result, conn->in_z ) ); abort(); } @@ -330,7 +338,7 @@ socket_start_deflate( conn_t *conn ) Z_DEFAULT_STRATEGY /* Don't try to do anything fancy */ ); if (result != Z_OK) { - error( "Fatal: Cannot initialize compression: %s\n", conn->out_z->msg ); + error( "Fatal: Cannot initialize compression: %s\n", z_err_msg( result, conn->out_z ) ); abort(); } @@ -343,6 +351,7 @@ static void socket_fake_cb( void * ); static void socket_timeout_cb( void * ); static void socket_connect_one( conn_t * ); +static void socket_connect_next( conn_t * ); static void socket_connect_failed( conn_t * ); static void socket_connected( conn_t * ); static void socket_connect_bail( conn_t * ); @@ -485,8 +494,8 @@ socket_connect_one( conn_t *sock ) s = socket( PF_INET, SOCK_STREAM, 0 ); #endif if (s < 0) { - perror( "socket" ); - exit( 1 ); + socket_connect_next( sock ); + return; } socket_open_internal( sock, s ); @@ -511,10 +520,9 @@ socket_connect_one( conn_t *sock ) } static void -socket_connect_failed( conn_t *conn ) +socket_connect_next( conn_t *conn ) { sys_error( "Cannot connect to %s", conn->name ); - socket_close_internal( conn ); free( conn->name ); conn->name = 0; #ifdef HAVE_IPV6 @@ -526,6 +534,13 @@ socket_connect_failed( conn_t *conn ) } static void +socket_connect_failed( conn_t *conn ) +{ + socket_close_internal( conn ); + socket_connect_next( conn ); +} + +static void socket_connected( conn_t *conn ) { #ifdef HAVE_IPV6 @@ -648,8 +663,10 @@ socket_fill_z( conn_t *sock ) sock->in_z->next_out = (unsigned char *)buf; ret = inflate( sock->in_z, Z_SYNC_FLUSH ); - if (ret != Z_OK && ret != Z_STREAM_END) { - error( "Error decompressing data from %s: %s\n", sock->name, sock->in_z->msg ); + /* Z_BUF_ERROR happens here when the previous call both consumed + * all input and exactly filled up the output buffer. */ + if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_STREAM_END) { + error( "Error decompressing data from %s: %s\n", sock->name, z_err_msg( ret, sock->in_z ) ); socket_fail( sock ); return; } @@ -832,6 +849,7 @@ do_flush( conn_t *conn ) if (!conn->z_written) return; do { + int ret; if (!bc) { buf_avail = WRITE_CHUNK_SIZE; bc = nfmalloc( offsetof(buff_chunk_t, data) + buf_avail ); @@ -841,8 +859,11 @@ do_flush( conn_t *conn ) conn->out_z->avail_in = 0; conn->out_z->next_out = (uchar *)bc->data + bc->len; conn->out_z->avail_out = buf_avail; - if (deflate( conn->out_z, Z_PARTIAL_FLUSH ) != Z_OK) { - error( "Fatal: Compression error: %s\n", conn->out_z->msg ); + /* Z_BUF_ERROR cannot happen here, as zlib suppresses the error + * both upon increasing the flush level (1st iteration) and upon + * a no-op after the output buffer was full (later iterations). */ + if ((ret = deflate( conn->out_z, Z_PARTIAL_FLUSH )) != Z_OK) { + error( "Fatal: Compression error: %s\n", z_err_msg( ret, conn->out_z ) ); abort(); } bc->len = (char *)conn->out_z->next_out - bc->data; @@ -904,12 +925,15 @@ socket_write( conn_t *conn, conn_iovec_t *iov, int iovcnt ) len = iov->len - offset; #ifdef HAVE_LIBZ if (conn->out_z) { + int ret; conn->out_z->next_in = (uchar *)iov->buf + offset; conn->out_z->avail_in = len; conn->out_z->next_out = (uchar *)bc->data + bc->len; conn->out_z->avail_out = buf_avail; - if (deflate( conn->out_z, Z_NO_FLUSH ) != Z_OK) { - error( "Fatal: Compression error: %s\n", conn->out_z->msg ); + /* Z_BUF_ERROR is impossible here, as the input buffer always has data, + * and the output buffer always has space. */ + if ((ret = deflate( conn->out_z, Z_NO_FLUSH )) != Z_OK) { + error( "Fatal: Compression error: %s\n", z_err_msg( ret, conn->out_z ) ); abort(); } bc->len = (char *)conn->out_z->next_out - bc->data;