silence various compiler complaints; expose NVALGRIND
[exim.git] / src / src / transports / tf_maildir.c
index 50a4c186495aeb470f81bfb818bb3947f33bc434..8e57d28b2041777fb47a14573a30b75f1cb5aeb6 100644 (file)
@@ -1,10 +1,8 @@
-/* $Cambridge: exim/src/src/transports/tf_maildir.c,v 1.8 2006/02/07 11:19:03 ph10 Exp $ */
-
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2006 */
+/* Copyright (c) University of Cambridge 1995 - 2009 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions in support of the use of maildirsize files for handling quotas in
@@ -29,46 +27,49 @@ calculations are not hard wired in, but are supplied as a regex. */
 *************************************************/
 
 /* This function is called at the start of a maildir delivery, to ensure that
-all the relevant directories exist.
+all the relevant directories exist. It also creates a maildirfolder file if the
+base directory matches a given pattern.
 
 Argument:
   path              the base directory name
   addr              the address item (for setting an error message)
   create_directory  true if we are allowed to create missing directories
   dirmode           the mode for created directories
+  maildirfolder_create_regex
+                    the pattern to match for maildirfolder creation
 
 Returns:            TRUE on success; FALSE on failure
 */
 
 BOOL maildir_ensure_directories(uschar *path, address_item *addr,
-  BOOL create_directory, int dirmode)
+  BOOL create_directory, int dirmode, uschar *maildirfolder_create_regex)
 {
 int i;
 struct stat statbuf;
-char *subdirs[] = { "/tmp", "/new", "/cur" };
+const char *subdirs[] = { "/tmp", "/new", "/cur" };
 
 DEBUG(D_transport)
   debug_printf("ensuring maildir directories exist in %s\n", path);
 
 /* First ensure that the path we have is a directory; if it does not exist,
 create it. Then make sure the tmp, new & cur subdirs of the maildir are
-there. If not, fail which aborts the delivery (even though the cur subdir is
+there. If not, fail. This aborts the delivery (even though the cur subdir is
 not actually needed for delivery). Handle all 4 directory tests/creates in a
 loop so that code can be shared. */
 
 for (i = 0; i < 4; i++)
   {
   int j;
-  uschar *dir, *mdir;
+  const uschar *dir, *mdir;
 
   if (i == 0)
     {
-    mdir = US"";
+    mdir = CUS"";
     dir = path;
     }
   else
     {
-    mdir = US subdirs[i-1];
+    mdir = CUS subdirs[i-1];
     dir = mdir + 1;
     }
 
@@ -135,7 +136,55 @@ for (i = 0; i < 4; i++)
     }
   }
 
-return TRUE;   /* All directories exist */
+/* If the basic path matches maildirfolder_create_regex, we are dealing with
+a subfolder, and should ensure that a maildirfolder file exists. */
+
+if (maildirfolder_create_regex != NULL)
+  {
+  const uschar *error;
+  int offset;
+  const pcre *regex;
+
+  DEBUG(D_transport) debug_printf("checking for maildirfolder requirement\n");
+
+  regex = pcre_compile(CS maildirfolder_create_regex, PCRE_COPT,
+    (const char **)&error, &offset, NULL);
+
+  if (regex == NULL)
+    {
+    addr->message = string_sprintf("appendfile: regular expression "
+      "error: %s at offset %d while compiling %s", error, offset,
+      maildirfolder_create_regex);
+    return FALSE;
+    }
+
+  if (pcre_exec(regex, NULL, CS path, Ustrlen(path), 0, 0, NULL, 0) >= 0)
+    {
+    uschar *fname = string_sprintf("%s/maildirfolder", path);
+    if (Ustat(fname, &statbuf) == 0)
+      {
+      DEBUG(D_transport) debug_printf("maildirfolder already exists\n");
+      }
+    else
+      {
+      int fd = Uopen(fname, O_WRONLY|O_APPEND|O_CREAT, 0600);
+      if (fd < 0)
+        {
+        addr->message = string_sprintf("appendfile: failed to create "
+          "maildirfolder file in %s directory: %s", path, strerror(errno));
+        return FALSE;
+        }
+      (void)close(fd);
+      DEBUG(D_transport) debug_printf("created maildirfolder file\n");
+      }
+    }
+  else
+    {
+    DEBUG(D_transport) debug_printf("maildirfolder file not required\n");
+    }
+  }
+
+return TRUE;   /* Everything exists that should exist */
 }
 
 
@@ -341,7 +390,7 @@ the same thing. */
 filename = string_sprintf("%s/maildirsize", path);
 
 DEBUG(D_transport) debug_printf("looking for maildirsize in %s\n", path);
-fd = Uopen(filename, O_RDWR|O_APPEND, 0);
+fd = Uopen(filename, O_RDWR|O_APPEND, ob->mode ? ob->mode : 0600);
 if (fd < 0)
   {
   if (errno != ENOENT) return -1;
@@ -506,9 +555,9 @@ else
 
   (void)gettimeofday(&tv, NULL);
   tempname = string_sprintf("%s/tmp/%lu.H%luP%lu.%s", path, tv.tv_sec,
-    tv.tv_usec, getpid(), primary_hostname);
+    tv.tv_usec, (long unsigned) getpid(), primary_hostname);
 
-  fd = Uopen(tempname, O_RDWR|O_CREAT|O_EXCL, 0600);
+  fd = Uopen(tempname, O_RDWR|O_CREAT|O_EXCL, ob->mode ? ob->mode : 0600);
   if (fd >= 0)
     {
     (void)sprintf(CS buffer, OFF_T_FMT "S,%dC\n" OFF_T_FMT " %d\n",
@@ -533,7 +582,7 @@ else
       "a later subdirectory modification\n");
     (void)Uunlink(filename);
     (void)close(fd);
-    fd = -1;
+    fd = -2;
     }
   }