~james-page/ubuntu/raring/dovecot/autopkgtest

« back to all changes in this revision

Viewing changes to src/doveadm/doveadm-mail-index.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-06-11 11:11:54 UTC
  • mfrom: (1.15.2) (4.1.27 sid)
  • Revision ID: package-import@ubuntu.com-20120611111154-678cwbdj6ktgsv1h
Tags: 1:2.1.7-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/{control,rules}: enable PIE hardening.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + d/control: Added Pre-Depends: dpkg (>= 1.15.6) to dovecot-dbg to support
    xz compression in Ubuntu.
  + d/control: Demote dovecot-common Recommends: to Suggests: to prevent
    install of extra packages on upgrade.
  + d/patches/dovecot-drac.patch: Updated with version for dovecot >= 2.0.0.
  + d/control: Drop B-D on systemd.
* Dropped changes:
  + d/patches/fix-racey-restart.patch: part of 2.1.x, no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
 
4
#include "str.h"
 
5
#include "strescape.h"
 
6
#include "network.h"
 
7
#include "write-full.h"
4
8
#include "mail-namespace.h"
5
9
#include "mail-storage.h"
6
10
#include "mail-search-build.h"
 
11
#include "doveadm-settings.h"
7
12
#include "doveadm-mail.h"
8
13
 
 
14
#include <stdio.h>
 
15
 
 
16
#define INDEXER_SOCKET_NAME "indexer"
 
17
#define INDEXER_HANDSHAKE "VERSION\tindexer\t1\t0\n"
 
18
 
 
19
struct index_cmd_context {
 
20
        struct doveadm_mail_cmd_context ctx;
 
21
 
 
22
        int queue_fd;
 
23
        unsigned int max_recent_msgs;
 
24
        unsigned int queue:1;
 
25
        unsigned int have_wildcards:1;
 
26
};
 
27
 
 
28
static int cmd_index_box_precache(struct mailbox *box)
 
29
{
 
30
        struct mailbox_status status;
 
31
        struct mailbox_transaction_context *trans;
 
32
        struct mail_search_args *search_args;
 
33
        struct mail_search_context *ctx;
 
34
        struct mail *mail;
 
35
        struct mailbox_metadata metadata;
 
36
        uint32_t seq;
 
37
        unsigned int counter = 0, max;
 
38
        int ret = 0;
 
39
 
 
40
        if (mailbox_get_metadata(box, MAILBOX_METADATA_PRECACHE_FIELDS,
 
41
                                 &metadata) < 0)
 
42
                return -1;
 
43
        mailbox_get_open_status(box, STATUS_MESSAGES | STATUS_LAST_CACHED_SEQ,
 
44
                                &status);
 
45
 
 
46
        seq = status.last_cached_seq + 1;
 
47
        if (seq > status.messages) {
 
48
                if (doveadm_verbose) {
 
49
                        i_info("%s: Cache is already up to date",
 
50
                               mailbox_get_vname(box));
 
51
                }
 
52
                return 0;
 
53
        }
 
54
        if (doveadm_verbose) {
 
55
                i_info("%s: Caching mails seq=%u..%u",
 
56
                       mailbox_get_vname(box), seq, status.messages);
 
57
        }
 
58
 
 
59
        trans = mailbox_transaction_begin(box, MAILBOX_TRANSACTION_FLAG_NO_CACHE_DEC);
 
60
        search_args = mail_search_build_init();
 
61
        mail_search_build_add_seqset(search_args, seq, status.messages);
 
62
        ctx = mailbox_search_init(trans, search_args, NULL,
 
63
                                  metadata.precache_fields, NULL);
 
64
        mail_search_args_unref(&search_args);
 
65
 
 
66
        max = status.messages - seq + 1;
 
67
        while (mailbox_search_next(ctx, &mail)) {
 
68
                mail_precache(mail);
 
69
                if (doveadm_verbose && ++counter % 100 == 0) {
 
70
                        printf("\r%u/%u", counter, max);
 
71
                        fflush(stdout);
 
72
                }
 
73
        }
 
74
        if (doveadm_verbose)
 
75
                printf("\r%u/%u\n", counter, max);
 
76
        if (mailbox_search_deinit(&ctx) < 0)
 
77
                ret = -1;
 
78
        if (mailbox_transaction_commit(&trans) < 0)
 
79
                ret = -1;
 
80
        return ret;
 
81
}
 
82
 
9
83
static int
10
 
cmd_index_box(const struct mailbox_info *info)
 
