Here's a patch that attempts to version the header cache more accurately. It uses a little script to extract the type definitions for the structures hcache saves, pipes them through an MD5, and uses an unsigned long's worth of the result as a CRC. Comments?
# HG changeset patch
# User Brendan Cully <brendan@xxxxxxxxxx>
# Date 1175725201 25200
# Node ID df41e0e8f394b2976aed779096b50c9267df5df1
# Parent 5e0ea671962d44e201843c8fd016f1bbf5d4069d
Version header cache against MD5 of structures on which it depends
diff --git a/Makefile.am b/Makefile.am
--- a/Makefile.am
+++ b/Makefile.am
@@ -13,7 +13,7 @@ SUBDIRS = m4 po intl doc contrib $(IMAP_
bin_SCRIPTS = muttbug flea @SMIMEAUX_TARGET@
-BUILT_SOURCES = keymap_defs.h patchlist.c reldate.h
+BUILT_SOURCES = keymap_defs.h patchlist.c reldate.h hcversion.h
bin_PROGRAMS = mutt @DOTLOCK_TARGET@ @PGPAUX_TARGET@
mutt_SOURCES = $(BUILT_SOURCES) \
@@ -78,7 +78,7 @@ EXTRA_DIST = COPYRIGHT GPL OPS OPS.PGP O
makedoc.c makedoc-defs.h stamp-doc-rc README.SSL smime.h \
muttbug pgppacket.h depcomp ascii.h BEWARE PATCHES patchlist.sh \
ChangeLog ChangeLog.old mkchangelog.sh cvslog2changelog.pl mutt_idna.h \
- snprintf.c regex.c crypt-gpgme.h
+ snprintf.c regex.c crypt-gpgme.h hcachever.py
EXTRA_SCRIPTS = smime_keys
@@ -125,6 +125,10 @@ reldate.h: $(srcdir)/ChangeLog
echo 'const char *ReleaseDate = "'`head -n 1 $(srcdir)/ChangeLog |
LC_ALL=C cut -d ' ' -f 1`'";' > reldate.h.tmp; \
cmp -s reldate.h.tmp reldate.h || cp reldate.h.tmp reldate.h; \
rm reldate.h.tmp
+
+# TODO: scan hcache.c for types
+hcversion.h: $(srcdir)/mutt.h $(srcdir)/rfc822.h
+ $(CPP) $(AM_CPPFLAGS) $(CPPFLAGS) -include config.h $^ | python
$(srcdir)/hcachever.py ADDRESS LIST BUFFER PARAMETER BODY ENVELOPE > hcversion.h
patchlist.c: $(srcdir)/PATCHES $(srcdir)/patchlist.sh
$(srcdir)/patchlist.sh < $(srcdir)/PATCHES > patchlist.c
diff --git a/hcache.c b/hcache.c
--- a/hcache.c
+++ b/hcache.c
@@ -18,8 +18,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
-/* this comment bumps Id after $assumed_charset changed BODY. */
-
#if HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
@@ -41,6 +39,7 @@
#endif
#include "mutt.h"
#include "hcache.h"
+#include "hcversion.h"
#ifdef USE_IMAP
#include "message.h"
#endif
@@ -447,75 +446,8 @@ restore_envelope(ENVELOPE * e, const uns
restore_list(&e->userhdrs, d, off);
}
-static unsigned int
-crc32(unsigned int crc, unsigned char const *p, size_t len)
-{
- int i;
- while (len--)
- {
- crc ^= *p++;
- for (i = 0; i < 8; i++)
- crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
- }
- return crc;
-}
-
static int
-generate_crc32()
-{
- int crc = 0;
- SPAM_LIST *sp = SpamList;
- RX_LIST *rx = NoSpamList;
-
- crc = crc32(crc, (unsigned char const *) "$Id$", mutt_strlen("$Id$"));
-
-#if HAVE_LANGINFO_CODESET
- crc = crc32(crc, (unsigned char const *) Charset, mutt_strlen(Charset));
- crc = crc32(crc, (unsigned char const *) "HAVE_LANGINFO_CODESET",
- mutt_strlen("HAVE_LANGINFO_CODESET"));
-#endif
-
-#if EXACT_ADDRESS
- crc = crc32(crc, (unsigned char const *) "EXACT_ADDRESS",
- mutt_strlen("EXACT_ADDRESS"));
-#endif
-
-#ifdef USE_POP
- crc = crc32(crc, (unsigned char const *) "USE_POP", mutt_strlen("USE_POP"));
-#endif
-
-#ifdef MIXMASTER
- crc = crc32(crc, (unsigned char const *) "MIXMASTER",
- mutt_strlen("MIXMASTER"));
-#endif
-
-#ifdef USE_IMAP
- crc = crc32(crc, (unsigned char const *) "USE_IMAP",
mutt_strlen("USE_IMAP"));
- crc = crc32(crc, (unsigned char const *) ImapHeaders,
- mutt_strlen(ImapHeaders));
-#endif
- while (sp)
- {
- crc = crc32(crc, (unsigned char const *) sp->rx->pattern,
- mutt_strlen(sp->rx->pattern));
- sp = sp->next;
- }
-
- crc = crc32(crc, (unsigned char const *) "SPAM_SEPERATOR",
- mutt_strlen("SPAM_SEPERATOR"));
-
- while (rx)
- {
- crc = crc32(crc, (unsigned char const *) rx->rx->pattern,
- mutt_strlen(rx->rx->pattern));
- rx = rx->next;
- }
-
- return crc;
-}
-
-static int
-crc32_matches(const char *d, unsigned int crc)
+crc_matches(const char *d, unsigned int crc)
{
int off = sizeof (validate);
unsigned int mycrc = 0;
@@ -639,7 +571,7 @@ mutt_hcache_fetch(header_cache_t *h, con
data = mutt_hcache_fetch_raw (h, filename, keylen);
- if (!data || !crc32_matches(data, h->crc))
+ if (!data || !crc_matches(data, h->crc))
{
FREE(&data);
return NULL;
@@ -795,7 +727,7 @@ mutt_hcache_open(const char *path, const
h->db = NULL;
h->folder = get_foldername(folder);
- h->crc = generate_crc32();
+ h->crc = HCACHEVER;
if (!path || path[0] == '\0')
{
@@ -860,7 +792,7 @@ mutt_hcache_open(const char *path, const
h->db = NULL;
h->folder = get_foldername(folder);
- h->crc = generate_crc32();
+ h->crc = HCACHEVER;
if (!path || path[0] == '\0')
{
@@ -946,7 +878,7 @@ mutt_hcache_open(const char *path, const
int pagesize = atoi(HeaderCachePageSize);
char* tmp;
- h->crc = generate_crc32();
+ h->crc = HCACHEVER;
if (!path || path[0] == '\0')
{
diff --git a/hcachever.py b/hcachever.py
new file mode 100755
--- /dev/null
+++ b/hcachever.py
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+
+import sys
+import md5
+import struct
+
+baseversion = 1
+
+def dehash(text):
+ sections = [l for l in text.split('\n')
+ if not l.startswith('#')]
+ return '\n'.join(sections)
+
+def despace(text):
+ return ' '.join(text.split())
+
+def extracttypedef(text, name):
+ end = text.find('%s;' % name)
+ end = text.rfind('}', 0, end) - 1
+ if end < 0:
+ return ''
+ start = text.rfind('\ntypedef ', 0, end)
+ start = text.find('{', start) + 1
+ if start <= 0:
+ return ''
+ return despace(text[start:end])
+
+inc = sys.stdin
+f = inc.read()
+
+text = dehash(f)
+baseversion = str(baseversion)
+m = md5.new(baseversion)
+print "/* base version: %s" % baseversion
+for t in sys.argv[1:]:
+ td = extracttypedef(text, t)
+ print " * %s: %s" % (t, td)
+ m.update(td)
+print " */"
+ll = struct.calcsize('L')
+ver = struct.unpack('L', m.digest()[:ll])[0]
+print '#define HCACHEVER %d' % ver
Attachment:
pgpnI70x9tFR4.pgp
Description: PGP signature