X-Git-Url: https://git.exim.org/users/jgh/exim.git/blobdiff_plain/554e333ebbe0552b61604cdf8fec77f507a3ab9b..4c04137d73637107669e02b21f890387aaa2ef34:/src/src/transports/appendfile.c diff --git a/src/src/transports/appendfile.c b/src/src/transports/appendfile.c index 39dd4f8f0..9b3379be2 100644 --- a/src/src/transports/appendfile.c +++ b/src/src/transports/appendfile.c @@ -1,10 +1,8 @@ -/* $Cambridge: exim/src/src/transports/appendfile.c,v 1.27 2010/06/07 00:12:42 pdp Exp $ */ - /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2009 */ +/* Copyright (c) University of Cambridge 1995 - 2016 */ /* See the file NOTICE for conditions of use and distribution. */ @@ -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 */ @@ -612,19 +619,18 @@ if (host_find_byname(&host, NULL, 0, NULL, FALSE) == HOST_FIND_FAILED) host.address = US"127.0.0.1"; -for (h = &host; h != NULL; h = h->next) +for (h = &host; h; h = h->next) { int sock, rc; - int host_af = (Ustrchr(h->address, ':') != NULL)? AF_INET6 : AF_INET; + int host_af = Ustrchr(h->address, ':') != NULL ? AF_INET6 : AF_INET; DEBUG(D_transport) debug_printf("calling comsat on %s\n", h->address); - sock = ip_socket(SOCK_DGRAM, host_af); - if (sock < 0) continue; + if ((sock = ip_socket(SOCK_DGRAM, host_af)) < 0) continue; /* Connect never fails for a UDP socket, so don't set a timeout. */ - (void)ip_connect(sock, host_af, h->address, ntohs(sp->s_port), 0); + (void)ip_connect(sock, host_af, h->address, ntohs(sp->s_port), 0, FALSE); rc = send(sock, buffer, Ustrlen(buffer) + 1, 0); (void)close(sock); @@ -657,7 +663,7 @@ Returns: pointer to the required transport, or NULL transport_instance * check_file_format(int cfd, transport_instance *tblock, address_item *addr) { -uschar *format = +const uschar *format = ((appendfile_transport_options_block *)(tblock->options_block))->file_format; uschar data[256]; int len = read(cfd, data, sizeof(data)); @@ -672,15 +678,16 @@ if (len == 0) return tblock; /* Search the formats for a match */ -while ((s = string_nextinlist(&format,&sep,big_buffer,big_buffer_size))!= NULL) +while ((s = string_nextinlist(&format,&sep,big_buffer,big_buffer_size))) { int slen = Ustrlen(s); BOOL match = len >= slen && Ustrncmp(data, s, slen) == 0; uschar *tp = string_nextinlist(&format, &sep, big_buffer, big_buffer_size); - if (match) + + if (match && tp) { transport_instance *tt; - for (tt = transports; tt != NULL; tt = tt->next) + for (tt = transports; tt; tt = tt->next) if (Ustrcmp(tp, tt->name) == 0) { DEBUG(D_transport) @@ -1139,7 +1146,7 @@ directory name) is given, that is, when appending to a single file: Open with O_WRONLY + O_EXCL + O_CREAT with configured mode, unless we know this is via a symbolic link (only possible if allow_symlinks is set), in - which case don't use O_EXCL, as it dosn't work. + which case don't use O_EXCL, as it doesn't work. If open fails because the file already exists, go to (6f). To avoid looping for ever in a situation where the file is continuously being @@ -1613,6 +1620,7 @@ if (!isdirectory) if (ob->use_lockfile) { + /* cf. exim_lock.c */ lockname = string_sprintf("%s.lock", filename); hitchname = string_sprintf( "%s.%s.%08x.%08x", lockname, primary_hostname, (unsigned int)(time(NULL)), (unsigned int)getpid()); @@ -1764,8 +1772,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; + } } @@ -2526,8 +2540,8 @@ else uschar *basename; (void)gettimeofday(&msg_tv, NULL); - basename = string_sprintf("%lu.H%luP%lu.%s", msg_tv.tv_sec, - msg_tv.tv_usec, getpid(), primary_hostname); + basename = string_sprintf(TIME_T_FMT ".H%luP%lu.%s", + msg_tv.tv_sec, msg_tv.tv_usec, getpid(), primary_hostname); filename = dataname = string_sprintf("tmp/%s", basename); newname = string_sprintf("new/%s", basename); @@ -2566,8 +2580,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 */ @@ -2608,8 +2627,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. */ @@ -2700,8 +2724,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 */ @@ -2710,8 +2739,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; + } } @@ -2839,9 +2873,14 @@ at initialization time. */ if (yield == OK) { - if (!transport_write_message(addr, fd, ob->options, 0, tblock->add_headers, - tblock->remove_headers, ob->check_string, ob->escape_string, - tblock->rewrite_rules, tblock->rewrite_existflags)) + transport_ctx tctx = { + tblock, + addr, + ob->check_string, + ob->escape_string, + ob->options + }; + if (!transport_write_message(fd, &tctx, 0)) yield = DEFER; } @@ -3088,7 +3127,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 resetting file size\n"); } /* Handle successful writing - we want the modification time to be now for