NeoMutt  2022-04-29-215-gc12b98
Teaching an old dog new tricks
DOXYGEN
hcache.c File Reference

Header cache multiplexor. More...

#include "config.h"
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "lib.h"
#include "compress/lib.h"
#include "store/lib.h"
#include "hcache/hcversion.h"
#include "muttlib.h"
#include "serialize.h"
+ Include dependency graph for hcache.c:

Go to the source code of this file.

Data Structures

struct  RealKey
 Hcache key name (including compression method) More...
 

Functions

static size_t header_size (void)
 Compute the size of the header with uuid validity and crc. More...
 
static void * dump (struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
 Serialise an Email object. More...
 
static struct Emailrestore (const unsigned char *d)
 Restore an Email from data retrieved from the cache. More...
 
static struct RealKeyrealkey (const char *key, size_t keylen)
 Compute the real key used in the backend, taking into account the compression method. More...
 
static bool create_hcache_dir (const char *path)
 Create parent dirs for the hcache database. More...
 
static void hcache_per_folder (struct Buffer *hcpath, const char *path, const char *folder, hcache_namer_t namer)
 Generate the hcache pathname. More...
 
static char * get_foldername (const char *folder)
 Where should the cache be stored? More...
 
struct HeaderCachemutt_hcache_open (const char *path, const char *folder, hcache_namer_t namer)
 Multiplexor for StoreOps::open. More...
 
void mutt_hcache_close (struct HeaderCache *hc)
 Multiplexor for StoreOps::close. More...
 
struct HCacheEntry mutt_hcache_fetch (struct HeaderCache *hc, const char *key, size_t keylen, uint32_t uidvalidity)
 Multiplexor for StoreOps::fetch. More...
 
void * mutt_hcache_fetch_raw (struct HeaderCache *hc, const char *key, size_t keylen, size_t *dlen)
 Fetch a message's header from the cache. More...
 
void mutt_hcache_free_raw (struct HeaderCache *hc, void **data)
 Multiplexor for StoreOps::free. More...
 
int mutt_hcache_store (struct HeaderCache *hc, const char *key, size_t keylen, struct Email *e, uint32_t uidvalidity)
 Multiplexor for StoreOps::store. More...
 
int mutt_hcache_store_raw (struct HeaderCache *hc, const char *key, size_t keylen, void *data, size_t dlen)
 Store a key / data pair. More...
 
int mutt_hcache_delete_record (struct HeaderCache *hc, const char *key, size_t keylen)
 Multiplexor for StoreOps::delete_record. More...
 

Variables

static unsigned int hcachever = 0x0
 

Detailed Description

Header cache multiplexor.

Authors
  • Thomas Glanzmann
  • Tobias Werth
  • Brian Fundakowski Feldman
  • Pietro Cerutti
  • Tino Reichardt

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file hcache.c.

Function Documentation

◆ header_size()

static size_t header_size ( void  )
static

Compute the size of the header with uuid validity and crc.

Return values
numSize of the header

Definition at line 69 of file hcache.c.

70{
71 return sizeof(int) + sizeof(uint32_t);
72}
+ Here is the caller graph for this function:

◆ dump()

static void * dump ( struct HeaderCache hc,
const struct Email e,
int *  off,
uint32_t  uidvalidity 
)
static

Serialise an Email object.

Parameters
hcHeader cache handle
eEmail to serialise
offSize of the binary blob
uidvalidityIMAP server identifier
Return values
ptrBinary blob representing the Email

This function transforms an Email into a binary string so that it can be saved to a database.

Definition at line 85 of file hcache.c.

86{
87 struct Email e_dump;
88 bool convert = !CharsetIsUtf8;
89
90 *off = 0;
91 unsigned char *d = mutt_mem_malloc(4096);
92
93 d = serial_dump_uint32_t((uidvalidity != 0) ? uidvalidity : mutt_date_epoch(), d, off);
94 d = serial_dump_int(hc->crc, d, off);
95
96 assert((size_t) *off == header_size());
97
98 lazy_realloc(&d, *off + sizeof(struct Email));
99 memcpy(&e_dump, e, sizeof(struct Email));
100
101 /* some fields are not safe to cache */
102 e_dump.tagged = false;
103 e_dump.changed = false;
104 e_dump.threaded = false;
105 e_dump.recip_valid = false;
106 e_dump.searched = false;
107 e_dump.matched = false;
108 e_dump.collapsed = false;
109 e_dump.visible = true;
110 e_dump.num_hidden = 0;
111 e_dump.recipient = 0;
112 e_dump.attr_color = NULL;
113 e_dump.attach_valid = false;
114 e_dump.path = NULL;
115 e_dump.tree = NULL;
116 e_dump.thread = NULL;
117 e_dump.sequence = 0;
118 e_dump.notify = NULL;
119 STAILQ_INIT(&e_dump.tags);
120#ifdef MIXMASTER
121 STAILQ_INIT(&e_dump.chain);
122#endif
123 e_dump.edata = NULL;
124
125 memcpy(d + *off, &e_dump, sizeof(struct Email));
126 *off += sizeof(struct Email);
127
128 d = serial_dump_envelope(e_dump.env, d, off, convert);
129 d = serial_dump_body(e_dump.body, d, off, convert);
130 d = serial_dump_tags(&e->tags, d, off);
131
132 return d;
133}
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:428
static size_t header_size(void)
Compute the size of the header with uuid validity and crc.
Definition: hcache.c:69
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
bool CharsetIsUtf8
Is the user's current character set utf-8?
Definition: charset.c:62
#define STAILQ_INIT(head)
Definition: queue.h:372
unsigned char * serial_dump_uint32_t(uint32_t s, unsigned char *d, int *off)
Pack a uint32_t into a binary blob.
Definition: serialize.c:84
unsigned char * serial_dump_int(unsigned int i, unsigned char *d, int *off)
Pack an integer into a binary blob.
Definition: serialize.c:68
void lazy_realloc(void *ptr, size_t size)
Reallocate some memory.
Definition: serialize.c:51
unsigned char * serial_dump_envelope(struct Envelope *env, unsigned char *d, int *off, bool convert)
Pack an Envelope into a binary blob.
Definition: serialize.c:492
unsigned char * serial_dump_body(struct Body *c, unsigned char *d, int *off, bool convert)
Pack an Body into a binary blob.
Definition: serialize.c:426
unsigned char * serial_dump_tags(const struct TagList *tags, unsigned char *d, int *off)
Pack a TagList into a binary blob.
Definition: serialize.c:598
The envelope/body of an email.
Definition: email.h:37
struct TagList tags
For drivers that support server tagging.
Definition: email.h:70
unsigned int crc
CRC of the cache entry.
Definition: lib.h:89
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ restore()

static struct Email * restore ( const unsigned char *  d)
static

Restore an Email from data retrieved from the cache.

Parameters
dData retrieved using mutt_hcache_dump
Return values
ptrSuccess, the restored header (can't be NULL)
Note
The returned Email must be free'd by caller code with email_free()

Definition at line 143 of file hcache.c.

144{
145 int off = 0;
146 struct Email *e = email_new();
147 bool convert = !CharsetIsUtf8;
148
149 /* skip validate */
150 off += sizeof(uint32_t);
151
152 /* skip crc */
153 off += sizeof(unsigned int);
154
155 size_t sequence = e->sequence;
156 struct Notify *notify = e->notify;
157 memcpy(e, d + off, sizeof(struct Email));
158 off += sizeof(struct Email);
159 e->sequence = sequence;
160 e->notify = notify;
161
162 STAILQ_INIT(&e->tags);
163#ifdef MIXMASTER
164 STAILQ_INIT(&e->chain);
165#endif
166
167 e->env = mutt_env_new();
168 serial_restore_envelope(e->env, d, &off, convert);
169
170 e->body = mutt_body_new();
171 serial_restore_body(e->body, d, &off, convert);
172 serial_restore_tags(&e->tags, d, &off);
173
174 return e;
175}
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:43
void serial_restore_tags(struct TagList *tags, const unsigned char *d, int *off)
Unpack a TagList from a binary blob.
Definition: serialize.c:623
void serial_restore_envelope(struct Envelope *env, const unsigned char *d, int *off, bool convert)
Unpack an Envelope from a binary blob.
Definition: serialize.c:542
void serial_restore_body(struct Body *c, const unsigned char *d, int *off, bool convert)
Unpack a Body from a binary blob.
Definition: serialize.c:466
struct Envelope * env
Envelope information.
Definition: email.h:66
struct Body * body
List of MIME parts.
Definition: email.h:67
struct ListHead chain
Mixmaster chain.
Definition: email.h:90
struct Notify * notify
Notifications: NotifyEmail, EventEmail.
Definition: email.h:71
size_t sequence
Sequence number assigned on creation.
Definition: email.h:65
Notification API.
Definition: notify.c:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ realkey()

static struct RealKey * realkey ( const char *  key,
size_t  keylen 
)
static

Compute the real key used in the backend, taking into account the compression method.

Parameters
keyOriginal key
keylenLength of original key
Return values
ptrStatic location holding data and length of the real key

Definition at line 192 of file hcache.c.

193{
194 static struct RealKey rk;
195#ifdef USE_HCACHE_COMPRESSION
196 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
197 if (c_header_cache_compress_method)
198 {
199 const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
200
201 rk.len = snprintf(rk.key, sizeof(rk.key), "%s-%s", key, cops->name);
202 }
203 else
204#endif
205 {
206 memcpy(rk.key, key, keylen + 1); // Including NUL byte
207 rk.len = keylen;
208 }
209 return &rk;
210}
const struct ComprOps * compress_get_ops(const char *compr)
Get the API functions for a compress backend.
Definition: compress.c:80
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
Definition: lib.h:60
const char * name
Compression name.
Definition: lib.h:61
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Hcache key name (including compression method)
Definition: hcache.c:181
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ create_hcache_dir()

static bool create_hcache_dir ( const char *  path)
static

Create parent dirs for the hcache database.

Parameters
pathDatabase filename
Return values
trueSuccess
falseFailure (errno set)

Definition at line 218 of file hcache.c.

219{
220 char *dir = mutt_str_dup(path);
221 if (!dir)
222 return false;
223
224 char *p = strrchr(dir, '/');
225 if (!p)
226 {
227 FREE(&dir);
228 return true;
229 }
230
231 *p = '\0';
232
233 int rc = mutt_file_mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO);
234 if (rc != 0)
235 mutt_error(_("Can't create %s: %s"), dir, strerror(errno));
236
237 FREE(&dir);
238 return (rc == 0);
239}
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:930
#define mutt_error(...)
Definition: logging.h:87
#define FREE(x)
Definition: memory.h:43
#define _(a)
Definition: message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hcache_per_folder()

static void hcache_per_folder ( struct Buffer hcpath,
const char *  path,
const char *  folder,
hcache_namer_t  namer 
)
static

Generate the hcache pathname.

Parameters
hcpathBuffer for the result
pathBase directory, from $header_cache
folderMailbox name (including protocol)
namerCallback to generate database filename - Implements hcache_namer_t

Generate the pathname for the hcache database, it will be of the form: BASE/FOLDER/NAME

  • BASE: Base directory (path)
  • FOLDER: Mailbox name (folder)
  • NAME: Create by namer, or md5sum of folder

This function will create any parent directories needed, so the caller just needs to create the database file.

If path exists and is a directory, it is used. If path has a trailing '/' it is assumed to be a directory. Otherwise path is assumed to be a file.

Definition at line 262 of file hcache.c.

264{
265 struct stat st = { 0 };
266
267 int plen = mutt_str_len(path);
268 int rc = stat(path, &st);
269 bool slash = (path[plen - 1] == '/');
270
271 if (((rc == 0) && !S_ISDIR(st.st_mode)) || ((rc == -1) && !slash))
272 {
273 /* An existing file or a non-existing path not ending with a slash */
274 mutt_encode_path(hcpath, path);
276 return;
277 }
278
279 /* We have a directory - no matter whether it exists, or not */
280 struct Buffer *hcfile = mutt_buffer_pool_get();
281 if (namer)
282 {
283 namer(folder, hcfile);
284 mutt_buffer_concat_path(hcpath, path, mutt_buffer_string(hcfile));
285 }
286 else
287 {
288 unsigned char m[16]; /* binary md5sum */
289 struct Buffer *name = mutt_buffer_pool_get();
290
291 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
292 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
293
294#ifdef USE_HCACHE_COMPRESSION
295 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
296 const char *cm = c_header_cache_compress_method;
297 mutt_buffer_printf(name, "%s|%s%s", ops->name, folder, cm ? cm : "");
298#else
299 mutt_buffer_printf(name, "%s|%s", ops->name, folder);
300#endif
303 mutt_md5_toascii(m, name->data);
304 mutt_buffer_printf(hcpath, "%s%s%s", path, slash ? "" : "/", mutt_buffer_string(name));
306 }
307
308 mutt_encode_path(hcpath, mutt_buffer_string(hcpath));
311}
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:389
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
static bool create_hcache_dir(const char *path)
Create parent dirs for the hcache database.
Definition: hcache.c:218
void * mutt_md5(const char *str, void *buf)
Calculate the MD5 hash of a NULL-terminated string.
Definition: md5.c:318
void mutt_md5_toascii(const void *digest, char *resbuf)
Convert a binary MD5 digest into ASCII Hexadecimal.
Definition: md5.c:457
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to 'us-ascii'.
Definition: muttlib.c:1484
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
const struct StoreOps * store_get_backend_ops(const char *str)
Get the API functions for an store backend.
Definition: store.c:107
String manipulation buffer.
Definition: buffer.h:34
Definition: lib.h:66
const char * name
Store name.
Definition: lib.h:67
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_foldername()

static char * get_foldername ( const char *  folder)
static

Where should the cache be stored?

Parameters
folderPath to be canonicalised
Return values
ptrNew string with canonical path

Definition at line 318 of file hcache.c.

319{
320 /* if the folder is local, canonify the path to avoid
321 * to ensure equivalent paths share the hcache */
322 char *p = mutt_mem_malloc(PATH_MAX + 1);
323 if (!realpath(folder, p))
324 mutt_str_replace(&p, folder);
325
326 return p;
327}
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
#define PATH_MAX
Definition: mutt.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_open()

struct HeaderCache * mutt_hcache_open ( const char *  path,
const char *  folder,
hcache_namer_t  namer 
)

Multiplexor for StoreOps::open.

Open the connection to the header cache.

< MD5 digest as a string

< MD5 digest as an integer

Definition at line 332 of file hcache.c.

333{
334 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
335 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
336 if (!ops)
337 return NULL;
338
339 struct HeaderCache *hc = mutt_mem_calloc(1, sizeof(struct HeaderCache));
340
341 /* Calculate the current hcache version from dynamic configuration */
342 if (hcachever == 0x0)
343 {
344 union
345 {
346 unsigned char charval[16];
347 unsigned int intval;
348 } digest;
349 struct Md5Ctx md5ctx;
350
351 hcachever = HCACHEVER;
352
353 mutt_md5_init_ctx(&md5ctx);
354
355 /* Seed with the compiled-in header structure hash */
356 mutt_md5_process_bytes(&hcachever, sizeof(hcachever), &md5ctx);
357
358 /* Mix in user's spam list */
359 struct Replace *sp = NULL;
360 STAILQ_FOREACH(sp, &SpamList, entries)
361 {
362 mutt_md5_process(sp->regex->pattern, &md5ctx);
363 mutt_md5_process(sp->templ, &md5ctx);
364 }
365
366 /* Mix in user's nospam list */
367 struct RegexNode *np = NULL;
368 STAILQ_FOREACH(np, &NoSpamList, entries)
369 {
370 mutt_md5_process(np->regex->pattern, &md5ctx);
371 }
372
373 /* Get a hash and take its bytes as an (unsigned int) hash version */
374 mutt_md5_finish_ctx(&md5ctx, digest.charval);
375 hcachever = digest.intval;
376 }
377
378#ifdef USE_HCACHE_COMPRESSION
379 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
380 if (c_header_cache_compress_method)
381 {
382 const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
383
384 const short c_header_cache_compress_level = cs_subset_number(NeoMutt->sub, "header_cache_compress_level");
385 hc->cctx = cops->open(c_header_cache_compress_level);
386 if (!hc->cctx)
387 {
388 FREE(&hc);
389 return NULL;
390 }
391
392 /* remember the buffer of database backend */
393 mutt_debug(LL_DEBUG3, "Header cache will use %s compression\n", cops->name);
394 }
395#endif
396
397 hc->folder = get_foldername(folder);
398 hc->crc = hcachever;
399
400 if (!path || (path[0] == '\0'))
401 {
402 FREE(&hc->folder);
403 FREE(&hc);
404 return NULL;
405 }
406
407 struct Buffer *hcpath = mutt_buffer_pool_get();
408 hcache_per_folder(hcpath, path, hc->folder, namer);
409
410 hc->ctx = ops->open(mutt_buffer_string(hcpath));
411 if (!hc->ctx)
412 {
413 /* remove a possibly incompatible version */
414 if (unlink(mutt_buffer_string(hcpath)) == 0)
415 {
416 hc->ctx = ops->open(mutt_buffer_string(hcpath));
417 if (!hc->ctx)
418 {
419 FREE(&hc->folder);
420 FREE(&hc);
421 }
422 }
423 }
424
426 return hc;
427}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
struct ReplaceList SpamList
List of regexes and patterns to match spam emails.
Definition: globals.c:34
struct RegexList NoSpamList
List of regexes to whitelist non-spam emails.
Definition: globals.c:33
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
static unsigned int hcachever
Definition: hcache.c:63
static void hcache_per_folder(struct Buffer *hcpath, const char *path, const char *folder, hcache_namer_t namer)
Generate the hcache pathname.
Definition: hcache.c:262
static char * get_foldername(const char *folder)
Where should the cache be stored?
Definition: hcache.c:318
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
void mutt_md5_process_bytes(const void *buf, size_t buflen, struct Md5Ctx *md5ctx)
Process a block of data.
Definition: md5.c:374
void mutt_md5_process(const char *str, struct Md5Ctx *md5ctx)
Process a NULL-terminated string.
Definition: md5.c:356
void mutt_md5_init_ctx(struct Md5Ctx *md5ctx)
Initialise the MD5 computation.
Definition: md5.c:262
void * mutt_md5_finish_ctx(struct Md5Ctx *md5ctx, void *resbuf)
Process the remaining bytes in the buffer.
Definition: md5.c:286
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
void *(* open)(short level)
Definition: lib.h:74
Header cache structure.
Definition: lib.h:87
void * ctx
Store context (handle)
Definition: lib.h:90
char * folder
Folder name.
Definition: lib.h:88
void * cctx
Compression context (handle)
Definition: lib.h:91
Cursor for the MD5 hashing.
Definition: md5.h:37
List of regular expressions.
Definition: regex3.h:99
struct Regex * regex
Regex containing a regular expression.
Definition: regex3.h:100
char * pattern
printable version
Definition: regex3.h:90
List of regular expressions.
Definition: regex3.h:109
char * templ
Template to match.
Definition: regex3.h:112
struct Regex * regex
Regex containing a regular expression.
Definition: regex3.h:110
void *(* open)(const char *path)
Definition: lib.h:82
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_close()

void mutt_hcache_close ( struct HeaderCache hc)

Multiplexor for StoreOps::close.

Close the connection to the header cache.

Definition at line 432 of file hcache.c.

433{
434 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
435 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
436 if (!hc || !ops)
437 return;
438
439#ifdef USE_HCACHE_COMPRESSION
440 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
441 if (c_header_cache_compress_method)
442 {
443 const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
444 cops->close(&hc->cctx);
445 }
446#endif
447
448 ops->close(&hc->ctx);
449 FREE(&hc->folder);
450 FREE(&hc);
451}
void(* close)(void **cctx)
Definition: lib.h:119
void(* close)(void **ptr)
Definition: lib.h:143
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_fetch()

struct HCacheEntry mutt_hcache_fetch ( struct HeaderCache hc,
const char *  key,
size_t  keylen,
uint32_t  uidvalidity 
)

Multiplexor for StoreOps::fetch.

Fetch and validate a message's header from the cache.

Definition at line 456 of file hcache.c.

458{
459 struct RealKey *rk = realkey(key, keylen);
460 struct HCacheEntry entry = { 0 };
461
462 size_t dlen;
463 void *data = mutt_hcache_fetch_raw(hc, rk->key, rk->len, &dlen);
464 void *to_free = data;
465 if (!data)
466 {
467 goto end;
468 }
469
470 /* restore uidvalidity and crc */
471 size_t hlen = header_size();
472 if (hlen > dlen)
473 {
474 goto end;
475 }
476 int off = 0;
477 serial_restore_uint32_t(&entry.uidvalidity, data, &off);
478 serial_restore_int(&entry.crc, data, &off);
479 assert((size_t) off == hlen);
480 if (entry.crc != hc->crc || ((uidvalidity != 0) && uidvalidity != entry.uidvalidity))
481 {
482 goto end;
483 }
484
485#ifdef USE_HCACHE_COMPRESSION
486 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
487 if (c_header_cache_compress_method)
488 {
489 const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
490
491 void *dblob = cops->decompress(hc->cctx, (char *) data + hlen, dlen - hlen);
492 if (!dblob)
493 {
494 goto end;
495 }
496 data = (char *) dblob - hlen; /* restore skips uidvalidity and crc */
497 }
498#endif
499
500 entry.email = restore(data);
501
502end:
503 mutt_hcache_free_raw(hc, &to_free);
504 return entry;
505}
static struct RealKey * realkey(const char *key, size_t keylen)
Compute the real key used in the backend, taking into account the compression method.
Definition: hcache.c:192
void * mutt_hcache_fetch_raw(struct HeaderCache *hc, const char *key, size_t keylen, size_t *dlen)
Fetch a message's header from the cache.
Definition: hcache.c:519
static struct Email * restore(const unsigned char *d)
Restore an Email from data retrieved from the cache.
Definition: hcache.c:143
void mutt_hcache_free_raw(struct HeaderCache *hc, void **data)
Multiplexor for StoreOps::free.
Definition: hcache.c:538
void serial_restore_int(unsigned int *i, const unsigned char *d, int *off)
Unpack an integer from a binary blob.
Definition: serialize.c:99
void serial_restore_uint32_t(uint32_t *s, const unsigned char *d, int *off)
Unpack an uint32_t from a binary blob.
Definition: serialize.c:111
void *(* decompress)(void *cctx, const char *cbuf, size_t clen)
Definition: lib.h:107
Wrapper for Email retrieved from the header cache.
Definition: lib.h:98
uint32_t uidvalidity
IMAP-specific UIDVALIDITY.
Definition: lib.h:99
struct Email * email
Retrieved email.
Definition: lib.h:101
unsigned int crc
CRC of Email/Body/etc structs.
Definition: lib.h:100
char key[1024]
Key name.
Definition: hcache.c:182
size_t len
Length of key.
Definition: hcache.c:183
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_fetch_raw()

void * mutt_hcache_fetch_raw ( struct HeaderCache hc,
const char *  key,
size_t  keylen,
size_t *  dlen 
)

Fetch a message's header from the cache.

Parameters
[in]hcPointer to the struct HeaderCache structure got by mutt_hcache_open()
[in]keyMessage identification string
[in]keylenLength of the string pointed to by key
[out]dlenLength of the fetched data
Return values
ptrSuccess, the data if found
NULLOtherwise
Note
This function does not perform any check on the validity of the data found.
The returned data must be free with mutt_hcache_free_raw().

Definition at line 519 of file hcache.c.

521{
522 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
523 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
524
525 if (!hc || !ops)
526 return NULL;
527
528 struct Buffer path = mutt_buffer_make(1024);
529 keylen = mutt_buffer_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
530 void *blob = ops->fetch(hc->ctx, mutt_buffer_string(&path), keylen, dlen);
531 mutt_buffer_dealloc(&path);
532 return blob;
533}
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:67
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:309
void *(* fetch)(void *store, const char *key, size_t klen, size_t *vlen)
Definition: lib.h:96
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_free_raw()

void mutt_hcache_free_raw ( struct HeaderCache hc,
void **  data 
)

Multiplexor for StoreOps::free.

Free data fetched with mutt_hcache_fetch_raw()

Definition at line 538 of file hcache.c.

539{
540 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
541 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
542
543 if (!hc || !ops || !data || !*data)
544 return;
545
546 ops->free(hc->ctx, data);
547}
void(* free)(void *store, void **ptr)
Definition: lib.h:106
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_store()

int mutt_hcache_store ( struct HeaderCache hc,
const char *  key,
size_t  keylen,
struct Email e,
uint32_t  uidvalidity 
)

Multiplexor for StoreOps::store.

Store a Header along with a validity datum.

Definition at line 552 of file hcache.c.

554{
555 if (!hc)
556 return -1;
557
558 int dlen = 0;
559 char *data = dump(hc, e, &dlen, uidvalidity);
560
561#ifdef USE_HCACHE_COMPRESSION
562 const char *const c_header_cache_compress_method = cs_subset_string(NeoMutt->sub, "header_cache_compress_method");
563 if (c_header_cache_compress_method)
564 {
565 /* We don't compress uidvalidity and the crc, so we can check them before
566 * decompressing on fetch(). */
567 size_t hlen = header_size();
568
569 const struct ComprOps *cops = compress_get_ops(c_header_cache_compress_method);
570
571 /* data / dlen gets ptr to compressed data here */
572 size_t clen = dlen;
573 void *cdata = cops->compress(hc->cctx, data + hlen, dlen - hlen, &clen);
574 if (!cdata)
575 {
576 FREE(&data);
577 return -1;
578 }
579
580 char *whole = mutt_mem_malloc(hlen + clen);
581 memcpy(whole, data, hlen);
582 memcpy(whole + hlen, cdata, clen);
583
584 FREE(&data);
585
586 data = whole;
587 dlen = hlen + clen;
588 }
589#endif
590
591 /* store uncompressed data */
592 struct RealKey *rk = realkey(key, keylen);
593 int rc = mutt_hcache_store_raw(hc, rk->key, rk->len, data, dlen);
594
595 FREE(&data);
596
597 return rc;
598}
static void * dump(struct HeaderCache *hc, const struct Email *e, int *off, uint32_t uidvalidity)
Serialise an Email object.
Definition: hcache.c:85
int mutt_hcache_store_raw(struct HeaderCache *hc, const char *key, size_t keylen, void *data, size_t dlen)
Store a key / data pair.
Definition: hcache.c:610
void *(* compress)(void *cctx, const char *data, size_t dlen, size_t *clen)
Definition: lib.h:91
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_store_raw()

int mutt_hcache_store_raw ( struct HeaderCache hc,
const char *  key,
size_t  keylen,
void *  data,
size_t  dlen 
)

Store a key / data pair.

Parameters
hcPointer to the struct HeaderCache structure got by mutt_hcache_open()
keyMessage identification string
keylenLength of the string pointed to by key
dataPayload to associate with key
dlenLength of the buffer pointed to by the data parameter
Return values
0Success
numGeneric or backend-specific error code otherwise

Definition at line 610 of file hcache.c.

612{
613 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
614 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
615
616 if (!hc || !ops)
617 return -1;
618
619 struct Buffer path = mutt_buffer_make(1024);
620
621 keylen = mutt_buffer_printf(&path, "%s%.*s", hc->folder, (int) keylen, key);
622 int rc = ops->store(hc->ctx, mutt_buffer_string(&path), keylen, data, dlen);
623 mutt_buffer_dealloc(&path);
624
625 return rc;
626}
char * data
Pointer to data.
Definition: buffer.h:35
int(* store)(void *store, const char *key, size_t klen, void *value, size_t vlen)
Definition: lib.h:121
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hcache_delete_record()

int mutt_hcache_delete_record ( struct HeaderCache hc,
const char *  key,
size_t  keylen 
)

Multiplexor for StoreOps::delete_record.

Delete a key / data pair.

Definition at line 631 of file hcache.c.

632{
633 if (!hc)
634 return -1;
635
636 const char *const c_header_cache_backend = cs_subset_string(NeoMutt->sub, "header_cache_backend");
637 const struct StoreOps *ops = store_get_backend_ops(c_header_cache_backend);
638
639 struct Buffer path = mutt_buffer_make(1024);
640
641 keylen = mutt_buffer_printf(&path, "%s%s", hc->folder, key);
642
643 int rc = ops->delete_record(hc->ctx, mutt_buffer_string(&path), keylen);
644 mutt_buffer_dealloc(&path);
645 return rc;
646}
int(* delete_record)(void *store, const char *key, size_t klen)
Definition: lib.h:134
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ hcachever

unsigned int hcachever = 0x0
static

Definition at line 63 of file hcache.c.