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

« back to all changes in this revision

Viewing changes to src/lib-storage/index/maildir/maildir-uidlist.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) 2003-2011 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2003-2012 Dovecot authors, see the included COPYING file */
2
2
 
3
3
/*
4
4
   Version 1 format has been used for most versions of Dovecot up to v1.0.x.
30
30
#include "istream.h"
31
31
#include "ostream.h"
32
32
#include "str.h"
33
 
#include "hex-binary.h"
34
33
#include "file-dotlock.h"
35
34
#include "close-keep-errno.h"
36
35
#include "nfs-workarounds.h"
37
36
#include "eacces-error.h"
38
37
#include "maildir-storage.h"
39
 
#include "maildir-sync.h"
40
38
#include "maildir-filename.h"
41
39
#include "maildir-uidlist.h"
42
40
 
53
51
 
54
52
#define UIDLIST_IS_LOCKED(uidlist) \
55
53
        ((uidlist)->lock_count > 0)
56
 
#define UIDLIST_ALLOW_WRITING(uidlist) \
57
 
        (UIDLIST_IS_LOCKED(uidlist) || (uidlist)->mbox == NULL)
58
54
 
59
55
struct maildir_uidlist_rec {
60
56
        uint32_t uid;
65
61
ARRAY_DEFINE_TYPE(maildir_uidlist_rec_p, struct maildir_uidlist_rec *);
66
62
 
67
63
struct maildir_uidlist {
68
 
        struct maildir_mailbox *mbox;
 
64
        struct mailbox *box;
69
65
        char *path;
 
66
        struct maildir_index_header *mhdr;
70
67
 
71
68
        int fd;
72
69
        dev_t fd_dev;
90
87
        uoff_t last_read_offset;
91
88
        string_t *hdr_extensions;
92
89
 
93
 
        uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
 
90
        guid_128_t mailbox_guid;
94
91
 
95
92
        unsigned int recreate:1;
96
93
        unsigned int recreate_on_change:1;
100
97
        unsigned int locked_refresh:1;
101
98
        unsigned int unsorted:1;
102
99
        unsigned int have_mailbox_guid:1;
 
100
        unsigned int opened_readonly:1;
103
101
};
104
102
 
105
103
struct maildir_uidlist_sync_ctx {
137
135
                                        bool nonblock, bool refresh,
138
136
                                        bool refresh_when_locked)
139
137
{
140
 
        struct mailbox *box = &uidlist->mbox->box;
 
138
        struct mailbox *box = uidlist->box;
 
139
        const struct mailbox_permissions *perm = mailbox_get_permissions(box);
141
140
        const char *control_dir, *path;
142
141
        mode_t old_mask;
143
142
        const enum dotlock_create_flags dotlock_flags =
153
152
                return 1;
154
153
        }
155
154
 
156
 
        index_storage_lock_notify_reset(&uidlist->mbox->box);
 
155
        index_storage_lock_notify_reset(uidlist->box);
157
156
 
158
157
        control_dir = mailbox_list_get_path(box->list, box->name,
159
158
                                            MAILBOX_LIST_PATH_TYPE_CONTROL);
160
159
        path = t_strconcat(control_dir, "/" MAILDIR_UIDLIST_NAME, NULL);
161
160
 
162
161
        for (i = 0;; i++) {
163
 
                old_mask = umask(0777 & ~box->file_create_mode);
 
162
                old_mask = umask(0777 & ~perm->file_create_mode);
164
163
                ret = file_dotlock_create(&uidlist->dotlock_settings, path,
165
164
                                          dotlock_flags, &uidlist->dotlock);
166
165
                umask(old_mask);
173
172
                                MAIL_ERROR_TEMP, MAIL_ERRSTR_LOCK_TIMEOUT);
174
173
                        return 0;
175
174
                }
176
 
                if (errno != ENOENT || i == MAILDIR_DELETE_RETRY_COUNT ||
177
 
                    uidlist->mbox == NULL) {
 
175
                if (errno != ENOENT || i == MAILDIR_DELETE_RETRY_COUNT) {
178
176
                        if (errno == EACCES) {
179
177
                                mail_storage_set_critical(box->storage, "%s",
180
178
                                        eacces_error_get_creating("file_dotlock_create", path));
187
185
                }
188
186
                /* the control dir doesn't exist. create it unless the whole
189
187
                   mailbox was just deleted. */
