NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
mbox.c File Reference
#include "config.h"
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "mutt.h"
#include "lib.h"
#include "copy.h"
#include "mutt_globals.h"
#include "mutt_header.h"
#include "muttlib.h"
#include "mx.h"
#include "progress.h"
#include "protos.h"
#include "sort.h"
+ Include dependency graph for mbox.c:

Go to the source code of this file.

Data Structures

struct  MUpdate
 Store of new offsets, used by mutt_sync_mailbox() More...
 

Functions

static void mbox_adata_free (void **ptr)
 Free the private Account data - Implements Account::adata_free() More...
 
static struct MboxAccountDatambox_adata_new (void)
 Create a new MboxAccountData struct. More...
 
static struct MboxAccountDatambox_adata_get (struct Mailbox *m)
 Get the private data associated with a Mailbox. More...
 
static int init_mailbox (struct Mailbox *m)
 Add Mbox data to the Mailbox. More...
 
static int mbox_lock_mailbox (struct Mailbox *m, bool excl, bool retry)
 Lock a mailbox. More...
 
static void mbox_unlock_mailbox (struct Mailbox *m)
 Unlock a mailbox. More...
 
static enum MxOpenReturns mmdf_parse_mailbox (struct Mailbox *m)
 Read a mailbox in MMDF format. More...
 
static enum MxOpenReturns mbox_parse_mailbox (struct Mailbox *m)
 Read a mailbox from disk. More...
 
static int reopen_mailbox (struct Mailbox *m)
 Close and reopen a mailbox. More...
 
static bool mbox_has_new (struct Mailbox *m)
 Does the mailbox have new mail. More...
 
static int fseek_last_message (FILE *fp)
 Find the last message in the file. More...
 
static bool test_last_status_new (FILE *fp)
 Is the last message new. More...
 
bool mbox_test_new_folder (const char *path)
 Test if an mbox or mmdf mailbox has new mail. More...
 
void mbox_reset_atime (struct Mailbox *m, struct stat *st)
 Reset the access time on the mailbox file. More...
 
static bool mbox_ac_owns_path (struct Account *a, const char *path)
 Check whether an Account owns a Mailbox path - Implements MxOps::ac_owns_path() More...
 
static bool mbox_ac_add (struct Account *a, struct Mailbox *m)
 Add a Mailbox to an Account - Implements MxOps::ac_add() More...
 
static FILE * mbox_open_readwrite (struct Mailbox *m)
 Open an mbox read-write. More...
 
static FILE * mbox_open_readonly (struct Mailbox *m)
 Open an mbox read-only. More...
 
static enum MxOpenReturns mbox_mbox_open (struct Mailbox *m)
 Open a Mailbox - Implements MxOps::mbox_open() More...
 
static bool mbox_mbox_open_append (struct Mailbox *m, OpenMailboxFlags flags)
 Open a Mailbox for appending - Implements MxOps::mbox_open_append() More...
 
static enum MxStatus mbox_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() More...
 
static enum MxStatus mbox_mbox_sync (struct Mailbox *m)
 Save changes to the Mailbox - Implements MxOps::mbox_sync() More...
 
static enum MxStatus mbox_mbox_close (struct Mailbox *m)
 Close a Mailbox - Implements MxOps::mbox_close() More...
 
static bool mbox_msg_open (struct Mailbox *m, struct Message *msg, int msgno)
 Open an email message in a Mailbox - Implements MxOps::msg_open() More...
 
static bool mbox_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() More...
 
static int mbox_msg_commit (struct Mailbox *m, struct Message *msg)
 Save changes to an email - Implements MxOps::msg_commit() More...
 
static int mbox_msg_close (struct Mailbox *m, struct Message *msg)
 Close an email - Implements MxOps::msg_close() More...
 
static int mbox_msg_padding_size (struct Mailbox *m)
 Bytes of padding between messages - Implements MxOps::msg_padding_size() More...
 
enum MailboxType mbox_path_probe (const char *path, const struct stat *st)
 Is this an mbox Mailbox? - Implements MxOps::path_probe() More...
 
static int mbox_path_canon (char *buf, size_t buflen)
 Canonicalise a Mailbox path - Implements MxOps::path_canon() More...
 
static int mbox_path_pretty (char *buf, size_t buflen, const char *folder)
 Abbreviate a Mailbox path - Implements MxOps::path_pretty() More...
 
static int mbox_path_parent (char *buf, size_t buflen)
 Find the parent of a Mailbox path - Implements MxOps::path_parent() More...
 
static int mbox_path_is_empty (const char *path)
 Is the mailbox empty - Implements MxOps::path_is_empty() More...
 
static int mmdf_msg_commit (struct Mailbox *m, struct Message *msg)
 Save changes to an email - Implements MxOps::msg_commit() More...
 
static int mmdf_msg_padding_size (struct Mailbox *m)
 Bytes of padding between messages - Implements MxOps::msg_padding_size() More...
 
static enum MxStatus mbox_mbox_check_stats (struct Mailbox *m, uint8_t flags)
 Check the Mailbox statistics - Implements MxOps::mbox_check_stats() More...
 

Variables

struct MxOps MxMboxOps
 Mbox Mailbox - Implements MxOps. More...
 
struct MxOps MxMmdfOps
 MMDF Mailbox - Implements MxOps. More...
 

Detailed Description

Mbox local mailbox type

Authors
  • Michael R. Elkins
  • Richard Russon
  • Pietro Cerutti

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file mbox.c.

Function Documentation

◆ mbox_adata_free()

static void mbox_adata_free ( void **  ptr)
static

Free the private Account data - Implements Account::adata_free()

Definition at line 75 of file mbox.c.

