NeoMutt  2024-04-25-89-g194907
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
compress.c File Reference

Compressed mbox local mailbox type. More...

#include "config.h"
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "lib.h"
#include "expando/lib.h"
#include "globals.h"
#include "hook.h"
#include "mx.h"
#include "protos.h"
+ Include dependency graph for compress.c:

Go to the source code of this file.

Functions

void mutt_comp_init (void)
 Setup feature commands.
 
static bool lock_realpath (struct Mailbox *m, bool excl)
 Try to lock the Mailbox.realpath.
 
static void unlock_realpath (struct Mailbox *m)
 Unlock the mailbox->realpath.
 
static int setup_paths (struct Mailbox *m)
 Set the mailbox paths.
 
static void store_size (const struct Mailbox *m)
 Save the size of the compressed file.
 
static struct Expandovalidate_compress_expando (const char *s)
 Validate the Compress hooks.
 
static struct CompressInfoset_compress_info (struct Mailbox *m)
 Find the compress hooks for a mailbox.
 
static void compress_info_free (struct Mailbox *m)
 Frees the compress info members and structure.
 
void compress_f (const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
 Compress: From filename - Implements ExpandoRenderData::get_string() -.
 
void compress_t (const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
 Compress: To filename - Implements ExpandoRenderData::get_string() -.
 
static bool execute_command (struct Mailbox *m, const struct Expando *exp, const char *progress)
 Run a system command.
 
bool mutt_comp_can_append (struct Mailbox *m)
 Can we append to this path?
 
bool mutt_comp_can_read (const char *path)
 Can we read from this file?
 
int mutt_comp_valid_command (const char *cmd)
 Is this command string allowed?
 
static bool comp_ac_owns_path (struct Account *a, const char *path)
 Check whether an Account owns a Mailbox path - Implements MxOps::ac_owns_path() -.
 
static bool comp_ac_add (struct Account *a, struct Mailbox *m)
 Add a Mailbox to an Account - Implements MxOps::ac_add() -.
 
static enum MxOpenReturns comp_mbox_open (struct Mailbox *m)
 Open a Mailbox - Implements MxOps::mbox_open() -.
 
static bool comp_mbox_open_append (struct Mailbox *m, OpenMailboxFlags flags)
 Open a Mailbox for appending - Implements MxOps::mbox_open_append() -.
 
static enum MxStatus comp_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -.
 
static enum MxStatus comp_mbox_sync (struct Mailbox *m)
 Save changes to the Mailbox - Implements MxOps::mbox_sync() -.
 
static enum MxStatus comp_mbox_close (struct Mailbox *m)
 Close a Mailbox - Implements MxOps::mbox_close() -.
 
static bool comp_msg_open (struct Mailbox *m, struct Message *msg, struct Email *e)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -.
 
static bool comp_msg_open_new (struct Mailbox *m, struct Message *msg, const struct Email *e)
 Open a new message in a Mailbox - Implements MxOps::msg_open_new() -.
 
static int comp_msg_commit (struct Mailbox *m, struct Message *msg)
 Save changes to an email - Implements MxOps::msg_commit() -.
 
static int comp_msg_close (struct Mailbox *m, struct Message *msg)
 Close an email - Implements MxOps::msg_close() -.
 
static int comp_msg_padding_size (struct Mailbox *m)
 Bytes of padding between messages - Implements MxOps::msg_padding_size() -.
 
static int comp_msg_save_hcache (struct Mailbox *m, struct Email *e)
 Save message to the header cache - Implements MxOps::msg_save_hcache() -.
 
static int comp_tags_edit (struct Mailbox *m, const char *tags, struct Buffer *buf)
 Prompt and validate new messages tags - Implements MxOps::tags_edit() -.
 
static int comp_tags_commit (struct Mailbox *m, struct Email *e, const char *buf)
 Save the tags to a message - Implements MxOps::tags_commit() -.
 
static enum MailboxType comp_path_probe (const char *path, const struct stat *st)
 Is this a compressed Mailbox? - Implements MxOps::path_probe() -.
 
static int comp_path_canon (struct Buffer *path)
 Canonicalise a Mailbox path - Implements MxOps::path_canon() -.
 

Variables

const struct ExpandoRenderData CompressRenderData []
 Callbacks for Compression Hook Expandos.
 
static const struct Command CompCommands []
 Compression Commands.
 
const struct ExpandoDefinition CompressFormatDef []
 Expando definitions.
 
const struct MxOps MxCompOps
 Compressed Mailbox - Implements MxOps -.
 

Detailed Description

Compressed mbox local mailbox type.

Authors
  • Richard Russon
  • Pietro Cerutti
  • Reto Brunner
  • Tóth János

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 compress.c.

Function Documentation

◆ mutt_comp_init()

void mutt_comp_init ( void  )

Setup feature commands.

Definition at line 91 of file compress.c.

92{
94}
static const struct Command CompCommands[]
Compression Commands.
Definition: compress.c:64
void commands_register(const struct Command *cmds, const size_t num_cmds)
Add commands to Commands array.
Definition: command.c:53
#define mutt_array_size(x)
Definition: memory.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ lock_realpath()

static bool lock_realpath ( struct Mailbox m,
bool  excl 
)
static

Try to lock the Mailbox.realpath.

Parameters
mMailbox to lock
exclLock exclusively?
Return values
trueSuccess (locked or readonly)
falseError (can't lock the file)

Try to (exclusively) lock the mailbox. If we succeed, then we mark the mailbox as locked. If we fail, but we didn't want exclusive rights, then the mailbox will be marked readonly.

Definition at line 107 of file compress.c.

108{
109 if (!m || !m->compress_info)
110 return false;
111
112 struct CompressInfo *ci = m->compress_info;
113
114 if (ci->locked)
115 return true;
116
117 if (excl)
118 ci->fp_lock = mutt_file_fopen(m->realpath, "a");
119 else
120 ci->fp_lock = mutt_file_fopen(m->realpath, "r");
121 if (!ci->fp_lock)
122 {
123 mutt_perror("%s", m->realpath);
124 return false;
125 }
126
127 int r = mutt_file_lock(fileno(ci->fp_lock), excl, true);
128 if (r == 0)
129 {
130 ci->locked = true;
131 }
132 else if (excl)
133 {
135 m->readonly = true;
136 return true;
137 }
138
139 return r == 0;
140}
int mutt_file_lock(int fd, bool excl, bool timeout)
(Try to) Lock a file using fcntl()
Definition: file.c:1202
#define mutt_file_fclose(FP)
Definition: file.h:149
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:148
#define mutt_perror(...)
Definition: logging2.h:93
Private data for compress.
Definition: lib.h:58
FILE * fp_lock
fp used for locking
Definition: lib.h:65
bool locked
if realpath is locked
Definition: lib.h:64
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:81
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:121
bool readonly
Don't allow changes to the mailbox.
Definition: mailbox.h:116
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unlock_realpath()

static void unlock_realpath ( struct Mailbox m)
static

Unlock the mailbox->realpath.

Parameters
mMailbox to unlock

Unlock a mailbox previously locked by lock_mailbox().

Definition at line 148 of file compress.c.

149{
150 if (!m || !m->compress_info)
151 return;
152
153 struct CompressInfo *ci = m->compress_info;
154
155 if (!ci->locked)
156 return;
157
158 mutt_file_unlock(fileno(ci->fp_lock));
159
160 ci->locked = false;
162}
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1249
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setup_paths()

static int setup_paths ( struct Mailbox m)
static

Set the mailbox paths.

Parameters
mMailbox to modify
Return values
0Success
-1Error

Save the compressed filename in mailbox->realpath. Create a temporary filename and put its name in mailbox->path. The temporary file is created to prevent symlink attacks.

Definition at line 174 of file compress.c.

175{
176 if (!m)
177 return -1;
178
179 /* Setup the right paths */
181
182 /* We will uncompress to TMPDIR */
183 struct Buffer *buf = buf_pool_get();
184 buf_mktemp(buf);
185 buf_copy(&m->pathbuf, buf);
186 buf_pool_release(&buf);
187
188 FILE *fp = mutt_file_fopen(mailbox_path(m), "w");
189 if (!fp)
190 return -1;
191
192 mutt_file_fclose(&fp);
193 return 0;
194}
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:601
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:223
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:280
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
String manipulation buffer.
Definition: buffer.h:36
struct Buffer pathbuf
Path of the Mailbox.
Definition: mailbox.h:80
#define buf_mktemp(buf)
Definition: tmp.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ store_size()

static void store_size ( const struct Mailbox m)
static

Save the size of the compressed file.

Parameters
mMailbox

Save the compressed file size in the compress_info struct.

Definition at line 202 of file compress.c.

203{
204 if (!m || !m->compress_info)
205 return;
206
207 struct CompressInfo *ci = m->compress_info;
208
210}
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1519
long size
size of the compressed file
Definition: lib.h:62
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ validate_compress_expando()

static struct Expando * validate_compress_expando ( const char *  s)
static

Validate the Compress hooks.

Parameters
sCommand string
Return values
ptrExpando

Definition at line 217 of file compress.c.

218{
219 struct Buffer *err = buf_pool_get();
220
221 struct Expando *exp = expando_parse(s, CompressFormatDef, err);
222 if (!exp)
223 {
224 mutt_error(_("Expando parse error: %s"), buf_string(err));
225 }
226
227 buf_pool_release(&err);
228 return exp;
229}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
const struct ExpandoDefinition CompressFormatDef[]
Expando definitions.
Definition: compress.c:80
struct Expando * expando_parse(const char *str, const struct ExpandoDefinition *defs, struct Buffer *err)
Parse an Expando string.
Definition: expando.c:74
#define mutt_error(...)
Definition: logging2.h:92
#define _(a)
Definition: message.h:28
Parsed Expando trees.
Definition: expando.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_compress_info()

static struct CompressInfo * set_compress_info ( struct Mailbox m)
static

Find the compress hooks for a mailbox.

Parameters
mMailbox to examine
Return values
ptrCompressInfo Hook info for the mailbox's path
NULLError

When a mailbox is opened, we check if there are any matching hooks.

Definition at line 239 of file compress.c.

240{
241 if (!m)
242 return NULL;
243
244 if (m->compress_info)
245 return m->compress_info;
246
247 /* Open is compulsory */
248 const char *o = mutt_find_hook(MUTT_OPEN_HOOK, mailbox_path(m));
249 if (!o)
250 return NULL;
251
252 const char *c = mutt_find_hook(MUTT_CLOSE_HOOK, mailbox_path(m));
253 const char *a = mutt_find_hook(MUTT_APPEND_HOOK, mailbox_path(m));
254
255 struct CompressInfo *ci = mutt_mem_calloc(1, sizeof(struct CompressInfo));
256 m->compress_info = ci;
257
261
262 return ci;
263}
static struct Expando * validate_compress_expando(const char *s)
Validate the Compress hooks.
Definition: compress.c:217
char * mutt_find_hook(HookFlags type, const char *pat)
Find a matching hook.
Definition: hook.c:671
#define MUTT_OPEN_HOOK
open-hook: to read a compressed mailbox
Definition: hook.h:49
#define MUTT_CLOSE_HOOK
close-hook: write to a compressed mailbox
Definition: hook.h:51
#define MUTT_APPEND_HOOK
append-hook: append to a compressed mailbox
Definition: hook.h:50
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
struct Expando * cmd_open
open-hook command
Definition: lib.h:61
struct Expando * cmd_append
append-hook command
Definition: lib.h:59
struct Expando * cmd_close
close-hook command
Definition: lib.h:60
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compress_info_free()

static void compress_info_free ( struct Mailbox m)
static

Frees the compress info members and structure.

Parameters
mMailbox to free compress_info for

Definition at line 269 of file compress.c.

270{
271 if (!m || !m->compress_info)
272 return;
273
274 struct CompressInfo *ci = m->compress_info;
278
280
281 FREE(&m->compress_info);
282}
static void unlock_realpath(struct Mailbox *m)
Unlock the mailbox->realpath.
Definition: compress.c:148
void expando_free(struct Expando **ptr)
Free an Expando object.
Definition: expando.c:54
#define FREE(x)
Definition: memory.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ execute_command()

static bool execute_command ( struct Mailbox m,
const struct Expando exp,
const char *  progress 
)
static

Run a system command.

Parameters
mMailbox to work with
expCommand expando to execute
progressMessage to show the user
Return values
trueSuccess
falseFailure

Run the supplied command, taking care of all the NeoMutt requirements, such as locking files and blocking signals.

Definition at line 323 of file compress.c.

324{
325 if (!m || !exp || !progress)
326 return false;
327
328 if (m->verbose)
329 mutt_message(progress, m->realpath);
330
331 bool rc = true;
332 struct Buffer *sys_cmd = buf_pool_get();
333 buf_alloc(sys_cmd, STR_COMMAND);
334
336 mutt_endwin();
337 fflush(stdout);
338
339 expando_render(exp, CompressRenderData, m, MUTT_FORMAT_NO_FLAGS, sys_cmd->dsize, sys_cmd);
340
341 if (mutt_system(buf_string(sys_cmd)) != 0)
342 {
343 rc = false;
345 mutt_error(_("Error running \"%s\""), buf_string(sys_cmd));
346 }
347
349
350 buf_pool_release(&sys_cmd);
351 return rc;
352}
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:337
const struct ExpandoRenderData CompressRenderData[]
Callbacks for Compression Hook Expandos.
Definition: compress.c:59
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:173
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:151
int expando_render(const struct Expando *exp, const struct ExpandoRenderData *rdata, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Render an Expando + data into a string.
Definition: expando.c:109
#define mutt_message(...)
Definition: logging2.h:91
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:52
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: render.h:33
void mutt_sig_block(void)
Block signals during critical operations.
Definition: signal.c:212
void mutt_sig_unblock(void)
Restore previously blocked signals.
Definition: signal.c:230
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:35
size_t dsize
Length of data.
Definition: buffer.h:39
bool verbose
Display status messages?
Definition: mailbox.h:117
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_comp_can_append()

bool mutt_comp_can_append ( struct Mailbox m)

Can we append to this path?

Parameters
mMailbox
Return values
trueYes, we can append to the file
falseNo, appending isn't possible

To append to a file we can either use an 'append-hook' or a combination of 'open-hook' and 'close-hook'.

A match means it's our responsibility to append to the file.

Definition at line 365 of file compress.c.

366{
367 if (!m)
368 return false;
369
370 /* If this succeeds, we know there's an open-hook */
371 struct CompressInfo *ci = set_compress_info(m);
372 if (!ci)
373 return false;
374
375 /* We have an open-hook, so to append we need an append-hook,
376 * or a close-hook. */
377 if (ci->cmd_append || ci->cmd_close)
378 return true;
379
380 mutt_error(_("Can't append without an append-hook or close-hook : %s"), mailbox_path(m));
381 return false;
382}
static struct CompressInfo * set_compress_info(struct Mailbox *m)
Find the compress hooks for a mailbox.
Definition: compress.c:239
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_comp_can_read()

bool mutt_comp_can_read ( const char *  path)

Can we read from this file?

Parameters
pathPathname of file to be tested
Return values
trueYes, we can read the file
falseNo, we can't read the file

Search for an 'open-hook' with a regex that matches the path.

A match means it's our responsibility to open the file.

Definition at line 394 of file compress.c.

395{
396 if (!path)
397 return false;
398
400 return true;
401
402 return false;
403}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_comp_valid_command()

int mutt_comp_valid_command ( const char *  cmd)

Is this command string allowed?

Parameters
cmdCommand string
Return values
1Valid command
0"%f" and/or "%t" is missing

A valid command string must have both "%f" (from file) and "%t" (to file). We don't check if we can actually run the command.

Definition at line 414 of file compress.c.

415{
416 if (!cmd)
417 return 0;
418
419 return strstr(cmd, "%f") && strstr(cmd, "%t");
420}
+ Here is the caller graph for this function:

Variable Documentation

◆ CompressRenderData

const struct ExpandoRenderData CompressRenderData
Initial value:
= {
{ -1, -1, NULL, NULL },
}
@ ED_CMP_FROM
'from' path
Definition: lib.h:48
@ ED_CMP_TO
'to' path
Definition: lib.h:49
@ ED_COMPRESS
Compress ED_CMP_ ExpandoDataCompress.
Definition: domain.h:40
void compress_f(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Compress: From filename - Implements ExpandoRenderData::get_string() -.
Definition: compress.c:287
void compress_t(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Compress: To filename - Implements ExpandoRenderData::get_string() -.
Definition: compress.c:301

Callbacks for Compression Hook Expandos.

See also
CompressFormatDef, ExpandoDataCompress

Definition at line 59 of file compress.c.

◆ CompCommands

const struct Command CompCommands[]
static
Initial value:
= {
{ "append-hook", mutt_parse_hook, MUTT_APPEND_HOOK },
{ "close-hook", mutt_parse_hook, MUTT_CLOSE_HOOK },
{ "open-hook", mutt_parse_hook, MUTT_OPEN_HOOK },
}
enum CommandResult mutt_parse_hook(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'hook' family of commands - Implements Command::parse() -.
Definition: hook.c:167

Compression Commands.

Definition at line 64 of file compress.c.

◆ CompressFormatDef

const struct ExpandoDefinition CompressFormatDef[]
Initial value:
= {
{ "f", "from", ED_COMPRESS, ED_CMP_FROM, E_TYPE_STRING, NULL },
{ "t", "to", ED_COMPRESS, ED_CMP_TO, E_TYPE_STRING, NULL },
{ NULL, NULL, 0, -1, -1, NULL }
}
@ E_TYPE_STRING
Data is a string.
Definition: definition.h:37

Expando definitions.

Config:

  • append-hook
  • close-hook
  • open-hook

Definition at line 80 of file compress.c.