SPDX: Mass-update to GPL-2.0-or-later
[exim.git] / src / src / transports / appendfile.c
index 5d957b62e0b833358abc6ec608a496d2df3a5b1c..c39c07c9fd3813280eb4764d1964db0a7ea5d733 100644 (file)
@@ -2,9 +2,10 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
+/* Copyright (c) The Exim maintainers 2020 - 2022 */
 /* Copyright (c) University of Cambridge 1995 - 2020 */
-/* Copyright (c) The Exim maintainers 2020 */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 
 #include "../exim.h"
@@ -174,9 +175,6 @@ Arguments:
 Returns:     OK, FAIL, or DEFER
 */
 
-void
-open_logs(void);
-
 static int
 appendfile_transport_setup(transport_instance *tblock, address_item *addrlist,
   transport_feedback *dummy, uid_t uid, gid_t gid, uschar **errmsg)
@@ -186,14 +184,6 @@ appendfile_transport_options_block *ob =
 uschar *q = ob->quota;
 double default_value = 0.0;
 
-addrlist = addrlist;    /* Keep picky compilers happy */
-dummy = dummy;
-uid = uid;
-gid = gid;
-
-/* we can't wait until we're not privileged anymore */
-open_logs();
-
 if (ob->expand_maildir_use_size_file)
        ob->maildir_use_size_file = expand_check_condition(ob->expand_maildir_use_size_file,
                US"`maildir_use_size_file` in transport", tblock->name);
@@ -435,7 +425,7 @@ if ((s = ob->create_file_string ) && *s)
   else if (Ustrcmp(s, "inhome") == 0)                  val = create_inhome;
   else
     log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
-      "invalid value given for \"file_create\" for the %s transport: '%s'",
+      "invalid value given for \"create_file\" for the %s transport: '%s'",
       tblock->name, s);
   ob->create_file = val;
   }
@@ -662,14 +652,14 @@ the log, because we are running as an unprivileged user here.
 Arguments:
   dirname       the name of the directory
   countptr      where to add the file count (because this function recurses)
-  regex         a compiled regex to get the size from a name
+  re            a compiled regex to get the size from a name
 
 Returns:        the sum of the sizes of the stattable files
                 zero if the directory cannot be opened
 */
 
 off_t
-check_dir_size(const uschar * dirname, int *countptr, const pcre *regex)
+check_dir_size(const uschar * dirname, int * countptr, const pcre2_code * re)
 {
 DIR *dir;
 off_t sum = 0;
@@ -688,22 +678,28 @@ for (struct dirent *ent; ent = readdir(dir); )
 
   /* If there's a regex, try to find the size using it */
 
-  if (regex)
+  if (re)
     {
-    int ovector[6];
-    if (pcre_exec(regex, NULL, CS name, Ustrlen(name), 0, 0, ovector,6) >= 2)
+    pcre2_match_data * md = pcre2_match_data_create(2, pcre_gen_ctx);
+    int rc = pcre2_match(re, (PCRE2_SPTR)name, PCRE2_ZERO_TERMINATED,
+                         0, 0, md, pcre_gen_mtc_ctx);
+    PCRE2_SIZE * ovec = pcre2_get_ovector_pointer(md);
+    if (  rc >= 0
+       && (rc = pcre2_get_ovector_count(md)) >= 2)
       {
       uschar *endptr;
-      off_t size = (off_t)Ustrtod(name + ovector[2], &endptr);
-      if (endptr == name + ovector[3])
+      off_t size = (off_t)Ustrtod(name + ovec[2], &endptr);
+      if (endptr == name + ovec[3])
         {
         sum += size;
         DEBUG(D_transport)
           debug_printf("check_dir_size: size from %s is " OFF_T_FMT "\n", name,
             size);
+       /* pcre2_match_data_free(md);   gen ctx needs no free */
         continue;
         }
       }
+    /* pcre2_match_data_free(md);      gen ctx needs no free */
     DEBUG(D_transport)
       debug_printf("check_dir_size: regex did not match %s\n", name);
     }
@@ -722,7 +718,7 @@ for (struct dirent *ent; ent = readdir(dir); )
     if ((statbuf.st_mode & S_IFMT) == S_IFREG)
       sum += statbuf.st_size / statbuf.st_nlink;
     else if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
-      sum += check_dir_size(path, &count, regex);
+      sum += check_dir_size(path, &count, re);
   }
 
 closedir(dir);
@@ -1354,7 +1350,7 @@ if (!isdirectory)
     if (is_tainted(path))
       {
       DEBUG(D_transport) debug_printf("de-tainting path '%s'\n", path);
-      path = string_copy_taint(path, FALSE);
+      path = string_copy_taint(path, GET_UNTAINTED);
       }
 
   if (is_tainted(path)) goto tainted_ret_panic;
