📄 hcache.c
字号:
}static intcrc32_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, 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(header_cache_t *h, HEADER * header, int *off, unsigned long uid_validity){ 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(h->crc, d, off); lazy_realloc(&d, *off + sizeof (HEADER)); memcpy(d + *off, header, sizeof (HEADER)); *off += sizeof (HEADER); d = dump_envelope(header->env, d, off); d = dump_body(header->content, d, off); d = dump_char(header->maildir_flags, d, off); return d;}HEADER *mutt_hcache_restore(const unsigned char *d, HEADER ** oh){ int off = 0; HEADER *h = mutt_new_header(); /* skip validate */ off += sizeof (validate); /* skip crc */ off += sizeof (unsigned int); memcpy(h, d + off, sizeof (HEADER)); off += sizeof (HEADER); h->env = mutt_new_envelope(); restore_envelope(h->env, d, &off); h->content = mutt_new_body(); 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 = safe_strdup((*oh)->path); mutt_free_header(oh); } return h;}void *mutt_hcache_fetch(header_cache_t *h, const char *filename, size_t(*keylen) (const char *fn)){ void* data; data = mutt_hcache_fetch_raw (h, filename, keylen); if (!data || !crc32_matches(data, h->crc)) { FREE(&data); return NULL; } return data;}void *mutt_hcache_fetch_raw (header_cache_t *h, const char *filename, size_t(*keylen) (const char *fn)){#ifndef HAVE_DB4 char path[_POSIX_PATH_MAX]; int ksize;#endif#ifdef HAVE_QDBM char *data = NULL;#elif HAVE_GDBM datum key; datum data;#elif HAVE_DB4 DBT key; DBT data;#endif if (!h) return NULL; #ifdef HAVE_DB4 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); return data.data;#else strncpy(path, h->folder, sizeof (path)); safe_strcat(path, sizeof (path), filename); ksize = strlen (h->folder) + keylen (path + strlen (h->folder)); #endif#ifdef HAVE_QDBM data = vlget(h->db, path, ksize, NULL); return data;#elif HAVE_GDBM key.dptr = path; key.dsize = ksize; data = gdbm_fetch(h->db, key); return data.dptr;#endif}intmutt_hcache_store(header_cache_t *h, const char *filename, HEADER * header, unsigned long uid_validity, size_t(*keylen) (const char *fn)){ char* data; int dlen; int ret; if (!h) return -1; data = mutt_hcache_dump(h, header, &dlen, uid_validity); ret = mutt_hcache_store_raw (h, filename, data, dlen, keylen); FREE(&data); return ret;}intmutt_hcache_store_raw (header_cache_t* h, const char* filename, void* data, size_t dlen, size_t(*keylen) (const char* fn)){#ifndef HAVE_DB4 char path[_POSIX_PATH_MAX]; int ksize;#endif#if HAVE_GDBM datum key; datum databuf;#elif HAVE_DB4 DBT key; DBT databuf;#endif if (!h) return -1;#if HAVE_DB4 filename++; /* skip '/' */ mutt_hcache_dbt_init(&key, (void *) filename, keylen(filename)); mutt_hcache_dbt_empty_init(&databuf); databuf.flags = DB_DBT_USERMEM; databuf.data = data; databuf.size = dlen; databuf.ulen = dlen; return h->db->put(h->db, NULL, &key, &databuf, 0);#else strncpy(path, h->folder, sizeof (path)); safe_strcat(path, sizeof (path), filename); ksize = strlen(h->folder) + keylen(path + strlen(h->folder));#endif#if HAVE_QDBM return vlput(h->db, path, ksize, data, dlen, VL_DOVER);#elif HAVE_GDBM key.dptr = path; key.dsize = ksize; databuf.dsize = dlen; databuf.dptr = data; return gdbm_store(h->db, key, databuf, GDBM_REPLACE);#endif}#if HAVE_QDBMheader_cache_t *mutt_hcache_open(const char *path, const char *folder){ struct header_cache *h = safe_calloc(1, sizeof (HEADER_CACHE)); int flags = VL_OWRITER | VL_OCREAT; h->db = NULL; h->folder = safe_strdup(folder); h->crc = generate_crc32(); if (!path || path[0] == '\0') { FREE(&h->folder); FREE(&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 { FREE(&h->folder); FREE(&h); return NULL; }}voidmutt_hcache_close(header_cache_t *h){ if (!h) return; vlclose(h->db); FREE(&h->folder); FREE(&h);}intmutt_hcache_delete(header_cache_t *h, const char *filename, size_t(*keylen) (const char *fn)){ char path[_POSIX_PATH_MAX]; int ksize; if (!h) return -1; strncpy(path, h->folder, sizeof (path)); safe_strcat(path, sizeof (path), filename); ksize = strlen(h->folder) + keylen(path + strlen(h->folder)); return vlout(h->db, path, ksize);}#elif HAVE_GDBMheader_cache_t *mutt_hcache_open(const char *path, const char *folder){ struct header_cache *h = safe_calloc(1, sizeof (HEADER_CACHE)); int pagesize = atoi(HeaderCachePageSize) ? atoi(HeaderCachePageSize) : 16384; h->db = NULL; h->folder = safe_strdup(folder); h->crc = generate_crc32(); if (!path || path[0] == '\0') { FREE(&h->folder); FREE(&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 { FREE(&h->folder); FREE(&h); return NULL; }}voidmutt_hcache_close(header_cache_t *h){ if (!h) return; gdbm_close(h->db); FREE(&h->folder); FREE(&h);}intmutt_hcache_delete(header_cache_t *h, const char *filename, size_t(*keylen) (const char *fn)){ datum key; char path[_POSIX_PATH_MAX]; if (!h) return -1; strncpy(path, h->folder, sizeof (path)); safe_strcat(path, sizeof (path), filename); key.dptr = path; key.dsize = strlen(h->folder) + keylen(path + strlen(h->folder)); return gdbm_delete(h->db, key);}#elif HAVE_DB4static voidmutt_hcache_dbt_init(DBT * dbt, void *data, size_t len){ dbt->data = data; dbt->size = dbt->ulen = len; dbt->dlen = dbt->doff = 0; dbt->flags = DB_DBT_USERMEM;}static voidmutt_hcache_dbt_empty_init(DBT * dbt){ dbt->data = NULL; dbt->size = dbt->ulen = dbt->dlen = dbt->doff = 0; dbt->flags = 0;}header_cache_t *mutt_hcache_open(const char *path, const char *folder){ struct stat sb; u_int32_t createflags = DB_CREATE; int ret; struct header_cache *h = calloc(1, sizeof (HEADER_CACHE)); int pagesize = atoi(HeaderCachePageSize); h->crc = generate_crc32(); if (!path || path[0] == '\0') { FREE(&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) { FREE(&h); return NULL; } if (mx_lock_file(h->lockfile, h->fd, 1, 0, 5)) { close(h->fd); FREE(&h); return NULL; } ret = db_env_create(&h->env, 0); if (ret) { mx_unlock_file(h->lockfile, h->fd, 0); close(h->fd); FREE(&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); FREE(&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); FREE(&h); return NULL; } return h;}voidmutt_hcache_close(header_cache_t *h){ 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); FREE(&h);}intmutt_hcache_delete(header_cache_t *h, const char *filename, size_t(*keylen) (const char *fn)){ DBT key; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -