comparison src/lib-storage/index/maildir/maildir-sync.c @ 5910:289f828591f7 HEAD

Code cleanup
author Timo Sirainen <tss@iki.fi>
date Sun, 08 Jul 2007 22:13:53 +0300
parents 62ceb6b2b20d
children 8bb5c7a69405
comparison
equal deleted inserted replaced
5909:afea0be7e27c 5910:289f828591f7
548 TRUE, FALSE); 548 TRUE, FALSE);
549 } 549 }
550 } 550 }
551 551
552 static int maildir_fix_duplicate(struct maildir_sync_context *ctx, 552 static int maildir_fix_duplicate(struct maildir_sync_context *ctx,
553 const char *dir, const char *old_fname) 553 const char *dir, const char *fname2)
554 { 554 {
555 struct maildir_mailbox *mbox = ctx->mbox; 555 const char *fname1, *path1, *path2;
556 const char *existing_fname, *existing_path; 556 const char *new_fname, *new_path;
557 const char *new_fname, *old_path, *new_path; 557 struct stat st1, st2;
558 struct stat ex_st, old_st;
559 int ret = 0; 558 int ret = 0;
560 559
561 existing_fname = 560 fname1 = maildir_uidlist_sync_get_full_filename(ctx->uidlist_sync_ctx,
562 maildir_uidlist_sync_get_full_filename(ctx->uidlist_sync_ctx, 561 fname2);
563 old_fname); 562 i_assert(fname1 != NULL);
564 i_assert(existing_fname != NULL);
565 563
566 t_push(); 564 t_push();
567 565
568 existing_path = t_strconcat(dir, "/", existing_fname, NULL); 566 path1 = t_strconcat(dir, "/", fname1, NULL);
569 old_path = t_strconcat(dir, "/", old_fname, NULL); 567 path2 = t_strconcat(dir, "/", fname2, NULL);
570 568
571 if (stat(existing_path, &ex_st) < 0 || 569 if (stat(path1, &st1) < 0 || stat(path2, &st2) < 0) {
572 stat(old_path, &old_st) < 0) {
573 /* most likely the files just don't exist anymore. 570 /* most likely the files just don't exist anymore.
574 don't really care about other errors much. */ 571 don't really care about other errors much. */
575 t_pop(); 572 t_pop();
576 return 0; 573 return 0;
577 } 574 }
578 if (ex_st.st_ino == old_st.st_ino && 575 if (st1.st_ino == st2.st_ino &&
579 CMP_DEV_T(ex_st.st_dev, old_st.st_dev)) { 576 CMP_DEV_T(st1.st_dev, st2.st_dev)) {
580 /* Files are the same. this means either a race condition 577 /* Files are the same. this means either a race condition
581 between stat() calls, or that the files were link()ed. */ 578 between stat() calls, or that the files were link()ed. */
582 if (ex_st.st_nlink > 1 && old_st.st_nlink == ex_st.st_nlink && 579 if (st1.st_nlink > 1 && st2.st_nlink == st1.st_nlink &&
583 ex_st.st_ctime == old_st.st_ctime && 580 st1.st_ctime == st2.st_ctime &&
584 ex_st.st_ctime < ioloop_time - DUPE_LINKS_DELETE_SECS) { 581 st1.st_ctime < ioloop_time - DUPE_LINKS_DELETE_SECS) {
585 /* The file has hard links and it hasn't had any 582 /* The file has hard links and it hasn't had any
586 changes (such as renames) for a while, so this 583 changes (such as renames) for a while, so this
587 isn't a race condition. 584 isn't a race condition.
588 585
589 rename()ing one file on top of the other would fix 586 rename()ing one file on top of the other would fix
590 this safely, except POSIX decided that rename() 587 this safely, except POSIX decided that rename()
591 doesn't work that way. So we'll have unlink() one 588 doesn't work that way. So we'll have unlink() one
592 and hope that another process didn't just decide to 589 and hope that another process didn't just decide to
593 unlink() the other (uidlist lock prevents this from 590 unlink() the other (uidlist lock prevents this from
594 happening) */ 591 happening) */
595 if (unlink(old_path) == 0) { 592 if (unlink(path2) == 0)
596 i_warning("Unlinked a duplicate: %s", 593 i_warning("Unlinked a duplicate: %s", path2);
597 old_fname); 594 else {
598 } else {
599 mail_storage_set_critical( 595 mail_storage_set_critical(
600 &mbox->storage->storage, 596 &ctx->mbox->storage->storage,
601 "unlink(%s) failed: %m", old_path); 597 "unlink(%s) failed: %m", path2);
602 } 598 }
603 } 599 }
604 t_pop(); 600 t_pop();
605 return 0; 601 return 0;
606 } 602 }
607 603
608 new_fname = maildir_filename_generate(); 604 new_fname = maildir_filename_generate();
609 new_path = t_strconcat(mbox->path, "/new/", new_fname, NULL); 605 new_path = t_strconcat(ctx->mbox->path, "/new/", new_fname, NULL);
610 606
611 if (rename(old_path, new_path) == 0) 607 if (rename(path2, new_path) == 0)
612 i_warning("Fixed a duplicate: %s -> %s", old_fname, new_fname); 608 i_warning("Fixed a duplicate: %s -> %s", path2, new_fname);
613 else if (errno != ENOENT) { 609 else if (errno != ENOENT) {
614 mail_storage_set_critical(&mbox->storage->storage, 610 mail_storage_set_critical(&ctx->mbox->storage->storage,
615 "Couldn't fix a duplicate: rename(%s, %s) failed: %m", 611 "Couldn't fix a duplicate: rename(%s, %s) failed: %m",
616 old_path, new_path); 612 path2, new_path);
617 ret = -1; 613 ret = -1;
618 } 614 }
619 t_pop(); 615 t_pop();
620 616
621 return ret; 617 return ret;