~ubuntu-branches/ubuntu/trusty/dovecot/trusty-updates

« back to all changes in this revision

Viewing changes to src/lib-storage/index/dbox-common/dbox-storage.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-08 09:35:49 UTC
  • mfrom: (1.15.3) (96.1.1 trusty-proposed)
  • Revision ID: package-import@ubuntu.com-20140108093549-814nkqdcxfbvgktg
Tags: 1:2.2.9-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/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.
  + Use the autotools-dev dh addon to update config.guess/config.sub for
    arm64.
* Dropped changes, included in Debian:
  - Update Dovecot name to reflect distribution in login greeting.
  - Update Drac plugin for >= 2.0.0 support.
* d/control: Drop dovecot-postfix package as its no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2007-2012 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2007-2013 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
 
4
#include "abspath.h"
4
5
#include "ioloop.h"
 
6
#include "abspath.h"
5
7
#include "fs-api.h"
6
8
#include "mkdir-parents.h"
7
9
#include "unlink-old-files.h"
28
30
}
29
31
 
30
32
static bool
31
 
dbox_alt_path_has_changed(const char *root_dir,
32
 
                          const char *alt_path, const char *alt_symlink_path)
 
33
dbox_alt_path_has_changed(const char *root_dir, const char *alt_path,
 
34
                          const char *alt_path2, const char *alt_symlink_path)
33
35
{
34
 
        char buf[PATH_MAX];
35
 
        ssize_t ret;
 
36
        const char *linkpath;
36
37
 
37
 
        ret = readlink(alt_symlink_path, buf, sizeof(buf)-1);
38
 
        if (ret < 0) {
 
38
        if (t_readlink(alt_symlink_path, &linkpath) < 0) {
39
39
                if (errno == ENOENT)
40
40
                        return alt_path != NULL;
41
41
                i_error("readlink(%s) failed: %m", alt_symlink_path);
42
42
                return FALSE;
43
43
        }
44
 
        buf[ret] = '\0';
45
44
 
46
45
        if (alt_path == NULL) {
47
46
                i_warning("dbox %s: Original ALT=%s, "
48
 
                          "but currently no ALT path set", root_dir, buf);
 
47
                          "but currently no ALT path set", root_dir, linkpath);
49
48
                return TRUE;
50
 
        } else if (strcmp(buf, alt_path) != 0) {
 
49
        } else if (strcmp(linkpath, alt_path) != 0) {
 
50
                if (strcmp(linkpath, alt_path2) == 0) {
 
51
                        /* FIXME: for backwards compatibility. old versions
 
52
                           created the symlink to mailboxes/ directory, which
 
53
                           was fine with sdbox, but didn't even exist with
 
54
                           mdbox. we'll silently replace the symlink. */
 
55
                        return TRUE;
 
56
                }
51
57
                i_warning("dbox %s: Original ALT=%s, "
52
 
                          "but currently ALT=%s", root_dir, buf, alt_path);
 
58
                          "but currently ALT=%s", root_dir, linkpath, alt_path);
53
59
                return TRUE;
54
60
        }
55
61
        return FALSE;
57
63
 
58
64
static void dbox_verify_alt_path(struct mailbox_list *list)
59
65
{
60
 
        const char *root_dir, *alt_symlink_path, *alt_path;
 
66
        const char *root_dir, *alt_symlink_path, *alt_path, *alt_path2;
61
67
 
62
 
        root_dir = mailbox_list_get_path(list, NULL,
63
 
                                         MAILBOX_LIST_PATH_TYPE_DIR);
 
68
        root_dir = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_DIR);
64
69
        alt_symlink_path =
65
70
                t_strconcat(root_dir, "/"DBOX_ALT_SYMLINK_NAME, NULL);
66
 
        alt_path = mailbox_list_get_path(list, NULL,
67
 
                                         MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX);
68
 
        if (!dbox_alt_path_has_changed(root_dir, alt_path, alt_symlink_path))
 
71
        (void)mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_ALT_DIR,
 
72
                                         &alt_path);
 
73
        (void)mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX,
 
74
                                         &alt_path2);
 
75
        if (!dbox_alt_path_has_changed(root_dir, alt_path, alt_path2,
 
76
                                       alt_symlink_path))
69
77
                return;
70
78
 
