NeoMutt  2022-04-29-247-gc6aae8
Teaching an old dog new tricks
DOXYGEN
mbox_check()

Check for new mail. More...

+ Collaboration diagram for mbox_check():

Functions

static enum MxStatus comp_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
static enum MxStatus imap_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
enum MxStatus maildir_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
enum MxStatus mh_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
static enum MxStatus mbox_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
static enum MxStatus nntp_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
static enum MxStatus nm_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
static enum MxStatus pop_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 

Detailed Description

Check for new mail.

Parameters
mMailbox
Return values
enumMxStatus

Contract

Function Documentation

◆ comp_mbox_check()

static enum MxStatus comp_mbox_check ( struct Mailbox m)
static

Check for new mail - Implements MxOps::mbox_check() -.

Parameters
mMailbox
Return values
enumMxStatus

If the compressed file changes in size but the mailbox hasn't been changed in NeoMutt, then we can close and reopen the mailbox.

If the mailbox has been changed in NeoMutt, warn the user.

Definition at line 582 of file compress.c.

583{
584 if (!m->compress_info)
585 return MX_STATUS_ERROR;
586
587 struct CompressInfo *ci = m->compress_info;
588
589 const struct MxOps *ops = ci->child_ops;
590 if (!ops)
591 return MX_STATUS_ERROR;
592
593 int size = mutt_file_get_size(m->realpath);
594 if (size == ci->size)
595 return MX_STATUS_OK;
596
597 if (!lock_realpath(m, false))
598 {
599 mutt_error(_("Unable to lock mailbox"));
600 return MX_STATUS_ERROR;
601 }
602
603 int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
604 store_size(m);
606 if (rc == 0)
607 return MX_STATUS_ERROR;
608
609 return ops->mbox_check(m);
610}
static int execute_command(struct Mailbox *m, const char *command, const char *progress)
Run a system command.
Definition: compress.c:322
static void store_size(const struct Mailbox *m)
Save the size of the compressed file.
Definition: compress.c:179
static bool lock_realpath(struct Mailbox *m, bool excl)
Try to lock the Mailbox.realpath.
Definition: compress.c:86
static void unlock_realpath(struct Mailbox *m)
Unlock the mailbox->realpath.
Definition: compress.c:125
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1551
#define mutt_error(...)
Definition: logging.h:87
#define _(a)
Definition: message.h:28
@ MX_STATUS_ERROR
An error occurred.
Definition: mxapi.h:85
@ MX_STATUS_OK
No changes.
Definition: mxapi.h:86
Private data for compress.
Definition: lib.h:47
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
long size
size of the compressed file
Definition: lib.h:51
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:81
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:120
Definition: mxapi.h:112
enum MxStatus(* mbox_check)(struct Mailbox *m)
Definition: mxapi.h:188
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_mbox_check()

static enum MxStatus imap_mbox_check ( struct Mailbox m)
static

Check for new mail - Implements MxOps::mbox_check() -.

Parameters
mMailbox
Return values
>0Success, e.g. MX_STATUS_REOPENED
-1Failure

Definition at line 2167 of file imap.c.

2168{
2170 enum MxStatus rc = imap_check_mailbox(m, false);
2171 /* NOTE - mv might have been changed at this point. In particular,
2172 * m could be NULL. Beware. */
2174
2175 return rc;
2176}
void imap_allow_reopen(struct Mailbox *m)
Allow re-opening a folder upon expunge.
Definition: util.c:1016
void imap_disallow_reopen(struct Mailbox *m)
Disallow re-opening a folder upon expunge.
Definition: util.c:1029
enum MxStatus imap_check_mailbox(struct Mailbox *m, bool force)
Use the NOOP or IDLE command to poll for new mail.
Definition: imap.c:1106
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_snc(), and mbox_close()
Definition: mxapi.h:84
+ Here is the call graph for this function:

◆ maildir_mbox_check()

enum MxStatus maildir_mbox_check ( struct Mailbox m)

Check for new mail - Implements MxOps::mbox_check() -.

This function handles arrival of new mail and reopening of maildir folders. The basic idea here is we check to see if either the new or cur subdirectories have changed, and if so, we scan them for the list of files. We check for newly added messages, and then merge the flags messages we already knew about. We don't treat either subdirectory differently, as mail could be copied directly into the cur directory from another agent.

Definition at line 1167 of file maildir.c.

