NeoMutt  2022-04-29-145-g9b6a0e
Teaching an old dog new tricks
compress.c File Reference

Compressed mbox local mailbox type. More...

#include "config.h"
#include <stdbool.h>
#include <stdint.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 "format_flags.h"
#include "hook.h"
#include "mutt_commands.h"
#include "mutt_globals.h"
#include "muttlib.h"
#include "mx.h"
#include "protos.h"
+ Include dependency graph for compress.c:

Go to the source code of this file.


void mutt_comp_init (void)
 Setup feature commands. More...
static bool lock_realpath (struct Mailbox *m, bool excl)
 Try to lock the Mailbox.realpath. More...
static void unlock_realpath (struct Mailbox *m)
 Unlock the mailbox->realpath. More...
static int setup_paths (struct Mailbox *m)
 Set the mailbox paths. More...
static void store_size (const struct Mailbox *m)
 Save the size of the compressed file. More...
static struct CompressInfoset_compress_info (struct Mailbox *m)
 Find the compress hooks for a mailbox. More...
static void compress_info_free (struct Mailbox *m)
 Frees the compress info members and structure. More...
static const char * compress_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Expand the filenames in a command string - Implements format_t -. More...
static void expand_command_str (const struct Mailbox *m, const char *cmd, char *buf, int buflen)
 Expand placeholders in command string. More...
static int execute_command (struct Mailbox *m, const char *command, const char *progress)
 Run a system command. More...
bool mutt_comp_can_append (struct Mailbox *m)
 Can we append to this path? More...
bool mutt_comp_can_read (const char *path)
 Can we read from this file? More...
int mutt_comp_valid_command (const char *cmd)
 Is this command string allowed? More...
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() -. More...
static bool comp_ac_add (struct Account *a, struct Mailbox *m)
 Add a Mailbox to an Account - Implements MxOps::ac_add() -. More...
static enum MxOpenReturns comp_mbox_open (struct Mailbox *m)
 Open a Mailbox - Implements MxOps::mbox_open() -. More...
static bool comp_mbox_open_append (struct Mailbox *m, OpenMailboxFlags flags)
 Open a Mailbox for appending - Implements MxOps::mbox_open_append() -. More...
static enum MxStatus comp_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
static enum MxStatus comp_mbox_sync (struct Mailbox *m)
 Save changes to the Mailbox - Implements MxOps::mbox_sync() -. More...
static enum MxStatus comp_mbox_close (struct Mailbox *m)
 Close a Mailbox - Implements MxOps::mbox_close() -. More...
static bool comp_msg_open (struct Mailbox *m, struct Message *msg, int msgno)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -. More...
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() -. More...
static int comp_msg_commit (struct Mailbox *m, struct Message *msg)
 Save changes to an email - Implements MxOps::msg_commit() -. More...
static int comp_msg_close (struct Mailbox *m, struct Message *msg)
 Close an email - Implements MxOps::msg_close() -. More...
static int comp_msg_padding_size (struct Mailbox *m)
 Bytes of padding between messages - Implements MxOps::msg_padding_size() -. More...
static int comp_msg_save_hcache (struct Mailbox *m, struct Email *e)
 Save message to the header cache - Implements MxOps::msg_save_hcache() -. More...
static int comp_tags_edit (struct Mailbox *m, const char *tags, struct Buffer *buf)
 Prompt and validate new messages tags - Implements MxOps::tags_edit() -. More...
static int comp_tags_commit (struct Mailbox *m, struct Email *e, const char *buf)
 Save the tags to a message - Implements MxOps::tags_commit() -. More...
static enum MailboxType comp_path_probe (const char *path, const struct stat *st)
 Is this a compressed Mailbox? - Implements MxOps::path_probe() -. More...
static int comp_path_canon (char *buf, size_t buflen)
 Canonicalise a Mailbox path - Implements MxOps::path_canon() -. More...
static int comp_path_pretty (char *buf, size_t buflen, const char *folder)
 Abbreviate a Mailbox path - Implements MxOps::path_pretty() -. More...
static int comp_path_parent (char *buf, size_t buflen)
 Find the parent of a Mailbox path - Implements MxOps::path_parent() -. More...


static const struct Command comp_commands []
struct MxOps MxCompOps
 Compressed Mailbox - Implements MxOps -. More...

Detailed Description

Compressed mbox local mailbox type.

  • Alain Penders
  • Richard Russon

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

Definition in file compress.c.

Function Documentation

◆ mutt_comp_init()

