NeoMutt  2022-04-29-249-gaae397
Teaching an old dog new tricks
DOXYGEN
compress.c
Go to the documentation of this file.
1
37#include "config.h"
38#include <stdbool.h>
39#include <stdint.h>
40#include <stdio.h>
41#include <string.h>
42#include <sys/stat.h>
43#include <unistd.h>
44#include "mutt/lib.h"
45#include "config/lib.h"
46#include "core/lib.h"
47#include "gui/lib.h"
48#include "lib.h"
49#include "format_flags.h"
50#include "hook.h"
51#include "mutt_commands.h"
52#include "mutt_globals.h"
53#include "muttlib.h"
54#include "mx.h"
55#include "protos.h"
56
57struct Email;
58
59static const struct Command comp_commands[] = {
60 // clang-format off
61 { "append-hook", mutt_parse_hook, MUTT_APPEND_HOOK },
62 { "close-hook", mutt_parse_hook, MUTT_CLOSE_HOOK },
63 { "open-hook", mutt_parse_hook, MUTT_OPEN_HOOK },
64 // clang-format on
65};
66
71{
73}
74
86static bool lock_realpath(struct Mailbox *m, bool excl)
87{
88 if (!m || !m->compress_info)
89 return false;
90
91 struct CompressInfo *ci = m->compress_info;
92
93 if (ci->locked)
94 return true;
95
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 {
103 return false;
104 }
105
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 }
115
116 return r == 0;
117}
118
125static void unlock_realpath(struct Mailbox *m)
126{
127 if (!m || !m->compress_info)
128 return;
129
130 struct CompressInfo *ci = m->compress_info;
131
132 if (!ci->locked)
133 return;
134
135 mutt_file_unlock(fileno(ci->fp_lock));
136
137 ci->locked = false;
139}
140
151static int setup_paths(struct Mailbox *m)
152{
153 if (!m)
154 return -1;
155
156 /* Setup the right paths */
158
159 /* We will uncompress to TMPDIR */
160 struct Buffer *buf = mutt_buffer_pool_get();
162 mutt_buffer_copy(&m->pathbuf, buf);
164
165 FILE *fp = mutt_file_fopen(mailbox_path(m), "w");
166 if (!fp)
167 return -1;
168
169 mutt_file_fclose(&fp);
170 return 0;
171}
172
179static void store_size(const struct Mailbox *m)
180{
181 if (!m || !m->compress_info)
182 return;
183
184 struct CompressInfo *ci = m->compress_info;
185
187}
188
197static struct CompressInfo *set_compress_info(struct Mailbox *m)
198{
199 if (!m)
200 return NULL;
201
202 if (m->compress_info)
203 return m->compress_info;
204
205 /* Open is compulsory */
206 const char *o = mutt_find_hook(MUTT_OPEN_HOOK, mailbox_path(m));
207 if (!o)
208 return NULL;
209
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));
212
213 struct CompressInfo *ci = mutt_mem_calloc(1, sizeof(struct CompressInfo));
214 m->compress_info = ci;
215
216 ci->cmd_open = mutt_str_dup(o);
217 ci->cmd_close = mutt_str_dup(c);
218 ci->cmd_append = mutt_str_dup(a);
219
220 return ci;
221}
222
227static void compress_info_free(struct Mailbox *m)
228{
229 if (!m || !m->compress_info)
230 return;
231
232 struct CompressInfo *ci = m->compress_info;
233 FREE(&ci->cmd_open);
234 FREE(&ci->cmd_close);
235 FREE(&ci->cmd_append);
236
238
239 FREE(&m->compress_info);
240}
241
250static const char *compress_format_str(char *buf, size_t buflen, size_t col, int cols,
251 char op, const char *src, const char *prec,
252 const char *if_str, const char *else_str,
253 intptr_t data, MuttFormatFlags flags)
254{
255 if (!buf || (data == 0))
256 return src;
257
258 struct Mailbox *m = (struct Mailbox *) data;
259
260 /* NOTE the compressed file config vars expect %f and %t to be
261 * surrounded by '' (unlike other NeoMutt config vars, which add the
262 * outer quotes for the user). This is why we use the
263 * mutt_buffer_quote_filename() form with add_outer of false. */
264 struct Buffer *quoted = mutt_buffer_pool_get();
265 switch (op)
266 {
267 case 'f':
268 /* Compressed file */
269 mutt_buffer_quote_filename(quoted, m->realpath, false);
270 snprintf(buf, buflen, "%s", mutt_buffer_string(quoted));
271 break;
272 case 't':
273 /* Plaintext, temporary file */
274 mutt_buffer_quote_filename(quoted, mailbox_path(m), false);
275 snprintf(buf, buflen, "%s", mutt_buffer_string(quoted));
276 break;
277 }
278
280 return src;
281}
282
302static void expand_command_str(const struct Mailbox *m, const char *cmd, char *buf, int buflen)
303{
304 if (!m || !cmd || !buf)
305 return;
306
307 mutt_expando_format(buf, buflen, 0, buflen, cmd, compress_format_str,
308 (intptr_t) m, MUTT_FORMAT_NO_FLAGS);
309}
310
322static int execute_command(struct Mailbox *m, const char *command, const char *progress)
323{
324 if (!m || !command || !progress)
325 return 0;
326
327 if (m->verbose)
328 mutt_message(progress, m->realpath);
329
330 int rc = 1;
331 char sys_cmd[STR_COMMAND] = { 0 };
332
334 endwin();
335 fflush(stdout);
336
337 expand_command_str(m, command, sys_cmd, sizeof(sys_cmd));
338
339 if (mutt_system(sys_cmd) != 0)
340 {
341 rc = 0;
343 mutt_error(_("Error running \"%s\""), sys_cmd);
344 }
345
347
348 return rc;
349}
350
363{
364 if (!m)
365 return false;
366
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;
371
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;
376
377 mutt_error(_("Can't append without an append-hook or close-hook : %s"), mailbox_path(m));
378 return false;
379}
380
391bool mutt_comp_can_read(const char *path)
392{
393 if (!path)
394 return false;
395
397 return true;
398
399 return false;
400}
401
411int mutt_comp_valid_command(const char *cmd)
412{
413 if (!cmd)
414 return 0;
415
416 return strstr(cmd, "%f") && strstr(cmd, "%t");
417}
418
422static bool comp_ac_owns_path(struct Account *a, const char *path)
423{
424 return false;
425}
426
430static bool comp_ac_add(struct Account *a, struct Mailbox *m)
431{
432 return true;
433}
434
444{
445 struct CompressInfo *ci = set_compress_info(m);
446 if (!ci)
447 return MX_OPEN_ERROR;
448
449 /* If there's no close-hook, or the file isn't writable */
450 if (!ci->cmd_close || (access(mailbox_path(m), W_OK) != 0))
451 m->readonly = true;
452
453 if (setup_paths(m) != 0)
454 goto cmo_fail;
455 store_size(m);
456
457 if (!lock_realpath(m, false))
458 {
459 mutt_error(_("Unable to lock mailbox"));
460 goto cmo_fail;
461 }
462
463 int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
464 if (rc == 0)
465 goto cmo_fail;
466
468
470 if (m->type == MUTT_UNKNOWN)
471 {
472 mutt_error(_("Can't identify the contents of the compressed file"));
473 goto cmo_fail;
474 }
475
476 ci->child_ops = mx_get_ops(m->type);
477 if (!ci->child_ops)
478 {
479 mutt_error(_("Can't find mailbox ops for mailbox type %d"), m->type);
480 goto cmo_fail;
481 }
482
483 m->account->type = m->type;
484 return ci->child_ops->mbox_open(m);
485
486cmo_fail:
487 /* remove the partial uncompressed file */
488 (void) remove(mailbox_path(m));
490 return MX_OPEN_ERROR;
491}
492
501static bool comp_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
502{
503 /* If this succeeds, we know there's an open-hook */
504 struct CompressInfo *ci = set_compress_info(m);
505 if (!ci)
506 return false;
507
508 /* To append we need an append-hook or a close-hook */
509 if (!ci->cmd_append && !ci->cmd_close)
510 {
511 mutt_error(_("Can't append without an append-hook or close-hook : %s"),
512 mailbox_path(m));
513 goto cmoa_fail1;
514 }
515
516 if (setup_paths(m) != 0)
517 goto cmoa_fail2;
518
519 /* Lock the realpath for the duration of the append.
520 * It will be unlocked in the close */
521 if (!lock_realpath(m, true))
522 {
523 mutt_error(_("Unable to lock mailbox"));
524 goto cmoa_fail2;
525 }
526
527 /* Open the existing mailbox, unless we are appending */
528 if (!ci->cmd_append && (mutt_file_get_size(m->realpath) > 0))
529 {
530 int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
531 if (rc == 0)
532 {
533 mutt_error(_("Compress command failed: %s"), ci->cmd_open);
534 goto cmoa_fail2;
535 }
537 }
538 else
539 {
540 m->type = cs_subset_enum(NeoMutt->sub, "mbox_type");
541 }
542
543 /* We can only deal with mbox and mmdf mailboxes */
544 if ((m->type != MUTT_MBOX) && (m->type != MUTT_MMDF))
545 {
546 mutt_error(_("Unsupported mailbox type for appending"));
547 goto cmoa_fail2;
548 }
549
550 ci->child_ops = mx_get_ops(m->type);
551 if (!ci->child_ops)
552 {
553 mutt_error(_("Can't find mailbox ops for mailbox type %d"), m->type);
554 goto cmoa_fail2;
555 }
556
557 if (!ci->child_ops->mbox_open_append(m, flags))
558 goto cmoa_fail2;
559
560 return true;
561
562cmoa_fail2:
563 /* remove the partial uncompressed file */
564 (void) remove(mailbox_path(m));
565cmoa_fail1:
566 /* Free the compress_info to prevent close from trying to recompress */
568
569 return false;
570}
571
582static enum MxStatus comp_mbox_check(struct Mailbox *m)
583{
584 if (!m->compress_info)
585 return MX_STATUS_ERROR;
586
587 struct CompressInfo *ci = m->compress_info;
588
589 const struct MxOps *ops = ci->child_ops;
590 if (!ops)
591 return MX_STATUS_ERROR;
592
593 int size = mutt_file_get_size(m->realpath);
594 if (size == ci->size)
595 return MX_STATUS_OK;
596
597 if (!lock_realpath(m, false))
598 {
599 mutt_error(_("Unable to lock mailbox"));
600 return MX_STATUS_ERROR;
601 }
602
603 int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
604 store_size(m);
606 if (rc == 0)
607 return MX_STATUS_ERROR;
608
609 return ops->mbox_check(m);
610}
611
618static enum MxStatus comp_mbox_sync(struct Mailbox *m)
619{
620 if (!m->compress_info)
621 return MX_STATUS_ERROR;
622
623 struct CompressInfo *ci = m->compress_info;
624
625 if (!ci->cmd_close)
626 {
627 mutt_error(_("Can't sync a compressed file without a close-hook"));
628 return MX_STATUS_ERROR;
629 }
630
631 const struct MxOps *ops = ci->child_ops;
632 if (!ops)
633 return MX_STATUS_ERROR;
634
635 if (!lock_realpath(m, true))
636 {
637 mutt_error(_("Unable to lock mailbox"));
638 return MX_STATUS_ERROR;
639 }
640
641 enum MxStatus check = comp_mbox_check(m);
642 if (check != MX_STATUS_OK)
643 goto sync_cleanup;
644
645 check = ops->mbox_sync(m);
646 if (check != MX_STATUS_OK)
647 goto sync_cleanup;
648
649 int rc = execute_command(m, ci->cmd_close, _("Compressing %s"));
650 if (rc == 0)
651 {
652 check = MX_STATUS_ERROR;
653 goto sync_cleanup;
654 }
655
656 check = MX_STATUS_OK;
657
658sync_cleanup:
659 store_size(m);
661 return check;
662}
663
670static enum MxStatus comp_mbox_close(struct Mailbox *m)
671{
672 if (!m->compress_info)
673 return MX_STATUS_ERROR;
674
675 struct CompressInfo *ci = m->compress_info;
676
677 const struct MxOps *ops = ci->child_ops;
678 if (!ops)
679 {
681 return MX_STATUS_ERROR;
682 }
683
684 ops->mbox_close(m);
685
686 /* sync has already been called, so we only need to delete some files */
687 if (m->append)
688 {
689 const char *append = NULL;
690 const char *msg = NULL;
691
692 /* The file exists and we can append */
693 if ((access(m->realpath, F_OK) == 0) && ci->cmd_append)
694 {
695 append = ci->cmd_append;
696 msg = _("Compressed-appending to %s...");
697 }
698 else
699 {
700 append = ci->cmd_close;
701 msg = _("Compressing %s");
702 }
703
704 int rc = execute_command(m, append, msg);
705 if (rc == 0)
706 {
708 mutt_error(_("Error. Preserving temporary file: %s"), mailbox_path(m));
709 }
710 else
711 remove(mailbox_path(m));
712
714 }
715 else
716 {
717 /* If the file was removed, remove the compressed folder too */
718 if (access(mailbox_path(m), F_OK) != 0)
719 {
720 const bool c_save_empty = cs_subset_bool(NeoMutt->sub, "save_empty");
721 if (!c_save_empty)
722 {
723 remove(m->realpath);
724 }
725 }
726 else
727 {
728 remove(mailbox_path(m));
729 }
730 }
731
733
734 return MX_STATUS_OK;
735}
736
740static bool comp_msg_open(struct Mailbox *m, struct Message *msg, int msgno)
741{
742 if (!m->compress_info)
743 return false;
744
745 struct CompressInfo *ci = m->compress_info;
746
747 const struct MxOps *ops = ci->child_ops;
748 if (!ops)
749 return false;
750
751 /* Delegate */
752 return ops->msg_open(m, msg, msgno);
753}
754
758static bool comp_msg_open_new(struct Mailbox *m, struct Message *msg, const struct Email *e)
759{
760 if (!m->compress_info)
761 return false;
762
763 struct CompressInfo *ci = m->compress_info;
764
765 const struct MxOps *ops = ci->child_ops;
766 if (!ops)
767 return false;
768
769 /* Delegate */
770 return ops->msg_open_new(m, msg, e);
771}
772
776static int comp_msg_commit(struct Mailbox *m, struct Message *msg)
777{
778 if (!m->compress_info)
779 return -1;
780
781 struct CompressInfo *ci = m->compress_info;
782
783 const struct MxOps *ops = ci->child_ops;
784 if (!ops)
785 return -1;
786
787 /* Delegate */
788 return ops->msg_commit(m, msg);
789}
790
794static int comp_msg_close(struct Mailbox *m, struct Message *msg)
795{
796 if (!m->compress_info)
797 return -1;
798
799 struct CompressInfo *ci = m->compress_info;
800
801 const struct MxOps *ops = ci->child_ops;
802 if (!ops)
803 return -1;
804
805 /* Delegate */
806 return ops->msg_close(m, msg);
807}
808
812static int comp_msg_padding_size(struct Mailbox *m)
813{
814 if (!m->compress_info)
815 return 0;
816
817 struct CompressInfo *ci = m->compress_info;
818
819 const struct MxOps *ops = ci->child_ops;
820 if (!ops || !ops->msg_padding_size)
821 return 0;
822
823 return ops->msg_padding_size(m);
824}
825
829static int comp_msg_save_hcache(struct Mailbox *m, struct Email *e)
830{
831 if (!m->compress_info)
832 return 0;
833
834 struct CompressInfo *ci = m->compress_info;
835
836 const struct MxOps *ops = ci->child_ops;
837 if (!ops || !ops->msg_save_hcache)
838 return 0;
839
840 return ops->msg_save_hcache(m, e);
841}
842
846static int comp_tags_edit(struct Mailbox *m, const char *tags, struct Buffer *buf)
847{
848 if (!m->compress_info)
849 return 0;
850
851 struct CompressInfo *ci = m->compress_info;
852
853 const struct MxOps *ops = ci->child_ops;
854 if (!ops || !ops->tags_edit)
855 return 0;
856
857 return ops->tags_edit(m, tags, buf);
858}
859
863static int comp_tags_commit(struct Mailbox *m, struct Email *e, const char *buf)
864{
865 if (!m->compress_info)
866 return 0;
867
868 struct CompressInfo *ci = m->compress_info;
869
870 const struct MxOps *ops = ci->child_ops;
871 if (!ops || !ops->tags_commit)
872 return 0;
873
874 return ops->tags_commit(m, e, buf);
875}
876
880static enum MailboxType comp_path_probe(const char *path, const struct stat *st)
881{
882 if (!st || !S_ISREG(st->st_mode))
883 return MUTT_UNKNOWN;
884
885 if (mutt_comp_can_read(path))
886 return MUTT_COMPRESSED;
887
888 return MUTT_UNKNOWN;
889}
890
894static int comp_path_canon(char *buf, size_t buflen)
895{
896 mutt_path_canon(buf, buflen, HomeDir, false);
897 return 0;
898}
899
903static int comp_path_pretty(char *buf, size_t buflen, const char *folder)
904{
905 if (mutt_path_abbr_folder(buf, folder))
906 return 0;
907
908 if (mutt_path_pretty(buf, buflen, HomeDir, false))
909 return 0;
910
911 return -1;
912}
913
917static int comp_path_parent(char *buf, size_t buflen)
918{
919 if (mutt_path_parent(buf))
920 return 0;
921
922 if (buf[0] == '~')
923 mutt_path_canon(buf, buflen, HomeDir, false);
924
925 if (mutt_path_parent(buf))
926 return 0;
927
928 return -1;
929}
930
937struct MxOps MxCompOps = {
938 // clang-format off
940 .name = "compressed",
941 .is_local = true,
942 .ac_owns_path = comp_ac_owns_path,
943 .ac_add = comp_ac_add,
944 .mbox_open = comp_mbox_open,
945 .mbox_open_append = comp_mbox_open_append,
946 .mbox_check = comp_mbox_check,
947 .mbox_check_stats = NULL,
948 .mbox_sync = comp_mbox_sync,
949 .mbox_close = comp_mbox_close,
950 .msg_open = comp_msg_open,
951 .msg_open_new = comp_msg_open_new,
952 .msg_commit = comp_msg_commit,
953 .msg_close = comp_msg_close,
954 .msg_padding_size = comp_msg_padding_size,
955 .msg_save_hcache = comp_msg_save_hcache,
956 .tags_edit = comp_tags_edit,
957 .tags_commit = comp_tags_commit,
958 .path_probe = comp_path_probe,
959 .path_canon = comp_path_canon,
960 .path_pretty = comp_path_pretty,
961 .path_parent = comp_path_parent,
962 .path_is_empty = NULL,
963 // clang-format on
964};
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:462
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
static const struct Command comp_commands[]
Definition: compress.c:59
static struct CompressInfo * set_compress_info(struct Mailbox *m)
Find the compress hooks for a mailbox.
Definition: compress.c:197
static void compress_info_free(struct Mailbox *m)
Frees the compress info members and structure.
Definition: compress.c:227
static int setup_paths(struct Mailbox *m)
Set the mailbox paths.
Definition: compress.c:151
static int execute_command(struct Mailbox *m, const char *command, const char *progress)
Run a system command.
Definition: compress.c:322
void mutt_comp_init(void)
Setup feature commands.
Definition: compress.c:70
static void store_size(const struct Mailbox *m)
Save the size of the compressed file.
Definition: compress.c:179
static bool lock_realpath(struct Mailbox *m, bool excl)
Try to lock the Mailbox.realpath.
Definition: compress.c:86
bool mutt_comp_can_append(struct Mailbox *m)
Can we append to this path?
Definition: compress.c:362
static void unlock_realpath(struct Mailbox *m)
Unlock the mailbox->realpath.
Definition: compress.c:125
int mutt_comp_valid_command(const char *cmd)
Is this command string allowed?
Definition: compress.c:411
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
bool mutt_comp_can_read(const char *path)
Can we read from this file?
Definition: compress.c:391
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition: helpers.c:97
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Convenience wrapper for the config headers.
char * HomeDir
User's home directory.
Definition: mutt_globals.h:49
Convenience wrapper for the core headers.
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:387
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
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
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:891
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1279
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1551
Flags to control mutt_expando_format()
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
uint8_t MuttFormatFlags
Flags for mutt_expando_format(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: format_flags.h:29
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:128
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
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
#define mutt_perror(...)
Definition: logging.h:88
static bool comp_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Implements MxOps::ac_add() -.
Definition: compress.c:430
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:422
struct MxOps MxCompOps
Compressed Mailbox - Implements MxOps -.
Definition: compress.c:937
static enum MxStatus comp_mbox_check(struct Mailbox *m)
Check for new mail - Implements MxOps::mbox_check() -.
Definition: compress.c:582
static enum MxStatus comp_mbox_close(struct Mailbox *m)
Close a Mailbox - Implements MxOps::mbox_close() -.
Definition: compress.c:670
static bool comp_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a Mailbox for appending - Implements MxOps::mbox_open_append() -.
Definition: compress.c:501
static enum MxOpenReturns comp_mbox_open(struct Mailbox *m)
Open a Mailbox - Implements MxOps::mbox_open() -.
Definition: compress.c:443
static enum MxStatus comp_mbox_sync(struct Mailbox *m)
Save changes to the Mailbox - Implements MxOps::mbox_sync() -.
Definition: compress.c:618
static int comp_msg_close(struct Mailbox *m, struct Message *msg)
Close an email - Implements MxOps::msg_close() -.
Definition: compress.c:794
static int comp_msg_commit(struct Mailbox *m, struct Message *msg)
Save changes to an email - Implements MxOps::msg_commit() -.
Definition: compress.c:776
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:758
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:740
static int comp_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Implements MxOps::msg_padding_size() -.
Definition: compress.c:812
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:829
static int comp_path_canon(char *buf, size_t buflen)
Canonicalise a Mailbox path - Implements MxOps::path_canon() -.
Definition: compress.c:894
static int comp_path_parent(char *buf, size_t buflen)
Find the parent of a Mailbox path - Implements MxOps::path_parent() -.
Definition: compress.c:917
static int comp_path_pretty(char *buf, size_t buflen, const char *folder)
Abbreviate a Mailbox path - Implements MxOps::path_pretty() -.
Definition: compress.c:903
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:880
static int comp_tags_commit(struct Mailbox *m, struct Email *e, const char *buf)
Save the tags to a message - Implements MxOps::tags_commit() -.
Definition: compress.c:863
static int comp_tags_edit(struct Mailbox *m, const char *tags, struct Buffer *buf)
Prompt and validate new messages tags - Implements MxOps::tags_edit() -.
Definition: compress.c:846
Convenience wrapper for the gui headers.
char * mutt_find_hook(HookFlags type, const char *pat)
Find a matching hook.
Definition: hook.c:637
Parse and execute user-defined hooks.
#define MUTT_OPEN_HOOK
open-hook: to read a compressed mailbox
Definition: hook.h:51
#define MUTT_CLOSE_HOOK
close-hook: write to a compressed mailbox
Definition: hook.h:53
#define MUTT_APPEND_HOOK
append-hook: append to a compressed mailbox
Definition: hook.h:52
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:210
MailboxType
Supported mailbox formats.
Definition: mailbox.h:41
@ MUTT_MMDF
'mmdf' Mailbox type
Definition: mailbox.h:46
@ MUTT_MBOX
'mbox' Mailbox type
Definition: mailbox.h:45
@ MUTT_COMPRESSED
Compressed file Mailbox type.
Definition: mailbox.h:53
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition: mailbox.h:44
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:43
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
bool mutt_path_abbr_folder(char *buf, const char *folder)
Create a folder abbreviation.
Definition: path.c:490
bool mutt_path_pretty(char *buf, size_t buflen, const char *homedir, bool is_dir)
Tidy a filesystem path.
Definition: path.c:186
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
bool mutt_path_parent(char *buf)
Find the parent of a path.
Definition: path.c:458
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
Definitions of NeoMutt commands.
#define COMMANDS_REGISTER(cmds)
Definition: mutt_commands.h:47
Hundreds of global variables to back the user variables.
Some miscellaneous functions.
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
const struct MxOps * mx_get_ops(enum MailboxType type)
Get mailbox operations.
Definition: mx.c:141
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1327
API for mailboxes.
uint8_t OpenMailboxFlags
Flags for mutt_open_mailbox(), e.g. MUTT_NOSORT.
Definition: mxapi.h:60
MxOpenReturns
Return values for mbox_open()
Definition: mxapi.h:97
@ MX_OPEN_ERROR
Open failed with an error.
Definition: mxapi.h:99
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_snc(), and mbox_close()
Definition: mxapi.h:84
@ MX_STATUS_ERROR
An error occurred.
Definition: mxapi.h:85
@ MX_STATUS_OK
No changes.
Definition: mxapi.h:86
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
Prototypes for many functions.
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
Key value store.
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:35
A group of associated Mailboxes.
Definition: account.h:37
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
String manipulation buffer.
Definition: buffer.h:34
Private data for compress.
Definition: lib.h:47
const char * cmd_append
append-hook command
Definition: lib.h:48
FILE * fp_lock
fp used for locking
Definition: lib.h:54
const char * cmd_open
open-hook command
Definition: lib.h:50
const struct MxOps * child_ops
callbacks of de-compressed file
Definition: lib.h:52
bool locked
if realpath is locked
Definition: lib.h:53
const char * cmd_close
close-hook command
Definition: lib.h:49
long size
size of the compressed file
Definition: lib.h:51
The envelope/body of an email.
Definition: email.h:37
A mailbox.
Definition: mailbox.h:79
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:81
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:109
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
struct Buffer pathbuf
Path of the Mailbox.
Definition: mailbox.h:80
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:127
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:120
bool readonly
Don't allow changes to the mailbox.
Definition: mailbox.h:115
bool verbose
Display status messages?
Definition: mailbox.h:114
A local copy of an email.
Definition: mxapi.h:43
Definition: mxapi.h:112
int(* tags_commit)(struct Mailbox *m, struct Email *e, const char *buf)
Definition: mxapi.h:360
int(* msg_save_hcache)(struct Mailbox *m, struct Email *e)
Definition: mxapi.h:324
enum MailboxType type
Mailbox type, e.g. MUTT_IMAP.
Definition: mxapi.h:113
int(* msg_padding_size)(struct Mailbox *m)
Definition: mxapi.h:308
int(* tags_edit)(struct Mailbox *m, const char *tags, struct Buffer *buf)
Definition: mxapi.h:342
int(* msg_commit)(struct Mailbox *m, struct Message *msg)
Definition: mxapi.h:279
enum MxOpenReturns(* mbox_open)(struct Mailbox *m)
Definition: mxapi.h:160
int(* msg_close)(struct Mailbox *m, struct Message *msg)
Definition: mxapi.h:295
bool(* msg_open_new)(struct Mailbox *m, struct Message *msg, const struct Email *e)
Definition: mxapi.h:263
enum MxStatus(* mbox_close)(struct Mailbox *m)
Definition: mxapi.h:228
enum MxStatus(* mbox_sync)(struct Mailbox *m)
Definition: mxapi.h:215
bool(* mbox_open_append)(struct Mailbox *m, OpenMailboxFlags flags)
Definition: mxapi.h:175
enum MxStatus(* mbox_check)(struct Mailbox *m)
Definition: mxapi.h:188
bool(* msg_open)(struct Mailbox *m, struct Message *msg, int msgno)
Definition: mxapi.h:246
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39