71
79
        /* unlink/create the current alt path symlink */
82
90
 
83
91
int dbox_storage_create(struct mail_storage *_storage,
84
92
                        struct mail_namespace *ns,
85
 
                        const char **error_r ATTR_UNUSED)
 
93
                        const char **error_r)
86
94
{
87
95
        struct dbox_storage *storage = (struct dbox_storage *)_storage;
88
96
        const struct mail_storage_settings *set = _storage->set;
89
 
        struct fs_settings fs_set;
90
 
 
91
 
        memset(&fs_set, 0, sizeof(fs_set));
92
 
        fs_set.temp_file_prefix = mailbox_list_get_global_temp_prefix(ns->list);
93
 
 
94
 
        if (*set->mail_attachment_fs != '\0') T_BEGIN {
 
97
        const char *error;
 
98
 
 
99
        if (*set->mail_attachment_fs != '\0') {
95
100
                const char *name, *args, *dir;
96
101
 
97
102
                args = strchr(set->mail_attachment_fs, ' ');
101
106
                } else {
102
107
                        name = t_strdup_until(set->mail_attachment_fs, args++);
103
108
                }
 
109
                if (strcmp(name, "sis-queue") == 0 &&
 
110
                    (_storage->class_flags & MAIL_STORAGE_CLASS_FLAG_FILE_PER_MSG) != 0) {
 
111
                        /* FIXME: the deduplication part doesn't work, because
 
112
                           sdbox renames the files.. */
 
113
                        *error_r = "mail_attachment_fs: "
 
114
                                "sis-queue not currently supported by sdbox";
 
115
                        return -1;
 
116
                }
104
117
                dir = mail_user_home_expand(_storage->user,
105
118
                                            set->mail_attachment_dir);
106
119
                storage->attachment_dir = p_strdup(_storage->pool, dir);
107
 
                storage->attachment_fs = fs_init(name, args, &fs_set);
108
 
        } T_END;
109
 
 
110
 
        dbox_verify_alt_path(ns->list);
 
120
 
 
121
                if (mailbox_list_init_fs(ns->list, name, args,
 
122
                                         storage->attachment_dir,
 
123
                                         &storage->attachment_fs, &error) < 0) {
 
124
                        *error_r = t_strdup_printf("mail_attachment_fs: %s",
 
125
                                                   error);
 
126
                        return -1;
 
127
                }
 
128
        }
 
129
 
 
130
        if (!ns->list->set.alt_dir_nocheck)
 
131
                dbox_verify_alt_path(ns->list);
111
132
        return 0;
112
133
}
113
134
 
117
138
 
118
139
        if (storage->attachment_fs != NULL)
119
140
                fs_deinit(&storage->attachment_fs);
 
141
        index_storage_destroy(_storage);
120
142
}
121
143
 
122
144
uint32_t dbox_get_uidvalidity_next(struct mailbox_list *list)
123
145
{
124
146
        const char *path;
125
147
 
126
 
        path = mailbox_list_get_path(list, NULL,
127
 
                                     MAILBOX_LIST_PATH_TYPE_CONTROL);
 
148
        path = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_CONTROL);
128
149
        path = t_strconcat(path, "/"DBOX_UIDVALIDITY_FILE_NAME, NULL);
129
150
        return mailbox_uidvalidity_next(list, path);
130
151
}
136
157
        if (box->notify_callback == NULL)
137
158
                index_mailbox_check_remove_all(box);
138
159
        else {
139
 
                dir = mailbox_list_get_path(box->list, box->name,
140
 
                                            MAILBOX_LIST_PATH_TYPE_INDEX);
141
 
                path = t_strdup_printf("%s/"DBOX_INDEX_PREFIX".log", dir);
 
160
                if (mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_INDEX,
 
161
                                        &dir) <= 0)
 
162
                        return;
 
163
                path = t_strdup_printf("%s/"MAIL_INDEX_PREFIX".log", dir);
142
164
                index_mailbox_check_add(box, path);
143
165
        }