1168{
1169 struct stat st_new = { 0 }; /* status of the "new" subdirectory */
1170 struct stat st_cur = { 0 }; /* status of the "cur" subdirectory */
1171 int changed = MMC_NO_DIRS; /* which subdirectories have changed */
1172 bool occult = false; /* messages were removed from the mailbox */
1173 int num_new = 0; /* number of new messages added to the mailbox */
1174 bool flags_changed = false; /* message flags were changed in the mailbox */
1175 struct HashTable *fnames = NULL; /* hash table for quickly looking up the base filename
1176 for a maildir message */
1178
1179 /* XXX seems like this check belongs in mx_mbox_check() rather than here. */
1180 const bool c_check_new = cs_subset_bool(NeoMutt->sub, "check_new");
1181 if (!c_check_new)
1182 return MX_STATUS_OK;
1183
1184 struct Buffer *buf = mutt_buffer_pool_get();
1185 mutt_buffer_printf(buf, "%s/new", mailbox_path(m));
1186 if (stat(mutt_buffer_string(buf), &st_new) == -1)
1187 {
1189 return MX_STATUS_ERROR;
1190 }
1191
1192 mutt_buffer_printf(buf, "%s/cur", mailbox_path(m));
1193 if (stat(mutt_buffer_string(buf), &st_cur) == -1)
1194 {
1196 return MX_STATUS_ERROR;
1197 }
1198
1199 /* determine which subdirectories need to be scanned */
1201 changed = MMC_NEW_DIR;
1203 changed |= MMC_CUR_DIR;
1204
1205 if (changed == MMC_NO_DIRS)
1206 {
1208 return MX_STATUS_OK; /* nothing to do */
1209 }
1210
1211 /* Update the modification times on the mailbox.
1212 *
1213 * The monitor code notices changes in the open mailbox too quickly.
1214 * In practice, this sometimes leads to all the new messages not being
1215 * noticed during the SAME group of mtime stat updates. To work around
1216 * the problem, don't update the stat times for a monitor caused check. */
1217#ifdef USE_INOTIFY
1219 MonitorContextChanged = false;
1220 else
1221#endif
1222 {
1225 }
1226
1227 /* do a fast scan of just the filenames in
1228 * the subdirectories that have changed. */
1229 struct MdEmailArray mda = ARRAY_HEAD_INITIALIZER;
1230 if (changed & MMC_NEW_DIR)
1231 maildir_parse_dir(m, &mda, "new", NULL);
1232 if (changed & MMC_CUR_DIR)
1233 maildir_parse_dir(m, &mda, "cur", NULL);
1234
1235 /* we create a hash table keyed off the canonical (sans flags) filename
1236 * of each message we scanned. This is used in the loop over the
1237 * existing messages below to do some correlation. */
1239
1240 struct MdEmail *md = NULL;
1241 struct MdEmail **mdp = NULL;
1242 ARRAY_FOREACH(mdp, &mda)
1243 {
1244 md = *mdp;
1247 mutt_hash_insert(fnames, md->canon_fname, md);
1248 }
1249
1250 /* check for modifications and adjust flags */
1251 for (int i = 0; i < m->msg_count; i++)
1252 {
1253 struct Email *e = m->emails[i];
1254 if (!e)
1255 break;
1256
1257 e->active = false;
1259 md = mutt_hash_find(fnames, mutt_buffer_string(buf));
1260 if (md && md->email)
1261 {
1262 /* message already exists, merge flags */
1263 e->active = true;
1264
1265 /* check to see if the message has moved to a different
1266 * subdirectory. If so, update the associated filename. */
1267 if (!mutt_str_equal(e->path, md->email->path))
1268 mutt_str_replace(&e->path, md->email->path);
1269
1270 /* if the user hasn't modified the flags on this message, update
1271 * the flags we just detected. */
1272 if (!e->changed)
1273 if (maildir_update_flags(m, e, md->email))
1274 flags_changed = true;
1275
1276 if (e->deleted == e->trash)
1277 {
1278 if (e->deleted != md->email->deleted)
1279 {
1280 e->deleted = md->email->deleted;
1281 flags_changed = true;
1282 }
1283 }
1284 e->trash = md->email->trash;
1285
1286 /* this is a duplicate of an existing email, so remove it */
1287 email_free(&md->email);
1288 }
1289 /* This message was not in the list of messages we just scanned.
1290 * Check to see if we have enough information to know if the
1291 * message has disappeared out from underneath us. */
1292 else if (((changed & MMC_NEW_DIR) && mutt_strn_equal(e->path, "new/", 4)) ||
1293 ((changed & MMC_CUR_DIR) && mutt_strn_equal(e->path, "cur/", 4)))
1294 {
1295 /* This message disappeared, so we need to simulate a "reopen"
1296 * event. We know it disappeared because we just scanned the
1297 * subdirectory it used to reside in. */
1298 occult = true;
1299 e->deleted = true;
1300 e->purge = true;
1301 }
1302 else
1303 {
1304 /* This message resides in a subdirectory which was not
1305 * modified, so we assume that it is still present and
1306 * unchanged. */
1307 e->active = true;
1308 }
1309 }
1310
1311 /* destroy the file name hash */
1312 mutt_hash_free(&fnames);
1313
1314 /* If we didn't just get new mail, update the tables. */
1315 if (occult)
1317
1318 /* do any delayed parsing we need to do. */
1319 maildir_delayed_parsing(m, &mda, NULL);
1320
1321 /* Incorporate new messages */
1322 num_new = maildir_move_to_mailbox(m, &mda);
1323 if (num_new > 0)
1324 {
1326 m->changed = true;
1327 }
1328
1330
1331 ARRAY_FREE(&mda);
1332 if (occult)
1333 return MX_STATUS_REOPENED;
1334 if (num_new > 0)
1335 return MX_STATUS_NEW_MAIL;
1336 if (flags_changed)
1337 return MX_STATUS_FLAGS;
1338 return MX_STATUS_OK;
1339}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:211
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:86
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:203
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:57
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:447
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
void mutt_file_get_stat_timespec(struct timespec *dest, struct stat *st, enum MuttStatType type)
Read the stat() time into a time value.
Definition: file.c:1611
int mutt_file_stat_timespec_compare(struct stat *st, enum MuttStatType type, struct timespec *b)
Compare stat info with a time value.
Definition: file.c:1651
@ MUTT_STAT_MTIME
File/dir's mtime - last modified time.
Definition: file.h:63
struct HashElem * mutt_hash_insert(struct HashTable *table, const char *strkey, void *data)
Add a new element to the Hash Table (with string keys)
Definition: hash.c:335
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:362
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition: hash.c:259
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:457
#define MUTT_HASH_NO_FLAGS
No flags are set.
Definition: hash.h:109
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:222
@ NT_MAILBOX_RESORT
Email list needs resorting.
Definition: mailbox.h:177
@ NT_MAILBOX_INVALID
Email list was changed.
Definition: mailbox.h:176
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:210
bool maildir_update_flags(struct Mailbox *m, struct Email *e_old, struct Email *e_new)
Update the mailbox flags.
Definition: shared.c:122
struct MaildirMboxData * maildir_mdata_get(struct Mailbox *m)
Get the private data for this Mailbox.
Definition: mdata.c:58
int maildir_move_to_mailbox(struct Mailbox *m, struct MdEmailArray *mda)
Copy the Maildir list to the Mailbox.
Definition: shared.c:75
int maildir_parse_dir(struct Mailbox *m, struct MdEmailArray *mda, const char *subdir, struct Progress *progress)
Read a Maildir mailbox.
Definition: maildir.c:513
#define MMC_CUR_DIR
'cur' directory changed
Definition: maildir.c:75
#define MMC_NO_DIRS
No directories changed.
Definition: maildir.c:73
#define MMC_NEW_DIR
'new' directory changed
Definition: maildir.c:74
void maildir_delayed_parsing(struct Mailbox *m, struct MdEmailArray *mda, struct Progress *progress)
This function does the second parsing pass.
Definition: maildir.c:596
void maildir_canon_filename(struct Buffer *dest, const char *src)
Generate the canonical filename for a Maildir folder.
Definition: maildir.c:724
bool MonitorContextChanged
true after the current mailbox has changed
Definition: monitor.c:51
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:496
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
@ MX_STATUS_FLAGS
Nondestructive flags change (IMAP)
Definition: mxapi.h:90
@ MX_STATUS_REOPENED
Mailbox was reopened.
Definition: mxapi.h:89
@ MX_STATUS_NEW_MAIL
New mail received in Mailbox.
Definition: mxapi.h:87
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
String manipulation buffer.
Definition: buffer.h:34
The envelope/body of an email.
Definition: email.h:37
bool purge
Skip trash folder when deleting.
Definition: email.h:77
bool active
Message is not to be removed.
Definition: email.h:74
bool changed
Email has been edited.
Definition: email.h:75
char * path
Path of Email (for local Mailboxes)
Definition: email.h:68
bool deleted
Email is deleted.
Definition: email.h:76
bool trash
Message is marked as trashed on disk (used by the maildir_trash option)
Definition: email.h:51
A Hash Table.
Definition: hash.h:97
bool changed
Mailbox has been modified.
Definition: mailbox.h:110
struct timespec mtime
Time Mailbox was last changed.
Definition: mailbox.h:104
int msg_count
Total number of messages.
Definition: mailbox.h:88
void * mdata
Driver specific data.
Definition: mailbox.h:132
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
Maildir-specific Mailbox data -.
Definition: mdata.h:35
struct timespec mtime_cur
Timestamp of the 'cur' dir.
Definition: mdata.h:36
A Maildir Email helper.
Definition: mdemail.h:34
char * canon_fname
Definition: mdemail.h:36
struct Email * email
Definition: mdemail.h:35
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mh_mbox_check()

