X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=mh.c;h=56ff8b4b3b541fd28d0ccd96cd84d0ee38ec677c;hp=56265b5fb5efe72dd3c75ccfcaef1d98436e4f83;hb=4a9d00d99a1b6b24a9fcc8eb604dc3812b2782b8;hpb=6833ce8bdca2d64e14485118f2a4417b7e1cb1b1 diff --git a/mh.c b/mh.c index 56265b5..56ff8b4 100644 --- a/mh.c +++ b/mh.c @@ -30,6 +30,7 @@ #include "sort.h" #include +#include #include #include #include @@ -47,6 +48,7 @@ struct maildir HEADER *h; char *canon_fname; unsigned header_parsed:1; + ino_t inode; struct maildir *next; }; @@ -190,7 +192,8 @@ static int mh_mkstemp (CONTEXT * dest, FILE ** fp, char **tgt) { snprintf (path, _POSIX_PATH_MAX, "%s/.mutt-%s-%d-%d", dest->path, NONULL (Hostname), (int) getpid (), Counter++); - if ((fd = open (path, O_WRONLY | O_EXCL | O_CREAT, 0600)) == -1) + umask(Umask); + if ((fd = open (path, O_WRONLY | O_EXCL | O_CREAT, 0666)) == -1) { if (errno != EEXIST) { @@ -626,7 +629,7 @@ static HEADER *maildir_parse_message (int magic, const char *fname, static int maildir_parse_entry (CONTEXT * ctx, struct maildir ***last, const char *subdir, const char *fname, - int *count, int is_old) + int *count, int is_old, ino_t inode) { struct maildir *entry; HEADER *h = NULL; @@ -666,6 +669,7 @@ static int maildir_parse_entry (CONTEXT * ctx, struct maildir ***last, entry = safe_calloc (sizeof (struct maildir), 1); entry->h = h; entry->header_parsed = (ctx->magic == M_MH); + entry->inode = inode; **last = entry; *last = &entry->next; @@ -723,7 +727,8 @@ static int maildir_parse_dir (CONTEXT * ctx, struct maildir ***last, dprint (2, (debugfile, "%s:%d: parsing %s\n", __FILE__, __LINE__, de->d_name)); - maildir_parse_entry (ctx, last, subdir, de->d_name, count, is_old); + maildir_parse_entry (ctx, last, subdir, de->d_name, count, is_old, + de->d_ino); } closedir (dirp); @@ -779,29 +784,168 @@ static int maildir_move_to_context (CONTEXT * ctx, struct maildir **md) return r; } +/* + * Merge two maildir lists according to the inode numbers. + */ +static struct maildir* maildir_merge_inode (struct maildir *left, + struct maildir *right) +{ + struct maildir* head; + struct maildir* tail; + + if (left && right) + { + if (left->inode < right->inode) + { + head = left; + left = left->next; + } + else + { + head = right; + right = right->next; + } + } + else + { + if (left) + return left; + else + return right; + } + + tail = head; + + while (left && right) + { + if (left->inode < right->inode) + { + tail->next = left; + left = left->next; + } + else + { + tail->next = right; + right = right->next; + } + tail = tail->next; + } + + if (left) + { + tail->next = left; + } + else + { + tail->next = right; + } + + return head; +} + +/* + * Sort maildir list according to inode. + */ +static struct maildir* maildir_sort_inode(struct maildir* list) +{ + struct maildir* left = list; + struct maildir* right = list; + + if (!list || !list->next) + { + return list; + } + + list = list->next; + while (list && list->next) + { + right = right->next; + list = list->next->next; + } + + list = right; + right = right->next; + list->next = 0; + + left = maildir_sort_inode(left); + right = maildir_sort_inode(right); + return maildir_merge_inode(left, right); +} + +#if USE_HCACHE +static size_t maildir_hcache_keylen (const char *fn) +{ + const char * p = strchr (fn, ':'); + return p ? (size_t) (p - fn) : mutt_strlen(fn); +} +#endif /* * This function does the second parsing pass for a maildir-style * folder. */ - void maildir_delayed_parsing (CONTEXT * ctx, struct maildir *md) { struct maildir *p; char fn[_POSIX_PATH_MAX]; + int count; - for (p = md; p; p = p->next) - if (p && p->h && !p->header_parsed) - { - snprintf (fn, sizeof (fn), "%s/%s", ctx->path, p->h->path); - if (maildir_parse_message (ctx->magic, fn, p->h->old, p->h)) - p->header_parsed = 1; - else - mutt_free_header (&p->h); - } -} +#if USE_HCACHE + void *hc = NULL; + void *data; + unsigned int size; + struct timeval *when = NULL; + struct stat lastchanged; + int ret; + + hc = mutt_hcache_open (HeaderCache, ctx->path); +#endif + + for (p = md, count = 0; p; p = p->next, count++) + { + if (! (p && p->h && !p->header_parsed)) + continue; +#if USE_HCACHE + data = mutt_hcache_fetch (hc, p->h->path + 3, &maildir_hcache_keylen); + when = (struct timeval *) data; +#endif + + if (!ctx->quiet && ReadInc && ((count % ReadInc) == 0 || count == 1)) + mutt_message (_("Reading %s... %d"), ctx->path, count); + snprintf (fn, sizeof (fn), "%s/%s", ctx->path, p->h->path); +#if USE_HCACHE + if (option(OPTHCACHEVERIFY)) { + ret = stat(fn, &lastchanged); + } else { + lastchanged.st_mtime = 0; + ret = 0; + } + + if (data != NULL && !ret && lastchanged.st_mtime <= when->tv_sec) + { + p->h = mutt_hcache_restore ((unsigned char *)data, &p->h); + maildir_parse_flags (p->h, fn); + } else +#endif + if (maildir_parse_message (ctx->magic, fn, p->h->old, p->h)) + { + p->header_parsed = 1; + maildir_parse_flags (p->h, fn); +#if USE_HCACHE + mutt_hcache_store (hc, p->h->path + 3, p->h, 0, &maildir_hcache_keylen); +#endif + } else + mutt_free_header (&p->h); +#if USE_HCACHE + FREE(&data); +#endif + } +#if USE_HCACHE + mutt_hcache_close (hc); +#endif +} /* Read a MH/maildir style mailbox. * @@ -835,6 +979,8 @@ int mh_read_dir (CONTEXT * ctx, const char *subdir) mhs_free_sequences (&mhs); } + md = maildir_sort_inode(md); + if (ctx->magic == M_MAILDIR) maildir_delayed_parsing (ctx, md); @@ -930,14 +1076,15 @@ int maildir_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr) FOREVER { - snprintf (path, _POSIX_PATH_MAX, "%s/tmp/%s.%ld.%d_%d.%s%s", - dest->path, subdir, time (NULL), getpid (), Counter++, - NONULL (Hostname), suffix); + snprintf (path, _POSIX_PATH_MAX, "%s/tmp/%s.%ld.%u_%d.%s%s", + dest->path, subdir, time (NULL), (unsigned int)getpid (), + Counter++, NONULL (Hostname), suffix); dprint (2, (debugfile, "maildir_open_new_message (): Trying %s.\n", path)); - if ((fd = open (path, O_WRONLY | O_EXCL | O_CREAT, 0600)) == -1) + umask(Umask); + if ((fd = open (path, O_WRONLY | O_EXCL | O_CREAT, 0666)) == -1) { if (errno != EEXIST) { @@ -1011,8 +1158,9 @@ int maildir_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr) /* construct a new file name. */ FOREVER { - snprintf (path, _POSIX_PATH_MAX, "%s/%ld.%d_%d.%s%s", subdir, - time (NULL), getpid (), Counter++, NONULL (Hostname), suffix); + snprintf (path, _POSIX_PATH_MAX, "%s/%ld.%u_%d.%s%s", subdir, + time (NULL), (unsigned int)getpid (), Counter++, + NONULL (Hostname), suffix); snprintf (full, _POSIX_PATH_MAX, "%s/%s", ctx->path, path); dprint (2, (debugfile, "maildir_commit_message (): renaming %s to %s.\n", @@ -1220,7 +1368,7 @@ static int mh_sync_message (CONTEXT * ctx, int msgno) { HEADER *h = ctx->hdrs[msgno]; - if (h->attach_del) + if (h->attach_del || h->refs_changed || h->irt_changed) if (mh_rewrite_message (ctx, msgno) != 0) return -1; @@ -1231,9 +1379,9 @@ static int maildir_sync_message (CONTEXT * ctx, int msgno) { HEADER *h = ctx->hdrs[msgno]; - if (h->attach_del) + if (h->attach_del || h->refs_changed || h->irt_changed) { - /* when doing attachment deletion, fall back to the MH case. */ + /* when doing attachment deletion/rethreading, fall back to the MH case. */ if (mh_rewrite_message (ctx, msgno) != 0) return (-1); } @@ -1293,6 +1441,9 @@ int mh_sync_mailbox (CONTEXT * ctx, int *index_hint) { char path[_POSIX_PATH_MAX], tmp[_POSIX_PATH_MAX]; int i, j; +#if USE_HCACHE + void *hc = NULL; +#endif /* USE_HCACHE */ if (ctx->magic == M_MH) i = mh_check_mailbox (ctx, index_hint); @@ -1302,6 +1453,11 @@ int mh_sync_mailbox (CONTEXT * ctx, int *index_hint) if (i != 0) return i; +#if USE_HCACHE + if (ctx->magic == M_MAILDIR) + hc = mutt_hcache_open(HeaderCache, ctx->path); +#endif /* USE_HCACHE */ + for (i = 0; i < ctx->msgcount; i++) { if (ctx->hdrs[i]->deleted @@ -1310,7 +1466,13 @@ int mh_sync_mailbox (CONTEXT * ctx, int *index_hint) snprintf (path, sizeof (path), "%s/%s", ctx->path, ctx->hdrs[i]->path); if (ctx->magic == M_MAILDIR || (option (OPTMHPURGE) && ctx->magic == M_MH)) + { +#if USE_HCACHE + if (ctx->magic == M_MAILDIR) + mutt_hcache_delete (hc, ctx->hdrs[i]->path + 3, &maildir_hcache_keylen); +#endif /* USE_HCACHE */ unlink (path); + } else if (ctx->magic == M_MH) { /* MH just moves files out of the way when you delete them */ @@ -1332,16 +1494,21 @@ int mh_sync_mailbox (CONTEXT * ctx, int *index_hint) if (ctx->magic == M_MAILDIR) { if (maildir_sync_message (ctx, i) == -1) - return -1; + goto err; } else { if (mh_sync_message (ctx, i) == -1) - return -1; + goto err; } } } +#if USE_HCACHE + if (ctx->magic == M_MAILDIR) + mutt_hcache_close (hc); +#endif /* USE_HCACHE */ + if (ctx->magic == M_MH) mh_update_sequences (ctx); @@ -1362,6 +1529,13 @@ int mh_sync_mailbox (CONTEXT * ctx, int *index_hint) } return 0; + +err: +#if USE_HCACHE + if (ctx->magic == M_MAILDIR) + mutt_hcache_close (hc); +#endif /* USE_HCACHE */ + return -1; } static char *maildir_canon_filename (char *dest, const char *src, size_t l)