NeoMutt  2019-11-11
Teaching an old dog new tricks
DOXYGEN
monitor.c File Reference

Monitor files for changes. More...

#include "config.h"
#include <errno.h>
#include <limits.h>
#include <poll.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mutt/mutt.h"
#include "core/lib.h"
#include "monitor.h"
#include "context.h"
#include "curs_lib.h"
#include "globals.h"
#include <fcntl.h>
+ Include dependency graph for monitor.c:

Go to the source code of this file.

Data Structures

struct  Monitor
 A watch on a file. More...
 
struct  MonitorInfo
 Information about a monitored file. More...
 

Macros

#define INOTIFY_MASK_DIR   (IN_MOVED_TO | IN_ATTRIB | IN_CLOSE_WRITE | IN_ISDIR)
 
#define INOTIFY_MASK_FILE   IN_CLOSE_WRITE
 
#define EVENT_BUFLEN   MAX(4096, sizeof(struct inotify_event) + NAME_MAX + 1)
 

Enumerations

enum  ResolveResult {
  RESOLVE_RES_FAIL_NOMAILBOX = -3, RESOLVE_RES_FAIL_NOMAGIC = -2, RESOLVE_RES_FAIL_STAT = -1, RESOLVE_RES_OK_NOTEXISTING = 0,
  RESOLVE_RES_OK_EXISTING = 1
}
 Results for the Monitor functions. More...
 

Functions

static void mutt_poll_fd_add (int fd, short events)
 Add a file to the watch list. More...
 
static int mutt_poll_fd_remove (int fd)
 Remove a file from the watch list. More...
 
static int monitor_init (void)
 Set up file monitoring. More...
 
static void monitor_check_free (void)
 Close down file monitoring. More...
 
static struct Monitormonitor_new (struct MonitorInfo *info, int descriptor)
 Create a new file monitor. More...
 
static void monitor_info_init (struct MonitorInfo *info)
 Set up a file monitor. More...
 
static void monitor_info_free (struct MonitorInfo *info)
 Shutdown a file monitor. More...
 
static void monitor_delete (struct Monitor *monitor)
 Free a file monitor. More...
 
static int monitor_handle_ignore (int desc)
 Listen for when a backup file is closed. More...
 
static enum ResolveResult monitor_resolve (struct MonitorInfo *info, struct Mailbox *m)
 Get the monitor for a mailbox. More...
 
int mutt_monitor_poll (void)
 Check for filesystem changes. More...
 
int mutt_monitor_add (struct Mailbox *m)
 Add a watch for a mailbox. More...
 
int mutt_monitor_remove (struct Mailbox *m)
 Remove a watch for a mailbox. More...
 

Variables

bool MonitorFilesChanged = false
 true after a monitored file has changed More...
 
bool MonitorContextChanged = false
 true after the current mailbox has changed More...
 
static int INotifyFd = -1
 
static struct MonitorMonitor = NULL
 
static size_t PollFdsCount = 0
 
static size_t PollFdsLen = 0
 
static struct pollfd * PollFds = NULL
 
static int MonitorContextDescriptor = -1
 

Detailed Description

Monitor files for changes.

Authors
  • Gero Treuer

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 monitor.c.

Macro Definition Documentation

◆ INOTIFY_MASK_DIR

#define INOTIFY_MASK_DIR   (IN_MOVED_TO | IN_ATTRIB | IN_CLOSE_WRITE | IN_ISDIR)

Definition at line 61 of file monitor.c.

◆ INOTIFY_MASK_FILE

#define INOTIFY_MASK_FILE   IN_CLOSE_WRITE

Definition at line 62 of file monitor.c.

◆ EVENT_BUFLEN

#define EVENT_BUFLEN   MAX(4096, sizeof(struct inotify_event) + NAME_MAX + 1)

Definition at line 64 of file monitor.c.

Enumeration Type Documentation

◆ ResolveResult

Results for the Monitor functions.

Enumerator
RESOLVE_RES_FAIL_NOMAILBOX 

