NeoMutt  2020-03-20-65-g141838
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/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "monitor.h"
#include "context.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_NOTYPE = -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_NOTYPE 

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 };
File exists, monitor is already attached.
Definition: monitor.c:75
No Mailbox to work on.
Definition: monitor.c:71
Can&#39;t identify Mailbox type.
Definition: monitor.c:72
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 #ifdef 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:41
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->type = info->type;
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->type == 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
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
enum MailboxType type
Definition: monitor.c:96
char * mh_backup_path
Definition: monitor.c:84
static struct Monitor * Monitor
Definition: monitor.c:54
&#39;MH&#39; Mailbox type
Definition: mailbox.h:50
dev_t st_dev
Definition: monitor.c:85
enum MailboxType type
Definition: monitor.c:87
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->type == 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:41
char * mh_backup_path
Definition: monitor.c:84
static struct Monitor * Monitor
Definition: monitor.c:54
&#39;MH&#39; Mailbox type
Definition: mailbox.h:50
dev_t st_dev
Definition: monitor.c:85
enum MailboxType type
Definition: monitor.c:87
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:42
+ 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)
-2type not set
-1stat() failed (see errno; MonitorInfo fields: type, 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->type = m->type;
336  info->path = m->realpath;
337  }
338  else if (Context && Context->mailbox)
339  {
340  info->type = Context->mailbox->type;
341  info->path = Context->mailbox->realpath;
342  }
343  else
344  {
346  }
347 
348  if (info->type == MUTT_UNKNOWN)
349  {
351  }
352  else if (info->type == MUTT_MAILDIR)
353  {
354  info->is_dir = true;
355  fmt = "%s/new";
356  }
357  else
358  {
359  info->is_dir = false;
360  if (info->type == 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:37
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
ino_t st_ino
Definition: monitor.c:86
struct Buffer path_buf
Definition: monitor.c:102
static int const char * fmt
Definition: acutest.h:473
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:47
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:51
enum MailboxType type
Definition: monitor.c:96
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
No Mailbox to work on.
Definition: monitor.c:71
Can&#39;t identify Mailbox type.
Definition: monitor.c:72
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:50
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  {
441  mutt_debug(LL_DEBUG2, "read inotify events failed, errno=%d %s\n",
442  errno, strerror(errno));
443  }
444  break;
445  }
446 
447  while (ptr < (buf + len))
448  {
449  event = (const struct inotify_event *) ptr;
450  mutt_debug(LL_DEBUG3, "+ detail: descriptor=%d mask=0x%x\n",
451  event->wd, event->mask);
452  if (event->mask & IN_IGNORED)
453  monitor_handle_ignore(event->wd);
454  else if (event->wd == MonitorContextDescriptor)
455  MonitorContextChanged = true;
456  ptr += sizeof(struct inotify_event) + event->len;
457  }
458  }
459  }
460  }
461  }
462  if (!input_ready)
463  rc = MonitorFilesChanged ? -2 : -3;
464  }
465  }
466 
467  return rc;
468 }
#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:41
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:42
int MuttGetchTimeout
Timeout in ms for mutt_getch()
Definition: curs_lib.c:92
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 478 of file monitor.c.

479 {
480  struct MonitorInfo info;
481  monitor_info_init(&info);
482 
483  int rc = 0;
484  enum ResolveResult desc = monitor_resolve(&info, m);
485  if (desc != RESOLVE_RES_OK_NOTEXISTING)
486  {
487  if (!m && (desc == RESOLVE_RES_OK_EXISTING))
488  MonitorContextDescriptor = info.monitor->desc;
489  rc = (desc == RESOLVE_RES_OK_EXISTING) ? 0 : -1;
490  goto cleanup;
491  }
492 
493  uint32_t mask = info.is_dir ? INOTIFY_MASK_DIR : INOTIFY_MASK_FILE;
494  if (((INotifyFd == -1) && (monitor_init() == -1)) ||
495  ((desc = inotify_add_watch(INotifyFd, info.path, mask)) == -1))
496  {
497  mutt_debug(LL_DEBUG2, "inotify_add_watch failed for '%s', errno=%d %s\n",
498  info.path, errno, strerror(errno));
499  rc = -1;
500  goto cleanup;
501  }
502 
503  mutt_debug(LL_DEBUG3, "inotify_add_watch descriptor=%d for '%s'\n", desc, info.path);
504  if (!m)
506 
507  monitor_new(&info, desc);
508 
509 cleanup:
510  monitor_info_free(&info);
511  return rc;
512 }
#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:41
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:42
+ 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 523 of file monitor.c.

524 {
525  struct MonitorInfo info, info2;
526  int rc = 0;
527 
528  monitor_info_init(&info);
529  monitor_info_init(&info2);
530 
531  if (!m)
532  {
534  MonitorContextChanged = false;
535  }
536 
537  if (monitor_resolve(&info, m) != RESOLVE_RES_OK_EXISTING)
538  {
539  rc = 2;
540  goto cleanup;
541  }
542 
543  if (Context && Context->mailbox)
544  {
545  if (m)
546  {
547  if ((monitor_resolve(&info2, NULL) == RESOLVE_RES_OK_EXISTING) &&
548  (info.st_ino == info2.st_ino) && (info.st_dev == info2.st_dev))
549  {
550  rc = 1;
551  goto cleanup;
552  }
553  }
554  else
555  {
557  {
558  rc = 1;
559  goto cleanup;
560  }
561  }
562  }
563 
564  inotify_rm_watch(info.monitor->desc, INotifyFd);
565  mutt_debug(LL_DEBUG3, "inotify_rm_watch for '%s' descriptor=%d\n", info.path,
566  info.monitor->desc);
567 
568  monitor_delete(info.monitor);
570 
571 cleanup:
572  monitor_info_free(&info);
573  monitor_info_free(&info2);
574  return rc;
575 }
The "current" mailbox.
Definition: context.h:37
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:88
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
File exists, monitor is already attached.
Definition: monitor.c:75
static int INotifyFd
Definition: monitor.c:53
struct Mailbox * mailbox
Definition: context.h:51
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:42
+ 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.