Mercurial > dovecot > original-hg > dovecot-1.2
changeset 4397:5cbabd4ccd9c HEAD
Don't go fixing duplicate maildir filenames without properly checking that
they really are such.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 17 Jun 2006 16:55:30 +0300 |
parents | 208194b3742a |
children | 3e74b2b09ed1 |
files | src/lib-storage/index/maildir/maildir-sync.c src/lib-storage/index/maildir/maildir-uidlist.c src/lib-storage/index/maildir/maildir-uidlist.h |
diffstat | 3 files changed, 42 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/maildir/maildir-sync.c Sat Jun 17 16:42:37 2006 +0300 +++ b/src/lib-storage/index/maildir/maildir-sync.c Sat Jun 17 16:55:30 2006 +0300 @@ -611,15 +611,41 @@ (void)maildir_sync_index_finish(&ctx->index_sync_ctx, TRUE); } -static int maildir_fix_duplicate(struct maildir_mailbox *mbox, const char *dir, - const char *old_fname) +static int maildir_fix_duplicate(struct maildir_sync_context *ctx, + const char *dir, const char *old_fname) { + struct maildir_mailbox *mbox = ctx->mbox; + const char *existing_fname, *existing_path; const char *new_fname, *old_path, *new_path; + struct stat st, st2; int ret = 0; + existing_fname = + maildir_uidlist_sync_get_full_filename(ctx->uidlist_sync_ctx, + old_fname); + i_assert(existing_fname != NULL); + t_push(); + existing_path = t_strconcat(dir, "/", existing_fname, NULL); old_path = t_strconcat(dir, "/", old_fname, NULL); + + if (stat(existing_path, &st) < 0 || + stat(old_path, &st2) < 0) { + /* most likely the files just don't exist anymore. + don't really care about other errors much. */ + t_pop(); + return 0; + } + if (st.st_ino == st2.st_ino && CMP_DEV_T(st.st_dev, st2.st_dev)) { + /* files are the same. this means either a race condition + between stat() calls, or someone has started link()ing the + files. either way there's no data loss if we just leave it + there. */ + t_pop(); + return 0; + } + new_fname = maildir_generate_tmp_filename(&ioloop_timeval); new_path = t_strconcat(mbox->path, "/new/", new_fname, NULL); @@ -724,8 +750,7 @@ break; /* possibly duplicate - try fixing it */ - if (maildir_fix_duplicate(ctx->mbox, - dir, dp->d_name) < 0) { + if (maildir_fix_duplicate(ctx, dir, dp->d_name) < 0) { ret = -1; break; }
--- a/src/lib-storage/index/maildir/maildir-uidlist.c Sat Jun 17 16:42:37 2006 +0300 +++ b/src/lib-storage/index/maildir/maildir-uidlist.c Sat Jun 17 16:55:30 2006 +0300 @@ -804,6 +804,16 @@ return 1; } +const char * +maildir_uidlist_sync_get_full_filename(struct maildir_uidlist_sync_ctx *ctx, + const char *filename) +{ + struct maildir_uidlist_rec *rec; + + rec = hash_lookup(ctx->files, filename); + return rec == NULL ? NULL : rec->filename; +} + static int maildir_time_cmp(const void *p1, const void *p2) { const struct maildir_uidlist_rec *const *rec1 = p1, *const *rec2 = p2;
--- a/src/lib-storage/index/maildir/maildir-uidlist.h Sat Jun 17 16:42:37 2006 +0300 +++ b/src/lib-storage/index/maildir/maildir-uidlist.h Sat Jun 17 16:55:30 2006 +0300 @@ -49,6 +49,9 @@ int maildir_uidlist_sync_next(struct maildir_uidlist_sync_ctx *ctx, const char *filename, enum maildir_uidlist_rec_flag flags); +const char * +maildir_uidlist_sync_get_full_filename(struct maildir_uidlist_sync_ctx *ctx, + const char *filename); void maildir_uidlist_sync_finish(struct maildir_uidlist_sync_ctx *ctx); int maildir_uidlist_sync_deinit(struct maildir_uidlist_sync_ctx **ctx);