enum MxStatus mh_mbox_check ( struct Mailbox m)

Check for new mail - Implements MxOps::mbox_check() -.

This function handles arrival of new mail and reopening of mh/maildir folders. Things are getting rather complex because we don't have a well-defined "mailbox order", so the tricks from mbox.c and mx.c won't work here.

Don't change this code unless you really understand what happens.

Definition at line 892 of file mh.c.

893{
894 char buf[PATH_MAX] = { 0 };
895 struct stat st = { 0 };
896 struct stat st_cur = { 0 };
897 bool modified = false, occult = false, flags_changed = false;
898 int num_new = 0;
899 struct MhSequences mhs = { 0 };
900 struct HashTable *fnames = NULL;
902
903 const bool c_check_new = cs_subset_bool(NeoMutt->sub, "check_new");
904 if (!c_check_new)
905 return MX_STATUS_OK;
906
907 mutt_str_copy(buf, mailbox_path(m), sizeof(buf));
908 if (stat(buf, &st) == -1)
909 return MX_STATUS_ERROR;
910
911 /* create .mh_sequences when there isn't one. */
912 snprintf(buf, sizeof(buf), "%s/.mh_sequences", mailbox_path(m));
913 int rc = stat(buf, &st_cur);
914 if ((rc == -1) && (errno == ENOENT))
915 {
916 char *tmp = NULL;
917 FILE *fp = NULL;
918
919 if (mh_mkstemp(m, &fp, &tmp))
920 {
921 mutt_file_fclose(&fp);
922 if (mutt_file_safe_rename(tmp, buf) == -1)
923 unlink(tmp);
924 FREE(&tmp);
925 }
926 }
927
928 if ((rc == -1) && (stat(buf, &st_cur) == -1))
929 modified = true;
930
932 (mutt_file_stat_timespec_compare(&st_cur, MUTT_STAT_MTIME, &mdata->mtime_cur) > 0))
933 {
934 modified = true;
935 }
936
937 if (!modified)
938 return MX_STATUS_OK;
939
940 /* Update the modification times on the mailbox.
941 *
942 * The monitor code notices changes in the open mailbox too quickly.
943 * In practice, this sometimes leads to all the new messages not being
944 * noticed during the SAME group of mtime stat updates. To work around
945 * the problem, don't update the stat times for a monitor caused check. */
946#ifdef USE_INOTIFY
948 MonitorContextChanged = false;
949 else
950#endif
951 {
954 }
955
956 struct MdEmailArray mda = ARRAY_HEAD_INITIALIZER;
957
958 mh_parse_dir(m, &mda, NULL);
959 mh_delayed_parsing(m, &mda, NULL);
960
961 if (mh_seq_read(&mhs, mailbox_path(m)) < 0)
962 return MX_STATUS_ERROR;
963 mh_update_maildir(&mda, &mhs);
964 mh_seq_free(&mhs);
965
966 /* check for modifications and adjust flags */
968
969 struct MdEmail *md = NULL;
970 struct MdEmail **mdp = NULL;
971 ARRAY_FOREACH(mdp, &mda)
972 {
973 md = *mdp;
974 /* the hash key must survive past the header, which is freed below. */
976 mutt_hash_insert(fnames, md->canon_fname, md);
977 }
978
979 for (int i = 0; i < m->msg_count; i++)
980 {
981 struct Email *e = m->emails[i];
982 if (!e)
983 break;
984
985 e->active = false;
986
987 md = mutt_hash_find(fnames, e->path);
988 if (md && md->email && email_cmp_strict(e, md->email))
989 {
990 e->active = true;
991 /* found the right message */
992 if (!e->changed)
993 if (maildir_update_flags(m, e, md->email))
994 flags_changed = true;
995
996 email_free(&md->email);
997 }
998 else /* message has disappeared */
999 occult = true;
1000 }
1001
1002 /* destroy the file name hash */
1003
1004 mutt_hash_free(&fnames);
1005
1006 /* If we didn't just get new mail, update the tables. */
1007 if (occult)
1009
1010 /* Incorporate new messages */
1011 num_new = maildir_move_to_mailbox(m, &mda);
1012 if (num_new > 0)
1013 {
1015 m->changed = true;
1016 }
1017
1018 ARRAY_FREE(&mda);
1019 if (occult)
1020 return MX_STATUS_REOPENED;
1021 if (num_new > 0)
1022 return MX_STATUS_NEW_MAIL;
1023 if (flags_changed)
1024 return MX_STATUS_FLAGS;
1025 return MX_STATUS_OK;
1026}
bool email_cmp_strict(const struct Email *e1, const struct Email *e2)
Strictly compare message emails.
Definition: email.c:100
int mutt_file_safe_rename(const char *src, const char *target)
NFS-safe renaming of files.
Definition: file.c:344
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
#define FREE(x)
Definition: memory.h:43
void mh_delayed_parsing(struct Mailbox *m, struct MdEmailArray *mda, struct Progress *progress)
This function does the second parsing pass.
Definition: mh.c:614
void mh_update_maildir(struct MdEmailArray *mda, struct MhSequences *mhs)
Update our record of flags.
Definition: mh.c:260
bool mh_mkstemp(struct Mailbox *m, FILE **fp, char **tgt)
Create a temporary file.
Definition: mh.c:78
int mh_parse_dir(struct Mailbox *m, struct MdEmailArray *mda, struct Progress *progress)
Read a Maildir mailbox.
Definition: mh.c:502
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:652
#define PATH_MAX
Definition: mutt.h:40
void mh_seq_free(struct MhSequences *mhs)
Free some sequences.
Definition: sequence.c:67
int mh_seq_read(struct MhSequences *mhs, const char *path)
Read a set of MH sequences.
Definition: sequence.c:375
Set of MH sequence numbers.
Definition: sequence.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mbox_mbox_check()

static enum MxStatus mbox_mbox_check ( struct Mailbox m)
static

Check for new mail - Implements MxOps::mbox_check() -.

Parameters
[in]mMailbox
Return values
MX_STATUS_REOPENEDMailbox has been reopened
MX_STATUS_NEW_MAILNew mail has arrived
MX_STATUS_LOCKEDCouldn't lock the file

Definition at line 1026 of file mbox.c.

1027{
1029 if (!adata)
1030 return MX_STATUS_ERROR;
1031
1032 if (!adata->fp)
1033 {
1034 if (mbox_mbox_open(m) != MX_OPEN_OK)
1035 return MX_STATUS_ERROR;
1037 }
1038 if (!adata->fp)
1039 return MX_STATUS_ERROR;
1040
1041 struct stat st = { 0 };
1042 bool unlock = false;
1043 bool modified = false;
1044
1045 if (stat(mailbox_path(m), &st) == 0)
1046 {
1048 (st.st_size == m->size))
1049 {
1050 return MX_STATUS_OK;
1051 }
1052
1053 if (st.st_size == m->size)
1054 {
1055 /* the file was touched, but it is still the same length, so just exit */
1057 return MX_STATUS_OK;
1058 }
1059
1060 if (st.st_size > m->size)
1061 {
1062 /* lock the file if it isn't already */
1063 if (!adata->locked)
1064 {
1066 if (mbox_lock_mailbox(m, false, false) == -1)
1067 {
1069 /* we couldn't lock the mailbox, but nothing serious happened:
1070 * probably the new mail arrived: no reason to wait till we can
1071 * parse it: we'll get it on the next pass */
1072 return MX_STATUS_LOCKED;
1073 }
1074 unlock = 1;
1075 }
1076
1077 /* Check to make sure that the only change to the mailbox is that
1078 * message(s) were appended to this file. My heuristic is that we should
1079 * see the message separator at *exactly* what used to be the end of the
1080 * folder. */
1081 char buf[1024] = { 0 };
1082 if (!mutt_file_seek(adata->fp, m->size, SEEK_SET))
1083 {
1084 goto error;
1085 }
1086 if (fgets(buf, sizeof(buf), adata->fp))
1087 {
1088 if (((m->type == MUTT_MBOX) && mutt_str_startswith(buf, "From ")) ||
1089 ((m->type == MUTT_MMDF) && mutt_str_equal(buf, MMDF_SEP)))
1090 {
1091 if (!mutt_file_seek(adata->fp, m->size, SEEK_SET))
1092 {
1093 goto error;
1094 }
1095
1096 int old_msg_count = m->msg_count;
1097 if (m->type == MUTT_MBOX)
1099 else
1101
1102 if (m->msg_count > old_msg_count)
1104
1105 /* Only unlock the folder if it was locked inside of this routine.
1106 * It may have been locked elsewhere, like in
1107 * mutt_checkpoint_mailbox(). */
1108 if (unlock)
1109 {
1112 }
1113
1114 return MX_STATUS_NEW_MAIL; /* signal that new mail arrived */
1115 }
1116 else
1117 modified = true;
1118 }
1119 else
1120 {
1121 mutt_debug(LL_DEBUG1, "fgets returned NULL\n");
1122 modified = true;
1123 }
1124 }
1125 else
1126 modified = true;
1127 }
1128
1129 if (modified)
1130 {
1131 if (reopen_mailbox(m) != -1)
1132 {
1134 if (unlock)
1135 {
1138 }
1139 return MX_STATUS_REOPENED;
1140 }
1141 }
1142
1143 /* fatal error */
1144
1145error:
1147 mx_fastclose_mailbox(m, false);
1149 mutt_error(_("Mailbox was corrupted"));
1150 return MX_STATUS_ERROR;
1151}
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:690
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
static enum MxOpenReturns mbox_mbox_open(struct Mailbox *m)
Open a Mailbox - Implements MxOps::mbox_open() -.
Definition: mbox.c:925
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
@ MUTT_MMDF
'mmdf' Mailbox type
Definition: mailbox.h:46
@ MUTT_MBOX
'mbox' Mailbox type
Definition: mailbox.h:45
#define MMDF_SEP
Definition: lib.h:61
static enum MxOpenReturns mbox_parse_mailbox(struct Mailbox *m)
Read a mailbox from disk.
Definition: mbox.c:343
static int mbox_lock_mailbox(struct Mailbox *m, bool excl, bool retry)
Lock a mailbox.
Definition: mbox.c:134
static struct MboxAccountData * mbox_adata_get(struct Mailbox *m)
Get the private data associated with a Mailbox.
Definition: mbox.c:119
static void mbox_unlock_mailbox(struct Mailbox *m)
Unlock a mailbox.
Definition: mbox.c:156
static enum MxOpenReturns mmdf_parse_mailbox(struct Mailbox *m)
Read a mailbox in MMDF format.
Definition: mbox.c:176
static int reopen_mailbox(struct Mailbox *m)
Close and reopen a mailbox.
Definition: mbox.c:531
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:227
void mx_fastclose_mailbox(struct Mailbox *m, bool keep_account)
Free up memory associated with the Mailbox.
Definition: mx.c:430
@ MX_OPEN_OK
Open succeeded.
Definition: mxapi.h:98
@ MX_STATUS_LOCKED
Couldn't lock the Mailbox.
Definition: mxapi.h:88
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
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
off_t size
Size of the Mailbox.
Definition: mailbox.h:84
Mbox-specific Account data -.
Definition: lib.h:49
FILE * fp
Mailbox file.
Definition: lib.h:50
bool locked
is the mailbox locked?
Definition: lib.h:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_mbox_check()

static enum MxStatus nntp_mbox_check ( struct Mailbox m)
static

Check for new mail - Implements MxOps::mbox_check() -.

Parameters
mMailbox
Return values
enumMxStatus

Definition at line 2461 of file nntp.c.

2462{
2463 enum MxStatus rc = check_mailbox(m);
2464 if (rc == MX_STATUS_OK)
2465 {
2466 struct NntpMboxData *mdata = m->mdata;
2467 struct NntpAccountData *adata = mdata->adata;
2469 }
2470 return rc;
2471}
void nntp_newsrc_close(struct NntpAccountData *adata)
Unlock and close .newsrc file.
Definition: newsrc.c:118
static enum MxStatus check_mailbox(struct Mailbox *m)
Check current newsgroup for new articles.
Definition: nntp.c:1433
NNTP-specific Account data -.
Definition: adata.h:37
NNTP-specific Mailbox data -.
Definition: mdata.h:33
struct NntpAccountData * adata
Definition: mdata.h:47
+ Here is the call graph for this function:

◆ nm_mbox_check()

static enum MxStatus nm_mbox_check ( struct Mailbox m)
static

Check for new mail - Implements MxOps::mbox_check() -.

Parameters
mMailbox
Return values
enumMxStatus

Definition at line 2068 of file notmuch.c.