84
cmd_index_box(struct index_cmd_context *ctx, const struct mailbox_info *info)
11
85
{
12
86
        struct mailbox *box;
13
 
        const char *storage_name;
 
87
        struct mailbox_status status;
14
88
        int ret = 0;
15
89
 
16
 
        storage_name = mail_namespace_get_storage_name(info->ns, info->name);
17
 
        box = mailbox_alloc(info->ns->list, storage_name,
18
 
                            MAILBOX_FLAG_KEEP_RECENT |
 
90
        box = mailbox_alloc(info->ns->list, info->name,
19
91
                            MAILBOX_FLAG_IGNORE_ACLS);
20
 
 
21
 
        if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ |
22
 
                         MAILBOX_SYNC_FLAG_PRECACHE) < 0) {
 
92
        if (ctx->max_recent_msgs != 0) {
 
93
                /* index only if there aren't too many recent messages.
 
94
                   don't bother syncing the mailbox, that alone can take a
 
95
                   while with large maildirs. */
 
96
                if (mailbox_open(box) < 0) {
 
97
                        i_error("Opening mailbox %s failed: %s", info->name,
 
98
                                mail_storage_get_last_error(mailbox_get_storage(box), NULL));
 
99
                        doveadm_mail_failed_mailbox(&ctx->ctx, box);
 
100
                        mailbox_free(&box);
 
101
                        return -1;
 
102
                } 
 
103
 
 
104
                mailbox_get_open_status(box, STATUS_RECENT, &status);
 
105
                if (status.recent > ctx->max_recent_msgs) {
 
106
                        mailbox_free(&box);
 
107
                        return 0;
 
108
                }
 
109
        }
 
110
 
 
111
        if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
23
112
                i_error("Syncing mailbox %s failed: %s", info->name,
24
113
                        mail_storage_get_last_error(mailbox_get_storage(box), NULL));
 
114
                doveadm_mail_failed_mailbox(&ctx->ctx, box);
25
115
                ret = -1;
 
116
        } else {
 
117
                if (cmd_index_box_precache(box) < 0) {
 
118
                        doveadm_mail_failed_mailbox(&ctx->ctx, box);
 
119
                        ret = -1;
 
120
                }
26
121
        }
27
 
 
28
122
        mailbox_free(&box);
29
123
        return ret;
30
124
}
31
125
 
32
 
static void
33
 
cmd_index_run(struct doveadm_mail_cmd_context *ctx, struct mail_user *user)
34
 
