NeoMutt  2023-03-22
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 "globals.h"
51#include "hook.h"
52#include "muttlib.h"
53#include "mx.h"
54#include "protos.h"
55
56struct Email;
57
61static const struct Command CompCommands[] = {
62 // clang-format off
63 { "append-hook", mutt_parse_hook, MUTT_APPEND_HOOK },
64 { "close-hook", mutt_parse_hook, MUTT_CLOSE_HOOK },
65 { "open-hook", mutt_parse_hook, MUTT_OPEN_HOOK },
66 // clang-format on
67};
68
73{
75}
76
88static bool lock_realpath(struct Mailbox *m, bool excl)
89{
90 if (!m || !m->compress_info)
91 return false;
92
93 struct CompressInfo *ci = m->compress_info;
94
95 if (ci->locked)
96 return true;
97
98 if (excl)
99 ci->fp_lock = fopen(m->realpath, "a");
100 else
101 ci->fp_lock = fopen(m->realpath, "r");
102 if (!ci->fp_lock)
103 {
105 return false;
106 }
107
108 int r = mutt_file_lock(fileno(ci->fp_lock), excl, true);
109 if (r == 0)
110 ci->locked = true;
111 else if (excl)
112 {
114 m->readonly = true;
115 return true;
116 }
117
118 return r == 0;
119}
120
127static void unlock_realpath(struct Mailbox *m)
128{
129 if (!m || !m->compress_info)
130 return;
131
132 struct CompressInfo *ci = m->compress_info;
133
134 if (!ci->locked)
135 return;
136
137 mutt_file_unlock(fileno(ci->fp_lock));
138
139 ci->locked = false;
141}
142
153static int setup_paths(struct Mailbox *m)
154{
155 if (!m)
156 return -1;
157
158 /* Setup the right paths */
160
161 /* We will uncompress to TMPDIR */
162 struct Buffer *buf = mutt_buffer_pool_get();
164 mutt_buffer_copy(&m->pathbuf, buf);
166
167 FILE *fp = mutt_file_fopen(mailbox_path(m), "w");
168 if (!fp)
169 return -1;
170
171 mutt_file_fclose(&fp);
172 return 0;
173}
174
181static void store_size(const struct Mailbox *m)
182{
183 if (!m || !m->compress_info)
184 return;
185
186 struct CompressInfo *ci = m->compress_info;
187
189}
190
199static struct CompressInfo *set_compress_info(struct Mailbox *m)
200{
201 if (!m)
202 return NULL;
203
204 if (m->compress_info)
205 return m->compress_info;
206
207 /* Open is compulsory */
208 const char *o = mutt_find_hook(MUTT_OPEN_HOOK, mailbox_path(m));
209 if (!o)
210 return NULL;
211
212 const char *c = mutt_find_hook(MUTT_CLOSE_HOOK, mailbox_path(m));
213 const char *a = mutt_find_hook(MUTT_APPEND_HOOK, mailbox_path(m));
214
215 struct CompressInfo *ci = mutt_mem_calloc(1, sizeof(struct CompressInfo));
216 m->compress_info = ci;
217
218 ci->cmd_open = mutt_str_dup(o);
219 ci->cmd_close = mutt_str_dup(c);
220 ci->cmd_append = mutt_str_dup(a);
221
222 return ci;
223}
224
229static void compress_info_free(struct Mailbox *m)
230{
231 if (!m || !m->compress_info)
232 return;
233
234 struct CompressInfo *ci = m->compress_info;
235 FREE(&ci->cmd_open);
236 FREE(&ci->cmd_close);
237 FREE(&ci->cmd_append);
238
240
241 FREE(&m->compress_info);
242}
243
252static const char *compress_format_str(char *buf, size_t buflen, size_t col, int cols,
253 char op, const char *src, const char *prec,
254 const char *if_str, const char *else_str,
255 intptr_t data, MuttFormatFlags flags)
256{
257 if (!buf || (data == 0))
258 return src;
259
260 struct Mailbox *m = (struct Mailbox *) data;
261
262 /* NOTE the compressed file config vars expect %f and %t to be
263 * surrounded by '' (unlike other NeoMutt config vars, which add the
264 * outer quotes for the user). This is why we use the
265 * mutt_buffer_quote_filename() form with add_outer of false. */
266 struct Buffer *quoted = mutt_buffer_pool_get();
267 switch (op)
268 {
269 case 'f':
270 /* Compressed file */
271 mutt_buffer_quote_filename(quoted, m->realpath, false);
272 snprintf(buf, buflen, "%s", mutt_buffer_string(quoted));
273 break;
274 case 't':
275 /* Plaintext, temporary file */
276 mutt_buffer_quote_filename(quoted, mailbox_path(m), false);
277 snprintf(buf, buflen, "%s", mutt_buffer_string(quoted));
278 break;
279 }
280
282 return src;
283}
284
304static void expand_command_str(const struct Mailbox *m, const char *cmd, char *buf, int buflen)
305{
306 if (!m || !cmd || !buf)
307 return;
308
309 mutt_expando_format(buf, buflen, 0, buflen, cmd, compress_format_str,
310 (intptr_t) m, MUTT_FORMAT_NO_FLAGS);
311}
312
324static int execute_command(struct Mailbox *m, const char *command, const char *progress)
325{
326 if (!m || !command || !progress)
327 return 0;
328
329 if (m->verbose)
330 mutt_message(progress, m->realpath);
331
332 int rc = 1;
333 char sys_cmd[STR_COMMAND] = { 0 };
334
336 endwin();
337 fflush(stdout);
338
339 expand_command_str(m, command, sys_cmd, sizeof(sys_cmd));
340
341 if (mutt_system(sys_cmd) != 0)
342 {
343 rc = 0;
345 mutt_error(_("Error running \"%s\""), sys_cmd);
346 }
347
349
350 return rc;
351}
352
365{
366 if (!m)
367 return false;
368
369 /* If this succeeds, we know there's an open-hook */
370 struct CompressInfo *ci = set_compress_info(m);
371 if (!ci)
372 return false;
373
374 /* We have an open-hook, so to append we need an append-hook,
375 * or a close-hook. */
376 if (ci->cmd_append || ci->cmd_close)
377 return true;
378
379 mutt_error(_("Can't append without an append-hook or close-hook : %s"), mailbox_path(m));
380 return false;
381}
382
393bool mutt_comp_can_read(const char *path)
394{
395 if (!path)
396 return false;
397
399 return true;
400
401 return false;
402}
403
413int mutt_comp_valid_command(const char *cmd)
414{
415 if (!cmd)
416 return 0;
417
418 return strstr(cmd, "%f") && strstr(cmd, "%t");
419}
420
424static bool comp_ac_owns_path(struct Account *a, const char *path)
425{
426 return false;
427}
428
432static bool comp_ac_add(struct Account *a, struct Mailbox *m)
433{
434 return true;
435}
436
446{
447 struct CompressInfo *ci = set_compress_info(m);
448 if (!ci)
449 return MX_OPEN_ERROR;
450
451 /* If there's no close-hook, or the file isn't writable */
452 if (!ci->cmd_close || (access(mailbox_path(m), W_OK) != 0))
453 m->readonly = true;
454
455 if (setup_paths(m) != 0)
456 goto cmo_fail;
457 store_size(m);
458
459 if (!lock_realpath(m, false))
460 {
461 mutt_error(_("Unable to lock mailbox"));
462 goto cmo_fail;
463 }
464
465 int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
466 if (rc == 0)
467 goto cmo_fail;
468
470
472 if (m->type == MUTT_UNKNOWN)
473 {
474 mutt_error(_("Can't identify the contents of the compressed file"));
475 goto cmo_fail;
476 }
477
478 ci->child_ops = mx_get_ops(m->type);
479 if (!ci->child_ops)
480 {
481 mutt_error(_("Can't find mailbox ops for mailbox type %d"), m->type);
482 goto cmo_fail;
483 }
484
485 m->account->type = m->type;
486 return ci->child_ops->mbox_open(m);
487
488cmo_fail:
489 /* remove the partial uncompressed file */
490 (void) remove(mailbox_path(m));
492 return MX_OPEN_ERROR;
493}
494
503static bool comp_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
504{
505 /* If this succeeds, we know there's an open-hook */
506 struct CompressInfo *ci = set_compress_info(m);
507 if (!ci)
508 return false;
509
510 /* To append we need an append-hook or a close-hook */
511 if (!ci->cmd_append && !ci->cmd_close)
512 {
513 mutt_error(_("Can't append without an append-hook or close-hook : %s"),
514 mailbox_path(m));
515 goto cmoa_fail1;
516 }
517
518 if (setup_paths(m) != 0)
519 goto cmoa_fail2;
520
521 /* Lock the realpath for the duration of the append.
522 * It will be unlocked in the close */
523 if (!lock_realpath(m, true))
524 {
525 mutt_error(_("Unable to lock mailbox"));
526 goto cmoa_fail2;
527 }
528
529 /* Open the existing mailbox, unless we are appending */
530 if (!ci->cmd_append && (mutt_file_get_size(m->realpath) > 0))
531 {
532 int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
533 if (rc == 0)
534 {
535 mutt_error(_("Compress command failed: %s"), ci->cmd_open);
536 goto cmoa_fail2;
537 }
539 }
540 else
541 {
542 m->type = cs_subset_enum(NeoMutt->sub, "mbox_type");
543 }
544
545 /* We can only deal with mbox and mmdf mailboxes */
546 if ((m->type != MUTT_MBOX) && (m->type != MUTT_MMDF))
547 {
548 mutt_error(_("Unsupported mailbox type for appending"));
549 goto cmoa_fail2;
550 }
551
552 ci->child_ops = mx_get_ops(m->type);
553 if (!ci->child_ops)
554 {
555 mutt_error(_("Can't find mailbox ops for mailbox type %d"), m->type);
556 goto cmoa_fail2;
557 }
558
559 if (!ci->child_ops->mbox_open_append(m, flags))
560 goto cmoa_fail2;
561
562 return true;
563
564cmoa_fail2:
565 /* remove the partial uncompressed file */
566 (void) remove(mailbox_path(m));
567cmoa_fail1:
568 /* Free the compress_info to prevent close from trying to recompress */
570
571 return false;
572}
573
584static enum MxStatus comp_mbox_check(struct Mailbox *m)
585{
586 if (!m->compress_info)
587 return MX_STATUS_ERROR;
588
589 struct CompressInfo *ci = m->compress_info;
590
591 const struct MxOps *ops = ci->child_ops;
592 if (!ops)
593 return MX_STATUS_ERROR;
594
595 int size = mutt_file_get_size(m->realpath);
596 if (size == ci->size)
597 return MX_STATUS_OK;
598
599 if (!lock_realpath(m, false))
600 {
601 mutt_error(_("Unable to lock mailbox"));
602 return MX_STATUS_ERROR;
603 }
604
605 int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
606 store_size(m);
608 if (rc == 0)
609 return MX_STATUS_ERROR;
610
611 return ops->mbox_check(m);
612}
613
620static enum MxStatus comp_mbox_sync(struct Mailbox *m)
621{
622 if (!m->compress_info)
623 return MX_STATUS_ERROR;
624
625 struct CompressInfo *ci = m->compress_info;
626
627 if (!ci->cmd_close)
628 {
629 mutt_error(_("Can't sync a compressed file without a close-hook"));
630 return MX_STATUS_ERROR;
631 }
632
633 const struct MxOps *ops = ci->child_ops;
634 if (!ops)
635 return MX_STATUS_ERROR;
636
637 if (!lock_realpath(m, true))
638 {
639 mutt_error(_("Unable to lock mailbox"));
640 return MX_STATUS_ERROR;
641 }
642
643 enum MxStatus check = comp_mbox_check(m);
644 if (check != MX_STATUS_OK)
645 goto sync_cleanup;
646
647 check = ops->mbox_sync(m);
648 if (check != MX_STATUS_OK)
649 goto sync_cleanup;
650
651 int rc = execute_command(m, ci->cmd_close, _("Compressing %s"));
652 if (rc == 0)
653 {
654 check = MX_STATUS_ERROR;
655 goto sync_cleanup;
656 }
657
658 check = MX_STATUS_OK;
659
660sync_cleanup:
661 store_size(m);
663 return check;
664}
665
672static enum MxStatus comp_mbox_close(struct Mailbox *m)
673{
674 if (!m->compress_info)
675 return MX_STATUS_ERROR;
676
677 struct CompressInfo *ci = m->compress_info;
678
679 const struct MxOps *ops = ci->child_ops;
680 if (!ops)
681 {
683 return MX_STATUS_ERROR;
684 }
685
686 ops->mbox_close(m);
687
688 /* sync has already been called, so we only need to delete some files */
689 if (m->append)
690 {
691 const char *append = NULL;
692 const char *msg = NULL;
693
694 /* The file exists and we can append */
695 if ((access(m->realpath, F_OK) == 0) && ci->cmd_append)
696 {
697 append = ci->cmd_append;
698 msg = _("Compressed-appending to %s...");
699 }
700 else
701 {
702 append = ci->cmd_close;
703 msg = _("Compressing %s");
704 }
705
706 int rc = execute_command(m, append, msg);
707 if (rc == 0)
708 {
710 mutt_error(_("Error. Preserving temporary file: %s"), mailbox_path(m));
711 }
712 else
713 remove(mailbox_path(m));
714
716 }
717 else
718 {
719 /* If the file was removed, remove the compressed folder too */
720 if (access(mailbox_path(m), F_OK) != 0)
721 {
722 const bool c_save_empty = cs_subset_bool(NeoMutt->sub, "save_empty");
723 if (!c_save_empty)
724 {
725 remove(m->realpath);
726 }
727 }
728 else
729 {
730 remove(mailbox_path(m));
731 }
732 }
733
735
736 return MX_STATUS_OK;
737}
738
742static bool comp_msg_open(struct Mailbox *m, struct Message *msg, int msgno)
743{
744 if (!m->compress_info)
745 return false;
746
747 struct CompressInfo *ci = m->compress_info;
748
749 const struct MxOps *ops = ci->child_ops;
750 if (!ops)
751 return false;
752
753 /* Delegate */
754 return ops->msg_open(m, msg, msgno);
755}
756
760static bool comp_msg_open_new(struct Mailbox *m, struct Message *msg, const struct Email *e)
761{
762 if (!m->compress_info)
763 return false;
764
765 struct CompressInfo *ci = m->compress_info;
766
767 const struct MxOps *ops = ci->child_ops;
768 if (!ops)
769 return false;
770
771 /* Delegate */
772 return ops->msg_open_new(m, msg, e);
773}
774
778static int comp_msg_commit(struct Mailbox *m, struct Message *msg)
779{
780 if (!m->compress_info)
781 return -1;
782
783 struct CompressInfo *ci = m->compress_info;
784
785 const struct MxOps *ops = ci->child_ops;
786 if (!ops)
787 return -1;
788
789 /* Delegate */
790 return ops->msg_commit(m, msg);
791}
792
796static int comp_msg_close(struct Mailbox *m, struct Message *msg)
797{
798 if (!m->compress_info)
799 return -1;
800
801 struct CompressInfo *ci = m->compress_info;
802
803 const struct MxOps *ops = ci->child_ops;
804 if (!ops)
805 return -1;
806
807 /* Delegate */
808 return ops->msg_close(m, msg);
809}
810
814static int comp_msg_padding_size(struct Mailbox *m)
815{
816 if (!m->compress_info)
817 return 0;
818
819 struct CompressInfo *ci = m->compress_info;
820
821 const struct MxOps *ops = ci->child_ops;
822 if (!ops || !ops->msg_padding_size)
823 return 0;
824
825 return ops->msg_padding_size(m);
826}
827
831static int comp_msg_save_hcache(struct Mailbox *m, struct Email *e)
832{
833 if (!m->compress_info)
834 return 0;
835
836 struct CompressInfo *ci = m->compress_info;
837
838 const struct MxOps *ops = ci->child_ops;
839 if (!ops || !ops->msg_save_hcache)
840 return 0;
841
842 return ops->msg_save_hcache(m, e);
843}
844
848static int comp_tags_edit(struct Mailbox *m, const char *tags, struct Buffer *buf)
849{
850 if (!m->compress_info)
851 return 0;
852
853 struct CompressInfo *ci = m->compress_info;
854
855 const struct MxOps *ops = ci->child_ops;
856 if (!ops || !ops->tags_edit)
857 return 0;
858
859 return ops->tags_edit(m, tags, buf);
860}
861
865static int comp_tags_commit(struct Mailbox *m, struct Email *e, const char *buf)
866{
867 if (!m->compress_info)
868 return 0;
869
870 struct CompressInfo *ci = m->compress_info;
871
872 const struct MxOps *ops = ci->child_ops;
873 if (!ops || !ops->tags_commit)
874 return 0;
875
876 return ops->tags_commit(m, e, buf);
877}
878
882static enum MailboxType comp_path_probe(const char *path, const struct stat *st)
883{
884 if (!st || !S_ISREG(st->st_mode))
885 return MUTT_UNKNOWN;
886
887 if (mutt_comp_can_read(path))
888 return MUTT_COMPRESSED;
889
890 return MUTT_UNKNOWN;
891}
892
896static int comp_path_canon(char *buf, size_t buflen)
897{
898 mutt_path_canon(buf, buflen, HomeDir, false);
899 return 0;
900}
901
905static int comp_path_pretty(char *buf, size_t buflen, const char *folder)
906{
907 if (mutt_path_abbr_folder(buf, folder))
908 return 0;
909
910 if (mutt_path_pretty(buf, buflen, HomeDir, false))
911 return 0;
912
913 return -1;
914}
915
919static int comp_path_parent(char *buf, size_t buflen)
920{
921 if (mutt_path_parent(buf))
922 return 0;
923
924 if (buf[0] == '~')
925 mutt_path_canon(buf, buflen, HomeDir, false);
926
927 if (mutt_path_parent(buf))
928 return 0;
929
930 return -1;
931}
932
939struct MxOps MxCompOps = {
940 // clang-format off
942 .name = "compressed",
943 .is_local = true,
944 .ac_owns_path = comp_ac_owns_path,
945 .ac_add = comp_ac_add,
946 .mbox_open = comp_mbox_open,
947 .mbox_open_append = comp_mbox_open_append,
948 .mbox_check = comp_mbox_check,
949 .mbox_check_stats = NULL,
950 .mbox_sync = comp_mbox_sync,
951 .mbox_close = comp_mbox_close,
952 .msg_open = comp_msg_open,
953 .msg_open_new = comp_msg_open_new,
954 .msg_commit = comp_msg_commit,
955 .msg_close = comp_msg_close,
956 .msg_padding_size = comp_msg_padding_size,
957 .msg_save_hcache = comp_msg_save_hcache,
958 .tags_edit = comp_tags_edit,
959 .tags_commit = comp_tags_commit,
960 .path_probe = comp_path_probe,
961 .path_canon = comp_path_canon,
962 .path_pretty = comp_path_pretty,
963 .path_parent = comp_path_parent,
964 .path_is_empty = NULL,
965 // clang-format on
966};
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:500
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
static struct CompressInfo * set_compress_info(struct Mailbox *m)
Find the compress hooks for a mailbox.
Definition: compress.c:199
static void compress_info_free(struct Mailbox *m)
Frees the compress info members and structure.
Definition: compress.c:229
static int setup_paths(struct Mailbox *m)
Set the mailbox paths.
Definition: compress.c:153
static int execute_command(struct Mailbox *m, const char *command, const char *progress)
Run a system command.
Definition: compress.c:324
void mutt_comp_init(void)
Setup feature commands.
Definition: compress.c:72
static void store_size(const struct Mailbox *m)
Save the size of the compressed file.
Definition: compress.c:181
static bool lock_realpath(struct Mailbox *m, bool excl)
Try to lock the Mailbox.realpath.
Definition: compress.c:88
bool mutt_comp_can_append(struct Mailbox *m)
Can we append to this path?
Definition: compress.c:364
static void unlock_realpath(struct Mailbox *m)
Unlock the mailbox->realpath.
Definition: compress.c:127
static const struct Command CompCommands[]
Compression Commands.
Definition: compress.c:61
int mutt_comp_valid_command(const char *cmd)
Is this command string allowed?
Definition: compress.c:413
static void expand_command_str(const struct Mailbox *m, const char *cmd, char *buf, int buflen)
Expand placeholders in command string.
Definition: compress.c:304
bool mutt_comp_can_read(const char *path)
Can we read from this file?
Definition: compress.c:393
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: globals.c:38
void commands_register(const struct Command *cmds, const size_t num_cmds)
Add commands to Commands array.
Definition: command.c:53
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:386
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:634
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:151
int mutt_file_lock(int fd, bool excl, bool timeout)
(Try to) Lock a file using fcntl()
Definition: file.c:1247
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:907
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1295
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1567
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:126
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:252
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:778
#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:432
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:424
struct MxOps MxCompOps
Compressed Mailbox - Implements MxOps -.
Definition: compress.c:939
static enum MxStatus comp_mbox_check(struct Mailbox *m)
Check for new mail - Implements MxOps::mbox_check() -.
Definition: compress.c:584
static enum MxStatus comp_mbox_close(struct Mailbox *m)
Close a Mailbox - Implements MxOps::mbox_close() -.
Definition: compress.c:672
static bool comp_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a Mailbox for appending - Implements MxOps::mbox_open_append() -.
Definition: compress.c:503
static enum MxOpenReturns comp_mbox_open(struct Mailbox *m)
Open a Mailbox - Implements MxOps::mbox_open() -.
Definition: compress.c:445
static enum MxStatus comp_mbox_sync(struct Mailbox *m)
Save changes to the Mailbox - Implements MxOps::mbox_sync() -.
Definition: compress.c:620
static int comp_msg_close(struct Mailbox *m, struct Message *msg)
Close an email - Implements MxOps::msg_close() -.
Definition: compress.c:796
static int comp_msg_commit(struct Mailbox *m, struct Message *msg)
Save changes to an email - Implements MxOps::msg_commit() -.
Definition: compress.c:778
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:760
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:742
static int comp_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Implements MxOps::msg_padding_size() -.
Definition: compress.c:814
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:831
static int comp_path_canon(char *buf, size_t buflen)
Canonicalise a Mailbox path - Implements MxOps::path_canon() -.
Definition: compress.c:896
static int comp_path_parent(char *buf, size_t buflen)
Find the parent of a Mailbox path - Implements MxOps::path_parent() -.
Definition: compress.c:919
static int comp_path_pretty(char *buf, size_t buflen, const char *folder)
Abbreviate a Mailbox path - Implements MxOps::path_pretty() -.
Definition: compress.c:905
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:882
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:865
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:848
Convenience wrapper for the gui headers.
char * mutt_find_hook(HookFlags type, const char *pat)
Find a matching hook.
Definition: hook.c:635
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:209
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
#define mutt_array_size(x)
Definition: memory.h:36
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
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:140
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1326
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:344
int(* msg_save_hcache)(struct Mailbox *m, struct Email *e)
Definition: mxapi.h:310
enum MailboxType type
Mailbox type, e.g. MUTT_IMAP.
Definition: mxapi.h:113
int(* msg_padding_size)(struct Mailbox *m)
Definition: mxapi.h:295
int(* tags_edit)(struct Mailbox *m, const char *tags, struct Buffer *buf)
Definition: mxapi.h:327
int(* msg_commit)(struct Mailbox *m, struct Message *msg)
Definition: mxapi.h:268
enum MxOpenReturns(* mbox_open)(struct Mailbox *m)
Definition: mxapi.h:157
int(* msg_close)(struct Mailbox *m, struct Message *msg)
Definition: mxapi.h:283
bool(* msg_open_new)(struct Mailbox *m, struct Message *msg, const struct Email *e)
Definition: mxapi.h:253
enum MxStatus(* mbox_close)(struct Mailbox *m)
Definition: mxapi.h:220
enum MxStatus(* mbox_sync)(struct Mailbox *m)
Definition: mxapi.h:208
bool(* mbox_open_append)(struct Mailbox *m, OpenMailboxFlags flags)
Definition: mxapi.h:171
enum MxStatus(* mbox_check)(struct Mailbox *m)
Definition: mxapi.h:183
bool(* msg_open)(struct Mailbox *m, struct Message *msg, int msgno)
Definition: mxapi.h:237
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39