NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
compress.c
Go to the documentation of this file.
1 
35 #include "config.h"
36 #include <stdbool.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <sys/stat.h>
40 #include <unistd.h>
41 #include "mutt/lib.h"
42 #include "core/lib.h"
43 #include "gui/lib.h"
44 #include "lib.h"
45 #include "format_flags.h"
46 #include "hook.h"
47 #include "mutt_commands.h"
48 #include "mutt_globals.h"
49 #include "muttlib.h"
50 #include "mx.h"
51 #include "protos.h"
52 
53 struct Email;
54 
55 static const struct Command comp_commands[] = {
56  // clang-format off
57  { "append-hook", mutt_parse_hook, MUTT_APPEND_HOOK },
58  { "close-hook", mutt_parse_hook, MUTT_CLOSE_HOOK },
59  { "open-hook", mutt_parse_hook, MUTT_OPEN_HOOK },
60  // clang-format on
61 };
62 
66 void mutt_comp_init(void)
67 {
69 }
70 
82 static bool lock_realpath(struct Mailbox *m, bool excl)
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 }
114 
121 static void unlock_realpath(struct Mailbox *m)
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 }
136 
147 static int setup_paths(struct Mailbox *m)
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 }
168 
175 static void store_size(const struct Mailbox *m)
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 }
184 
193 static struct CompressInfo *set_compress_info(struct Mailbox *m)
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 }
218 
223 static void compress_info_free(struct Mailbox *m)
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 }
237 
246 static const char *compress_format_str(char *buf, size_t buflen, size_t col, int cols,
247  char op, const char *src, const char *prec,
248  const char *if_str, const char *else_str,
249  intptr_t data, MuttFormatFlags flags)
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 }
278 
296 static void expand_command_str(const struct Mailbox *m, const char *cmd, char *buf, int buflen)
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 }
304 
316 static int execute_command(struct Mailbox *m, const char *command, const char *progress)
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 }
344 
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 }
374 
385 bool mutt_comp_can_read(const char *path)
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 }
395 
405 int mutt_comp_valid_command(const char *cmd)
406 {
407  if (!cmd)
408  return 0;
409 
410  return strstr(cmd, "%f") && strstr(cmd, "%t");
411 }
412 
416 static bool comp_ac_owns_path(struct Account *a, const char *path)
417 {
418  return false;
419 }
420 
424 static bool comp_ac_add(struct Account *a, struct Mailbox *m)
425 {
426  return true;
427 }
428 
437 static enum MxOpenReturns comp_mbox_open(struct Mailbox *m)
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 }
486 
495 static bool comp_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
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 }
563 
574 static enum MxStatus comp_mbox_check(struct Mailbox *m)
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 }
603 
610 static enum MxStatus comp_mbox_sync(struct Mailbox *m)
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 }
655 
662 static enum MxStatus comp_mbox_close(struct Mailbox *m)
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 }
724 
728 static bool comp_msg_open(struct Mailbox *m, struct Message *msg, int msgno)
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 }
742 
746 static bool comp_msg_open_new(struct Mailbox *m, struct Message *msg, const struct Email *e)
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 }
760 
764 static int comp_msg_commit(struct Mailbox *m, struct Message *msg)
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 }
778 
782 static int comp_msg_close(struct Mailbox *m, struct Message *msg)
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 }
796 
800 static int comp_msg_padding_size(struct Mailbox *m)
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 }
813 
817 static int comp_msg_save_hcache(struct Mailbox *m, struct Email *e)
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 }
830 
834 static int comp_tags_edit(struct Mailbox *m, const char *tags, char *buf, size_t buflen)
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 }
847 
851 static int comp_tags_commit(struct Mailbox *m, struct Email *e, char *buf)
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 }
864 
868 static enum MailboxType comp_path_probe(const char *path, const struct stat *st)
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 }
878 
882 static int comp_path_canon(char *buf, size_t buflen)
883 {
884  mutt_path_canon(buf, buflen, HomeDir, false);
885  return 0;
886 }
887 
891 static int comp_path_pretty(char *buf, size_t buflen, const char *folder)
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 }
901 
905 static int comp_path_parent(char *buf, size_t buflen)
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 }
918 
919 // clang-format off
926 struct MxOps MxCompOps = {
928  .name = "compressed",
929  .is_local = true,
930  .ac_owns_path = comp_ac_owns_path,
931  .ac_add = comp_ac_add,
932  .mbox_open = comp_mbox_open,
933  .mbox_open_append = comp_mbox_open_append,
934  .mbox_check = comp_mbox_check,
935  .mbox_check_stats = NULL,
936  .mbox_sync = comp_mbox_sync,
937  .mbox_close = comp_mbox_close,
938  .msg_open = comp_msg_open,
939  .msg_open_new = comp_msg_open_new,
940  .msg_commit = comp_msg_commit,
941  .msg_close = comp_msg_close,
942  .msg_padding_size = comp_msg_padding_size,
943  .msg_save_hcache = comp_msg_save_hcache,
944  .tags_edit = comp_tags_edit,
945  .tags_commit = comp_tags_commit,
946  .path_probe = comp_path_probe,
947  .path_canon = comp_path_canon,
948  .path_pretty = comp_path_pretty,
949  .path_parent = comp_path_parent,
950  .path_is_empty = NULL,
951 };
952 // clang-format on
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
MxOps::type
enum MailboxType type
Mailbox type, e.g. MUTT_IMAP.
Definition: mx.h:118
_
#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
format_flags.h
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
MxOpenReturns
MxOpenReturns
Return values for mbox_open()
Definition: mx.h:84
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_globals.h
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
mutt_comp_valid_command
int mutt_comp_valid_command(const char *cmd)
Is this command string allowed?
Definition: compress.c:405
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
protos.h
mutt_comp_init
void mutt_comp_init(void)
Setup feature commands.
Definition: compress.c:66
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
Command
A user-callable command.
Definition: mutt_commands.h:45
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
lib.h
Account
A group of associated Mailboxes.
Definition: account.h:36
muttlib.h
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
lib.h
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
lib.h
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
OpenMailboxFlags
uint8_t OpenMailboxFlags
Flags for mutt_open_mailbox(), e.g. MUTT_NOSORT.
Definition: mx.h:50
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
MxCompOps
struct MxOps MxCompOps
Compressed Mailbox - Implements MxOps.
Definition: compress.c:926
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
MailboxType
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
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
mutt_commands.h
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
mx.h
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_comp_can_append
bool mutt_comp_can_append(struct Mailbox *m)
Can we append to this path?
Definition: compress.c:356
Email
The envelope/body of an email.
Definition: email.h:37
lib.h
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
hook.h
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
Message
A local copy of an email.
Definition: mx.h:94
CompressInfo::locked
bool locked
if realpath is locked
Definition: lib.h:55
MuttFormatFlags
uint8_t MuttFormatFlags
Flags for mutt_expando_format(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: format_flags.h:29
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