X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=lib-mx%2Fhcache.c;h=413d6c8664356950a592f8c7615d6c3e90009d02;hp=4f4504c94772a7ed4f18e757f2da77291b4475f4;hb=5d0104e059e3bd33be6acc3c00b3f3944a3897f6;hpb=fd97b7b962d97d99e98cd566a34fcdaaeb950bfd diff --git a/lib-mx/hcache.c b/lib-mx/hcache.c index 4f4504c..413d6c8 100644 --- a/lib-mx/hcache.c +++ b/lib-mx/hcache.c @@ -13,41 +13,28 @@ #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 "md5.h" #include "charset.h" #include "mutt.h" #include "hcache.h" -struct header_cache { +struct hcache_t { #if defined(HAVE_QDBM) - VILLA *db; - char *folder; - unsigned int crc; + VILLA *db; #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]; + GDBM_FILE db; #endif + char *folder; + unsigned int crc; }; typedef union { @@ -336,97 +323,62 @@ static void restore_envelope (ENVELOPE * e, const unsigned char *d, int *off) restore_list (&e->userhdrs, d, off); } -static -unsigned int crc32 (unsigned int crc, unsigned char const *p, ssize_t len) +static unsigned int crc32(unsigned int crc, const void *src, ssize_t len) { - int i; + int i; + const unsigned char *p = src; - while (len--) { - crc ^= *p++; - for (i = 0; i < 8; i++) - crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); - } - return crc; + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); + } + return crc; } -static int generate_crc32 () +static int generate_crc32(void) { - 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")); + static int crc = 0; + crc = crc32(crc, "madmutt.2007.05.13", m_strlen("madmutt.2007.05.13")); #ifdef HAVE_LANGINFO_CODESET - crc = crc32(crc, (unsigned char const *) MCharset.charset, m_strlen(MCharset.charset)); - crc = crc32(crc, (unsigned char const *) "HAVE_LANGINFO_CODESET", - m_strlen("HAVE_LANGINFO_CODESET")); + crc = crc32(crc, MCharset.charset, m_strlen(MCharset.charset)); + crc = crc32(crc, "HAVE_LANGINFO_CODESET", + m_strlen("HAVE_LANGINFO_CODESET")); #endif - - crc = crc32(crc, (unsigned char const *) "USE_POP", m_strlen("USE_POP")); - - crc = crc32(crc, (unsigned char const *) "MIXMASTER", - m_strlen("MIXMASTER")); - - crc = crc32(crc, (unsigned char const *) "USE_IMAP", m_strlen("USE_IMAP")); - + crc = crc32(crc, "USE_POP", m_strlen("USE_POP")); + crc = crc32(crc, "MIXMASTER", m_strlen("MIXMASTER")); + crc = crc32(crc, "USE_IMAP", m_strlen("USE_IMAP")); #ifdef USE_NNTP - crc = crc32(crc, (unsigned char const *) "USE_NNTP", m_strlen("USE_NNTP")); + crc = crc32(crc, "USE_NNTP", m_strlen("USE_NNTP")); #endif - return crc; + return crc; } -static int crc32_matches (const char *d, unsigned int crc) +static const char * +mutt_hcache_per_folder(const char *path, const char *folder) { - int off = sizeof (validate); - unsigned int mycrc = 0; - - if (!d) { - return 0; - } - - restore_int (&mycrc, (unsigned char *) d, &off); + static char buf[_POSIX_PATH_MAX]; + struct stat st; + int pos; - 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 (stat(path, &st) < 0 || !S_ISDIR(st.st_mode)) { + return path; + } - if (ret <= 0) { - return path; - } + pos = m_strcpy(buf, sizeof(buf), path); + pos += m_strputc(buf + pos, sizeof(buf) - pos, '/'); - return mutt_hcache_per_folder_path; + while (*folder) { + if (isalnum((unsigned char)*folder) || *folder == '.') { + pos += m_strputc(buf + pos, sizeof(buf) - pos, *folder); + } else { + pos += m_strputc(buf + pos, sizeof(buf) - pos, '_'); + } + folder++; + } + pos += m_strcpy(buf + pos, sizeof(buf) - pos, ".hdb"); + return buf; } /* This function transforms a header into a char so that it is useable by @@ -434,7 +386,7 @@ static const char *mutt_hcache_per_folder (const char *path, static void *mutt_hcache_dump (void *_db, HEADER * h, int *off, unsigned long uid_validity) { - struct header_cache *db = _db; + struct hcache_t *db = _db; unsigned char *d = NULL; *off = 0; @@ -497,431 +449,141 @@ HEADER *mutt_hcache_restore (const unsigned char *d, HEADER ** 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)) +hcache_t *mutt_hcache_open(const char *path, const char *folder) { - 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); + hcache_t *h = p_new(hcache_t, 1); - ksize = strlen(h->folder) + keylen(path + strlen(h->folder)); + h->folder = m_strdup(folder); + h->crc = generate_crc32(); - 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); + if (m_strisempty(path)) { + p_delete(&h->folder); + p_delete(&h); + return NULL; + } - ksize = strlen(h->folder) + keylen(path + strlen(h->folder)); + path = mutt_hcache_per_folder(path, folder); - return vlout(h->db, path, ksize); -} + { +#if defined(HAVE_QDBM) + int flags = VL_OWRITER | VL_OCREAT; + if (option(OPTHCACHECOMPRESS)) + flags |= VL_OZCOMP; + h->db = vlopen(path, flags, VL_CMPLEX); #elif defined(HAVE_GDBM) + int pagesize = atoi(HeaderCachePageSize) ?: 16384; -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; - } + h->db = gdbm_open((char *) path, pagesize, GDBM_WRCREAT, 00600, NULL); +#endif + } - /* if rw failed try ro */ - h->db = gdbm_open ((char *) path, pagesize, GDBM_READER, 00600, NULL); - if (h->db) { + if (!h->db) { + p_delete(&h->folder); + p_delete(&h); + } 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)) +void mutt_hcache_close(hcache_t **db) { - 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 (!*db) + return; - 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; -} +#if defined(HAVE_QDBM) + vlclose((*db)->db); +#elif defined(HAVE_GDBM) + gdbm_close((*db)->db); +#endif -static void mutt_hcache_dbt_empty_init (DBT * dbt) -{ - dbt->data = NULL; - dbt->size = dbt->ulen = dbt->dlen = dbt->doff = 0; - dbt->flags = 0; + p_delete(&(*db)->folder); + p_delete(db); } -void *mutt_hcache_open (const char *path, const char *folder) +void *mutt_hcache_fetch(hcache_t *db, const char *filename, + ssize_t (*keylen)(const char *fn)) { - 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 (); + char path[_POSIX_PATH_MAX]; + void *data = NULL; - 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 (!db) + return NULL; - if (mx_lock_file (h->lockfile, h->fd, 1, 0, 5)) { - close (h->fd); - p_delete(&h); - return NULL; - } + snprintf(path, sizeof(path), "%s%s", db->folder, filename); - 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; - } + { +#if defined(HAVE_QDBM) + int ksize = strlen(db->folder) + keylen(path + strlen(db->folder)); + data = vlget(db->db, path, ksize, NULL); +#elif defined(HAVE_GDBM) + datum k = { .dptr = path, .dsize = keylen(path) }; - 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; + data = gdbm_fetch(db->db, k).dtpr; +#endif } - } - 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 (data) { + int off = sizeof(validate); + unsigned crc = 0; - 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; - } + restore_int(&crc, data, &off); + if (crc != db->crc) + p_delete(&data); + } - return data.data; + return data; } -int -mutt_hcache_store (void *db, const char *filename, HEADER * header, - unsigned long uid_validity, ssize_t (*keylen) (const char *fn)) +int mutt_hcache_store(hcache_t *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; + char path[_POSIX_PATH_MAX]; + int ret, dsize; + void *data = NULL; - if (!h) { - return -1; - } + if (!db) + return -1; - filename++; /* skip '/' */ + snprintf(path, sizeof(path), "%s%s", db->folder, filename); + data = mutt_hcache_dump(db, header, &dsize, uid_validity); - 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; + { +#if defined(HAVE_QDBM) + int ksize = strlen(db->folder) + keylen(path + strlen(db->folder)); - ret = h->db->put (h->db, NULL, &key, &data, 0); + ret = vlput(db->db, path, ksize, data, dsize, VL_DOVER); +#elif defined(HAVE_GDBM) + datum k = { .dptr = path, .dsize = keylen(path) }; + datum v = { .dptr = data, .dsize = dsize }; - p_delete(&data.data); + ret = gdbm_store (db->db, k, v, GDBM_REPLACE); +#endif + } - return ret; + p_delete(&data); + return ret; } -int -mutt_hcache_delete (void *db, const char *filename, - ssize_t (*keylen) (const char *fn)) +int mutt_hcache_delete(hcache_t *db, const char *filename, + ssize_t (*keylen)(const char *fn)) { - DBT key; - struct header_cache *h = db; + char path[_POSIX_PATH_MAX]; - if (!h) { - return -1; - } + if (!db) + return -1; - filename++; /* skip '/' */ + snprintf(path, sizeof(path), "%s%s", db->folder, filename); - mutt_hcache_dbt_init (&key, (void *) filename, keylen (filename)); - return h->db->del (h->db, NULL, &key, 0); -} + { +#if defined(HAVE_QDBM) + int ksize = strlen(db->folder) + keylen(path + strlen(db->folder)); + return vlout(db->db, path, ksize); +#elif defined(HAVE_GDBM) + datum k = { .dptr = path, .dsize = keylen(path) }; + return gdbm_delete(db->db, k); #endif + } +} #endif /* USE_HCACHE */