void mutt_comp_init ( void  )

Setup feature commands.

Definition at line 70 of file compress.c.

71 {
73 }
static const struct Command comp_commands[]
Definition: compress.c:59
Definition: mutt_commands.h:47
+ Here is the caller graph for this function:

◆ lock_realpath()

static bool lock_realpath ( struct Mailbox m,
bool  excl 

Try to lock the Mailbox.realpath.

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 86 of file compress.c.

87 {
88  if (!m || !m->compress_info)
89  return false;
91  struct CompressInfo *ci = m->compress_info;
93  if (ci->locked)
94  return true;
96  if (excl)
97  ci->fp_lock = fopen(m->realpath, "a");
98  else
99  ci->fp_lock = fopen(m->realpath, "r");
100  if (!ci->fp_lock)
101  {
102  mutt_perror(m->realpath);
103  return false;
104  }
106  int r = mutt_file_lock(fileno(ci->fp_lock), excl, true);
107  if (r == 0)
108  ci->locked = true;
109  else if (excl)
110  {
112  m->readonly = true;
113  return true;
114  }
116  return r == 0;
117 }
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
int mutt_file_lock(int fd, bool excl, bool timeout)
(Try to) Lock a file using fcntl()
Definition: file.c:1231
#define mutt_perror(...)
Definition: logging.h:88
Private data for compress.
Definition: lib.h:47
FILE * fp_lock
fp used for locking
Definition: lib.h:54
bool locked
if realpath is locked
Definition: lib.h:53
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)

Unlock the mailbox->realpath.

mMailbox to unlock

Unlock a mailbox previously locked by lock_mailbox().

Definition at line 125 of file compress.c.

126 {
127  if (!m || !m->compress_info)
128  return;
130  struct CompressInfo *ci = m->compress_info;
132  if (!ci->locked)
133  return;
135  mutt_file_unlock(fileno(ci->fp_lock));
137  ci->locked = false;
139 }
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1279
+ 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)

Set the mailbox paths.

mMailbox to modify
Return values

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 151 of file compress.c.

152 {
153  if (!m)
154  return -1;
156  /* Setup the right paths */
159  /* We will uncompress to TMPDIR */
160  struct Buffer *buf = mutt_buffer_pool_get();
161  mutt_buffer_mktemp(buf);
162  mutt_buffer_copy(&m->pathbuf, buf);
165  FILE *fp = mutt_file_fopen(mailbox_path(m), "w");
166  if (!fp)
167  return -1;
169  mutt_file_fclose(&fp);
170  return 0;
171 }
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:445
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:211
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
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
struct Buffer pathbuf
Path of the Mailbox.
Definition: mailbox.h:80
+ 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)

Save the size of the compressed file.


Save the compressed file size in the compress_info struct.

Definition at line 179 of file compress.c.

180 {
181  if (!m || !m->compress_info)
182  return;
184  struct CompressInfo *ci = m->compress_info;
186  ci->size = mutt_file_get_size(m->realpath);
187 }
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1551
long size
size of the compressed file
Definition: lib.h:51
+ Here is the call graph for this function:

◆ set_compress_info()

static struct CompressInfo* set_compress_info ( struct Mailbox m)

Find the compress hooks for a mailbox.

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

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

Definition at line 197 of file compress.c.

198 {
199  if (!m)
200  return NULL;
202  if (m->compress_info)
203  return m->compress_info;
205  /* Open is compulsory */
206  const char *o = mutt_find_hook(MUTT_OPEN_HOOK, mailbox_path(m));
207  if (!o)
208  return NULL;
210  const char *c = mutt_find_hook(MUTT_CLOSE_HOOK, mailbox_path(m));
211  const char *a = mutt_find_hook(MUTT_APPEND_HOOK, mailbox_path(m));
213  struct CompressInfo *ci = mutt_mem_calloc(1, sizeof(struct CompressInfo));
214  m->compress_info = ci;
216  ci->cmd_open = mutt_str_dup(o);
217  ci->cmd_close = mutt_str_dup(c);
218  ci->cmd_append = mutt_str_dup(a);
220  return ci;
221 }
char * mutt_find_hook(HookFlags type, const char *pat)
Find a matching hook.
Definition: hook.c:631
open-hook: to read a compressed mailbox
Definition: hook.h:51
close-hook: write to a compressed mailbox
Definition: hook.h:53
append-hook: append to a compressed mailbox
Definition: hook.h:52
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
const char * cmd_append
append-hook command
Definition: lib.h:48
const char * cmd_open
open-hook command
Definition: lib.h:50
const char * cmd_close
close-hook command
Definition: lib.h:49
+ 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)

