From 33d8d08f7818a6d10e14ad8397c61adfcd377a6f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 10 Sep 2009 01:46:02 +0200 Subject: [PATCH] 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 --- libbb/isdirectory.c | 2 +- networking/httpd.c | 97 +++++++++++++++++++++++++-------------------- 2 files changed, 56 insertions(+), 43 deletions(-) diff --git a/libbb/isdirectory.c b/libbb/isdirectory.c index 28ed3ec29..4a2961e0d 100644 --- a/libbb/isdirectory.c +++ b/libbb/isdirectory.c @@ -15,7 +15,7 @@ * Return TRUE if fileName is a directory. * 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; struct stat astatBuf; diff --git a/networking/httpd.c b/networking/httpd.c index 07dcd71ff..a2a52b58a 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -20,14 +20,14 @@ * 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 * after setting QUERY_STRING and other environment variables. * * Doc: * "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: * foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World" * bar=`httpd -e ""` # encode as "<Hello World>" @@ -1325,10 +1325,8 @@ static void send_cgi_and_exit( /* Check for [dirs/]script.cgi/PATH_INFO */ script = (char*)url; while ((script = strchr(script + 1, '/')) != NULL) { - struct stat sb; - *script = '\0'; - if (!is_directory(url + 1, 1, &sb)) { + if (!is_directory(url + 1, 1, NULL)) { /* not directory, found script.cgi/PATH_INFO */ *script = '/'; break; @@ -1504,32 +1502,8 @@ static void send_cgi_and_exit( */ 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; int fd; - const char *const *table; - const char *try_suffix; ssize_t count; 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): */ signal(SIGPIPE, SIG_IGN); - suffix = strrchr(url, '.'); - - /* If not found, set default as "application/octet-stream"; */ + /* If not found, default is "application/octet-stream" */ found_mime_type = "application/octet-stream"; + suffix = strrchr(url, '.'); 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; - for (table = suffixTable; *table; table += 2) { - try_suffix = strstr(table[0], suffix); - if (try_suffix) { - try_suffix += strlen(suffix); - if (*try_suffix == '\0' || *try_suffix == '.') { - found_mime_type = table[1]; - break; - } + + /* Examine built-in table */ + 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); + if (*try_suffix == '\0' || *try_suffix == '.') { + found_mime_type = mime_type; + 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) { if (strcmp(cur->before_colon, suffix) == 0) { 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 (urlp[-1] != '/') { - if (is_directory(urlcopy + 1, 1, &sb)) { + if (is_directory(urlcopy + 1, 1, NULL)) { 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) { /* have path1/path2 */ *tptr = '\0'; - if (is_directory(urlcopy + 1, 1, &sb)) { + if (is_directory(urlcopy + 1, 1, NULL)) { /* may have subdir config */ parse_conf(urlcopy + 1, SUBDIR_PARSE); ip_allowed = checkPermIP(); -- 2.25.1