-/* $Cambridge: exim/src/src/transport.c,v 1.12 2005/06/27 14:29:44 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transport.c,v 1.19 2007/01/08 10:50:18 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) University of Cambridge 1995 - 2007 */
/* See the file NOTICE for conditions of use and distribution. */
/* General functions concerned with transportation, and generic options for all
#include "exim.h"
+#ifdef HAVE_LINUX_SENDFILE
+#include <sys/sendfile.h>
+#endif
/* Structure for keeping list of addresses that have been added to
Envelope-To:, in order to avoid duplication. */
int sread = 0;
int wwritten = 0;
uschar *dk_signature = NULL;
+ off_t size = 0;
- snprintf(CS dk_spool_name, 256, "%s/input/%s/%s-K",
- spool_directory, message_subdir, message_id);
- dk_fd = Uopen(dk_spool_name, O_RDWR|O_CREAT|O_EXCL, SPOOL_MODE);
+ (void)string_format(dk_spool_name, 256, "%s/input/%s/%s-%d-K",
+ spool_directory, message_subdir, message_id, (int)getpid());
+ dk_fd = Uopen(dk_spool_name, O_RDWR|O_CREAT|O_TRUNC, SPOOL_MODE);
if (dk_fd < 0)
{
/* Can't create spool file. Ugh. */
}
}
- /* Rewind file and send it down the original fd. */
+ /* Fetch file positition (the size) */
+ size = lseek(dk_fd,0,SEEK_CUR);
+
+ /* Rewind file */
lseek(dk_fd, 0, SEEK_SET);
+#ifdef HAVE_LINUX_SENDFILE
+ /* We can use sendfile() to shove the file contents
+ to the socket. However only if we don't use TLS,
+ in which case theres another layer of indirection
+ before the data finally hits the socket. */
+ if (tls_active != fd)
+ {
+ ssize_t copied = 0;
+ off_t offset = 0;
+ while((copied >= 0) && (offset<size))
+ {
+ copied = sendfile(fd, dk_fd, &offset, (size - offset));
+ }
+ if (copied < 0)
+ {
+ save_errno = errno;
+ rc = FALSE;
+ }
+ goto CLEANUP;
+ }
+#endif
+
+ /* Send file down the original fd */
while((sread = read(dk_fd,sbuf,2048)) > 0)
{
char *p = sbuf;
goto CLEANUP;
}
-
CLEANUP:
/* unlink -K file */
(void)close(dk_fd);
Old records should eventually get swept up by the exim_tidydb utility.
Arguments:
- hostlist list of hosts that this message could be sent to;
- the update_waiting flag is set if a host is to be noted
+ hostlist list of hosts that this message could be sent to
tpname name of the transport
Returns: nothing
open_db dbblock;
open_db *dbm_file;
+DEBUG(D_transport) debug_printf("updating wait-%s database\n", tpname);
+
/* Open the database for this transport */
sprintf(CS buffer, "wait-%.200s", tpname);
if (dbm_file == NULL) return;
/* Scan the list of hosts for which this message is waiting, and ensure
-that the message id is in each host record for those that have the
-update_waiting flag set. */
+that the message id is in each host record. */
for (host = hostlist; host!= NULL; host = host->next)
{
uschar *s;
int i, host_length;
- /* Skip if the update_waiting flag is not set. */
-
- if (!host->update_waiting) continue;
-
/* Skip if this is the same host as we just processed; otherwise remember
the name for next time. */
/* If this message is already in a record, no need to update. */
- if (already) continue;
+ if (already)
+ {
+ DEBUG(D_transport) debug_printf("already listed for %s\n", host->name);
+ continue;
+ }
/* If this record is full, write it out with a new name constructed
/* Update the database */
dbfn_write(dbm_file, host->name, host_record, sizeof(dbdata_wait) + host_length);
+ DEBUG(D_transport) debug_printf("added to list for %s\n", host->name);
}
/* All now done */
automatic comparison. */
if ((pid = fork()) != 0) _exit(EXIT_SUCCESS);
- if (running_in_test_harness) millisleep(500);
+ if (running_in_test_harness) sleep(1);
/* Set up the calling arguments; use the standard function for the basics,
but we have a number of extras that may be added. */