/*
- * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org>
- * Copyright (C) 1999-2002 Thomas Roessler <roessler@does-not-exist.org>
+ * Copyright (C) 1996-2002,2007,2009 Michael R. Elkins <me@mutt.org>
+ * Copyright (C) 1999-2005 Thomas Roessler <roessler@does-not-exist.org>
*
* 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
#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
#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;
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;
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)
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;
}
/* 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;
/* 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;
else
p = ctx->hdrs[l]->path;
- i = atoi (p);
+ if (mutt_atoi (p, &i) < 0)
+ continue;
if (!ctx->hdrs[l]->read)
{
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)))
{
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;
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;
/*
* 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;
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
{
{
#endif /* USE_HCACHE */
- DO_SORT();
if (maildir_parse_message (ctx->magic, fn, p->h->old, p->h))
{
p->header_parsed = 1;
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);
}
if (!data->mh_umask)
data->mh_umask = mh_umask (ctx);
-
+
return 0;
}
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));
}
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",
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;
/* 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);
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)
{
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
* 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)
{
/* 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;
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);
* 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];
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;
+}