2069{
2070 struct NmMboxData *mdata = nm_mdata_get(m);
2071 time_t mtime = 0;
2072 if (!mdata || (nm_db_get_mtime(m, &mtime) != 0))
2073 return MX_STATUS_ERROR;
2074
2075 int new_flags = 0;
2076 bool occult = false;
2077
2078 if (m->mtime.tv_sec >= mtime)
2079 {
2080 mutt_debug(LL_DEBUG2, "nm: check unnecessary (db=%lu mailbox=%lu)\n", mtime,
2081 m->mtime.tv_sec);
2082 return MX_STATUS_OK;
2083 }
2084
2085 mutt_debug(LL_DEBUG1, "nm: checking (db=%lu mailbox=%lu)\n", mtime, m->mtime.tv_sec);
2086
2087 notmuch_query_t *q = get_query(m, false);
2088 if (!q)
2089 goto done;
2090
2091 mutt_debug(LL_DEBUG1, "nm: start checking (count=%d)\n", m->msg_count);
2092 mdata->oldmsgcount = m->msg_count;
2093
2094 for (int i = 0; i < m->msg_count; i++)
2095 {
2096 struct Email *e = m->emails[i];
2097 if (!e)
2098 break;
2099
2100 e->active = false;
2101 }
2102
2103 int limit = get_limit(mdata);
2104
2105 notmuch_messages_t *msgs = get_messages(q);
2106
2107 // TODO: Analyze impact of removing this version guard.
2108#if LIBNOTMUCH_CHECK_VERSION(5, 0, 0)
2109 if (!msgs)
2110 return MX_STATUS_OK;
2111#elif LIBNOTMUCH_CHECK_VERSION(4, 3, 0)
2112 if (!msgs)
2113 goto done;
2114#endif
2115
2116 struct HeaderCache *h = nm_hcache_open(m);
2117
2118 for (int i = 0; notmuch_messages_valid(msgs) && ((limit == 0) || (i < limit));
2119 notmuch_messages_move_to_next(msgs), i++)
2120 {
2121 notmuch_message_t *msg = notmuch_messages_get(msgs);
2122 struct Email *e = get_mutt_email(m, msg);
2123
2124 if (!e)
2125 {
2126 /* new email */
2127 append_message(h, m, msg, false);
2128 notmuch_message_destroy(msg);
2129 continue;
2130 }
2131
2132 /* message already exists, merge flags */
2133 e->active = true;
2134
2135 /* Check to see if the message has moved to a different subdirectory.
2136 * If so, update the associated filename. */
2137 const char *new_file = get_message_last_filename(msg);
2138 char old_file[PATH_MAX] = { 0 };
2139 email_get_fullpath(e, old_file, sizeof(old_file));
2140
2141 if (!mutt_str_equal(old_file, new_file))
2142 update_message_path(e, new_file);
2143
2144 if (!e->changed)
2145 {
2146 /* if the user hasn't modified the flags on this message, update the
2147 * flags we just detected. */
2148 struct Email e_tmp = { 0 };
2149 e_tmp.edata = maildir_edata_new();
2150 maildir_parse_flags(&e_tmp, new_file);
2151 e_tmp.old = e->old;
2152 maildir_update_flags(m, e, &e_tmp);
2153 maildir_edata_free(&e_tmp.edata);
2154 }
2155
2156 if (update_email_tags(e, msg) == 0)
2157 new_flags++;
2158
2159 notmuch_message_destroy(msg);
2160 }
2161
2162 nm_hcache_close(h);
2163
2164 for (int i = 0; i < m->msg_count; i++)
2165 {
2166 struct Email *e = m->emails[i];
2167 if (!e)
2168 break;
2169
2170 if (!e->active)
2171 {
2172 occult = true;
2173 break;
2174 }
2175 }
2176
2177 if (m->msg_count > mdata->oldmsgcount)
2179done:
2180 if (q)
2181 notmuch_query_destroy(q);
2182
2183 nm_db_release(m);
2184
2186 m->mtime.tv_nsec = 0;
2187
2188 mutt_debug(LL_DEBUG1, "nm: ... check done [count=%d, new_flags=%d, occult=%d]\n",
2189 m->msg_count, new_flags, occult);
2190
2191 if (occult)
2192 return MX_STATUS_REOPENED;
2193 if (m->msg_count > mdata->oldmsgcount)
2194 return MX_STATUS_NEW_MAIL;
2195 if (new_flags)
2196 return MX_STATUS_FLAGS;
2197 return MX_STATUS_OK;
2198}
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:428
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
void maildir_edata_free(void **ptr)
Free the private Email data - Implements Email::edata_free()
Definition: edata.c:38
struct MaildirEmailData * maildir_edata_new(void)
Create a new MaildirEmailData object.
Definition: edata.c:53
void maildir_parse_flags(struct Email *e, const char *path)
Parse Maildir file flags.
Definition: maildir.c:808
int nm_db_get_mtime(struct Mailbox *m, time_t *mtime)
Get the database modification time.
Definition: db.c:304
int nm_db_release(struct Mailbox *m)
Close the Notmuch database.
Definition: db.c:222
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:97
static char * email_get_fullpath(struct Email *e, char *buf, size_t buflen)
Get the full path of an email.
Definition: notmuch.c:224
static void nm_hcache_close(struct HeaderCache *h)
Close the header cache.
Definition: notmuch.c:123
static int get_limit(struct NmMboxData *mdata)
Get the database limit.
Definition: notmuch.c:396
static void append_message(struct HeaderCache *h, struct Mailbox *m, notmuch_message_t *msg, bool dedup)
Associate a message.
Definition: notmuch.c:733
static struct HeaderCache * nm_hcache_open(struct Mailbox *m)
Open a header cache.
Definition: notmuch.c:109
static notmuch_query_t * get_query(struct Mailbox *m, bool writable)
Create a new query.
Definition: notmuch.c:431
static int update_message_path(struct Email *e, const char *path)
Set the path for a message.
Definition: notmuch.c:514
static const char * get_message_last_filename(notmuch_message_t *msg)
Get a message's last filename.
Definition: notmuch.c:646
static int update_email_tags(struct Email *e, notmuch_message_t *msg)
Update the Email's tags from Notmuch.
Definition: notmuch.c:463
static notmuch_messages_t * get_messages(notmuch_query_t *query)
Load messages for a query.
Definition: notmuch.c:897
static struct Email * get_mutt_email(struct Mailbox *m, notmuch_message_t *msg)
Get the Email of a Notmuch message.
Definition: notmuch.c:699
void * edata
Driver-specific data.
Definition: email.h:72
bool old
Email is seen, but unread.
Definition: email.h:47
Header cache structure.
Definition: lib.h:87
Notmuch-specific Mailbox data -.
Definition: mdata.h:34
int oldmsgcount
Definition: mdata.h:41
long tv_nsec
Number of nanosecond, on top.
Definition: file.h:51
time_t tv_sec
Number of seconds since the epoch.
Definition: file.h:50
+ Here is the call graph for this function:

