Project

General

Profile

0001-network_backends.h-support-darwin-sendfile_patch.txt

mackyle, 2015-12-04 08:51

 
1
From ae23ffcfef6bc303824f98c63978b29ca9d9e33f Mon Sep 17 00:00:00 2001
2
From: "Kyle J. McKay" <mackyle@gmail.com>
3
Date: Fri, 4 Dec 2015 00:41:14 -0800
4
Subject: [PATCH] network_backends.h: support darwin sendfile
5

    
6
The FreeBSD version of sendfile is already supported.  Starting
7
with OS X 10.5, Darwin also supports sendfile, but using a
8
slightly different argument list even though much of the
9
implementation is likely taken from FreeBSD just like the man
10
page is.
11

    
12
Add support for darwin's sendfile by introducing a new
13
network_darwin_sendfile.c file that's just a copy of the
14
network_freebsd_sendfile.c file except with the arguments
15
adjusted to compensate for the minor API difference (FreeBSD
16
has separate in and out byte count arguments whereas Darwin
17
has a combined in/out byte count argument).
18

    
19
Signed-off-by: Kyle J. McKay <mackyle@gmail.com>
20
---
21
 src/CMakeLists.txt            |  2 +-
22
 src/Makefile.am               |  2 +-
23
 src/SConscript                |  2 +-
24
 src/network_backends.h        | 11 +++++---
25
 src/network_darwin_sendfile.c | 61 +++++++++++++++++++++++++++++++++++++++++++
26
 src/server.c                  |  5 ++++
27
 6 files changed, 77 insertions(+), 6 deletions(-)
28
 create mode 100644 src/network_darwin_sendfile.c
29

    
30
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
31
index 4f574d9f..a4deeba8 100644
32
--- a/src/CMakeLists.txt
33
+++ b/src/CMakeLists.txt
34
@@ -494,7 +494,7 @@ set(COMMON_SRC
35
 	network_write.c network_linux_sendfile.c
36
 	network_freebsd_sendfile.c
37
 	network_solaris_sendfilev.c network_openssl.c
38
-	status_counter.c safe_memclear.c
39
+	status_counter.c safe_memclear.c network_darwin_sendfile.c
40
 )
41
 
42
 if(WIN32)
43
diff --git a/src/Makefile.am b/src/Makefile.am
44
index e7b24440..906823ec 100644
45
--- a/src/Makefile.am
46
+++ b/src/Makefile.am
47
@@ -76,7 +76,7 @@ common_src=base64.c buffer.c log.c \
48
 	network_freebsd_sendfile.c network_writev.c \
49
 	network_solaris_sendfilev.c network_openssl.c \
50
 	splaytree.c status_counter.c \
51
-	safe_memclear.c
52
+	safe_memclear.c network_darwin_sendfile.c
53
 
54
 src = server.c response.c connections.c network.c \
55
 	configfile.c configparser.c request.c proc_open.c
