Logo Search packages:      
Sourcecode: mswatch version File versions  Download package

watcher_maildir.cc

#include <assert.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <string>

#include "lib/util.h"
#include "watch_maildirs.h"
#include "watcher_partial.h"
#include "watcher_maildir.h"

using std::string;

watcher_maildir::watcher_maildir(struct dnotify_state* state, const string& maildir)
      : maildir(maildir), imap_name(maildir_to_imap(maildir)), state(state)
{
      string full_maildir(mkfilename(state->base_path, maildir));
      string maildir_cur(mkfilename(full_maildir, "cur/"));;
      string maildir_new(mkfilename(full_maildir, "new/"));

      fd_maildir = start_watch(full_maildir.c_str(), m_notify);
      fd_cur = start_watch(maildir_cur.c_str(), cn_notify);
      fd_new = start_watch(maildir_new.c_str(), cn_notify);
}

watcher_maildir::~watcher_maildir()
{
      if (fd_maildir >= 0)
            stop_watch(fd_maildir);
      if (fd_cur >= 0)
            stop_watch(fd_cur);
      if (fd_new >= 0)
            stop_watch(fd_new);
}


void watcher_maildir::process_event(int fd)
{
      if (fd == fd_cur || fd == fd_new)
            send_maildir_modified(imap_name.c_str());
      else
      {
            assert(fd == fd_maildir);

            // XXX: Checking whether cur/ and new/ still exists /can/ miss changes,
            // eg a quick "mv cur/ /foo/; mkdir cur/". We could send a modified
            // message, but this would generate many extra notifies.
            // Because this might generate many extra notifies and this move
            // behavior is unexpected, don't send the notifies.
            // TODO: would sending the extra notifies cause more mswatch syncs?
            if (is_maildir(mkfilename(state->base_path, maildir)))
                  return;

            send_maildir_modified(imap_name.c_str());

            stop_watch(fd_maildir);
            stop_watch(fd_cur);
            stop_watch(fd_new);
            fd_maildir = fd_cur = fd_new = -1;

            new watcher_partial(state, maildir);

            delete this;
            return;
      }
}

int watcher_maildir::start_watch(const char* dir, long notify)
{
      int fd = open(dir, O_RDONLY);
      die_if(fd < 0, "open(\"%s\")", imap_name.c_str());
      set_fd_watch(fd, notify, dir);
      state->add_imap_watcher(fd, imap_name, this);
      return fd;
}

void watcher_maildir::stop_watch(int fd)
{
      state->remove_imap_watcher(fd, imap_name);
      int r = close(fd);
      die_if(r < 0, "close");
}

Generated by  Doxygen 1.6.0   Back to index