◆ pop_mbox_check()

static enum MxStatus pop_mbox_check ( struct Mailbox m)
static

Check for new mail - Implements MxOps::mbox_check() -.

Definition at line 819 of file pop.c.

820{
822
823 const short c_pop_check_interval = cs_subset_number(NeoMutt->sub, "pop_check_interval");
824 if ((adata->check_time + c_pop_check_interval) > mutt_date_epoch())
825 return MX_STATUS_OK;
826
827 pop_logout(m);
828
830
831 if (pop_open_connection(adata) < 0)
832 return MX_STATUS_ERROR;
833
834 m->size = adata->size;
835
836 mutt_message(_("Checking for new messages..."));
837
838 int old_msg_count = m->msg_count;
839 int rc = pop_fetch_headers(m);
841 if (m->msg_count > old_msg_count)
843
844 if (rc < 0)
845 return MX_STATUS_ERROR;
846
847 if (rc > 0)
848 return MX_STATUS_NEW_MAIL;
849
850 return MX_STATUS_OK;
851}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
#define mutt_message(...)
Definition: logging.h:86
struct PopAccountData * pop_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:64
int pop_open_connection(struct PopAccountData *adata)
Open connection and authenticate.
Definition: lib.c:308
void pop_logout(struct Mailbox *m)
Logout from a POP server.
Definition: lib.c:416
static void pop_clear_cache(struct PopAccountData *adata)
Delete all cached messages.
Definition: pop.c:491
static int pop_fetch_headers(struct Mailbox *m)
Read headers.
Definition: pop.c:321
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:98
POP-specific Account data -.
Definition: adata.h:37
+ Here is the call graph for this function: