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