X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/73a4670220991e000cc31a60fc90264cf12bd981..1ac6b2e7857d7b6645dbd09047c4c2ac3b6cef1d:/src/src/transports/appendfile.c diff --git a/src/src/transports/appendfile.c b/src/src/transports/appendfile.c index e53761582..db3b5aeee 100644 --- a/src/src/transports/appendfile.c +++ b/src/src/transports/appendfile.c @@ -1,5 +1,3 @@ -/* $Cambridge: exim/src/src/transports/appendfile.c,v 1.27 2010/06/07 00:12:42 pdp Exp $ */ - /************************************************* * Exim - an Internet mail transport agent * *************************************************/ @@ -21,7 +19,7 @@ supported only if SUPPORT_MBX is set. */ enum { mbf_unix, mbf_mbx, mbf_smail, mbf_maildir, mbf_mailstore }; -static char *mailbox_formats[] = { +static const char *mailbox_formats[] = { "unix", "mbx", "smail", "maildir", "mailstore" }; @@ -38,6 +36,10 @@ stored in the publicly visible instance block - these are flagged with the opt_public flag. */ 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) }, +#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, @@ -105,7 +107,7 @@ optionlist appendfile_transport_options[] = { (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_bool, + { "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 ) }, @@ -184,6 +186,7 @@ appendfile_transport_options_block appendfile_transport_option_defaults = { NULL, /* quota_warn_threshold */ NULL, /* mailbox_size_string */ NULL, /* mailbox_filecount_string */ + NULL, /* expand_maildir_use_size_file */ US"^(?:cur|new|\\..*)$", /* maildir_dir_regex */ NULL, /* maildir_tag */ NULL, /* maildirfolder_create_regex */ @@ -272,6 +275,10 @@ dummy = dummy; uid = uid; gid = gid; +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); + /* Loop for quota, quota_filecount, quota_warn_threshold, mailbox_size, mailbox_filecount */ @@ -1764,8 +1771,14 @@ if (!isdirectory) /* We have successfully created and opened the file. Ensure that the group and the mode are correct. */ - (void)Uchown(filename, uid, gid); - (void)Uchmod(filename, mode); + if(Uchown(filename, uid, gid) || Uchmod(filename, mode)) + { + addr->basic_errno = errno; + addr->message = string_sprintf("while setting perms on mailbox %s", + filename); + addr->transport_return = FAIL; + goto RETURN; + } } @@ -2419,6 +2432,9 @@ else "%s/maildirsize", check_path); return FALSE; } + /* can also return -2, which means that the file was removed because of + raciness; but in this case, the size & filecount will still have been + updated. */ if (mailbox_size < 0) mailbox_size = size; if (mailbox_filecount < 0) mailbox_filecount = filecount; @@ -2563,8 +2579,13 @@ else /* Why are these here? Put in because they are present in the non-maildir directory case above. */ - (void)Uchown(filename, uid, gid); - (void)Uchmod(filename, mode); + if(Uchown(filename, uid, gid) || Uchmod(filename, mode)) + { + addr->basic_errno = errno; + addr->message = string_sprintf("while setting perms on maildir %s", + filename); + return FALSE; + } } #endif /* SUPPORT_MAILDIR */ @@ -2605,8 +2626,13 @@ else /* Why are these here? Put in because they are present in the non-maildir directory case above. */ - (void)Uchown(filename, uid, gid); - (void)Uchmod(filename, mode); + if(Uchown(filename, uid, gid) || Uchmod(filename, mode)) + { + addr->basic_errno = errno; + addr->message = string_sprintf("while setting perms on file %s", + filename); + return FALSE; + } /* Built a C stream from the open file descriptor. */ @@ -2697,8 +2723,13 @@ else Uunlink(filename); return FALSE; } - (void)Uchown(dataname, uid, gid); - (void)Uchmod(dataname, mode); + if(Uchown(dataname, uid, gid) || Uchmod(dataname, mode)) + { + addr->basic_errno = errno; + addr->message = string_sprintf("while setting perms on file %s", + dataname); + return FALSE; + } } #endif /* SUPPORT_MAILSTORE */ @@ -2707,8 +2738,13 @@ else /* In all cases of writing to a new file, ensure that the file which is going to be renamed has the correct ownership and mode. */ - (void)Uchown(filename, uid, gid); - (void)Uchmod(filename, mode); + if(Uchown(filename, uid, gid) || Uchmod(filename, mode)) + { + addr->basic_errno = errno; + addr->message = string_sprintf("while setting perms on file %s", + filename); + return FALSE; + } } @@ -2782,6 +2818,7 @@ if (yield == OK && ob->mbx_format) functions. */ transport_count = 0; +transport_newlines = 0; /* Write any configured prefix text first */ @@ -2807,21 +2844,26 @@ file, use its parent in the RCPT TO. */ if (yield == OK && ob->use_bsmtp) { transport_count = 0; + transport_newlines = 0; if (ob->use_crlf) cr = US"\r"; if (!transport_write_string(fd, "MAIL FROM:<%s>%s\n", return_path, cr)) yield = DEFER; else { address_item *a; + transport_newlines++; for (a = addr; a != NULL; a = a->next) { address_item *b = testflag(a, af_pfr)? a->parent: a; if (!transport_write_string(fd, "RCPT TO:<%s>%s\n", transport_rcpt_address(b, tblock->rcpt_include_affixes), cr)) { yield = DEFER; break; } + transport_newlines++; } if (yield == OK && !transport_write_string(fd, "DATA%s\n", cr)) yield = DEFER; + else + transport_newlines++; } } @@ -2854,8 +2896,10 @@ if (yield == OK && ob->message_suffix != NULL && ob->message_suffix[0] != 0) /* If batch smtp, write the terminating dot. */ -if (yield == OK && ob->use_bsmtp && - !transport_write_string(fd, ".%s\n", cr)) yield = DEFER; +if (yield == OK && ob->use_bsmtp ) { + if(!transport_write_string(fd, ".%s\n", cr)) yield = DEFER; + else transport_newlines++; +} /* If MBX format is being used, all that writing was to the temporary file. However, if there was an earlier failure (Exim quota exceeded, for example), @@ -2873,6 +2917,8 @@ if (temp_file != NULL && ob->mbx_format) if (yield == OK) { transport_count = 0; /* Reset transport count for actual write */ + /* No need to reset transport_newlines as we're just using a block copy + * routine so the number won't be affected */ yield = copy_mbx_message(fd, fileno(temp_file), saved_size); } else if (errno >= 0) dataname = US"temporary file"; @@ -2890,10 +2936,13 @@ fsync() to be called for a FIFO. */ if (yield == OK && !isfifo && EXIMfsync(fd) < 0) yield = DEFER; -/* Update message_size to the accurate count of bytes written, including -added headers. */ +/* Update message_size and message_linecount to the accurate count of bytes +written, including added headers. Note; we subtract 1 from message_linecount as +this variable doesn't count the new line between the header and the body of the +message. */ message_size = transport_count; +message_linecount = transport_newlines - 1; /* If using a maildir++ quota file, add this message's size to it, and close the file descriptor, except when the quota has been disabled because we @@ -2905,7 +2954,8 @@ if (!disable_quota) if (yield == OK && maildirsize_fd >= 0) maildir_record_length(maildirsize_fd, message_size); maildir_save_errno = errno; /* Preserve errno while closing the file */ - (void)close(maildirsize_fd); + if (maildirsize_fd >= 0) + (void)close(maildirsize_fd); errno = maildir_save_errno; } #endif /* SUPPORT_MAILDIR */ @@ -3071,7 +3121,8 @@ if (yield != OK) investigated so far have ftruncate(), whereas not all have the F_FREESP fcntl() call (BSDI & FreeBSD do not). */ - if (!isdirectory) (void)ftruncate(fd, saved_size); + if (!isdirectory && ftruncate(fd, saved_size)) + DEBUG(D_transport) debug_printf("Error restting file size\n"); } /* Handle successful writing - we want the modification time to be now for