Frees the compress info members and structure.

mMailbox to free compress_info for

Definition at line 227 of file compress.c.

228 {
229  if (!m || !m->compress_info)
230  return;
232  struct CompressInfo *ci = m->compress_info;
233  FREE(&ci->cmd_open);
234  FREE(&ci->cmd_close);
235  FREE(&ci->cmd_append);
237  unlock_realpath(m);
239  FREE(&m->compress_info);
240 }
static void unlock_realpath(struct Mailbox *m)
Unlock the mailbox->realpath.
Definition: compress.c:125
#define FREE(x)
Definition: memory.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ expand_command_str()

static void expand_command_str ( const struct Mailbox m,
const char *  cmd,
char *  buf,
int  buflen 

Expand placeholders in command string.

mMailbox for paths
cmdTemplate command to be expanded
bufBuffer to store the command
buflenSize of the buffer

This function takes a hook command and expands the filename placeholders within it. The function calls mutt_expando_format() to do the replacement which calls our callback function compress_format_str(). e.g.

Template command: gzip -cd 'f' > 't'

Result: gzip -dc '~/mail/abc.gz' > '/tmp/xyz'

See also

Definition at line 302 of file compress.c.

303 {
304  if (!m || !cmd || !buf)
305  return;
307  mutt_expando_format(buf, buflen, 0, buflen, cmd, compress_format_str,
308  (intptr_t) m, MUTT_FORMAT_NO_FLAGS);
309 }
No flags are set.
Definition: format_flags.h:30
static const char * compress_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Expand the filenames in a command string - Implements format_t -.
Definition: compress.c:250
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string -.
Definition: muttlib.c:777
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ execute_command()

static int execute_command ( struct Mailbox m,
const char *  command,
const char *  progress 

Run a system command.

mMailbox to work with
commandCommand string to execute
progressMessage to show the user
Return values

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

Definition at line 322 of file compress.c.

323 {
324  if (!m || !command || !progress)
325  return 0;
327  if (m->verbose)
328  mutt_message(progress, m->realpath);
330  int rc = 1;
331  char sys_cmd[STR_COMMAND];
333  mutt_sig_block();
334  endwin();
335  fflush(stdout);
337  expand_command_str(m, command, sys_cmd, sizeof(sys_cmd));
339  if (mutt_system(sys_cmd) != 0)
340  {
341  rc = 0;
343  mutt_error(_("Error running \"%s\""), sys_cmd);
344  }
348  return rc;
349 }
static void expand_command_str(const struct Mailbox *m, const char *cmd, char *buf, int buflen)
Expand placeholders in command string.
Definition: compress.c:302
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:388
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
#define _(a)
Definition: message.h:28
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
void mutt_sig_block(void)
Block signals during critical operations.
Definition: signal.c:150
void mutt_sig_unblock(void)
Restore previously blocked signals.
Definition: signal.c:168
Enough space for a long command line.
Definition: string2.h:35
bool verbose
Display status messages?
Definition: mailbox.h:115
+ 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?

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 362 of file compress.c.

363 {
364  if (!m)
365  return false;
367  /* If this succeeds, we know there's an open-hook */
368  struct CompressInfo *ci = set_compress_info(m);
369  if (!ci)
370  return false;
372  /* We have an open-hook, so to append we need an append-hook,
373  * or a close-hook. */
374  if (ci->cmd_append || ci->cmd_close)
375  return true;
377  mutt_error(_("Can't append without an append-hook or close-hook : %s"), mailbox_path(m));
378  return false;
379 }
static struct CompressInfo * set_compress_info(struct Mailbox *m)
Find the compress hooks for a mailbox.
Definition: compress.c:197
+ 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?

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 391 of file compress.c.

392 {
393  if (!path)
394  return false;
396  if (mutt_find_hook(MUTT_OPEN_HOOK, path))
397  return true;
399  return false;
400 }
+ Here is the call graph for this function:

◆ mutt_comp_valid_command()

int mutt_comp_valid_command ( const char *  cmd)

Is this command string allowed?

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 411 of file compress.c.

412 {
413  if (!cmd)
414  return 0;
416  return strstr(cmd, "%f") && strstr(cmd, "%t");
417 }

Variable Documentation

◆ comp_commands

const struct Command comp_commands[]
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:126

Definition at line 1 of file compress.c.