NeoMutt  2024-04-16-36-g75b6fb
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
compress.c
Go to the documentation of this file.
1
39#include "config.h"
40#include <errno.h>
41#include <stdbool.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 "expando/lib.h"
52#include "globals.h"
53#include "hook.h"
54#include "mx.h"
55#include "protos.h"
56
57struct Email;
58
60
64static const struct Command CompCommands[] = {
65 // clang-format off
66 { "append-hook", mutt_parse_hook, MUTT_APPEND_HOOK },
67 { "close-hook", mutt_parse_hook, MUTT_CLOSE_HOOK },
68 { "open-hook", mutt_parse_hook, MUTT_OPEN_HOOK },
69 // clang-format on
70};
71
81 // clang-format off
82 { "f", "from", ED_COMPRESS, ED_CMP_FROM, E_TYPE_STRING, NULL },
83 { "t", "to", ED_COMPRESS, ED_CMP_TO, E_TYPE_STRING, NULL },
84 { NULL, NULL, 0, -1, -1, NULL }
85 // clang-format on
86};
87
92{
94}
95
107static bool lock_realpath(struct Mailbox *m, bool excl)
108{
109 if (!m || !m->compress_info)
110 return false;
111
112 struct CompressInfo *ci = m->compress_info;
113
114 if (ci->locked)
115 return true;
116
117 if (excl)
118 ci->fp_lock = mutt_file_fopen(m->realpath, "a");
119 else
120 ci->fp_lock = mutt_file_fopen(m->realpath, "r");
121 if (!ci->fp_lock)
122 {
123 mutt_perror("%s", m->realpath);
124 return false;
125 }
126
127 int r = mutt_file_lock(fileno(ci->fp_lock), excl, true);
128 if (r == 0)
129 {
130 ci->locked = true;
131 }
132 else if (excl)
133 {
135 m->readonly = true;
136 return true;
137 }
138
139 return r == 0;
140}
141
148static void unlock_realpath(struct Mailbox *m)
149{
150 if (!m || !m->compress_info)
151 return;
152
153 struct CompressInfo *ci = m->compress_info;
154
155 if (!ci->locked)
156 return;
157
158 mutt_file_unlock(fileno(ci->fp_lock));
159
160 ci->locked = false;
162}
163
174static int setup_paths(struct Mailbox *m)
175{
176 if (!m)
177 return -1;
178
179 /* Setup the right paths */
181
182 /* We will uncompress to TMPDIR */
183 struct Buffer *buf = buf_pool_get();
184 buf_mktemp(buf);
185 buf_copy(&m->pathbuf, buf);
186 buf_pool_release(&buf);
187
188 FILE *fp = mutt_file_fopen(mailbox_path(m), "w");
189 if (!fp)
190 return -1;
191
192 mutt_file_fclose(&fp);
193 return 0;
194}
195
202static void store_size(const struct Mailbox *m)
203{
204 if (!m || !m->compress_info)
205 return;
206
207 struct CompressInfo *ci = m->compress_info;
208
210}
211
217static struct Expando *validate_compress_expando(const char *s)
218{
219 struct Buffer *err = buf_pool_get();
220
221 struct Expando *exp = expando_parse(s, CompressFormatDef, err);
222 if (!exp)
223 {
224 mutt_error(_("Expando parse error: %s"), buf_string(err));
225 }
226
227 buf_pool_release(&err);
228 return exp;
229}
230
239static struct CompressInfo *set_compress_info(struct Mailbox *m)
240{
241 if (!m)
242 return NULL;
243
244 if (m->compress_info)
245 return m->compress_info;
246
247 /* Open is compulsory */
248 const char *o = mutt_find_hook(MUTT_OPEN_HOOK, mailbox_path(m));
249 if (!o)
250 return NULL;
251
252 const char *c = mutt_find_hook(MUTT_CLOSE_HOOK, mailbox_path(m));
253 const char *a = mutt_find_hook(MUTT_APPEND_HOOK, mailbox_path(m));
254
255 struct CompressInfo *ci = mutt_mem_calloc(1, sizeof(struct CompressInfo));
256 m->compress_info = ci;
257
261
262 return ci;
263}
264
269static void compress_info_free(struct Mailbox *m)
270{
271 if (!m || !m->compress_info)
272 return;
273
274 struct CompressInfo *ci = m->compress_info;
278
280
281 FREE(&m->compress_info);
282}
283
287void compress_f(const struct ExpandoNode *node, void *data,
288 MuttFormatFlags flags, int max_cols, struct Buffer *buf)
289{
290 const struct Mailbox *m = data;
291
292 struct Buffer *quoted = buf_pool_get();
293 buf_quote_filename(quoted, m->realpath, false);
294 buf_copy(buf, quoted);
295 buf_pool_release(&quoted);
296}
297
301void compress_t(const struct ExpandoNode *node, void *data,
302 MuttFormatFlags flags, int max_cols, struct Buffer *buf)
303{
304 const struct Mailbox *m = data;
305
306 struct Buffer *quoted = buf_pool_get();
307 buf_quote_filename(quoted, mailbox_path(m), false);
308 buf_copy(buf, quoted);
309 buf_pool_release(&quoted);
310}
311
323static bool execute_command(struct Mailbox *m, const struct Expando *exp, const char *progress)
324{
325 if (!m || !exp || !progress)
326 return false;
327
328 if (m->verbose)
329 mutt_message(progress, m->realpath);
330
331 bool rc = true;
332 struct Buffer *sys_cmd = buf_pool_get();
333 buf_alloc(sys_cmd, STR_COMMAND);
334
336 mutt_endwin();
337 fflush(stdout);
338
339 expando_render(exp, CompressRenderData, m, MUTT_FORMAT_NO_FLAGS, sys_cmd->dsize, sys_cmd);
340
341 if (mutt_system(buf_string(sys_cmd)) != 0)
342 {
343 rc = false;
345 mutt_error(_("Error running \"%s\""), buf_string(sys_cmd));
346 }
347
349
350 buf_pool_release(&sys_cmd);
351 return rc;
352}
353
366{
367 if (!m)
368 return false;
369
370 /* If this succeeds, we know there's an open-hook */
371 struct CompressInfo *ci = set_compress_info(m);
372 if (!ci)
373 return false;
374
375 /* We have an open-hook, so to append we need an append-hook,
376 * or a close-hook. */
377 if (ci->cmd_append || ci->cmd_close)
378 return true;
379
380 mutt_error(_("Can't append without an append-hook or close-hook : %s"), mailbox_path(m));
381 return false;
382}
383
394bool mutt_comp_can_read(const char *path)
395{
396 if (!path)
397 return false;
398
400 return true;
401
402 return false;
403}
404
414int mutt_comp_valid_command(const char *cmd)
415{
416 if (!cmd)
417 return 0;
418
419 return strstr(cmd, "%f") && strstr(cmd, "%t");
420}
421
425static bool comp_ac_owns_path(struct Account *a, const char *path)
426{
427 return false;
428}
429
433static bool comp_ac_add(struct Account *a, struct Mailbox *m)
434{
435 return true;
436}
437
447{
448 struct CompressInfo *ci = set_compress_info(m);
449 if (!ci)
450 return MX_OPEN_ERROR;
451
452 /* If there's no close-hook, or the file isn't writable */
453 if (!ci->cmd_close || (access(mailbox_path(m), W_OK) != 0))
454 m->readonly = true;
455
456 if (setup_paths(m) != 0)
457 goto cmo_fail;
458 store_size(m);
459
460 if (!lock_realpath(m, false))
461 {
462 mutt_error(_("Unable to lock mailbox"));
463 goto cmo_fail;
464 }
465
466 if (!execute_command(m, ci->cmd_open, _("Decompressing %s")))
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 if (!execute_command(m, ci->cmd_open, _("Decompressing %s")))
533 {
534 mutt_error(_("Compress command failed: %s"), ci->cmd_open->string);
535 goto cmoa_fail2;
536 }
538 }
539 else
540 {
541 m->type = cs_subset_enum(NeoMutt->sub, "mbox_type");
542 }
543
544 /* We can only deal with mbox and mmdf mailboxes */
545 if ((m->type != MUTT_MBOX) && (m->type != MUTT_MMDF))
546 {
547 mutt_error(_("Unsupported mailbox type for appending"));
548 goto cmoa_fail2;
549 }
550
551 ci->child_ops = mx_get_ops(m->type);
552 if (!ci->child_ops)
553 {
554 mutt_error(_("Can't find mailbox ops for mailbox type %d"), m->type);
555 goto cmoa_fail2;
556 }
557
558 if (!ci->child_ops->mbox_open_append(m, flags))
559 goto cmoa_fail2;
560
561 return true;
562
563cmoa_fail2:
564 /* remove the partial uncompressed file */
565 (void) remove(mailbox_path(m));
566cmoa_fail1:
567 /* Free the compress_info to prevent close from trying to recompress */
569
570 return false;
571}
572
583static enum MxStatus comp_mbox_check(struct Mailbox *m)
584{
585 if (!m->compress_info)
586 return MX_STATUS_ERROR;
587
588 struct CompressInfo *ci = m->compress_info;
589
590 const struct MxOps *ops = ci->child_ops;
591 if (!ops)
592 return MX_STATUS_ERROR;
593
594 int size = mutt_file_get_size(m->realpath);
595 if (size == ci->size)
596 return MX_STATUS_OK;
597
598 if (!lock_realpath(m, false))
599 {
600 mutt_error(_("Unable to lock mailbox"));
601 return MX_STATUS_ERROR;
602 }
603
604 bool rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
605 store_size(m);
607 if (!rc)
608 return MX_STATUS_ERROR;
609
610 return ops->mbox_check(m);
611}
612
619static enum MxStatus comp_mbox_sync(struct Mailbox *m)
620{
621 if (!m->compress_info)
622 return MX_STATUS_ERROR;
623
624 struct CompressInfo *ci = m->compress_info;
625
626 if (!ci->cmd_close)
627 {
628 mutt_error(_("Can't sync a compressed file without a close-hook"));
629 return MX_STATUS_ERROR;
630 }
631
632 const struct MxOps *ops = ci->child_ops;
633 if (!ops)
634 return MX_STATUS_ERROR;
635
636 if (!lock_realpath(m, true))
637 {
638 mutt_error(_("Unable to lock mailbox"));
639 return MX_STATUS_ERROR;
640 }
641
642 enum MxStatus check = comp_mbox_check(m);
643 if (check != MX_STATUS_OK)
644 goto sync_cleanup;
645
646 check = ops->mbox_sync(m);
647 if (check != MX_STATUS_OK)
648 goto sync_cleanup;
649
650 if (!execute_command(m, ci->cmd_close, _("Compressing %s")))
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 struct Expando *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 if (!execute_command(m, append, msg))
705 {
707 mutt_error(_("Error. Preserving temporary file: %s"), mailbox_path(m));
708 }
709 else
710 {
711 if (remove(mailbox_path(m)) < 0)
712 {
713 mutt_debug(LL_DEBUG1, "remove failed: %s: %s (errno %d)\n",
714 mailbox_path(m), strerror(errno), errno);
715 }
716 }
717
719 }
720 else
721 {
722 /* If the file was removed, remove the compressed folder too */
723 if (access(mailbox_path(m), F_OK) != 0)
724 {
725 const bool c_save_empty = cs_subset_bool(NeoMutt->sub, "save_empty");
726 if (!c_save_empty)
727 {
728 if (remove(m->realpath) < 0)
729 {
730 mutt_debug(LL_DEBUG1, "remove failed: %s: %s (errno %d)\n",
731 m->realpath, strerror(errno), errno);
732 }
733 }
734 }
735 else
736 {
737 if (remove(mailbox_path(m)) < 0)
738 {
739 mutt_debug(LL_DEBUG1, "remove failed: %s: %s (errno %d)\n",
740 mailbox_path(m), strerror(errno), errno);
741 }
742 }
743 }
744
746
747 return MX_STATUS_OK;
748}
749
753static bool comp_msg_open(struct Mailbox *m, struct Message *msg, struct Email *e)
754{
755 if (!m->compress_info)
756 return false;
757
758 struct CompressInfo *ci = m->compress_info;
759
760 const struct MxOps *ops = ci->child_ops;
761 if (!ops)
762 return false;
763
764 /* Delegate */
765 return ops->msg_open(m, msg, e);
766}
767
771static bool comp_msg_open_new(struct Mailbox *m, struct Message *msg, const struct Email *e)
772{
773 if (!m->compress_info)
774 return false;
775
776 struct CompressInfo *ci = m->compress_info;
777
778 const struct MxOps *ops = ci->child_ops;
779 if (!ops)
780 return false;
781
782 /* Delegate */
783 return ops->msg_open_new(m, msg, e);
784}
785
789static int comp_msg_commit(struct Mailbox *m, struct Message *msg)
790{
791 if (!m->compress_info)
792 return -1;
793
794 struct CompressInfo *ci = m->compress_info;
795
796 const struct MxOps *ops = ci->child_ops;
797 if (!ops)
798 return -1;
799
800 /* Delegate */
801 return ops->msg_commit(m, msg);
802}
803
807static int comp_msg_close(struct Mailbox *m, struct Message *msg)
808{
809 if (!m->compress_info)
810 return -1;
811
812 struct CompressInfo *ci = m->compress_info;
813
814 const struct MxOps *ops = ci->child_ops;
815 if (!ops)
816 return -1;
817
818 /* Delegate */
819 return ops->msg_close(m, msg);
820}
821
825static int comp_msg_padding_size(struct Mailbox *m)
826{
827 if (!m->compress_info)
828 return 0;
829
830 struct CompressInfo *ci = m->compress_info;
831
832 const struct MxOps *ops = ci->child_ops;
833 if (!ops || !ops->msg_padding_size)
834 return 0;
835
836 return ops->msg_padding_size(m);
837}
838
842static int comp_msg_save_hcache(struct Mailbox *m, struct Email *e)
843{
844 if (!m->compress_info)
845 return 0;
846
847 struct CompressInfo *ci = m->compress_info;
848
849 const struct MxOps *ops = ci->child_ops;
850 if (!ops || !ops->msg_save_hcache)
851 return 0;
852
853 return ops->msg_save_hcache(m, e);
854}
855
859static int comp_tags_edit(struct Mailbox *m, const char *tags, struct Buffer *buf)
860{
861 if (!m->compress_info)
862 return 0;
863
864 struct CompressInfo *ci = m->compress_info;
865
866 const struct MxOps *ops = ci->child_ops;
867 if (!ops || !ops->tags_edit)
868 return 0;
869
870 return ops->tags_edit(m, tags, buf);
871}
872
876static int comp_tags_commit(struct Mailbox *m, struct Email *e, const char *buf)
877{
878 if (!m->compress_info)
879 return 0;
880
881 struct CompressInfo *ci = m->compress_info;
882
883 const struct MxOps *ops = ci->child_ops;
884 if (!ops || !ops->tags_commit)
885 return 0;
886
887 return ops->tags_commit(m, e, buf);
888}
889
893static enum MailboxType comp_path_probe(const char *path, const struct stat *st)
894{
895 if (!st || !S_ISREG(st->st_mode))
896 return MUTT_UNKNOWN;
897
898 if (mutt_comp_can_read(path))
899 return MUTT_COMPRESSED;
900
901 return MUTT_UNKNOWN;
902}
903
907static int comp_path_canon(struct Buffer *path)
908{
909 mutt_path_canon(path, HomeDir, false);
910 return 0;
911}
912
918const struct ExpandoRenderData CompressRenderData[] = {
919 // clang-format off
921 { ED_COMPRESS, ED_CMP_TO, compress_t, NULL },
922 { -1, -1, NULL, NULL },
923 // clang-format on
924};
925
932const struct MxOps MxCompOps = {
933 // clang-format off
935 .name = "compressed",
936 .is_local = true,
937 .ac_owns_path = comp_ac_owns_path,
938 .ac_add = comp_ac_add,
939 .mbox_open = comp_mbox_open,
940 .mbox_open_append = comp_mbox_open_append,
941 .mbox_check = comp_mbox_check,
942 .mbox_check_stats = NULL,
943 .mbox_sync = comp_mbox_sync,
944 .mbox_close = comp_mbox_close,
945 .msg_open = comp_msg_open,
946 .msg_open_new = comp_msg_open_new,
947 .msg_commit = comp_msg_commit,
948 .msg_close = comp_msg_close,
949 .msg_padding_size = comp_msg_padding_size,
950 .msg_save_hcache = comp_msg_save_hcache,
951 .tags_edit = comp_tags_edit,
952 .tags_commit = comp_tags_commit,
953 .path_probe = comp_path_probe,
954 .path_canon = comp_path_canon,
955 .path_is_empty = NULL,
956 // clang-format on
957};
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:600
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:336
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
static struct CompressInfo * set_compress_info(struct Mailbox *m)
Find the compress hooks for a mailbox.
Definition: compress.c:239
static void compress_info_free(struct Mailbox *m)
Frees the compress info members and structure.
Definition: compress.c:269
const struct ExpandoRenderData CompressRenderData[]
Callbacks for Compression Hook Expandos.
Definition: compress.c:59
static int setup_paths(struct Mailbox *m)
Set the mailbox paths.
Definition: compress.c:174
const struct ExpandoDefinition CompressFormatDef[]
Expando definitions.
Definition: compress.c:80
void mutt_comp_init(void)
Setup feature commands.
Definition: compress.c:91
static void store_size(const struct Mailbox *m)
Save the size of the compressed file.
Definition: compress.c:202
static bool lock_realpath(struct Mailbox *m, bool excl)
Try to lock the Mailbox.realpath.
Definition: compress.c:107
bool mutt_comp_can_append(struct Mailbox *m)
Can we append to this path?
Definition: compress.c:365
static void unlock_realpath(struct Mailbox *m)
Unlock the mailbox->realpath.
Definition: compress.c:148
static const struct Command CompCommands[]
Compression Commands.
Definition: compress.c:64
int mutt_comp_valid_command(const char *cmd)
Is this command string allowed?
Definition: compress.c:414
static bool execute_command(struct Mailbox *m, const struct Expando *exp, const char *progress)
Run a system command.
Definition: compress.c:323
static struct Expando * validate_compress_expando(const char *s)
Validate the Compress hooks.
Definition: compress.c:217
bool mutt_comp_can_read(const char *path)
Can we read from this file?
Definition: compress.c:394
@ ED_CMP_FROM
'from' path
Definition: lib.h:48
@ ED_CMP_TO
'to' path
Definition: lib.h:49
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:223
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:173
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:151
@ E_TYPE_STRING
Data is a string.
Definition: definition.h:37
@ ED_COMPRESS
Compress ED_CMP_ ExpandoDataCompress.
Definition: domain.h:40
Parse Expando string.
struct Expando * expando_parse(const char *str, const struct ExpandoDefinition *defs, struct Buffer *err)
Parse an Expando string.
Definition: expando.c:74
int expando_render(const struct Expando *exp, const struct ExpandoRenderData *rdata, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Render an Expando + data into a string.
Definition: expando.c:109
void expando_free(struct Expando **ptr)
Free an Expando object.
Definition: expando.c:54
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:930
int mutt_file_lock(int fd, bool excl, bool timeout)
(Try to) Lock a file using fcntl()
Definition: file.c:1199
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1246
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1516
#define mutt_file_fclose(FP)
Definition: file.h:147
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:146
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:167
void compress_f(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Compress: From filename - Implements ExpandoRenderData::get_string() -.
Definition: compress.c:287
void compress_t(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, int max_cols, struct Buffer *buf)
Compress: To filename - Implements ExpandoRenderData::get_string() -.
Definition: compress.c:301
#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:433
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:425
const struct MxOps MxCompOps
Compressed Mailbox - Implements MxOps -.
Definition: compress.c:932
static enum MxStatus comp_mbox_check(struct Mailbox *m)
Check for new mail - Implements MxOps::mbox_check() -.
Definition: compress.c:583
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:503
static enum MxOpenReturns comp_mbox_open(struct Mailbox *m)
Open a Mailbox - Implements MxOps::mbox_open() -.
Definition: compress.c:446
static enum MxStatus comp_mbox_sync(struct Mailbox *m)
Save changes to the Mailbox - Implements MxOps::mbox_sync() -.
Definition: compress.c:619
static int comp_msg_close(struct Mailbox *m, struct Message *msg)
Close an email - Implements MxOps::msg_close() -.
Definition: compress.c:807
static int comp_msg_commit(struct Mailbox *m, struct Message *msg)
Save changes to an email - Implements MxOps::msg_commit() -.
Definition: compress.c:789
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:771
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:753
static int comp_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Implements MxOps::msg_padding_size() -.
Definition: compress.c:825
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:842
static int comp_path_canon(struct Buffer *path)
Canonicalise a Mailbox path - Implements MxOps::path_canon() -.
Definition: compress.c:907
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:893
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:876
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:859
Convenience wrapper for the gui headers.
char * mutt_find_hook(HookFlags type, const char *pat)
Find a matching hook.
Definition: hook.c:671
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:248
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:274
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
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: render.h:33
uint8_t MuttFormatFlags
Flags for expando_render(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: render.h:32
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:58
struct Expando * cmd_open
open-hook command
Definition: lib.h:61
FILE * fp_lock
fp used for locking
Definition: lib.h:65
struct Expando * cmd_append
append-hook command
Definition: lib.h:59
const struct MxOps * child_ops
callbacks of de-compressed file
Definition: lib.h:63
bool locked
if realpath is locked
Definition: lib.h:64
long size
size of the compressed file
Definition: lib.h:62
struct Expando * cmd_close
close-hook command
Definition: lib.h:60
The envelope/body of an email.
Definition: email.h:39
Definition of a format string.
Definition: definition.h:52
Basic Expando Node.
Definition: node.h:67
Parsed Expando trees.
Definition: expando.h:41
const char * string
Pointer to the parsed string.
Definition: expando.h:42
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