No Mailbox to work on.

RESOLVE_RES_FAIL_NOMAGIC 

Can't identify Mailbox type.

RESOLVE_RES_FAIL_STAT 

Can't stat() the Mailbox file.

RESOLVE_RES_OK_NOTEXISTING 

File exists, no monitor is attached.

RESOLVE_RES_OK_EXISTING 

File exists, monitor is already attached.

Definition at line 69 of file monitor.c.

70 {
76 };
Can&#39;t identify Mailbox type.
Definition: monitor.c:72
File exists, monitor is already attached.
Definition: monitor.c:75
No Mailbox to work on.
Definition: monitor.c:71
Can&#39;t stat() the Mailbox file.
Definition: monitor.c:73
File exists, no monitor is attached.
Definition: monitor.c:74

Function Documentation

◆ mutt_poll_fd_add()

static void mutt_poll_fd_add ( int  fd,
short  events 
)
static

Add a file to the watch list.

Parameters
fdFile to watch
eventsEvents to listen for, e.g. POLLIN

Definition at line 110 of file monitor.c.

111 {
112  int i = 0;
113  for (; (i < PollFdsCount) && (PollFds[i].fd != fd); i++)
114  ;
115 
116  if (i == PollFdsCount)
117  {
118  if (PollFdsCount == PollFdsLen)
119  {
120  PollFdsLen += 2;
121  mutt_mem_realloc(&PollFds, PollFdsLen * sizeof(struct pollfd));
122  }
123  PollFdsCount++;
124  PollFds[i].fd = fd;
125  PollFds[i].events = events;
126  }
127  else
128  PollFds[i].events |= events;
129 }
static size_t PollFdsLen
Definition: monitor.c:56
static struct pollfd * PollFds
Definition: monitor.c:57
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
static size_t PollFdsCount
Definition: monitor.c:55
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_poll_fd_remove()

static int mutt_poll_fd_remove ( int  fd)
static

Remove a file from the watch list.

Parameters
fdFile to remove
Return values
0Success
-1Error

Definition at line 137 of file monitor.c.

138 {
139  int i = 0;
140  for (; (i < PollFdsCount) && (PollFds[i].fd != fd); i++)
141  ;
142  if (i == PollFdsCount)
143  return -1;
144  int d = PollFdsCount - i - 1;
145  if (d != 0)
146  memmove(&PollFds[i], &PollFds[i + 1], d * sizeof(struct pollfd));
147  PollFdsCount--;
148  return 0;
149 }
static struct pollfd * PollFds
Definition: monitor.c:57
static size_t PollFdsCount
Definition: monitor.c:55
+ Here is the caller graph for this function:

◆ monitor_init()

static int monitor_init ( void  )
static

Set up file monitoring.

Return values
0Success
-1Error

Definition at line 156 of file monitor.c.

157 {
158  if (INotifyFd == -1)
159  {
160 #if HAVE_INOTIFY_INIT1
161  INotifyFd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
162  if (INotifyFd == -1)
163  {
164  mutt_debug(LL_DEBUG2, "inotify_init1 failed, errno=%d %s\n", errno, strerror(errno));
165  return -1;
166  }
167 #else
168  INotifyFd = inotify_init();
169  if (INotifyFd == -1)
170  {
171  mutt_debug(LL_DEBUG2, "monitor: inotify_init failed, errno=%d %s\n",
172  errno, strerror(errno));
173  return -1;
174  }
175  fcntl(INotifyFd, F_SETFL, O_NONBLOCK);
176  fcntl(INotifyFd, F_SETFD, FD_CLOEXEC);
177 #endif
178  mutt_poll_fd_add(0, POLLIN);
179  mutt_poll_fd_add(INotifyFd, POLLIN);
180  }
181  return 0;
182 }
static int INotifyFd
Definition: monitor.c:53
Log at debug level 2.
Definition: logging.h:57
static void mutt_poll_fd_add(int fd, short events)
Add a file to the watch list.
Definition: monitor.c:110
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ monitor_check_free()

