X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/b1c749bb7f147e7f9215fe6067c848cf02938b92..ca5aa725ec67d4335f4a41738dd3b7dc0d17393d:/src/src/transports/tf_maildir.c diff --git a/src/src/transports/tf_maildir.c b/src/src/transports/tf_maildir.c index 5277ef092..7411d9a3e 100644 --- a/src/src/transports/tf_maildir.c +++ b/src/src/transports/tf_maildir.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/transports/tf_maildir.c,v 1.6 2005/06/16 14:10:14 ph10 Exp $ */ +/* $Cambridge: exim/src/src/transports/tf_maildir.c,v 1.14 2009/11/16 19:56:54 nm4 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2005 */ +/* 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,19 +29,22 @@ 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; @@ -52,7 +55,7 @@ DEBUG(D_transport) /* 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. */ @@ -135,7 +138,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 +392,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; @@ -498,7 +549,7 @@ else RECALCULATE: - if (fd >= 0) close(fd); + if (fd >= 0) (void)close(fd); old_latest = 0; filecount = 0; size = maildir_compute_size(path, &filecount, &old_latest, regex, dir_regex, @@ -508,7 +559,7 @@ else tempname = string_sprintf("%s/tmp/%lu.H%luP%lu.%s", path, tv.tv_sec, tv.tv_usec, 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", @@ -516,7 +567,7 @@ else len = Ustrlen(buffer); if (write(fd, buffer, len) != len || Urename(tempname, filename) < 0) { - close(fd); + (void)close(fd); fd = -1; } } @@ -532,7 +583,7 @@ else DEBUG(D_transport) debug_printf("abandoning maildirsize because of " "a later subdirectory modification\n"); (void)Uunlink(filename); - close(fd); + (void)close(fd); fd = -1; } }