@@ -1368,8 +1364,8 @@ if (!isdirectory)
   if (ob->create_directory && allow_creation_here)
     {
     uschar *p = Ustrrchr(path, '/');
-    *p = '\0';
-    if (!directory_make(NULL, path, ob->dirmode, FALSE))
+    p = string_copyn(path, p - path);
+    if (!directory_make(NULL, p, ob->dirmode, FALSE))
       {
       addr->basic_errno = errno;
       addr->message =
@@ -1378,7 +1374,6 @@ if (!isdirectory)
       DEBUG(D_transport) debug_printf("%s transport: %s\n", tblock->name, path);
       return FALSE;
       }
-    *p = '/';
     }
 
   /* If file_format is set we must check that any existing file matches one of
@@ -2176,7 +2171,7 @@ scanning is expensive; for maildirs some fudges have been invented:
 else
   {
   uschar *check_path;          /* Default quota check path */
-  const pcre *regex = NULL;     /* Regex for file size from file name */
+  const pcre2_code * re = NULL;     /* Regex for file size from file name */
 
   if (!check_creation(string_sprintf("%s/any", path),
                      ob->create_file, deliver_dir))
@@ -2194,7 +2189,7 @@ else
     if (ob->create_file == create_belowhome)
       {
       DEBUG(D_transport) debug_printf("de-tainting path '%s'\n", path);
-      path = string_copy_taint(path, FALSE);
+      path = string_copy_taint(path, GET_UNTAINTED);
       }
     else
       goto tainted_ret_panic;
@@ -2219,21 +2214,14 @@ else
 
   if (ob->quota_value > 0 || THRESHOLD_CHECK || ob->maildir_use_size_file)
     {
-    const uschar *error;
-    int offset;
-
     /* Compile the regex if there is one. */
 
     if (ob->quota_size_regex)
       {
-      if (!(regex = pcre_compile(CS ob->quota_size_regex, PCRE_COPT,
-         CCSS &error, &offset, NULL)))
-        {
-        addr->message = string_sprintf("appendfile: regular expression "
-          "error: %s at offset %d while compiling %s", error, offset,
-          ob->quota_size_regex);
+      if (!(re = regex_compile(ob->quota_size_regex,
+                 MCS_NOFLAGS, &addr->message, pcre_gen_cmp_ctx)))
         return FALSE;
-        }
+
       DEBUG(D_transport) debug_printf("using regex for file sizes: %s\n",
         ob->quota_size_regex);
       }
@@ -2305,22 +2293,15 @@ else
   #ifdef SUPPORT_MAILDIR
   if (ob->maildir_use_size_file)
     {
-    const pcre *dir_regex = NULL;
-    const uschar *error;
-    int offset;
+    const pcre2_code * dir_regex = NULL;
 
     if (ob->maildir_dir_regex)
       {
       int check_path_len = Ustrlen(check_path);
 
-      if (!(dir_regex = pcre_compile(CS ob->maildir_dir_regex, PCRE_COPT,
-         CCSS &error, &offset, NULL)))
-        {
-        addr->message = string_sprintf("appendfile: regular expression "
-          "error: %s at offset %d while compiling %s", error, offset,
-          ob->maildir_dir_regex);
+      if (!(dir_regex = regex_compile(ob->maildir_dir_regex,
+           MCS_NOFLAGS, &addr->message, pcre_gen_cmp_ctx)))
         return FALSE;
-        }
 
       DEBUG(D_transport)
         debug_printf("using regex for maildir directory selection: %s\n",
@@ -2336,7 +2317,7 @@ else
         uschar *s = path + check_path_len;
         while (*s == '/') s++;
         s = *s ? string_sprintf("%s/new", s) : US"new";
-        if (pcre_exec(dir_regex, NULL, CS s, Ustrlen(s), 0, 0, NULL, 0) < 0)
+       if (!regex_match(dir_regex, s, -1, NULL))
           {
           disable_quota = TRUE;
           DEBUG(D_transport) debug_printf("delivery directory does not match "
@@ -2357,7 +2338,7 @@ else
       off_t size;
       int filecount;
 
-      if ((maildirsize_fd = maildir_ensure_sizefile(check_path, ob, regex, dir_regex,
+      if ((maildirsize_fd = maildir_ensure_sizefile(check_path, ob,  re, dir_regex,
          &size, &filecount)) == -1)
         {
         addr->basic_errno = errno;
@@ -2382,7 +2363,7 @@ else
  *    (void)unlink(CS string_sprintf("%s/maildirsize", check_path));
  *    if (THRESHOLD_CHECK)
  *      mailbox_size = maildir_compute_size(check_path, &mailbox_filecount, &old_latest,
- *        regex, dir_regex, FALSE);
+ *         re, dir_regex, FALSE);
  *    }
 */
 
@@ -2404,7 +2385,7 @@ else
     int filecount = 0;
     DEBUG(D_transport)
       debug_printf("quota checks on directory %s\n", check_path);
-    size = check_dir_size(check_path, &filecount, regex);
+    size = check_dir_size(check_path, &filecount,  re);
     if (mailbox_size < 0) mailbox_size = size;
     if (mailbox_filecount < 0) mailbox_filecount = filecount;
     }
@@ -3195,7 +3176,7 @@ else
           uschar *iptr = expand_string(nametag);
           if (iptr)
             {
-            uschar *etag = store_get(Ustrlen(iptr) + 2, is_tainted(iptr));
+            uschar *etag = store_get(Ustrlen(iptr) + 2, iptr);
             uschar *optr = etag;
             for ( ; *iptr; iptr++)
               if (mac_isgraph(*iptr) && *iptr != '/')