{
 
126
static void index_queue_connect(struct index_cmd_context *ctx)
 
127
{
 
128
        const char *path;
 
129
 
 
130
        path = t_strconcat(doveadm_settings->base_dir,
 
131
                           "/"INDEXER_SOCKET_NAME, NULL);
 
132
        ctx->queue_fd = net_connect_unix(path);
 
133
        if (ctx->queue_fd == -1)
 
134
                i_fatal("net_connect_unix(%s) failed: %m", path);
 
135
        if (write_full(ctx->queue_fd, INDEXER_HANDSHAKE,
 
136
                       strlen(INDEXER_HANDSHAKE)) < 0)
 
137
                i_fatal("write(indexer) failed: %m");
 
138
}
 
139
 
 
140
static void cmd_index_queue(struct index_cmd_context *ctx,
 
141
                            struct mail_user *user, const char *mailbox)
 
142
{
 
143
        if (ctx->queue_fd == -1)
 
144
                index_queue_connect(ctx);
 
145
 
 
146
        T_BEGIN {
 
147
                string_t *str = t_str_new(256);
 
148
 
 
149
                str_append(str, "APPEND\t0\t");
 
150
                str_tabescape_write(str, user->username);
 
151
                str_append_c(str, '\t');
 
152
                str_tabescape_write(str, mailbox);
 
153
                str_printfa(str, "\t%u\n", ctx->max_recent_msgs);
 
154
                if (write_full(ctx->queue_fd, str_data(str), str_len(str)) < 0)
 
155
                        i_fatal("write(indexer) failed: %m");
 
156
        } T_END;
 
157
}
 
158
 
 
159
static int
 
160
cmd_index_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
 
161
{
 
162
        struct index_cmd_context *ctx = (struct index_cmd_context *)_ctx;
35
163
        const enum mailbox_list_iter_flags iter_flags =
36
164
                MAILBOX_LIST_ITER_RAW_LIST |
37
 
                MAILBOX_LIST_ITER_NO_AUTO_INBOX |
 
165
                MAILBOX_LIST_ITER_NO_AUTO_BOXES |
38
166
                MAILBOX_LIST_ITER_RETURN_NO_FLAGS |
39
167
                MAILBOX_LIST_ITER_STAR_WITHIN_NS;
40
168
        const enum namespace_type ns_mask =
41
169
                NAMESPACE_PRIVATE | NAMESPACE_SHARED | NAMESPACE_PUBLIC;
42
170
        struct mailbox_list_iterate_context *iter;
43
171
        const struct mailbox_info *info;
44
 
 
45
 
        iter = mailbox_list_iter_init_namespaces(user->namespaces, ctx->args,
 
172
        unsigned int i;
 
173
        int ret = 0;
 
174
 
 
175
        if (ctx->queue && !ctx->have_wildcards) {
 
176
                /* we can do this quickly without going through the mailboxes */
 
177
                for (i = 0; _ctx->args[i] != NULL; i++)
 
178
                        cmd_index_queue(ctx, user, _ctx->args[i]);
 
179
                return 0;
 
180
        }
 
181
 
 
182
        iter = mailbox_list_iter_init_namespaces(user->namespaces, _ctx->args,
46
183
                                                 ns_mask, iter_flags);
47
184
        while ((info = mailbox_list_iter_next(iter)) != NULL) {
48
185
                if ((info->flags & (MAILBOX_NOSELECT |
49
186
                                    MAILBOX_NONEXISTENT)) == 0) T_BEGIN {
50
 
                        (void)cmd_index_box(info);
 
187
                        if (ctx->queue)
 
188
                                cmd_index_queue(ctx, user, info->name);
 
189
                        else {
 
190
                                if (cmd_index_box(ctx, info) < 0)
 
191
                                        ret = -1;
 
192
                        }
51
193
                } T_END;
52
194
        }
53
 
        if (mailbox_list_iter_deinit(&iter) < 0)
 
195
        if (mailbox_list_iter_deinit(&iter) < 0) {
54
196
                i_error("Listing mailboxes failed");
 
197
                doveadm_mail_failed_error(_ctx, MAIL_ERROR_TEMP);
 
198
                ret = -1;
 
199
        }
 
200
        return ret;
55
201
}
56
202
 
57
 
static void cmd_index_init(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
 
203
static void cmd_index_init(struct doveadm_mail_cmd_context *_ctx,
58
204
                           const char *const args[])
59
205
{
 
206
        struct index_cmd_context *ctx = (struct index_cmd_context *)_ctx;
 
207
        unsigned int i;
 
208
 
60
209
        if (args[0] == NULL)
61
210
                doveadm_mail_help_name("index");
 
211
        for (i = 0; args[i] != NULL; i++) {
 
212
                if (strchr(args[i], '*') != NULL ||
 
213
                    strchr(args[i], '%') != NULL) {
 
214
                        ctx->have_wildcards = TRUE;
 
215
                        break;
 
216
                }
 
217
        }
 
218
}
 
219
 
 
220
static void cmd_index_deinit(struct doveadm_mail_cmd_context *_ctx)
 
221
{
 
222
        struct index_cmd_context *ctx = (struct index_cmd_context *)_ctx;
 
223
 
 
224
        if (ctx->queue_fd != -1) {
 
225
                net_disconnect(ctx->queue_fd);
 
226
                ctx->queue_fd = -1;
 
227
        }
 
228
}
 
229
 
 
230
static bool
 
231
cmd_index_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)
 
232
{
 
233
        struct index_cmd_context *ctx = (struct index_cmd_context *)_ctx;
 
234
 
 
235
        switch (c) {
 
236
        case 'q':
 
237
                ctx->queue = TRUE;
 
238
                break;
 
239
        case 'n':
 
240
                if (str_to_uint(optarg, &ctx->max_recent_msgs) < 0) {
 
241
                        i_fatal_status(EX_USAGE,
 
242
                                "Invalid -n parameter number: %s", optarg);
 
243
                }
 
244
                break;
 
245
        default:
 
246
                return FALSE;
 
247
        }
 
248
        return TRUE;
62
249
}
63
250
 
64
251
static struct doveadm_mail_cmd_context *cmd_index_alloc(void)
65
252
{
66
 
        struct doveadm_mail_cmd_context *ctx;
 
253
        struct index_cmd_context *ctx;
67
254
 
68
 
        ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
69
 
        ctx->v.init = cmd_index_init;
70
 
        ctx->v.run = cmd_index_run;
71
 
        return ctx;
 
255
        ctx = doveadm_mail_cmd_alloc(struct index_cmd_context);
 
256
        ctx->queue_fd = -1;
 
257
        ctx->ctx.getopt_args = "qn:";
 
258
        ctx->ctx.v.parse_arg = cmd_index_parse_arg;
 
259
        ctx->ctx.v.init = cmd_index_init;
 
260
        ctx->ctx.v.deinit = cmd_index_deinit;
 
261
        ctx->ctx.v.run = cmd_index_run;
 
262
        return &ctx->ctx;
72
263
}
73
264
 
74
265
struct doveadm_mail_cmd cmd_index = {
75
 
        cmd_index_alloc, "index", "<mailbox mask>"
 
266
        cmd_index_alloc, "index", "[-q] [-n <max recent>] <mailbox mask>"
76
267
};