maildir-util.c revision 490f66d6476d51cc02333d6eb398a5cd94b67f48
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2004-2009 Dovecot authors, see the included COPYING file */
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainenstatic const char *
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainenmaildir_filename_guess(struct maildir_mailbox *mbox, uint32_t uid,
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen struct mail_index_view *view = mbox->flags_view;
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen if (view == NULL || !mail_index_lookup_seq(view, uid, &seq)) {
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen mail_index_lookup_view_flags(view, seq, &flags, &keywords);
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen *have_flags_r = (flags & MAIL_FLAGS_NONRECENT) != 0;
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen fname = maildir_filename_set_flags(NULL, fname, flags, NULL);
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen kw_ctx = maildir_keywords_sync_init_readonly(mbox->keywords,
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen fname = maildir_filename_set_flags(kw_ctx, fname,
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenstatic int maildir_file_do_try(struct maildir_mailbox *mbox, uint32_t uid,
00efa7d99981e18e286c02b18c1163dde18ee521Timo Sirainen maildir_file_do_func *callback, void *context)
7ede6554e451ec039a67beec7d6ee4aff61d386eTimo Sirainen ret = maildir_uidlist_lookup(mbox->uidlist, uid, &flags, &fname);
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen if ((flags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) {
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen /* let's see if we can guess the filename based on index */
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen fname = maildir_filename_guess(mbox, uid, fname, &have_flags);
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen /* don't even bother looking into new/ dir */
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen if ((flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* probably in new/ dir */
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen path = t_strconcat(mbox->path, "/new/", fname, NULL);
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen path = t_strconcat(mbox->path, "/cur/", fname, NULL);
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainenstatic int do_racecheck(struct maildir_mailbox *mbox, const char *path,
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen if (lstat(path, &st) == 0 && (st.st_mode & S_IFLNK) != 0) {
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen /* most likely a symlink pointing to a non-existing file */
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen "Maildir: Symlink destination doesn't exist: %s", path);
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen "maildir_file_do(%s): Filename keeps changing", path);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenint maildir_file_do(struct maildir_mailbox *mbox, uint32_t uid,
00efa7d99981e18e286c02b18c1163dde18ee521Timo Sirainen maildir_file_do_func *callback, void *context)
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen ret = maildir_file_do_try(mbox, uid, callback, context);
7ccdf78cd45aea9d14e048a5b9f077515c71978fTimo Sirainen for (i = 0; i < MAILDIR_RESYNC_RETRY_COUNT && ret == 0; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* file is either renamed or deleted. sync the maildir and
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen see which one. if file appears to be renamed constantly,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen don't try to open it more than 10 times. */
f7ad1162969feff6b08f0e640a928db1783daae9Timo Sirainen if (maildir_storage_sync_force(mbox, uid) < 0)
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen ret = maildir_file_do_try(mbox, uid, callback, context);
785d9cca224d33ca3938e9166784f6483e8a27d7Timo Sirainen if (i == MAILDIR_RESYNC_RETRY_COUNT) T_BEGIN {
825f6569a5276488133796c2f529c65128a09ba0Timo Sirainen ret = maildir_file_do_try(mbox, uid, do_racecheck, context);
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainenstatic int maildir_create_path(struct mailbox *box, const char *path,
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen const char *p, *parent;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen /* mailbox was being deleted just now */
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen /* create index/control root directory */
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen mailbox_list_get_dir_permissions(box->storage->list, NULL,
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen if (mkdir_parents_chown(parent, parent_mode, (uid_t)-1,
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen /* should work now, try again */
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen /* fall through */
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainenstatic int maildir_create_subdirs(struct maildir_mailbox *mbox)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen static const char *subdirs[] = { "cur", "new", "tmp" };
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen unsigned int i;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen /* @UNSAFE: get a list of directories we want to create */
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen dirs[i] = t_strconcat(mbox->path, "/", subdirs[i], NULL);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen dirs[i++] = mail_storage_get_mailbox_control_dir(box->storage,
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen dirs[i++] = mail_storage_get_mailbox_index_dir(box->storage,
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen if (maildir_create_path(box, path, is_mail_dir) < 0)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainenbool maildir_set_deleted(struct maildir_mailbox *mbox)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen /* maildir itself exists. create all of its subdirectories in case
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen they got lost. */