*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
order (note that "_" comes before the lower case letters). Some of them are
stored in the publicly visible instance block - these are flagged with the
opt_public flag. */
+#define LOFF(field) OPT_OFF(appendfile_transport_options_block, field)
optionlist appendfile_transport_options[] = {
#ifdef SUPPORT_MAILDIR
- { "*expand_maildir_use_size_file", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, expand_maildir_use_size_file) },
+ { "*expand_maildir_use_size_file", opt_stringptr, LOFF(expand_maildir_use_size_file) },
#endif
- { "*set_use_fcntl_lock",opt_bool | opt_hidden,
- (void *)offsetof(appendfile_transport_options_block, set_use_fcntl) },
- { "*set_use_flock_lock",opt_bool | opt_hidden,
- (void *)offsetof(appendfile_transport_options_block, set_use_flock) },
- { "*set_use_lockfile", opt_bool | opt_hidden,
- (void *)offsetof(appendfile_transport_options_block, set_use_lockfile) },
+ { "*set_use_fcntl_lock",opt_bool | opt_hidden, LOFF(set_use_fcntl) },
+ { "*set_use_flock_lock",opt_bool | opt_hidden, LOFF(set_use_flock) },
+ { "*set_use_lockfile", opt_bool | opt_hidden, LOFF(set_use_lockfile) },
#ifdef SUPPORT_MBX
- { "*set_use_mbx_lock", opt_bool | opt_hidden,
- (void *)offsetof(appendfile_transport_options_block, set_use_mbx_lock) },
+ { "*set_use_mbx_lock", opt_bool | opt_hidden, LOFF(set_use_mbx_lock) },
#endif
- { "allow_fifo", opt_bool,
- (void *)offsetof(appendfile_transport_options_block, allow_fifo) },
- { "allow_symlink", opt_bool,
- (void *)offsetof(appendfile_transport_options_block, allow_symlink) },
- { "batch_id", opt_stringptr | opt_public,
- (void *)offsetof(transport_instance, batch_id) },
- { "batch_max", opt_int | opt_public,
- (void *)offsetof(transport_instance, batch_max) },
- { "check_group", opt_bool,
- (void *)offsetof(appendfile_transport_options_block, check_group) },
- { "check_owner", opt_bool,
- (void *)offsetof(appendfile_transport_options_block, check_owner) },
- { "check_string", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, check_string) },
- { "create_directory", opt_bool,
- (void *)offsetof(appendfile_transport_options_block, create_directory) },
- { "create_file", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, create_file_string) },
- { "directory", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, dirname) },
- { "directory_file", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, dirfilename) },
- { "directory_mode", opt_octint,
- (void *)offsetof(appendfile_transport_options_block, dirmode) },
- { "escape_string", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, escape_string) },
- { "file", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, filename) },
- { "file_format", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, file_format) },
- { "file_must_exist", opt_bool,
- (void *)offsetof(appendfile_transport_options_block, file_must_exist) },
- { "lock_fcntl_timeout", opt_time,
- (void *)offsetof(appendfile_transport_options_block, lock_fcntl_timeout) },
- { "lock_flock_timeout", opt_time,
- (void *)offsetof(appendfile_transport_options_block, lock_flock_timeout) },
- { "lock_interval", opt_time,
- (void *)offsetof(appendfile_transport_options_block, lock_interval) },
- { "lock_retries", opt_int,
- (void *)offsetof(appendfile_transport_options_block, lock_retries) },
- { "lockfile_mode", opt_octint,
- (void *)offsetof(appendfile_transport_options_block, lockfile_mode) },
- { "lockfile_timeout", opt_time,
- (void *)offsetof(appendfile_transport_options_block, lockfile_timeout) },
- { "mailbox_filecount", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, mailbox_filecount_string) },
- { "mailbox_size", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, mailbox_size_string) },
+ { "allow_fifo", opt_bool, LOFF(allow_fifo) },
+ { "allow_symlink", opt_bool, LOFF(allow_symlink) },
+ { "batch_id", opt_stringptr | opt_public, OPT_OFF(transport_instance, batch_id) },
+ { "batch_max", opt_int | opt_public, OPT_OFF(transport_instance, batch_max) },
+ { "check_group", opt_bool, LOFF(check_group) },
+ { "check_owner", opt_bool, LOFF(check_owner) },
+ { "check_string", opt_stringptr, LOFF(check_string) },
+ { "create_directory", opt_bool, LOFF(create_directory) },
+ { "create_file", opt_stringptr, LOFF(create_file_string) },
+ { "directory", opt_stringptr, LOFF(dirname) },
+ { "directory_file", opt_stringptr, LOFF(dirfilename) },
+ { "directory_mode", opt_octint, LOFF(dirmode) },
+ { "escape_string", opt_stringptr, LOFF(escape_string) },
+ { "file", opt_stringptr, LOFF(filename) },
+ { "file_format", opt_stringptr, LOFF(file_format) },
+ { "file_must_exist", opt_bool, LOFF(file_must_exist) },
+ { "lock_fcntl_timeout", opt_time, LOFF(lock_fcntl_timeout) },
+ { "lock_flock_timeout", opt_time, LOFF(lock_flock_timeout) },
+ { "lock_interval", opt_time, LOFF(lock_interval) },
+ { "lock_retries", opt_int, LOFF(lock_retries) },
+ { "lockfile_mode", opt_octint, LOFF(lockfile_mode) },
+ { "lockfile_timeout", opt_time, LOFF(lockfile_timeout) },
+ { "mailbox_filecount", opt_stringptr, LOFF(mailbox_filecount_string) },
+ { "mailbox_size", opt_stringptr, LOFF(mailbox_size_string) },
#ifdef SUPPORT_MAILDIR
- { "maildir_format", opt_bool,
- (void *)offsetof(appendfile_transport_options_block, maildir_format ) } ,
- { "maildir_quota_directory_regex", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, maildir_dir_regex) },
- { "maildir_retries", opt_int,
- (void *)offsetof(appendfile_transport_options_block, maildir_retries) },
- { "maildir_tag", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, maildir_tag) },
- { "maildir_use_size_file", opt_expand_bool,
- (void *)offsetof(appendfile_transport_options_block, maildir_use_size_file ) } ,
- { "maildirfolder_create_regex", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, maildirfolder_create_regex ) },
+ { "maildir_format", opt_bool, LOFF(maildir_format ) } ,
+ { "maildir_quota_directory_regex", opt_stringptr, LOFF(maildir_dir_regex) },
+ { "maildir_retries", opt_int, LOFF(maildir_retries) },
+ { "maildir_tag", opt_stringptr, LOFF(maildir_tag) },
+ { "maildir_use_size_file", opt_expand_bool, LOFF(maildir_use_size_file ) } ,
+ { "maildirfolder_create_regex", opt_stringptr, LOFF(maildirfolder_create_regex ) },
#endif /* SUPPORT_MAILDIR */
#ifdef SUPPORT_MAILSTORE
- { "mailstore_format", opt_bool,
- (void *)offsetof(appendfile_transport_options_block, mailstore_format ) },
- { "mailstore_prefix", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, mailstore_prefix ) },
- { "mailstore_suffix", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, mailstore_suffix ) },
+ { "mailstore_format", opt_bool, LOFF(mailstore_format ) },
+ { "mailstore_prefix", opt_stringptr, LOFF(mailstore_prefix ) },
+ { "mailstore_suffix", opt_stringptr, LOFF(mailstore_suffix ) },
#endif /* SUPPORT_MAILSTORE */
#ifdef SUPPORT_MBX
- { "mbx_format", opt_bool,
- (void *)offsetof(appendfile_transport_options_block, mbx_format ) } ,
+ { "mbx_format", opt_bool, LOFF(mbx_format ) } ,
#endif /* SUPPORT_MBX */
- { "message_prefix", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, message_prefix) },
- { "message_suffix", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, message_suffix) },
- { "mode", opt_octint,
- (void *)offsetof(appendfile_transport_options_block, mode) },
- { "mode_fail_narrower",opt_bool,
- (void *)offsetof(appendfile_transport_options_block, mode_fail_narrower) },
- { "notify_comsat", opt_bool,
- (void *)offsetof(appendfile_transport_options_block, notify_comsat) },
- { "quota", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, quota) },
- { "quota_directory", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, quota_directory) },
- { "quota_filecount", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, quota_filecount) },
- { "quota_is_inclusive", opt_bool,
- (void *)offsetof(appendfile_transport_options_block, quota_is_inclusive) },
- { "quota_size_regex", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, quota_size_regex) },
- { "quota_warn_message", opt_stringptr | opt_public,
- (void *)offsetof(transport_instance, warn_message) },
- { "quota_warn_threshold", opt_stringptr,
- (void *)offsetof(appendfile_transport_options_block, quota_warn_threshold) },
- { "use_bsmtp", opt_bool,
- (void *)offsetof(appendfile_transport_options_block, use_bsmtp) },
- { "use_crlf", opt_bool,
- (void *)offsetof(appendfile_transport_options_block, use_crlf) },
- { "use_fcntl_lock", opt_bool_set,
- (void *)offsetof(appendfile_transport_options_block, use_fcntl) },
- { "use_flock_lock", opt_bool_set,
- (void *)offsetof(appendfile_transport_options_block, use_flock) },
- { "use_lockfile", opt_bool_set,
- (void *)offsetof(appendfile_transport_options_block, use_lockfile) },
+ { "message_prefix", opt_stringptr, LOFF(message_prefix) },
+ { "message_suffix", opt_stringptr, LOFF(message_suffix) },
+ { "mode", opt_octint, LOFF(mode) },
+ { "mode_fail_narrower",opt_bool, LOFF(mode_fail_narrower) },
+ { "notify_comsat", opt_bool, LOFF(notify_comsat) },
+ { "quota", opt_stringptr, LOFF(quota) },
+ { "quota_directory", opt_stringptr, LOFF(quota_directory) },
+ { "quota_filecount", opt_stringptr, LOFF(quota_filecount) },
+ { "quota_is_inclusive", opt_bool, LOFF(quota_is_inclusive) },
+ { "quota_size_regex", opt_stringptr, LOFF(quota_size_regex) },
+ { "quota_warn_message", opt_stringptr | opt_public, OPT_OFF(transport_instance, warn_message) },
+ { "quota_warn_threshold", opt_stringptr, LOFF(quota_warn_threshold) },
+ { "use_bsmtp", opt_bool, LOFF(use_bsmtp) },
+ { "use_crlf", opt_bool, LOFF(use_crlf) },
+ { "use_fcntl_lock", opt_bool_set, LOFF(use_fcntl) },
+ { "use_flock_lock", opt_bool_set, LOFF(use_flock) },
+ { "use_lockfile", opt_bool_set, LOFF(use_lockfile) },
#ifdef SUPPORT_MBX
- { "use_mbx_lock", opt_bool_set,
- (void *)offsetof(appendfile_transport_options_block, use_mbx_lock) },
+ { "use_mbx_lock", opt_bool_set, LOFF(use_mbx_lock) },
#endif /* SUPPORT_MBX */
};
rest += sizeof("/no_check") - 1;
}
- while (isspace(*rest)) rest++;
+ Uskip_whitespace(&rest);
- if (*rest != 0)
+ if (*rest)
{
*errmsg = string_sprintf("Malformed value \"%s\" (expansion of \"%s\") "
"in %s transport", s, q, tblock->name);
DIR *dir;
off_t sum = 0;
int count = *countptr;
-struct dirent *ent;
-struct stat statbuf;
-if (!(dir = opendir(CS dirname))) return 0;
+if (!(dir = exim_opendir(dirname))) return 0;
-while ((ent = readdir(dir)))
+for (struct dirent *ent; ent = readdir(dir); )
{
uschar * path, * name = US ent->d_name;
+ struct stat statbuf;
if (Ustrcmp(name, ".") == 0 || Ustrcmp(name, "..") == 0) continue;
}
if (!fdname)
{
- addr->transport_return = PANIC;
addr->message = string_sprintf("Mandatory file or directory option "
"missing from %s transport", tblock->name);
- return FALSE;
+ goto ret_panic;
}
}
if ((ob->maildir_format || ob->mailstore_format) && !isdirectory)
{
- addr->transport_return = PANIC;
addr->message = string_sprintf("mail%s_format requires \"directory\" "
"to be specified for the %s transport",
ob->maildir_format ? "dir" : "store", tblock->name);
- return FALSE;
+ goto ret_panic;
}
if (!(path = expand_string(fdname)))
{
- addr->transport_return = PANIC;
addr->message = string_sprintf("Expansion of \"%s\" (file or directory "
"name for %s transport) failed: %s", fdname, tblock->name,
expand_string_message);
- return FALSE;
+ goto ret_panic;
+ }
+if (is_tainted(path))
+ {
+ addr->message = string_sprintf("Tainted '%s' (file or directory "
+ "name for %s transport) not permitted", path, tblock->name);
+ goto ret_panic;
}
if (path[0] != '/')
to the true local part. */
if (testflag(addr, af_file))
- for (address_item * addr2 = addr; addr2 != NULL; addr2 = addr2->next)
+ for (address_item * addr2 = addr; addr2; addr2 = addr2->next)
addr2->local_part = string_copy(path);
/* The available mailbox formats depend on whether it is a directory or a file
{
if (!(check_path = expand_string(ob->quota_directory)))
{
- addr->transport_return = PANIC;
addr->message = string_sprintf("Expansion of \"%s\" (quota_directory "
"name for %s transport) failed: %s", ob->quota_directory,
tblock->name, expand_string_message);
- return FALSE;
+ goto ret_panic;
}
if (check_path[0] != '/')
{
uschar *new_check_path = string_copy(check_path);
uschar *slash = Ustrrchr(new_check_path, '/');
- if (slash != NULL)
+ if (slash)
{
- if (slash[1] == 0)
+ if (!slash[1])
{
*slash = 0;
slash = Ustrrchr(new_check_path, '/');
}
- if (slash != NULL)
+ if (slash)
{
*slash = 0;
check_path = new_check_path;
{
uschar *s = path + check_path_len;
while (*s == '/') s++;
- s = (*s == 0) ? US "new" : string_sprintf("%s/new", 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)
{
disable_quota = TRUE;
count. Note that ob->quota_filecount_value cannot be set without
ob->quota_value being set. */
- if (!disable_quota &&
- (ob->quota_value > 0 || THRESHOLD_CHECK) &&
- (mailbox_size < 0 ||
- (mailbox_filecount < 0 && ob->quota_filecount_value > 0)))
+ if ( !disable_quota
+ && (ob->quota_value > 0 || THRESHOLD_CHECK)
+ && ( mailbox_size < 0
+ || mailbox_filecount < 0 && ob->quota_filecount_value > 0
+ ) )
{
off_t size;
int filecount = 0;
if (nametag && !expand_string(nametag) && !f.expand_string_forcedfail)
{
- addr->transport_return = PANIC;
addr->message = string_sprintf("Expansion of \"%s\" (maildir_tag "
"for %s transport) failed: %s", nametag, tblock->name,
expand_string_message);
- return FALSE;
+ goto ret_panic;
}
/* We ensured the existence of all the relevant directories above. Attempt
uschar *basename;
(void)gettimeofday(&msg_tv, NULL);
- basename = string_sprintf(TIME_T_FMT ".H%luP" PID_T_FMT ".%s",
+ basename = string_sprintf(TIME_T_FMT ".M%luP" PID_T_FMT ".%s",
msg_tv.tv_sec, msg_tv.tv_usec, getpid(), primary_hostname);
filename = dataname = string_sprintf("tmp/%s", basename);
dataname = string_sprintf("%s.msg", mailstore_basename);
fd = Uopen(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
- if (fd < 0 && /* failed to open, and */
- (errno != ENOENT || /* either not non-exist */
- !ob->create_directory || /* or not allowed to make */
- !directory_make(NULL, path, ob->dirmode, FALSE) || /* or failed to create dir */
- (fd = Uopen(filename, O_WRONLY|O_CREAT|O_EXCL, mode)) < 0)) /* or then failed to open */
+ if ( fd < 0 /* failed to open, and */
+ && ( errno != ENOENT /* either not non-exist */
+ || !ob->create_directory /* or not allowed to make */
+ || !directory_make(NULL, path, ob->dirmode, FALSE) /* or failed to create dir */
+ || (fd = Uopen(filename, O_WRONLY|O_CREAT|O_EXCL, mode)) < 0 /* or then failed to open */
+ ) )
{
addr->basic_errno = errno;
addr->message = string_sprintf("while creating file %s", filename);
if (!(env_file = fdopen(fd, "wb")))
{
addr->basic_errno = errno;
- addr->transport_return = PANIC;
addr->message = string_sprintf("fdopen of %s ("
"for %s transport) failed", filename, tblock->name);
(void)close(fd);
Uunlink(filename);
- return FALSE;
+ goto ret_panic;
}
/* Write the envelope file, then close it. */
{
if (!f.expand_string_forcedfail)
{
- addr->transport_return = PANIC;
addr->message = string_sprintf("Expansion of \"%s\" (mailstore "
"prefix for %s transport) failed: %s", ob->mailstore_prefix,
tblock->name, expand_string_message);
(void)fclose(env_file);
Uunlink(filename);
- return FALSE;
+ goto ret_panic;
}
}
else
{
if (!f.expand_string_forcedfail)
{
- addr->transport_return = PANIC;
addr->message = string_sprintf("Expansion of \"%s\" (mailstore "
"suffix for %s transport) failed: %s", ob->mailstore_suffix,
tblock->name, expand_string_message);
(void)fclose(env_file);
Uunlink(filename);
- return FALSE;
+ goto ret_panic;
}
}
else
}
+if (verify_mode)
+ {
+ addr->basic_errno = errno;
+ addr->message = US"Over quota";
+ addr->transport_return = yield;
+ DEBUG(D_transport)
+ debug_printf("appendfile (verify) yields %d with errno=%d more_errno=%d\n",
+ yield, addr->basic_errno, addr->more_errno);
+
+ goto RETURN;
+ }
+
/* If we are writing in MBX format, what we actually do is to write the message
to a temporary file, and then copy it to the real file once we know its size.
This is the most straightforward way of getting the correct length in the
put in the first address of a batch. */
return FALSE;
+
+ret_panic:
+ addr->transport_return = PANIC;
+ return FALSE;
}
#endif /*!MACRO_PREDEF*/