+ 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;