httpd: shrink mime type matching code (suggested by Bernhard)

function                                             old     new   delta
static.suffixTable                                   100     231    +131
send_file_and_exit                                   625     658     +33
handle_incoming_and_exit                            2749    2745      -4
send_cgi_and_exit                                    936     901     -35
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/2 up/down: 164/-39)           Total: 125 bytes
   text    data     bss     dec     hex filename
 824631     458    6956  832045   cb22d busybox_old
 824550     458    6956  831964   cb1dc busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2009-09-10 01:46:02 +02:00
parent d069e5398d
commit 33d8d08f78
2 changed files with 56 additions and 43 deletions

View File

@ -15,7 +15,7 @@
* Return TRUE if fileName is a directory. * Return TRUE if fileName is a directory.
* Nonexistent files return FALSE. * Nonexistent files return FALSE.
*/ */
int FAST_FUNC is_directory(const char *fileName, const int followLinks, struct stat *statBuf) int FAST_FUNC is_directory(const char *fileName, int followLinks, struct stat *statBuf)
{ {
int status; int status;
struct stat astatBuf; struct stat astatBuf;

View File

@ -20,14 +20,14 @@
* httpd -p 80 -u 80 -h /www -c /etc/httpd.conf -r "Web Server Authentication" * httpd -p 80 -u 80 -h /www -c /etc/httpd.conf -r "Web Server Authentication"
* *
* *
* When a url starts by "/cgi-bin/" it is assumed to be a cgi script. The * When an url starts by "/cgi-bin/" it is assumed to be a cgi script. The
* server changes directory to the location of the script and executes it * server changes directory to the location of the script and executes it
* after setting QUERY_STRING and other environment variables. * after setting QUERY_STRING and other environment variables.
* *
* Doc: * Doc:
* "CGI Environment Variables": http://hoohoo.ncsa.uiuc.edu/cgi/env.html * "CGI Environment Variables": http://hoohoo.ncsa.uiuc.edu/cgi/env.html
* *
* The applet can also be invoked as a url arg decoder and html text encoder * The applet can also be invoked as an url arg decoder and html text encoder
* as follows: * as follows:
* foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World" * foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World"
* bar=`httpd -e "<Hello World>"` # encode as "&#60Hello&#32World&#62" * bar=`httpd -e "<Hello World>"` # encode as "&#60Hello&#32World&#62"
@ -1325,10 +1325,8 @@ static void send_cgi_and_exit(
/* Check for [dirs/]script.cgi/PATH_INFO */ /* Check for [dirs/]script.cgi/PATH_INFO */
script = (char*)url; script = (char*)url;
while ((script = strchr(script + 1, '/')) != NULL) { while ((script = strchr(script + 1, '/')) != NULL) {
struct stat sb;
*script = '\0'; *script = '\0';
if (!is_directory(url + 1, 1, &sb)) { if (!is_directory(url + 1, 1, NULL)) {
/* not directory, found script.cgi/PATH_INFO */ /* not directory, found script.cgi/PATH_INFO */
*script = '/'; *script = '/';
break; break;
@ -1504,32 +1502,8 @@ static void send_cgi_and_exit(
*/ */
static NOINLINE void send_file_and_exit(const char *url, int what) static NOINLINE void send_file_and_exit(const char *url, int what)
{ {
static const char *const suffixTable[] = {
/* Warning: shorter equivalent suffix in one line must be first */
".htm.html", "text/html",
".jpg.jpeg", "image/jpeg",
".gif", "image/gif",
".png", "image/png",
".txt.h.c.cc.cpp", "text/plain",
".css", "text/css",
".wav", "audio/wav",
".avi", "video/x-msvideo",
".qt.mov", "video/quicktime",
".mpe.mpeg", "video/mpeg",
".mid.midi", "audio/midi",
".mp3", "audio/mpeg",
#if 0 /* unpopular */
".au", "audio/basic",
".pac", "application/x-ns-proxy-autoconfig",
".vrml.wrl", "model/vrml",
#endif
NULL
};
char *suffix; char *suffix;
int fd; int fd;
const char *const *table;
const char *try_suffix;
ssize_t count; ssize_t count;
fd = open(url, O_RDONLY); fd = open(url, O_RDONLY);
@ -1547,22 +1521,61 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
* (happens if you abort downloads from local httpd): */ * (happens if you abort downloads from local httpd): */
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
suffix = strrchr(url, '.'); /* If not found, default is "application/octet-stream" */
/* If not found, set default as "application/octet-stream"; */
found_mime_type = "application/octet-stream"; found_mime_type = "application/octet-stream";
suffix = strrchr(url, '.');
if (suffix) { if (suffix) {
static const char suffixTable[] ALIGN1 =
/* Shorter suffix must be first:
* ".html.htm" will fail for ".htm"
*/
".txt.h.c.cc.cpp\0" "text/plain\0"
/* .htm line must be after .h line */
".htm.html\0" "text/html\0"
".jpg.jpeg\0" "image/jpeg\0"
".gif\0" "image/gif\0"
".png\0" "image/png\0"
/* .css line must be after .c line */
".css\0" "text/css\0"
".wav\0" "audio/wav\0"
".avi\0" "video/x-msvideo\0"
".qt.mov\0" "video/quicktime\0"
".mpe.mpeg\0" "video/mpeg\0"
".mid.midi\0" "audio/midi\0"
".mp3\0" "audio/mpeg\0"
#if 0 /* unpopular */
".au\0" "audio/basic\0"
".pac\0" "application/x-ns-proxy-autoconfig\0"
".vrml.wrl\0" "model/vrml\0"
#endif
/* compiler adds another "\0" here */
;
Htaccess *cur; Htaccess *cur;
for (table = suffixTable; *table; table += 2) {
try_suffix = strstr(table[0], suffix); /* Examine built-in table */
if (try_suffix) { const char *table = suffixTable;
const char *table_next;
for (; *table; table = table_next) {
const char *try_suffix;
const char *mime_type;
mime_type = table + strlen(table) + 1;
table_next = mime_type + strlen(mime_type) + 1;
try_suffix = strstr(table, suffix);
if (!try_suffix)
continue;
try_suffix += strlen(suffix); try_suffix += strlen(suffix);
if (*try_suffix == '\0' || *try_suffix == '.') { if (*try_suffix == '\0' || *try_suffix == '.') {
found_mime_type = table[1]; found_mime_type = mime_type;
break; break;
} }
/* Example: strstr(table, ".av") != NULL, but it
* does not match ".avi" after all and we end up here.
* The table is arranged so that in this case we know
* that it can't match anything in the following lines,
* and we stop the search: */
break;
} }
} /* ...then user's table */
for (cur = mime_a; cur; cur = cur->next) { for (cur = mime_a; cur; cur = cur->next) {
if (strcmp(cur->before_colon, suffix) == 0) { if (strcmp(cur->before_colon, suffix) == 0) {
found_mime_type = cur->after_colon; found_mime_type = cur->after_colon;
@ -1919,7 +1932,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
/* If URL is a directory, add '/' */ /* If URL is a directory, add '/' */
if (urlp[-1] != '/') { if (urlp[-1] != '/') {
if (is_directory(urlcopy + 1, 1, &sb)) { if (is_directory(urlcopy + 1, 1, NULL)) {
found_moved_temporarily = urlcopy; found_moved_temporarily = urlcopy;
} }
} }
@ -1933,7 +1946,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
while (ip_allowed && (tptr = strchr(tptr + 1, '/')) != NULL) { while (ip_allowed && (tptr = strchr(tptr + 1, '/')) != NULL) {
/* have path1/path2 */ /* have path1/path2 */
*tptr = '\0'; *tptr = '\0';
if (is_directory(urlcopy + 1, 1, &sb)) { if (is_directory(urlcopy + 1, 1, NULL)) {
/* may have subdir config */ /* may have subdir config */
parse_conf(urlcopy + 1, SUBDIR_PARSE); parse_conf(urlcopy + 1, SUBDIR_PARSE);
ip_allowed = checkPermIP(); ip_allowed = checkPermIP();