Mercurial > dovecot > original-hg > dovecot-1.2
comparison src/lib-storage/index/maildir/maildir-sync.c @ 9201:4e74f4651f5b HEAD
OSX+Maildir: If readdir() fails with EINVAL after doing rename()s, retry. Fixes HFS+.
Based on patch by Apple.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 07 Jul 2009 21:42:06 -0400 |
parents | e7792f4509e6 |
children | 797474444551 |
comparison
equal
deleted
inserted
replaced
9200:5d9eab092e97 | 9201:4e74f4651f5b |
---|---|
353 mail_storage_set_critical(mbox->ibox.box.storage, | 353 mail_storage_set_critical(mbox->ibox.box.storage, |
354 "stat(%s) failed: %m", path); | 354 "stat(%s) failed: %m", path); |
355 return -1; | 355 return -1; |
356 } | 356 } |
357 | 357 |
358 static int maildir_scan_dir(struct maildir_sync_context *ctx, bool new_dir) | 358 static int |
359 maildir_scan_dir(struct maildir_sync_context *ctx, bool new_dir, bool final) | |
359 { | 360 { |
360 struct mail_storage *storage = &ctx->mbox->storage->storage; | 361 struct mail_storage *storage = &ctx->mbox->storage->storage; |
361 const char *path; | 362 const char *path; |
362 DIR *dirp; | 363 DIR *dirp; |
363 string_t *src, *dest; | 364 string_t *src, *dest; |
485 if (ret < 0) | 486 if (ret < 0) |
486 break; | 487 break; |
487 } | 488 } |
488 } | 489 } |
489 | 490 |
491 #ifdef __APPLE__ | |
492 if (errno == EINVAL && move_count > 0 && !final) { | |
493 /* OS X HFS+: readdir() fails sometimes when rename() | |
494 have been done. */ | |
495 move_count = MAILDIR_RENAME_RESCAN_COUNT + 1; | |
496 } | |
497 #endif | |
498 | |
490 if (errno != 0) { | 499 if (errno != 0) { |
491 mail_storage_set_critical(storage, | 500 mail_storage_set_critical(storage, |
492 "readdir(%s) failed: %m", path); | 501 "readdir(%s) failed: %m", path); |
493 ret = -1; | 502 ret = -1; |
494 } | 503 } |
518 ST_MTIME_NSEC(st); | 527 ST_MTIME_NSEC(st); |
519 } | 528 } |
520 } | 529 } |
521 | 530 |
522 return ret < 0 ? -1 : | 531 return ret < 0 ? -1 : |
523 (move_count <= MAILDIR_RENAME_RESCAN_COUNT ? 0 : 1); | 532 (move_count <= MAILDIR_RENAME_RESCAN_COUNT || final ? 0 : 1); |
524 } | 533 } |
525 | 534 |
526 int maildir_sync_header_refresh(struct maildir_mailbox *mbox) | 535 int maildir_sync_header_refresh(struct maildir_mailbox *mbox) |
527 { | 536 { |
528 const void *data; | 537 const void *data; |
810 | 819 |
811 if (new_changed || cur_changed) { | 820 if (new_changed || cur_changed) { |
812 /* if we're going to check cur/ dir our current logic requires | 821 /* if we're going to check cur/ dir our current logic requires |
813 that new/ dir is checked as well. it's a good idea anyway. */ | 822 that new/ dir is checked as well. it's a good idea anyway. */ |
814 unsigned int count = 0; | 823 unsigned int count = 0; |
815 | 824 bool final = FALSE; |
816 while ((ret = maildir_scan_dir(ctx, TRUE)) > 0) { | 825 |
826 while ((ret = maildir_scan_dir(ctx, TRUE, final)) > 0) { | |
817 /* rename()d at least some files, which might have | 827 /* rename()d at least some files, which might have |
818 caused some other files to be missed. check again | 828 caused some other files to be missed. check again |
819 (see MAILDIR_RENAME_RESCAN_COUNT). */ | 829 (see MAILDIR_RENAME_RESCAN_COUNT). */ |
820 if (++count > MAILDIR_SCAN_DIR_MAX_COUNT) | 830 if (++count >= MAILDIR_SCAN_DIR_MAX_COUNT) |
821 break; | 831 final = TRUE; |
822 } | 832 } |
823 if (ret < 0) | 833 if (ret < 0) |
824 return -1; | 834 return -1; |
825 | 835 |
826 if (cur_changed) { | 836 if (cur_changed) { |
827 if (maildir_scan_dir(ctx, FALSE) < 0) | 837 if (maildir_scan_dir(ctx, FALSE, TRUE) < 0) |
828 return -1; | 838 return -1; |
829 } | 839 } |
830 | 840 |
831 maildir_sync_update_next_uid(ctx->mbox); | 841 maildir_sync_update_next_uid(ctx->mbox); |
832 | 842 |