X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/22ed7a5295f196fce32563f6e9c669110dd36f4d..38965d80d70cacd0c944d32f7107549a3a272b35:/src/src/transports/appendfile.c diff --git a/src/src/transports/appendfile.c b/src/src/transports/appendfile.c index bbd4a161f..0279659f2 100644 --- a/src/src/transports/appendfile.c +++ b/src/src/transports/appendfile.c @@ -2,12 +2,15 @@ * Exim - an Internet mail transport agent * *************************************************/ +/* Copyright (c) The Exim maintainers 2020 - 2023 */ /* 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" + +#ifdef TRANSPORT_APPENDFILE /* Remainder of file */ #include "appendfile.h" #ifdef SUPPORT_MAILDIR @@ -152,7 +155,6 @@ static const char *mailbox_formats[] = { (!ob->quota_warn_threshold_is_percent || ob->quota_value > 0)) - /************************************************* * Setup entry point * *************************************************/ @@ -174,33 +176,28 @@ 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) { -appendfile_transport_options_block *ob = +appendfile_transport_options_block * ob = (appendfile_transport_options_block *)(tblock->options_block); -uschar *q = ob->quota; +uschar * q; 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, + { + GET_OPTION("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); + } /* Loop for quota, quota_filecount, quota_warn_threshold, mailbox_size, mailbox_filecount */ +GET_OPTION("quota"); +q = ob->quota; for (int i = 0; i < 5; i++) { double d = default_value; @@ -269,6 +266,7 @@ for (int i = 0; i < 5; i++) which = US"quota"; ob->quota_value = (off_t)d; ob->quota_no_check = no_check; + GET_OPTION("quota_filecount"); q = ob->quota_filecount; break; @@ -277,6 +275,7 @@ for (int i = 0; i < 5; i++) which = US"quota_filecount"; ob->quota_filecount_value = (int)d; ob->quota_filecount_no_check = no_check; + GET_OPTION("quota_warn_threshold"); q = ob->quota_warn_threshold; break; @@ -284,6 +283,7 @@ for (int i = 0; i < 5; i++) if (d >= 2.0*1024.0*1024.0*1024.0 && sizeof(off_t) <= 4) which = US"quota_warn_threshold"; ob->quota_warn_threshold_value = (off_t)d; + GET_OPTION("mailbox_size"); q = ob->mailbox_size_string; default_value = -1.0; break; @@ -292,6 +292,7 @@ for (int i = 0; i < 5; i++) if (d >= 2.0*1024.0*1024.0*1024.0 && sizeof(off_t) <= 4) which = US"mailbox_size";; ob->mailbox_size_value = (off_t)d; + GET_OPTION("mailbox_filecount"); q = ob->mailbox_filecount_string; break; @@ -410,10 +411,10 @@ if (ob->dirname) if (ob->maildir_format && ob->mailstore_format) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s transport:\n " "only one of maildir and mailstore may be specified", tblock->name); - if (ob->quota_filecount != NULL && ob->quota == NULL) + if (ob->quota_filecount != NULL && !ob->quota) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s transport:\n " "quota must be set if quota_filecount is set", tblock->name); - if (ob->quota_directory != NULL && ob->quota == NULL) + if (ob->quota_directory != NULL && !ob->quota) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s transport:\n " "quota must be set if quota_directory is set", tblock->name); } @@ -435,7 +436,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; } @@ -512,7 +513,7 @@ Returns: nothing */ static void -notify_comsat(uschar *user, off_t offset) +notify_comsat(const uschar * user, off_t offset) { struct servent *sp; host_item host; @@ -671,13 +672,14 @@ Returns: the sum of the sizes of the stattable files off_t check_dir_size(const uschar * dirname, int * countptr, const pcre2_code * re) { -DIR *dir; +DIR * dir; off_t sum = 0; -int count = *countptr; +int count = *countptr, lcount = REGEX_LOOPCOUNT_STORE_RESET; +rmark reset_point = store_mark(); if (!(dir = exim_opendir(dirname))) return 0; -for (struct dirent *ent; ent = readdir(dir); ) +for (struct dirent * ent; ent = readdir(dir); ) { uschar * path, * name = US ent->d_name; struct stat statbuf; @@ -685,6 +687,11 @@ for (struct dirent *ent; ent = readdir(dir); ) if (Ustrcmp(name, ".") == 0 || Ustrcmp(name, "..") == 0) continue; count++; + if (--lcount == 0) + { + store_reset(reset_point); reset_point = store_mark(); + lcount = REGEX_LOOPCOUNT_STORE_RESET; + } /* If there's a regex, try to find the size using it */ @@ -692,7 +699,7 @@ for (struct dirent *ent; ent = readdir(dir); ) { 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_mtc_ctx); + 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) @@ -705,9 +712,11 @@ for (struct dirent *ent; ent = readdir(dir); ) 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); } @@ -734,6 +743,7 @@ DEBUG(D_transport) debug_printf("check_dir_size: dir=%s sum=" OFF_T_FMT " count=%d\n", dirname, sum, count); +store_reset(reset_point); *countptr = count; return sum; } @@ -1223,6 +1233,7 @@ if (!fdname) { if (!(fdname = ob->filename)) { + GET_OPTION("directory"); fdname = ob->dirname; isdirectory = TRUE; } @@ -1358,7 +1369,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; @@ -2197,7 +2208,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; @@ -2222,29 +2233,21 @@ else if (ob->quota_value > 0 || THRESHOLD_CHECK || ob->maildir_use_size_file) { - PCRE2_SIZE offset; - int err; - /* Compile the regex if there is one. */ if (ob->quota_size_regex) { - if (!(re = pcre2_compile((PCRE2_SPTR)ob->quota_size_regex, - PCRE2_ZERO_TERMINATED, PCRE_COPT, &err, &offset, pcre_cmp_ctx))) - { - uschar errbuf[128]; - pcre2_get_error_message(err, errbuf, sizeof(errbuf)); - addr->message = string_sprintf("appendfile: regular expression " - "error: %s at offset %l while compiling %s", errbuf, (long)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); } /* Use an explicitly configured directory if set */ + GET_OPTION("quota_directory"); if (ob->quota_directory) { if (!(check_path = expand_string(ob->quota_directory))) @@ -2311,23 +2314,14 @@ else if (ob->maildir_use_size_file) { const pcre2_code * dir_regex = NULL; - PCRE2_SIZE offset; - int err; if (ob->maildir_dir_regex) { int check_path_len = Ustrlen(check_path); - if (!(dir_regex = pcre2_compile((PCRE2_SPTR)ob->maildir_dir_regex, - PCRE2_ZERO_TERMINATED, PCRE_COPT, &err, &offset, pcre_cmp_ctx))) - { - uschar errbuf[128]; - pcre2_get_error_message(err, errbuf, sizeof(errbuf)); - addr->message = string_sprintf("appendfile: regular expression " - "error: %s at offset %l while compiling %s", errbuf, (long)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", @@ -2451,6 +2445,7 @@ else DEBUG(D_transport) debug_printf("delivering in maildir format in %s\n", path); + GET_OPTION("maildir_tag"); nametag = ob->maildir_tag; /* Check that nametag expands successfully; a hard failure causes a panic @@ -2538,9 +2533,9 @@ else else { - FILE *env_file; + FILE * env_file; mailstore_basename = string_sprintf("%s/%s-%s", path, message_id, - string_base62((long int)getpid())); + string_base62_64((long int)getpid())); DEBUG(D_transport) debug_printf("delivering in mailstore format in %s\n", path); @@ -2587,9 +2582,10 @@ else /* Write the envelope file, then close it. */ + GET_OPTION("mailstore_prefix"); if (ob->mailstore_prefix) { - uschar *s = expand_string(ob->mailstore_prefix); + uschar * s = expand_string(ob->mailstore_prefix); if (!s) { if (!f.expand_string_forcedfail) @@ -2615,9 +2611,10 @@ else for (address_item * taddr = addr; taddr; taddr = taddr->next) fprintf(env_file, "%s@%s\n", taddr->local_part, taddr->domain); + GET_OPTION("mailstore_suffix"); if (ob->mailstore_suffix) { - uschar *s = expand_string(ob->mailstore_suffix); + uschar * s = expand_string(ob->mailstore_suffix); if (!s) { if (!f.expand_string_forcedfail) @@ -2777,18 +2774,21 @@ transport_newlines = 0; /* Write any configured prefix text first */ -if (yield == OK && ob->message_prefix && *ob->message_prefix) +if (yield == OK) { - uschar *prefix = expand_string(ob->message_prefix); - if (!prefix) - { - errno = ERRNO_EXPANDFAIL; - addr->transport_return = PANIC; - addr->message = string_sprintf("Expansion of \"%s\" (prefix for %s " - "transport) failed", ob->message_prefix, tblock->name); - yield = DEFER; - } - else if (!transport_write_string(fd, "%s", prefix)) yield = DEFER; + uschar * prefix = ob->message_prefix; + GET_OPTION("message_prefix"); + if (prefix && *prefix) + if (!(prefix = expand_string(prefix))) + { + errno = ERRNO_EXPANDFAIL; + addr->transport_return = PANIC; + addr->message = string_sprintf("Expansion of \"%s\" (prefix for %s " + "transport) failed", ob->message_prefix, tblock->name); + yield = DEFER; + } + else if (!transport_write_string(fd, "%s", prefix)) + yield = DEFER; } /* If the use_bsmtp option is on, we need to write SMTP prefix information. The @@ -2840,18 +2840,21 @@ if (yield == OK) /* Now a configured suffix. */ -if (yield == OK && ob->message_suffix && *ob->message_suffix) +if (yield == OK) { - uschar *suffix = expand_string(ob->message_suffix); - if (!suffix) - { - errno = ERRNO_EXPANDFAIL; - addr->transport_return = PANIC; - addr->message = string_sprintf("Expansion of \"%s\" (suffix for %s " - "transport) failed", ob->message_suffix, tblock->name); - yield = DEFER; - } - else if (!transport_write_string(fd, "%s", suffix)) yield = DEFER; + uschar * suffix = ob->message_suffix; + GET_OPTION("message_suffix"); + if (suffix && *suffix) + if (!(suffix = expand_string(suffix))) + { + errno = ERRNO_EXPANDFAIL; + addr->transport_return = PANIC; + addr->message = string_sprintf("Expansion of \"%s\" (suffix for %s " + "transport) failed", ob->message_suffix, tblock->name); + yield = DEFER; + } + else if (!transport_write_string(fd, "%s", suffix)) + yield = DEFER; } /* If batch smtp, write the terminating dot. */ @@ -3202,7 +3205,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 != '/') @@ -3325,4 +3328,5 @@ ret_panic: } #endif /*!MACRO_PREDEF*/ +#endif /*TRANSPORT_APPENDFILE*/ /* End of transport/appendfile.c */