NeoMutt  2021-10-29-220-g2b1eec
Teaching an old dog new tricks
DOXYGEN
lib.h File Reference

Body Caching (local copies of email bodies) More...

#include <stdio.h>
+ Include dependency graph for lib.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef int(* bcache_list_t) (const char *id, struct BodyCache *bcache, void *data)
 

Functions

void mutt_bcache_close (struct BodyCache **bcache)
 Close an Email-Body Cache. More...
 
int mutt_bcache_commit (struct BodyCache *bcache, const char *id)
 Move a temporary file into the Body Cache. More...
 
int mutt_bcache_del (struct BodyCache *bcache, const char *id)
 Delete a file from the Body Cache. More...
 
int mutt_bcache_exists (struct BodyCache *bcache, const char *id)
 Check if a file exists in the Body Cache. More...
 
FILE * mutt_bcache_get (struct BodyCache *bcache, const char *id)
 Open a file in the Body Cache. More...
 
int mutt_bcache_list (struct BodyCache *bcache, bcache_list_t want_id, void *data)
 Find matching entries in the Body Cache. More...
 
struct BodyCachemutt_bcache_open (struct ConnAccount *account, const char *mailbox)
 Open an Email-Body Cache. More...
 
FILE * mutt_bcache_put (struct BodyCache *bcache, const char *id)
 Create a file in the Body Cache. More...
 

Detailed Description

Body Caching (local copies of email bodies)

Authors
  • Brendan Cully
  • Rocco Rutte

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 lib.h.

Typedef Documentation

◆ bcache_list_t

typedef int(* bcache_list_t) (const char *id, struct BodyCache *bcache, void *data)

Definition at line 55 of file lib.h.

Function Documentation

◆ mutt_bcache_close()

void mutt_bcache_close ( struct BodyCache **  bcache)

Close an Email-Body Cache.

Parameters
[out]bcacheBody cache

Free all memory of bcache and finally FREE() it, too.

Definition at line 166 of file bcache.c.

167 {
168  if (!bcache || !*bcache)
169  return;
170  FREE(&(*bcache)->path);
171  FREE(bcache);
172 }
#define FREE(x)
Definition: memory.h:40
+ Here is the caller graph for this function:

◆ mutt_bcache_commit()

int mutt_bcache_commit ( struct BodyCache bcache,
const char *  id 
)

Move a temporary file into the Body Cache.

Parameters
bcacheBody Cache from mutt_bcache_open()
idPer-mailbox unique identifier for the message
Return values
0Success
-1Failure

Definition at line 249 of file bcache.c.

250 {
251  struct Buffer *tmpid = mutt_buffer_pool_get();
252  mutt_buffer_printf(tmpid, "%s.tmp", id);
253 
254  int rc = mutt_bcache_move(bcache, mutt_buffer_string(tmpid), id);
255  mutt_buffer_pool_release(&tmpid);
256  return rc;
257 }
static int mutt_bcache_move(struct BodyCache *bcache, const char *id, const char *newid)
Change the id of a message in the cache.
Definition: bcache.c:115
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
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
String manipulation buffer.
Definition: buffer.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_bcache_del()

int mutt_bcache_del ( struct BodyCache bcache,
const char *  id 
)

Delete a file from the Body Cache.

Parameters
bcacheBody Cache from mutt_bcache_open()
idPer-mailbox unique identifier for the message
Return values
0Success
-1Failure

Definition at line 266 of file bcache.c.

267 {
268  if (!id || (*id == '\0') || !bcache)
269  return -1;
270 
271  struct Buffer *path = mutt_buffer_pool_get();
272  mutt_buffer_addstr(path, bcache->path);
273  mutt_buffer_addstr(path, id);
274 
275  mutt_debug(LL_DEBUG3, "bcache: del: '%s'\n", mutt_buffer_string(path));
276 
277  int rc = unlink(mutt_buffer_string(path));
279  return rc;
280 }
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
char * path
On-disk path to the file.
Definition: bcache.c:52
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_bcache_exists()

int mutt_bcache_exists ( struct BodyCache bcache,
const char *  id 
)

Check if a file exists in the Body Cache.

Parameters
bcacheBody Cache from mutt_bcache_open()
idPer-mailbox unique identifier for the message
Return values
0Success
-1Failure

Definition at line 289 of file bcache.c.

