NeoMutt  2024-02-01-35-geee02f
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
compress.c
Go to the documentation of this file.
1
38#include "config.h"
39#include <errno.h>
40#include <stdbool.h>
41#include <stdint.h>
42#include <stdio.h>
43#include <string.h>
44#include <sys/stat.h>
45#include <unistd.h>
46#include "mutt/lib.h"
47#include "config/lib.h"
48#include "core/lib.h"
49#include "gui/lib.h"
50#include "lib.h"
51#include "format_flags.h"
52#include "globals.h"
53#include "hook.h"
54#include "muttlib.h"
55#include "mx.h"
56#include "protos.h"
57
58struct Email;
59
63static const struct Command CompCommands[] = {
64 // clang-format off
65 { "append-hook", mutt_parse_hook, MUTT_APPEND_HOOK },
66 { "close-hook", mutt_parse_hook, MUTT_CLOSE_HOOK },
67 { "open-hook", mutt_parse_hook, MUTT_OPEN_HOOK },
68 // clang-format on
69};
70
75{
77}
78
90static bool lock_realpath(struct Mailbox *m, bool excl)
91{
92 if (!m || !m->compress_info)
93 return false;
94
95 struct CompressInfo *ci = m->compress_info;
96
97 if (ci->locked)
98 return true;
99
100 if (excl)
101 ci->fp_lock = mutt_file_fopen(m->realpath, "a");
102 else
103 ci->fp_lock = mutt_file_fopen(m->realpath, "r");
104 if (!ci->fp_lock)
105 {
106 mutt_perror("%s", m->realpath);
107 return false;
108 }
109
110 int r = mutt_file_lock(fileno(ci->fp_lock), excl, true);
111 if (r == 0)
112 {
113 ci->locked = true;
114 }
115 else if (excl)
116 {
118 m->readonly = true;
119 return true;
120 }
121
122 return r == 0;
123}
124
131static void unlock_realpath(struct Mailbox *m)
132{
133 if (!m || !m->compress_info)
134 return;
135
136 struct CompressInfo *ci = m->compress_info;
137
138 if (!ci->locked)
139 return;
140
141 mutt_file_unlock(fileno(ci->fp_lock));
142
143 ci->locked = false;
145}
146
157static int setup_paths(struct Mailbox *m)
158{
159 if (!m)
160 return -1;
161
162 /* Setup the right paths */
164
165 /* We will uncompress to TMPDIR */
166 struct Buffer *buf = buf_pool_get();
167 buf_mktemp(buf);
168 buf_copy(&m->pathbuf, buf);
169 buf_pool_release(&buf);
170
171 FILE *fp = mutt_file_fopen(mailbox_path(m), "w");
172 if (!fp)
173 return -1;
174
175 mutt_file_fclose(&fp);
176 return 0;
177}
178
185static void store_size(const struct Mailbox *m)
186{
187 if (!m || !m->compress_info)
188 return;
189
190 struct CompressInfo *ci = m->compress_info;
191
193}
194
203static struct CompressInfo *set_compress_info(struct Mailbox *m)
204{
205 if (!m)
206 return NULL;
207
208 if (m->compress_info)
209 return m->compress_info;
210
211 /* Open is compulsory */
212 const char *o = mutt_find_hook(MUTT_OPEN_HOOK, mailbox_path(m));
213 if (!o)
214 return NULL;
215
216 const char *c = mutt_find_hook(MUTT_CLOSE_HOOK, mailbox_path(m));
217 const char *a = mutt_find_hook(MUTT_APPEND_HOOK, mailbox_path(m));
218
219 struct CompressInfo *ci = mutt_mem_calloc(1, sizeof(struct CompressInfo));
220 m->compress_info = ci;
221
222 ci->cmd_open = mutt_str_dup(o);
223 ci->cmd_close = mutt_str_dup(c);
224 ci->cmd_append = mutt_str_dup(a);
225
226 return ci;
227}
228
233static void compress_info_free(struct Mailbox *m)
234{
235 if (!m || !m->compress_info)
236 return;
237
238 struct CompressInfo *ci = m->compress_info;
239 FREE(&ci->cmd_open);
240 FREE(&ci->cmd_close);
241 FREE(&ci->cmd_append);
242
244
245 FREE(&m->compress_info);
246}
247
256static const char *compress_format_str(char *buf, size_t buflen, size_t col, int cols,
257 char op, const char *src, const char *prec,
258 const char *if_str, const char *else_str,
259 intptr_t data, MuttFormatFlags flags)
260{
261 if (!buf || (data == 0))
262 return src;
263
264 struct Mailbox *m = (struct Mailbox *) data;
265
266 /* NOTE the compressed file config vars expect %f and %t to be
267 * surrounded by '' (unlike other NeoMutt config vars, which add the
268 * outer quotes for the user). This is why we use the
269 * buf_quote_filename() form with add_outer of false. */
270 struct Buffer *quoted = buf_pool_get();
271 switch (op)
272 {
273 case 'f':
274 /* Compressed file */
275 buf_quote_filename(quoted, m->realpath, false);
276 snprintf(buf, buflen, "%s", buf_string(quoted));
277 break;
278 case 't':
279 /* Plaintext, temporary file */
280 buf_quote_filename(quoted, mailbox_path(m), false);
281 snprintf(buf, buflen, "%s", buf_string(quoted));
282 break;
283 }
284
285 buf_pool_release(&quoted);
286 return src;
287}
288
300static bool execute_command(struct Mailbox *m, const char *command, const char *progress)
301{
302 if (!m || !command || !progress)
303 return false;
304
305 if (m->verbose)
306 mutt_message(progress, m->realpath);
307
308 bool rc = true;
309 struct Buffer *sys_cmd = buf_pool_get();
310 buf_alloc(sys_cmd, STR_COMMAND);
311
313 endwin();
314 fflush(stdout);
315
316 mutt_expando_format(sys_cmd->data, sys_cmd->dsize, 0, sys_cmd->dsize, command,
318
319 if (mutt_system(buf_string(sys_cmd)) != 0)
320 {
321 rc = false;
323 mutt_error(_("Error running \"%s\""), buf_string(sys_cmd));
324 }
325
327
328 buf_pool_release(&sys_cmd);
329 return rc;
330}
331
344{
345 if (!m)
346 return false;
347
348 /* If this succeeds, we know there's an open-hook */
349 struct CompressInfo *ci = set_compress_info(m);
350 if (!ci)
351 return false;
352
353 /* We have an open-hook, so to append we need an append-hook,
354 * or a close-hook. */
355 if (ci->cmd_append || ci->cmd_close)
356 return true;
357
358 mutt_error(_("Can't append without an append-hook or close-hook : %s"), mailbox_path(m));
359 return false;
360}
361
372bool mutt_comp_can_read(const char *path)
373{
374 if (!path)
375 return false;
376
378 return true;
379
380 return false;
381}
382
392int mutt_comp_valid_command(const char *cmd)
393{
394 if (!cmd)
395 return 0;
396
397 return strstr(cmd, "%f") && strstr(cmd, "%t");
398}
399
403static bool comp_ac_owns_path(struct Account *a, const char *path)
404{
405 return false;
406}
407
411static bool comp_ac_add(struct Account *a, struct Mailbox *m)
412{
413 return true;
414}
415
425{
426 struct CompressInfo *ci = set_compress_info(m);
427 if (!ci)
428 return MX_OPEN_ERROR;
429
430 /* If there's no close-hook, or the file isn't writable */
431 if (!ci->cmd_close || (access(mailbox_path(m), W_OK) != 0))
432 m->readonly = true;
433
434 if (setup_paths(m) != 0)
435 goto cmo_fail;
436 store_size(m);
437
438 if (!lock_realpath(m, false))
439 {
440 mutt_error(_("Unable to lock mailbox"));
441 goto cmo_fail;
442 }
443
444 if (!execute_command(m, ci->cmd_open, _("Decompressing %s")))
445 goto cmo_fail;
446
448
450 if (m->type == MUTT_UNKNOWN)
451 {
452 mutt_error(_("Can't identify the contents of the compressed file"));
453 goto cmo_fail;
454 }
455
456 ci->child_ops = mx_get_ops(m->type);
457 if (!ci->child_ops)
458 {
459 mutt_error(_("Can't find mailbox ops for mailbox type %d"), m->type);
460 goto cmo_fail;
461 }
462
463 m->account->type = m->type;
464 return ci->child_ops->mbox_open(m);
465
466cmo_fail:
467 /* remove the partial uncompressed file */
468 (void) remove(mailbox_path(m));
470 return MX_OPEN_ERROR;
471}
472
481static bool comp_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
482{
483 /* If this succeeds, we know there's an open-hook */
484 struct CompressInfo *ci = set_compress_info(m);
485 if (!ci)
486 return false;
487
488 /* To append we need an append-hook or a close-hook */
489 if (!ci->cmd_append && !ci->cmd_close)
490 {
491 mutt_error(_("Can't append without an append-hook or close-hook : %s"),
492 mailbox_path(m));
493 goto cmoa_fail1;
494 }
495
496 if (setup_paths(m) != 0)
497 goto cmoa_fail2;
498
499 /* Lock the realpath for the duration of the append.
500 * It will be unlocked in the close */
501 if (!lock_realpath(m, true))
502 {
503 mutt_error(_("Unable to lock mailbox"));
504 goto cmoa_fail2;
505 }
506
507 /* Open the existing mailbox, unless we are appending */
508 if (!ci->cmd_append && (mutt_file_get_size(m->realpath) > 0))
509 {
510 if (!execute_command(m, ci->cmd_open, _("Decompressing %s")))
511 {
512 mutt_error(_("Compress command failed: %s"), ci->cmd_open);
513 goto cmoa_fail2;
514 }
516 }
517 else
518 {
519 m->type = cs_subset_enum(NeoMutt->sub, "mbox_type");
520 }
521
522 /* We can only deal with mbox and mmdf mailboxes */
523 if ((m->type != MUTT_MBOX) && (m->type != MUTT_MMDF))
524 {
525 mutt_error(_("Unsupported mailbox type for appending"));
526 goto cmoa_fail2;
527 }
528
529 ci->child_ops = mx_get_ops(m->type);
530 if (!ci->child_ops)
531 {
532 mutt_error(_("Can't find mailbox ops for mailbox type %d"), m->type);
533 goto cmoa_fail2;
534 }
535
536 if (!ci->child_ops->mbox_open_append(m, flags))
537 goto cmoa_fail2;
538
539 return true;
540
541cmoa_fail2:
542 /* remove the partial uncompressed file */
543 (void) remove(mailbox_path(m));
544cmoa_fail1:
545 /* Free the compress_info to prevent close from trying to recompress */
547
548 return false;
549}
550
561static enum MxStatus comp_mbox_check(struct Mailbox *m)
562{
563 if (!m->compress_info)
564 return MX_STATUS_ERROR;
565
566 struct CompressInfo *ci = m->compress_info;
567
568 const struct MxOps *ops = ci->child_ops;
569 if (!ops)
570 return MX_STATUS_ERROR;
571
572 int size = mutt_file_get_size(m->realpath);
573 if (size == ci->size)
574 return MX_STATUS_OK;
575
576 if (!lock_realpath(m, false))
577 {
578 mutt_error(_("Unable to lock mailbox"));
579 return MX_STATUS_ERROR;
580 }
581
582 bool rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
583 store_size(m);
585 if (!rc)
586 return MX_STATUS_ERROR;
587
588 return ops->mbox_check(m);
589}
590
597static enum MxStatus comp_mbox_sync(struct Mailbox *m)
598{
599 if (!m->compress_info)
600 return MX_STATUS_ERROR;
601
602 struct CompressInfo *ci = m->compress_info;
603
604 if (!ci->cmd_close)
605 {
606 mutt_error(_("Can't sync a compressed file without a close-hook"));
607 return MX_STATUS_ERROR;
608 }
609
610 const struct MxOps *ops = ci->child_ops;
611 if (!ops)
612 return MX_STATUS_ERROR;
613
614 if (!lock_realpath(m, true))
615 {
616 mutt_error(_("Unable to lock mailbox"));
617 return MX_STATUS_ERROR;
618 }
619
620 enum MxStatus check = comp_mbox_check(m);
621 if (check != MX_STATUS_OK)
622 goto sync_cleanup;
623
624 check = ops->mbox_sync(m);
625 if (check != MX_STATUS_OK)
626 goto sync_cleanup;
627
628 if (!execute_command(m, ci->cmd_close, _("Compressing %s")))
629 {
630 check = MX_STATUS_ERROR;
631 goto sync_cleanup;
632 }
633
634 check = MX_STATUS_OK;
635
636sync_cleanup:
637 store_size(m);
639 return check;
640}
641
648static enum MxStatus comp_mbox_close(struct Mailbox *m)
649{
650 if (!m->compress_info)
651 return MX_STATUS_ERROR;
652
653 struct CompressInfo *ci = m->compress_info;
654
655 const struct MxOps *ops = ci->child_ops;
656 if (!ops)
657 {
659 return MX_STATUS_ERROR;
660 }
661
662 ops->mbox_close(m);
663
664 /* sync has already been called, so we only need to delete some files */
665 if (m->append)
666 {
667 const char *append = NULL;
668 const char *msg = NULL;
669
670 /* The file exists and we can append */
671 if ((access(m->realpath, F_OK) == 0) && ci->cmd_append)
672 {
673 append = ci->cmd_append;
674 msg = _("Compressed-appending to %s...");
675 }
676 else
677 {
678 append = ci->cmd_close;
679 msg = _("Compressing %s");
680 }
681
682 if (!execute_command(m, append, msg))
683 {
685 mutt_error(_("Error. Preserving temporary file: %s"), mailbox_path(m));
686 }
687 else
688 {
689 if (remove(mailbox_path(m)) < 0)
690 {
691 mutt_debug(LL_DEBUG1, "remove failed: %s: %s (errno %d)\n",
692 mailbox_path(m), strerror(errno), errno);
693 }
694 }
695
697 }
698 else
699 {
700 /* If the file was removed, remove the compressed folder too */
701 if (access(mailbox_path(m), F_OK) != 0)
702 {
703 const bool c_save_empty = cs_subset_bool(NeoMutt->sub, "save_empty");
704 if (!c_save_empty)
705 {
706 if (remove(m->realpath) < 0)
707 {
708 mutt_debug(LL_DEBUG1, "remove failed: %s: %s (errno %d)\n",
709 m->realpath, strerror(errno), errno);
710 }
711 }
712 }
713 else
714 {
715 if (remove(mailbox_path(m)) < 0)
716 {
717 mutt_debug(LL_DEBUG1, "remove failed: %s: %s (errno %d)\n",
718 mailbox_path(m), strerror(errno), errno);
719 }
720 }
721 }
722
724
725 return MX_STATUS_OK;
726}
727
731static bool comp_msg_open(struct Mailbox *m, struct Message *msg, struct Email *e)
732{
733 if (!m->compress_info)
734 return false;
735
736 struct CompressInfo *ci = m->compress_info;
737
738 const struct MxOps *ops = ci->child_ops;
739 if (!ops)
740 return false;
741
742 /* Delegate */
743 return ops->msg_open(m, msg, e);
744}
745
749static bool comp_msg_open_new(struct Mailbox *m, struct Message *msg, const struct Email *e)
750{
751 if (!m->compress_info)
752 return false;
753
754 struct CompressInfo *ci = m->compress_info;
755
756 const struct MxOps *ops = ci->child_ops;
757 if (!ops)
758 return false;
759
760 /* Delegate */
761 return ops->msg_open_new(m, msg, e);
762}
763
767static int comp_msg_commit(struct Mailbox *m, struct Message *msg)
768{
769 if (!m->compress_info)
770 return -1;
771
772 struct CompressInfo *ci = m->compress_info;
773
774 const struct MxOps *ops = ci->child_ops;
775 if (!ops)
776 return -1;
777
778 /* Delegate */
779 return ops->msg_commit(m, msg);
780}
781
785static int comp_msg_close(struct Mailbox *m, struct Message *msg)
786{
787 if (!m->compress_info)
788 return -1;
789
790 struct CompressInfo *ci = m->compress_info;
791
792 const struct MxOps *ops = ci->child_ops;
793 if (!ops)
794 return -1;
795
796 /* Delegate */
797 return ops->msg_close(m, msg);
798}
799
803static int comp_msg_padding_size(struct Mailbox *m)
804{
805 if (!m->compress_info)
806 return 0;
807
808 struct CompressInfo *ci = m->compress_info;
809
810 const struct MxOps *ops = ci->child_ops;
811 if (!ops || !ops->msg_padding_size)
812 return 0;
813
814 return ops->msg_padding_size(m);
815}
816
820static int comp_msg_save_hcache(struct Mailbox *m, struct Email *e)
821{
822 if (!m->compress_info)
823 return 0;
824
825 struct CompressInfo *ci = m->compress_info;
826
827 const struct MxOps *ops = ci->child_ops;
828 if (!ops || !ops->msg_save_hcache)
829 return 0;
830
831 return ops->msg_save_hcache(m, e);
832}
833
837static int comp_tags_edit(struct Mailbox *m, const char *tags, struct Buffer *buf)
838{
839 if (!m->compress_info)
840 return 0;
841
842 struct CompressInfo *ci = m->compress_info;
843
844 const struct MxOps *ops = ci->child_ops;
845 if (!ops || !ops->tags_edit)
846 return 0;
847
848 return ops->tags_edit(m, tags, buf);
849}
850
854static int comp_tags_commit(struct Mailbox *m, struct Email *e, const char *buf)
855{
856 if (!m->compress_info)
857 return 0;
858
859 struct CompressInfo *ci = m->compress_info;
860
861 const struct MxOps *ops = ci->child_ops;
862 if (!ops || !ops->tags_commit)
863 return 0;
864
865 return ops->tags_commit(m, e, buf);
866}
867
871static enum MailboxType comp_path_probe(const char *path, const struct stat *st)
872{
873 if (!st || !S_ISREG(st->st_mode))
874 return MUTT_UNKNOWN;
875
876 if (mutt_comp_can_read(path))
877 return MUTT_COMPRESSED;
878
879 return MUTT_UNKNOWN;
880}
881
885static int comp_path_canon(struct Buffer *path)
886{
887 mutt_path_canon(path, HomeDir, false);
888 return 0;
889}
890
897const struct MxOps MxCompOps = {
898 // clang-format off
900 .name = "compressed",
901 .is_local = true,
902 .ac_owns_path = comp_ac_owns_path,
903 .ac_add = comp_ac_add,
904 .mbox_open = comp_mbox_open,
905 .mbox_open_append = comp_mbox_open_append,
906 .mbox_check = comp_mbox_check,
907 .mbox_check_stats = NULL,
908 .mbox_sync = comp_mbox_sync,
909 .mbox_close = comp_mbox_close,
910 .msg_open = comp_msg_open,
911 .msg_open_new = comp_msg_open_new,
912 .msg_commit = comp_msg_commit,
913 .msg_close = comp_msg_close,
914 .msg_padding_size = comp_msg_padding_size,
915 .msg_save_hcache = comp_msg_save_hcache,
916 .tags_edit = comp_tags_edit,
917 .tags_commit = comp_tags_commit,
918 .path_probe = comp_path_probe,
919 .path_canon = comp_path_canon,
920 .path_is_empty = NULL,
921 // clang-format on
922};
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:618
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:354
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:97
static struct CompressInfo * set_compress_info(struct Mailbox *m)
Find the compress hooks for a mailbox.
Definition: compress.c:203
static void compress_info_free(struct Mailbox *m)
Frees the compress info members and structure.
Definition: compress.c:233
static int setup_paths(struct Mailbox *m)
Set the mailbox paths.
Definition: compress.c:157
void mutt_comp_init(void)
Setup feature commands.
Definition: compress.c:74
static void store_size(const struct Mailbox *m)
Save the size of the compressed file.
Definition: compress.c:185
static bool lock_realpath(struct Mailbox *m, bool excl)
Try to lock the Mailbox.realpath.
Definition: compress.c:90
bool mutt_comp_can_append(struct Mailbox *m)
Can we append to this path?
Definition: compress.c:343
static void unlock_realpath(struct Mailbox *m)
Unlock the mailbox->realpath.
Definition: compress.c:131
static const struct Command CompCommands[]
Compression Commands.
Definition: compress.c:63
static bool execute_command(struct Mailbox *m, const char *command, const char *progress)
Run a system command.
Definition: compress.c:300
int mutt_comp_valid_command(const char *cmd)
Is this command string allowed?
Definition: compress.c:392
bool mutt_comp_can_read(const char *path)
Can we read from this file?
Definition: compress.c:372
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition: helpers.c:72
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
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.
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:211
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
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:175
void buf_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell's quoting rules.
Definition: file.c:974
int mutt_file_lock(int fd, bool excl, bool timeout)
(Try to) Lock a file using fcntl()
Definition: file.c:1243
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1290
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1560
#define mutt_file_fclose(FP)
Definition: file.h:148
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:147
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:162
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:256
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:740
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
#define mutt_perror(...)
Definition: logging2.h:93
static bool comp_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Implements MxOps::ac_add() -.
Definition: compress.c:411
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:403
const struct MxOps MxCompOps
Compressed Mailbox - Implements MxOps -.
Definition: compress.c:897
static enum MxStatus comp_mbox_check(struct Mailbox *m)
Check for new mail - Implements MxOps::mbox_check() -.
Definition: compress.c:561
static enum MxStatus comp_mbox_close(struct Mailbox *m)
Close a Mailbox - Implements MxOps::mbox_close() -.
Definition: compress.c:648
static bool comp_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a Mailbox for appending - Implements MxOps::mbox_open_append() -.
Definition: compress.c:481
static enum MxOpenReturns comp_mbox_open(struct Mailbox *m)
Open a Mailbox - Implements MxOps::mbox_open() -.
Definition: compress.c:424
static enum MxStatus comp_mbox_sync(struct Mailbox *m)
Save changes to the Mailbox - Implements MxOps::mbox_sync() -.
Definition: compress.c:597
static int comp_msg_close(struct Mailbox *m, struct Message *msg)
Close an email - Implements MxOps::msg_close() -.
Definition: compress.c:785
static int comp_msg_commit(struct Mailbox *m, struct Message *msg)
Save changes to an email - Implements MxOps::msg_commit() -.
Definition: compress.c:767
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:749
static bool comp_msg_open(struct Mailbox *m, struct Message *msg, struct Email *e)
Open an email message in a Mailbox - Implements MxOps::msg_open() -.
Definition: compress.c:731
static int comp_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Implements MxOps::msg_padding_size() -.
Definition: compress.c:803
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:820
static int comp_path_canon(struct Buffer *path)
Canonicalise a Mailbox path - Implements MxOps::path_canon() -.
Definition: compress.c:885
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:871
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:854
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:837
Convenience wrapper for the gui headers.
char * mutt_find_hook(HookFlags type, const char *pat)
Find a matching hook.
Definition: hook.c:650
Parse and execute user-defined hooks.
#define MUTT_OPEN_HOOK
open-hook: to read a compressed mailbox
Definition: hook.h:49
#define MUTT_CLOSE_HOOK
close-hook: write to a compressed mailbox
Definition: hook.h:51
#define MUTT_APPEND_HOOK
append-hook: append to a compressed mailbox
Definition: hook.h:50
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
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:45
#define mutt_array_size(x)
Definition: memory.h:38
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
bool mutt_path_canon(struct Buffer *path, const char *homedir, bool is_dir)
Create the canonical version of a path.
Definition: path.c:247
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:329
Some miscellaneous functions.
const struct MxOps * mx_get_ops(enum MailboxType type)
Get mailbox operations.
Definition: mx.c:125
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1319
API for mailboxes.
uint8_t OpenMailboxFlags
Flags for mutt_open_mailbox(), e.g. MUTT_NOSORT.
Definition: mxapi.h:39
MxOpenReturns
Return values for mbox_open()
Definition: mxapi.h:76
@ MX_OPEN_ERROR
Open failed with an error.
Definition: mxapi.h:78
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_sync(), and mbox_close()
Definition: mxapi.h:63
@ MX_STATUS_ERROR
An error occurred.
Definition: mxapi.h:64
@ MX_STATUS_OK
No changes.
Definition: mxapi.h:65
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
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:166
void mutt_sig_unblock(void)
Restore previously blocked signals.
Definition: signal.c:184
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:36
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:37
String manipulation buffer.
Definition: buffer.h:36
size_t dsize
Length of data.
Definition: buffer.h:39
char * data
Pointer to data.
Definition: buffer.h:37
Private data for compress.
Definition: lib.h:46
const char * cmd_append
append-hook command
Definition: lib.h:47
FILE * fp_lock
fp used for locking
Definition: lib.h:53
const char * cmd_open
open-hook command
Definition: lib.h:49
const struct MxOps * child_ops
callbacks of de-compressed file
Definition: lib.h:51
bool locked
if realpath is locked
Definition: lib.h:52
const char * cmd_close
close-hook command
Definition: lib.h:48
long size
size of the compressed file
Definition: lib.h:50
The envelope/body of an email.
Definition: email.h:39
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:121
bool readonly
Don't allow changes to the mailbox.
Definition: mailbox.h:116
bool verbose
Display status messages?
Definition: mailbox.h:117
A local copy of an email.
Definition: message.h:34
Definition: mxapi.h:91
bool(* msg_open)(struct Mailbox *m, struct Message *msg, struct Email *e)
Definition: mxapi.h:216
int(* tags_commit)(struct Mailbox *m, struct Email *e, const char *buf)
Definition: mxapi.h:323
int(* msg_save_hcache)(struct Mailbox *m, struct Email *e)
Definition: mxapi.h:289
enum MailboxType type
Mailbox type, e.g. MUTT_IMAP.
Definition: mxapi.h:92
int(* msg_padding_size)(struct Mailbox *m)
Definition: mxapi.h:274
int(* tags_edit)(struct Mailbox *m, const char *tags, struct Buffer *buf)
Definition: mxapi.h:306
int(* msg_commit)(struct Mailbox *m, struct Message *msg)
Definition: mxapi.h:247
enum MxOpenReturns(* mbox_open)(struct Mailbox *m)
Definition: mxapi.h:136
int(* msg_close)(struct Mailbox *m, struct Message *msg)
Definition: mxapi.h:262
bool(* msg_open_new)(struct Mailbox *m, struct Message *msg, const struct Email *e)
Definition: mxapi.h:232
enum MxStatus(* mbox_close)(struct Mailbox *m)
Definition: mxapi.h:199
enum MxStatus(* mbox_sync)(struct Mailbox *m)
Definition: mxapi.h:187
bool(* mbox_open_append)(struct Mailbox *m, OpenMailboxFlags flags)
Definition: mxapi.h:150
enum MxStatus(* mbox_check)(struct Mailbox *m)
Definition: mxapi.h:162
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
#define buf_mktemp(buf)
Definition: tmp.h:33