56
diff --git a/src/SConscript b/src/SConscript
57
index 3d873e8d..b29f4c07 100644
58
--- a/src/SConscript
59
+++ b/src/SConscript
60
@@ -28,7 +28,7 @@ common_src = Split("base64.c buffer.c log.c \
61
 	network_write.c network_linux_sendfile.c \
62
 	network_freebsd_sendfile.c  \
63
 	network_solaris_sendfilev.c network_openssl.c \
64
-	status_counter.c safe_memclear.c \
65
+	status_counter.c safe_memclear.c network_darwin_sendfile.c \
66
 ")
67
 
68
 src = Split("server.c response.c connections.c network.c \
69
diff --git a/src/network_backends.h b/src/network_backends.h
70
index 8233c488..859f9bdb 100644
71
--- a/src/network_backends.h
72
+++ b/src/network_backends.h
73
@@ -17,12 +17,17 @@
74
 # define USE_LINUX_SENDFILE
75
 #endif
76
 
77
-#if defined HAVE_SENDFILE && (defined(__FreeBSD__) || defined(__DragonFly__))
78
+#if defined HAVE_SENDFILE && (defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__))
79
 # ifdef USE_SENDFILE
80
 #  error "can't have more than one sendfile implementation"
81
 # endif
82
-# define USE_SENDFILE "freebsd-sendfile"
83
-# define USE_FREEBSD_SENDFILE
84
+# ifdef __APPLE__
85
+#  define USE_SENDFILE "darwin-sendfile"
86
+#  define USE_DARWIN_SENDFILE
87
+# else
88
+#  define USE_SENDFILE "freebsd-sendfile"
89
+#  define USE_FREEBSD_SENDFILE
90
+# endif
91
 #endif
92
 
93
 #if defined HAVE_SYS_SENDFILE_H && defined HAVE_SENDFILEV && defined(__sun)
94
diff --git a/src/network_darwin_sendfile.c b/src/network_darwin_sendfile.c
95
new file mode 100644
96
index 00000000..a249d72a
97
--- /dev/null
98
+++ b/src/network_darwin_sendfile.c
99
@@ -0,0 +1,61 @@
100
+#include "network_backends.h"
101
+
102
+#if defined(USE_DARWIN_SENDFILE)
103
+
104
+#include "network.h"
105
+#include "log.h"
106
+
107
+#include <sys/types.h>
108
+#include <sys/socket.h>
109
+#include <sys/uio.h>
110
+
111
+#include <errno.h>
112
+#include <string.h>
113
+
114
+int network_write_file_chunk_sendfile(server *srv, connection *con, int fd, chunkqueue *cq, off_t *p_max_bytes) {
115
+	chunk* const c = cq->first;
116
+	off_t offset, written = 0;
117
+	off_t toSend;
118
+	int r;
119
+
120
+	force_assert(NULL != c);
121
+	force_assert(FILE_CHUNK == c->type);
122
+	force_assert(c->offset >= 0 && c->offset <= c->file.length);
123
+
124
+	offset = c->file.start + c->offset;
125
+	toSend = c->file.length - c->offset;
126
+	if (toSend > *p_max_bytes) toSend = *p_max_bytes;
127
+
128
+	if (0 == toSend) {
129
+		chunkqueue_remove_finished_chunks(cq);
130
+		return 0;
131
+	}
132
+
133
+	if (0 != network_open_file_chunk(srv, con, cq)) return -1;
134
+
135
+	/* Darwin sendfile() */
136
+	written = toSend;
137
+	if (-1 == (r = sendfile(c->file.fd, fd, offset, &written, NULL, 0))) {
138
+		switch(errno) {
139
+		case EAGAIN:
140
+		case EINTR:
141
+			/* for EAGAIN/EINTR written still contains the sent bytes */
142
+			break; /* try again later */
143
+		case EPIPE:
144
+		case ENOTCONN:
145
+			return -2;
146
+		default:
147
+			log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
148
+			return -1;
149
+		}
150
+	}
151
+
152
+	if (written >= 0) {
153
+		chunkqueue_mark_written(cq, written);
154
+		*p_max_bytes -= written;
155
+	}
156
+
157
+	return (r >= 0 && written == toSend) ? 0 : -3;
158
+}
159
+
160
+#endif /* USE_DARWIN_SENDFILE */
161
diff --git a/src/server.c b/src/server.c
162
index d79594cd..8a563b6a 100644
163
--- a/src/server.c
164
+++ b/src/server.c
165
@@ -422,6 +422,11 @@ static void show_features (void) {
166
 #else
167
       "\t- freebsd-sendfile\n"
168
 #endif
169
+#if defined USE_DARWIN_SENDFILE
170
+      "\t+ darwin-sendfile\n"
171
+#else
172
+      "\t- darwin-sendfile\n"
173
+#endif
174
 #if defined USE_SOLARIS_SENDFILEV
175
       "\t+ solaris-sendfilev\n"
176
 #else
177
-- 
178
2.4.10
179