static void monitor_check_free ( void  )
static

Close down file monitoring.

Definition at line 187 of file monitor.c.

188 {
189  if (!Monitor && (INotifyFd != -1))
190  {
192  close(INotifyFd);
193  INotifyFd = -1;
194  MonitorFilesChanged = false;
195  }
196 }
A watch on a file.
Definition: monitor.c:81
bool MonitorFilesChanged
true after a monitored file has changed
Definition: monitor.c:50
static int INotifyFd
Definition: monitor.c:53
static int mutt_poll_fd_remove(int fd)
Remove a file from the watch list.
Definition: monitor.c:137
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ monitor_new()

static struct Monitor* monitor_new ( struct MonitorInfo info,
int  descriptor 
)
static

Create a new file monitor.

Parameters
infoDetails of file to monitor
descriptorWatch descriptor
Return values
ptrNewly allocated Monitor

Definition at line 204 of file monitor.c.

205 {
206  struct Monitor *monitor = mutt_mem_calloc(1, sizeof(struct Monitor));
207  monitor->magic = info->magic;
208  monitor->st_dev = info->st_dev;
209  monitor->st_ino = info->st_ino;
210  monitor->desc = descriptor;
211  monitor->next = Monitor;
212  if (info->magic == MUTT_MH)
213  monitor->mh_backup_path = mutt_str_strdup(info->path);
214 
215  Monitor = monitor;
216 
217  return monitor;
218 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
enum MailboxType magic
Definition: monitor.c:96
ino_t st_ino
Definition: monitor.c:86
int desc
Definition: monitor.c:88
A watch on a file.
Definition: monitor.c:81
struct Monitor * next
Definition: monitor.c:83
char * mh_backup_path
Definition: monitor.c:84
enum MailboxType magic
Definition: monitor.c:87
static struct Monitor * Monitor
Definition: monitor.c:54
&#39;MH&#39; Mailbox type
Definition: mailbox.h:49
dev_t st_dev
Definition: monitor.c:85
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
const char * path
Definition: monitor.c:98
dev_t st_dev
Definition: monitor.c:99
ino_t st_ino
Definition: monitor.c:100
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ monitor_info_init()

static void monitor_info_init ( struct MonitorInfo info)
static

Set up a file monitor.

Parameters
infoMonitor to initialise

Definition at line 224 of file monitor.c.

225 {
226  memset(info, 0, sizeof(*info));
227 }
+ Here is the caller graph for this function:

◆ monitor_info_free()

static void monitor_info_free ( struct MonitorInfo info)
static

Shutdown a file monitor.

Parameters
infoMonitor to shut down

Definition at line 233 of file monitor.c.

234 {
236 }
struct Buffer path_buf
Definition: monitor.c:102
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ monitor_delete()

static void monitor_delete ( struct Monitor monitor)
static

Free a file monitor.

Parameters
monitorMonitor to free

Definition at line 242 of file monitor.c.

243 {
244  if (!monitor)
245  return;
246 
247  struct Monitor **ptr = &Monitor;
248 
249  while (true)
250  {
251  if (!*ptr)
252  return;
253  if (*ptr == monitor)
254  break;
255  ptr = &(*ptr)->next;
256  }
257 
258  FREE(&monitor->mh_backup_path);
259  monitor = monitor->next;
260  FREE(ptr);
261  *ptr = monitor;
262 }
A watch on a file.
Definition: monitor.c:81
struct Monitor * next
Definition: monitor.c:83
char * mh_backup_path
Definition: monitor.c:84
static struct Monitor * Monitor
Definition: monitor.c:54
#define FREE(x)
Definition: memory.h:40
+ Here is the caller graph for this function:

◆ monitor_handle_ignore()

static int monitor_handle_ignore ( int  desc)
static

Listen for when a backup file is closed.

Parameters
descWatch descriptor
Return values
>=0New descriptor
-1Error

Definition at line 270 of file monitor.c.

271 {
272  int new_desc = -1;
273  struct Monitor *iter = Monitor;
274  struct stat sb;
275 
276  while (iter && (iter->desc != desc))
277  iter = iter->next;
278 
279  if (iter)
280  {
281  if ((iter->magic == MUTT_MH) && (stat(iter->mh_backup_path, &sb) == 0))
282  {
283  new_desc = inotify_add_watch(INotifyFd, iter->mh_backup_path, INOTIFY_MASK_FILE);
284  if (new_desc == -1)
285  {
286  mutt_debug(LL_DEBUG2, "inotify_add_watch failed for '%s', errno=%d %s\n",
287  iter->mh_backup_path, errno, strerror(errno));
288  }
289  else
290  {
291  mutt_debug(LL_DEBUG3, "inotify_add_watch descriptor=%d for '%s'\n",
292  desc, iter->mh_backup_path);
293  iter->st_dev = sb.st_dev;
294  iter->st_ino = sb.st_ino;
295  iter->desc = new_desc;
296  }
297  }
298  else
299  {
300  mutt_debug(LL_DEBUG3, "cleanup watch (implicitly removed) - descriptor=%d\n", desc);
301  }
302 
303  if (MonitorContextDescriptor == desc)
304  MonitorContextDescriptor = new_desc;
305 
306  if (new_desc == -1)
307  {
308  monitor_delete(iter);
310  }
311  }
312 
313  return new_desc;
314 }
#define INOTIFY_MASK_FILE
Definition: monitor.c:62
ino_t st_ino
Definition: monitor.c:86
int desc
Definition: monitor.c:88
static void monitor_delete(struct Monitor *monitor)
Free a file monitor.
Definition: monitor.c:242
A watch on a file.
Definition: monitor.c:81
struct Monitor * next
Definition: monitor.c:83
static int INotifyFd
Definition: monitor.c:53
Log at debug level 2.
Definition: logging.h:57
char * mh_backup_path
Definition: monitor.c:84
enum MailboxType magic
Definition: monitor.c:87
static struct Monitor * Monitor
Definition: monitor.c:54
&#39;MH&#39; Mailbox type
Definition: mailbox.h:49
dev_t st_dev
Definition: monitor.c:85
static void monitor_check_free(void)
Close down file monitoring.
Definition: monitor.c:187
static int MonitorContextDescriptor
Definition: monitor.c:59
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Log at debug level 3.
Definition: logging.h:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ monitor_resolve()

static enum ResolveResult monitor_resolve ( struct MonitorInfo info,
struct Mailbox m 
)
static

Get the monitor for a mailbox.

Parameters
[out]infoDetails of the mailbox's monitor
[in]mMailbox
Return values
>=0mailbox is valid and locally accessible: 0: no monitor / 1: preexisting monitor
-3no mailbox (MonitorInfo: no fields set)
-2magic not set
-1stat() failed (see errno; MonitorInfo fields: magic, is_dir, path)

If m is NULL, the current mailbox (Context) is used.

Definition at line 328 of file monitor.c.

329 {
330  char *fmt = NULL;
331  struct stat sb;
332 
333  if (m)
334  {
335  info->magic = m->magic;
336  info->path = m->realpath;
337  }
338  else if (Context && Context->mailbox)
339  {
340  info->magic = Context->mailbox->magic;
341  info->path = Context->mailbox->realpath;
342  }
343  else
344  {
346  }
347 
348  if (info->magic == MUTT_UNKNOWN)
349  {
351  }
352  else if (info->magic == MUTT_MAILDIR)
353  {
354  info->is_dir = true;
355  fmt = "%s/new";
356  }
357  else
358  {
359  info->is_dir = false;
360  if (info->magic == MUTT_MH)
361  fmt = "%s/.mh_sequences";
362  }
363  if (fmt)
364  {
365  mutt_buffer_printf(&info->path_buf, fmt, info->path);
366  info->path = mutt_b2s(&info->path_buf);
367  }
368  if (stat(info->path, &sb) != 0)
369  return RESOLVE_RES_FAIL_STAT;
370 
371  struct Monitor *iter = Monitor;
372  while (iter && ((iter->st_ino != sb.st_ino) || (iter->st_dev != sb.st_dev)))
373  iter = iter->next;
374 
375  info->st_dev = sb.st_dev;
376  info->st_ino = sb.st_ino;
377  info->monitor = iter;
378 
380 }
The "current" mailbox.
Definition: context.h:36
Can&#39;t identify Mailbox type.
Definition: monitor.c:72
enum MailboxType magic
Definition: monitor.c:96
ino_t st_ino
Definition: monitor.c:86
struct Buffer path_buf
Definition: monitor.c:102
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:95
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:46
A watch on a file.
Definition: monitor.c:81
struct Monitor * next
Definition: monitor.c:83
File exists, monitor is already attached.
Definition: monitor.c:75
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
bool is_dir
Definition: monitor.c:97
struct Mailbox * mailbox
Definition: context.h:50
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:116
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:50
No Mailbox to work on.
Definition: monitor.c:71
struct Monitor * monitor
Definition: monitor.c:101
#define mutt_b2s(buf)
Definition: buffer.h:41
static struct Monitor * Monitor
Definition: monitor.c:54
&#39;MH&#39; Mailbox type
Definition: mailbox.h:49
dev_t st_dev
Definition: monitor.c:85
Can&#39;t stat() the Mailbox file.
Definition: monitor.c:73
File exists, no monitor is attached.
Definition: monitor.c:74
const char * path
Definition: monitor.c:98
dev_t st_dev
Definition: monitor.c:99
ino_t st_ino
Definition: monitor.c:100
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_monitor_poll()

int mutt_monitor_poll ( void  )

Check for filesystem changes.

Return values
-3unknown/unexpected events: poll timeout / fds not handled by us
-2monitor detected changes, no STDIN input
-1error (see errno)
0(1) input ready from STDIN, or (2) monitoring inactive -> no poll()

Wait for I/O ready file descriptors or signals.

MonitorFilesChanged also reflects changes to monitored files.

Only STDIN and INotify file handles currently expected/supported. More would ask for common infrastructure (sockets?).

Definition at line 396 of file monitor.c.

397 {
398  int rc = 0;
399  char buf[EVENT_BUFLEN] __attribute__((aligned(__alignof__(struct inotify_event))));
400 
401  MonitorFilesChanged = false;
402 
403  if (INotifyFd != -1)
404  {
405  int fds = poll(PollFds, PollFdsLen, MuttGetchTimeout);
406 
407  if (fds == -1)
408  {
409  rc = -1;
410  if (errno != EINTR)
411  {
412  mutt_debug(LL_DEBUG2, "poll() failed, errno=%d %s\n", errno, strerror(errno));
413  }
414  }
415  else
416  {
417  bool input_ready = false;
418  for (int i = 0; fds && (i < PollFdsCount); i++)
419  {
420  if (PollFds[i].revents)
421  {
422  fds--;
423  if (PollFds[i].fd == 0)
424  {
425  input_ready = true;
426  }
427  else if (PollFds[i].fd == INotifyFd)
428  {
429  MonitorFilesChanged = true;
430  mutt_debug(LL_DEBUG3, "file change(s) detected\n");
431  char *ptr = buf;
432  const struct inotify_event *event = NULL;
433 
434  while (true)
435  {
436  int len = read(INotifyFd, buf, sizeof(buf));
437  if (len == -1)
438  {
439  if (errno != EAGAIN)
440  mutt_debug(LL_DEBUG2, "read inotify events failed, errno=%d %s\n",
441  errno, strerror(errno));
442  break;
443  }
444 
445  while (ptr < (buf + len))
446  {
447  event = (const struct inotify_event *) ptr;
448  mutt_debug(LL_DEBUG3, "+ detail: descriptor=%d mask=0x%x\n",
449  event->wd, event->mask);
450  if (event->mask & IN_IGNORED)
451  monitor_handle_ignore(event->wd);
452  else if (event->wd == MonitorContextDescriptor)
453  MonitorContextChanged = true;
454  ptr += sizeof(struct inotify_event) + event->len;
455  }
456  }
457  }
458  }
459  }
460  if (!input_ready)
461  rc = MonitorFilesChanged ? -2 : -3;
462  }
463  }
464 
465  return rc;
466 }
#define EVENT_BUFLEN
Definition: monitor.c:64
static size_t PollFdsLen
Definition: monitor.c:56
static struct pollfd * PollFds
Definition: monitor.c:57
bool MonitorFilesChanged
true after a monitored file has changed
Definition: monitor.c:50
static int INotifyFd
Definition: monitor.c:53
Log at debug level 2.
Definition: logging.h:57
bool MonitorContextChanged
true after the current mailbox has changed
Definition: monitor.c:51
static int MonitorContextDescriptor
Definition: monitor.c:59
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
static size_t PollFdsCount
Definition: monitor.c:55
Log at debug level 3.
Definition: logging.h:58
int MuttGetchTimeout
Timeout in ms for mutt_getch()
Definition: curs_lib.c:90
static int monitor_handle_ignore(int desc)
Listen for when a backup file is closed.
Definition: monitor.c:270
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_monitor_add()

int mutt_monitor_add ( struct Mailbox m)

Add a watch for a mailbox.

Parameters
mMailbox to watch
Return values
0success: new or already existing monitor
-1failed: no mailbox, inaccessible file, create monitor/watcher failed

If mailbox is NULL, the current mailbox (Context) is used.

Definition at line 476 of file monitor.c.

477 {
478  struct MonitorInfo info;
479  monitor_info_init(&info);
480 
481  int rc = 0;
482  enum ResolveResult desc = monitor_resolve(&info, m);
483  if (desc != RESOLVE_RES_OK_NOTEXISTING)
484  {
485  if (!m && (desc == RESOLVE_RES_OK_EXISTING))
486  MonitorContextDescriptor = info.monitor->desc;
487  rc = (desc == RESOLVE_RES_OK_EXISTING) ? 0 : -1;
488  goto cleanup;
489  }
490 
491  uint32_t mask = info.is_dir ? INOTIFY_MASK_DIR : INOTIFY_MASK_FILE;
492  if (((INotifyFd == -1) && (monitor_init() == -1)) ||
493  ((desc = inotify_add_watch(INotifyFd, info.path, mask)) == -1))
494  {
495  mutt_debug(LL_DEBUG2, "inotify_add_watch failed for '%s', errno=%d %s\n",
496  info.path, errno, strerror(errno));
497  rc = -1;
498  goto cleanup;
499  }
500 
501  mutt_debug(LL_DEBUG3, "inotify_add_watch descriptor=%d for '%s'\n", desc, info.path);
502  if (!m)
504 
505  monitor_new(&info, desc);
506 
507 cleanup:
508  monitor_info_free(&info);
509  return rc;
510 }
#define INOTIFY_MASK_FILE
Definition: monitor.c:62
Information about a monitored file.
Definition: monitor.c:94
File exists, monitor is already attached.
Definition: monitor.c:75
static int monitor_init(void)
Set up file monitoring.
Definition: monitor.c:156
static int INotifyFd
Definition: monitor.c:53
Log at debug level 2.
Definition: logging.h:57
ResolveResult
Results for the Monitor functions.
Definition: monitor.c:69
#define INOTIFY_MASK_DIR
Definition: monitor.c:61
File exists, no monitor is attached.
Definition: monitor.c:74
static void monitor_info_init(struct MonitorInfo *info)
Set up a file monitor.
Definition: monitor.c:224
static int MonitorContextDescriptor
Definition: monitor.c:59
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
static struct Monitor * monitor_new(struct MonitorInfo *info, int descriptor)
Create a new file monitor.
Definition: monitor.c:204
static enum ResolveResult monitor_resolve(struct MonitorInfo *info, struct Mailbox *m)
Get the monitor for a mailbox.
Definition: monitor.c:328
static void monitor_info_free(struct MonitorInfo *info)
Shutdown a file monitor.
Definition: monitor.c:233
Log at debug level 3.
Definition: logging.h:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_monitor_remove()

int mutt_monitor_remove ( struct Mailbox m)

Remove a watch for a mailbox.

Parameters
mMailbox
Return values
0monitor removed (not shared)
1monitor not removed (shared)
2no monitor

If mailbox is NULL, the current mailbox (Context) is used.

Definition at line 521 of file monitor.c.

522 {
523  struct MonitorInfo info, info2;
524  int rc = 0;
525 
526  monitor_info_init(&info);
527  monitor_info_init(&info2);
528 
529  if (!m)
530  {
532  MonitorContextChanged = false;
533  }
534 
535  if (monitor_resolve(&info, m) != RESOLVE_RES_OK_EXISTING)
536  {
537  rc = 2;
538  goto cleanup;
539  }
540 
541  if (Context && Context->mailbox)
542  {
543  if (m)
544  {
545  if ((monitor_resolve(&info2, NULL) == RESOLVE_RES_OK_EXISTING) &&
546  (info.st_ino == info2.st_ino) && (info.st_dev == info2.st_dev))
547  {
548  rc = 1;
549  goto cleanup;
550  }
551  }
552  else
553  {
555  {
556  rc = 1;
557  goto cleanup;
558  }
559  }
560  }
561 
562  inotify_rm_watch(info.monitor->desc, INotifyFd);
563  mutt_debug(LL_DEBUG3, "inotify_rm_watch for '%s' descriptor=%d\n", info.path,
564  info.monitor->desc);
565 
566  monitor_delete(info.monitor);
568 
569 cleanup:
570  monitor_info_free(&info);
571  monitor_info_free(&info2);
572  return rc;
573 }
The "current" mailbox.
Definition: context.h:36
Information about a monitored file.
Definition: monitor.c:94
static void monitor_delete(struct Monitor *monitor)
Free a file monitor.
Definition: monitor.c:242
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition: mailbox.c:79
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:95
File exists, monitor is already attached.
Definition: monitor.c:75
static int INotifyFd
Definition: monitor.c:53
struct Mailbox * mailbox
Definition: context.h:50
static void monitor_info_init(struct MonitorInfo *info)
Set up a file monitor.
Definition: monitor.c:224
bool MonitorContextChanged
true after the current mailbox has changed
Definition: monitor.c:51
static void monitor_check_free(void)
Close down file monitoring.
Definition: monitor.c:187
static int MonitorContextDescriptor
Definition: monitor.c:59
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
static enum ResolveResult monitor_resolve(struct MonitorInfo *info, struct Mailbox *m)
Get the monitor for a mailbox.
Definition: monitor.c:328
static void monitor_info_free(struct MonitorInfo *info)
Shutdown a file monitor.
Definition: monitor.c:233
Log at debug level 3.
Definition: logging.h:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ MonitorFilesChanged

bool MonitorFilesChanged = false

true after a monitored file has changed

Definition at line 50 of file monitor.c.

◆ MonitorContextChanged

bool MonitorContextChanged = false

true after the current mailbox has changed

Definition at line 51 of file monitor.c.

◆ INotifyFd

int INotifyFd = -1
static

Definition at line 53 of file monitor.c.

◆ Monitor

struct Monitor* Monitor = NULL
static

Definition at line 54 of file monitor.c.

◆ PollFdsCount

size_t PollFdsCount = 0
static

Definition at line 55 of file monitor.c.

◆ PollFdsLen

size_t PollFdsLen = 0
static

Definition at line 56 of file monitor.c.

◆ PollFds

struct pollfd* PollFds = NULL
static

Definition at line 57 of file monitor.c.

◆ MonitorContextDescriptor

int MonitorContextDescriptor = -1
static

Definition at line 59 of file monitor.c.