X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=hcache.c;fp=hcache.c;h=0000000000000000000000000000000000000000;hp=953e70f1e226aa175cce07bd04f5d8fc99cfa40d;hb=8476307969a605bea67f6b702b0c1e7a52038bed;hpb=74697a5c38af6a85ce3b0062d781c35814a9f536 diff --git a/hcache.c b/hcache.c deleted file mode 100644 index 953e70f..0000000 --- a/hcache.c +++ /dev/null @@ -1,931 +0,0 @@ -/* - * Copyright notice from original mutt: - * Copyright (C) 2004 Thomas Glanzmann - * Copyright (C) 2004 Tobias Werth - * Copyright (C) 2004 Brian Fundakowski Feldman - * - * This file is part of mutt-ng, see http://www.muttng.org/. - * It's licensed under the GNU General Public License, - * please see the file GPL in the top level source directory. - */ - -#include - -#ifdef USE_HCACHE - -#define MUTTNG_HCACHE_ID "0x004" - -#if defined(HAVE_QDBM) -#include -#include -#include -#elif defined(HAVE_GDBM) -#include -#elif defined(HAVE_DB4) -#include -#endif - -#include -#include - -#include "charset.h" -#include "mutt.h" -#include -#include "mx.h" -#include "lib.h" - -struct header_cache { -#if defined(HAVE_QDBM) - VILLA *db; - char *folder; - unsigned int crc; -#elif defined(HAVE_GDBM) - GDBM_FILE db; - char *folder; - unsigned int crc; -#elif defined(HAVE_DB4) - DB_ENV *env; - DB *db; - unsigned int crc; - int fd; - char lockfile[_POSIX_PATH_MAX]; -#endif -}; - -typedef union { - struct timeval timeval; - unsigned long uid_validity; -} validate; - -#define UPPER4K(i) ((i & ~(4096 - 1)) + 4096) - -static unsigned char *lazy_malloc(ssize_t siz) -{ - return p_new(unsigned char, UPPER4K(siz)); -} - -static void lazy_realloc(unsigned char **p, ssize_t siz) -{ - p_realloc(p, UPPER4K(siz)); -} - -static unsigned char *dump_int (unsigned int i, unsigned char *d, int *off) -{ - lazy_realloc (&d, *off + sizeof (int)); - memcpy (d + *off, &i, sizeof (int)); - (*off) += sizeof (int); - - return d; -} - -static void restore_int (unsigned int *i, const unsigned char *d, int *off) -{ - memcpy (i, d + *off, sizeof (int)); - (*off) += sizeof (int); -} - -static unsigned char *dump_char (char *c, unsigned char *d, int *off) -{ - unsigned int size; - - if (c == NULL) { - size = 0; - d = dump_int (size, d, off); - return d; - } - - size = m_strlen(c) + 1; - d = dump_int (size, d, off); - lazy_realloc (&d, *off + size); - memcpy (d + *off, c, size); - *off += size; - - return d; -} - -static void restore_char (char **c, const unsigned char *d, int *off) -{ - unsigned int size; - - restore_int (&size, d, off); - - if (size == 0) { - *c = NULL; - return; - } - - *c = p_dup(d + *off, size); - *off += size; -} - -static unsigned char *dump_address (address_t * a, unsigned char *d, int *off) -{ - unsigned int counter = 0; - unsigned int start_off = *off; - - d = dump_int (0xdeadbeef, d, off); - - while (a) { - d = dump_char (a->personal, d, off); - d = dump_char (a->mailbox, d, off); - d = dump_int (a->group, d, off); - a = a->next; - counter++; - } - - memcpy (d + start_off, &counter, sizeof (int)); - - return d; -} - -static void restore_address (address_t ** a, const unsigned char *d, int *off) -{ - unsigned int counter; - - restore_int (&counter, d, off); - - while (counter) { - *a = p_new(address_t, 1); - restore_char (&(*a)->personal, d, off); - restore_char (&(*a)->mailbox, d, off); - restore_int ((unsigned int *) &(*a)->group, d, off); - a = &(*a)->next; - counter--; - } - - *a = NULL; -} - -static unsigned char *dump_list (string_list_t * l, unsigned char *d, int *off) -{ - unsigned int counter = 0; - unsigned int start_off = *off; - - d = dump_int (0xdeadbeef, d, off); - - while (l) { - d = dump_char (l->data, d, off); - l = l->next; - counter++; - } - - memcpy (d + start_off, &counter, sizeof (int)); - - return d; -} - -static void restore_list (string_list_t ** l, const unsigned char *d, int *off) -{ - unsigned int counter; - - restore_int (&counter, d, off); - - while (counter) { - *l = p_new(string_list_t, 1); - restore_char (&(*l)->data, d, off); - l = &(*l)->next; - counter--; - } - - *l = NULL; -} - -static unsigned char *dump_parameter (parameter_t * p, unsigned char *d, - int *off) -{ - unsigned int counter = 0; - unsigned int start_off = *off; - - d = dump_int (0xdeadbeef, d, off); - - while (p) { - d = dump_char (p->attribute, d, off); - d = dump_char (p->value, d, off); - p = p->next; - counter++; - } - - memcpy (d + start_off, &counter, sizeof (int)); - - return d; -} - -static void -restore_parameter (parameter_t ** p, const unsigned char *d, int *off) -{ - unsigned int counter; - - restore_int (&counter, d, off); - - while (counter) { - *p = parameter_new(); - restore_char (&(*p)->attribute, d, off); - restore_char (&(*p)->value, d, off); - p = &(*p)->next; - counter--; - } -} - -static unsigned char *dump_body (BODY * c, unsigned char *d, int *off) -{ - lazy_realloc (&d, *off + sizeof (BODY)); - memcpy (d + *off, c, sizeof (BODY)); - *off += sizeof (BODY); - - d = dump_char (c->xtype, d, off); - d = dump_char (c->subtype, d, off); - - d = dump_parameter (c->parameter, d, off); - - d = dump_char (c->description, d, off); - d = dump_char (c->form_name, d, off); - d = dump_char (c->filename, d, off); - d = dump_char (c->d_filename, d, off); - - return d; -} - -static void restore_body (BODY * c, const unsigned char *d, int *off) -{ - memcpy (c, d + *off, sizeof (BODY)); - *off += sizeof (BODY); - - restore_char (&c->xtype, d, off); - restore_char (&c->subtype, d, off); - - restore_parameter (&c->parameter, d, off); - - restore_char (&c->description, d, off); - restore_char (&c->form_name, d, off); - restore_char (&c->filename, d, off); - restore_char (&c->d_filename, d, off); -} - -static unsigned char *dump_envelope (ENVELOPE * e, unsigned char *d, int *off) -{ - d = dump_address (e->return_path, d, off); - d = dump_address (e->from, d, off); - d = dump_address (e->to, d, off); - d = dump_address (e->cc, d, off); - d = dump_address (e->bcc, d, off); - d = dump_address (e->sender, d, off); - d = dump_address (e->reply_to, d, off); - d = dump_address (e->mail_followup_to, d, off); - - d = dump_char (e->subject, d, off); - if (e->real_subj) { - d = dump_int (e->real_subj - e->subject, d, off); - } - else { - d = dump_int (-1, d, off); - } - d = dump_char (e->message_id, d, off); - d = dump_char (e->supersedes, d, off); - d = dump_char (e->date, d, off); - d = dump_char (e->x_label, d, off); - d = dump_char (e->list_post, d, off); - -#ifdef USE_NNTP - d = dump_char (e->newsgroups, d, off); - d = dump_char (e->xref, d, off); - d = dump_char (e->followup_to, d, off); - d = dump_char (e->x_comment_to, d, off); -#endif - - d = dump_list (e->references, d, off); - d = dump_list (e->in_reply_to, d, off); - d = dump_list (e->userhdrs, d, off); - - return d; -} - -static void restore_envelope (ENVELOPE * e, const unsigned char *d, int *off) -{ - int real_subj_off; - - restore_address (&e->return_path, d, off); - restore_address (&e->from, d, off); - restore_address (&e->to, d, off); - restore_address (&e->cc, d, off); - restore_address (&e->bcc, d, off); - restore_address (&e->sender, d, off); - restore_address (&e->reply_to, d, off); - restore_address (&e->mail_followup_to, d, off); - - restore_char (&e->subject, d, off); - restore_int ((unsigned int *) (&real_subj_off), d, off); - if (0 <= real_subj_off) { - e->real_subj = e->subject + real_subj_off; - } - else { - e->real_subj = NULL; - } - restore_char (&e->message_id, d, off); - restore_char (&e->supersedes, d, off); - restore_char (&e->date, d, off); - restore_char (&e->x_label, d, off); - restore_char (&e->list_post, d, off); - -#ifdef USE_NNTP - restore_char (&e->newsgroups, d, off); - restore_char (&e->xref, d, off); - restore_char (&e->followup_to, d, off); - restore_char (&e->x_comment_to, d, off); -#endif - - restore_list (&e->references, d, off); - restore_list (&e->in_reply_to, d, off); - restore_list (&e->userhdrs, d, off); -} - -static -unsigned int crc32 (unsigned int crc, unsigned char const *p, ssize_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; - - crc = crc32 (crc, (unsigned char const *) - MUTTNG_HCACHE_ID "sithglan@stud.uni-erlangen.de[sithglan]|hcache.c|20041108231548|29613", - m_strlen - (MUTTNG_HCACHE_ID "sithglan@stud.uni-erlangen.de[sithglan]|hcache.c|20041108231548|29613")); - -#ifdef HAVE_LANGINFO_CODESET - crc = crc32(crc, (unsigned char const *) Charset, m_strlen(Charset)); - crc = crc32(crc, (unsigned char const *) "HAVE_LANGINFO_CODESET", - m_strlen("HAVE_LANGINFO_CODESET")); -#endif - - crc = crc32(crc, (unsigned char const *) "USE_POP", m_strlen("USE_POP")); - -#ifdef MIXMASTER - crc = crc32(crc, (unsigned char const *) "MIXMASTER", - m_strlen("MIXMASTER")); -#endif - - crc = crc32(crc, (unsigned char const *) "USE_IMAP", m_strlen("USE_IMAP")); - -#ifdef USE_NNTP - crc = crc32(crc, (unsigned char const *) "USE_NNTP", m_strlen("USE_NNTP")); -#endif - return crc; -} - -static int crc32_matches (const char *d, unsigned int crc) -{ - int off = sizeof (validate); - unsigned int mycrc = 0; - - if (!d) { - return 0; - } - - restore_int (&mycrc, (unsigned char *) d, &off); - - return (crc == mycrc); -} - -/* Append md5sumed folder to path if path is a directory. */ -static const char *mutt_hcache_per_folder (const char *path, - const char *folder) -{ - static char mutt_hcache_per_folder_path[_POSIX_PATH_MAX]; - struct stat path_stat; - MD5_CTX md5; - unsigned char md5sum[16]; - int ret; - - ret = stat (path, &path_stat); - if (ret < 0) { - return path; - } - - if (!S_ISDIR (path_stat.st_mode)) { - return path; - } - - MD5Init (&md5); - MD5Update (&md5, (unsigned char *) folder, m_strlen(folder)); - MD5Final (md5sum, &md5); - - ret = snprintf (mutt_hcache_per_folder_path, _POSIX_PATH_MAX, - "%s/%02x%02x%02x%02x%02x%02x%02x%02x" - "%02x%02x%02x%02x%02x%02x%02x%02x", - path, md5sum[0], md5sum[1], md5sum[2], md5sum[3], - md5sum[4], md5sum[5], md5sum[6], md5sum[7], md5sum[8], - md5sum[9], md5sum[10], md5sum[11], md5sum[12], - md5sum[13], md5sum[14], md5sum[15]); - - if (ret <= 0) { - return path; - } - - return mutt_hcache_per_folder_path; -} - -/* This function transforms a header into a char so that it is useable by - * db_store */ -static void *mutt_hcache_dump (void *_db, HEADER * h, int *off, - unsigned long uid_validity) -{ - struct header_cache *db = _db; - unsigned char *d = NULL; - - *off = 0; - - d = lazy_malloc (sizeof (validate)); - - if (uid_validity) { - memcpy (d, &uid_validity, sizeof (unsigned long)); - } - else { - struct timeval now; - - gettimeofday (&now, NULL); - memcpy (d, &now, sizeof (struct timeval)); - } - *off += sizeof (validate); - - d = dump_int (db->crc, d, off); - - lazy_realloc (&d, *off + sizeof (HEADER)); - memcpy (d + *off, h, sizeof (HEADER)); - *off += sizeof (HEADER); - - d = dump_envelope (h->env, d, off); - d = dump_body (h->content, d, off); - d = dump_char (h->maildir_flags, d, off); - - return d; -} - -HEADER *mutt_hcache_restore (const unsigned char *d, HEADER ** oh) -{ - int off = 0; - HEADER *h = header_new(); - - /* skip validate */ - off += sizeof (validate); - - /* skip crc */ - off += sizeof (unsigned int); - - memcpy (h, d + off, sizeof (HEADER)); - off += sizeof (HEADER); - - h->env = envelope_new(); - restore_envelope (h->env, d, &off); - - h->content = body_new(); - restore_body (h->content, d, &off); - - restore_char (&h->maildir_flags, d, &off); - - /* this is needed for maildir style mailboxes */ - if (oh) { - h->old = (*oh)->old; - h->path = m_strdup((*oh)->path); - header_delete(oh); - } - - return h; -} - -#if defined(HAVE_QDBM) -void * -mutt_hcache_open(const char *path, const char *folder) -{ - struct header_cache *h = p_new(struct header_cache, 1); - int flags = VL_OWRITER | VL_OCREAT; - h->db = NULL; - h->folder = m_strdup(folder); - h->crc = generate_crc32(); - - if (!path || path[0] == '\0') - { - p_delete(&h->folder); - p_delete(&h); - return NULL; - } - - path = mutt_hcache_per_folder(path, folder); - - if (option(OPTHCACHECOMPRESS)) - flags |= VL_OZCOMP; - - h->db = vlopen(path, flags, VL_CMPLEX); - if (h->db) - return h; - else - { - p_delete(&h->folder); - p_delete(&h); - - return NULL; - } -} - -void -mutt_hcache_close(void *db) -{ - struct header_cache *h = db; - - if (!h) - return; - - vlclose(h->db); - p_delete(&h->folder); - p_delete(&h); -} - -void * -mutt_hcache_fetch(void *db, const char *filename, - ssize_t(*keylen) (const char *fn)) -{ - struct header_cache *h = db; - char path[_POSIX_PATH_MAX]; - int ksize; - char *data = NULL; - - if (!h) - return NULL; - - m_strcpy(path, sizeof(path), h->folder); - m_strcat(path, sizeof(path), filename); - - ksize = strlen(h->folder) + keylen(path + strlen(h->folder)); - - data = vlget(h->db, path, ksize, NULL); - - if (!crc32_matches(data, h->crc)) - { - p_delete(&data); - return NULL; - } - - return data; -} - -int -mutt_hcache_store(void *db, const char *filename, HEADER * header, - unsigned long uid_validity, - ssize_t(*keylen) (const char *fn)) -{ - struct header_cache *h = db; - char path[_POSIX_PATH_MAX]; - int ret; - int ksize, dsize; - char *data = NULL; - - if (!h) - return -1; - - m_strcpy(path, sizeof(path), h->folder); - m_strcat(path, sizeof(path), filename); - - ksize = strlen(h->folder) + keylen(path + strlen(h->folder)); - - data = mutt_hcache_dump(db, header, &dsize, uid_validity); - - ret = vlput(h->db, path, ksize, data, dsize, VL_DOVER); - - p_delete(&data); - - return ret; -} - -int -mutt_hcache_delete(void *db, const char *filename, - ssize_t(*keylen) (const char *fn)) -{ - struct header_cache *h = db; - char path[_POSIX_PATH_MAX]; - int ksize; - - if (!h) - return -1; - - m_strcpy(path, sizeof(path), h->folder); - m_strcat(path, sizeof(path), filename); - - ksize = strlen(h->folder) + keylen(path + strlen(h->folder)); - - return vlout(h->db, path, ksize); -} - -#elif defined(HAVE_GDBM) - -void *mutt_hcache_open (const char *path, const char *folder) -{ - struct header_cache *h = p_new(struct header_cache, 1); - int pagesize = - atoi (HeaderCachePageSize) ? atoi (HeaderCachePageSize) : 16384; - h->db = NULL; - h->folder = m_strdup(folder); - h->crc = generate_crc32 (); - - if (!path || path[0] == '\0') { - p_delete(&h->folder); - p_delete(&h); - return NULL; - } - - path = mutt_hcache_per_folder (path, folder); - - h->db = gdbm_open ((char *) path, pagesize, GDBM_WRCREAT, 00600, NULL); - if (h->db) { - return h; - } - - /* if rw failed try ro */ - h->db = gdbm_open ((char *) path, pagesize, GDBM_READER, 00600, NULL); - if (h->db) { - return h; - } - else { - p_delete(&h->folder); - p_delete(&h); - - return NULL; - } -} - -void mutt_hcache_close (void *db) -{ - struct header_cache *h = db; - - if (!h) { - return; - } - - gdbm_close (h->db); - p_delete(&h->folder); - p_delete(&h); -} - -void *mutt_hcache_fetch (void *db, const char *filename, - ssize_t (*keylen) (const char *fn)) -{ - struct header_cache *h = db; - datum key; - datum data; - char path[_POSIX_PATH_MAX]; - - if (!h) { - return NULL; - } - - m_strcpy(path, sizeof(path), h->folder); - strncat (path, filename, sizeof (path) - m_strlen(path)); - - key.dptr = path; - key.dsize = keylen (path); - - data = gdbm_fetch (h->db, key); - - if (!crc32_matches (data.dptr, h->crc)) { - p_delete(&data.dptr); - return NULL; - } - - return data.dptr; -} - -int -mutt_hcache_store (void *db, const char *filename, HEADER * header, - unsigned long uid_validity, ssize_t (*keylen) (const char *fn)) -{ - struct header_cache *h = db; - datum key; - datum data; - char path[_POSIX_PATH_MAX]; - int ret; - - if (!h) { - return -1; - } - - m_strcpy(path, sizeof(path), h->folder); - strncat (path, filename, sizeof (path) - m_strlen(path)); - - key.dptr = path; - key.dsize = keylen (path); - - data.dptr = mutt_hcache_dump (db, header, &data.dsize, uid_validity); - - ret = gdbm_store (h->db, key, data, GDBM_REPLACE); - - p_delete(&data.dptr); - - return ret; -} - -int -mutt_hcache_delete (void *db, const char *filename, - ssize_t (*keylen) (const char *fn)) -{ - datum key; - struct header_cache *h = db; - char path[_POSIX_PATH_MAX]; - - if (!h) { - return -1; - } - - m_strcpy(path, sizeof(path), h->folder); - strncat (path, filename, sizeof (path) - m_strlen(path)); - - key.dptr = path; - key.dsize = keylen (path); - - return gdbm_delete (h->db, key); -} -#elif defined(HAVE_DB4) - -static void mutt_hcache_dbt_init (DBT * dbt, void *data, ssize_t len) -{ - dbt->data = data; - dbt->size = dbt->ulen = len; - dbt->dlen = dbt->doff = 0; - dbt->flags = DB_DBT_USERMEM; -} - -static void mutt_hcache_dbt_empty_init (DBT * dbt) -{ - dbt->data = NULL; - dbt->size = dbt->ulen = dbt->dlen = dbt->doff = 0; - dbt->flags = 0; -} - -void *mutt_hcache_open (const char *path, const char *folder) -{ - struct stat sb; - u_int32_t createflags = DB_CREATE; - int ret; - struct header_cache *h = p_new(struct header_cache, 1); - int pagesize = atoi (HeaderCachePageSize); - - - h->crc = generate_crc32 (); - - if (!path || path[0] == '\0') { - p_delete(&h); - return NULL; - } - - path = mutt_hcache_per_folder (path, folder); - - snprintf (h->lockfile, _POSIX_PATH_MAX, "%s-lock-hack", path); - - h->fd = open (h->lockfile, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); - if (h->fd < 0) { - p_delete(&h); - return NULL; - } - - if (mx_lock_file (h->lockfile, h->fd, 1, 0, 5)) { - close (h->fd); - p_delete(&h); - return NULL; - } - - ret = db_env_create (&h->env, 0); - if (ret) { - mx_unlock_file (h->lockfile, h->fd, 0); - close (h->fd); - p_delete(&h); - return NULL; - } - - ret = - (h->env->open)(h->env, NULL, DB_INIT_MPOOL | DB_CREATE | DB_PRIVATE, 0600); - if (!ret) { - ret = db_create (&h->db, h->env, 0); - if (ret) { - h->env->close (h->env, 0); - mx_unlock_file (h->lockfile, h->fd, 0); - close (h->fd); - p_delete(&h); - return NULL; - } - } - - if (stat (path, &sb) != 0 && errno == ENOENT) { - createflags |= DB_EXCL; - h->db->set_pagesize (h->db, pagesize); - } - - ret = (h->db->open)(h->db, NULL, path, folder, DB_BTREE, createflags, 0600); - if (ret) { - h->db->close (h->db, 0); - h->env->close (h->env, 0); - mx_unlock_file (h->lockfile, h->fd, 0); - close (h->fd); - p_delete(&h); - return NULL; - } - - return h; -} - -void mutt_hcache_close (void *db) -{ - struct header_cache *h = db; - - if (!h) { - return; - } - - h->db->close (h->db, 0); - h->env->close (h->env, 0); - mx_unlock_file (h->lockfile, h->fd, 0); - close (h->fd); - p_delete(&h); -} - -void *mutt_hcache_fetch (void *db, const char *filename, - ssize_t (*keylen) (const char *fn)) -{ - DBT key; - DBT data; - struct header_cache *h = db; - - if (!h) { - return NULL; - } - - filename++; /* skip '/' */ - - mutt_hcache_dbt_init (&key, (void *) filename, keylen (filename)); - mutt_hcache_dbt_empty_init (&data); - data.flags = DB_DBT_MALLOC; - - h->db->get (h->db, NULL, &key, &data, 0); - - if (!crc32_matches (data.data, h->crc)) { - p_delete(&data.data); - return NULL; - } - - return data.data; -} - -int -mutt_hcache_store (void *db, const char *filename, HEADER * header, - unsigned long uid_validity, ssize_t (*keylen) (const char *fn)) -{ - DBT key; - DBT data; - int ret; - struct header_cache *h = db; - - if (!h) { - return -1; - } - - filename++; /* skip '/' */ - - mutt_hcache_dbt_init (&key, (void *) filename, keylen (filename)); - - mutt_hcache_dbt_empty_init (&data); - data.flags = DB_DBT_USERMEM; - data.data = - mutt_hcache_dump (db, header, (signed int *) &data.size, uid_validity); - data.ulen = data.size; - - ret = h->db->put (h->db, NULL, &key, &data, 0); - - p_delete(&data.data); - - return ret; -} - -int -mutt_hcache_delete (void *db, const char *filename, - ssize_t (*keylen) (const char *fn)) -{ - DBT key; - struct header_cache *h = db; - - if (!h) { - return -1; - } - - filename++; /* skip '/' */ - - mutt_hcache_dbt_init (&key, (void *) filename, keylen (filename)); - return h->db->del (h->db, NULL, &key, 0); -} -#endif - -#endif /* USE_HCACHE */