190
 
                if (!maildir_set_deleted(&uidlist->mbox->box))
 
188
                if (!maildir_set_deleted(uidlist->box))
191
189
                        return -1;
192
190
        }
193
191
 
232
230
        return uidlist->initial_read;
233
231
}
234
232
 
 
233
bool maildir_uidlist_is_open(struct maildir_uidlist *uidlist)
 
234
{
 
235
        return uidlist->fd != -1;
 
236
}
 
237
 
235
238
void maildir_uidlist_unlock(struct maildir_uidlist *uidlist)
236
239
{
237
240
        i_assert(uidlist->lock_count > 0);
256
259
 
257
260
struct maildir_uidlist *maildir_uidlist_init(struct maildir_mailbox *mbox)
258
261
{
 
262
        struct mailbox *box = &mbox->box;
259
263
        struct maildir_uidlist *uidlist;
260
264
        const char *control_dir;
261
265
 
262
 
        control_dir = mailbox_list_get_path(mbox->box.list, mbox->box.name,
 
266
        control_dir = mailbox_list_get_path(box->list, box->name,
263
267
                                            MAILBOX_LIST_PATH_TYPE_CONTROL);
264
268
 
265
269
        uidlist = i_new(struct maildir_uidlist, 1);
266
 
        uidlist->mbox = mbox;
 
270
        uidlist->box = box;
 
271
        uidlist->mhdr = &mbox->maildir_hdr;
267
272
        uidlist->fd = -1;
268
273
        uidlist->path = i_strconcat(control_dir, "/"MAILDIR_UIDLIST_NAME, NULL);
269
274
        i_array_init(&uidlist->records, 128);
275
280
 
276
281
        uidlist->dotlock_settings.use_io_notify = TRUE;
277
282
        uidlist->dotlock_settings.use_excl_lock =
278
 
                mbox->box.storage->set->dotlock_use_excl;
 
283
                box->storage->set->dotlock_use_excl;
279
284
        uidlist->dotlock_settings.nfs_flush =
280
 
                mbox->box.storage->set->mail_nfs_storage;
 
285
                box->storage->set->mail_nfs_storage;
281
286
        uidlist->dotlock_settings.timeout =
282
 
                mail_storage_get_lock_timeout(&mbox->storage->storage,
 
287
                mail_storage_get_lock_timeout(box->storage,
283
288
                        MAILDIR_UIDLIST_LOCK_STALE_TIMEOUT + 2);
284
289
        uidlist->dotlock_settings.stale_timeout =
285
290
                MAILDIR_UIDLIST_LOCK_STALE_TIMEOUT;
286
291
        uidlist->dotlock_settings.callback = dotlock_callback;
287
 
        uidlist->dotlock_settings.context = &mbox->box;
 
292
        uidlist->dotlock_settings.context = box;
288
293
        uidlist->dotlock_settings.temp_prefix = mbox->storage->temp_prefix;
289
294
        return uidlist;
290
295
}
291
296
 
292
297
static void maildir_uidlist_close(struct maildir_uidlist *uidlist)
293
298
{
294
 
        struct mail_storage *storage = uidlist->mbox->box.storage;
 
299
        struct mail_storage *storage = uidlist->box->storage;
295
300
 
296
301
        if (uidlist->fd != -1) {
297
302
                if (close(uidlist->fd) < 0) {
347
352
maildir_uidlist_set_corrupted(struct maildir_uidlist *uidlist,
348
353
                              const char *fmt, ...)
349
354
{
350
 
        struct mail_storage *storage = uidlist->mbox->box.storage;
 
355
        struct mail_storage *storage = uidlist->box->storage;
351
356
        va_list args;
352
357
 
353
358
        va_start(args, fmt);
368
373
static void maildir_uidlist_update_hdr(struct maildir_uidlist *uidlist,
369
374
                                       const struct stat *st)
370
375
{
371
 
        struct maildir_index_header *mhdr;
372
 
 
373
 
        if (uidlist->mbox == NULL) {
374
 
                /* dbox is using this */
375
 
                return;
376
 
        }
377
 
 
378
 
        mhdr = &uidlist->mbox->maildir_hdr;
 
376
        struct maildir_index_header *mhdr = uidlist->mhdr;
 
377
 
379
378
        if (mhdr->uidlist_mtime == 0 && uidlist->version != UIDLIST_VERSION) {
380
379
                /* upgrading from older verson. don't update the
381
380
                   uidlist times until it uses the new format */
580
579
                               unsigned int *uid_validity_r,
581
580
                               unsigned int *next_uid_r)
582
581
{
583
 
        buffer_t *buf;
584
582
        char key;
585
583
 
586
584
        str_truncate(uidlist->hdr_extensions, 0);
600
598
                        *next_uid_r = strtoul(value, NULL, 10);
601
599
                        break;
602
600
                case MAILDIR_UIDLIST_HDR_EXT_GUID:
603
 
                        buf = buffer_create_dynamic(pool_datastack_create(),
604
 
                                                    MAIL_GUID_128_SIZE);
605
 
                        if (hex_to_binary(value, buf) < 0 ||
606
 
                            buf->used != MAIL_GUID_128_SIZE) {
 
601
                        if (guid_128_from_string(value,
 
602
                                                 uidlist->mailbox_guid) < 0) {
607
603
                                maildir_uidlist_set_corrupted(uidlist,
608
604
                                        "Invalid mailbox GUID: %s", value);
609
605
                                return -1;
610
606
                        }
611
 
                        memcpy(uidlist->mailbox_guid, buf->data,
612
 
                               sizeof(uidlist->mailbox_guid));
613
607
                        uidlist->have_mailbox_guid = TRUE;
614
608
                        break;
615
609
                default:
702
696
maildir_uidlist_update_read(struct maildir_uidlist *uidlist,
703
697
                            bool *retry_r, bool try_retry)
704
698
{
705
 
        struct mail_storage *storage = uidlist->mbox->box.storage;
 
699
        struct mail_storage *storage = uidlist->box->storage;
706
700
        const char *line;
707
701
        uint32_t orig_next_uid, orig_uid_validity;
708
702
        struct istream *input;
709
703
        struct stat st;
710
704
        uoff_t last_read_offset;
711
705
        int fd, ret;
 
706
        bool readonly = FALSE;
712
707
 
713
708
        *retry_r = FALSE;
714
709
 
715
710
        if (uidlist->fd == -1) {
716
711
                fd = nfs_safe_open(uidlist->path, O_RDWR);
 
712
                if (fd == -1 && errno == EACCES) {
 
713
                        fd = nfs_safe_open(uidlist->path, O_RDONLY);
 
714
                        readonly = TRUE;
 
715
                }
717
716
                if (fd == -1) {
718
717
                        if (errno != ENOENT) {
719
718
                                mail_storage_set_critical(storage,
814
813
                (void)unlink(uidlist->path);
815
814
        } else if (ret > 0) {
816
815
                /* success */
 
816
                if (readonly)
 
817
                        uidlist->recreate_on_change = TRUE;
817
818
                uidlist->fd = fd;
818
819
                uidlist->fd_dev = st.st_dev;
819
820
                uidlist->fd_ino = st.st_ino;
845
846
static int
846
847
maildir_uidlist_stat(struct maildir_uidlist *uidlist, struct stat *st_r)
847
848
{
848
 
        struct mail_storage *storage = uidlist->mbox->box.storage;
 
849
        struct mail_storage *storage = uidlist->box->storage;
849
850
 
850
851
        if (storage->set->mail_nfs_storage) {
851
852
                nfs_flush_file_handle_cache(uidlist->path);
865
866
static int
866
867
maildir_uidlist_has_changed(struct maildir_uidlist *uidlist, bool *recreated_r)
867
868
{
868
 
        struct mail_storage *storage = uidlist->mbox->box.storage;
 
869
        struct mail_storage *storage = uidlist->box->storage;
869
870
        struct stat st;
870
871
        int ret;
871
872
 
924
925
        }
925
926
 
926
927
        uidlist->fd = nfs_safe_open(uidlist->path, O_RDWR);
 
928
        if (uidlist->fd == -1 && errno == EACCES) {
 
929
                uidlist->fd = nfs_safe_open(uidlist->path, O_RDONLY);
 
930
                uidlist->recreate_on_change = TRUE;
 
931
        }
927
932
        if (uidlist->fd == -1 && errno != ENOENT) {
928
 
                mail_storage_set_critical(uidlist->mbox->box.storage,
 
933
                mail_storage_set_critical(uidlist->box->storage,
929
934
                        "open(%s) failed: %m", uidlist->path);
930
935
                return -1;
931
936
        }
964
969
 
965
970
int maildir_uidlist_refresh_fast_init(struct maildir_uidlist *uidlist)
966
971
{
967
 
        const struct maildir_index_header *mhdr = &uidlist->mbox->maildir_hdr;
968
 
        struct mail_index *index = uidlist->mbox->box.index;
 
972
        const struct maildir_index_header *mhdr = uidlist->mhdr;
 
973
        struct mail_index *index = uidlist->box->index;
969
974
        struct mail_index_view *view;
970
975
        const struct mail_index_header *hdr;
971
976
        struct stat st;
1035
1040
                           enum maildir_uidlist_rec_flag *flags_r,
1036
1041
                           const char **fname_r)
1037
1042
{
1038
 
        int ret;
1039
 
 
1040
 
        ret = maildir_uidlist_lookup_nosync(uidlist, uid, flags_r, fname_r);
1041
 
        if (ret <= 0) {
1042
 
                if (ret < 0)
1043
 
                        return -1;
1044
 
                if (uidlist->fd != -1 || uidlist->mbox == NULL) {
1045
 
                        /* refresh uidlist and check again in case it was added
1046
 
                           after the last mailbox sync */
1047
 
                        if (maildir_uidlist_refresh(uidlist) < 0)
1048
 
                                return -1;
1049
 
                } else {
1050
 
                        /* the uidlist doesn't exist. */
1051
 
                        if (maildir_storage_sync_force(uidlist->mbox, uid) < 0)
1052
 
                                return -1;
1053
 
                }
1054
 
 
1055
 
                /* try again */
1056
 
                ret = maildir_uidlist_lookup_nosync(uidlist, uid,
1057
 
                                                    flags_r, fname_r);
1058
 
        }
1059
 
 
1060
 
        return ret;
1061
 
}
1062
 
 
1063
 
int maildir_uidlist_lookup_nosync(struct maildir_uidlist *uidlist, uint32_t uid,
1064
 
                                  enum maildir_uidlist_rec_flag *flags_r,
1065
 
                                  const char **fname_r)
1066
 
{
1067
1043
        struct maildir_uidlist_rec *rec;
1068
1044
        int ret;
1069
1045
 
1109
1085
}
1110
1086
 
1111
1087
int maildir_uidlist_get_mailbox_guid(struct maildir_uidlist *uidlist,
1112
 
                                     uint8_t mailbox_guid[MAIL_GUID_128_SIZE])
 
1088
                                     guid_128_t mailbox_guid)
1113
1089
{
1114
1090
        if (!uidlist->initial_hdr_read) {
1115
1091
                if (maildir_uidlist_refresh(uidlist) < 0)
1120
1096
                if (maildir_uidlist_update(uidlist) < 0)
1121
1097
                        return -1;
1122
1098
        }
1123
 
        memcpy(mailbox_guid, uidlist->mailbox_guid, MAIL_GUID_128_SIZE);
 
1099
        memcpy(mailbox_guid, uidlist->mailbox_guid, GUID_128_SIZE);
1124
1100
        return 0;
1125
1101
}
1126
1102
 
1127
1103
void maildir_uidlist_set_mailbox_guid(struct maildir_uidlist *uidlist,
1128
 
                                      const uint8_t mailbox_guid[MAIL_GUID_128_SIZE])
 
1104
                                      const guid_128_t mailbox_guid)
1129
1105
{
1130
1106
        if (memcmp(uidlist->mailbox_guid, mailbox_guid,
1131
1107
                   sizeof(uidlist->mailbox_guid)) != 0) {
1228
1204
{
1229
1205
        const struct mail_index_header *hdr;
1230
1206
 
1231
 
        if (uidlist->mbox->box.opened) {
1232
 
                hdr = mail_index_get_header(uidlist->mbox->box.view);
 
1207
        if (uidlist->box->opened) {
 
1208
                hdr = mail_index_get_header(uidlist->box->view);
1233
1209
                if (hdr->uid_validity != 0) {
1234
1210
                        uidlist->uid_validity = hdr->uid_validity;
1235
1211
                        return;
1236
1212
                }
1237
1213
        }
1238
1214
        uidlist->uid_validity =
1239
 
                maildir_get_uidvalidity_next(uidlist->mbox->box.list);
 
1215
                maildir_get_uidvalidity_next(uidlist->box->list);
1240
1216
}
1241
1217
 
1242
1218
static int maildir_uidlist_write_fd(struct maildir_uidlist *uidlist, int fd,
1243
1219
                                    const char *path, unsigned int first_idx,
1244
1220
                                    uoff_t *file_size_r)
1245
1221
{
1246
 
        struct mail_storage *storage = uidlist->mbox->box.storage;
 
1222
        struct mail_storage *storage = uidlist->box->storage;
1247
1223
        struct maildir_uidlist_iter_ctx *iter;
1248
1224
        struct ostream *output;
1249
1225
        struct maildir_uidlist_rec *rec;
1266
1242
                if (uidlist->uid_validity == 0)
1267
1243
                        maildir_uidlist_generate_uid_validity(uidlist);
1268
1244
                if (!uidlist->have_mailbox_guid)
1269
 
                        mail_generate_guid_128(uidlist->mailbox_guid);
 
1245
                        guid_128_generate(uidlist->mailbox_guid);
1270
1246
 
1271
1247
                i_assert(uidlist->next_uid > 0);
1272
1248
                str_printfa(str, "%u %c%u %c%u %c%s", uidlist->version,
1275
1251
                            MAILDIR_UIDLIST_HDR_EXT_NEXT_UID,
1276
1252
                            uidlist->next_uid,
1277
1253
                            MAILDIR_UIDLIST_HDR_EXT_GUID,
1278
 
                            binary_to_hex(uidlist->mailbox_guid,
1279
 
                                          sizeof(uidlist->mailbox_guid)));
 
1254
                            guid_128_to_string(uidlist->mailbox_guid));
1280
1255
                if (str_len(uidlist->hdr_extensions) > 0) {
1281
1256
                        str_append_c(str, ' ');
1282
1257
                        str_append_str(str, uidlist->hdr_extensions);
1348
1323
 
1349
1324
        /* we could get here when opening and locking mailbox,
1350
1325
           before index files have been opened. */
1351
 
        if (!uidlist->mbox->box.opened)
 
1326
        if (!uidlist->box->opened)
1352
1327
                return;
1353
1328
 
1354
 
        mail_index_refresh(uidlist->mbox->box.index);
1355
 
        view = mail_index_view_open(uidlist->mbox->box.index);
 
1329
        mail_index_refresh(uidlist->box->index);
 
1330
        view = mail_index_view_open(uidlist->box->index);
1356
1331
        count = array_count(&uidlist->records);
1357
1332
        hdr = mail_index_get_header(view);
1358
1333
        if (count * UIDLIST_COMPRESS_PERCENTAGE / 100 <= hdr->messages_count) {
1397
1372
 
1398
1373
static int maildir_uidlist_recreate(struct maildir_uidlist *uidlist)
1399
1374
{
1400
 
        struct mailbox *box = &uidlist->mbox->box;
 
1375
        struct mailbox *box = uidlist->box;
 
1376
        const struct mailbox_permissions *perm = mailbox_get_permissions(box);
1401
1377
        const char *control_dir, *temp_path;
1402
1378
        struct stat st;
1403
1379
        mode_t old_mask;
1414
1390
                                "/" MAILDIR_UIDLIST_NAME ".tmp", NULL);
1415
1391
 
1416
1392
        for (i = 0;; i++) {
1417
 
                old_mask = umask(0777 & ~box->file_create_mode);
 
1393
                old_mask = umask(0777 & ~perm->file_create_mode);
1418
1394
                fd = open(temp_path, O_RDWR | O_CREAT | O_TRUNC, 0777);
1419
1395
                umask(old_mask);
1420
1396
                if (fd != -1)
1421
1397
                        break;
1422
1398
 
1423
 
                if (errno != ENOENT || i == MAILDIR_DELETE_RETRY_COUNT ||
1424
 
                    uidlist->mbox == NULL) {
 
1399
                if (errno != ENOENT || i == MAILDIR_DELETE_RETRY_COUNT) {
1425
1400
                        mail_storage_set_critical(box->storage,
1426
1401
                                "open(%s, O_CREAT) failed: %m", temp_path);
1427
1402
                        return -1;
1428
1403
                }
1429
1404
                /* the control dir doesn't exist. create it unless the whole
1430
1405
                   mailbox was just deleted. */
1431
 
                if (!maildir_set_deleted(&uidlist->mbox->box))
 
1406
                if (!maildir_set_deleted(uidlist->box))
1432
1407
                        return -1;
1433
1408
        }
1434
1409
 
1435
 
        if (box->file_create_gid != (gid_t)-1 &&
1436
 
            fchown(fd, (uid_t)-1, box->file_create_gid) < 0) {
 
1410
        if (perm->file_create_gid != (gid_t)-1 &&
 
1411
            fchown(fd, (uid_t)-1, perm->file_create_gid) < 0) {
1437
1412
                if (errno == EPERM) {
1438
1413
                        mail_storage_set_critical(box->storage, "%s",
1439
1414
                                eperm_error_get_chgrp("fchown", temp_path,
1440
 
                                                box->file_create_gid,
1441
 
                                                box->file_create_gid_origin));
 
1415
                                                perm->file_create_gid,
 
1416
                                                perm->file_create_gid_origin));
1442
1417
                } else {
1443
1418
                        mail_storage_set_critical(box->storage,
1444
1419
                                "fchown(%s) failed: %m", temp_path);
1535
1510
static int maildir_uidlist_sync_update(struct maildir_uidlist_sync_ctx *ctx)
1536
1511
{
1537
1512
        struct maildir_uidlist *uidlist = ctx->uidlist;
1538
 
        struct mail_storage *storage = uidlist->mbox->box.storage;
 
1513
        struct mail_storage *storage = uidlist->box->storage;
1539
1514
        struct stat st;
1540
1515
        uoff_t file_size;
1541
1516
 
1547
1522
                i_assert(uidlist->initial_hdr_read);
1548
1523
                if (maildir_uidlist_open_latest(uidlist) < 0)
1549
1524
                        return -1;
 
1525
                if (uidlist->recreate_on_change)
 
1526
                        return maildir_uidlist_recreate(uidlist);
1550
1527
        }
1551
1528
        i_assert(ctx->first_unwritten_pos != (unsigned int)-1);
1552
1529
 
1647
1624
        *sync_ctx_r = ctx = i_new(struct maildir_uidlist_sync_ctx, 1);
1648
1625
        ctx->uidlist = uidlist;
1649
1626
        ctx->sync_flags = sync_flags;
1650
 
        ctx->partial = (!locked && ctx->uidlist->mbox != NULL) ||
 
1627
        ctx->partial = !locked ||
1651
1628
                (sync_flags & MAILDIR_UIDLIST_SYNC_PARTIAL) != 0;
1652
1629
        ctx->locked = locked;
1653
1630
        ctx->first_unwritten_pos = (unsigned int)-1;
1710
1687
        }
1711
1688
        if (uid != 0) {
1712
1689
                if (rec->uid != uid && rec->uid != (uint32_t)-1) {
1713
 
                        mail_storage_set_critical(uidlist->mbox->box.storage,
 
1690
                        mail_storage_set_critical(uidlist->box->storage,
1714
1691
                                "Maildir: %s changed UID %u -> %u",
1715
1692
                                filename, rec->uid, uid);
1716
1693
                        return -1;
1725
1702
                }
1726
1703
        }
1727
1704
 
1728
 
        rec->flags = (rec->flags | flags) & ~MAILDIR_UIDLIST_REC_FLAG_NONSYNCED;
 
1705
        rec->flags &= ~MAILDIR_UIDLIST_REC_FLAG_NEW_DIR;
 
1706
        rec->flags = (rec->flags | flags) &
 
1707
                ~MAILDIR_UIDLIST_REC_FLAG_NONSYNCED;
1729
1708
        rec->filename = p_strdup(uidlist->record_pool, filename);
1730
1709
        hash_table_insert(uidlist->files, rec->filename, rec);
1731
1710
 
1777
1756
                return -1;
1778
1757
        for (p = filename; *p != '\0'; p++) {
1779
1758
                if (*p == 13 || *p == 10) {
1780
 
                        struct mailbox *box = &uidlist->mbox->box;
 
1759
                        struct mailbox *box = uidlist->box;
1781
1760
 
1782
1761
                        dir = mailbox_list_get_path(box->list, box->name,
1783
1762
                                                MAILBOX_LIST_PATH_TYPE_MAILBOX);
1807
1786
                                MAILDIR_UIDLIST_REC_FLAG_MOVED);
1808
1787
        } else {
1809
1788
                old_rec = hash_table_lookup(uidlist->files, filename);
1810
 
                i_assert(old_rec != NULL || UIDLIST_ALLOW_WRITING(uidlist));
 
1789
                i_assert(old_rec != NULL || UIDLIST_IS_LOCKED(uidlist));
1811
1790
 
1812
1791
                rec = p_new(ctx->record_pool, struct maildir_uidlist_rec, 1);
1813
1792
 
1903
1882
        return TRUE;
1904
1883
}
1905
1884
 
 
1885
void maildir_uidlist_update_fname(struct maildir_uidlist *uidlist,
 
1886
                                  const char *filename)
 
1887
{
 
1888
        struct maildir_uidlist_rec *rec;
 
1889
 
 
1890
        rec = hash_table_lookup(uidlist->files, filename);
 
1891
        if (rec == NULL)
 
1892
                return;
 
1893
 
 
1894
        rec->flags &= ~MAILDIR_UIDLIST_REC_FLAG_NONSYNCED;
 
1895
        if (strcmp(rec->filename, filename) != 0)
 
1896
                rec->filename = p_strdup(uidlist->record_pool, filename);
 
1897
}
 
1898
 
1906
1899
const char *
1907
1900
maildir_uidlist_get_full_filename(struct maildir_uidlist *uidlist,
1908
1901
                                  const char *filename)
1931
1924
        struct maildir_uidlist_rec **recs;
1932
1925
        unsigned int dest, count;
1933
1926
 
1934
 
        i_assert(UIDLIST_ALLOW_WRITING(ctx->uidlist));
 
1927
        i_assert(UIDLIST_IS_LOCKED(ctx->uidlist));
1935
1928
        i_assert(ctx->first_new_pos != (unsigned int)-1);
1936
1929
 
1937
1930
        if (ctx->first_unwritten_pos == (unsigned int)-1)
2014
2007
 
2015
2008
        /* mbox=NULL means we're coming from dbox rebuilding code.
2016
2009
           the dbox is already locked, so allow uidlist recreation */
2017
 
        i_assert(ctx->locked || !ctx->changed || ctx->uidlist->mbox == NULL);
 
2010
        i_assert(ctx->locked || !ctx->changed);
2018
2011
        if ((ctx->changed || maildir_uidlist_want_compress(ctx)) &&
2019
 
            !ctx->failed && (ctx->locked || ctx->uidlist->mbox == NULL)) {
 
2012
            !ctx->failed && ctx->locked) {
2020
2013
                T_BEGIN {
2021
2014
                        if (maildir_uidlist_sync_update(ctx) < 0) {
2022
2015
                                /* we couldn't write everything we wanted. make