NeoMutt  2023-05-17-56-ga67199
Teaching an old dog new tricks
DOXYGEN
mailbox.c
Go to the documentation of this file.
1
31#include "config.h"
32#include <assert.h>
33#include <sys/stat.h>
34#include "config/lib.h"
35#include "email/lib.h"
36#include "mailbox.h"
37#include "neomutt.h"
38
40static const struct Mapping MailboxTypes[] = {
41 // clang-format off
42 { "compressed", MUTT_COMPRESSED },
43 { "imap", MUTT_IMAP },
44 { "maildir", MUTT_MAILDIR },
45 { "mbox", MUTT_MBOX },
46 { "mh", MUTT_MH },
47 { "mmdf", MUTT_MMDF },
48 { "nntp", MUTT_NNTP },
49 { "notmuch", MUTT_NOTMUCH },
50 { "pop", MUTT_POP },
51 { NULL, 0 },
52 // clang-format on
53};
54
59int mailbox_gen(void)
60{
61 static int gen = 0;
62 return gen++;
63}
64
69struct Mailbox *mailbox_new(void)
70{
71 struct Mailbox *m = mutt_mem_calloc(1, sizeof(struct Mailbox));
72
73 buf_init(&m->pathbuf);
74 m->notify = notify_new();
75
76 m->email_max = 25;
77 m->emails = mutt_mem_calloc(m->email_max, sizeof(struct Email *));
78 m->v2r = mutt_mem_calloc(m->email_max, sizeof(int));
79 m->gen = mailbox_gen();
80
81 return m;
82}
83
88void mailbox_free(struct Mailbox **ptr)
89{
90 if (!ptr || !*ptr)
91 return;
92
93 struct Mailbox *m = *ptr;
94
95 const bool do_free = (m->opened == 0) && !m->visible;
96
97 mutt_debug(LL_DEBUG3, "%sfreeing %s mailbox %s with refcount %d\n",
98 do_free ? "" : "not ", m->visible ? "visible" : "invisible",
99 buf_string(&m->pathbuf), m->opened);
100
101 if (!do_free)
102 {
103 return;
104 }
105
106 mutt_debug(LL_NOTIFY, "NT_MAILBOX_DELETE: %s %p\n", mailbox_get_type_name(m->type), m);
107 struct EventMailbox ev_m = { m };
109
110 mutt_debug(LL_NOTIFY, "NT_EMAIL_DELETE_ALL\n");
111 struct EventEmail ev_e = { 0, NULL };
113
114 for (size_t i = 0; i < m->email_max; i++)
115 email_free(&m->emails[i]);
116
117 if (m->mdata_free && m->mdata)
118 m->mdata_free(&m->mdata);
119
120 buf_dealloc(&m->pathbuf);
121 cs_subset_free(&m->sub);
122 FREE(&m->name);
123 FREE(&m->realpath);
124 FREE(&m->emails);
125 FREE(&m->v2r);
126 notify_free(&m->notify);
128
129 /* The NT_MAILBOX_DELETE notification might already have caused *ptr to be NULL,
130 * so call free() on the m pointer */
131 *ptr = NULL;
132 FREE(&m);
133}
134
140struct Mailbox *mailbox_find(const char *path)
141{
142 if (!path)
143 return NULL;
144
145 struct stat st = { 0 };
146 struct stat st_tmp = { 0 };
147
148 if (stat(path, &st) != 0)
149 return NULL;
150
151 struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
153 struct MailboxNode *np = NULL;
154 struct Mailbox *m = NULL;
155 STAILQ_FOREACH(np, &ml, entries)
156 {
157 if ((stat(mailbox_path(np->mailbox), &st_tmp) == 0) &&
158 (st.st_dev == st_tmp.st_dev) && (st.st_ino == st_tmp.st_ino))
159 {
160 m = np->mailbox;
161 break;
162 }
163 }
165
166 return m;
167}
168
177struct Mailbox *mailbox_find_name(const char *name)
178{
179 if (!name)
180 return NULL;
181
182 struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
184 struct MailboxNode *np = NULL;
185 struct Mailbox *m = NULL;
186 STAILQ_FOREACH(np, &ml, entries)
187 {
188 if (mutt_str_equal(np->mailbox->name, name))
189 {
190 m = np->mailbox;
191 break;
192 }
193 }
195
196 return m;
197}
198
205void mailbox_update(struct Mailbox *m)
206{
207 struct stat st = { 0 };
208
209 if (!m)
210 return;
211
212 if (stat(mailbox_path(m), &st) == 0)
213 m->size = (off_t) st.st_size;
214 else
215 m->size = 0;
216}
217
223void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
224{
225 if (!m)
226 return;
227
228 mutt_debug(LL_NOTIFY, "NT_MAILBOX_CHANGE: %s %p\n", mailbox_get_type_name(m->type), m);
229 struct EventMailbox ev_m = { m };
230 notify_send(m->notify, NT_MAILBOX, action, &ev_m);
231}
232
238void mailbox_size_add(struct Mailbox *m, const struct Email *e)
239{
240 m->size += email_size(e);
241}
242
248void mailbox_size_sub(struct Mailbox *m, const struct Email *e)
249{
250 m->size -= email_size(e);
251}
252
259bool mailbox_set_subset(struct Mailbox *m, struct ConfigSubset *sub)
260{
261 if (!m || m->sub || !sub)
262 return false;
263
264 m->sub = cs_subset_new(m->name, sub, m->notify);
266 return true;
267}
268
273{
274 struct Email *arr[10];
275 size_t idx;
276};
277
279static struct EmailGarbageCollector GC = { 0 };
280
287void mailbox_gc_add(struct Email *e)
288{
289 assert(e);
290 if (GC.idx == mutt_array_size(GC.arr))
291 {
293 }
294 GC.arr[GC.idx] = e;
295 GC.idx++;
296}
297
302{
303 for (size_t i = 0; i < GC.idx; i++)
304 {
305 email_free(&GC.arr[i]);
306 }
307 GC.idx = 0;
308}
309
315const char *mailbox_get_type_name(enum MailboxType type)
316{
317 const char *name = mutt_map_get_name(type, MailboxTypes);
318 if (name)
319 return name;
320 return "UNKNOWN";
321}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:383
struct Buffer * buf_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:55
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:90
Convenience wrapper for the config headers.
size_t email_size(const struct Email *e)
Compute the size of an email.
Definition: email.c:125
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
Structs that make up an email.
@ NT_EMAIL_DELETE_ALL
All the Emails are about to be deleted.
Definition: email.h:149
#define mutt_debug(LEVEL,...)
Definition: logging2.h:87
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:45
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:48
bool mailbox_set_subset(struct Mailbox *m, struct ConfigSubset *sub)
Set a Mailbox's Config Subset.
Definition: mailbox.c:259
void mailbox_gc_run(void)
Run the garbage-collection.
Definition: mailbox.c:301
void mailbox_size_add(struct Mailbox *m, const struct Email *e)
Add an email's size to the total size of a Mailbox.
Definition: mailbox.c:238
void mailbox_size_sub(struct Mailbox *m, const struct Email *e)
Subtract an email's size from the total size of a Mailbox.
Definition: mailbox.c:248
int mailbox_gen(void)
Get the next generation number.
Definition: mailbox.c:59
struct Mailbox * mailbox_new(void)
Create a new Mailbox.
Definition: mailbox.c:69
void mailbox_gc_add(struct Email *e)
Add an Email to the garbage-collection set.
Definition: mailbox.c:287
void mailbox_update(struct Mailbox *m)
Get the mailbox's current size.
Definition: mailbox.c:205
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:88
static const struct Mapping MailboxTypes[]
Lookups for Mailbox types.
Definition: mailbox.c:40
struct Mailbox * mailbox_find_name(const char *name)
Find the mailbox with a given name.
Definition: mailbox.c:177
static struct EmailGarbageCollector GC
Set of Emails to be deleted.
Definition: mailbox.c:279
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:223
const char * mailbox_get_type_name(enum MailboxType type)
Get the type of a Mailbox.
Definition: mailbox.c:315
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition: mailbox.c:140
Representation of a mailbox.
NotifyMailbox
Types of Mailbox Event.
Definition: mailbox.h:167
@ NT_MAILBOX_DELETE
Mailbox is about to be deleted.
Definition: mailbox.h:169
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_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:51
@ MUTT_MMDF
'mmdf' Mailbox type
Definition: mailbox.h:46
@ MUTT_POP
'POP3' Mailbox type
Definition: mailbox.h:52
@ MUTT_MH
'MH' Mailbox type
Definition: mailbox.h:47
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition: mailbox.h:49
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
@ MUTT_MBOX
'mbox' Mailbox type
Definition: mailbox.h:45
@ MUTT_MAILBOX_ANY
Match any Mailbox type.
Definition: mailbox.h:42
@ MUTT_COMPRESSED
Compressed file Mailbox type.
Definition: mailbox.h:53
@ MUTT_MAILDIR
'Maildir' Mailbox type
Definition: mailbox.h:48
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
Definition: mapping.c:42
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
struct Notify * notify_new(void)
Create a new notifications handler.
Definition: notify.c:60
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:73
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:141
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:164
Container for Accounts, Notifications.
@ NT_EMAIL
Email has changed, NotifyEmail, EventEmail.
Definition: notify_type.h:44
@ NT_MAILBOX
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition: notify_type.h:49
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
A set of inherited config items.
Definition: subset.h:47
enum ConfigScope scope
Scope of Subset, e.g. SET_SCOPE_ACCOUNT.
Definition: subset.h:49
Email garbage collection.
Definition: mailbox.c:273
size_t idx
Current position.
Definition: mailbox.c:275
struct Email * arr[10]
Array of Emails to be deleted.
Definition: mailbox.c:274
The envelope/body of an email.
Definition: email.h:37
An Event that happened to an Email.
Definition: email.h:160
An Event that happened to a Mailbox.
Definition: mailbox.h:185
List of Mailboxes.
Definition: mailbox.h:152
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:153
A mailbox.
Definition: mailbox.h:79
void(* mdata_free)(void **ptr)
Free the private data attached to the Mailbox.
Definition: mailbox.h:141
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:81
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:98
int email_max
Size of emails array.
Definition: mailbox.h:97
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
void * mdata
Driver specific data.
Definition: mailbox.h:132
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
char * name
A short name for the Mailbox.
Definition: mailbox.h:82
struct Notify * notify
Notifications: NotifyMailbox, EventMailbox.
Definition: mailbox.h:143
struct Buffer pathbuf
Path of the Mailbox.
Definition: mailbox.h:80
off_t size
Size of the Mailbox.
Definition: mailbox.h:84
bool visible
True if a result of "mailboxes".
Definition: mailbox.h:130
int opened
Number of times mailbox is opened.
Definition: mailbox.h:128
int gen
Generation number, for sorting.
Definition: mailbox.h:145
struct ConfigSubset * sub
Inherited config items.
Definition: mailbox.h:83
Mapping between user-readable string and a constant.
Definition: mapping.h:32
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * cs_subset_new(const char *name, struct ConfigSubset *sub_parent, struct Notify *not_parent)
Create a new Config Subset.
Definition: subset.c:149
void cs_subset_free(struct ConfigSubset **ptr)
Free a Config Subset.
Definition: subset.c:105
@ SET_SCOPE_MAILBOX
This Config is Mailbox-specific.
Definition: subset.h:40