76 {
77  if (!ptr || !*ptr)
78  return;
79 
80  struct MboxAccountData *m = *ptr;
81 
82  mutt_file_fclose(&m->fp);
83  FREE(ptr);
84 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mbox_adata_new()

static struct MboxAccountData* mbox_adata_new ( void  )
static

Create a new MboxAccountData struct.

Return values
ptrNew MboxAccountData

Definition at line 90 of file mbox.c.

91 {
92  return mutt_mem_calloc(1, sizeof(struct MboxAccountData));
93 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mbox_adata_get()

static struct MboxAccountData* mbox_adata_get ( struct Mailbox m)
static

Get the private data associated with a Mailbox.

Parameters
mMailbox
Return values
ptrPrivate data

Definition at line 100 of file mbox.c.

101 {
102  if (!m)
103  return NULL;
104  if ((m->type != MUTT_MBOX) && (m->type != MUTT_MMDF))
105  return NULL;
106  struct Account *a = m->account;
107  if (!a)
108  return NULL;
109  return a->adata;
110 }
+ Here is the caller graph for this function:

◆ init_mailbox()

static int init_mailbox ( struct Mailbox m)
static

Add Mbox data to the Mailbox.

Parameters
mMailbox
Return values
0Success
-1Error Bad format

Definition at line 118 of file mbox.c.

119 {
120  if (!m || !m->account)
121  return -1;
122  if ((m->type != MUTT_MBOX) && (m->type != MUTT_MMDF))
123  return -1;
124  if (m->account->adata)
125  return 0;
126 
127  m->account->adata = mbox_adata_new();
129  return 0;
130 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mbox_lock_mailbox()

static int mbox_lock_mailbox ( struct Mailbox m,
bool  excl,
bool  retry 
)
static

Lock a mailbox.

Parameters
mMailbox to lock
exclExclusive lock?
retryShould retry if unable to lock?
Return values
0Success
-1Failure

Definition at line 140 of file mbox.c.

141 {
142  struct MboxAccountData *adata = mbox_adata_get(m);
143  if (!adata)
144  return -1;
145 
146  int rc = mutt_file_lock(fileno(adata->fp), excl, retry);
147  if (rc == 0)
148  adata->locked = true;
149  else if (retry && !excl)
150  {
151  m->readonly = true;
152  return 0;
153  }
154 
155  return rc;
156 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mbox_unlock_mailbox()

static void mbox_unlock_mailbox ( struct Mailbox m)
static

Unlock a mailbox.

Parameters
mMailbox to unlock

Definition at line 162 of file mbox.c.

163 {
164  struct MboxAccountData *adata = mbox_adata_get(m);
165  if (!adata)
166  return;
167 
168  if (adata->locked)
169  {
170  fflush(adata->fp);
171 
172  mutt_file_unlock(fileno(adata->fp));
173  adata->locked = false;
174  }
175 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mmdf_parse_mailbox()

static enum MxOpenReturns mmdf_parse_mailbox ( struct Mailbox m)
static

Read a mailbox in MMDF format.

Parameters
mMailbox
Return values
enumMxOpenReturns

Definition at line 182 of file mbox.c.

183 {
184  if (!m)
185  return MX_OPEN_ERROR;
186 
187  struct MboxAccountData *adata = mbox_adata_get(m);
188  if (!adata)
189  return MX_OPEN_ERROR;
190 
191  char buf[8192];
192  char return_path[1024];
193  int count = 0;
194  int lines;
195  time_t t;
196  LOFF_T loc, tmploc;
197  struct Email *e = NULL;
198  struct stat sb;
199  struct Progress progress;
200 
201  if (stat(mailbox_path(m), &sb) == -1)
202  {
204  return MX_OPEN_ERROR;
205  }
208  m->size = sb.st_size;
209 
210  buf[sizeof(buf) - 1] = '\0';
211 
212  if (m->verbose)
213  {
214  char msg[PATH_MAX];
215  snprintf(msg, sizeof(msg), _("Reading %s..."), mailbox_path(m));
216  mutt_progress_init(&progress, msg, MUTT_PROGRESS_READ, 0);
217  }
218 
219  while (true)
220  {
221  if (!fgets(buf, sizeof(buf) - 1, adata->fp))
222  break;
223 
224  if (SigInt == 1)
225  break;
226 
227  if (mutt_str_equal(buf, MMDF_SEP))
228  {
229  loc = ftello(adata->fp);
230  if (loc < 0)
231  return MX_OPEN_ERROR;
232 
233  count++;
234  if (m->verbose)
235  mutt_progress_update(&progress, count, (int) (loc / (m->size / 100 + 1)));
236 
237  if (m->msg_count == m->email_max)
238  mx_alloc_memory(m);
239  e = email_new();
240  m->emails[m->msg_count] = e;
241  e->offset = loc;
242  e->index = m->msg_count;
243 
244  if (!fgets(buf, sizeof(buf) - 1, adata->fp))
245  {
246  /* TODO: memory leak??? */
247  mutt_debug(LL_DEBUG1, "unexpected EOF\n");
248  break;
249  }
250 
251  return_path[0] = '\0';
252 
253  if (!is_from(buf, return_path, sizeof(return_path), &t))
254  {
255  if (fseeko(adata->fp, loc, SEEK_SET) != 0)
256  {
257  mutt_debug(LL_DEBUG1, "#1 fseek() failed\n");
258  mutt_error(_("Mailbox is corrupt"));
259  return MX_OPEN_ERROR;
260  }
261  }
262  else
263  e->received = t - mutt_date_local_tz(t);
264 
265  e->env = mutt_rfc822_read_header(adata->fp, e, false, false);
266 
267  loc = ftello(adata->fp);
268  if (loc < 0)
269  return MX_OPEN_ERROR;
270 
271  if ((e->body->length > 0) && (e->lines > 0))
272  {
273  tmploc = loc + e->body->length;
274 
275  if ((tmploc > 0) && (tmploc < m->size))
276  {
277  if ((fseeko(adata->fp, tmploc, SEEK_SET) != 0) ||
278  !fgets(buf, sizeof(buf) - 1, adata->fp) || !mutt_str_equal(MMDF_SEP, buf))
279  {
280  if (fseeko(adata->fp, loc, SEEK_SET) != 0)
281  mutt_debug(LL_DEBUG1, "#2 fseek() failed\n");
282  e->body->length = -1;
283  }
284  }
285  else
286  e->body->length = -1;
287  }
288  else
289  e->body->length = -1;
290 
291  if (e->body->length < 0)
292  {
293  lines = -1;
294  do
295  {
296  loc = ftello(adata->fp);
297  if (loc < 0)
298  return MX_OPEN_ERROR;
299  if (!fgets(buf, sizeof(buf) - 1, adata->fp))
300  break;
301  lines++;
302  } while (!mutt_str_equal(buf, MMDF_SEP));
303 
304  e->lines = lines;
305  e->body->length = loc - e->body->offset;
306  }
307 
308  if (TAILQ_EMPTY(&e->env->return_path) && return_path[0])
309  mutt_addrlist_parse(&e->env->return_path, return_path);
310 
311  if (TAILQ_EMPTY(&e->env->from))
312  mutt_addrlist_copy(&e->env->from, &e->env->return_path, false);
313 
314  m->msg_count++;
315  }
316  else
317  {
318  mutt_debug(LL_DEBUG1, "corrupt mailbox\n");
319  mutt_error(_("Mailbox is corrupt"));
320  return MX_OPEN_ERROR;
321  }
322  }
323 
324  if (SigInt == 1)
325  {
326  SigInt = 0;
327  return MX_OPEN_ABORT; /* action aborted */
328  }
329 
330  return MX_OPEN_OK;
331 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mbox_parse_mailbox()

static enum MxOpenReturns mbox_parse_mailbox ( struct Mailbox m)
static

Read a mailbox from disk.

Parameters
mMailbox
Return values
enumMxOpenReturns

Note that this function is also called when new mail is appended to the currently open folder, and NOT just when the mailbox is initially read.

Note
It is assumed that the mailbox being read has been locked before this routine gets called. Strange things could happen if it's not!

Definition at line 344 of file mbox.c.

345 {
346  if (!m)
347  return MX_OPEN_ERROR;
348 
349  struct MboxAccountData *adata = mbox_adata_get(m);
350  if (!adata)
351  return MX_OPEN_ERROR;
352 
353  struct stat sb;
354  char buf[8192], return_path[256];
355  struct Email *e_cur = NULL;
356  time_t t;
357  int count = 0, lines = 0;
358  LOFF_T loc;
359  struct Progress progress;
360 
361  /* Save information about the folder at the time we opened it. */
362  if (stat(mailbox_path(m), &sb) == -1)
363  {
365  return MX_OPEN_ERROR;
366  }
367 
368  m->size = sb.st_size;
371 
372  if (!m->readonly)
373  m->readonly = access(mailbox_path(m), W_OK) ? true : false;
374 
375  if (m->verbose)
376  {
377  char msg[PATH_MAX];
378  snprintf(msg, sizeof(msg), _("Reading %s..."), mailbox_path(m));
379  mutt_progress_init(&progress, msg, MUTT_PROGRESS_READ, 0);
380  }
381 
382  loc = ftello(adata->fp);
383  while ((fgets(buf, sizeof(buf), adata->fp)) && (SigInt != 1))
384  {
385  if (is_from(buf, return_path, sizeof(return_path), &t))
386  {
387  /* Save the Content-Length of the previous message */
388  if (count > 0)
389  {
390  struct Email *e = m->emails[m->msg_count - 1];
391  if (e->body->length < 0)
392  {
393  e->body->length = loc - e->body->offset - 1;
394  if (e->body->length < 0)
395  e->body->length = 0;
396  }
397  if (!e->lines)
398  e->lines = lines ? lines - 1 : 0;
399  }
400 
401  count++;
402 
403  if (m->verbose)
404  {
405  mutt_progress_update(&progress, count,
406  (int) (ftello(adata->fp) / (m->size / 100 + 1)));
407  }
408 
409  if (m->msg_count == m->email_max)
410  mx_alloc_memory(m);
411 
412  m->emails[m->msg_count] = email_new();
413  e_cur = m->emails[m->msg_count];
414  e_cur->received = t - mutt_date_local_tz(t);
415  e_cur->offset = loc;
416  e_cur->index = m->msg_count;
417 
418  e_cur->env = mutt_rfc822_read_header(adata->fp, e_cur, false, false);
419 
420  /* if we know how long this message is, either just skip over the body,
421  * or if we don't know how many lines there are, count them now (this will
422  * save time by not having to search for the next message marker). */
423  if (e_cur->body->length > 0)
424  {
425  LOFF_T tmploc;
426 
427  loc = ftello(adata->fp);
428 
429  /* The test below avoids a potential integer overflow if the
430  * content-length is huge (thus necessarily invalid). */
431  tmploc = (e_cur->body->length < m->size) ? (loc + e_cur->body->length + 1) : -1;
432 
433  if ((tmploc > 0) && (tmploc < m->size))
434  {
435  /* check to see if the content-length looks valid. we expect to
436  * to see a valid message separator at this point in the stream */
437  if ((fseeko(adata->fp, tmploc, SEEK_SET) != 0) ||
438  !fgets(buf, sizeof(buf), adata->fp) || !mutt_str_startswith(buf, "From "))
439  {
440  mutt_debug(LL_DEBUG1, "bad content-length in message %d (cl=" OFF_T_FMT ")\n",
441  e_cur->index, e_cur->body->length);
442  mutt_debug(LL_DEBUG1, " LINE: %s", buf);
443  /* nope, return the previous position */
444  if ((loc < 0) || (fseeko(adata->fp, loc, SEEK_SET) != 0))
445  {
446  mutt_debug(LL_DEBUG1, "#1 fseek() failed\n");
447  }
448  e_cur->body->length = -1;
449  }
450  }
451  else if (tmploc != m->size)
452  {
453  /* content-length would put us past the end of the file, so it
454  * must be wrong */
455  e_cur->body->length = -1;
456  }
457 
458  if (e_cur->body->length != -1)
459  {
460  /* good content-length. check to see if we know how many lines
461  * are in this message. */
462  if (e_cur->lines == 0)
463  {
464  int cl = e_cur->body->length;
465 
466  /* count the number of lines in this message */
467  if ((loc < 0) || (fseeko(adata->fp, loc, SEEK_SET) != 0))
468  mutt_debug(LL_DEBUG1, "#2 fseek() failed\n");
469  while (cl-- > 0)
470  {
471  if (fgetc(adata->fp) == '\n')
472  e_cur->lines++;
473  }
474  }
475 
476  /* return to the offset of the next message separator */
477  if (fseeko(adata->fp, tmploc, SEEK_SET) != 0)
478  mutt_debug(LL_DEBUG1, "#3 fseek() failed\n");
479  }
480  }
481 
482  m->msg_count++;
483 
484  if (TAILQ_EMPTY(&e_cur->env->return_path) && return_path[0])
485  {
486  mutt_addrlist_parse(&e_cur->env->return_path, return_path);
487  }
488 
489  if (TAILQ_EMPTY(&e_cur->env->from))
490  mutt_addrlist_copy(&e_cur->env->from, &e_cur->env->return_path, false);
491 
492  lines = 0;
493  }
494  else
495  lines++;
496 
497  loc = ftello(adata->fp);
498  }
499 
500  /* Only set the content-length of the previous message if we have read more
501  * than one message during _this_ invocation. If this routine is called
502  * when new mail is received, we need to make sure not to clobber what
503  * previously was the last message since the headers may be sorted. */
504  if (count > 0)
505  {
506  struct Email *e = m->emails[m->msg_count - 1];
507  if (e->body->length < 0)
508  {
509  e->body->length = ftello(adata->fp) - e->body->offset - 1;
510  if (e->body->length < 0)
511  e->body->length = 0;
512  }
513 
514  if (!e->lines)
515  e->lines = lines ? lines - 1 : 0;
516  }
517 
518  if (SigInt == 1)
519  {
520  SigInt = 0;
521  return MX_OPEN_ABORT; /* action aborted */
522  }
523 
524  return MX_OPEN_OK;
525 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ reopen_mailbox()

static int reopen_mailbox ( struct Mailbox m)
static

Close and reopen a mailbox.

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

Definition at line 533 of file mbox.c.

534 {
535  if (!m)
536  return -1;
537 
538  struct MboxAccountData *adata = mbox_adata_get(m);
539  if (!adata)
540  return -1;
541 
542  bool (*cmp_headers)(const struct Email *, const struct Email *) = NULL;
543  struct Email **e_old = NULL;
544  int old_msg_count;
545  bool msg_mod = false;
546  int rc = -1;
547 
548  /* silent operations */
549  m->verbose = false;
550 
551  /* our heuristics require the old mailbox to be unsorted */
552  if (C_Sort != SORT_ORDER)
553  {
554  short old_sort = C_Sort;
555  C_Sort = SORT_ORDER;
557  C_Sort = old_sort;
558  }
559 
560  e_old = NULL;
561  old_msg_count = 0;
562 
563  /* simulate a close */
564  mutt_hash_free(&m->id_hash);
567  FREE(&m->v2r);
568  if (m->readonly)
569  {
570  for (int i = 0; i < m->msg_count; i++)
571  email_free(&(m->emails[i])); /* nothing to do! */
572  FREE(&m->emails);
573  }
574  else
575  {
576  /* save the old headers */
577  old_msg_count = m->msg_count;
578  e_old = m->emails;
579  m->emails = NULL;
580  }
581 
582  m->email_max = 0; /* force allocation of new headers */
583  m->msg_count = 0;
584  m->vcount = 0;
585  m->msg_tagged = 0;
586  m->msg_deleted = 0;
587  m->msg_new = 0;
588  m->msg_unread = 0;
589  m->msg_flagged = 0;
590  m->changed = false;
591  m->id_hash = NULL;
592  m->subj_hash = NULL;
594 
595  switch (m->type)
596  {
597  case MUTT_MBOX:
598  case MUTT_MMDF:
599  cmp_headers = email_cmp_strict;
600  mutt_file_fclose(&adata->fp);
601  adata->fp = mutt_file_fopen(mailbox_path(m), "r");
602  if (!adata->fp)
603  rc = -1;
604  else if (m->type == MUTT_MBOX)
605  rc = mbox_parse_mailbox(m);
606  else
607  rc = mmdf_parse_mailbox(m);
608  break;
609 
610  default:
611  rc = -1;
612  break;
613  }
614 
615  if (rc == -1)
616  {
617  /* free the old headers */
618  for (int i = 0; i < old_msg_count; i++)
619  email_free(&(e_old[i]));
620  FREE(&e_old);
621 
622  m->verbose = true;
623  return -1;
624  }
625 
626  mutt_file_touch_atime(fileno(adata->fp));
627 
628  /* now try to recover the old flags */
629 
630  if (!m->readonly)
631  {
632  for (int i = 0; i < m->msg_count; i++)
633  {
634  bool found = false;
635 
636  /* some messages have been deleted, and new messages have been
637  * appended at the end; the heuristic is that old messages have then
638  * "advanced" towards the beginning of the folder, so we begin the
639  * search at index "i" */
640  int j;
641  for (j = i; j < old_msg_count; j++)
642  {
643  if (!e_old[j])
644  continue;
645  if (cmp_headers(m->emails[i], e_old[j]))
646  {
647  found = true;
648  break;
649  }
650  }
651  if (!found)
652  {
653  for (j = 0; (j < i) && (j < old_msg_count); j++)
654  {
655  if (!e_old[j])
656  continue;
657  if (cmp_headers(m->emails[i], e_old[j]))
658  {
659  found = true;
660  break;
661  }
662  }
663  }
664 
665  if (found)
666  {
667  m->changed = true;
668  if (e_old[j]->changed)
669  {
670  /* Only update the flags if the old header was changed;
671  * otherwise, the header may have been modified externally,
672  * and we don't want to lose _those_ changes */
673  mutt_set_flag(m, m->emails[i], MUTT_FLAG, e_old[j]->flagged);
674  mutt_set_flag(m, m->emails[i], MUTT_REPLIED, e_old[j]->replied);
675  mutt_set_flag(m, m->emails[i], MUTT_OLD, e_old[j]->old);
676  mutt_set_flag(m, m->emails[i], MUTT_READ, e_old[j]->read);
677  }
678  mutt_set_flag(m, m->emails[i], MUTT_DELETE, e_old[j]->deleted);
679  mutt_set_flag(m, m->emails[i], MUTT_PURGE, e_old[j]->purge);
680  mutt_set_flag(m, m->emails[i], MUTT_TAG, e_old[j]->tagged);
681 
682  /* we don't need this header any more */
683  email_free(&(e_old[j]));
684  }
685  }
686 
687  /* free the remaining old headers */
688  for (int j = 0; j < old_msg_count; j++)
689  {
690  if (e_old[j])
691  {
692  email_free(&(e_old[j]));
693  msg_mod = true;
694  }
695  }
696  FREE(&e_old);
697  }
698 
700  m->verbose = true;
701 
702  return (m->changed || msg_mod) ? MX_STATUS_REOPENED : MX_STATUS_NEW_MAIL;
703 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mbox_has_new()

static bool mbox_has_new ( struct Mailbox m)
static

Does the mailbox have new mail.

Parameters
mMailbox
Return values
trueif the mailbox has at least 1 new messages (not old)
falseotherwise

Definition at line 711 of file mbox.c.

712 {
713  for (int i = 0; i < m->msg_count; i++)
714  {
715  struct Email *e = m->emails[i];
716  if (!e)
717  break;
718  if (!e->deleted && !e->read && !e->old)
719  return true;
720  }
721  return false;
722 }
+ Here is the caller graph for this function:

◆ fseek_last_message()

static int fseek_last_message ( FILE *  fp)
static

Find the last message in the file.

Parameters
fpFile to search
Return values
0Success
-1No message found

Definition at line 730 of file mbox.c.

731 {
732  LOFF_T pos;
733  char buf[BUFSIZ + 9] = { 0 }; /* 7 for "\n\nFrom " */
734  size_t bytes_read;
735 
736  fseek(fp, 0, SEEK_END);
737  pos = ftello(fp);
738 
739  /* Set 'bytes_read' to the size of the last, probably partial, buf;
740  * 0 < 'bytes_read' <= 'BUFSIZ'. */
741  bytes_read = pos % BUFSIZ;
742  if (bytes_read == 0)
743  bytes_read = BUFSIZ;
744  /* Make 'pos' a multiple of 'BUFSIZ' (0 if the file is short), so that all
745  * reads will be on block boundaries, which might increase efficiency. */
746  while ((pos -= bytes_read) >= 0)
747  {
748  /* we save in the buf at the end the first 7 chars from the last read */
749  strncpy(buf + BUFSIZ, buf, 5 + 2); /* 2 == 2 * mutt_str_len(CRLF) */
750  fseeko(fp, pos, SEEK_SET);
751  bytes_read = fread(buf, sizeof(char), bytes_read, fp);
752  if (bytes_read == 0)
753  return -1;
754  /* 'i' is Index into 'buf' for scanning. */
755  for (int i = bytes_read; i >= 0; i--)
756  {
757  if (mutt_str_startswith(buf + i, "\n\nFrom "))
758  { /* found it - go to the beginning of the From */
759  fseeko(fp, pos + i + 2, SEEK_SET);
760  return 0;
761  }
762  }
763  bytes_read = BUFSIZ;
764  }
765 
766  /* here we are at the beginning of the file */
767  if (mutt_str_startswith(buf, "From "))
768  {
769  fseek(fp, 0, SEEK_SET);
770  return 0;
771  }
772 
773  return -1;
774 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ test_last_status_new()

static bool test_last_status_new ( FILE *  fp)
static

Is the last message new.

Parameters
fpFile to check
Return values
trueif the last message is new

Definition at line 781 of file mbox.c.

782 {
783  struct Email *e = NULL;
784  struct Envelope *tmp_envelope = NULL;
785  bool rc = false;
786 
787  if (fseek_last_message(fp) == -1)
788  return false;
789 
790  e = email_new();
791  tmp_envelope = mutt_rfc822_read_header(fp, e, false, false);
792  if (!e->read && !e->old)
793  rc = true;
794 
795  mutt_env_free(&tmp_envelope);
796  email_free(&e);
797 
798  return rc;
799 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mbox_test_new_folder()

bool mbox_test_new_folder ( const char *  path)

Test if an mbox or mmdf mailbox has new mail.

Parameters
pathPath to the mailbox
Return values
booltrue if the folder contains new mail

Definition at line 806 of file mbox.c.

807 {
808  bool rc = false;
809 
810  enum MailboxType type = mx_path_probe(path);
811 
812  if ((type != MUTT_MBOX) && (type != MUTT_MMDF))
813  return false;
814 
815  FILE *fp = fopen(path, "rb");
816  if (fp)
817  {
818  rc = test_last_status_new(fp);
819  mutt_file_fclose(&fp);
820  }
821 
822  return rc;
823 }
+ Here is the call graph for this function:

◆ mbox_reset_atime()

void mbox_reset_atime ( struct Mailbox m,
struct stat *  st 
)

Reset the access time on the mailbox file.

Parameters
mMailbox
stTimestamp

if mailbox has at least 1 new message, sets mtime > atime of mailbox so mailbox check reports new mail

Definition at line 833 of file mbox.c.

834 {
835  struct utimbuf utimebuf;
836  struct stat st2;
837 
838  if (!st)
839  {
840  if (stat(mailbox_path(m), &st2) < 0)
841  return;
842  st = &st2;
843  }
844 
845  utimebuf.actime = st->st_atime;
846  utimebuf.modtime = st->st_mtime;
847 
848  /* When $mbox_check_recent is set, existing new mail is ignored, so do not
849  * reset the atime to mtime-1 to signal new mail. */
850  if (!C_MailCheckRecent && (utimebuf.actime >= utimebuf.modtime) && mbox_has_new(m))
851  {
852  utimebuf.actime = utimebuf.modtime - 1;
853  }
854 
855  utime(mailbox_path(m), &utimebuf);
856 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mbox_ac_owns_path()

static bool mbox_ac_owns_path ( struct Account a,
const char *  path 
)
static

Check whether an Account owns a Mailbox path - Implements MxOps::ac_owns_path()

Definition at line 861 of file mbox.c.

862 {
863  if ((a->type != MUTT_MBOX) && (a->type != MUTT_MMDF))
864  return false;
865 
866  struct MailboxNode *np = STAILQ_FIRST(&a->mailboxes);
867  if (!np)
868  return false;
869 
870  return mutt_str_equal(mailbox_path(np->mailbox), path);
871 }
+ Here is the call graph for this function:

◆ mbox_ac_add()

static bool mbox_ac_add ( struct Account a,
struct Mailbox m 
)
static

Add a Mailbox to an Account - Implements MxOps::ac_add()

Definition at line 876 of file mbox.c.

877 {
878  return true;
879 }

◆ mbox_open_readwrite()

static FILE* mbox_open_readwrite ( struct Mailbox m)
static

Open an mbox read-write.

Parameters
mMailbox
Return values
ptrFILE handle

This function ensures that the FILE and readonly flag are changed atomically.

Definition at line 888 of file mbox.c.

889 {
890  FILE *fp = fopen(mailbox_path(m), "r+");
891  if (fp)
892  m->readonly = false;
893  return fp;
894 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mbox_open_readonly()

static FILE* mbox_open_readonly ( struct Mailbox m)
static

Open an mbox read-only.

Parameters
mMailbox
Return values
ptrFILE handle

This function ensures that the FILE and readonly flag are changed atomically.

Definition at line 903 of file mbox.c.

904 {
905  FILE *fp = fopen(mailbox_path(m), "r");
906  if (fp)
907  m->readonly = true;
908  return fp;
909 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mbox_mbox_open()

static enum MxOpenReturns mbox_mbox_open ( struct Mailbox m)
static

Open a Mailbox - Implements MxOps::mbox_open()

Definition at line 914 of file mbox.c.

915 {
916  if (init_mailbox(m) != 0)
917  return MX_OPEN_ERROR;
918 
919  struct MboxAccountData *adata = mbox_adata_get(m);
920  if (!adata)
921  return MX_OPEN_ERROR;
922 
923  adata->fp = mbox_open_readwrite(m);
924  if (!adata->fp)
925  {
926  adata->fp = mbox_open_readonly(m);
927  }
928  if (!adata->fp)
929  {
931  return MX_OPEN_ERROR;
932  }
933 
934  mutt_sig_block();
935  if (mbox_lock_mailbox(m, false, true) == -1)
936  {
938  return MX_OPEN_ERROR;
939  }
940 
941  m->has_new = true;
942  enum MxOpenReturns rc = MX_OPEN_ERROR;
943  if (m->type == MUTT_MBOX)
944  rc = mbox_parse_mailbox(m);
945  else if (m->type == MUTT_MMDF)
946  rc = mmdf_parse_mailbox(m);
947  else
948  rc = MX_OPEN_ERROR;
949 
950  if (!mbox_has_new(m))
951  m->has_new = false;
952  clearerr(adata->fp); // Clear the EOF flag
953  mutt_file_touch_atime(fileno(adata->fp));
954 
957  return rc;
958 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mbox_mbox_open_append()

static bool mbox_mbox_open_append ( struct Mailbox m,
OpenMailboxFlags  flags 
)
static

Open a Mailbox for appending - Implements MxOps::mbox_open_append()

Definition at line 963 of file mbox.c.

964 {
965  if (init_mailbox(m) != 0)
966  return false;
967 
968  struct MboxAccountData *adata = mbox_adata_get(m);
969  if (!adata)
970  return false;
971 
972  if (!adata->fp)
973  {
974  // create dir recursively
975  char *tmp_path = mutt_path_dirname(mailbox_path(m));
976  if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
977  {
979  FREE(&tmp_path);
980  return false;
981  }
982  FREE(&tmp_path);
983 
984  adata->fp =
985  mutt_file_fopen(mailbox_path(m), (flags & MUTT_NEWFOLDER) ? "w+" : "a+");
986  if (!adata->fp)
987  {
989  return false;
990  }
991 
992  if (mbox_lock_mailbox(m, true, true) != false)
993  {
994  mutt_error(_("Couldn't lock %s"), mailbox_path(m));
995  mutt_file_fclose(&adata->fp);
996  return false;
997  }
998  }
999 
1000  fseek(adata->fp, 0, SEEK_END);
1001 
1002  return true;
1003 }
+ Here is the call 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 1012 of file mbox.c.

1013 {
1014  struct MboxAccountData *adata = mbox_adata_get(m);
1015  if (!adata)
1016  return MX_STATUS_ERROR;
1017 
1018  if (!adata->fp)
1019  {
1020  if (mbox_mbox_open(m) != MX_OPEN_OK)
1021  return MX_STATUS_ERROR;
1023  }
1024 
1025  struct stat st;
1026  bool unlock = false;
1027  bool modified = false;
1028 
1029  if (stat(mailbox_path(m), &st) == 0)
1030  {
1031  if ((mutt_file_stat_timespec_compare(&st, MUTT_STAT_MTIME, &m->mtime) == 0) &&
1032  (st.st_size == m->size))
1033  {
1034  return MX_STATUS_OK;
1035  }
1036 
1037  if (st.st_size == m->size)
1038  {
1039  /* the file was touched, but it is still the same length, so just exit */
1041  return MX_STATUS_OK;
1042  }
1043 
1044  if (st.st_size > m->size)
1045  {
1046  /* lock the file if it isn't already */
1047  if (!adata->locked)
1048  {
1049  mutt_sig_block();
1050  if (mbox_lock_mailbox(m, false, false) == -1)
1051  {
1052  mutt_sig_unblock();
1053  /* we couldn't lock the mailbox, but nothing serious happened:
1054  * probably the new mail arrived: no reason to wait till we can
1055  * parse it: we'll get it on the next pass */
1056  return MX_STATUS_LOCKED;
1057  }
1058  unlock = 1;
1059  }
1060 
1061  /* Check to make sure that the only change to the mailbox is that
1062  * message(s) were appended to this file. My heuristic is that we should
1063  * see the message separator at *exactly* what used to be the end of the
1064  * folder. */
1065  char buf[1024];
1066  if (fseeko(adata->fp, m->size, SEEK_SET) != 0)
1067  mutt_debug(LL_DEBUG1, "#1 fseek() failed\n");
1068  if (fgets(buf, sizeof(buf), adata->fp))
1069  {
1070  if (((m->type == MUTT_MBOX) && mutt_str_startswith(buf, "From ")) ||
1071  ((m->type == MUTT_MMDF) && mutt_str_equal(buf, MMDF_SEP)))
1072  {
1073  if (fseeko(adata->fp, m->size, SEEK_SET) != 0)
1074  mutt_debug(LL_DEBUG1, "#2 fseek() failed\n");
1075 
1076  int old_msg_count = m->msg_count;
1077  if (m->type == MUTT_MBOX)
1078  mbox_parse_mailbox(m);
1079  else
1080  mmdf_parse_mailbox(m);
1081 
1082  if (m->msg_count > old_msg_count)
1084 
1085  /* Only unlock the folder if it was locked inside of this routine.
1086  * It may have been locked elsewhere, like in
1087  * mutt_checkpoint_mailbox(). */
1088  if (unlock)
1089  {
1091  mutt_sig_unblock();
1092  }
1093 
1094  return MX_STATUS_NEW_MAIL; /* signal that new mail arrived */
1095  }
1096  else
1097  modified = true;
1098  }
1099  else
1100  {
1101  mutt_debug(LL_DEBUG1, "fgets returned NULL\n");
1102  modified = true;
1103  }
1104  }
1105  else
1106  modified = true;
1107  }
1108 
1109  if (modified)
1110  {
1111  if (reopen_mailbox(m) != -1)
1112  {
1114  if (unlock)
1115  {
1117  mutt_sig_unblock();
1118  }
1119  return MX_STATUS_REOPENED;
1120  }
1121  }
1122 
1123  /* fatal error */
1124 
1127  mutt_sig_unblock();
1128  mutt_error(_("Mailbox was corrupted"));
1129  return MX_STATUS_ERROR;
1130 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mbox_mbox_sync()

static enum MxStatus mbox_mbox_sync ( struct Mailbox m)
static

Save changes to the Mailbox - Implements MxOps::mbox_sync()

Definition at line 1135 of file mbox.c.

1136 {
1137  struct MboxAccountData *adata = mbox_adata_get(m);
1138  if (!adata)
1139  return MX_STATUS_ERROR;
1140 
1141  struct Buffer *tempfile = NULL;
1142  char buf[32];
1143  int j;
1144  enum SortType save_sort = SORT_ORDER;
1145  bool unlink_tempfile = false;
1146  int need_sort = 0; /* flag to resort mailbox if new mail arrives */
1147  int first = -1; /* first message to be written */
1148  LOFF_T offset; /* location in mailbox to write changed messages */
1149  struct stat statbuf;
1150  struct MUpdate *new_offset = NULL;
1151  struct MUpdate *old_offset = NULL;
1152  FILE *fp = NULL;
1153  struct Progress progress;
1154  enum MxStatus rc = MX_STATUS_ERROR;
1155 
1156  /* sort message by their position in the mailbox on disk */
1157  if (C_Sort != SORT_ORDER)
1158  {
1159  save_sort = C_Sort;
1160  C_Sort = SORT_ORDER;
1162  C_Sort = save_sort;
1163  need_sort = 1;
1164  }
1165 
1166  /* need to open the file for writing in such a way that it does not truncate
1167  * the file, so use read-write mode. */
1168  adata->fp = freopen(mailbox_path(m), "r+", adata->fp);
1169  if (!adata->fp)
1170  {
1172  mutt_error(_("Fatal error! Could not reopen mailbox!"));
1173  goto fatal;
1174  }
1175 
1176  mutt_sig_block();
1177 
1178  if (mbox_lock_mailbox(m, true, true) == -1)
1179  {
1180  mutt_sig_unblock();
1181  mutt_error(_("Unable to lock mailbox"));
1182  goto bail;
1183  }
1184 
1185  /* Check to make sure that the file hasn't changed on disk */
1186  enum MxStatus check = mbox_mbox_check(m);
1187  if ((check == MX_STATUS_NEW_MAIL) || (check == MX_STATUS_REOPENED))
1188  {
1189  /* new mail arrived, or mailbox reopened */
1190  rc = check;
1191  goto bail;
1192  }
1193  else if (check < 0)
1194  {
1195  goto fatal;
1196  }
1197 
1198  /* Create a temporary file to write the new version of the mailbox in. */
1199  tempfile = mutt_buffer_pool_get();
1200  mutt_buffer_mktemp(tempfile);
1201  int fd = open(mutt_buffer_string(tempfile), O_WRONLY | O_EXCL | O_CREAT, 0600);
1202  if ((fd == -1) || !(fp = fdopen(fd, "w")))
1203  {
1204  if (fd != -1)
1205  {
1206  close(fd);
1207  unlink_tempfile = true;
1208  }
1209  mutt_error(_("Could not create temporary file"));
1210  goto bail;
1211  }
1212  unlink_tempfile = true;
1213 
1214  /* find the first deleted/changed message. we save a lot of time by only
1215  * rewriting the mailbox from the point where it has actually changed. */
1216  int i = 0;
1217  for (; (i < m->msg_count) && !m->emails[i]->deleted &&
1218  !m->emails[i]->changed && !m->emails[i]->attach_del;
1219  i++)
1220  {
1221  }
1222  if (i == m->msg_count)
1223  {
1224  /* this means ctx->changed or m->msg_deleted was set, but no
1225  * messages were found to be changed or deleted. This should
1226  * never happen, is we presume it is a bug in neomutt. */
1227  mutt_error(
1228  _("sync: mbox modified, but no modified messages (report this bug)"));
1229  mutt_debug(LL_DEBUG1, "no modified messages\n");
1230  goto bail;
1231  }
1232 
1233  /* save the index of the first changed/deleted message */
1234  first = i;
1235  /* where to start overwriting */
1236  offset = m->emails[i]->offset;
1237 
1238  /* the offset stored in the header does not include the MMDF_SEP, so make
1239  * sure we seek to the correct location */
1240  if (m->type == MUTT_MMDF)
1241  offset -= (sizeof(MMDF_SEP) - 1);
1242 
1243  /* allocate space for the new offsets */
1244  new_offset = mutt_mem_calloc(m->msg_count - first, sizeof(struct MUpdate));
1245  old_offset = mutt_mem_calloc(m->msg_count - first, sizeof(struct MUpdate));
1246 
1247  if (m->verbose)
1248  {
1249  char msg[PATH_MAX];
1250  snprintf(msg, sizeof(msg), _("Writing %s..."), mailbox_path(m));
1252  }
1253 
1254  for (i = first, j = 0; i < m->msg_count; i++)
1255  {
1256  if (m->verbose)
1257  mutt_progress_update(&progress, i, i / (m->msg_count / 100 + 1));
1258  /* back up some information which is needed to restore offsets when
1259  * something fails. */
1260 
1261  old_offset[i - first].valid = true;
1262  old_offset[i - first].hdr = m->emails[i]->offset;
1263  old_offset[i - first].body = m->emails[i]->body->offset;
1264  old_offset[i - first].lines = m->emails[i]->lines;
1265  old_offset[i - first].length = m->emails[i]->body->length;
1266 
1267  if (!m->emails[i]->deleted)
1268  {
1269  j++;
1270 
1271  if (m->type == MUTT_MMDF)
1272  {
1273  if (fputs(MMDF_SEP, fp) == EOF)
1274  {
1275  mutt_perror(mutt_buffer_string(tempfile));
1276  goto bail;
1277  }
1278  }
1279 
1280  /* save the new offset for this message. we add 'offset' because the
1281  * temporary file only contains saved message which are located after
1282  * 'offset' in the real mailbox */
1283  new_offset[i - first].hdr = ftello(fp) + offset;
1284 
1285  if (mutt_copy_message(fp, m, m->emails[i], MUTT_CM_UPDATE,
1286  CH_FROM | CH_UPDATE | CH_UPDATE_LEN, 0) != 0)
1287  {
1288  mutt_perror(mutt_buffer_string(tempfile));
1289  goto bail;
1290  }
1291 
1292  /* Since messages could have been deleted, the offsets stored in memory
1293  * will be wrong, so update what we can, which is the offset of this
1294  * message, and the offset of the body. If this is a multipart message,
1295  * we just flush the in memory cache so that the message will be reparsed
1296  * if the user accesses it later. */
1297  new_offset[i - first].body = ftello(fp) - m->emails[i]->body->length + offset;
1298  mutt_body_free(&m->emails[i]->body->parts);
1299 
1300  switch (m->type)
1301  {
1302  case MUTT_MMDF:
1303  if (fputs(MMDF_SEP, fp) == EOF)
1304  {
1305  mutt_perror(mutt_buffer_string(tempfile));
1306  goto bail;
1307  }
1308  break;
1309  default:
1310  if (fputs("\n", fp) == EOF)
1311  {
1312  mutt_perror(mutt_buffer_string(tempfile));
1313  goto bail;
1314  }
1315  }
1316  }
1317  }
1318 
1319  if (mutt_file_fclose(&fp) != 0)
1320  {
1321  mutt_debug(LL_DEBUG1, "mutt_file_fclose (&) returned non-zero\n");
1322  mutt_perror(mutt_buffer_string(tempfile));
1323  goto bail;
1324  }
1325 
1326  /* Save the state of this folder. */
1327  if (stat(mailbox_path(m), &statbuf) == -1)
1328  {
1330  goto bail;
1331  }
1332 
1333  unlink_tempfile = false;
1334 
1335  fp = fopen(mutt_buffer_string(tempfile), "r");
1336  if (!fp)
1337  {
1338  mutt_sig_unblock();
1340  mutt_debug(LL_DEBUG1, "unable to reopen temp copy of mailbox!\n");
1341  mutt_perror(mutt_buffer_string(tempfile));
1342  FREE(&new_offset);
1343  FREE(&old_offset);
1344  goto fatal;
1345  }
1346 
1347  if ((fseeko(adata->fp, offset, SEEK_SET) != 0) || /* seek the append location */
1348  /* do a sanity check to make sure the mailbox looks ok */
1349  !fgets(buf, sizeof(buf), adata->fp) ||
1350  ((m->type == MUTT_MBOX) && !mutt_str_startswith(buf, "From ")) ||
1351  ((m->type == MUTT_MMDF) && !mutt_str_equal(MMDF_SEP, buf)))
1352  {
1353  mutt_debug(LL_DEBUG1, "message not in expected position\n");
1354  mutt_debug(LL_DEBUG1, " LINE: %s\n", buf);
1355  i = -1;
1356  }
1357  else
1358  {
1359  if (fseeko(adata->fp, offset, SEEK_SET) != 0) /* return to proper offset */
1360  {
1361  i = -1;
1362  mutt_debug(LL_DEBUG1, "fseek() failed\n");
1363  }
1364  else
1365  {
1366  /* copy the temp mailbox back into place starting at the first
1367  * change/deleted message */
1368  if (m->verbose)
1369  mutt_message(_("Committing changes..."));
1370  i = mutt_file_copy_stream(fp, adata->fp);
1371 
1372  if (ferror(adata->fp))
1373  i = -1;
1374  }
1375  if (i >= 0)
1376  {
1377  m->size = ftello(adata->fp); /* update the mailbox->size of the mailbox */
1378  if ((m->size < 0) || (ftruncate(fileno(adata->fp), m->size) != 0))
1379  {
1380  i = -1;
1381  mutt_debug(LL_DEBUG1, "ftruncate() failed\n");
1382  }
1383  }
1384  }
1385 
1386  mutt_file_fclose(&fp);
1387  fp = NULL;
1389 
1390  if ((mutt_file_fclose(&adata->fp) != 0) || (i == -1))
1391  {
1392  /* error occurred while writing the mailbox back, so keep the temp copy around */
1393 
1394  struct Buffer *savefile = mutt_buffer_pool_get();
1395 
1396  mutt_buffer_printf(savefile, "%s/neomutt.%s-%s-%u", NONULL(C_Tmpdir), NONULL(Username),
1397  NONULL(ShortHostname), (unsigned int) getpid());
1398  rename(mutt_buffer_string(tempfile), mutt_buffer_string(savefile));
1399  mutt_sig_unblock();
1401  mutt_buffer_pretty_mailbox(savefile);
1402  mutt_error(_("Write failed! Saved partial mailbox to %s"), mutt_buffer_string(savefile));
1403  mutt_buffer_pool_release(&savefile);
1404  FREE(&new_offset);
1405  FREE(&old_offset);
1406  goto fatal;
1407  }
1408 
1409  /* Restore the previous access/modification times */
1410  mbox_reset_atime(m, &statbuf);
1411 
1412  /* reopen the mailbox in read-only mode */
1413  adata->fp = mbox_open_readwrite(m);
1414  if (!adata->fp)
1415  {
1416  adata->fp = mbox_open_readonly(m);
1417  }
1418  if (!adata->fp)
1419  {
1420  unlink(mutt_buffer_string(tempfile));
1421  mutt_sig_unblock();
1423  mutt_error(_("Fatal error! Could not reopen mailbox!"));
1424  FREE(&new_offset);
1425  FREE(&old_offset);
1426  goto fatal;
1427  }
1428 
1429  /* update the offsets of the rewritten messages */
1430  for (i = first, j = first; i < m->msg_count; i++)
1431  {
1432  if (!m->emails[i]->deleted)
1433  {
1434  m->emails[i]->offset = new_offset[i - first].hdr;
1435  m->emails[i]->body->hdr_offset = new_offset[i - first].hdr;
1436  m->emails[i]->body->offset = new_offset[i - first].body;
1437  m->emails[i]->index = j++;
1438  }
1439  }
1440  FREE(&new_offset);
1441  FREE(&old_offset);
1442  unlink(mutt_buffer_string(tempfile)); /* remove partial copy of the mailbox */
1443  mutt_buffer_pool_release(&tempfile);
1444  mutt_sig_unblock();
1445 
1446  if (C_CheckMboxSize)
1447  {
1448  struct Mailbox *m_tmp = mailbox_find(mailbox_path(m));
1449  if (m_tmp && !m_tmp->has_new)
1450  mailbox_update(m_tmp);
1451  }
1452 
1453  return 0; /* signal success */
1454 
1455 bail: /* Come here in case of disaster */
1456 
1457  mutt_file_fclose(&fp);
1458 
1459  if (tempfile && unlink_tempfile)
1460  unlink(mutt_buffer_string(tempfile));
1461 
1462  /* restore offsets, as far as they are valid */
1463  if ((first >= 0) && old_offset)
1464  {
1465  for (i = first; (i < m->msg_count) && old_offset[i - first].valid; i++)
1466  {
1467  m->emails[i]->offset = old_offset[i - first].hdr;
1468  m->emails[i]->body->hdr_offset = old_offset[i - first].hdr;
1469  m->emails[i]->body->offset = old_offset[i - first].body;
1470  m->emails[i]->lines = old_offset[i - first].lines;
1471  m->emails[i]->body->length = old_offset[i - first].length;
1472  }
1473  }
1474 
1475  /* this is ok to call even if we haven't locked anything */
1477 
1478  mutt_sig_unblock();
1479  FREE(&new_offset);
1480  FREE(&old_offset);
1481 
1482  adata->fp = freopen(mailbox_path(m), "r", adata->fp);
1483  if (!adata->fp)
1484  {
1485  mutt_error(_("Could not reopen mailbox"));
1487  goto fatal;
1488  }
1489 
1491  if (need_sort)
1492  {
1493  /* if the mailbox was reopened, the thread tree will be invalid so make
1494  * sure to start threading from scratch. */
1496  }
1497 
1498 fatal:
1499  mutt_buffer_pool_release(&tempfile);
1500  return rc;
1501 }
+ Here is the call graph for this function:

◆ mbox_mbox_close()

static enum MxStatus mbox_mbox_close ( struct Mailbox m)
static

Close a Mailbox - Implements MxOps::mbox_close()

Definition at line 1506 of file mbox.c.

1507 {
1508  struct MboxAccountData *adata = mbox_adata_get(m);
1509  if (!adata)
1510  return MX_STATUS_ERROR;
1511 
1512  if (!adata->fp)
1513  return MX_STATUS_OK;
1514 
1515  if (adata->append)
1516  {
1517  mutt_file_unlock(fileno(adata->fp));
1518  mutt_sig_unblock();
1519  }
1520 
1521  mutt_file_fclose(&adata->fp);
1522 
1523  /* fix up the times so mailbox won't get confused */
1524  if (m->peekonly && !mutt_buffer_is_empty(&m->pathbuf) &&
1525  (mutt_file_timespec_compare(&m->mtime, &adata->atime) > 0))
1526  {
1527 #ifdef HAVE_UTIMENSAT
1528  struct timespec ts[2];
1529  ts[0] = adata->atime;
1530  ts[1] = m->mtime;
1531  utimensat(AT_FDCWD, m->path, ts, 0);
1532 #else
1533  struct utimbuf ut;
1534  ut.actime = adata->atime.tv_sec;
1535  ut.modtime = m->mtime.tv_sec;
1536  utime(mailbox_path(m), &ut);
1537 #endif
1538  }
1539 
1540  return MX_STATUS_OK;
1541 }
+ Here is the call graph for this function:

◆ mbox_msg_open()

static bool mbox_msg_open ( struct Mailbox m,
struct Message msg,
int  msgno 
)
static

Open an email message in a Mailbox - Implements MxOps::msg_open()

Definition at line 1546 of file mbox.c.

1547 {
1548  struct MboxAccountData *adata = mbox_adata_get(m);
1549  if (!adata)
1550  return false;
1551 
1552  msg->fp = mutt_file_fopen(mailbox_path(m), "r");
1553  if (!msg->fp)
1554  return false;
1555 
1556  return true;
1557 }
+ Here is the call graph for this function:

◆ mbox_msg_open_new()

static bool mbox_msg_open_new ( struct Mailbox m,
struct Message msg,
const struct Email e 
)
static

Open a new message in a Mailbox - Implements MxOps::msg_open_new()

Definition at line 1562 of file mbox.c.

1563 {
1564  struct MboxAccountData *adata = mbox_adata_get(m);
1565  if (!adata)
1566  return false;
1567 
1568  msg->fp = adata->fp;
1569  return true;
1570 }
+ Here is the call graph for this function:

◆ mbox_msg_commit()

static int mbox_msg_commit ( struct Mailbox m,
struct Message msg 
)
static

Save changes to an email - Implements MxOps::msg_commit()

Definition at line 1575 of file mbox.c.

1576 {
1577  if (fputc('\n', msg->fp) == EOF)
1578  return -1;
1579 
1580  if ((fflush(msg->fp) == EOF) || (fsync(fileno(msg->fp)) == -1))
1581  {
1582  mutt_perror(_("Can't write message"));
1583  return -1;
1584  }
1585 
1586  return 0;
1587 }

◆ mbox_msg_close()

static int mbox_msg_close ( struct Mailbox m,
struct Message msg 
)
static

Close an email - Implements MxOps::msg_close()

Definition at line 1592 of file mbox.c.

1593 {
1594  if (msg->write)
1595  msg->fp = NULL;
1596  else
1597  mutt_file_fclose(&msg->fp);
1598 
1599  return 0;
1600 }
+ Here is the call graph for this function:

◆ mbox_msg_padding_size()

static int mbox_msg_padding_size ( struct Mailbox m)
static

Bytes of padding between messages - Implements MxOps::msg_padding_size()

Parameters
mMailbox
Return values
1Always

Definition at line 1607 of file mbox.c.

1608 {
1609  return 1;
1610 }

◆ mbox_path_probe()

enum MailboxType mbox_path_probe ( const char *  path,
const struct stat *  st 
)

Is this an mbox Mailbox? - Implements MxOps::path_probe()

Definition at line 1615 of file mbox.c.

1616 {
1617  if (!st)
1618  return MUTT_UNKNOWN;
1619 
1620  if (S_ISDIR(st->st_mode))
1621  return MUTT_UNKNOWN;
1622 
1623  if (st->st_size == 0)
1624  return MUTT_MBOX;
1625 
1626  FILE *fp = fopen(path, "r");
1627  if (!fp)
1628  return MUTT_UNKNOWN;
1629 
1630  int ch;
1631  while ((ch = fgetc(fp)) != EOF)
1632  {
1633  /* Some mailbox creation tools erroneously append a blank line to
1634  * a file before appending a mail message. This allows neomutt to
1635  * detect type for and thus open those files. */
1636  if ((ch != '\n') && (ch != '\r'))
1637  {
1638  ungetc(ch, fp);
1639  break;
1640  }
1641  }
1642 
1643  enum MailboxType type = MUTT_UNKNOWN;
1644  char tmp[256];
1645  if (fgets(tmp, sizeof(tmp), fp))
1646  {
1647  if (mutt_str_startswith(tmp, "From "))
1648  type = MUTT_MBOX;
1649  else if (mutt_str_equal(tmp, MMDF_SEP))
1650  type = MUTT_MMDF;
1651  }
1652  mutt_file_fclose(&fp);
1653 
1654  if (!C_CheckMboxSize)
1655  {
1656  /* need to restore the times here, the file was not really accessed,
1657  * only the type was accessed. This is important, because detection
1658  * of "new mail" depends on those times set correctly. */
1659 #ifdef HAVE_UTIMENSAT
1660  struct timespec ts[2];
1663  utimensat(AT_FDCWD, path, ts, 0);
1664 #else
1665  struct utimbuf times;
1666  times.actime = st->st_atime;
1667  times.modtime = st->st_mtime;
1668  utime(path, &times);
1669 #endif
1670  }
1671 
1672  return type;
1673 }
+ Here is the call graph for this function:

◆ mbox_path_canon()

static int mbox_path_canon ( char *  buf,
size_t  buflen 
)
static

Canonicalise a Mailbox path - Implements MxOps::path_canon()

Definition at line 1678 of file mbox.c.

1679 {
1680  mutt_path_canon(buf, buflen, HomeDir, false);
1681  return 0;
1682 }
+ Here is the call graph for this function:

◆ mbox_path_pretty()

static int mbox_path_pretty ( char *  buf,
size_t  buflen,
const char *  folder 
)
static

Abbreviate a Mailbox path - Implements MxOps::path_pretty()

Definition at line 1687 of file mbox.c.

1688 {
1689  if (mutt_path_abbr_folder(buf, buflen, folder))
1690  return 0;
1691 
1692  if (mutt_path_pretty(buf, buflen, HomeDir, false))
1693  return 0;
1694 
1695  return -1;
1696 }
+ Here is the call graph for this function:

◆ mbox_path_parent()

static int mbox_path_parent ( char *  buf,
size_t  buflen 
)
static

Find the parent of a Mailbox path - Implements MxOps::path_parent()

Definition at line 1701 of file mbox.c.

1702 {
1703  if (mutt_path_parent(buf, buflen))
1704  return 0;
1705 
1706  if (buf[0] == '~')
1707  mutt_path_canon(buf, buflen, HomeDir, false);
1708 
1709  if (mutt_path_parent(buf, buflen))
1710  return 0;
1711 
1712  return -1;
1713 }
+ Here is the call graph for this function:

◆ mbox_path_is_empty()

static int mbox_path_is_empty ( const char *  path)
static

Is the mailbox empty - Implements MxOps::path_is_empty()

Definition at line 1718 of file mbox.c.

1719 {
1720  return mutt_file_check_empty(path);
1721 }
+ Here is the call graph for this function:

◆ mmdf_msg_commit()

static int mmdf_msg_commit ( struct Mailbox m,
struct Message msg 
)
static

Save changes to an email - Implements MxOps::msg_commit()

Definition at line 1726 of file mbox.c.

1727 {
1728  if (fputs(MMDF_SEP, msg->fp) == EOF)
1729  return -1;
1730 
1731  if ((fflush(msg->fp) == EOF) || (fsync(fileno(msg->fp)) == -1))
1732  {
1733  mutt_perror(_("Can't write message"));
1734  return -1;
1735  }
1736 
1737  return 0;
1738 }

◆ mmdf_msg_padding_size()

static int mmdf_msg_padding_size ( struct Mailbox m)
static

Bytes of padding between messages - Implements MxOps::msg_padding_size()

Parameters
mMailbox
Return values
10Always

Definition at line 1745 of file mbox.c.

1746 {
1747  return 10;
1748 }

◆ mbox_mbox_check_stats()

static enum MxStatus mbox_mbox_check_stats ( struct Mailbox m,
uint8_t  flags 
)
static

Check the Mailbox statistics - Implements MxOps::mbox_check_stats()

Definition at line 1753 of file mbox.c.

1754 {
1755  struct stat sb = { 0 };
1756  if (stat(mailbox_path(m), &sb) != 0)
1757  return MX_STATUS_ERROR;
1758 
1759  bool new_or_changed;
1760 
1761  if (C_CheckMboxSize)
1762  new_or_changed = (sb.st_size > m->size);
1763  else
1764  {
1765  new_or_changed =
1767  (m->newly_created &&
1770  }
1771 
1772  if (new_or_changed)
1773  {
1774  if (!C_MailCheckRecent ||
1776  {
1777  m->has_new = true;
1778  }
1779  }
1780  else if (C_CheckMboxSize)
1781  {
1782  /* some other program has deleted mail from the folder */
1783  m->size = (off_t) sb.st_size;
1784  }
1785 
1786  if (m->newly_created && ((sb.st_ctime != sb.st_mtime) || (sb.st_ctime != sb.st_atime)))
1787  m->newly_created = false;
1788 
1789  if ((flags != 0) && mutt_file_stat_timespec_compare(&sb, MUTT_STAT_MTIME,
1790  &m->stats_last_checked) > 0)
1791  {
1792  bool old_peek = m->peekonly;
1793  struct Context *ctx = mx_mbox_open(m, MUTT_QUIET | MUTT_NOSORT | MUTT_PEEK);
1794  mx_mbox_close(&ctx);
1795  m->peekonly = old_peek;
1796  }
1797 
1798  if (m->has_new || m->msg_new)
1799  return MX_STATUS_NEW_MAIL;
1800  return MX_STATUS_OK;
1801 }
+ Here is the call graph for this function:

Variable Documentation

◆ MxMboxOps

struct MxOps MxMboxOps
Initial value:
= {
.type = MUTT_MBOX,
.name = "mbox",
.is_local = true,
.ac_owns_path = mbox_ac_owns_path,
.ac_add = mbox_ac_add,
.mbox_open = mbox_mbox_open,
.mbox_open_append = mbox_mbox_open_append,
.mbox_check = mbox_mbox_check,
.mbox_check_stats = mbox_mbox_check_stats,
.mbox_sync = mbox_mbox_sync,
.mbox_close = mbox_mbox_close,
.msg_open = mbox_msg_open,
.msg_open_new = mbox_msg_open_new,
.msg_commit = mbox_msg_commit,
.msg_close = mbox_msg_close,
.msg_padding_size = mbox_msg_padding_size,
.msg_save_hcache = NULL,
.tags_edit = NULL,
.tags_commit = NULL,
.path_probe = mbox_path_probe,
.path_canon = mbox_path_canon,
.path_pretty = mbox_path_pretty,
.path_parent = mbox_path_parent,
.path_is_empty = mbox_path_is_empty,
}

Mbox Mailbox - Implements MxOps.

Definition at line 1807 of file mbox.c.

◆ MxMmdfOps

struct MxOps MxMmdfOps
Initial value:
= {
.type = MUTT_MMDF,
.name = "mmdf",
.is_local = true,
.ac_owns_path = mbox_ac_owns_path,
.ac_add = mbox_ac_add,
.mbox_open = mbox_mbox_open,
.mbox_open_append = mbox_mbox_open_append,
.mbox_check = mbox_mbox_check,
.mbox_check_stats = mbox_mbox_check_stats,
.mbox_sync = mbox_mbox_sync,
.mbox_close = mbox_mbox_close,
.msg_open = mbox_msg_open,
.msg_open_new = mbox_msg_open_new,
.msg_commit = mmdf_msg_commit,
.msg_close = mbox_msg_close,
.msg_padding_size = mmdf_msg_padding_size,
.msg_save_hcache = NULL,
.tags_edit = NULL,
.tags_commit = NULL,
.path_probe = mbox_path_probe,
.path_canon = mbox_path_canon,
.path_pretty = mbox_path_pretty,
.path_parent = mbox_path_parent,
.path_is_empty = mbox_path_is_empty,
}

MMDF Mailbox - Implements MxOps.

Definition at line 1837 of file mbox.c.

Body::hdr_offset
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
Envelope
The header of an Email.
Definition: envelope.h:54
Mailbox::subj_hash
struct HashTable * subj_hash
Hash Table by subject.
Definition: mailbox.h:128
MX_STATUS_LOCKED
@ MX_STATUS_LOCKED
Couldn't lock the Mailbox.
Definition: mx.h:76
CH_FROM
#define CH_FROM
Retain the "From " message separator?
Definition: copy.h:55
MUTT_PEEK
#define MUTT_PEEK
Revert atime back after taking a look (if applicable)
Definition: mx.h:59
mutt_file_lock
int mutt_file_lock(int fd, bool excl, bool timeout)
(try to) lock a file using fcntl()
Definition: file.c:1175
mbox_open_readwrite
static FILE * mbox_open_readwrite(struct Mailbox *m)
Open an mbox read-write.
Definition: mbox.c:888
mbox_adata_get
static struct MboxAccountData * mbox_adata_get(struct Mailbox *m)
Get the private data associated with a Mailbox.
Definition: mbox.c:100
SigInt
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: mutt_globals.h:74
mbox_msg_open
static bool mbox_msg_open(struct Mailbox *m, struct Message *msg, int msgno)
Open an email message in a Mailbox - Implements MxOps::msg_open()
Definition: mbox.c:1546
MUTT_FLAG
@ MUTT_FLAG
Flagged messages.
Definition: mutt.h:102
MUTT_MMDF
@ MUTT_MMDF
'mmdf' Mailbox type
Definition: mailbox.h:49
MxStatus
MxStatus
Return values from mx_mbox_check(), mx_mbox_sync(), and mx_mbox_close()
Definition: mx.h:71
mbox_reset_atime
void mbox_reset_atime(struct Mailbox *m, struct stat *st)
Reset the access time on the mailbox file.
Definition: mbox.c:833
MailboxNode
List of Mailboxes.
Definition: mailbox.h:152
mutt_mem_calloc
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
_
#define _(a)
Definition: message.h:28
NONULL
#define NONULL(x)
Definition: string2.h:37
Mailbox
A mailbox.
Definition: mailbox.h:81
Email::lines
int lines
How many lines in the body of this message?
Definition: email.h:85
mbox_msg_open_new
static bool mbox_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: mbox.c:1562
Mailbox::v2r
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:101
Mailbox::emails
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
NT_MAILBOX_INVALID
@ NT_MAILBOX_INVALID
Email list was changed.
Definition: mailbox.h:173
Buffer
String manipulation buffer.
Definition: buffer.h:33
mutt_path_abbr_folder
bool mutt_path_abbr_folder(char *buf, size_t buflen, const char *folder)
Create a folder abbreviation.
Definition: path.c:492
Account::type
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
Body::offset
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
mmdf_msg_commit
static int mmdf_msg_commit(struct Mailbox *m, struct Message *msg)
Save changes to an email - Implements MxOps::msg_commit()
Definition: mbox.c:1726
Mailbox::msg_deleted
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
MUpdate::valid
bool valid
Definition: mbox.c:65
mutt_sig_unblock
void mutt_sig_unblock(void)
Restore previously blocked signals.
Definition: signal.c:168
mutt_file_fclose
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
mutt_buffer_pretty_mailbox
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:599
mutt_buffer_is_empty
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
mbox_lock_mailbox
static int mbox_lock_mailbox(struct Mailbox *m, bool excl, bool retry)
Lock a mailbox.
Definition: mbox.c:140
mutt_sig_block
void mutt_sig_block(void)
Block signals during critical operations.
Definition: signal.c:150
mbox_msg_close
static int mbox_msg_close(struct Mailbox *m, struct Message *msg)
Close an email - Implements MxOps::msg_close()
Definition: mbox.c:1592
MUTT_STAT_MTIME
@ MUTT_STAT_MTIME
File/dir's mtime - last modified time.
Definition: file.h:64
mbox_has_new
static bool mbox_has_new(struct Mailbox *m)
Does the mailbox have new mail.
Definition: mbox.c:711
MxOpenReturns
MxOpenReturns
Return values for mbox_open()
Definition: mx.h:84
MUTT_PROGRESS_WRITE
@ MUTT_PROGRESS_WRITE
Progress tracks elements, according to $write_inc
Definition: progress.h:43
mutt_buffer_mktemp
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
TAILQ_EMPTY
#define TAILQ_EMPTY(head)
Definition: queue.h:714
Email::offset
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:84
MUTT_STAT_ATIME
@ MUTT_STAT_ATIME
File/dir's atime - last accessed time.
Definition: file.h:63
SortType
SortType
Methods for sorting.
Definition: sort2.h:43
mbox_open_readonly
static FILE * mbox_open_readonly(struct Mailbox *m)
Open an mbox read-only.
Definition: mbox.c:903
init_mailbox
static int init_mailbox(struct Mailbox *m)
Add Mbox data to the Mailbox.
Definition: mbox.c:118
MUTT_NEWFOLDER
#define MUTT_NEWFOLDER
Create a new folder - same as MUTT_APPEND,.
Definition: mx.h:56
Context
The "current" mailbox.
Definition: context.h:38
mutt_file_fopen
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
LL_DEBUG1
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
Mailbox::size
off_t size
Size of the Mailbox.
Definition: mailbox.h:87
Mailbox::has_new
bool has_new
Mailbox has new mail.
Definition: mailbox.h:88
FREE
#define FREE(x)
Definition: memory.h:40
STAILQ_FIRST
#define STAILQ_FIRST(head)
Definition: queue.h:347
mutt_perror
#define mutt_perror(...)
Definition: logging.h:85
mutt_addrlist_parse
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
MX_OPEN_OK
@ MX_OPEN_OK
Open succeeded.
Definition: mx.h:86
C_CheckMboxSize
bool C_CheckMboxSize
Config: (mbox,mmdf) Use mailbox size as an indicator of new mail.
Definition: config.c:36
mutt_path_canon
bool mutt_path_canon(char *buf, size_t buflen, const char *homedir, bool is_dir)
Create the canonical version of a path.
Definition: path.c:285
PATH_MAX
#define PATH_MAX
Definition: mutt.h:44
MailboxNode::mailbox
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:154
mutt_buffer_pool_release
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
mbox_path_canon
static int mbox_path_canon(char *buf, size_t buflen)
Canonicalise a Mailbox path - Implements MxOps::path_canon()
Definition: mbox.c:1678
Username
WHERE char * Username
User's login name.
Definition: mutt_globals.h:52
mx_path_probe
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1335
email_new
struct Email * email_new(void)
Create a new Email.
Definition: email.c:72
mutt_body_free
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
MUTT_STAT_CTIME
@ MUTT_STAT_CTIME
File/dir's ctime - creation time.
Definition: file.h:65
Mailbox::label_hash
struct HashTable * label_hash
Hash Table for x-labels.
Definition: mailbox.h:129
Mailbox::vcount
int vcount
The number of virtual messages.
Definition: mailbox.h:102
MX_STATUS_REOPENED
@ MX_STATUS_REOPENED
Mailbox was reopened.
Definition: mx.h:77
Account::adata_free
void(* adata_free)(void **ptr)
Free the private data attached to the Account.
Definition: account.h:49
MUTT_READ
@ MUTT_READ
Messages that have been read.
Definition: mutt.h:96
mutt_str_equal
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
MX_STATUS_NEW_MAIL
@ MX_STATUS_NEW_MAIL
New mail received in Mailbox.
Definition: mx.h:75
mmdf_msg_padding_size
static int mmdf_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Implements MxOps::msg_padding_size()
Definition: mbox.c:1745
MUpdate::lines
long lines
Definition: mbox.c:68
mutt_file_touch_atime
void mutt_file_touch_atime(int fd)
Set the access time to current time.
Definition: file.c:1026
Email::old
bool old
Email is seen, but unread.
Definition: email.h:50
Email::received
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:83
mutt_progress_init
void mutt_progress_init(struct Progress *progress, const char *msg, enum ProgressType type, size_t size)
Set up a progress bar.
Definition: progress.c:153
MUTT_PURGE
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:100
mbox_mbox_check_stats
static enum MxStatus mbox_mbox_check_stats(struct Mailbox *m, uint8_t flags)
Check the Mailbox statistics - Implements MxOps::mbox_check_stats()
Definition: mbox.c:1753
fseek_last_message
static int fseek_last_message(FILE *fp)
Find the last message in the file.
Definition: mbox.c:730
mx_alloc_memory
void mx_alloc_memory(struct Mailbox *m)
Create storage for the emails.
Definition: mx.c:1230
mbox_path_probe
enum MailboxType mbox_path_probe(const char *path, const struct stat *st)
Is this an mbox Mailbox? - Implements MxOps::path_probe()
Definition: mbox.c:1615
mutt_env_free
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
mutt_buffer_pool_get
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
timespec::tv_sec
time_t tv_sec
Definition: file.h:51
mutt_file_check_empty
int mutt_file_check_empty(const char *path)
Is the mailbox empty.
Definition: file.c:1412
Mailbox::type
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
NT_MAILBOX_UPDATE
@ NT_MAILBOX_UPDATE
Update internal tables.
Definition: mailbox.h:176
MboxAccountData::fp
FILE * fp
Mailbox file.
Definition: lib.h:52
Mailbox::stats_last_checked
struct timespec stats_last_checked
Mtime of mailbox the last time stats where checked.
Definition: mailbox.h:109
Account
A group of associated Mailboxes.
Definition: account.h:36
mutt_file_copy_stream
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
Message::write
bool write
nonzero if message is open for writing
Definition: mx.h:99
MUpdate::length
LOFF_T length
Definition: mbox.c:69
mutt_file_unlock
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1223
mx_mbox_close
enum MxStatus mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:632
Progress
A progress bar.
Definition: progress.h:50
Body::length
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
Mailbox::changed
bool changed
Mailbox has been modified.
Definition: mailbox.h:114
mbox_adata_new
static struct MboxAccountData * mbox_adata_new(void)
Create a new MboxAccountData struct.
Definition: mbox.c:90
Mailbox::account
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:131
Account::mailboxes
struct MailboxList mailboxes
List of Mailboxes.
Definition: account.h:41
is_from
bool is_from(const char *s, char *path, size_t pathlen, time_t *tp)
Is a string a 'From' header line?
Definition: from.c:48
Mailbox::msg_count
int msg_count
Total number of messages.
Definition: mailbox.h:91
mbox_unlock_mailbox
static void mbox_unlock_mailbox(struct Mailbox *m)
Unlock a mailbox.
Definition: mbox.c:162
Mailbox::mtime
struct timespec mtime
Time Mailbox was last changed.
Definition: mailbox.h:107
MUTT_UNKNOWN
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition: mailbox.h:47
mutt_date_local_tz
time_t mutt_date_local_tz(time_t t)
Calculate the local timezone in seconds east of UTC.
Definition: date.c:206
MboxAccountData
Mbox-specific Account data -.
Definition: lib.h:50
Mailbox::newly_created
bool newly_created
Mbox or mmdf just popped into existence.
Definition: mailbox.h:106
MUTT_NOSORT
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition: mx.h:52
MboxAccountData::locked
bool locked
is the mailbox locked?
Definition: lib.h:55
Body::parts
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
MUTT_PROGRESS_READ
@ MUTT_PROGRESS_READ
Progress tracks elements, according to $read_inc
Definition: progress.h:42
Email::env
struct Envelope * env
Envelope information.
Definition: email.h:90
mutt_debug
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Mailbox::email_max
int email_max
Number of pointers in emails.
Definition: mailbox.h:100
MUTT_REPLIED
@ MUTT_REPLIED
Messages that have been replied to.
Definition: mutt.h:95
mailbox_update
void mailbox_update(struct Mailbox *m)
Get the mailbox's current size.
Definition: mailbox.c:168
C_Tmpdir
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:56
CH_UPDATE
#define CH_UPDATE
Update the status and x-status fields?
Definition: copy.h:51
mbox_ac_owns_path
static bool mbox_ac_owns_path(struct Account *a, const char *path)
Check whether an Account owns a Mailbox path - Implements MxOps::ac_owns_path()
Definition: mbox.c:861
Mailbox::msg_flagged
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:93
Message::fp
FILE * fp
pointer to the message data
Definition: mx.h:96
MX_STATUS_ERROR
@ MX_STATUS_ERROR
An error occurred.
Definition: mx.h:73
MUTT_QUIET
#define MUTT_QUIET
Do not print any messages.
Definition: mx.h:55
mutt_buffer_string
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Mailbox::verbose
bool verbose
Display status messages?
Definition: mailbox.h:118
mbox_path_pretty
static int mbox_path_pretty(char *buf, size_t buflen, const char *folder)
Abbreviate a Mailbox path - Implements MxOps::path_pretty()
Definition: mbox.c:1687
SORT_ORDER
@ SORT_ORDER
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:50
mutt_file_stat_compare
int mutt_file_stat_compare(struct stat *sba, enum MuttStatType sba_type, struct stat *sbb, enum MuttStatType sbb_type)
Compare two stat infos.
Definition: file.c:1599
MUTT_OLD
@ MUTT_OLD
Old messages.
Definition: mutt.h:94
mbox_ac_add
static bool mbox_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Implements MxOps::ac_add()
Definition: mbox.c:876
mbox_mbox_check
static enum MxStatus mbox_mbox_check(struct Mailbox *m)
Check for new mail - Implements MxOps::mbox_check()
Definition: mbox.c:1012
Email::deleted
bool deleted
Email is deleted.
Definition: email.h:45
mutt_file_mkdir
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:875
Mailbox::readonly
bool readonly
Don't allow changes to the mailbox.
Definition: mailbox.h:119
MUpdate::hdr
LOFF_T hdr
Definition: mbox.c:66
mmdf_parse_mailbox
static enum MxOpenReturns mmdf_parse_mailbox(struct Mailbox *m)
Read a mailbox in MMDF format.
Definition: mbox.c:182
Envelope::from
struct AddressList from
Email's 'From' list.
Definition: envelope.h:57
mutt_path_parent
bool mutt_path_parent(char *buf, size_t buflen)
Find the parent of a path.
Definition: path.c:459
MUTT_DELETE
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:98
HomeDir
char * HomeDir
User's home directory.
Definition: mutt_globals.h:49
C_MailCheckRecent
WHERE bool C_MailCheckRecent
Config: Notify the user about new mail since the last time the mailbox was opened.
Definition: mutt_globals.h:150
C_Sort
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:60
Progress::msg
char msg[1024]
Definition: progress.h:52
MMDF_SEP
#define MMDF_SEP
Definition: lib.h:64
ShortHostname
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:50
mutt_file_timespec_compare
int mutt_file_timespec_compare(struct timespec *a, struct timespec *b)
Compare to time values.
Definition: file.c:1515
Mailbox::last_visited
struct timespec last_visited
Time of last exit from this mailbox.
Definition: mailbox.h:108
MUTT_TAG
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:103
mbox_path_parent
static int mbox_path_parent(char *buf, size_t buflen)
Find the parent of a Mailbox path - Implements MxOps::path_parent()
Definition: mbox.c:1701
mbox_parse_mailbox
static enum MxOpenReturns mbox_parse_mailbox(struct Mailbox *m)
Read a mailbox from disk.
Definition: mbox.c:344
mbox_mbox_open
static enum MxOpenReturns mbox_mbox_open(struct Mailbox *m)
Open a Mailbox - Implements MxOps::mbox_open()
Definition: mbox.c:914
mx_mbox_open
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:309
mbox_mbox_close
static enum MxStatus mbox_mbox_close(struct Mailbox *m)
Close a Mailbox - Implements MxOps::mbox_close()
Definition: mbox.c:1506
MUTT_CM_UPDATE
#define MUTT_CM_UPDATE
Update structs on sync.
Definition: copy.h:39
mailbox_changed
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:186
mbox_mbox_sync
static enum MxStatus mbox_mbox_sync(struct Mailbox *m)
Save changes to the Mailbox - Implements MxOps::mbox_sync()
Definition: mbox.c:1135
mutt_file_get_stat_timespec
void mutt_file_get_stat_timespec(struct timespec *dest, struct stat *sb, enum MuttStatType type)
Read the stat() time into a time value.
Definition: file.c:1537
mbox_adata_free
static void mbox_adata_free(void **ptr)
Free the private Account data - Implements Account::adata_free()
Definition: mbox.c:75
Account::adata
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
MX_OPEN_ABORT
@ MX_OPEN_ABORT
Open was aborted.
Definition: mx.h:88
MailboxType
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
MUpdate
Store of new offsets, used by mutt_sync_mailbox()
Definition: mbox.c:63
mbox_mbox_open_append
static bool mbox_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a Mailbox for appending - Implements MxOps::mbox_open_append()
Definition: mbox.c:963
Email::index
int index
The absolute (unsorted) message number.
Definition: email.h:86
mutt_rfc822_read_header
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:1112
email_cmp_strict
bool email_cmp_strict(const struct Email *e1, const struct Email *e2)
Strictly compare message emails.
Definition: email.c:92
email_free
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:43
mutt_progress_update
void mutt_progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:212
Mailbox::msg_unread
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
Progress::size
size_t size
Definition: progress.h:55
Mailbox::msg_tagged
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:97
mbox_path_is_empty
static int mbox_path_is_empty(const char *path)
Is the mailbox empty - Implements MxOps::path_is_empty()
Definition: mbox.c:1718
Envelope::return_path
struct AddressList return_path
Return path for the Email.
Definition: envelope.h:56
MboxAccountData::atime
struct timespec atime
File's last-access time.
Definition: lib.h:53
Email::attach_del
bool attach_del
Has an attachment marked for deletion.
Definition: email.h:49
mailbox_path
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:206
MUpdate::body
LOFF_T body
Definition: mbox.c:67
mx_fastclose_mailbox
void mx_fastclose_mailbox(struct Mailbox *m)
free up memory associated with the Mailbox
Definition: mx.c:451
mutt_path_pretty
bool mutt_path_pretty(char *buf, size_t buflen, const char *homedir, bool is_dir)
Tidy a filesystem path.
Definition: path.c:186
timespec
Time value with nanosecond precision.
Definition: file.h:49
mbox_msg_padding_size
static int mbox_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Implements MxOps::msg_padding_size()
Definition: mbox.c:1607
test_last_status_new
static bool test_last_status_new(FILE *fp)
Is the last message new.
Definition: mbox.c:781
mbox_msg_commit
static int mbox_msg_commit(struct Mailbox *m, struct Message *msg)
Save changes to an email - Implements MxOps::msg_commit()
Definition: mbox.c:1575
reopen_mailbox
static int reopen_mailbox(struct Mailbox *m)
Close and reopen a mailbox.
Definition: mbox.c:533
Email
The envelope/body of an email.
Definition: email.h:37
mutt_str_startswith
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
mutt_message
#define mutt_message(...)
Definition: logging.h:83
mutt_set_flag
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:67
Mailbox::msg_new
int msg_new
Number of new messages.
Definition: mailbox.h:95
MX_OPEN_ERROR
@ MX_OPEN_ERROR
Open failed with an error.
Definition: mx.h:87
mutt_buffer_printf
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
mutt_file_stat_timespec_compare
int mutt_file_stat_timespec_compare(struct stat *sba, enum MuttStatType type, struct timespec *b)
Compare stat info with a time value.
Definition: file.c:1577
mutt_addrlist_copy
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:737
mutt_copy_message
int mutt_copy_message(FILE *fp_out, struct Mailbox *m, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Copy a message from a Mailbox.
Definition: copy.c:835
NT_MAILBOX_RESORT
@ NT_MAILBOX_RESORT
Email list needs resorting.
Definition: mailbox.h:174
CH_UPDATE_LEN
#define CH_UPDATE_LEN
Update Lines: and Content-Length:
Definition: copy.h:61
Email::read
bool read
Email is read.
Definition: email.h:51
MUTT_MBOX
@ MUTT_MBOX
'mbox' Mailbox type
Definition: mailbox.h:48
mutt_make_label_hash
void mutt_make_label_hash(struct Mailbox *m)
Create a Hash Table to store the labels.
Definition: mutt_header.c:368
Mailbox::id_hash
struct HashTable * id_hash
Hash Table by msg id.
Definition: mailbox.h:127
Mailbox::peekonly
bool peekonly
Just taking a glance, revert atime.
Definition: mailbox.h:117
mutt_hash_free
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:447
Mailbox::pathbuf
struct Buffer pathbuf
Definition: mailbox.h:83
Email::changed
bool changed
Email has been edited.
Definition: email.h:48
mailbox_find
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition: mailbox.c:103
MX_STATUS_OK
@ MX_STATUS_OK
No changes.
Definition: mx.h:74
Email::body
struct Body * body
List of MIME parts.
Definition: email.h:91
mutt_error
#define mutt_error(...)
Definition: logging.h:84
mutt_path_dirname
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final '/'.
Definition: path.c:376