NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
compress.c File Reference
#include "config.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mutt/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.

Functions

void mutt_comp_init (void)
 Setup feature commands. More...
 
static bool lock_realpath (struct Mailbox *m, bool excl)
 Try to lock the ctx->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, char *buf, size_t buflen)
 Prompt and validate new messages tags - Implements MxOps::tags_edit() More...
 
static int comp_tags_commit (struct Mailbox *m, struct Email *e, 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...
 

Variables

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

Detailed Description

Compressed mbox local mailbox type

Authors
  • 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 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 66 of file compress.c.

67 {
69 }
+ Here is the caller graph for this function:

◆ lock_realpath()

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

Try to lock the ctx->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 82 of file compress.c.

83 {
84  if (!m || !m->compress_info)
85  return false;
86 
87  struct CompressInfo *ci = m->compress_info;
88 
89  if (ci->locked)
90  return true;
91 
92  if (excl)
93  ci->fp_lock = fopen(m->realpath, "a");
94  else
95  ci->fp_lock = fopen(m->realpath, "r");
96  if (!ci->fp_lock)
97  {
99  return false;
100  }
101 
102  int r = mutt_file_lock(fileno(ci->fp_lock), excl, true);
103  if (r == 0)
104  ci->locked = true;
105  else if (excl)
106  {
108  m->readonly = true;
109  return true;
110  }
111 
112  return r == 0;
113 }
+ 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 121 of file compress.c.

122 {
123  if (!m || !m->compress_info)
124  return;
125 
126  struct CompressInfo *ci = m->compress_info;
127 
128  if (!ci->locked)
129  return;
130 
131  mutt_file_unlock(fileno(ci->fp_lock));
132 
133  ci->locked = false;
135 }
+ 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 147 of file compress.c.

148 {
149  if (!m)
150  return -1;
151 
152  /* Setup the right paths */
154 
155  /* We will uncompress to TMPDIR */
156  struct Buffer *buf = mutt_buffer_pool_get();
157  mutt_buffer_mktemp(buf);
158  mutt_buffer_copy(&m->pathbuf, buf);
160 
161  FILE *fp = mutt_file_fopen(mailbox_path(m), "w");
162  if (!fp)
163  return -1;
164 
165  mutt_file_fclose(&fp);
166  return 0;
167 }
+ 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 175 of file compress.c.

176 {
177  if (!m || !m->compress_info)
178  return;
179 
180  struct CompressInfo *ci = m->compress_info;
181 
182  ci->size = mutt_file_get_size(m->realpath);
183 }
+ 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 193 of file compress.c.

194 {
195  if (!m)
196  return NULL;
197 
198  if (m->compress_info)
199  return m->compress_info;
200 
201  /* Open is compulsory */
202  const char *o = mutt_find_hook(MUTT_OPEN_HOOK, mailbox_path(m));
203  if (!o)
204  return NULL;
205 
206  const char *c = mutt_find_hook(MUTT_CLOSE_HOOK, mailbox_path(m));
207  const char *a = mutt_find_hook(MUTT_APPEND_HOOK, mailbox_path(m));
208 
209  struct CompressInfo *ci = mutt_mem_calloc(1, sizeof(struct CompressInfo));
210  m->compress_info = ci;
211 
212  ci->cmd_open = mutt_str_dup(o);
213  ci->cmd_close = mutt_str_dup(c);
214  ci->cmd_append = mutt_str_dup(a);
215 
216  return ci;
217 }
+ 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 223 of file compress.c.

224 {
225  if (!m || !m->compress_info)
226  return;
227 
228  struct CompressInfo *ci = m->compress_info;
229  FREE(&ci->cmd_open);
230  FREE(&ci->cmd_close);
231  FREE(&ci->cmd_append);
232 
233  unlock_realpath(m);
234 
235  FREE(&m->compress_info);
236 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compress_format_str()

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 
)
static

Expand the filenames in a command string - Implements format_t.

Expando Description
%f Compressed file
%t Plaintext, temporary file

Definition at line 246 of file compress.c.

250 {
251  if (!buf || (data == 0))
252  return src;
253 
254  struct Mailbox *m = (struct Mailbox *) data;
255 
256  /* NOTE the compressed file config vars expect %f and %t to be
257  * surrounded by '' (unlike other NeoMutt config vars, which add the
258  * outer quotes for the user). This is why we use the
259  * mutt_buffer_quote_filename() form with add_outer of false. */
260  struct Buffer *quoted = mutt_buffer_pool_get();
261  switch (op)
262  {
263  case 'f':
264  /* Compressed file */
265  mutt_buffer_quote_filename(quoted, m->realpath, false);
266  snprintf(buf, buflen, "%s", mutt_buffer_string(quoted));
267  break;
268  case 't':
269  /* Plaintext, temporary file */
270  mutt_buffer_quote_filename(quoted, mailbox_path(m), false);
271  snprintf(buf, buflen, "%s", mutt_buffer_string(quoted));
272  break;
273  }
274 
275  mutt_buffer_pool_release(&quoted);
276  return src;
277 }
+ 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 
)
static

Expand placeholders in command string.

Parameters
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'

Definition at line 296 of file compress.c.

297 {
298  if (!m || !cmd || !buf)
299  return;
300 
301  mutt_expando_format(buf, buflen, 0, buflen, cmd, compress_format_str,
302  (intptr_t) m, MUTT_FORMAT_NO_FLAGS);
303 }
+ 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 
)
static

Run a system command.

Parameters
mMailbox to work with
commandCommand string to execute
progressMessage to show the user
Return values
1Success
0Failure

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

Definition at line 316 of file compress.c.

317 {
318  if (!m || !command || !progress)
319  return 0;
320 
321  if (m->verbose)
322  mutt_message(progress, m->realpath);
323 
324  int rc = 1;
325  char sys_cmd[STR_COMMAND];
326 
327  mutt_sig_block();
328  endwin();
329  fflush(stdout);
330 
331  expand_command_str(m, command, sys_cmd, sizeof(sys_cmd));
332 
333  if (mutt_system(sys_cmd) != 0)
334  {
335  rc = 0;
337  mutt_error(_("Error running \"%s\""), sys_cmd);
338  }
339 
341 
342  return rc;
343 }
+ 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 356 of file compress.c.

357 {
358  if (!m)
359  return false;
360 
361  /* If this succeeds, we know there's an open-hook */
362  struct CompressInfo *ci = set_compress_info(m);
363  if (!ci)
364  return false;
365 
366  /* We have an open-hook, so to append we need an append-hook,
367  * or a close-hook. */
368  if (ci->cmd_append || ci->cmd_close)
369  return true;
370 
371  mutt_error(_("Can't append without an append-hook or close-hook : %s"), mailbox_path(m));
372  return false;
373 }
+ 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 385 of file compress.c.

386 {
387  if (!path)
388  return false;
389 
390  if (mutt_find_hook(MUTT_OPEN_HOOK, path))
391  return true;
392 
393  return false;
394 }
+ 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 405 of file compress.c.

406 {
407  if (!cmd)
408  return 0;
409 
410  return strstr(cmd, "%f") && strstr(cmd, "%t");
411 }
+ Here is the caller graph for this function:

◆ comp_ac_owns_path()

static bool comp_ac_owns_path ( struct Account a,
const char *  path 
)
static

Check whether an Account owns a Mailbox path - Implements MxOps::ac_owns_path()

Definition at line 416 of file compress.c.

417 {
418  return false;
419 }

◆ comp_ac_add()

static bool comp_ac_add ( struct Account a,
struct Mailbox m 
)
static

Add a Mailbox to an Account - Implements MxOps::ac_add()

Definition at line 424 of file compress.c.

425 {
426  return true;
427 }

◆ comp_mbox_open()

static enum MxOpenReturns comp_mbox_open ( struct Mailbox m)
static

Open a Mailbox - Implements MxOps::mbox_open()

Set up a compressed mailbox to be read. Decompress the mailbox and set up the paths and hooks needed. Then determine the type of the mailbox so we can delegate the handling of messages.

Definition at line 437 of file compress.c.

438 {
439  struct CompressInfo *ci = set_compress_info(m);
440  if (!ci)
441  return MX_OPEN_ERROR;
442 
443  /* If there's no close-hook, or the file isn't writable */
444  if (!ci->cmd_close || (access(mailbox_path(m), W_OK) != 0))
445  m->readonly = true;
446 
447  if (setup_paths(m) != 0)
448  goto cmo_fail;
449  store_size(m);
450 
451  if (!lock_realpath(m, false))
452  {
453  mutt_error(_("Unable to lock mailbox"));
454  goto cmo_fail;
455  }
456 
457  int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
458  if (rc == 0)
459  goto cmo_fail;
460 
461  unlock_realpath(m);
462 
464  if (m->type == MUTT_UNKNOWN)
465  {
466  mutt_error(_("Can't identify the contents of the compressed file"));
467  goto cmo_fail;
468  }
469 
470  ci->child_ops = mx_get_ops(m->type);
471  if (!ci->child_ops)
472  {
473  mutt_error(_("Can't find mailbox ops for mailbox type %d"), m->type);
474  goto cmo_fail;
475  }
476 
477  m->account->type = m->type;
478  return ci->child_ops->mbox_open(m);
479 
480 cmo_fail:
481  /* remove the partial uncompressed file */
482  remove(mailbox_path(m));
484  return MX_OPEN_ERROR;
485 }
+ Here is the call graph for this function:

◆ comp_mbox_open_append()

static bool comp_mbox_open_append ( struct Mailbox m,
OpenMailboxFlags  flags 
)
static

Open a Mailbox for appending - Implements MxOps::mbox_open_append()

flags may also contain MUTT_NEWFOLDER

To append to a compressed mailbox we need an append-hook (or both open- and close-hooks).

Definition at line 495 of file compress.c.

496 {
497  /* If this succeeds, we know there's an open-hook */
498  struct CompressInfo *ci = set_compress_info(m);
499  if (!ci)
500  return false;
501 
502  /* To append we need an append-hook or a close-hook */
503  if (!ci->cmd_append && !ci->cmd_close)
504  {
505  mutt_error(_("Can't append without an append-hook or close-hook : %s"),
506  mailbox_path(m));
507  goto cmoa_fail1;
508  }
509 
510  if (setup_paths(m) != 0)
511  goto cmoa_fail2;
512 
513  /* Lock the realpath for the duration of the append.
514  * It will be unlocked in the close */
515  if (!lock_realpath(m, true))
516  {
517  mutt_error(_("Unable to lock mailbox"));
518  goto cmoa_fail2;
519  }
520 
521  /* Open the existing mailbox, unless we are appending */
522  if (!ci->cmd_append && (mutt_file_get_size(m->realpath) > 0))
523  {
524  int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
525  if (rc == 0)
526  {
527  mutt_error(_("Compress command failed: %s"), ci->cmd_open);
528  goto cmoa_fail2;
529  }
531  }
532  else
533  m->type = C_MboxType;
534 
535  /* We can only deal with mbox and mmdf mailboxes */
536  if ((m->type != MUTT_MBOX) && (m->type != MUTT_MMDF))
537  {
538  mutt_error(_("Unsupported mailbox type for appending"));
539  goto cmoa_fail2;
540  }
541 
542  ci->child_ops = mx_get_ops(m->type);
543  if (!ci->child_ops)
544  {
545  mutt_error(_("Can't find mailbox ops for mailbox type %d"), m->type);
546  goto cmoa_fail2;
547  }
548 
549  if (!ci->child_ops->mbox_open_append(m, flags))
550  goto cmoa_fail2;
551 
552  return true;
553 
554 cmoa_fail2:
555  /* remove the partial uncompressed file */
556  remove(mailbox_path(m));
557 cmoa_fail1:
558  /* Free the compress_info to prevent close from trying to recompress */
560 
561  return false;
562 }
+ Here is the call graph for this function:

◆ comp_mbox_check()

static enum MxStatus comp_mbox_check ( struct Mailbox m)
static

Check for new mail - Implements MxOps::mbox_check()

Parameters
mMailbox
Return values
enumMxStatus

If the compressed file changes in size but the mailbox hasn't been changed in NeoMutt, then we can close and reopen the mailbox.

If the mailbox has been changed in NeoMutt, warn the user.

Definition at line 574 of file compress.c.

575 {
576  if (!m->compress_info)
577  return MX_STATUS_ERROR;
578 
579  struct CompressInfo *ci = m->compress_info;
580 
581  const struct MxOps *ops = ci->child_ops;
582  if (!ops)
583  return MX_STATUS_ERROR;
584 
585  int size = mutt_file_get_size(m->realpath);
586  if (size == ci->size)
587  return MX_STATUS_OK;
588 
589  if (!lock_realpath(m, false))
590  {
591  mutt_error(_("Unable to lock mailbox"));
592  return MX_STATUS_ERROR;
593  }
594 
595  int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
596  store_size(m);
597  unlock_realpath(m);
598  if (rc == 0)
599  return MX_STATUS_ERROR;
600 
601  return ops->mbox_check(m);
602 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ comp_mbox_sync()

static enum MxStatus comp_mbox_sync ( struct Mailbox m)
static

Save changes to the Mailbox - Implements MxOps::mbox_sync()

Changes in NeoMutt only affect the tmp file. Calling comp_mbox_sync() will commit them to the compressed file.

Definition at line 610 of file compress.c.

611 {
612  if (!m->compress_info)
613  return MX_STATUS_ERROR;
614 
615  struct CompressInfo *ci = m->compress_info;
616 
617  if (!ci->cmd_close)
618  {
619  mutt_error(_("Can't sync a compressed file without a close-hook"));
620  return MX_STATUS_ERROR;
621  }
622 
623  const struct MxOps *ops = ci->child_ops;
624  if (!ops)
625  return MX_STATUS_ERROR;
626 
627  if (!lock_realpath(m, true))
628  {
629  mutt_error(_("Unable to lock mailbox"));
630  return MX_STATUS_ERROR;
631  }
632 
633  enum MxStatus check = comp_mbox_check(m);
634  if (check != MX_STATUS_OK)
635  goto sync_cleanup;
636 
637  check = ops->mbox_sync(m);
638  if (check != MX_STATUS_OK)
639  goto sync_cleanup;
640 
641  int rc = execute_command(m, ci->cmd_close, _("Compressing %s"));
642  if (rc == 0)
643  {
644  check = MX_STATUS_ERROR;
645  goto sync_cleanup;
646  }
647 
648  check = MX_STATUS_OK;
649 
650 sync_cleanup:
651  store_size(m);
652  unlock_realpath(m);
653  return check;
654 }
+ Here is the call graph for this function:

◆ comp_mbox_close()

static enum MxStatus comp_mbox_close ( struct Mailbox m)
static

Close a Mailbox - Implements MxOps::mbox_close()

If the mailbox has been changed then re-compress the tmp file. Then delete the tmp file.

Definition at line 662 of file compress.c.

663 {
664  if (!m->compress_info)
665  return MX_STATUS_ERROR;
666 
667  struct CompressInfo *ci = m->compress_info;
668 
669  const struct MxOps *ops = ci->child_ops;
670  if (!ops)
671  {
673  return MX_STATUS_ERROR;
674  }
675 
676  ops->mbox_close(m);
677 
678  /* sync has already been called, so we only need to delete some files */
679  if (m->append)
680  {
681  const char *append = NULL;
682  const char *msg = NULL;
683 
684  /* The file exists and we can append */
685  if ((access(m->realpath, F_OK) == 0) && ci->cmd_append)
686  {
687  append = ci->cmd_append;
688  msg = _("Compressed-appending to %s...");
689  }
690  else
691  {
692  append = ci->cmd_close;
693  msg = _("Compressing %s");
694  }
695 
696  int rc = execute_command(m, append, msg);
697  if (rc == 0)
698  {
700  mutt_error(_("Error. Preserving temporary file: %s"), mailbox_path(m));
701  }
702  else
703  remove(mailbox_path(m));
704 
705  unlock_realpath(m);
706  }
707  else
708  {
709  /* If the file was removed, remove the compressed folder too */
710  if ((access(mailbox_path(m), F_OK) != 0) && !C_SaveEmpty)
711  {
712  remove(m->realpath);
713  }
714  else
715  {
716  remove(mailbox_path(m));
717  }
718  }
719 
721 
722  return MX_STATUS_OK;
723 }
+ Here is the call graph for this function:

◆ comp_msg_open()

static bool comp_msg_open ( struct Mailbox m,
struct Message msg,
int  msgno 
)
static

Open an email message in a Mailbox - Implements MxOps::msg_open()

Definition at line 728 of file compress.c.

729 {
730  if (!m->compress_info)
731  return false;
732 
733  struct CompressInfo *ci = m->compress_info;
734 
735  const struct MxOps *ops = ci->child_ops;
736  if (!ops)
737  return false;
738 
739  /* Delegate */
740  return ops->msg_open(m, msg, msgno);
741 }

◆ comp_msg_open_new()

static bool comp_msg_open_new ( struct Mailbox m,
struct Message msg,
const struct Email e 
)
static

Open a new message in a Mailbox - Implements MxOps::msg_open_new()

Definition at line 746 of file compress.c.

747 {
748  if (!m->compress_info)
749  return false;
750 
751  struct CompressInfo *ci = m->compress_info;
752 
753  const struct MxOps *ops = ci->child_ops;
754  if (!ops)
755  return false;
756 
757  /* Delegate */
758  return ops->msg_open_new(m, msg, e);
759 }

◆ comp_msg_commit()

static int comp_msg_commit ( struct Mailbox m,
struct Message msg 
)
static

Save changes to an email - Implements MxOps::msg_commit()

Definition at line 764 of file compress.c.

765 {
766  if (!m->compress_info)
767  return -1;
768 
769  struct CompressInfo *ci = m->compress_info;
770 
771  const struct MxOps *ops = ci->child_ops;
772  if (!ops)
773  return -1;
774 
775  /* Delegate */
776  return ops->msg_commit(m, msg);
777 }

◆ comp_msg_close()

static int comp_msg_close ( struct Mailbox m,
struct Message msg 
)
static

Close an email - Implements MxOps::msg_close()

Definition at line 782 of file compress.c.

783 {
784  if (!m->compress_info)
785  return -1;
786 
787  struct CompressInfo *ci = m->compress_info;
788 
789  const struct MxOps *ops = ci->child_ops;
790  if (!ops)
791  return -1;
792 
793  /* Delegate */
794  return ops->msg_close(m, msg);
795 }

◆ comp_msg_padding_size()

static int comp_msg_padding_size ( struct Mailbox m)
static

Bytes of padding between messages - Implements MxOps::msg_padding_size()

Definition at line 800 of file compress.c.

801 {
802  if (!m->compress_info)
803  return 0;
804 
805  struct CompressInfo *ci = m->compress_info;
806 
807  const struct MxOps *ops = ci->child_ops;
808  if (!ops || !ops->msg_padding_size)
809  return 0;
810 
811  return ops->msg_padding_size(m);
812 }

◆ comp_msg_save_hcache()

static int comp_msg_save_hcache ( struct Mailbox m,
struct Email e 
)
static

Save message to the header cache - Implements MxOps::msg_save_hcache()

Definition at line 817 of file compress.c.

818 {
819  if (!m->compress_info)
820  return 0;
821 
822  struct CompressInfo *ci = m->compress_info;
823 
824  const struct MxOps *ops = ci->child_ops;
825  if (!ops || !ops->msg_save_hcache)
826  return 0;
827 
828  return ops->msg_save_hcache(m, e);
829 }

◆ comp_tags_edit()

static int comp_tags_edit ( struct Mailbox m,
const char *  tags,
char *  buf,
size_t  buflen 
)
static

Prompt and validate new messages tags - Implements MxOps::tags_edit()

Definition at line 834 of file compress.c.

835 {
836  if (!m->compress_info)
837  return 0;
838 
839  struct CompressInfo *ci = m->compress_info;
840 
841  const struct MxOps *ops = ci->child_ops;
842  if (!ops || !ops->tags_edit)
843  return 0;
844 
845  return ops->tags_edit(m, tags, buf, buflen);
846 }

◆ comp_tags_commit()

static int comp_tags_commit ( struct Mailbox m,
struct Email e,
char *  buf 
)
static

Save the tags to a message - Implements MxOps::tags_commit()

Definition at line 851 of file compress.c.

852 {
853  if (!m->compress_info)
854  return 0;
855 
856  struct CompressInfo *ci = m->compress_info;
857 
858  const struct MxOps *ops = ci->child_ops;
859  if (!ops || !ops->tags_commit)
860  return 0;
861 
862  return ops->tags_commit(m, e, buf);
863 }

◆ comp_path_probe()

static enum MailboxType comp_path_probe ( const char *  path,
const struct stat *  st 
)
static

Is this a compressed Mailbox? - Implements MxOps::path_probe()

Definition at line 868 of file compress.c.

869 {
870  if (!st || !S_ISREG(st->st_mode))
871  return MUTT_UNKNOWN;
872 
873  if (mutt_comp_can_read(path))
874  return MUTT_COMPRESSED;
875 
876  return MUTT_UNKNOWN;
877 }
+ Here is the call graph for this function:

◆ comp_path_canon()

static int comp_path_canon ( char *  buf,
size_t  buflen 
)
static

Canonicalise a Mailbox path - Implements MxOps::path_canon()

Definition at line 882 of file compress.c.

883 {
884  mutt_path_canon(buf, buflen, HomeDir, false);
885  return 0;
886 }
+ Here is the call graph for this function:

◆ comp_path_pretty()

static int comp_path_pretty ( char *  buf,
size_t  buflen,
const char *  folder 
)
static

Abbreviate a Mailbox path - Implements MxOps::path_pretty()

Definition at line 891 of file compress.c.

892 {
893  if (mutt_path_abbr_folder(buf, buflen, folder))
894  return 0;
895 
896  if (mutt_path_pretty(buf, buflen, HomeDir, false))
897  return 0;
898 
899  return -1;
900 }
+ Here is the call graph for this function:

◆ comp_path_parent()

static int comp_path_parent ( char *  buf,
size_t  buflen 
)
static

Find the parent of a Mailbox path - Implements MxOps::path_parent()

Definition at line 905 of file compress.c.

906 {
907  if (mutt_path_parent(buf, buflen))
908  return 0;
909 
910  if (buf[0] == '~')
911  mutt_path_canon(buf, buflen, HomeDir, false);
912 
913  if (mutt_path_parent(buf, buflen))
914  return 0;
915 
916  return -1;
917 }
+ Here is the call graph for this function:

Variable Documentation

◆ comp_commands

const struct Command comp_commands[]
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 },
}

Definition at line 55 of file compress.c.

◆ MxCompOps

struct MxOps MxCompOps
Initial value:
= {
.type = MUTT_COMPRESSED,
.name = "compressed",
.is_local = true,
.ac_owns_path = comp_ac_owns_path,
.ac_add = comp_ac_add,
.mbox_open = comp_mbox_open,
.mbox_open_append = comp_mbox_open_append,
.mbox_check = comp_mbox_check,
.mbox_check_stats = NULL,
.mbox_sync = comp_mbox_sync,
.mbox_close = comp_mbox_close,
.msg_open = comp_msg_open,
.msg_open_new = comp_msg_open_new,
.msg_commit = comp_msg_commit,
.msg_close = comp_msg_close,
.msg_padding_size = comp_msg_padding_size,
.msg_save_hcache = comp_msg_save_hcache,
.tags_edit = comp_tags_edit,
.tags_commit = comp_tags_commit,
.path_probe = comp_path_probe,
.path_canon = comp_path_canon,
.path_pretty = comp_path_pretty,
.path_parent = comp_path_parent,
.path_is_empty = NULL,
}

Compressed Mailbox - Implements MxOps.

Compress only uses open, close and check. The message functions are delegated to mbox.

Definition at line 926 of file compress.c.

MxOps::msg_padding_size
int(* msg_padding_size)(struct Mailbox *m)
Bytes of padding between messages.
Definition: mx.h:274
unlock_realpath
static void unlock_realpath(struct Mailbox *m)
Unlock the mailbox->realpath.
Definition: compress.c:121
mutt_file_lock
int mutt_file_lock(int fd, bool excl, bool timeout)
(try to) lock a file using fcntl()
Definition: file.c:1175
C_SaveEmpty
WHERE bool C_SaveEmpty
Config: (mbox,mmdf) Preserve empty mailboxes.
Definition: mutt_globals.h:158
comp_path_pretty
static int comp_path_pretty(char *buf, size_t buflen, const char *folder)
Abbreviate a Mailbox path - Implements MxOps::path_pretty()
Definition: compress.c:891
CompressInfo::cmd_close
const char * cmd_close
close-hook command
Definition: lib.h:51
compress_info_free
static void compress_info_free(struct Mailbox *m)
Frees the compress info members and structure.
Definition: compress.c:223
MUTT_MMDF
@ MUTT_MMDF
'mmdf' Mailbox type
Definition: mailbox.h:49
comp_mbox_open_append
static bool comp_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a Mailbox for appending - Implements MxOps::mbox_open_append()
Definition: compress.c:495
MxStatus
MxStatus
Return values from mx_mbox_check(), mx_mbox_sync(), and mx_mbox_close()
Definition: mx.h:71
comp_path_parent
static int comp_path_parent(char *buf, size_t buflen)
Find the parent of a Mailbox path - Implements MxOps::path_parent()
Definition: compress.c:905
mutt_mem_calloc
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
MxOps::tags_edit
int(* tags_edit)(struct Mailbox *m, const char *tags, char *buf, size_t buflen)
Prompt and validate new messages tags.
Definition: mx.h:303
_
#define _(a)
Definition: message.h:28
Mailbox
A mailbox.
Definition: mailbox.h:81
lock_realpath
static bool lock_realpath(struct Mailbox *m, bool excl)
Try to lock the ctx->realpath.
Definition: compress.c:82
MxOps::mbox_sync
enum MxStatus(* mbox_sync)(struct Mailbox *m)
Save changes to the Mailbox.
Definition: mx.h:199
mutt_system
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
Mailbox::append
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:113
MxOps::msg_open_new
bool(* msg_open_new)(struct Mailbox *m, struct Message *msg, const struct Email *e)
Open a new message in a Mailbox.
Definition: mx.h:238
Buffer
String manipulation buffer.
Definition: buffer.h:33
comp_path_probe
static enum MailboxType comp_path_probe(const char *path, const struct stat *st)
Is this a compressed Mailbox? - Implements MxOps::path_probe()
Definition: compress.c:868
mutt_path_abbr_folder
bool mutt_path_abbr_folder(char *buf, size_t buflen, const char *folder)
Create a folder abbreviation.
Definition: path.c:492
Account::type
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
mutt_sig_unblock
void mutt_sig_unblock(void)
Restore previously blocked signals.
Definition: signal.c:168
MxOps::msg_save_hcache
int(* msg_save_hcache)(struct Mailbox *m, struct Email *e)
Save message to the header cache.
Definition: mx.h:287
mutt_file_fclose
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
mutt_sig_block
void mutt_sig_block(void)
Block signals during critical operations.
Definition: signal.c:150
CompressInfo
Private data for compress.
Definition: lib.h:48
MxOps::msg_close
int(* msg_close)(struct Mailbox *m, struct Message *msg)
Close an email.
Definition: mx.h:264
mutt_buffer_mktemp
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
MxOps
The Mailbox API.
Definition: mx.h:116
CompressInfo::cmd_open
const char * cmd_open
open-hook command
Definition: lib.h:52
mutt_str_dup
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
mutt_file_fopen
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
FREE
#define FREE(x)
Definition: memory.h:40
mutt_perror
#define mutt_perror(...)
Definition: logging.h:85
mutt_path_canon
bool mutt_path_canon(char *buf, size_t buflen, const char *homedir, bool is_dir)
Create the canonical version of a path.
Definition: path.c:285
MUTT_APPEND_HOOK
#define MUTT_APPEND_HOOK
append-hook: append to a compressed mailbox
Definition: hook.h:59
comp_msg_commit
static int comp_msg_commit(struct Mailbox *m, struct Message *msg)
Save changes to an email - Implements MxOps::msg_commit()
Definition: compress.c:764
comp_mbox_close
static enum MxStatus comp_mbox_close(struct Mailbox *m)
Close a Mailbox - Implements MxOps::mbox_close()
Definition: compress.c:662
mx_get_ops
const struct MxOps * mx_get_ops(enum MailboxType type)
Get mailbox operations.
Definition: mx.c:147
MUTT_OPEN_HOOK
#define MUTT_OPEN_HOOK
open-hook: to read a compressed mailbox
Definition: hook.h:58
comp_commands
static const struct Command comp_commands[]
Definition: compress.c:55
mutt_buffer_pool_release
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
MUTT_FORMAT_NO_FLAGS
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
mx_path_probe
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1335
comp_msg_padding_size
static int comp_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Implements MxOps::msg_padding_size()
Definition: compress.c:800
mutt_file_get_size
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1495
MUTT_COMPRESSED
@ MUTT_COMPRESSED
Compressed file Mailbox type.
Definition: mailbox.h:56
comp_msg_open
static bool comp_msg_open(struct Mailbox *m, struct Message *msg, int msgno)
Open an email message in a Mailbox - Implements MxOps::msg_open()
Definition: compress.c:728
comp_ac_owns_path
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()
Definition: compress.c:416
mutt_any_key_to_continue
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:605
MUTT_CLOSE_HOOK
#define MUTT_CLOSE_HOOK
close-hook: write to a compressed mailbox
Definition: hook.h:60
comp_tags_commit
static int comp_tags_commit(struct Mailbox *m, struct Email *e, char *buf)
Save the tags to a message - Implements MxOps::tags_commit()
Definition: compress.c:851
MxOps::mbox_open_append
bool(* mbox_open_append)(struct Mailbox *m, OpenMailboxFlags flags)
Open a Mailbox for appending.
Definition: mx.h:168
mutt_buffer_pool_get
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
expand_command_str
static void expand_command_str(const struct Mailbox *m, const char *cmd, char *buf, int buflen)
Expand placeholders in command string.
Definition: compress.c:296
MxOps::mbox_close
enum MxStatus(* mbox_close)(struct Mailbox *m)
Close a Mailbox.
Definition: mx.h:209
store_size
static void store_size(const struct Mailbox *m)
Save the size of the compressed file.
Definition: compress.c:175
Mailbox::type
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
comp_msg_save_hcache
static int comp_msg_save_hcache(struct Mailbox *m, struct Email *e)
Save message to the header cache - Implements MxOps::msg_save_hcache()
Definition: compress.c:817
mutt_buffer_copy
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:445
comp_msg_open_new
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()
Definition: compress.c:746
setup_paths
static int setup_paths(struct Mailbox *m)
Set the mailbox paths.
Definition: compress.c:147
MxOps::msg_commit
int(* msg_commit)(struct Mailbox *m, struct Message *msg)
Save changes to an email.
Definition: mx.h:251
mutt_file_unlock
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1223
Mailbox::account
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:131
MxOps::msg_open
bool(* msg_open)(struct Mailbox *m, struct Message *msg, int msgno)
Open an email message in a Mailbox.
Definition: mx.h:224
MUTT_UNKNOWN
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition: mailbox.h:47
CompressInfo::child_ops
const struct MxOps * child_ops
callbacks of de-compressed file
Definition: lib.h:54
MxOps::tags_commit
int(* tags_commit)(struct Mailbox *m, struct Email *e, char *buf)
Save the tags to a message.
Definition: mx.h:318
mutt_comp_can_read
bool mutt_comp_can_read(const char *path)
Can we read from this file?
Definition: compress.c:385
STR_COMMAND
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:35
execute_command
static int execute_command(struct Mailbox *m, const char *command, const char *progress)
Run a system command.
Definition: compress.c:316
Mailbox::realpath
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
MX_STATUS_ERROR
@ MX_STATUS_ERROR
An error occurred.
Definition: mx.h:73
mutt_find_hook
char * mutt_find_hook(HookFlags type, const char *pat)
Find a matching hook.
Definition: hook.c:553
mutt_buffer_string
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Mailbox::verbose
bool verbose
Display status messages?
Definition: mailbox.h:118
comp_mbox_open
static enum MxOpenReturns comp_mbox_open(struct Mailbox *m)
Open a Mailbox - Implements MxOps::mbox_open()
Definition: compress.c:437
mutt_str_replace
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
CompressInfo::fp_lock
FILE * fp_lock
fp used for locking
Definition: lib.h:56
comp_ac_add
static bool comp_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Implements MxOps::ac_add()
Definition: compress.c:424
comp_path_canon
static int comp_path_canon(char *buf, size_t buflen)
Canonicalise a Mailbox path - Implements MxOps::path_canon()
Definition: compress.c:882
Mailbox::readonly
bool readonly
Don't allow changes to the mailbox.
Definition: mailbox.h:119
comp_msg_close
static int comp_msg_close(struct Mailbox *m, struct Message *msg)
Close an email - Implements MxOps::msg_close()
Definition: compress.c:782
Mailbox::compress_info
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:124
mutt_path_parent
bool mutt_path_parent(char *buf, size_t buflen)
Find the parent of a path.
Definition: path.c:459
HomeDir
char * HomeDir
User's home directory.
Definition: mutt_globals.h:49
mutt_expando_format
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:774
CompressInfo::cmd_append
const char * cmd_append
append-hook command
Definition: lib.h:50
mutt_parse_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:85
comp_mbox_sync
static enum MxStatus comp_mbox_sync(struct Mailbox *m)
Save changes to the Mailbox - Implements MxOps::mbox_sync()
Definition: compress.c:610
compress_format_str
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:246
mailbox_path
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:206
mutt_buffer_quote_filename
void mutt_buffer_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell's quoting rules.
Definition: file.c:836
mutt_path_pretty
bool mutt_path_pretty(char *buf, size_t buflen, const char *homedir, bool is_dir)
Tidy a filesystem path.
Definition: path.c:186
mutt_message
#define mutt_message(...)
Definition: logging.h:83
MX_OPEN_ERROR
@ MX_OPEN_ERROR
Open failed with an error.
Definition: mx.h:87
MxOps::mbox_open
enum MxOpenReturns(* mbox_open)(struct Mailbox *m)
Open a Mailbox.
Definition: mx.h:156
set_compress_info
static struct CompressInfo * set_compress_info(struct Mailbox *m)
Find the compress hooks for a mailbox.
Definition: compress.c:193
comp_mbox_check
static enum MxStatus comp_mbox_check(struct Mailbox *m)
Check for new mail - Implements MxOps::mbox_check()
Definition: compress.c:574
MUTT_MBOX
@ MUTT_MBOX
'mbox' Mailbox type
Definition: mailbox.h:48
COMMANDS_REGISTER
#define COMMANDS_REGISTER(cmds)
Definition: mutt_commands.h:77
C_MboxType
unsigned char C_MboxType
Config: Default type for creating new mailboxes.
Definition: mx.c:90
Mailbox::pathbuf
struct Buffer pathbuf
Definition: mailbox.h:83
CompressInfo::locked
bool locked
if realpath is locked
Definition: lib.h:55
MxOps::mbox_check
enum MxStatus(* mbox_check)(struct Mailbox *m)
Check for new mail.
Definition: mx.h:178
CompressInfo::size
long size
size of the compressed file
Definition: lib.h:53
MX_STATUS_OK
@ MX_STATUS_OK
No changes.
Definition: mx.h:74
comp_tags_edit
static int comp_tags_edit(struct Mailbox *m, const char *tags, char *buf, size_t buflen)
Prompt and validate new messages tags - Implements MxOps::tags_edit()
Definition: compress.c:834
mutt_error
#define mutt_error(...)
Definition: logging.h:84