144
166
}
158
180
        } else if (st.st_atime > st.st_ctime + DBOX_TMP_DELETE_SECS) {
159
181
                /* there haven't been any changes to this directory since we
160
182
                   last checked it. */
161
 
        } else if (st.st_atime < ioloop_time - interval) {
 
183
        } else if (st.st_atime < ioloop_time - (time_t)interval) {
162
184
                /* time to scan */
163
185
                const char *prefix =
164
186
                        mailbox_list_get_global_temp_prefix(list);
177
199
                ;
178
200
        else if (errno == ENOENT || errno == ENAMETOOLONG) {
179
201
                mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
180
 
                        T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
 
202
                        T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
181
203
                return -1;
182
204
        } else if (errno == EACCES) {
183
205
                mail_storage_set_critical(box->storage, "%s",
193
215
                return -1;
194
216
        mail_index_set_fsync_mode(box->index,
195
217
                                  box->storage->set->parsed_fsync_mode,
196
 
                                  MAIL_INDEX_SYNC_TYPE_APPEND |
197
 
                                  MAIL_INDEX_SYNC_TYPE_EXPUNGE);
 
218
                                  MAIL_INDEX_FSYNC_MASK_APPENDS |
 
219
                                  MAIL_INDEX_FSYNC_MASK_EXPUNGES);
198
220
        return 0;
199
221
}
200
222
 
240
262
        struct stat st;
241
263
        int ret;
242
264
 
243
 
        if (directory &&
244
 
            (box->list->props & MAILBOX_LIST_PROP_NO_NOSELECT) == 0)
245
 
                return 0;
246
 
 
 
265
        if ((ret = index_storage_mailbox_create(box, directory)) <= 0)
 
266
                return ret;
247
267
        if (mailbox_open(box) < 0)
248
268
                return -1;
249
269
 
 
270
        if (mail_index_get_header(box->view)->uid_validity != 0) {
 
271
                mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
 
272
                                       "Mailbox already exists");
 
273
                return -1;
 
274
        }
 
275
 
250
276
        /* if alt path already exists and contains files, rebuild storage so
251
277
           that we don't start overwriting files. */
252
 
        alt_path = mailbox_list_get_path(box->list, box->name,
253
 
                                         MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX);
254
 
        if (alt_path != NULL && stat(alt_path, &st) == 0) {
 
278
        ret = mailbox_get_path_to(box, MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX, &alt_path);
 
279
        if (ret > 0 && stat(alt_path, &st) == 0) {
255
280
                ret = dir_is_empty(box->storage, alt_path);
256
281
                if (ret < 0)
257
282
                        return -1;
270
295
        ret = mail_index_sync_begin(box->index, &sync_ctx, &view, &trans, 0);
271
296
        if (ret <= 0) {
272
297
                i_assert(ret != 0);
273
 
                mail_storage_set_index_error(box);
 
298
                mailbox_set_index_error(box);
274
299
                return -1;
275
300
        }
276
301
 
283
308
 
284
309
        return mail_index_sync_commit(&sync_ctx);
285
310
}
 
311
 
 
312
int dbox_verify_alt_storage(struct mailbox_list *list)
 
313
{
 
314
        const char *alt_path;
 
315
        struct stat st;
 
316
 
 
317
        if (!mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_ALT_DIR,
 
318
                                        &alt_path))
 
319
                return 0;
 
320
 
 
321
        /* make sure alt storage is mounted. if it's not, abort the rebuild. */
 
322
        if (stat(alt_path, &st) == 0)
 
323
                return 0;
 
324
        if (errno != ENOENT) {
 
325
                i_error("stat(%s) failed: %m", alt_path);
 
326
                return -1;
 
327
        }
 
328
 
 
329
        /* try to create the alt directory. if it fails, it means alt
 
330
           storage isn't mounted. */
 
331
        if (mailbox_list_mkdir_root(list, alt_path,
 
332
                                    MAILBOX_LIST_PATH_TYPE_ALT_DIR) < 0)
 
333
                return -1;
 
334
        return 0;
 
335
}
 
336
 
 
337
bool dbox_header_have_flag(struct mailbox *box, uint32_t ext_id,
 
338
                           unsigned int flags_offset, uint8_t flag)
 
339
{
 
340
        const void *data;
 
341
        size_t data_size;
 
342
        uint8_t flags = 0;
 
343
 
 
344
        mail_index_get_header_ext(box->view, ext_id, &data, &data_size);
 
345
        if (flags_offset < data_size)
 
346
                flags = *((const uint8_t *)data + flags_offset);
 
347
        return (flags & flag) != 0;
 
348
}