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

watch_maildirs.h

#ifndef WATCHMAILDIRS_H
#define WATCHMAILDIRS_H

#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <iterator>
#include <string>
#include <utility>

#include "compat.h"
#include "lib/util.h"

#define EXIT_RESTART 2

// watch_maildirs.cc uses these two external symbols:
// name of the notify method
extern char notify_method[];
// called to watch 'maildir' once watch_maildirs is configured
void watch(const char* maildir);


template <typename Container>
inline std::insert_iterator<Container> inserter(Container& c)
{
      return std::inserter(c, c.begin());
}

template <typename X, typename Y>
std::pair<Y,X> reverse_pair(const std::pair<X,Y>& p)
{
      return std::pair<Y,X>(p.second, p.first);
}

// readdir() that returns errno == 0 when no failures
struct dirent* safe_readdir(DIR* dir);

// Return true iff 'maildir' is a Maildir
bool is_maildir(const std::string& maildir);
// Exit if 'maildir' is not a Maildir
void die_if_not_maildir(const std::string& maildir);
// Return the IMAP name for the maildir name 'maildir'
std::string maildir_to_imap(const std::string& maildir);

// Notify that watching has begun
void send_watch_started();
// Notify that a maildir has been modified
void send_maildir_modified(const char* imap_name);

// Output the Malidir rooted at 'base_maildir' and all Maildir++s
template<typename OutputIter>
void add_maildirs(const char* base_maildir, OutputIter maildirs, OutputIter partial_maildirs)
{
      die_if_not_maildir(base_maildir);
      ++*maildirs = "";

      DIR* base_maildir_dir = opendir(base_maildir);
      die_if(!base_maildir_dir, "opendir(\"%s\")", base_maildir);

      std::string base(base_maildir);
      struct dirent* ep;
      while ((ep = safe_readdir(base_maildir_dir)))
      {
            if (ep->d_type == DT_UNKNOWN || ep->d_type == DT_LNK)
            {
                  // ep->d_type is optional (POSIX) so we must stat() should
                  // the backing file system not support the d_type field.
                  // Also stat() in the case of a symlink so that symlinks
                  // are followed.
                  struct stat st;
                  std::string subname = mkfilename(base, ep->d_name);
                  int r = stat(subname.c_str(), &st);
                  die_if(r < 0, "stat(%s)", subname.c_str());
                  if (!S_ISDIR(st.st_mode))
                        continue;
            }
            else if (ep->d_type != DT_DIR)
                  continue;
            if (strncmp(ep->d_name, ".", 1))
                  continue;
            if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, ".."))
                  continue;
            if (!strcmp(ep->d_name, ".INBOX"))
            {
                  if (is_maildir(mkfilename(base, ep->d_name)))
                  {
                        fprintf(stderr, "IMAP folder name collision between INBOX and the Maildir .INBOX\n");
                        exit(1);
                  }

                  // Ignore dovecot's '.INBOX/' used for metadata, not mail.
                  continue;
            }

            if (is_maildir(mkfilename(base, ep->d_name)))
                  ++*maildirs = ep->d_name;
            else
                  ++*partial_maildirs = ep->d_name;
      }
      die_if(errno != 0, "readdir");

      int r = closedir(base_maildir_dir);
      die_if(r < 0, "closedir(\"%s\")", base_maildir);
}

#endif // WATCHMAILDIRS_H

Generated by  Doxygen 1.6.0   Back to index