Hi,

Here is a small patch to enable the use of the linux kernel function 
sendfile() in the httpd server (the last remaining TODO in network/httpd.c). 
This is enabled by a configuration option, disabled by default.


Without enabling sendfile feature:
$ make bloatcheck
function                                             old     new   delta
sendFile                                             252     247      -5
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-5)               Total: -5 bytes
   text    data     bss     dec     hex filename
  87684    1068   10280   99032   182d8 busybox_old
  87668    1068   10280   99016   182c8 busybox_unstripped

With sendfile feature enabled:
$ make bloatcheck
function                                             old     new   delta
sendFile                                             252     294     +42
.rodata                                             9715    9747     +32
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 74/0)               Total: 74 bytes
   text    data     bss     dec     hex filename
  87684    1068   10280   99032   182d8 busybox_old
  87805    1072   10280   99157   18355 busybox_unstripped

-- Pierre Métras
Index: networking/httpd.c
===================================================================
--- networking/httpd.c	(revision 19418)
+++ networking/httpd.c	(working copy)
@@ -92,6 +92,9 @@
 */
 
 #include "libbb.h"
+#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
+#include <sys/sendfile.h>
+#endif
 
 /* amount of buffering in a pipe */
 #ifndef PIPE_BUF
@@ -922,15 +925,15 @@
 	len += 2;
 	if (infoString) {
 		len += sprintf(buf+len,
-				"<HEAD><TITLE>%d %s</TITLE></HEAD>\n"
-				"<BODY><H1>%d %s</H1>\n%s\n</BODY>\n",
+				"<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n"
+				"<BODY><H1>%d %s</H1>\n%s\n</BODY></HTML>\n",
 				responseNum, responseString,
 				responseNum, responseString, infoString);
 	}
 	if (DEBUG)
 		fprintf(stderr, "headers: '%s'\n", buf);
 	i = accepted_socket;
-	if (i == 0) i++; /* write to fd# 1 in inetd mode */
+	if (i == 0) i++; /* write to fd #1 in inetd mode */
 	return full_write(i, buf, len);
 }
 
@@ -1360,17 +1363,24 @@
 
 	f = open(url, O_RDONLY);
 	if (f >= 0) {
+		sendHeaders(HTTP_OK);
+		int fd = accepted_socket;
+		if (fd == 0) fd++; /* write to fd #1 in inetd mode */
+#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
+		struct stat f_stat;
+		if (fstat(f, &f_stat)) {
+			bb_perror_msg("cannot stat file '%s'", url);
+		}
+		off_t offset = 0;
+		sendfile(fd, f, &offset, f_stat.st_size);
+#else
 		int count;
 		char *buf = iobuf;
-
-		sendHeaders(HTTP_OK);
-		/* TODO: sendfile() */
 		while ((count = full_read(f, buf, MAX_MEMORY_BUFF)) > 0) {
-			int fd = accepted_socket;
-			if (fd == 0) fd++; /* write to fd# 1 in inetd mode */
 			if (full_write(fd, buf, count) != count)
 				break;
 		}
+#endif
 		close(f);
 	} else {
 		if (DEBUG)
@@ -1673,11 +1683,11 @@
 				if ((STRNCASECMP(buf, "Content-length:") == 0)) {
 					/* extra read only for POST */
 					if (prequest != request_GET) {
-						test = buf + sizeof("Content-length:")-1;
+						test = buf + sizeof("Content-length:") - 1;
 						if (!test[0])
 							goto bail_out;
 						errno = 0;
-						/* not using strtoul: it ignores leading munis! */
+						/* not using strtoul: it ignores leading minus! */
 						length = strtol(test, &test, 10);
 						/* length is "ulong", but we need to pass it to int later */
 						/* so we check for negative or too large values in one go: */
Index: networking/Config.in
===================================================================
--- networking/Config.in	(revision 19418)
+++ networking/Config.in	(working copy)
@@ -83,6 +83,14 @@
 	help
 	  Serve web pages via an HTTP server.
 
+config FEATURE_HTTPD_USE_SENDFILE
+	bool "Use sendfile system call"
+	default n
+	depends on HTTPD
+	help
+	  When enabled, httpd will use the kernel sendfile() function
+	  instead of emulating it in user space.
+
 config FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP
 	bool "Support reloading the global config file using hup signal"
 	default n
_______________________________________________
busybox mailing list
busybox@busybox.net
http://busybox.net/cgi-bin/mailman/listinfo/busybox

Reply via email to