290 {
291  if (!id || (*id == '\0') || !bcache)
292  return -1;
293 
294  struct Buffer *path = mutt_buffer_pool_get();
295  mutt_buffer_addstr(path, bcache->path);
296  mutt_buffer_addstr(path, id);
297 
298  int rc = 0;
299  struct stat st = { 0 };
300  if (stat(mutt_buffer_string(path), &st) < 0)
301  rc = -1;
302  else
303  rc = (S_ISREG(st.st_mode) && (st.st_size != 0)) ? 0 : -1;
304 
305  mutt_debug(LL_DEBUG3, "bcache: exists: '%s': %s\n", mutt_buffer_string(path),
306  (rc == 0) ? "yes" : "no");
307 
309  return rc;
310 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_bcache_get()

FILE* mutt_bcache_get ( struct BodyCache bcache,
const char *  id 
)

Open a file in the Body Cache.

Parameters
bcacheBody Cache from mutt_bcache_open()
idPer-mailbox unique identifier for the message
Return values
ptrSuccess
NULLFailure

Definition at line 181 of file bcache.c.

182 {
183  if (!id || (*id == '\0') || !bcache)
184  return NULL;
185 
186  struct Buffer *path = mutt_buffer_pool_get();
187  mutt_buffer_addstr(path, bcache->path);
188  mutt_buffer_addstr(path, id);
189 
190  FILE *fp = mutt_file_fopen(mutt_buffer_string(path), "r");
191 
192  mutt_debug(LL_DEBUG3, "bcache: get: '%s': %s\n", mutt_buffer_string(path),
193  fp ? "yes" : "no");
194 
196  return fp;
197 }
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:593
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_bcache_list()

int mutt_bcache_list ( struct BodyCache bcache,
bcache_list_t  want_id,
void *  data 
)

Find matching entries in the Body Cache.

Parameters
bcacheBody Cache from mutt_bcache_open()
want_idCallback function called for each match
dataData to pass to the callback function
Return values
-1Failure
>=0count of matching items

This more or less "examines" the cache and calls a function with each id it finds if given.

The optional callback function gets the id of a message, the very same body cache handle mutt_bcache_list() is called with (to, perhaps, perform further operations on the bcache), and a data cookie which is just passed as-is. If the return value of the callback is non-zero, the listing is aborted and continued otherwise. The callback is optional so that this function can be used to count the items in the cache (see below for return value).

Definition at line 331 of file bcache.c.

332 {
333  DIR *d = NULL;
334  struct dirent *de = NULL;
335  int rc = -1;
336 
337  if (!bcache || !(d = opendir(bcache->path)))
338  goto out;
339 
340  rc = 0;
341 
342  mutt_debug(LL_DEBUG3, "bcache: list: dir: '%s'\n", bcache->path);
343 
344  while ((de = readdir(d)))
345  {
346  if (mutt_str_startswith(de->d_name, ".") || mutt_str_startswith(de->d_name, ".."))
347  {
348  continue;
349  }
350 
351  mutt_debug(LL_DEBUG3, "bcache: list: dir: '%s', id :'%s'\n", bcache->path, de->d_name);
352 
353  if (want_id && (want_id(de->d_name, bcache, data) != 0))
354  goto out;
355 
356  rc++;
357  }
358 
359 out:
360  if (d)
361  {
362  if (closedir(d) < 0)
363  rc = -1;
364  }
365  mutt_debug(LL_DEBUG3, "bcache: list: did %d entries\n", rc);
366  return rc;
367 }
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:158
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_bcache_open()

struct BodyCache* mutt_bcache_open ( struct ConnAccount account,
const char *  mailbox 
)

Open an Email-Body Cache.

Parameters
accountcurrent mailbox' account (required)
mailboxpath to the mailbox of the account (optional)
Return values
NULLFailure

The driver using it is responsible for ensuring that hierarchies are separated by '/' (if it knows of such a concepts like mailboxes or hierarchies)

Definition at line 145 of file bcache.c.

146 {
147  if (!account)
148  return NULL;
149 
150  struct BodyCache *bcache = mutt_mem_calloc(1, sizeof(struct BodyCache));
151  if (bcache_path(account, mailbox, bcache) < 0)
152  {
153  mutt_bcache_close(&bcache);
154  return NULL;
155  }
156 
157  return bcache;
158 }
static int bcache_path(struct ConnAccount *account, const char *mailbox, struct BodyCache *bcache)
Create the cache path for a given account/mailbox.
Definition: bcache.c:63
void mutt_bcache_close(struct BodyCache **bcache)
Close an Email-Body Cache.
Definition: bcache.c:166
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
Local cache of email bodies.
Definition: bcache.c:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_bcache_put()

FILE* mutt_bcache_put ( struct BodyCache bcache,
const char *  id 
)

Create a file in the Body Cache.

Parameters
bcacheBody Cache from mutt_bcache_open()
idPer-mailbox unique identifier for the message
Return values
ptrSuccess
NULLFailure

The returned FILE* is in a temporary location. Use mutt_bcache_commit to put it into place

Definition at line 209 of file bcache.c.

210 {
211  if (!id || (*id == '\0') || !bcache)
212  return NULL;
213 
214  struct Buffer *path = mutt_buffer_pool_get();
215  mutt_buffer_printf(path, "%s%s%s", bcache->path, id, ".tmp");
216 
217  struct stat st = { 0 };
218  if (stat(bcache->path, &st) == 0)
219  {
220  if (!S_ISDIR(st.st_mode))
221  {
222  mutt_error(_("Message cache isn't a directory: %s"), bcache->path);
223  return NULL;
224  }
225  }
226  else
227  {
228  if (mutt_file_mkdir(bcache->path, S_IRWXU | S_IRWXG | S_IRWXO) < 0)
229  {
230  mutt_error(_("Can't create %s: %s"), bcache->path, strerror(errno));
231  return NULL;
232  }
233  }
234 
235  mutt_debug(LL_DEBUG3, "bcache: put: '%s'\n", path);
236 
237  FILE *fp = mutt_file_fopen(mutt_buffer_string(path), "w+");
239  return fp;
240 }
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:905
#define mutt_error(...)
Definition: logging.h:87
#define _(a)
Definition: message.h:28
+ Here is the call graph for this function:
+ Here is the caller graph for this function: