X-Git-Url: https://git.llucax.com/software/mutt-debian.git/blobdiff_plain/14c29200cb58d3c4a0830265f2433849781858d0..cefebddeeae89408bcf1b0474c5a734979e5e3ff:/mh.c diff --git a/mh.c b/mh.c index e020d0b..ebe8cd9 100644 --- a/mh.c +++ b/mh.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 1996-2002 Michael R. Elkins - * Copyright (C) 1999-2002 Thomas Roessler + * Copyright (C) 1996-2002,2007,2009 Michael R. Elkins + * Copyright (C) 1999-2005 Thomas Roessler * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,9 +30,7 @@ #include "mailbox.h" #include "mx.h" #include "copy.h" -#include "buffy.h" #include "sort.h" -#include "account.h" #if USE_HCACHE #include "hcache.h" #endif @@ -142,20 +140,25 @@ static short mhs_unset (struct mh_sequences *mhs, int i, short f) #endif -static void mh_read_token (char *t, int *first, int *last) +static int mh_read_token (char *t, int *first, int *last) { char *p; if ((p = strchr (t, '-'))) { *p++ = '\0'; - *first = atoi (t); - *last = atoi (p); + if (mutt_atoi (t, first) < 0 || mutt_atoi (t, last) < 0) + return -1; } else - *first = *last = atoi (t); + { + if (mutt_atoi (t, first) < 0) + return -1; + *last = *first; + } + return 0; } -static void mh_read_sequences (struct mh_sequences *mhs, const char *path) +static int mh_read_sequences (struct mh_sequences *mhs, const char *path) { FILE *fp; int line = 1; @@ -164,15 +167,15 @@ static void mh_read_sequences (struct mh_sequences *mhs, const char *path) size_t sz = 0; short f; - int first, last; + int first, last, rc; char pathname[_POSIX_PATH_MAX]; snprintf (pathname, sizeof (pathname), "%s/.mh_sequences", path); if (!(fp = fopen (pathname, "r"))) - return; + return 0; /* yes, ask callers to silently ignore the error */ - while ((buff = mutt_read_line (buff, &sz, fp, &line))) + while ((buff = mutt_read_line (buff, &sz, fp, &line, 0))) { if (!(t = strtok (buff, " \t:"))) continue; @@ -188,14 +191,23 @@ static void mh_read_sequences (struct mh_sequences *mhs, const char *path) while ((t = strtok (NULL, " \t:"))) { - mh_read_token (t, &first, &last); + if (mh_read_token (t, &first, &last) < 0) + { + mhs_free_sequences (mhs); + rc = -1; + goto out; + } for (; first <= last; first++) mhs_set (mhs, first, f); } } + rc = 0; + +out: FREE (&buff); safe_fclose (&fp); + return 0; } static inline mode_t mh_umask (CONTEXT* ctx) @@ -221,11 +233,11 @@ int mh_buffy (const char *path) struct mh_sequences mhs; memset (&mhs, 0, sizeof (mhs)); - mh_read_sequences (&mhs, path); + if (mh_read_sequences (&mhs, path) < 0) + return 0; for (i = 0; !r && i <= mhs.max; i++) if (mhs_check (&mhs, i) & MH_SEQ_UNSEEN) r = 1; - mhs_free_sequences (&mhs); return r; } @@ -312,7 +324,7 @@ static void mhs_write_one_sequence (FILE * fp, struct mh_sequences *mhs, /* XXX - we don't currently remove deleted messages from sequences we don't know. Should we? */ -void mh_update_sequences (CONTEXT * ctx) +static void mh_update_sequences (CONTEXT * ctx) { FILE *ofp, *nfp; @@ -352,7 +364,7 @@ void mh_update_sequences (CONTEXT * ctx) /* first, copy unknown sequences */ if ((ofp = fopen (sequences, "r"))) { - while ((buff = mutt_read_line (buff, &s, ofp, &l))) + while ((buff = mutt_read_line (buff, &s, ofp, &l, 0))) { if (!mutt_strncmp (buff, seq_unseen, mutt_strlen (seq_unseen))) continue; @@ -377,7 +389,8 @@ void mh_update_sequences (CONTEXT * ctx) else p = ctx->hdrs[l]->path; - i = atoi (p); + if (mutt_atoi (p, &i) < 0) + continue; if (!ctx->hdrs[l]->read) { @@ -450,7 +463,7 @@ static void mh_sequences_add_one (CONTEXT * ctx, int n, short unseen, snprintf (sequences, sizeof (sequences), "%s/.mh_sequences", ctx->path); if ((ofp = fopen (sequences, "r"))) { - while ((buff = mutt_read_line (buff, &sz, ofp, &line))) + while ((buff = mutt_read_line (buff, &sz, ofp, &line, 0))) { if (unseen && !strncmp (buff, seq_unseen, mutt_strlen (seq_unseen))) { @@ -505,7 +518,8 @@ static void mh_update_maildir (struct maildir *md, struct mh_sequences *mhs) else p = md->h->path; - i = atoi (p); + if (mutt_atoi (p, &i) < 0) + continue; f = mhs_check (mhs, i); md->h->read = (f & MH_SEQ_UNSEEN) ? 0 : 1; @@ -639,7 +653,7 @@ static HEADER *maildir_parse_message (int magic, const char *fname, h->env = mutt_read_rfc822_header (f, h, 0, 0); fstat (fileno (f), &st); - fclose (f); + safe_fclose (&f); if (!h->received) h->received = h->date_sent; @@ -978,7 +992,7 @@ static struct maildir *skip_duplicates (struct maildir *p, struct maildir **last /* * This function does the second parsing pass */ -void maildir_delayed_parsing (CONTEXT * ctx, struct maildir **md, +static void maildir_delayed_parsing (CONTEXT * ctx, struct maildir **md, progress_t *progress) { struct maildir *p, *last = NULL; @@ -1029,13 +1043,14 @@ void maildir_delayed_parsing (CONTEXT * ctx, struct maildir **md, if (!ctx->quiet && progress) mutt_progress_update (progress, count, -1); + DO_SORT(); + snprintf (fn, sizeof (fn), "%s/%s", ctx->path, p->h->path); #if USE_HCACHE if (option(OPTHCACHEVERIFY)) { - DO_SORT(); - ret = stat(fn, &lastchanged); + ret = stat(fn, &lastchanged); } else { @@ -1059,7 +1074,6 @@ void maildir_delayed_parsing (CONTEXT * ctx, struct maildir **md, { #endif /* USE_HCACHE */ - DO_SORT(); if (maildir_parse_message (ctx->magic, fn, p->h->old, p->h)) { p->header_parsed = 1; @@ -1141,7 +1155,8 @@ int mh_read_dir (CONTEXT * ctx, const char *subdir) if (ctx->magic == M_MH) { - mh_read_sequences (&mhs, ctx->path); + if (mh_read_sequences (&mhs, ctx->path) >= 0) + return -1; mh_update_maildir (md, &mhs); mhs_free_sequences (&mhs); } @@ -1150,7 +1165,7 @@ int mh_read_dir (CONTEXT * ctx, const char *subdir) if (!data->mh_umask) data->mh_umask = mh_umask (ctx); - + return 0; } @@ -1175,7 +1190,7 @@ int mh_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr) return mh_mkstemp (dest, &msg->fp, &msg->path); } -int ch_compar (const void *a, const void *b) +static int ch_compar (const void *a, const void *b) { return (int)( *((const char *) a) - *((const char *) b)); } @@ -1244,8 +1259,8 @@ int maildir_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr) omask = umask (mh_umask (dest)); FOREVER { - snprintf (path, _POSIX_PATH_MAX, "%s/tmp/%s.%ld.%u_%d.%s%s", - dest->path, subdir, time (NULL), (unsigned int)getpid (), + snprintf (path, _POSIX_PATH_MAX, "%s/tmp/%s.%lld.%u_%d.%s%s", + dest->path, subdir, (long long)time (NULL), (unsigned int)getpid (), Counter++, NONULL (Hostname), suffix); dprint (2, (debugfile, "maildir_open_new_message (): Trying %s.\n", @@ -1311,8 +1326,11 @@ int maildir_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr) char full[_POSIX_PATH_MAX]; char *s; - if (safe_fclose (&msg->fp) != 0) + if (safe_fsync_close (&msg->fp)) + { + mutt_perror (_("Could not flush message to disk")); return -1; + } /* extract the subdir */ s = strrchr (msg->path, '/') + 1; @@ -1327,8 +1345,8 @@ int maildir_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr) /* construct a new file name. */ FOREVER { - snprintf (path, _POSIX_PATH_MAX, "%s/%ld.%u_%d.%s%s", subdir, - time (NULL), (unsigned int)getpid (), Counter++, + snprintf (path, _POSIX_PATH_MAX, "%s/%lld.%u_%d.%s%s", subdir, + (long long)time (NULL), (unsigned int)getpid (), Counter++, NONULL (Hostname), suffix); snprintf (full, _POSIX_PATH_MAX, "%s/%s", ctx->path, path); @@ -1386,8 +1404,11 @@ static int _mh_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr, char path[_POSIX_PATH_MAX]; char tmp[16]; - if (safe_fclose (&msg->fp) != 0) + if (safe_fsync_close (&msg->fp)) + { + mutt_perror (_("Could not flush message to disk")); return -1; + } if ((dirp = opendir (ctx->path)) == NULL) { @@ -1686,6 +1707,18 @@ int mh_sync_mailbox (CONTEXT * ctx, int *index_hint) goto err; } } + +#if USE_HCACHE + if (ctx->hdrs[i]->changed) + { + if (ctx->magic == M_MAILDIR) + mutt_hcache_store (hc, ctx->hdrs[i]->path + 3, ctx->hdrs[i], + 0, &maildir_hcache_keylen); + else if (ctx->magic == M_MH) + mutt_hcache_store (hc, ctx->hdrs[i]->path, ctx->hdrs[i], 0, strlen); + } +#endif + } #if USE_HCACHE @@ -1866,7 +1899,7 @@ int maildir_check_mailbox (CONTEXT * ctx, int *index_hint) * of each message we scanned. This is used in the loop over the * existing messages below to do some correlation. */ - fnames = hash_create (1031); + fnames = hash_create (1031, 0); for (p = md; p; p = p->next) { @@ -1976,7 +2009,7 @@ int mh_check_mailbox (CONTEXT * ctx, int *index_hint) /* create .mh_sequences when there isn't one. */ snprintf (buf, sizeof (buf), "%s/.mh_sequences", ctx->path); - if ((i = stat (buf, &st_cur) == -1) && errno == ENOENT) + if ((i = stat (buf, &st_cur)) == -1 && errno == ENOENT) { char *tmp; FILE *fp = NULL; @@ -2010,12 +2043,13 @@ int mh_check_mailbox (CONTEXT * ctx, int *index_hint) maildir_parse_dir (ctx, &last, NULL, NULL, NULL); maildir_delayed_parsing (ctx, &md, NULL); - mh_read_sequences (&mhs, ctx->path); + if (mh_read_sequences (&mhs, ctx->path) < 0) + return -1; mh_update_maildir (md, &mhs); mhs_free_sequences (&mhs); /* check for modifications and adjust flags */ - fnames = hash_create (1031); + fnames = hash_create (1031, 0); for (p = md; p; p = p->next) hash_insert (fnames, p->h->path, p, 0); @@ -2061,7 +2095,7 @@ int mh_check_mailbox (CONTEXT * ctx, int *index_hint) * then again, it's called rarely. */ -FILE *_maildir_open_find_message (const char *folder, const char *unique, +static FILE *_maildir_open_find_message (const char *folder, const char *unique, const char *subfolder) { char dir[_POSIX_PATH_MAX]; @@ -2209,3 +2243,50 @@ int mh_check_empty (const char *path) return r; } + +int mx_is_maildir (const char *path) +{ + char tmp[_POSIX_PATH_MAX]; + struct stat st; + + snprintf (tmp, sizeof (tmp), "%s/cur", path); + if (stat (tmp, &st) == 0 && S_ISDIR (st.st_mode)) + return 1; + return 0; +} + +int mx_is_mh (const char *path) +{ + char tmp[_POSIX_PATH_MAX]; + + snprintf (tmp, sizeof (tmp), "%s/.mh_sequences", path); + if (access (tmp, F_OK) == 0) + return 1; + + snprintf (tmp, sizeof (tmp), "%s/.xmhcache", path); + if (access (tmp, F_OK) == 0) + return 1; + + snprintf (tmp, sizeof (tmp), "%s/.mew_cache", path); + if (access (tmp, F_OK) == 0) + return 1; + + snprintf (tmp, sizeof (tmp), "%s/.mew-cache", path); + if (access (tmp, F_OK) == 0) + return 1; + + snprintf (tmp, sizeof (tmp), "%s/.sylpheed_cache", path); + if (access (tmp, F_OK) == 0) + return 1; + + /* + * ok, this isn't an mh folder, but mh mode can be used to read + * Usenet news from the spool. ;-) + */ + + snprintf (tmp, sizeof (tmp), "%s/.overview", path); + if (access (tmp, F_OK) == 0) + return 1; + + return 0; +}