static bool pop3_uidl_assign_by_size(struct mailbox *box) { struct pop3_migration_mailbox *mbox = POP3_MIGRATION_CONTEXT(box); struct pop3_migration_mail_storage *mstorage = POP3_MIGRATION_CONTEXT(box->storage); struct pop3_uidl_map *pop3_map; struct imap_msg_map *imap_map; unsigned int i, pop3_count, imap_count, count; pop3_map = array_get_modifiable(&mstorage->pop3_uidl_map, &pop3_count); imap_map = array_get_modifiable(&mbox->imap_msg_map, &imap_count); count = I_MIN(pop3_count, imap_count); /* see if we can match the messages using sizes */ for (i = 0; i < count; i++) { if (pop3_map[i].size != imap_map[i].psize) break; if (i+1 < count && pop3_map[i].size == pop3_map[i+1].size) { /* two messages with same size, don't trust them */ break; } pop3_map[i].imap_uid = imap_map[i].uid; imap_map[i].pop3_uidl = pop3_map[i].pop3_uidl; imap_map[i].pop3_seq = pop3_map[i].pop3_seq; } mbox->first_unfound_idx = i; return i == count; }
static void virtual_mailbox_get_list_patterns(struct virtual_parse_context *ctx) { struct virtual_mailbox *mbox = ctx->mbox; ARRAY_TYPE(mailbox_virtual_patterns) *dest; struct mailbox_virtual_pattern pattern; struct virtual_backend_box *const *bboxes; unsigned int i, count; memset(&pattern, 0, sizeof(pattern)); bboxes = array_get_modifiable(&mbox->backend_boxes, &count); p_array_init(&mbox->list_include_patterns, ctx->pool, count); p_array_init(&mbox->list_exclude_patterns, ctx->pool, count); for (i = 0; i < count; i++) { if (bboxes[i]->metadata_entry == NULL) continue; pattern.ns = bboxes[i]->ns; pattern.pattern = bboxes[i]->name; if (bboxes[i]->negative_match) dest = &mbox->list_include_patterns; else { dest = &mbox->list_exclude_patterns; pattern.pattern++; } array_append(dest, &pattern, 1); } }
void io_loop_handler_run_internal(struct ioloop *ioloop) { struct ioloop_handler_context *ctx = ioloop->handler_context; struct epoll_event *events; const struct epoll_event *event; struct io_list *list; struct io_file *io; struct timeval tv; unsigned int events_count; int msecs, ret, i, j; bool call; /* get the time left for next timeout task */ msecs = io_loop_get_wait_time(ioloop, &tv); events = array_get_modifiable(&ctx->events, &events_count); if (ioloop->io_files != NULL && events_count > ctx->deleted_count) { ret = epoll_wait(ctx->epfd, events, events_count, msecs); if (ret < 0 && errno != EINTR) i_fatal("epoll_wait(): %m"); } else { /* no I/Os, but we should have some timeouts. just wait for them. */ i_assert(msecs >= 0); usleep(msecs*1000); ret = 0; } /* execute timeout handlers */ io_loop_handle_timeouts(ioloop); if (!ioloop->running) return; for (i = 0; i < ret; i++) { /* io_loop_handle_add() may cause events array reallocation, so we have use array_idx() */ event = array_idx(&ctx->events, i); list = event->data.ptr; for (j = 0; j < IOLOOP_IOLIST_IOS_PER_FD; j++) { io = list->ios[j]; if (io == NULL) continue; call = FALSE; if ((event->events & (EPOLLHUP | EPOLLERR)) != 0) call = TRUE; else if ((io->io.condition & IO_READ) != 0) call = (event->events & EPOLLIN) != 0; else if ((io->io.condition & IO_WRITE) != 0) call = (event->events & EPOLLOUT) != 0; else if ((io->io.condition & IO_ERROR) != 0) call = (event->events & IO_EPOLL_ERROR) != 0; if (call) io_loop_call_io(&io->io); } } }
static unsigned int view_sync_expunges2seqs(struct mail_index_view_sync_ctx *ctx) { struct mail_index_view *view = ctx->view; struct seq_range *src, *src_end, *dest; unsigned int count, expunge_count = 0; uint32_t prev_seq = 0; /* convert UIDs to sequences */ src = dest = array_get_modifiable(&ctx->expunges, &count); src_end = src + count; for (; src != src_end; src++) { if (!mail_index_lookup_seq_range(view, src->seq1, src->seq2, &dest->seq1, &dest->seq2)) count--; else { i_assert(dest->seq1 > prev_seq); prev_seq = dest->seq2; expunge_count += dest->seq2 - dest->seq1 + 1; dest++; } } array_delete(&ctx->expunges, count, array_count(&ctx->expunges) - count); return expunge_count; }
int virtual_transaction_commit(struct mailbox_transaction_context *t, struct mail_transaction_commit_changes *changes_r) { struct virtual_transaction_context *vt = (struct virtual_transaction_context *)t; struct mailbox_transaction_context **bt; unsigned int i, count; int ret = 0; if (t->save_ctx != NULL) { virtual_save_free(t->save_ctx); t->save_ctx = NULL; } bt = array_get_modifiable(&vt->backend_transactions, &count); for (i = 0; i < count; i++) { if (mailbox_transaction_commit(&bt[i]) < 0) ret = -1; } array_free(&vt->backend_transactions); if (index_transaction_commit(t, changes_r) < 0) ret = -1; return ret; }
void lmtp_client_fail(struct lmtp_client *client, const char *line) { struct lmtp_rcpt *recipients; unsigned int i, count; client->global_fail_string = p_strdup(client->pool, line); lmtp_client_ref(client); recipients = array_get_modifiable(&client->recipients, &count); for (i = client->rcpt_next_receive_idx; i < count; i++) { recipients[i].rcpt_to_callback(FALSE, line, recipients[i].context); recipients[i].failed = TRUE; } client->rcpt_next_receive_idx = count; for (i = client->rcpt_next_data_idx; i < count; i++) { if (!recipients[i].failed) { recipients[i].data_callback(FALSE, line, recipients[i].context); } } client->rcpt_next_data_idx = count; lmtp_client_close(client); lmtp_client_unref(&client); }
static void mail_user_expand_plugins_envs(struct mail_user *user) { const char **envs, *home; string_t *str; unsigned int i, count; if (!array_is_created(&user->set->plugin_envs)) return; str = t_str_new(256); envs = array_get_modifiable(&user->set->plugin_envs, &count); i_assert((count % 2) == 0); for (i = 0; i < count; i += 2) { if (user->_home == NULL && var_has_key(envs[i+1], 'h', "home") && mail_user_get_home(user, &home) <= 0) { user->error = p_strdup_printf(user->pool, "userdb didn't return a home directory, " "but plugin setting %s used it (%%h): %s", envs[i], envs[i+1]); return; } str_truncate(str, 0); var_expand(str, envs[i+1], mail_user_var_expand_table(user)); envs[i+1] = p_strdup(user->pool, str_c(str)); } }
void program_client_set_extra_fd (struct program_client *pclient, int fd, program_client_fd_callback_t *callback, void *context) { struct program_client_extra_fd *efds; struct program_client_extra_fd *efd = NULL; unsigned int i, count; i_assert(fd > 1); if ( !array_is_created(&pclient->extra_fds) ) p_array_init(&pclient->extra_fds, pclient->pool, 2); efds = array_get_modifiable(&pclient->extra_fds, &count); for ( i = 0; i < count; i++ ) { if ( efds[i].child_fd == fd ) { efd = &efds[i]; break; } } if ( efd == NULL ) { efd = array_append_space(&pclient->extra_fds); efd->pclient = pclient; efd->child_fd = fd; efd->parent_fd = -1; } efd->callback = callback; efd->context = context; }
static int lmtp_client_data_next(struct lmtp_client *client, const char *line) { struct lmtp_rcpt *rcpt; unsigned int i, count; rcpt = array_get_modifiable(&client->recipients, &count); for (i = client->rcpt_next_data_idx; i < count; i++) { if (rcpt[i].failed) { /* already called rcpt_to_callback with failure */ continue; } client->rcpt_next_data_idx = i + 1; rcpt[i].failed = line[0] != '2'; rcpt[i].data_callback(!rcpt[i].failed, line, rcpt[i].context); if (client->protocol == LMTP_CLIENT_PROTOCOL_LMTP) break; } if (client->rcpt_next_data_idx < count) return 0; o_stream_send_str(client->output, "QUIT\r\n"); lmtp_client_close(client); return -1; }
static void lmtp_client_fail_full(struct lmtp_client *client, const char *line, bool remote) { enum lmtp_client_result result; struct lmtp_rcpt *recipients; unsigned int i, count; client->global_fail_string = p_strdup(client->pool, line); client->global_remote_failure = remote; result = remote ? LMTP_CLIENT_RESULT_REMOTE_ERROR : LMTP_CLIENT_RESULT_INTERNAL_ERROR; lmtp_client_ref(client); recipients = array_get_modifiable(&client->recipients, &count); for (i = client->rcpt_next_receive_idx; i < count; i++) { recipients[i].rcpt_to_callback(result, line, recipients[i].context); recipients[i].failed = TRUE; } client->rcpt_next_receive_idx = count; for (i = client->rcpt_next_data_idx; i < count; i++) { if (!recipients[i].failed) { recipients[i].data_callback(result, line, recipients[i].context); } } client->rcpt_next_data_idx = count; lmtp_client_close(client); lmtp_client_unref(&client); }
void acl_rights_sort(struct acl_object *aclobj) { struct acl_rights *rights; unsigned int i, dest, count; if (!array_is_created(&aclobj->rights)) return; array_sort(&aclobj->rights, acl_rights_cmp); /* merge identical identifiers */ rights = array_get_modifiable(&aclobj->rights, &count); for (dest = 0, i = 1; i < count; i++) { if (acl_rights_cmp(&rights[i], &rights[dest]) == 0) { /* add i's rights to dest and delete i */ acl_right_names_merge(aclobj->rights_pool, &rights[dest].rights, rights[i].rights, FALSE); acl_right_names_merge(aclobj->rights_pool, &rights[dest].neg_rights, rights[i].neg_rights, FALSE); } else { if (++dest != i) rights[dest] = rights[i]; } } if (++dest != count) array_delete(&aclobj->rights, dest, count - dest); }
void io_loop_handler_run_internal(struct ioloop *ioloop) { struct ioloop_handler_context *ctx = ioloop->handler_context; struct kevent *events; const struct kevent *event; struct timeval tv; struct timespec ts; struct io_file *io; unsigned int events_count; int ret, i, msecs; /* get the time left for next timeout task */ msecs = io_loop_get_wait_time(ioloop, &tv); ts.tv_sec = tv.tv_sec; ts.tv_nsec = tv.tv_usec * 1000; /* wait for events */ events = array_get_modifiable(&ctx->events, &events_count); if (events_count > 0) { ret = kevent (ctx->kq, NULL, 0, events, events_count, &ts); if (ret < 0 && errno != EINTR) i_panic("kevent() failed: %m"); } else { if (msecs < 0) i_panic("BUG: No IOs or timeouts set. Not waiting for infinity."); usleep(msecs * 1000); ret = 0; } /* reference all IOs */ for (i = 0; i < ret; i++) { io = (void *)events[i].udata; i_assert(io->refcount > 0); io->refcount++; } /* execute timeout handlers */ io_loop_handle_timeouts(ioloop); for (i = 0; i < ret; i++) { /* io_loop_handle_add() may cause events array reallocation, so we have use array_idx() */ event = array_idx(&ctx->events, i); io = (void *)event->udata; /* callback is NULL if io_remove() was already called */ if (io->io.callback != NULL) io_loop_call_io(&io->io); i_assert(io->refcount > 0); if (--io->refcount == 0) i_free(io); } }
static struct ext_editheader_header *ext_editheader_config_header_find (struct ext_editheader_config *ext_config, const char *hname) { struct ext_editheader_header *headers; unsigned int count, i; headers = array_get_modifiable(&ext_config->headers, &count); for ( i = 0; i < count; i++ ) { if ( strcasecmp(hname, headers[i].name) == 0 ) return &headers[i]; } return NULL; }
void mail_index_view_unref_maps(struct mail_index_view *view) { struct mail_index_map **maps; unsigned int i, count; if (!array_is_created(&view->map_refs)) return; maps = array_get_modifiable(&view->map_refs, &count); for (i = 0; i < count; i++) mail_index_unmap(&maps[i]); array_clear(&view->map_refs); }
static void sieve_extension_registry_deinit(struct sieve_instance *svinst) { struct sieve_extension_registry *ext_reg = svinst->ext_reg; struct sieve_extension * const *exts; unsigned int i, ext_count; if ( !hash_table_is_created(ext_reg->extension_index) ) return; exts = array_get_modifiable(&ext_reg->extensions, &ext_count); for ( i = 0; i < ext_count; i++ ) { _sieve_extension_unload(exts[i]); } hash_table_destroy(&ext_reg->extension_index); }
void io_loop_handler_deinit(struct ioloop *ioloop) { struct ioloop_handler_context *ctx = ioloop->handler_context; struct io_list **list; unsigned int i, count; list = array_get_modifiable(&ctx->fd_index, &count); for (i = 0; i < count; i++) i_free(list[i]); if (close(ctx->epfd) < 0) i_error("close(epoll) failed: %m"); array_free(&ioloop->handler_context->fd_index); array_free(&ioloop->handler_context->events); i_free(ioloop->handler_context); }
static void virtual_mail_free(struct mail *mail) { struct virtual_mail *vmail = (struct virtual_mail *)mail; struct mail **mails; unsigned int i, count; mails = array_get_modifiable(&vmail->backend_mails, &count); for (i = 0; i < count; i++) mail_free(&mails[i]); array_free(&vmail->backend_mails); if (vmail->wanted_headers != NULL) mailbox_header_lookup_unref(&vmail->wanted_headers); pool_unref(&vmail->imail.data_pool); pool_unref(&vmail->imail.mail.pool); }
void program_client_init_streams(struct program_client *pclient) { /* Create streams for normal program I/O */ if ( pclient->fd_out >= 0 ) { pclient->program_output = o_stream_create_fd(pclient->fd_out, MAX_OUTPUT_BUFFER_SIZE, FALSE); } if ( pclient->fd_in >= 0 ) { struct istream *input; input = i_stream_create_fd(pclient->fd_in, (size_t)-1, FALSE); if (pclient->output_seekable) { struct istream *input2 = input, *input_list[2]; input_list[0] = input2; input_list[1] = NULL; input = i_stream_create_seekable(input_list, MAX_OUTPUT_MEMORY_BUFFER, program_client_seekable_fd_callback, pclient); i_stream_unref(&input2); pclient->seekable_output = input; i_stream_ref(pclient->seekable_output); } pclient->program_input = input; pclient->io = io_add (pclient->fd_in, IO_READ, program_client_program_input, pclient); } /* Create streams for additional output through side-channel fds */ if ( array_is_created(&pclient->extra_fds) ) { struct program_client_extra_fd *efds = NULL; unsigned int count, i; efds = array_get_modifiable(&pclient->extra_fds, &count); for ( i = 0; i < count; i++ ) { i_assert( efds[i].parent_fd >= 0 ); efds[i].input = i_stream_create_fd (efds[i].parent_fd, (size_t)-1, FALSE); efds[i].io = io_add (efds[i].parent_fd, IO_READ, program_client_extra_fd_input, &efds[i]); } } }
static void program_client_disconnect_extra_fds (struct program_client *pclient) { struct program_client_extra_fd *efds; unsigned int i, count; if (!array_is_created(&pclient->extra_fds)) return; efds = array_get_modifiable(&pclient->extra_fds, &count); for ( i = 0; i < count; i++ ) { if ( efds[i].input != NULL ) i_stream_unref(&efds[i].input); if ( efds[i].io != NULL ) io_remove(&efds[i].io); if ( efds[i].parent_fd != -1 && close(efds[i].parent_fd) < 0 ) i_error("close(fd=%d) failed: %m", efds[i].parent_fd); } }
void virtual_transaction_rollback(struct mailbox_transaction_context *t) { struct virtual_transaction_context *vt = (struct virtual_transaction_context *)t; struct mailbox_transaction_context **bt; unsigned int i, count; if (t->save_ctx != NULL) { virtual_save_free(t->save_ctx); t->save_ctx = NULL; } bt = array_get_modifiable(&vt->backend_transactions, &count); for (i = 0; i < count; i++) mailbox_transaction_rollback(&bt[i]); array_free(&vt->backend_transactions); index_transaction_rollback(t); }
static void priorityq_remove_idx(struct priorityq *pq, unsigned int idx) { struct priorityq_item **items; unsigned int count; items = array_get_modifiable(&pq->items, &count); i_assert(idx < count); /* move last item over the removed one and fix the heap */ count--; heap_items_swap(items, idx, count); array_delete(&pq->items, count, 1); if (count > 0 && idx != count) { if (idx > 0) idx = heap_item_bubble_up(pq, idx); heap_item_bubble_down(pq, idx); } }
struct imap_search_update * client_search_update_lookup(struct client *client, const char *tag, unsigned int *idx_r) { struct imap_search_update *updates; unsigned int i, count; if (!array_is_created(&client->search_updates)) return NULL; updates = array_get_modifiable(&client->search_updates, &count); for (i = 0; i < count; i++) { if (strcmp(updates[i].tag, tag) == 0) { *idx_r = i; return &updates[i]; } } return NULL; }
void index_sync_changes_delete_to(struct index_sync_changes_context *ctx, uint32_t last_uid) { struct mail_index_sync_rec *syncs; unsigned int src, dest, count; syncs = array_get_modifiable(&ctx->syncs, &count); for (src = dest = 0; src < count; src++) { i_assert(last_uid >= syncs[src].uid1); if (last_uid <= syncs[src].uid2) { /* keep it */ if (src != dest) syncs[dest] = syncs[src]; dest++; } } array_delete(&ctx->syncs, dest, count - dest); }
static unsigned int heap_item_bubble_up(struct priorityq *pq, unsigned int idx) { struct priorityq_item **items; unsigned int parent_idx, count; items = array_get_modifiable(&pq->items, &count); while (idx > 0) { parent_idx = PARENT_IDX(idx); i_assert(idx < count); if (pq->cmp_callback(items[idx], items[parent_idx]) >= 0) break; /* wrong order - swap */ heap_items_swap(items, idx, parent_idx); idx = parent_idx; } return idx; }
static void heap_item_bubble_down(struct priorityq *pq, unsigned int idx) { struct priorityq_item **items; unsigned int left_idx, right_idx, min_child_idx, count; items = array_get_modifiable(&pq->items, &count); while ((left_idx = LEFT_CHILD_IDX(idx)) < count) { right_idx = RIGHT_CHILD_IDX(idx); if (right_idx >= count || pq->cmp_callback(items[left_idx], items[right_idx]) < 0) min_child_idx = left_idx; else min_child_idx = right_idx; if (pq->cmp_callback(items[min_child_idx], items[idx]) >= 0) break; /* wrong order - swap */ heap_items_swap(items, idx, min_child_idx); idx = min_child_idx; } }
static void tview_close(struct mail_index_view *view) { struct mail_index_view_transaction *tview = (struct mail_index_view_transaction *)view; struct mail_index_transaction *t = tview->t; void **recs; unsigned int i, count; if (tview->lookup_map != NULL) mail_index_unmap(&tview->lookup_map); buffer_free(&tview->lookup_return_data); if (array_is_created(&tview->all_recs)) { recs = array_get_modifiable(&tview->all_recs, &count); for (i = 0; i < count; i++) i_free(recs[i]); array_free(&tview->all_recs); } tview->super->close(view); mail_index_transaction_unref(&t); }
static struct mail_log_group_changes * mail_log_action_get_group(struct mail_log_transaction_context *lt, enum mail_log_event event, const char *data) { struct mail_log_group_changes *group; unsigned int i, count; if (!array_is_created(<->group_changes)) p_array_init(<->group_changes, lt->pool, 8); group = array_get_modifiable(<->group_changes, &count); for (i = 0; i < count; i++) { if (group[i].event == event && null_strcmp(data, group[i].data) == 0) return &group[i]; } group = array_append_space(<->group_changes); group->event = event; group->data = p_strdup(lt->pool, data); return group; }
static bool program_client_input_pending(struct program_client *pclient) { struct program_client_extra_fd *efds = NULL; unsigned int count, i; if ( pclient->program_input != NULL && !pclient->program_input->closed && !i_stream_is_eof(pclient->program_input) ) { return TRUE; } if ( array_is_created(&pclient->extra_fds) ) { efds = array_get_modifiable(&pclient->extra_fds, &count); for ( i = 0; i < count; i++ ) { if ( efds[i].input != NULL && !efds[i].input->closed && !i_stream_is_eof(efds[i].input) ) { return TRUE; } } } return FALSE; }
} T_END; data->save_bodystructure_header = FALSE; return; } if (!hdr->continued) { T_BEGIN { const char *cache_field_name = t_strconcat("hdr.", hdr->name, NULL); data->parse_line.field_idx = mail_cache_register_lookup(_mail->box->cache, cache_field_name); } T_END; } field_idx = data->parse_line.field_idx; match = array_get_modifiable(&mail->header_match, &count); if (field_idx >= count || !HEADER_MATCH_USABLE(mail, match[field_idx])) { /* we don't want this header. */ return; } if (!hdr->continued) { /* beginning of a line. add the header name. */ data->parse_line.start_pos = str_len(mail->header_data); data->parse_line.line_num = data->parse_line_num; str_append(mail->header_data, hdr->name); str_append_n(mail->header_data, hdr->middle, hdr->middle_len); /* remember that we saw this header so we don't add it to cache as nonexistent. */
} array_append(dest, &pattern, 1); } } static void separate_wildcard_mailboxes(struct virtual_mailbox *mbox, ARRAY_TYPE(virtual_backend_box) *wildcard_boxes, ARRAY_TYPE(virtual_backend_box) *neg_boxes, ARRAY_TYPE(virtual_backend_box) *metadata_boxes) { struct virtual_backend_box *const *bboxes; ARRAY_TYPE(virtual_backend_box) *dest; unsigned int i, count; bboxes = array_get_modifiable(&mbox->backend_boxes, &count); t_array_init(wildcard_boxes, I_MIN(16, count)); t_array_init(neg_boxes, 4); t_array_init(metadata_boxes, 4); for (i = 0; i < count;) { if (bboxes[i]->metadata_entry != NULL) dest = metadata_boxes; else if (bboxes[i]->negative_match) dest = neg_boxes; else if (bboxes[i]->glob != NULL) dest = wildcard_boxes; else { dest = NULL; i++; }