make UIDs unsigned

complies with the IMAP spec, thus removing the (not really) arbitrary
limitation to INT_MAX for UIDs.
This commit is contained in:
Oswald Buddenhagen 2017-03-21 20:05:29 +01:00
parent a0961d6505
commit bb632d1cd0
7 changed files with 239 additions and 230 deletions

View File

@ -174,9 +174,9 @@ int map_name( const char *arg, char **result, int reserve, const char *in, const
(arr)->data = nfrealloc( (arr)->data, (arr)->size * sizeof((arr)->data[0]) ); \ (arr)->data = nfrealloc( (arr)->data, (arr)->size * sizeof((arr)->data[0]) ); \
} while (0) } while (0)
DEFINE_ARRAY_TYPE(int) DEFINE_ARRAY_TYPE(uint)
void sort_int_array( int_array_t array ); void sort_uint_array( uint_array_t array );
int find_int_array( const int_array_t array, int value ); int find_uint_array( const uint_array_t array, uint value );
void arc4_init( void ); void arc4_init( void );
uchar arc4_getbyte( void ); uchar arc4_getbyte( void );

View File

@ -66,7 +66,7 @@ typedef struct message {
char *msgid; /* owned */ char *msgid; /* owned */
/* string_list_t *keywords; */ /* string_list_t *keywords; */
int size; /* zero implies "not fetched" */ int size; /* zero implies "not fetched" */
int uid; uint uid;
uchar flags, status; uchar flags, status;
char tuid[TUIDL]; char tuid[TUIDL];
} message_t; } message_t;
@ -83,7 +83,7 @@ typedef struct message {
#define OPEN_FIND (1<<8) #define OPEN_FIND (1<<8)
#define OPEN_OLD_IDS (1<<9) #define OPEN_OLD_IDS (1<<9)
#define UIDVAL_BAD -1 #define UIDVAL_BAD ((uint)-1)
typedef struct store { typedef struct store {
struct store *next; struct store *next;
@ -206,7 +206,7 @@ struct driver {
* Messages up to seenuid need to have the size populated when OPEN_OLD_SIZE is set; * Messages up to seenuid need to have the size populated when OPEN_OLD_SIZE is set;
* likewise messages above seenuid when OPEN_NEW_SIZE is set. * likewise messages above seenuid when OPEN_NEW_SIZE is set.
* The returned message list remains owned by the driver. */ * The returned message list remains owned by the driver. */
void (*load_box)( store_t *ctx, int minuid, int maxuid, int newuid, int seenuid, int_array_t excs, void (*load_box)( store_t *ctx, uint minuid, uint maxuid, uint newuid, uint seenuid, uint_array_t excs,
void (*cb)( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux ), void *aux ); void (*cb)( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux ), void *aux );
/* Fetch the contents and flags of the given message from the current mailbox. */ /* Fetch the contents and flags of the given message from the current mailbox. */
@ -216,20 +216,20 @@ struct driver {
/* Store the given message to either the current mailbox or the trash folder. /* Store the given message to either the current mailbox or the trash folder.
* If the new copy's UID can be immediately determined, return it, otherwise 0. */ * If the new copy's UID can be immediately determined, return it, otherwise 0. */
void (*store_msg)( store_t *ctx, msg_data_t *data, int to_trash, void (*store_msg)( store_t *ctx, msg_data_t *data, int to_trash,
void (*cb)( int sts, int uid, void *aux ), void *aux ); void (*cb)( int sts, uint uid, void *aux ), void *aux );
/* Index the messages which have newly appeared in the mailbox, including their /* Index the messages which have newly appeared in the mailbox, including their
* temporary UID headers. This is needed if store_msg() does not guarantee returning * temporary UID headers. This is needed if store_msg() does not guarantee returning
* a UID; otherwise the driver needs to implement only the OPEN_FIND flag. * a UID; otherwise the driver needs to implement only the OPEN_FIND flag.
* The returned message list remains owned by the driver. */ * The returned message list remains owned by the driver. */
void (*find_new_msgs)( store_t *ctx, int newuid, void (*find_new_msgs)( store_t *ctx, uint newuid,
void (*cb)( int sts, message_t *msgs, void *aux ), void *aux ); void (*cb)( int sts, message_t *msgs, void *aux ), void *aux );
/* Add/remove the named flags to/from the given message. The message may be either /* Add/remove the named flags to/from the given message. The message may be either
* a pre-fetched one (in which case the in-memory representation is updated), * a pre-fetched one (in which case the in-memory representation is updated),
* or it may be identifed by UID only. The operation may be delayed until commit() * or it may be identifed by UID only. The operation may be delayed until commit()
* is called. */ * is called. */
void (*set_msg_flags)( store_t *ctx, message_t *msg, int uid, int add, int del, /* msg can be null, therefore uid as a fallback */ void (*set_msg_flags)( store_t *ctx, message_t *msg, uint uid, int add, int del, /* msg can be null, therefore uid as a fallback */
void (*cb)( int sts, void *aux ), void *aux ); void (*cb)( int sts, void *aux ), void *aux );
/* Move the given message from the current mailbox to the trash folder. /* Move the given message from the current mailbox to the trash folder.

View File

@ -112,7 +112,7 @@ struct imap_store {
// note that the message counts do _not_ reflect stats from msgs, // note that the message counts do _not_ reflect stats from msgs,
// but mailbox totals. also, don't trust them beyond the initial load. // but mailbox totals. also, don't trust them beyond the initial load.
int total_msgs, recent_msgs; int total_msgs, recent_msgs;
int uidvalidity, uidnext; uint uidvalidity, uidnext;
message_t *msgs; message_t *msgs;
message_t **msgapp; /* FETCH results */ message_t **msgapp; /* FETCH results */
uint caps; /* CAPABILITY results */ uint caps; /* CAPABILITY results */
@ -157,7 +157,7 @@ struct imap_cmd {
void (*done)( imap_store_t *ctx, imap_cmd_t *cmd, int response ); void (*done)( imap_store_t *ctx, imap_cmd_t *cmd, int response );
char *data; char *data;
int data_len; int data_len;
int uid; /* to identify fetch responses */ uint uid; /* to identify fetch responses */
char high_prio; /* if command is queued, put it at the front of the queue. */ char high_prio; /* if command is queued, put it at the front of the queue. */
char to_trash; /* we are storing to trash, not current. */ char to_trash; /* we are storing to trash, not current. */
char create; /* create the mailbox if we get an error which suggests so. */ char create; /* create the mailbox if we get an error which suggests so. */
@ -179,9 +179,9 @@ typedef struct {
typedef struct { typedef struct {
imap_cmd_t gen; imap_cmd_t gen;
void (*callback)( int sts, int uid, void *aux ); void (*callback)( int sts, uint uid, void *aux );
void *callback_aux; void *callback_aux;
int out_uid; uint out_uid;
} imap_cmd_out_uid_t; } imap_cmd_out_uid_t;
typedef struct { typedef struct {
@ -189,7 +189,7 @@ typedef struct {
void (*callback)( int sts, message_t *msgs, void *aux ); void (*callback)( int sts, message_t *msgs, void *aux );
void *callback_aux; void *callback_aux;
message_t **out_msgs; message_t **out_msgs;
int uid; uint uid;
} imap_cmd_find_new_t; } imap_cmd_find_new_t;
typedef struct { typedef struct {
@ -498,6 +498,8 @@ imap_vprintf( const char *fmt, va_list ap )
d += l; d += l;
} else if (c == 'd') { } else if (c == 'd') {
d += nfsnprintf( d, ed - d, "%d", va_arg( ap , int ) ); d += nfsnprintf( d, ed - d, "%d", va_arg( ap , int ) );
} else if (c == 'u') {
d += nfsnprintf( d, ed - d, "%u", va_arg( ap , uint ) );
} else { } else {
fputs( "Fatal: unsupported format specifier. Please report a bug.\n", stderr ); fputs( "Fatal: unsupported format specifier. Please report a bug.\n", stderr );
abort(); abort();
@ -959,12 +961,12 @@ static int
parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
{ {
list_t *tmp, *flags; list_t *tmp, *flags;
char *body = 0, *tuid = 0, *msgid = 0; char *body = 0, *tuid = 0, *msgid = 0, *ep;
imap_message_t *cur; imap_message_t *cur;
msg_data_t *msgdata; msg_data_t *msgdata;
imap_cmd_t *cmdp; imap_cmd_t *cmdp;
int uid = 0, mask = 0, status = 0, size = 0; int mask = 0, status = 0, size = 0;
uint i; uint i, uid = 0;
time_t date = 0; time_t date = 0;
if (!is_list( list )) { if (!is_list( list )) {
@ -977,9 +979,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
if (is_atom( tmp )) { if (is_atom( tmp )) {
if (!strcmp( "UID", tmp->val )) { if (!strcmp( "UID", tmp->val )) {
tmp = tmp->next; tmp = tmp->next;
if (is_atom( tmp )) if (!is_atom( tmp ) || (uid = strtoul( tmp->val, &ep, 10 ), *ep))
uid = atoi( tmp->val );
else
error( "IMAP error: unable to parse UID\n" ); error( "IMAP error: unable to parse UID\n" );
} else if (!strcmp( "FLAGS", tmp->val )) { } else if (!strcmp( "FLAGS", tmp->val )) {
tmp = tmp->next; tmp = tmp->next;
@ -1016,9 +1016,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
error( "IMAP error: unable to parse INTERNALDATE\n" ); error( "IMAP error: unable to parse INTERNALDATE\n" );
} else if (!strcmp( "RFC822.SIZE", tmp->val )) { } else if (!strcmp( "RFC822.SIZE", tmp->val )) {
tmp = tmp->next; tmp = tmp->next;
if (is_atom( tmp )) if (!is_atom( tmp ) || (size = strtoul( tmp->val, &ep, 10 ), *ep))
size = atoi( tmp->val );
else
error( "IMAP error: unable to parse RFC822.SIZE\n" ); error( "IMAP error: unable to parse RFC822.SIZE\n" );
} else if (!strcmp( "BODY[]", tmp->val )) { } else if (!strcmp( "BODY[]", tmp->val )) {
tmp = tmp->next; tmp = tmp->next;
@ -1046,7 +1044,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
break; break;
if (starts_with_upper( val, len, "X-TUID: ", 8 )) { if (starts_with_upper( val, len, "X-TUID: ", 8 )) {
if (len < 8 + TUIDL) { if (len < 8 + TUIDL) {
error( "IMAP error: malformed X-TUID header (UID %d)\n", uid ); error( "IMAP error: malformed X-TUID header (UID %u)\n", uid );
continue; continue;
} }
tuid = val + 8; tuid = val + 8;
@ -1093,7 +1091,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
for (cmdp = ctx->in_progress; cmdp; cmdp = cmdp->next) for (cmdp = ctx->in_progress; cmdp; cmdp = cmdp->next)
if (cmdp->param.uid == uid) if (cmdp->param.uid == uid)
goto gotuid; goto gotuid;
error( "IMAP error: unexpected FETCH response (UID %d)\n", uid ); error( "IMAP error: unexpected FETCH response (UID %u)\n", uid );
free_list( list ); free_list( list );
return LIST_BAD; return LIST_BAD;
gotuid: gotuid:
@ -1166,13 +1164,15 @@ parse_response_code( imap_store_t *ctx, imap_cmd_t *cmd, char *s )
goto bad_resp; goto bad_resp;
if (!strcmp( "UIDVALIDITY", arg )) { if (!strcmp( "UIDVALIDITY", arg )) {
if (!(arg = next_arg( &s )) || if (!(arg = next_arg( &s )) ||
(ctx->uidvalidity = strtoll( arg, &earg, 10 ), *earg)) (ctx->uidvalidity = strtoul( arg, &earg, 10 ), *earg))
{ {
error( "IMAP error: malformed UIDVALIDITY status\n" ); error( "IMAP error: malformed UIDVALIDITY status\n" );
return RESP_CANCEL; return RESP_CANCEL;
} }
} else if (!strcmp( "UIDNEXT", arg )) { } else if (!strcmp( "UIDNEXT", arg )) {
if (!(arg = next_arg( &s )) || !(ctx->uidnext = atoi( arg ))) { if (!(arg = next_arg( &s )) ||
(ctx->uidnext = strtoul( arg, &earg, 10 ), *earg))
{
error( "IMAP error: malformed NEXTUID status\n" ); error( "IMAP error: malformed NEXTUID status\n" );
return RESP_CANCEL; return RESP_CANCEL;
} }
@ -1186,9 +1186,9 @@ parse_response_code( imap_store_t *ctx, imap_cmd_t *cmd, char *s )
error( "*** IMAP ALERT *** %s\n", p ); error( "*** IMAP ALERT *** %s\n", p );
} else if (cmd && !strcmp( "APPENDUID", arg )) { } else if (cmd && !strcmp( "APPENDUID", arg )) {
if (!(arg = next_arg( &s )) || if (!(arg = next_arg( &s )) ||
(ctx->uidvalidity = strtoll( arg, &earg, 10 ), *earg) || (ctx->uidvalidity = strtoul( arg, &earg, 10 ), *earg) ||
!(arg = next_arg( &s )) || !(arg = next_arg( &s )) ||
!(((imap_cmd_out_uid_t *)cmd)->out_uid = atoi( arg ))) (((imap_cmd_out_uid_t *)cmd)->out_uid = strtoul( arg, &earg, 10 ), *earg))
{ {
error( "IMAP error: malformed APPENDUID status\n" ); error( "IMAP error: malformed APPENDUID status\n" );
return RESP_CANCEL; return RESP_CANCEL;
@ -2538,7 +2538,7 @@ static void imap_submit_load( imap_store_t *, const char *, int, imap_load_box_s
static void imap_submit_load_p3( imap_store_t *ctx, imap_load_box_state_t * ); static void imap_submit_load_p3( imap_store_t *ctx, imap_load_box_state_t * );
static void static void
imap_load_box( store_t *gctx, int minuid, int maxuid, int newuid, int seenuid, int_array_t excs, imap_load_box( store_t *gctx, uint minuid, uint maxuid, uint newuid, uint seenuid, uint_array_t excs,
void (*cb)( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux ), void *aux ) void (*cb)( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux ), void *aux )
{ {
imap_store_t *ctx = (imap_store_t *)gctx; imap_store_t *ctx = (imap_store_t *)gctx;
@ -2554,15 +2554,15 @@ imap_load_box( store_t *gctx, int minuid, int maxuid, int newuid, int seenuid, i
for (bl = 0; i < excs.size && bl < 960; i++) { for (bl = 0; i < excs.size && bl < 960; i++) {
if (bl) if (bl)
buf[bl++] = ','; buf[bl++] = ',';
bl += sprintf( buf + bl, "%d", excs.data[i] ); bl += sprintf( buf + bl, "%u", excs.data[i] );
j = i; j = i;
for (; i + 1 < excs.size && excs.data[i + 1] == excs.data[i] + 1; i++) {} for (; i + 1 < excs.size && excs.data[i + 1] == excs.data[i] + 1; i++) {}
if (i != j) if (i != j)
bl += sprintf( buf + bl, ":%d", excs.data[i] ); bl += sprintf( buf + bl, ":%u", excs.data[i] );
} }
imap_submit_load( ctx, buf, shifted_bit( ctx->opts, OPEN_OLD_IDS, WantMsgids ), sts ); imap_submit_load( ctx, buf, shifted_bit( ctx->opts, OPEN_OLD_IDS, WantMsgids ), sts );
} }
if (maxuid == INT_MAX) if (maxuid == UINT_MAX)
maxuid = ctx->uidnext - 1; maxuid = ctx->uidnext - 1;
if (maxuid >= minuid) { if (maxuid >= minuid) {
imap_range_t ranges[3]; imap_range_t ranges[3];
@ -2578,7 +2578,7 @@ imap_load_box( store_t *gctx, int minuid, int maxuid, int newuid, int seenuid, i
if (ctx->opts & OPEN_OLD_IDS) if (ctx->opts & OPEN_OLD_IDS)
imap_set_range( ranges, &nranges, WantMsgids, 0, seenuid ); imap_set_range( ranges, &nranges, WantMsgids, 0, seenuid );
for (int r = 0; r < nranges; r++) { for (int r = 0; r < nranges; r++) {
sprintf( buf, "%d:%d", ranges[r].first, ranges[r].last ); sprintf( buf, "%u:%u", ranges[r].first, ranges[r].last );
imap_submit_load( ctx, buf, ranges[r].flags, sts ); imap_submit_load( ctx, buf, ranges[r].flags, sts );
} }
} }
@ -2633,7 +2633,7 @@ imap_fetch_msg( store_t *ctx, message_t *msg, msg_data_t *data,
cmd->msg_data = data; cmd->msg_data = data;
data->data = 0; data->data = 0;
imap_exec( (imap_store_t *)ctx, &cmd->gen.gen, imap_fetch_msg_p2, imap_exec( (imap_store_t *)ctx, &cmd->gen.gen, imap_fetch_msg_p2,
"UID FETCH %d (%s%sBODY.PEEK[])", msg->uid, "UID FETCH %u (%s%sBODY.PEEK[])", msg->uid,
!(msg->status & M_FLAGS) ? "FLAGS " : "", !(msg->status & M_FLAGS) ? "FLAGS " : "",
(data->date== -1) ? "INTERNALDATE " : "" ); (data->date== -1) ? "INTERNALDATE " : "" );
} }
@ -2680,18 +2680,18 @@ static void imap_set_flags_p2( imap_store_t *, imap_cmd_t *, int );
static void imap_set_flags_p3( imap_set_msg_flags_state_t * ); static void imap_set_flags_p3( imap_set_msg_flags_state_t * );
static void static void
imap_flags_helper( imap_store_t *ctx, int uid, char what, int flags, imap_flags_helper( imap_store_t *ctx, uint uid, char what, int flags,
imap_set_msg_flags_state_t *sts ) imap_set_msg_flags_state_t *sts )
{ {
char buf[256]; char buf[256];
buf[imap_make_flags( flags, buf )] = 0; buf[imap_make_flags( flags, buf )] = 0;
imap_exec( ctx, imap_refcounted_new_cmd( &sts->gen ), imap_set_flags_p2, imap_exec( ctx, imap_refcounted_new_cmd( &sts->gen ), imap_set_flags_p2,
"UID STORE %d %cFLAGS.SILENT %s", uid, what, buf ); "UID STORE %u %cFLAGS.SILENT %s", uid, what, buf );
} }
static void static void
imap_set_msg_flags( store_t *gctx, message_t *msg, int uid, int add, int del, imap_set_msg_flags( store_t *gctx, message_t *msg, uint uid, int add, int del,
void (*cb)( int sts, void *aux ), void *aux ) void (*cb)( int sts, void *aux ), void *aux )
{ {
imap_store_t *ctx = (imap_store_t *)gctx; imap_store_t *ctx = (imap_store_t *)gctx;
@ -2759,11 +2759,11 @@ imap_close_box( store_t *gctx,
continue; continue;
if (bl) if (bl)
buf[bl++] = ','; buf[bl++] = ',';
bl += sprintf( buf + bl, "%d", msg->uid ); bl += sprintf( buf + bl, "%u", msg->uid );
fmsg = msg; fmsg = msg;
for (; (nmsg = msg->next) && (nmsg->flags & F_DELETED); msg = nmsg) {} for (; (nmsg = msg->next) && (nmsg->flags & F_DELETED); msg = nmsg) {}
if (msg != fmsg) if (msg != fmsg)
bl += sprintf( buf + bl, ":%d", msg->uid ); bl += sprintf( buf + bl, ":%u", msg->uid );
} }
if (!bl) if (!bl)
break; break;
@ -2813,7 +2813,7 @@ imap_trash_msg( store_t *gctx, message_t *msg,
return; return;
} }
imap_exec( ctx, &cmd->gen, imap_done_simple_msg, imap_exec( ctx, &cmd->gen, imap_done_simple_msg,
CAP(MOVE) ? "UID MOVE %d \"%\\s\"" : "UID COPY %d \"%\\s\"", msg->uid, buf ); CAP(MOVE) ? "UID MOVE %u \"%\\s\"" : "UID COPY %u \"%\\s\"", msg->uid, buf );
free( buf ); free( buf );
} }
@ -2829,7 +2829,7 @@ my_strftime( char *s, size_t max, const char *fmt, const struct tm *tm )
static void static void
imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash, imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
void (*cb)( int sts, int uid, void *aux ), void *aux ) void (*cb)( int sts, uint uid, void *aux ), void *aux )
{ {
imap_store_t *ctx = (imap_store_t *)gctx; imap_store_t *ctx = (imap_store_t *)gctx;
imap_cmd_out_uid_t *cmd; imap_cmd_out_uid_t *cmd;
@ -2891,7 +2891,7 @@ static void imap_find_new_msgs_p3( imap_store_t *, imap_cmd_t *, int );
static void imap_find_new_msgs_p4( imap_store_t *, imap_cmd_t *, int ); static void imap_find_new_msgs_p4( imap_store_t *, imap_cmd_t *, int );
static void static void
imap_find_new_msgs( store_t *gctx, int newuid, imap_find_new_msgs( store_t *gctx, uint newuid,
void (*cb)( int sts, message_t *msgs, void *aux ), void *aux ) void (*cb)( int sts, message_t *msgs, void *aux ), void *aux )
{ {
imap_store_t *ctx = (imap_store_t *)gctx; imap_store_t *ctx = (imap_store_t *)gctx;
@ -2938,7 +2938,7 @@ imap_find_new_msgs_p3( imap_store_t *ctx, imap_cmd_t *gcmd, int response )
INIT_IMAP_CMD(imap_cmd_find_new_t, cmd, cmdp->callback, cmdp->callback_aux) INIT_IMAP_CMD(imap_cmd_find_new_t, cmd, cmdp->callback, cmdp->callback_aux)
cmd->out_msgs = cmdp->out_msgs; cmd->out_msgs = cmdp->out_msgs;
imap_exec( (imap_store_t *)ctx, &cmd->gen, imap_find_new_msgs_p4, imap_exec( (imap_store_t *)ctx, &cmd->gen, imap_find_new_msgs_p4,
"UID FETCH %d:%d (UID BODY.PEEK[HEADER.FIELDS (X-TUID)])", cmdp->uid, ctx->uidnext - 1 ); "UID FETCH %u:%u (UID BODY.PEEK[HEADER.FIELDS (X-TUID)])", cmdp->uid, ctx->uidnext - 1 );
} }
static void static void

View File

@ -70,9 +70,9 @@ typedef struct {
typedef struct { typedef struct {
store_t gen; store_t gen;
uint opts; uint opts;
int uvfd, uvok, uidvalidity, nuid, is_inbox, fresh[3]; int uvfd, uvok, is_inbox, fresh[3];
int minuid, maxuid, newuid, seenuid; uint minuid, maxuid, newuid, seenuid, uidvalidity, nuid;
int_array_t excs; uint_array_t excs;
char *path; /* own */ char *path; /* own */
char *trash; char *trash;
#ifdef USE_DB #ifdef USE_DB
@ -518,7 +518,8 @@ typedef struct {
char *base; char *base;
char *msgid; char *msgid;
int size; int size;
uint uid:31, recent:1; uint uid;
uchar recent;
char tuid[TUIDL]; char tuid[TUIDL];
} msg_t; } msg_t;
@ -650,7 +651,8 @@ maildir_store_uidval( maildir_store_t *ctx )
{ {
int n; int n;
#ifdef USE_DB #ifdef USE_DB
int ret, uv[2]; int ret;
uint uv[2];
#endif #endif
char buf[128]; char buf[128];
@ -673,7 +675,7 @@ maildir_store_uidval( maildir_store_t *ctx )
} else } else
#endif /* USE_DB */ #endif /* USE_DB */
{ {
n = sprintf( buf, "%d\n%d\n", ctx->uidvalidity, ctx->nuid ); n = sprintf( buf, "%u\n%u\n", ctx->uidvalidity, ctx->nuid );
lseek( ctx->uvfd, 0, SEEK_SET ); lseek( ctx->uvfd, 0, SEEK_SET );
if (write( ctx->uvfd, buf, n ) != n || ftruncate( ctx->uvfd, n ) || (UseFSync && fdatasync( ctx->uvfd ))) { if (write( ctx->uvfd, buf, n ) != n || ftruncate( ctx->uvfd, n ) || (UseFSync && fdatasync( ctx->uvfd ))) {
error( "Maildir error: cannot write UIDVALIDITY.\n" ); error( "Maildir error: cannot write UIDVALIDITY.\n" );
@ -755,14 +757,14 @@ maildir_uidval_lock( maildir_store_t *ctx )
} }
return maildir_init_uidval_new( ctx ); return maildir_init_uidval_new( ctx );
} }
ctx->uidvalidity = ((int *)value.data)[0]; ctx->uidvalidity = ((uint *)value.data)[0];
ctx->nuid = ((int *)value.data)[1]; ctx->nuid = ((uint *)value.data)[1];
} else } else
#endif #endif
{ {
lseek( ctx->uvfd, 0, SEEK_SET ); lseek( ctx->uvfd, 0, SEEK_SET );
if ((n = read( ctx->uvfd, buf, sizeof(buf) - 1 )) <= 0 || if ((n = read( ctx->uvfd, buf, sizeof(buf) - 1 )) <= 0 ||
(buf[n] = 0, sscanf( buf, "%d\n%d", &ctx->uidvalidity, &ctx->nuid ) != 2)) { (buf[n] = 0, sscanf( buf, "%u\n%u", &ctx->uidvalidity, &ctx->nuid ) != 2)) {
#if 1 #if 1
/* In a generic driver, resetting the UID validity would be the right thing. /* In a generic driver, resetting the UID validity would be the right thing.
* But this would mess up the sync state completely. So better bail out and * But this would mess up the sync state completely. So better bail out and
@ -800,7 +802,7 @@ lcktmr_timeout( void *aux )
} }
static int static int
maildir_obtain_uid( maildir_store_t *ctx, int *uid ) maildir_obtain_uid( maildir_store_t *ctx, uint *uid )
{ {
int ret; int ret;
@ -812,7 +814,7 @@ maildir_obtain_uid( maildir_store_t *ctx, int *uid )
#ifdef USE_DB #ifdef USE_DB
static int static int
maildir_set_uid( maildir_store_t *ctx, const char *name, int *uid ) maildir_set_uid( maildir_store_t *ctx, const char *name, uint *uid )
{ {
int ret; int ret;
@ -906,7 +908,8 @@ maildir_scan( maildir_store_t *ctx, msg_t_array_alloc_t *msglist )
DBC *dbc; DBC *dbc;
#endif /* USE_DB */ #endif /* USE_DB */
msg_t *entry; msg_t *entry;
int i, uid, bl, fnl, ret; int i, bl, fnl, ret;
uint uid;
time_t now, stamps[2]; time_t now, stamps[2];
struct stat st; struct stat st;
char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX]; char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX];
@ -914,7 +917,7 @@ maildir_scan( maildir_store_t *ctx, msg_t_array_alloc_t *msglist )
again: again:
ARRAY_INIT( msglist ); ARRAY_INIT( msglist );
ctx->total_msgs = ctx->recent_msgs = 0; ctx->total_msgs = ctx->recent_msgs = 0;
if (ctx->uvok || ctx->maxuid == INT_MAX) { if (ctx->uvok || ctx->maxuid == UINT_MAX) {
#ifdef USE_DB #ifdef USE_DB
if (ctx->usedb) { if (ctx->usedb) {
if (db_create( &tdb, 0, 0 )) { if (db_create( &tdb, 0, 0 )) {
@ -980,24 +983,24 @@ maildir_scan( maildir_store_t *ctx, msg_t_array_alloc_t *msglist )
closedir( d ); closedir( d );
goto bork; goto bork;
} }
uid = INT_MAX; uid = UINT_MAX;
} else { } else {
value.size = 0; value.size = 0;
if ((ret = tdb->put( tdb, 0, &key, &value, 0 ))) { if ((ret = tdb->put( tdb, 0, &key, &value, 0 ))) {
tdb->err( tdb, ret, "Maildir error: tdb->put()" ); tdb->err( tdb, ret, "Maildir error: tdb->put()" );
goto mbork; goto mbork;
} }
uid = *(int *)value.data; uid = *(uint *)value.data;
} }
} else } else
#endif /* USE_DB */ #endif /* USE_DB */
{ {
uid = (ctx->uvok && (u = strstr( e->d_name, ",U=" ))) ? atoi( u + 3 ) : 0; uid = (ctx->uvok && (u = strstr( e->d_name, ",U=" ))) ? strtoul( u + 3, NULL, 10 ) : 0;
if (!uid) if (!uid)
uid = INT_MAX; uid = UINT_MAX;
} }
if (uid <= ctx->maxuid) { if (uid <= ctx->maxuid) {
if (uid < ctx->minuid && !find_int_array( ctx->excs, uid )) if (uid < ctx->minuid && !find_uint_array( ctx->excs, uid ))
continue; continue;
entry = msg_t_array_append( msglist ); entry = msg_t_array_append( msglist );
entry->base = nfstrdup( e->d_name ); entry->base = nfstrdup( e->d_name );
@ -1059,11 +1062,11 @@ maildir_scan( maildir_store_t *ctx, msg_t_array_alloc_t *msglist )
qsort( msglist->array.data, msglist->array.size, sizeof(msg_t), maildir_compare ); qsort( msglist->array.data, msglist->array.size, sizeof(msg_t), maildir_compare );
for (uid = i = 0; i < msglist->array.size; i++) { for (uid = i = 0; i < msglist->array.size; i++) {
entry = &msglist->array.data[i]; entry = &msglist->array.data[i];
if (entry->uid != INT_MAX) { if (entry->uid != UINT_MAX) {
if (uid == entry->uid) { if (uid == entry->uid) {
#if 1 #if 1
/* See comment in maildir_uidval_lock() why this is fatal. */ /* See comment in maildir_uidval_lock() why this is fatal. */
error( "Maildir error: duplicate UID %d.\n", uid ); error( "Maildir error: duplicate UID %u.\n", uid );
maildir_free_scan( msglist ); maildir_free_scan( msglist );
return DRV_BOX_BAD; return DRV_BOX_BAD;
#else #else
@ -1080,7 +1083,7 @@ maildir_scan( maildir_store_t *ctx, msg_t_array_alloc_t *msglist )
if (uid > ctx->nuid) { if (uid > ctx->nuid) {
/* In principle, we could just warn and top up nuid. However, getting into this /* In principle, we could just warn and top up nuid. However, getting into this
* situation might indicate some serious trouble, so let's not make it worse. */ * situation might indicate some serious trouble, so let's not make it worse. */
error( "Maildir error: UID %d is beyond highest assigned UID %d.\n", uid, ctx->nuid ); error( "Maildir error: UID %u is beyond highest assigned UID %u.\n", uid, ctx->nuid );
maildir_free_scan( msglist ); maildir_free_scan( msglist );
return DRV_BOX_BAD; return DRV_BOX_BAD;
} }
@ -1105,8 +1108,8 @@ maildir_scan( maildir_store_t *ctx, msg_t_array_alloc_t *msglist )
else else
u = ru = strchr( entry->base, conf->info_delimiter ); u = ru = strchr( entry->base, conf->info_delimiter );
fnl = (u ? fnl = (u ?
nfsnprintf( buf + bl, sizeof(buf) - bl, "%s/%.*s,U=%d%s", subdirs[entry->recent], (int)(u - entry->base), entry->base, uid, ru ) : nfsnprintf( buf + bl, sizeof(buf) - bl, "%s/%.*s,U=%u%s", subdirs[entry->recent], (int)(u - entry->base), entry->base, uid, ru ) :
nfsnprintf( buf + bl, sizeof(buf) - bl, "%s/%s,U=%d", subdirs[entry->recent], entry->base, uid )) nfsnprintf( buf + bl, sizeof(buf) - bl, "%s/%s,U=%u", subdirs[entry->recent], entry->base, uid ))
- 4; - 4;
memcpy( nbuf, buf, bl + 4 ); memcpy( nbuf, buf, bl + 4 );
nfsnprintf( nbuf + bl + 4, sizeof(nbuf) - bl - 4, "%s", entry->base ); nfsnprintf( nbuf + bl + 4, sizeof(nbuf) - bl - 4, "%s", entry->base );
@ -1160,7 +1163,7 @@ maildir_scan( maildir_store_t *ctx, msg_t_array_alloc_t *msglist )
break; break;
if (want_tuid && starts_with( nbuf, bufl, "X-TUID: ", 8 )) { if (want_tuid && starts_with( nbuf, bufl, "X-TUID: ", 8 )) {
if (bufl < 8 + TUIDL) { if (bufl < 8 + TUIDL) {
error( "Maildir error: malformed X-TUID header (UID %d)\n", uid ); error( "Maildir error: malformed X-TUID header (UID %u)\n", uid );
continue; continue;
} }
memcpy( entry->tuid, nbuf + 8, TUIDL ); memcpy( entry->tuid, nbuf + 8, TUIDL );
@ -1411,7 +1414,7 @@ maildir_prepare_load_box( store_t *gctx, int opts )
} }
static void static void
maildir_load_box( store_t *gctx, int minuid, int maxuid, int newuid, int seenuid, int_array_t excs, maildir_load_box( store_t *gctx, uint minuid, uint maxuid, uint newuid, uint seenuid, uint_array_t excs,
void (*cb)( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux ), void *aux ) void (*cb)( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux ), void *aux )
{ {
maildir_store_t *ctx = (maildir_store_t *)gctx; maildir_store_t *ctx = (maildir_store_t *)gctx;
@ -1454,31 +1457,31 @@ maildir_rescan( maildir_store_t *ctx )
{ {
if (!msg) { if (!msg) {
#if 0 #if 0
debug( "adding new message %d\n", msglist.array.data[i].uid ); debug( "adding new message %u\n", msglist.array.data[i].uid );
maildir_app_msg( ctx, &msgapp, msglist.array.data + i ); maildir_app_msg( ctx, &msgapp, msglist.array.data + i );
#else #else
debug( "ignoring new message %d\n", msglist.array.data[i].uid ); debug( "ignoring new message %u\n", msglist.array.data[i].uid );
#endif #endif
i++; i++;
} else if (i >= msglist.array.size) { } else if (i >= msglist.array.size) {
debug( "purging deleted message %d\n", msg->gen.uid ); debug( "purging deleted message %u\n", msg->gen.uid );
msg->gen.status = M_DEAD; msg->gen.status = M_DEAD;
msgapp = &msg->gen.next; msgapp = &msg->gen.next;
} else if (msglist.array.data[i].uid < msg->gen.uid) { } else if (msglist.array.data[i].uid < msg->gen.uid) {
/* this should not happen, actually */ /* this should not happen, actually */
#if 0 #if 0
debug( "adding new message %d\n", msglist.array.data[i].uid ); debug( "adding new message %u\n", msglist.array.data[i].uid );
maildir_app_msg( ctx, &msgapp, msglist.array.data + i ); maildir_app_msg( ctx, &msgapp, msglist.array.data + i );
#else #else
debug( "ignoring new message %d\n", msglist.array.data[i].uid ); debug( "ignoring new message %u\n", msglist.array.data[i].uid );
#endif #endif
i++; i++;
} else if (msglist.array.data[i].uid > msg->gen.uid) { } else if (msglist.array.data[i].uid > msg->gen.uid) {
debug( "purging deleted message %d\n", msg->gen.uid ); debug( "purging deleted message %u\n", msg->gen.uid );
msg->gen.status = M_DEAD; msg->gen.status = M_DEAD;
msgapp = &msg->gen.next; msgapp = &msg->gen.next;
} else { } else {
debug( "updating message %d\n", msg->gen.uid ); debug( "updating message %u\n", msg->gen.uid );
msg->gen.status &= ~(M_FLAGS|M_RECENT); msg->gen.status &= ~(M_FLAGS|M_RECENT);
free( msg->base ); free( msg->base );
free( msg->gen.msgid ); free( msg->gen.msgid );
@ -1558,11 +1561,12 @@ maildir_make_flags( char info_delimiter, int flags, char *buf )
static void static void
maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash, maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
void (*cb)( int sts, int uid, void *aux ), void *aux ) void (*cb)( int sts, uint uid, void *aux ), void *aux )
{ {
maildir_store_t *ctx = (maildir_store_t *)gctx; maildir_store_t *ctx = (maildir_store_t *)gctx;
const char *box; const char *box;
int ret, fd, bl, uid; int ret, fd, bl;
uint uid;
char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX], fbuf[NUM_FLAGS + 3], base[128]; char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX], fbuf[NUM_FLAGS + 3], base[128];
bl = nfsnprintf( base, sizeof(base), "%ld.%d_%d.%s", (long)time( 0 ), Pid, ++MaildirCount, Hostname ); bl = nfsnprintf( base, sizeof(base), "%ld.%d_%d.%s", (long)time( 0 ), Pid, ++MaildirCount, Hostname );
@ -1582,7 +1586,7 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
cb( ret, 0, aux ); cb( ret, 0, aux );
return; return;
} }
nfsnprintf( base + bl, sizeof(base) - bl, ",U=%d", uid ); nfsnprintf( base + bl, sizeof(base) - bl, ",U=%u", uid );
} }
box = ctx->path; box = ctx->path;
} else { } else {
@ -1651,14 +1655,14 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
} }
static void static void
maildir_find_new_msgs( store_t *gctx ATTR_UNUSED, int newuid ATTR_UNUSED, maildir_find_new_msgs( store_t *gctx ATTR_UNUSED, uint newuid ATTR_UNUSED,
void (*cb)( int sts, message_t *msgs, void *aux ) ATTR_UNUSED, void *aux ATTR_UNUSED ) void (*cb)( int sts, message_t *msgs, void *aux ) ATTR_UNUSED, void *aux ATTR_UNUSED )
{ {
assert( !"maildir_find_new_msgs is not supposed to be called" ); assert( !"maildir_find_new_msgs is not supposed to be called" );
} }
static void static void
maildir_set_msg_flags( store_t *gctx, message_t *gmsg, int uid ATTR_UNUSED, int add, int del, maildir_set_msg_flags( store_t *gctx, message_t *gmsg, uint uid ATTR_UNUSED, int add, int del,
void (*cb)( int sts, void *aux ), void *aux ) void (*cb)( int sts, void *aux ), void *aux )
{ {
maildir_store_conf_t *conf = (maildir_store_conf_t *)gctx->conf; maildir_store_conf_t *conf = (maildir_store_conf_t *)gctx->conf;

View File

@ -195,8 +195,8 @@ proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@void *aux ), v
//# DEFINE load_box_pre_print_args //# DEFINE load_box_pre_print_args
static char ubuf[12]; static char ubuf[12];
//# END //# END
//# DEFINE load_box_print_fmt_args , [%d,%s] (new >= %d, seen <= %d) //# DEFINE load_box_print_fmt_args , [%u,%s] (new >= %u, seen <= %u)
//# DEFINE load_box_print_pass_args , minuid, (maxuid == INT_MAX) ? "inf" : (nfsnprintf( ubuf, sizeof(ubuf), "%d", maxuid ), ubuf), newuid, seenuid //# DEFINE load_box_print_pass_args , minuid, (maxuid == UINT_MAX) ? "inf" : (nfsnprintf( ubuf, sizeof(ubuf), "%u", maxuid ), ubuf), newuid, seenuid
//# DEFINE load_box_print_args //# DEFINE load_box_print_args
if (excs.size) { if (excs.size) {
debugn( " excs:" ); debugn( " excs:" );
@ -213,7 +213,7 @@ proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@void *aux ), v
//# DEFINE load_box_print_cb_args //# DEFINE load_box_print_cb_args
if (sts == DRV_OK) { if (sts == DRV_OK) {
for (message_t *msg = msgs; msg; msg = msg->next) for (message_t *msg = msgs; msg; msg = msg->next)
debug( " uid=%5d, flags=%4s, size=%6d, tuid=%." stringify(TUIDL) "s\n", debug( " uid=%5u, flags=%4s, size=%6d, tuid=%." stringify(TUIDL) "s\n",
msg->uid, (msg->status & M_FLAGS) ? (proxy_make_flags( msg->flags, fbuf ), fbuf) : "?", msg->size, *msg->tuid ? msg->tuid : "?" ); msg->uid, (msg->status & M_FLAGS) ? (proxy_make_flags( msg->flags, fbuf ), fbuf) : "?", msg->size, *msg->tuid ? msg->tuid : "?" );
} }
//# END //# END
@ -223,7 +223,7 @@ proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@void *aux ), v
//# DEFINE find_new_msgs_print_cb_args //# DEFINE find_new_msgs_print_cb_args
if (sts == DRV_OK) { if (sts == DRV_OK) {
for (message_t *msg = msgs; msg; msg = msg->next) for (message_t *msg = msgs; msg; msg = msg->next)
debug( " uid=%5d, tuid=%." stringify(TUIDL) "s\n", msg->uid, msg->tuid ); debug( " uid=%5u, tuid=%." stringify(TUIDL) "s\n", msg->uid, msg->tuid );
} }
//# END //# END
@ -233,7 +233,7 @@ proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@void *aux ), v
//# DEFINE fetch_msg_assign_state //# DEFINE fetch_msg_assign_state
cmd->data = data; cmd->data = data;
//# END //# END
//# DEFINE fetch_msg_print_fmt_args , uid=%d, want_flags=%s, want_date=%s //# DEFINE fetch_msg_print_fmt_args , uid=%u, want_flags=%s, want_date=%s
//# DEFINE fetch_msg_print_pass_args , msg->uid, !(msg->status & M_FLAGS) ? "yes" : "no", data->date ? "yes" : "no" //# DEFINE fetch_msg_print_pass_args , msg->uid, !(msg->status & M_FLAGS) ? "yes" : "no", data->date ? "yes" : "no"
//# DEFINE fetch_msg_pre_print_cb_args //# DEFINE fetch_msg_pre_print_cb_args
static char fbuf[as(Flags) + 1]; static char fbuf[as(Flags) + 1];
@ -270,10 +270,10 @@ proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@void *aux ), v
proxy_make_flags( add, fbuf1 ); proxy_make_flags( add, fbuf1 );
proxy_make_flags( del, fbuf2 ); proxy_make_flags( del, fbuf2 );
//# END //# END
//# DEFINE set_msg_flags_print_fmt_args , uid=%d, add=%s, del=%s //# DEFINE set_msg_flags_print_fmt_args , uid=%u, add=%s, del=%s
//# DEFINE set_msg_flags_print_pass_args , uid, fbuf1, fbuf2 //# DEFINE set_msg_flags_print_pass_args , uid, fbuf1, fbuf2
//# DEFINE trash_msg_print_fmt_args , uid=%d //# DEFINE trash_msg_print_fmt_args , uid=%u
//# DEFINE trash_msg_print_pass_args , msg->uid //# DEFINE trash_msg_print_pass_args , msg->uid
//# DEFINE free_store_action //# DEFINE free_store_action

View File

@ -141,7 +141,7 @@ make_flags( int flags, char *buf )
typedef struct sync_rec { typedef struct sync_rec {
struct sync_rec *next; struct sync_rec *next;
/* string_list_t *keywords; */ /* string_list_t *keywords; */
int uid[2]; uint uid[2];
message_t *msg[2]; message_t *msg[2];
uchar status, wstate, flags, aflags[2], dflags[2]; uchar status, wstate, flags, aflags[2], dflags[2];
char tuid[TUIDL]; char tuid[TUIDL];
@ -158,15 +158,15 @@ typedef struct {
driver_t *drv[2]; driver_t *drv[2];
const char *orig_name[2]; const char *orig_name[2];
message_t *msgs[2], *new_msgs[2]; message_t *msgs[2], *new_msgs[2];
int_array_alloc_t trashed_msgs[2]; uint_array_alloc_t trashed_msgs[2];
int state[2], opts[2], ref_count, nsrecs, ret, lfd, existing, replayed; int state[2], opts[2], ref_count, nsrecs, ret, lfd, existing, replayed;
int new_pending[2], flags_pending[2], trash_pending[2]; int new_pending[2], flags_pending[2], trash_pending[2];
int maxuid[2]; /* highest UID that was already propagated */ uint maxuid[2]; // highest UID that was already propagated
int newmaxuid[2]; /* highest UID that is currently being propagated */ uint newmaxuid[2]; // highest UID that is currently being propagated
int uidval[2]; /* UID validity value */ uint uidval[2]; // UID validity value
int newuidval[2]; /* UID validity obtained from driver */ uint newuidval[2]; // UID validity obtained from driver
int newuid[2]; /* TUID lookup makes sense only for UIDs >= this */ uint newuid[2]; // TUID lookup makes sense only for UIDs >= this
int mmaxxuid; /* highest expired UID on master */ uint mmaxxuid; // highest expired UID on master
} sync_vars_t; } sync_vars_t;
static void sync_ref( sync_vars_t *svars ) { ++svars->ref_count; } static void sync_ref( sync_vars_t *svars ) { ++svars->ref_count; }
@ -239,7 +239,7 @@ match_tuids( sync_vars_t *svars, int t, message_t *msgs )
if (srec->status & S_DEAD) if (srec->status & S_DEAD)
continue; continue;
if (!srec->uid[t] && srec->tuid[0]) { if (!srec->uid[t] && srec->tuid[0]) {
debug( " pair(%d,%d): lookup %s, TUID %." stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], str_ms[t], srec->tuid ); debug( " pair(%u,%u): lookup %s, TUID %." stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], str_ms[t], srec->tuid );
for (tmsg = ntmsg; tmsg; tmsg = tmsg->next) { for (tmsg = ntmsg; tmsg; tmsg = tmsg->next) {
if (tmsg->status & M_DEAD) if (tmsg->status & M_DEAD)
continue; continue;
@ -257,15 +257,15 @@ match_tuids( sync_vars_t *svars, int t, message_t *msgs )
} }
} }
debug( " -> TUID lost\n" ); debug( " -> TUID lost\n" );
jFprintf( svars, "& %d %d\n", srec->uid[M], srec->uid[S] ); jFprintf( svars, "& %u %u\n", srec->uid[M], srec->uid[S] );
srec->flags = 0; srec->flags = 0;
// Note: status remains S_PENDING. // Note: status remains S_PENDING.
srec->tuid[0] = 0; srec->tuid[0] = 0;
num_lost++; num_lost++;
continue; continue;
mfound: mfound:
debug( " -> new UID %d %s\n", tmsg->uid, diag ); debug( " -> new UID %u %s\n", tmsg->uid, diag );
jFprintf( svars, "%c %d %d %d\n", "<>"[t], srec->uid[M], srec->uid[S], tmsg->uid ); jFprintf( svars, "%c %u %u %u\n", "<>"[t], srec->uid[M], srec->uid[S], tmsg->uid );
tmsg->srec = srec; tmsg->srec = srec;
srec->msg[t] = tmsg; srec->msg[t] = tmsg;
ntmsg = tmsg->next; ntmsg = tmsg->next;
@ -280,7 +280,7 @@ match_tuids( sync_vars_t *svars, int t, message_t *msgs )
typedef struct copy_vars { typedef struct copy_vars {
void (*cb)( int sts, int uid, struct copy_vars *vars ); void (*cb)( int sts, uint uid, struct copy_vars *vars );
void *aux; void *aux;
sync_rec_t *srec; /* also ->tuid */ sync_rec_t *srec; /* also ->tuid */
message_t *msg; message_t *msg;
@ -300,7 +300,7 @@ copy_msg( copy_vars_t *vars )
svars->drv[t]->fetch_msg( svars->ctx[t], vars->msg, &vars->data, msg_fetched, vars ); svars->drv[t]->fetch_msg( svars->ctx[t], vars->msg, &vars->data, msg_fetched, vars );
} }
static void msg_stored( int sts, int uid, void *aux ); static void msg_stored( int sts, uint uid, void *aux );
static void static void
copy_msg_bytes( char **out_ptr, const char *in_buf, int *in_idx, int in_len, int in_cr, int out_cr ) copy_msg_bytes( char **out_ptr, const char *in_buf, int *in_idx, int in_len, int in_cr, int out_cr )
@ -424,7 +424,7 @@ msg_fetched( int sts, void *aux )
tcr = (svars->drv[t]->get_caps( svars->ctx[t] ) / DRV_CRLF) & 1; tcr = (svars->drv[t]->get_caps( svars->ctx[t] ) / DRV_CRLF) & 1;
if (vars->srec || scr != tcr) { if (vars->srec || scr != tcr) {
if (!copy_msg_convert( scr, tcr, vars )) { if (!copy_msg_convert( scr, tcr, vars )) {
warn( "Warning: message %d from %s has incomplete header.\n", warn( "Warning: message %u from %s has incomplete header.\n",
vars->msg->uid, str_ms[1-t] ); vars->msg->uid, str_ms[1-t] );
vars->cb( SYNC_NOGOOD, 0, vars ); vars->cb( SYNC_NOGOOD, 0, vars );
return; return;
@ -446,7 +446,7 @@ msg_fetched( int sts, void *aux )
} }
static void static void
msg_stored( int sts, int uid, void *aux ) msg_stored( int sts, uint uid, void *aux )
{ {
copy_vars_t *vars = (copy_vars_t *)aux; copy_vars_t *vars = (copy_vars_t *)aux;
DECL_SVARS; DECL_SVARS;
@ -461,7 +461,7 @@ msg_stored( int sts, int uid, void *aux )
case DRV_MSG_BAD: case DRV_MSG_BAD:
INIT_SVARS(vars->aux); INIT_SVARS(vars->aux);
(void)svars; (void)svars;
warn( "Warning: %s refuses to store message %d from %s.\n", warn( "Warning: %s refuses to store message %u from %s.\n",
str_ms[t], vars->msg->uid, str_ms[1-t] ); str_ms[t], vars->msg->uid, str_ms[1-t] );
vars->cb( SYNC_NOGOOD, 0, vars ); vars->cb( SYNC_NOGOOD, 0, vars );
break; break;
@ -660,16 +660,16 @@ save_state( sync_vars_t *svars )
char fbuf[16]; /* enlarge when support for keywords is added */ char fbuf[16]; /* enlarge when support for keywords is added */
Fprintf( svars->nfp, Fprintf( svars->nfp,
"MasterUidValidity %d\nSlaveUidValidity %d\nMaxPulledUid %d\nMaxPushedUid %d\n", "MasterUidValidity %u\nSlaveUidValidity %u\nMaxPulledUid %u\nMaxPushedUid %u\n",
svars->uidval[M], svars->uidval[S], svars->maxuid[M], svars->maxuid[S] ); svars->uidval[M], svars->uidval[S], svars->maxuid[M], svars->maxuid[S] );
if (svars->mmaxxuid) if (svars->mmaxxuid)
Fprintf( svars->nfp, "MaxExpiredMasterUid %d\n", svars->mmaxxuid ); Fprintf( svars->nfp, "MaxExpiredMasterUid %u\n", svars->mmaxxuid );
Fprintf( svars->nfp, "\n" ); Fprintf( svars->nfp, "\n" );
for (srec = svars->srecs; srec; srec = srec->next) { for (srec = svars->srecs; srec; srec = srec->next) {
if (srec->status & S_DEAD) if (srec->status & S_DEAD)
continue; continue;
make_flags( srec->flags, fbuf ); make_flags( srec->flags, fbuf );
Fprintf( svars->nfp, "%d %d %s%s\n", srec->uid[M], srec->uid[S], Fprintf( svars->nfp, "%u %u %s%s\n", srec->uid[M], srec->uid[S],
(srec->status & S_SKIPPED) ? "^" : (srec->status & S_PENDING) ? "!" : (srec->status & S_EXPIRED) ? "~" : "", fbuf ); (srec->status & S_SKIPPED) ? "^" : (srec->status & S_PENDING) ? "!" : (srec->status & S_EXPIRED) ? "~" : "", fbuf );
} }
@ -690,8 +690,8 @@ load_state( sync_vars_t *svars )
sync_rec_t *srec, *nsrec; sync_rec_t *srec, *nsrec;
char *s; char *s;
FILE *jfp; FILE *jfp;
int line, t, t1, t2, t3; int ll;
int smaxxuid = 0; uint smaxxuid = 0;
char c; char c;
struct stat st; struct stat st;
char fbuf[16]; /* enlarge when support for keywords is added */ char fbuf[16]; /* enlarge when support for keywords is added */
@ -701,42 +701,43 @@ load_state( sync_vars_t *svars )
if (!lock_state( svars )) if (!lock_state( svars ))
goto jbail; goto jbail;
debug( "reading sync state %s ...\n", svars->dname ); debug( "reading sync state %s ...\n", svars->dname );
line = 0; int line = 0;
while (fgets( buf, sizeof(buf), jfp )) { while (fgets( buf, sizeof(buf), jfp )) {
line++; line++;
if (!(t = strlen( buf )) || buf[t - 1] != '\n') { if (!(ll = strlen( buf )) || buf[ll - 1] != '\n') {
error( "Error: incomplete sync state header entry at %s:%d\n", svars->dname, line ); error( "Error: incomplete sync state header entry at %s:%d\n", svars->dname, line );
jbail: jbail:
fclose( jfp ); fclose( jfp );
return 0; return 0;
} }
if (t == 1) if (ll == 1)
goto gothdr; goto gothdr;
if (line == 1 && isdigit( buf[0] )) { if (line == 1 && isdigit( buf[0] )) {
if (sscanf( buf, "%63s %63s", buf1, buf2 ) != 2 || if (sscanf( buf, "%63s %63s", buf1, buf2 ) != 2 ||
sscanf( buf1, "%d:%d", &svars->uidval[M], &svars->maxuid[M] ) < 2 || sscanf( buf1, "%u:%u", &svars->uidval[M], &svars->maxuid[M] ) < 2 ||
sscanf( buf2, "%d:%d:%d", &svars->uidval[S], &smaxxuid, &svars->maxuid[S] ) < 3) { sscanf( buf2, "%u:%u:%u", &svars->uidval[S], &smaxxuid, &svars->maxuid[S] ) < 3) {
error( "Error: invalid sync state header in %s\n", svars->dname ); error( "Error: invalid sync state header in %s\n", svars->dname );
goto jbail; goto jbail;
} }
goto gothdr; goto gothdr;
} }
if (sscanf( buf, "%63s %d", buf1, &t1 ) != 2) { uint uid;
if (sscanf( buf, "%63s %u", buf1, &uid ) != 2) {
error( "Error: malformed sync state header entry at %s:%d\n", svars->dname, line ); error( "Error: malformed sync state header entry at %s:%d\n", svars->dname, line );
goto jbail; goto jbail;
} }
if (!strcmp( buf1, "MasterUidValidity" )) if (!strcmp( buf1, "MasterUidValidity" ))
svars->uidval[M] = t1; svars->uidval[M] = uid;
else if (!strcmp( buf1, "SlaveUidValidity" )) else if (!strcmp( buf1, "SlaveUidValidity" ))
svars->uidval[S] = t1; svars->uidval[S] = uid;
else if (!strcmp( buf1, "MaxPulledUid" )) else if (!strcmp( buf1, "MaxPulledUid" ))
svars->maxuid[M] = t1; svars->maxuid[M] = uid;
else if (!strcmp( buf1, "MaxPushedUid" )) else if (!strcmp( buf1, "MaxPushedUid" ))
svars->maxuid[S] = t1; svars->maxuid[S] = uid;
else if (!strcmp( buf1, "MaxExpiredMasterUid" )) else if (!strcmp( buf1, "MaxExpiredMasterUid" ))
svars->mmaxxuid = t1; svars->mmaxxuid = uid;
else if (!strcmp( buf1, "MaxExpiredSlaveUid" )) // Legacy else if (!strcmp( buf1, "MaxExpiredSlaveUid" )) // Legacy
smaxxuid = t1; smaxxuid = uid;
else { else {
error( "Error: unrecognized sync state header entry at %s:%d\n", svars->dname, line ); error( "Error: unrecognized sync state header entry at %s:%d\n", svars->dname, line );
goto jbail; goto jbail;
@ -747,13 +748,14 @@ load_state( sync_vars_t *svars )
gothdr: gothdr:
while (fgets( buf, sizeof(buf), jfp )) { while (fgets( buf, sizeof(buf), jfp )) {
line++; line++;
if (!(t = strlen( buf )) || buf[--t] != '\n') { if (!(ll = strlen( buf )) || buf[--ll] != '\n') {
error( "Error: incomplete sync state entry at %s:%d\n", svars->dname, line ); error( "Error: incomplete sync state entry at %s:%d\n", svars->dname, line );
goto jbail; goto jbail;
} }
buf[t] = 0; buf[ll] = 0;
fbuf[0] = 0; fbuf[0] = 0;
if (sscanf( buf, "%d %d %15s", &t1, &t2, fbuf ) < 2) { uint t1, t2;
if (sscanf( buf, "%u %u %15s", &t1, &t2, fbuf ) < 2) {
error( "Error: invalid sync state entry at %s:%d\n", svars->dname, line ); error( "Error: invalid sync state entry at %s:%d\n", svars->dname, line );
goto jbail; goto jbail;
} }
@ -770,23 +772,23 @@ load_state( sync_vars_t *svars )
} else if (*s == '~' || *s == 'X' /* Pre-1.3 legacy */) { } else if (*s == '~' || *s == 'X' /* Pre-1.3 legacy */) {
s++; s++;
srec->status = S_EXPIRE | S_EXPIRED; srec->status = S_EXPIRE | S_EXPIRED;
} else if (srec->uid[M] == -1) { // Pre-1.3 legacy } else if (srec->uid[M] == (uint)-1) { // Pre-1.3 legacy
srec->uid[M] = 0; srec->uid[M] = 0;
srec->status = S_SKIPPED; srec->status = S_SKIPPED;
} else if (srec->uid[M] == -2) { } else if (srec->uid[M] == (uint)-2) {
srec->uid[M] = 0; srec->uid[M] = 0;
srec->status = S_PENDING; srec->status = S_PENDING;
} else if (srec->uid[S] == -1) { } else if (srec->uid[S] == (uint)-1) {
srec->uid[S] = 0; srec->uid[S] = 0;
srec->status = S_SKIPPED; srec->status = S_SKIPPED;
} else if (srec->uid[S] == -2) { } else if (srec->uid[S] == (uint)-2) {
srec->uid[S] = 0; srec->uid[S] = 0;
srec->status = S_PENDING; srec->status = S_PENDING;
} else } else
srec->status = 0; srec->status = 0;
srec->wstate = 0; srec->wstate = 0;
srec->flags = parse_flags( s ); srec->flags = parse_flags( s );
debug( " entry (%d,%d,%u,%s)\n", srec->uid[M], srec->uid[S], srec->flags, debug( " entry (%u,%u,%u,%s)\n", srec->uid[M], srec->uid[S], srec->flags,
(srec->status & S_SKIPPED) ? "SKIP" : (srec->status & S_PENDING) ? "FAIL" : (srec->status & S_EXPIRED) ? "XPIRE" : "" ); (srec->status & S_SKIPPED) ? "SKIP" : (srec->status & S_PENDING) ? "FAIL" : (srec->status & S_EXPIRED) ? "XPIRE" : "" );
srec->msg[M] = srec->msg[S] = 0; srec->msg[M] = srec->msg[S] = 0;
srec->tuid[0] = 0; srec->tuid[0] = 0;
@ -807,7 +809,7 @@ load_state( sync_vars_t *svars )
// This is legacy support for pre-1.3 sync states. // This is legacy support for pre-1.3 sync states.
if (smaxxuid) { if (smaxxuid) {
int minwuid = INT_MAX; uint minwuid = UINT_MAX;
for (srec = svars->srecs; srec; srec = srec->next) { for (srec = svars->srecs; srec; srec = srec->next) {
if ((srec->status & (S_DEAD | S_SKIPPED | S_PENDING)) || !srec->uid[M]) if ((srec->status & (S_DEAD | S_SKIPPED | S_PENDING)) || !srec->uid[M])
continue; continue;
@ -834,18 +836,18 @@ load_state( sync_vars_t *svars )
svars->newmaxuid[M] = svars->maxuid[M]; svars->newmaxuid[M] = svars->maxuid[M];
svars->newmaxuid[S] = svars->maxuid[S]; svars->newmaxuid[S] = svars->maxuid[S];
line = 0; int line = 0;
if ((jfp = fopen( svars->jname, "r" ))) { if ((jfp = fopen( svars->jname, "r" ))) {
if (!lock_state( svars )) if (!lock_state( svars ))
goto jbail; goto jbail;
if (!stat( svars->nname, &st ) && fgets( buf, sizeof(buf), jfp )) { if (!stat( svars->nname, &st ) && fgets( buf, sizeof(buf), jfp )) {
debug( "recovering journal ...\n" ); debug( "recovering journal ...\n" );
if (!(t = strlen( buf )) || buf[--t] != '\n') { if (!(ll = strlen( buf )) || buf[--ll] != '\n') {
error( "Error: incomplete journal header in %s\n", svars->jname ); error( "Error: incomplete journal header in %s\n", svars->jname );
goto jbail; goto jbail;
} }
buf[t] = 0; buf[ll] = 0;
if (!equals( buf, t, JOURNAL_VERSION, strlen(JOURNAL_VERSION) )) { if (!equals( buf, ll, JOURNAL_VERSION, strlen(JOURNAL_VERSION) )) {
error( "Error: incompatible journal version " error( "Error: incompatible journal version "
"(got %s, expected " JOURNAL_VERSION ")\n", buf ); "(got %s, expected " JOURNAL_VERSION ")\n", buf );
goto jbail; goto jbail;
@ -854,18 +856,20 @@ load_state( sync_vars_t *svars )
line = 1; line = 1;
while (fgets( buf, sizeof(buf), jfp )) { while (fgets( buf, sizeof(buf), jfp )) {
line++; line++;
if (!(t = strlen( buf )) || buf[--t] != '\n') { if (!(ll = strlen( buf )) || buf[--ll] != '\n') {
error( "Error: incomplete journal entry at %s:%d\n", svars->jname, line ); error( "Error: incomplete journal entry at %s:%d\n", svars->jname, line );
goto jbail; goto jbail;
} }
buf[t] = 0; buf[ll] = 0;
int tn;
uint t1, t2, t3;
if ((c = buf[0]) == '#' ? if ((c = buf[0]) == '#' ?
(t3 = 0, (sscanf( buf + 2, "%d %d %n", &t1, &t2, &t3 ) < 2) || !t3 || (t - t3 != TUIDL + 2)) : (tn = 0, (sscanf( buf + 2, "%u %u %n", &t1, &t2, &tn ) < 2) || !tn || (ll - tn != TUIDL + 2)) :
c == 'S' || c == '!' ? c == 'S' || c == '!' ?
(sscanf( buf + 2, "%d", &t1 ) != 1) : (sscanf( buf + 2, "%u", &t1 ) != 1) :
c == 'F' || c == 'T' || c == '+' || c == '&' || c == '-' || c == '=' || c == '|' ? c == 'F' || c == 'T' || c == '+' || c == '&' || c == '-' || c == '=' || c == '|' ?
(sscanf( buf + 2, "%d %d", &t1, &t2 ) != 2) : (sscanf( buf + 2, "%u %u", &t1, &t2 ) != 2) :
(sscanf( buf + 2, "%d %d %d", &t1, &t2, &t3 ) != 3)) (sscanf( buf + 2, "%u %u %u", &t1, &t2, &t3 ) != 3))
{ {
error( "Error: malformed journal entry at %s:%d\n", svars->jname, line ); error( "Error: malformed journal entry at %s:%d\n", svars->jname, line );
goto jbail; goto jbail;
@ -875,7 +879,7 @@ load_state( sync_vars_t *svars )
else if (c == 'F') else if (c == 'F')
svars->newuid[t1] = t2; svars->newuid[t1] = t2;
else if (c == 'T') else if (c == 'T')
*int_array_append( &svars->trashed_msgs[t1] ) = t2; *uint_array_append( &svars->trashed_msgs[t1] ) = t2;
else if (c == '!') else if (c == '!')
svars->mmaxxuid = t1; svars->mmaxxuid = t1;
else if (c == '|') { else if (c == '|') {
@ -889,7 +893,7 @@ load_state( sync_vars_t *svars )
svars->newmaxuid[M] = t1; svars->newmaxuid[M] = t1;
if (svars->newmaxuid[S] < t2) if (svars->newmaxuid[S] < t2)
svars->newmaxuid[S] = t2; svars->newmaxuid[S] = t2;
debug( " new entry(%d,%d)\n", t1, t2 ); debug( " new entry(%u,%u)\n", t1, t2 );
srec->msg[M] = srec->msg[S] = 0; srec->msg[M] = srec->msg[S] = 0;
srec->status = S_PENDING; srec->status = S_PENDING;
srec->wstate = 0; srec->wstate = 0;
@ -909,7 +913,7 @@ load_state( sync_vars_t *svars )
error( "Error: journal entry at %s:%d refers to non-existing sync state entry\n", svars->jname, line ); error( "Error: journal entry at %s:%d refers to non-existing sync state entry\n", svars->jname, line );
goto jbail; goto jbail;
syncfnd: syncfnd:
debugn( " entry(%d,%d,%u) ", srec->uid[M], srec->uid[S], srec->flags ); debugn( " entry(%u,%u,%u) ", srec->uid[M], srec->uid[S], srec->flags );
switch (c) { switch (c) {
case '-': case '-':
debug( "killed\n" ); debug( "killed\n" );
@ -921,7 +925,7 @@ load_state( sync_vars_t *svars )
srec->status = S_DEAD; srec->status = S_DEAD;
break; break;
case '#': case '#':
memcpy( srec->tuid, buf + t3 + 2, TUIDL ); memcpy( srec->tuid, buf + tn + 2, TUIDL );
debug( "TUID now %." stringify(TUIDL) "s\n", srec->tuid ); debug( "TUID now %." stringify(TUIDL) "s\n", srec->tuid );
break; break;
case '&': case '&':
@ -930,19 +934,19 @@ load_state( sync_vars_t *svars )
srec->tuid[0] = 0; srec->tuid[0] = 0;
break; break;
case '<': case '<':
debug( "master now %d\n", t3 ); debug( "master now %u\n", t3 );
srec->uid[M] = t3; srec->uid[M] = t3;
srec->status &= ~S_PENDING; srec->status &= ~S_PENDING;
srec->tuid[0] = 0; srec->tuid[0] = 0;
break; break;
case '>': case '>':
debug( "slave now %d\n", t3 ); debug( "slave now %u\n", t3 );
srec->uid[S] = t3; srec->uid[S] = t3;
srec->status &= ~S_PENDING; srec->status &= ~S_PENDING;
srec->tuid[0] = 0; srec->tuid[0] = 0;
break; break;
case '*': case '*':
debug( "flags now %d\n", t3 ); debug( "flags now %u\n", t3 );
srec->flags = t3; srec->flags = t3;
break; break;
case '~': case '~':
@ -985,7 +989,7 @@ static void box_deleted( int sts, void *aux );
static void box_created( int sts, void *aux ); static void box_created( int sts, void *aux );
static void box_opened( int sts, int uidvalidity, void *aux ); static void box_opened( int sts, int uidvalidity, void *aux );
static void box_opened2( sync_vars_t *svars, int t ); static void box_opened2( sync_vars_t *svars, int t );
static void load_box( sync_vars_t *svars, int t, int minwuid, int_array_t mexcs ); static void load_box( sync_vars_t *svars, int t, uint minwuid, uint_array_t mexcs );
void void
sync_boxes( store_t *ctx[], const char *names[], int present[], channel_conf_t *chan, sync_boxes( store_t *ctx[], const char *names[], int present[], channel_conf_t *chan,
@ -1187,8 +1191,9 @@ box_opened2( sync_vars_t *svars, int t )
store_t *ctx[2]; store_t *ctx[2];
channel_conf_t *chan; channel_conf_t *chan;
sync_rec_t *srec; sync_rec_t *srec;
int_array_alloc_t mexcs; uint_array_alloc_t mexcs;
int opts[2], fails, minwuid; uint minwuid;
int opts[2], fails;
svars->state[t] |= ST_SELECTED; svars->state[t] |= ST_SELECTED;
if (!(svars->state[1-t] & ST_SELECTED)) if (!(svars->state[1-t] & ST_SELECTED))
@ -1203,7 +1208,7 @@ box_opened2( sync_vars_t *svars, int t )
fails++; fails++;
if (fails == 2) { if (fails == 2) {
error( "Error: channel %s: UIDVALIDITY of both master and slave changed\n" error( "Error: channel %s: UIDVALIDITY of both master and slave changed\n"
"(master got %d, expected %d; slave got %d, expected %d).\n", "(master got %u, expected %u; slave got %u, expected %u).\n",
svars->chan->name, svars->chan->name,
svars->newuidval[M], svars->uidval[M], svars->newuidval[S], svars->uidval[S] ); svars->newuidval[M], svars->uidval[M], svars->newuidval[S], svars->uidval[S] );
bail: bail:
@ -1286,7 +1291,7 @@ box_opened2( sync_vars_t *svars, int t )
/* When messages have been expired on the slave, the master fetch is split into /* When messages have been expired on the slave, the master fetch is split into
* two ranges: The bulk fetch which corresponds with the most recent messages, and an * two ranges: The bulk fetch which corresponds with the most recent messages, and an
* exception list of messages which would have been expired if they weren't important. */ * exception list of messages which would have been expired if they weren't important. */
debug( "preparing master selection - max expired master uid is %d\n", svars->mmaxxuid ); debug( "preparing master selection - max expired master uid is %u\n", svars->mmaxxuid );
/* First, find out the lower bound for the bulk fetch. */ /* First, find out the lower bound for the bulk fetch. */
minwuid = svars->mmaxxuid + 1; minwuid = svars->mmaxxuid + 1;
/* Next, calculate the exception fetch. */ /* Next, calculate the exception fetch. */
@ -1299,27 +1304,27 @@ box_opened2( sync_vars_t *svars, int t )
if (!srec->uid[S] && !(srec->status & S_PENDING)) // Only actually paired up messages matter if (!srec->uid[S] && !(srec->status & S_PENDING)) // Only actually paired up messages matter
continue; continue;
/* The pair is alive, but outside the bulk range. */ /* The pair is alive, but outside the bulk range. */
*int_array_append( &mexcs ) = srec->uid[M]; *uint_array_append( &mexcs ) = srec->uid[M];
} }
} }
sort_int_array( mexcs.array ); sort_uint_array( mexcs.array );
} else { } else {
minwuid = 1; minwuid = 1;
} }
} else { } else {
minwuid = INT_MAX; minwuid = UINT_MAX;
} }
sync_ref( svars ); sync_ref( svars );
load_box( svars, M, minwuid, mexcs.array ); load_box( svars, M, minwuid, mexcs.array );
if (!check_cancel( svars )) if (!check_cancel( svars ))
load_box( svars, S, (svars->opts[S] & OPEN_OLD) ? 1 : INT_MAX, (int_array_t){ 0, 0 } ); load_box( svars, S, (svars->opts[S] & OPEN_OLD) ? 1 : UINT_MAX, (uint_array_t){ 0, 0 } );
sync_deref( svars ); sync_deref( svars );
} }
static int static int
get_seenuid( sync_vars_t *svars, int t ) get_seenuid( sync_vars_t *svars, int t )
{ {
int seenuid = 0; uint seenuid = 0;
for (sync_rec_t *srec = svars->srecs; srec; srec = srec->next) for (sync_rec_t *srec = svars->srecs; srec; srec = srec->next)
if (!(srec->status & S_DEAD) && seenuid < srec->uid[t]) if (!(srec->status & S_DEAD) && seenuid < srec->uid[t])
seenuid = srec->uid[t]; seenuid = srec->uid[t];
@ -1329,14 +1334,14 @@ get_seenuid( sync_vars_t *svars, int t )
static void box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux ); static void box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux );
static void static void
load_box( sync_vars_t *svars, int t, int minwuid, int_array_t mexcs ) load_box( sync_vars_t *svars, int t, uint minwuid, uint_array_t mexcs )
{ {
int maxwuid, seenuid; uint maxwuid, seenuid;
if (svars->opts[t] & OPEN_NEW) { if (svars->opts[t] & OPEN_NEW) {
if (minwuid > svars->maxuid[t] + 1) if (minwuid > svars->maxuid[t] + 1)
minwuid = svars->maxuid[t] + 1; minwuid = svars->maxuid[t] + 1;
maxwuid = INT_MAX; maxwuid = UINT_MAX;
if (svars->opts[t] & (OPEN_OLD_IDS|OPEN_OLD_SIZE)) if (svars->opts[t] & (OPEN_OLD_IDS|OPEN_OLD_SIZE))
seenuid = get_seenuid( svars, t ); seenuid = get_seenuid( svars, t );
else else
@ -1361,14 +1366,14 @@ typedef struct {
} flag_vars_t; } flag_vars_t;
typedef struct { typedef struct {
int uid; uint uid;
sync_rec_t *srec; sync_rec_t *srec;
} sync_rec_map_t; } sync_rec_map_t;
static void flags_set( int sts, void *aux ); static void flags_set( int sts, void *aux );
static void flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int t ); static void flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int t );
static void msgs_flags_set( sync_vars_t *svars, int t ); static void msgs_flags_set( sync_vars_t *svars, int t );
static void msg_copied( int sts, int uid, copy_vars_t *vars ); static void msg_copied( int sts, uint uid, copy_vars_t *vars );
static void msgs_copied( sync_vars_t *svars, int t ); static void msgs_copied( sync_vars_t *svars, int t );
static void static void
@ -1379,7 +1384,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
sync_rec_map_t *srecmap; sync_rec_map_t *srecmap;
message_t *tmsg; message_t *tmsg;
flag_vars_t *fv; flag_vars_t *fv;
int uid, no[2], del[2], alive, todel; int no[2], del[2], alive, todel;
int sflags, nflags, aflags, dflags; int sflags, nflags, aflags, dflags;
uint hashsz, idx; uint hashsz, idx;
@ -1401,10 +1406,10 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
for (srec = svars->srecs; srec; srec = srec->next) { for (srec = svars->srecs; srec; srec = srec->next) {
if (srec->status & S_DEAD) if (srec->status & S_DEAD)
continue; continue;
uid = srec->uid[t]; uint uid = srec->uid[t];
if (!uid) if (!uid)
continue; continue;
idx = (uint)((uint)uid * 1103515245U) % hashsz; idx = (uint)(uid * 1103515245U) % hashsz;
while (srecmap[idx].uid) while (srecmap[idx].uid)
if (++idx == hashsz) if (++idx == hashsz)
idx = 0; idx = 0;
@ -1414,8 +1419,8 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
for (tmsg = svars->msgs[t]; tmsg; tmsg = tmsg->next) { for (tmsg = svars->msgs[t]; tmsg; tmsg = tmsg->next) {
if (tmsg->srec) /* found by TUID */ if (tmsg->srec) /* found by TUID */
continue; continue;
uid = tmsg->uid; uint uid = tmsg->uid;
idx = (uint)((uint)uid * 1103515245U) % hashsz; idx = (uint)(uid * 1103515245U) % hashsz;
while (srecmap[idx].uid) { while (srecmap[idx].uid) {
if (srecmap[idx].uid == uid) { if (srecmap[idx].uid == uid) {
srec = srecmap[idx].srec; srec = srecmap[idx].srec;
@ -1449,7 +1454,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
if (!srec->msg[1-t]) if (!srec->msg[1-t])
continue; // Partner disappeared. continue; // Partner disappeared.
if (!srec->msg[1-t]->msgid || strcmp( srec->msg[M]->msgid, srec->msg[S]->msgid )) { if (!srec->msg[1-t]->msgid || strcmp( srec->msg[M]->msgid, srec->msg[S]->msgid )) {
error( "Error: channel %s, %s %s: UIDVALIDITY genuinely changed (at UID %d).\n", error( "Error: channel %s, %s %s: UIDVALIDITY genuinely changed (at UID %u).\n",
svars->chan->name, str_ms[t], svars->orig_name[t], srec->uid[t] ); svars->chan->name, str_ms[t], svars->orig_name[t], srec->uid[t] );
uvchg: uvchg:
svars->ret |= SYNC_FAIL; svars->ret |= SYNC_FAIL;
@ -1464,7 +1469,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
// normalization) or the message body (which should be truncated for sanity) // normalization) or the message body (which should be truncated for sanity)
// and comparing. // and comparing.
error( "Error: channel %s, %s %s: Unable to recover from UIDVALIDITY change\n" error( "Error: channel %s, %s %s: Unable to recover from UIDVALIDITY change\n"
"(got %d, expected %d).\n", "(got %u, expected %u).\n",
svars->chan->name, str_ms[t], svars->orig_name[t], svars->chan->name, str_ms[t], svars->orig_name[t],
svars->newuidval[t], svars->uidval[t] ); svars->newuidval[t], svars->uidval[t] );
goto uvchg; goto uvchg;
@ -1478,7 +1483,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
if (svars->uidval[M] == UIDVAL_BAD || svars->uidval[S] == UIDVAL_BAD) { if (svars->uidval[M] == UIDVAL_BAD || svars->uidval[S] == UIDVAL_BAD) {
svars->uidval[M] = svars->newuidval[M]; svars->uidval[M] = svars->newuidval[M];
svars->uidval[S] = svars->newuidval[S]; svars->uidval[S] = svars->newuidval[S];
jFprintf( svars, "| %d %d\n", svars->uidval[M], svars->uidval[S] ); jFprintf( svars, "| %u %u\n", svars->uidval[M], svars->uidval[S] );
} }
info( "Synchronizing...\n" ); info( "Synchronizing...\n" );
@ -1487,7 +1492,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
for (srec = svars->srecs; srec; srec = srec->next) { for (srec = svars->srecs; srec; srec = srec->next) {
if (srec->status & S_DEAD) if (srec->status & S_DEAD)
continue; continue;
debug( "pair (%d,%d)\n", srec->uid[M], srec->uid[S] ); debug( "pair (%u,%u)\n", srec->uid[M], srec->uid[S] );
assert( !srec->tuid[0] ); assert( !srec->tuid[0] );
// no[] means that a message is known to be not there. // no[] means that a message is known to be not there.
no[M] = !srec->msg[M] && (svars->opts[M] & OPEN_OLD); no[M] = !srec->msg[M] && (svars->opts[M] & OPEN_OLD);
@ -1498,7 +1503,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
// now both are missing, so the entry is superfluous. // now both are missing, so the entry is superfluous.
debug( " vanished\n" ); debug( " vanished\n" );
srec->status = S_DEAD; srec->status = S_DEAD;
jFprintf( svars, "- %d %d\n", srec->uid[M], srec->uid[S] ); jFprintf( svars, "- %u %u\n", srec->uid[M], srec->uid[S] );
} else { } else {
// del[] means that a message becomes known to have been expunged. // del[] means that a message becomes known to have been expunged.
del[M] = no[M] && srec->uid[M]; del[M] = no[M] && srec->uid[M];
@ -1522,11 +1527,11 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
if ((t == M) && (srec->status & (S_EXPIRE|S_EXPIRED))) { if ((t == M) && (srec->status & (S_EXPIRE|S_EXPIRED))) {
/* Don't propagate deletion resulting from expiration. */ /* Don't propagate deletion resulting from expiration. */
debug( " slave expired, orphaning master\n" ); debug( " slave expired, orphaning master\n" );
jFprintf( svars, "> %d %d 0\n", srec->uid[M], srec->uid[S] ); jFprintf( svars, "> %u %u 0\n", srec->uid[M], srec->uid[S] );
srec->uid[S] = 0; srec->uid[S] = 0;
} else { } else {
if (srec->msg[t] && (srec->msg[t]->status & M_FLAGS) && srec->msg[t]->flags != srec->flags) if (srec->msg[t] && (srec->msg[t]->status & M_FLAGS) && srec->msg[t]->flags != srec->flags)
notice( "Notice: conflicting changes in (%d,%d)\n", srec->uid[M], srec->uid[S] ); notice( "Notice: conflicting changes in (%u,%u)\n", srec->uid[M], srec->uid[S] );
if (svars->chan->ops[t] & OP_DELETE) { if (svars->chan->ops[t] & OP_DELETE) {
debug( " %sing delete\n", str_hl[t] ); debug( " %sing delete\n", str_hl[t] );
srec->aflags[t] = F_DELETED; srec->aflags[t] = F_DELETED;
@ -1582,12 +1587,12 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
(((srec->status & S_PENDING) && (svars->chan->ops[t] & OP_NEW)) || (((srec->status & S_PENDING) && (svars->chan->ops[t] & OP_NEW)) ||
((srec->status & S_SKIPPED) && (svars->chan->ops[t] & OP_RENEW))) ((srec->status & S_SKIPPED) && (svars->chan->ops[t] & OP_RENEW)))
: svars->newmaxuid[1-t] < tmsg->uid && (svars->chan->ops[t] & OP_NEW)) { : svars->newmaxuid[1-t] < tmsg->uid && (svars->chan->ops[t] & OP_NEW)) {
debug( "new message %d on %s\n", tmsg->uid, str_ms[1-t] ); debug( "new message %u on %s\n", tmsg->uid, str_ms[1-t] );
if ((svars->chan->ops[t] & OP_EXPUNGE) && (tmsg->flags & F_DELETED)) { if ((svars->chan->ops[t] & OP_EXPUNGE) && (tmsg->flags & F_DELETED)) {
debug( " -> not %sing - would be expunged anyway\n", str_hl[t] ); debug( " -> not %sing - would be expunged anyway\n", str_hl[t] );
} else { } else {
if (srec) { if (srec) {
debug( " -> pair(%d,%d) exists\n", srec->uid[M], srec->uid[S] ); debug( " -> pair(%u,%u) exists\n", srec->uid[M], srec->uid[S] );
} else { } else {
srec = nfmalloc( sizeof(*srec) ); srec = nfmalloc( sizeof(*srec) );
srec->next = 0; srec->next = 0;
@ -1605,13 +1610,13 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
tmsg->srec = srec; tmsg->srec = srec;
if (svars->newmaxuid[1-t] < tmsg->uid) if (svars->newmaxuid[1-t] < tmsg->uid)
svars->newmaxuid[1-t] = tmsg->uid; svars->newmaxuid[1-t] = tmsg->uid;
jFprintf( svars, "+ %d %d\n", srec->uid[M], srec->uid[S] ); jFprintf( svars, "+ %u %u\n", srec->uid[M], srec->uid[S] );
debug( " -> pair(%d,%d) created\n", srec->uid[M], srec->uid[S] ); debug( " -> pair(%u,%u) created\n", srec->uid[M], srec->uid[S] );
} }
if ((tmsg->flags & F_FLAGGED) || tmsg->size <= svars->chan->stores[t]->max_size) { if ((tmsg->flags & F_FLAGGED) || tmsg->size <= svars->chan->stores[t]->max_size) {
if (tmsg->flags != srec->flags) { if (tmsg->flags != srec->flags) {
srec->flags = tmsg->flags; srec->flags = tmsg->flags;
jFprintf( svars, "* %d %d %u\n", srec->uid[M], srec->uid[S], srec->flags ); jFprintf( svars, "* %u %u %u\n", srec->uid[M], srec->uid[S], srec->flags );
debug( " -> updated flags to %u\n", tmsg->flags ); debug( " -> updated flags to %u\n", tmsg->flags );
} }
if (srec->status != S_PENDING) { if (srec->status != S_PENDING) {
@ -1662,7 +1667,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
continue; continue;
if (!(srec = tmsg->srec) || !srec->uid[M]) { if (!(srec = tmsg->srec) || !srec->uid[M]) {
/* We did not push the message, so it must be kept. */ /* We did not push the message, so it must be kept. */
debug( " message %d unpropagated\n", tmsg->uid ); debug( " message %u unpropagated\n", tmsg->uid );
todel--; todel--;
} else { } else {
nflags = (tmsg->flags | srec->aflags[S]) & ~srec->dflags[S]; nflags = (tmsg->flags | srec->aflags[S]) & ~srec->dflags[S];
@ -1670,14 +1675,14 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
/* The message is not deleted, or is already (being) expired. */ /* The message is not deleted, or is already (being) expired. */
if ((nflags & F_FLAGGED) || !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) { if ((nflags & F_FLAGGED) || !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) {
/* Important messages are always kept. */ /* Important messages are always kept. */
debug( " old pair(%d,%d) important\n", srec->uid[M], srec->uid[S] ); debug( " old pair(%u,%u) important\n", srec->uid[M], srec->uid[S] );
todel--; todel--;
} else if (todel > 0 || } else if (todel > 0 ||
((srec->status & (S_EXPIRE|S_EXPIRED)) == (S_EXPIRE|S_EXPIRED)) || ((srec->status & (S_EXPIRE|S_EXPIRED)) == (S_EXPIRE|S_EXPIRED)) ||
((srec->status & (S_EXPIRE|S_EXPIRED)) && (tmsg->flags & F_DELETED))) { ((srec->status & (S_EXPIRE|S_EXPIRED)) && (tmsg->flags & F_DELETED))) {
/* The message is excess or was already (being) expired. */ /* The message is excess or was already (being) expired. */
srec->wstate |= W_NEXPIRE; srec->wstate |= W_NEXPIRE;
debug( " old pair(%d,%d) expired\n", srec->uid[M], srec->uid[S] ); debug( " old pair(%u,%u) expired\n", srec->uid[M], srec->uid[S] );
if (svars->mmaxxuid < srec->uid[M]) if (svars->mmaxxuid < srec->uid[M])
svars->mmaxxuid = srec->uid[M]; svars->mmaxxuid = srec->uid[M];
todel--; todel--;
@ -1691,7 +1696,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
if (!(nflags & F_DELETED)) { if (!(nflags & F_DELETED)) {
if ((nflags & F_FLAGGED) || !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) { if ((nflags & F_FLAGGED) || !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) {
/* Important messages are always fetched. */ /* Important messages are always fetched. */
debug( " new pair(%d,%d) important\n", srec->uid[M], srec->uid[S] ); debug( " new pair(%u,%u) important\n", srec->uid[M], srec->uid[S] );
todel--; todel--;
} else if (todel > 0) { } else if (todel > 0) {
/* The message is excess. */ /* The message is excess. */
@ -1721,12 +1726,12 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
/* The record needs a state change ... */ /* The record needs a state change ... */
if (nex != ((srec->status / S_EXPIRE) & 1)) { if (nex != ((srec->status / S_EXPIRE) & 1)) {
/* ... and we need to start a transaction. */ /* ... and we need to start a transaction. */
debug( " pair(%d,%d): %d (pre)\n", srec->uid[M], srec->uid[S], nex ); debug( " pair(%u,%u): %u (pre)\n", srec->uid[M], srec->uid[S], nex );
srec->status = (srec->status & ~S_EXPIRE) | (nex * S_EXPIRE); srec->status = (srec->status & ~S_EXPIRE) | (nex * S_EXPIRE);
jFprintf( svars, "~ %d %d %u\n", srec->uid[M], srec->uid[S], srec->status ); jFprintf( svars, "~ %u %u %u\n", srec->uid[M], srec->uid[S], srec->status );
} else { } else {
/* ... but the "right" transaction is already pending. */ /* ... but the "right" transaction is already pending. */
debug( " pair(%d,%d): %d (pending)\n", srec->uid[M], srec->uid[S], nex ); debug( " pair(%u,%u): %d (pending)\n", srec->uid[M], srec->uid[S], nex );
} }
} else { } else {
/* Note: the "wrong" transaction may be pending here, /* Note: the "wrong" transaction may be pending here,
@ -1734,8 +1739,8 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
} }
} else { } else {
if (srec->wstate & W_NEXPIRE) { if (srec->wstate & W_NEXPIRE) {
jFprintf( svars, "= %d %d\n", srec->uid[M], srec->uid[S] ); jFprintf( svars, "= %u %u\n", srec->uid[M], srec->uid[S] );
debug( " pair(%d,%d): 1 (abort)\n", srec->uid[M], srec->uid[S] ); debug( " pair(%u,%u): 1 (abort)\n", srec->uid[M], srec->uid[S] );
// If we have so many new messages that some of them are instantly expired, // If we have so many new messages that some of them are instantly expired,
// but some are still propagated because they are important, we need to // but some are still propagated because they are important, we need to
// ensure explicitly that the bulk fetch limit is upped. // ensure explicitly that the bulk fetch limit is upped.
@ -1813,7 +1818,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
fdatasync( fileno( svars->jfp ) ); fdatasync( fileno( svars->jfp ) );
for (t = 0; t < 2; t++) { for (t = 0; t < 2; t++) {
svars->newuid[t] = svars->drv[t]->get_uidnext( svars->ctx[t] ); svars->newuid[t] = svars->drv[t]->get_uidnext( svars->ctx[t] );
jFprintf( svars, "F %d %d\n", t, svars->newuid[t] ); jFprintf( svars, "F %d %u\n", t, svars->newuid[t] );
svars->new_msgs[t] = svars->msgs[1-t]; svars->new_msgs[t] = svars->msgs[1-t];
msgs_copied( svars, t ); msgs_copied( svars, t );
if (check_cancel( svars )) if (check_cancel( svars ))
@ -1825,7 +1830,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
} }
static void static void
msg_copied( int sts, int uid, copy_vars_t *vars ) msg_copied( int sts, uint uid, copy_vars_t *vars )
{ {
SVARS_CHECK_CANCEL_RET; SVARS_CHECK_CANCEL_RET;
switch (sts) { switch (sts) {
@ -1833,17 +1838,17 @@ msg_copied( int sts, int uid, copy_vars_t *vars )
if (!uid) { // Stored to a non-UIDPLUS mailbox if (!uid) { // Stored to a non-UIDPLUS mailbox
svars->state[t] |= ST_FIND_NEW; svars->state[t] |= ST_FIND_NEW;
} else { } else {
debug( " -> new UID %d on %s\n", uid, str_ms[t] ); debug( " -> new UID %u on %s\n", uid, str_ms[t] );
jFprintf( svars, "%c %d %d %d\n", "<>"[t], vars->srec->uid[M], vars->srec->uid[S], uid ); jFprintf( svars, "%c %u %u %u\n", "<>"[t], vars->srec->uid[M], vars->srec->uid[S], uid );
vars->srec->uid[t] = uid; vars->srec->uid[t] = uid;
vars->srec->status &= ~S_PENDING; vars->srec->status &= ~S_PENDING;
vars->srec->tuid[0] = 0; vars->srec->tuid[0] = 0;
} }
break; break;
case SYNC_NOGOOD: case SYNC_NOGOOD:
debug( " -> killing (%d,%d)\n", vars->srec->uid[M], vars->srec->uid[S] ); debug( " -> killing (%u,%u)\n", vars->srec->uid[M], vars->srec->uid[S] );
vars->srec->status = S_DEAD; vars->srec->status = S_DEAD;
jFprintf( svars, "- %d %d\n", vars->srec->uid[M], vars->srec->uid[S] ); jFprintf( svars, "- %u %u\n", vars->srec->uid[M], vars->srec->uid[S] );
break; break;
default: default:
cancel_sync( svars ); cancel_sync( svars );
@ -1884,8 +1889,8 @@ msgs_copied( sync_vars_t *svars, int t )
uchar c = arc4_getbyte() & 0x3f; uchar c = arc4_getbyte() & 0x3f;
srec->tuid[i] = c < 26 ? c + 'A' : c < 52 ? c + 'a' - 26 : c < 62 ? c + '0' - 52 : c == 62 ? '+' : '/'; srec->tuid[i] = c < 26 ? c + 'A' : c < 52 ? c + 'a' - 26 : c < 62 ? c + '0' - 52 : c == 62 ? '+' : '/';
} }
jFprintf( svars, "# %d %d %." stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], srec->tuid ); jFprintf( svars, "# %u %u %." stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], srec->tuid );
debug( "%sing message %d, TUID %." stringify(TUIDL) "s\n", str_hl[t], tmsg->uid, srec->tuid ); debug( "%sing message %u, TUID %." stringify(TUIDL) "s\n", str_hl[t], tmsg->uid, srec->tuid );
new_total[t]++; new_total[t]++;
stats(); stats();
svars->new_pending[t]++; svars->new_pending[t]++;
@ -1973,26 +1978,26 @@ static void
flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int t ) flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int t )
{ {
if (srec->wstate & W_DELETE) { if (srec->wstate & W_DELETE) {
debug( " pair(%d,%d): resetting %s UID\n", srec->uid[M], srec->uid[S], str_ms[1-t] ); debug( " pair(%u,%u): resetting %s UID\n", srec->uid[M], srec->uid[S], str_ms[1-t] );
jFprintf( svars, "%c %d %d 0\n", "><"[t], srec->uid[M], srec->uid[S] ); jFprintf( svars, "%c %u %u 0\n", "><"[t], srec->uid[M], srec->uid[S] );
srec->uid[1-t] = 0; srec->uid[1-t] = 0;
} else { } else {
int nflags = (srec->flags | srec->aflags[t]) & ~srec->dflags[t]; uint nflags = (srec->flags | srec->aflags[t]) & ~srec->dflags[t];
if (srec->flags != nflags) { if (srec->flags != nflags) {
debug( " pair(%d,%d): updating flags (%u -> %u; %sed)\n", srec->uid[M], srec->uid[S], srec->flags, nflags, str_hl[t] ); debug( " pair(%u,%u): updating flags (%u -> %u; %sed)\n", srec->uid[M], srec->uid[S], srec->flags, nflags, str_hl[t] );
srec->flags = nflags; srec->flags = nflags;
jFprintf( svars, "* %d %d %u\n", srec->uid[M], srec->uid[S], nflags ); jFprintf( svars, "* %u %u %u\n", srec->uid[M], srec->uid[S], nflags );
} }
if (t == S) { if (t == S) {
uint nex = (srec->wstate / W_NEXPIRE) & 1; uint nex = (srec->wstate / W_NEXPIRE) & 1;
if (nex != ((srec->status / S_EXPIRED) & 1)) { if (nex != ((srec->status / S_EXPIRED) & 1)) {
debug( " pair(%d,%d): expired %d (commit)\n", srec->uid[M], srec->uid[S], nex ); debug( " pair(%u,%u): expired %d (commit)\n", srec->uid[M], srec->uid[S], nex );
srec->status = (srec->status & ~S_EXPIRED) | (nex * S_EXPIRED); srec->status = (srec->status & ~S_EXPIRED) | (nex * S_EXPIRED);
jFprintf( svars, "~ %d %d %u\n", srec->uid[M], srec->uid[S], srec->status ); jFprintf( svars, "~ %u %u %u\n", srec->uid[M], srec->uid[S], srec->status );
} else if (nex != ((srec->status / S_EXPIRE) & 1)) { } else if (nex != ((srec->status / S_EXPIRE) & 1)) {
debug( " pair(%d,%d): expire %d (cancel)\n", srec->uid[M], srec->uid[S], nex ); debug( " pair(%u,%u): expire %d (cancel)\n", srec->uid[M], srec->uid[S], nex );
srec->status = (srec->status & ~S_EXPIRE) | (nex * S_EXPIRE); srec->status = (srec->status & ~S_EXPIRE) | (nex * S_EXPIRE);
jFprintf( svars, "~ %d %d %u\n", srec->uid[M], srec->uid[S], srec->status ); jFprintf( svars, "~ %u %u %u\n", srec->uid[M], srec->uid[S], srec->status );
} }
} }
} }
@ -2004,7 +2009,7 @@ typedef struct {
} trash_vars_t; } trash_vars_t;
static void msg_trashed( int sts, void *aux ); static void msg_trashed( int sts, void *aux );
static void msg_rtrashed( int sts, int uid, copy_vars_t *vars ); static void msg_rtrashed( int sts, uint uid, copy_vars_t *vars );
static void static void
msgs_flags_set( sync_vars_t *svars, int t ) msgs_flags_set( sync_vars_t *svars, int t )
@ -2022,11 +2027,11 @@ msgs_flags_set( sync_vars_t *svars, int t )
(svars->ctx[t]->conf->trash || (svars->ctx[1-t]->conf->trash && svars->ctx[1-t]->conf->trash_remote_new))) { (svars->ctx[t]->conf->trash || (svars->ctx[1-t]->conf->trash && svars->ctx[1-t]->conf->trash_remote_new))) {
debug( "trashing in %s\n", str_ms[t] ); debug( "trashing in %s\n", str_ms[t] );
for (tmsg = svars->msgs[t]; tmsg; tmsg = tmsg->next) for (tmsg = svars->msgs[t]; tmsg; tmsg = tmsg->next)
if ((tmsg->flags & F_DELETED) && !find_int_array( svars->trashed_msgs[t].array, tmsg->uid ) && if ((tmsg->flags & F_DELETED) && !find_uint_array( svars->trashed_msgs[t].array, tmsg->uid ) &&
(t == M || !tmsg->srec || !(tmsg->srec->status & (S_EXPIRE|S_EXPIRED)))) { (t == M || !tmsg->srec || !(tmsg->srec->status & (S_EXPIRE|S_EXPIRED)))) {
if (svars->ctx[t]->conf->trash) { if (svars->ctx[t]->conf->trash) {
if (!svars->ctx[t]->conf->trash_only_new || !tmsg->srec || (tmsg->srec->status & (S_PENDING | S_SKIPPED))) { if (!svars->ctx[t]->conf->trash_only_new || !tmsg->srec || (tmsg->srec->status & (S_PENDING | S_SKIPPED))) {
debug( "%s: trashing message %d\n", str_ms[t], tmsg->uid ); debug( "%s: trashing message %u\n", str_ms[t], tmsg->uid );
trash_total[t]++; trash_total[t]++;
stats(); stats();
svars->trash_pending[t]++; svars->trash_pending[t]++;
@ -2037,11 +2042,11 @@ msgs_flags_set( sync_vars_t *svars, int t )
if (check_cancel( svars )) if (check_cancel( svars ))
goto out; goto out;
} else } else
debug( "%s: not trashing message %d - not new\n", str_ms[t], tmsg->uid ); debug( "%s: not trashing message %u - not new\n", str_ms[t], tmsg->uid );
} else { } else {
if (!tmsg->srec || (tmsg->srec->status & (S_PENDING | S_SKIPPED))) { if (!tmsg->srec || (tmsg->srec->status & (S_PENDING | S_SKIPPED))) {
if (tmsg->size <= svars->ctx[1-t]->conf->max_size) { if (tmsg->size <= svars->ctx[1-t]->conf->max_size) {
debug( "%s: remote trashing message %d\n", str_ms[t], tmsg->uid ); debug( "%s: remote trashing message %u\n", str_ms[t], tmsg->uid );
trash_total[t]++; trash_total[t]++;
stats(); stats();
svars->trash_pending[t]++; svars->trash_pending[t]++;
@ -2054,9 +2059,9 @@ msgs_flags_set( sync_vars_t *svars, int t )
if (check_cancel( svars )) if (check_cancel( svars ))
goto out; goto out;
} else } else
debug( "%s: not remote trashing message %d - too big\n", str_ms[t], tmsg->uid ); debug( "%s: not remote trashing message %u - too big\n", str_ms[t], tmsg->uid );
} else } else
debug( "%s: not remote trashing message %d - not new\n", str_ms[t], tmsg->uid ); debug( "%s: not remote trashing message %u - not new\n", str_ms[t], tmsg->uid );
} }
} }
} }
@ -2078,8 +2083,8 @@ msg_trashed( int sts, void *aux )
if (check_ret( sts, vars->aux )) if (check_ret( sts, vars->aux ))
return; return;
INIT_SVARS(vars->aux); INIT_SVARS(vars->aux);
debug( " -> trashed %s %d\n", str_ms[t], vars->msg->uid ); debug( " -> trashed %s %u\n", str_ms[t], vars->msg->uid );
jFprintf( svars, "T %d %d\n", t, vars->msg->uid ); jFprintf( svars, "T %d %u\n", t, vars->msg->uid );
free( vars ); free( vars );
trash_done[t]++; trash_done[t]++;
stats(); stats();
@ -2088,7 +2093,7 @@ msg_trashed( int sts, void *aux )
} }
static void static void
msg_rtrashed( int sts, int uid ATTR_UNUSED, copy_vars_t *vars ) msg_rtrashed( int sts, uint uid ATTR_UNUSED, copy_vars_t *vars )
{ {
SVARS_CHECK_CANCEL_RET; SVARS_CHECK_CANCEL_RET;
switch (sts) { switch (sts) {
@ -2101,8 +2106,8 @@ msg_rtrashed( int sts, int uid ATTR_UNUSED, copy_vars_t *vars )
return; return;
} }
t ^= 1; t ^= 1;
debug( " -> remote trashed %s %d\n", str_ms[t], vars->msg->uid ); debug( " -> remote trashed %s %u\n", str_ms[t], vars->msg->uid );
jFprintf( svars, "T %d %d\n", t, vars->msg->uid ); jFprintf( svars, "T %d %u\n", t, vars->msg->uid );
free( vars ); free( vars );
trash_done[t]++; trash_done[t]++;
stats(); stats();
@ -2161,17 +2166,17 @@ box_closed_p2( sync_vars_t *svars, int t )
if (!srec->uid[S] || ((srec->wstate & W_DEL(S)) && (svars->state[S] & ST_DID_EXPUNGE))) { if (!srec->uid[S] || ((srec->wstate & W_DEL(S)) && (svars->state[S] & ST_DID_EXPUNGE))) {
if (!srec->uid[M] || ((srec->wstate & W_DEL(M)) && (svars->state[M] & ST_DID_EXPUNGE)) || if (!srec->uid[M] || ((srec->wstate & W_DEL(M)) && (svars->state[M] & ST_DID_EXPUNGE)) ||
((srec->status & S_EXPIRED) && svars->maxuid[M] >= srec->uid[M] && svars->mmaxxuid >= srec->uid[M])) { ((srec->status & S_EXPIRED) && svars->maxuid[M] >= srec->uid[M] && svars->mmaxxuid >= srec->uid[M])) {
debug( " -> killing (%d,%d)\n", srec->uid[M], srec->uid[S] ); debug( " -> killing (%u,%u)\n", srec->uid[M], srec->uid[S] );
jFprintf( svars, "- %u %u\n", srec->uid[M], srec->uid[S] );
srec->status = S_DEAD; srec->status = S_DEAD;
jFprintf( svars, "- %d %d\n", srec->uid[M], srec->uid[S] );
} else if (srec->uid[S]) { } else if (srec->uid[S]) {
debug( " -> orphaning (%d,[%d])\n", srec->uid[M], srec->uid[S] ); debug( " -> orphaning (%u,[%u])\n", srec->uid[M], srec->uid[S] );
jFprintf( svars, "> %d %d 0\n", srec->uid[M], srec->uid[S] ); jFprintf( svars, "> %u %u 0\n", srec->uid[M], srec->uid[S] );
srec->uid[S] = 0; srec->uid[S] = 0;
} }
} else if (srec->uid[M] && ((srec->wstate & W_DEL(M)) && (svars->state[M] & ST_DID_EXPUNGE))) { } else if (srec->uid[M] && ((srec->wstate & W_DEL(M)) && (svars->state[M] & ST_DID_EXPUNGE))) {
debug( " -> orphaning ([%d],%d)\n", srec->uid[M], srec->uid[S] ); debug( " -> orphaning ([%u],%u)\n", srec->uid[M], srec->uid[S] );
jFprintf( svars, "< %d %d 0\n", srec->uid[M], srec->uid[S] ); jFprintf( svars, "< %u %u 0\n", srec->uid[M], srec->uid[S] );
srec->uid[M] = 0; srec->uid[M] = 0;
} }
} }

View File

@ -539,24 +539,24 @@ map_name( const char *arg, char **result, int reserve, const char *in, const cha
} }
static int static int
compare_ints( const void *l, const void *r ) compare_uints( const void *l, const void *r )
{ {
return *(int *)l - *(int *)r; return *(uint *)l - *(uint *)r;
} }
void void
sort_int_array( int_array_t array ) sort_uint_array( uint_array_t array )
{ {
qsort( array.data, array.size, sizeof(int), compare_ints ); qsort( array.data, array.size, sizeof(uint), compare_uints );
} }
int int
find_int_array( int_array_t array, int value ) find_uint_array( uint_array_t array, uint value )
{ {
int bot = 0, top = array.size - 1; int bot = 0, top = array.size - 1;
while (bot <= top) { while (bot <= top) {
int i = (bot + top) / 2; int i = (bot + top) / 2;
int elt = array.data[i]; uint elt = array.data[i];
if (elt == value) if (elt == value)
return 1; return 1;
if (elt < value) if (elt < value)