From 7d8758598f49d5569018064f8824164a6a08eca7 Mon Sep 17 00:00:00 2001 From: Jan Kneschke Date: Tue, 22 Nov 2005 11:21:35 +0000 Subject: [PATCH] - init FAM after fdevent-backend is up - open + fstat instead of stat + open for speed reasons - only init FAM if requested by config git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-merge-1.4.x@872 152afb58-edef-0310-8abb-c4023f1b3aa9 --- src/server.c | 44 +++++++++++++++++++++++++------------------- src/stat_cache.c | 37 ++++++++++++++++++++++--------------- 2 files changed, 47 insertions(+), 34 deletions(-) diff --git a/src/server.c b/src/server.c index d3c26587..66c5ef26 100644 --- a/src/server.c +++ b/src/server.c @@ -763,24 +763,6 @@ int main (int argc, char **argv) { getitimer(ITIMER_REAL, &interval); #endif - /* might fail if user is using fam (not gamin) and famd isn't running */ - if (NULL == (srv->stat_cache = stat_cache_init())) { -#if defined(HAVE_FAM_H) && !defined(HAVE_FAMNOEXISTS) - log_error_write(srv, __FILE__, __LINE__, "s", - "FAMOpen2() failed. Is famd running?"); - return -1; -#else - SEGFAULT(); -#endif - } - -#ifdef HAVE_FAM_H - /* setup FAM */ - srv->stat_cache->fam_fcce_ndx = -1; - fdevent_register(srv->ev, FAMCONNECTION_GETFD(srv->stat_cache->fam), stat_cache_handle_fdevent, NULL); - fdevent_event_add(srv->ev, &(srv->stat_cache->fam_fcce_ndx), FAMCONNECTION_GETFD(srv->stat_cache->fam), FDEVENT_IN); -#endif - #ifdef HAVE_FORK /* start watcher and workers */ num_childs = srv->srvconf.max_worker; @@ -828,7 +810,31 @@ int main (int argc, char **argv) { return -1; } - + + /* might fail if user is using fam (not gamin) and famd isn't running */ + if (NULL == (srv->stat_cache = stat_cache_init())) { + log_error_write(srv, __FILE__, __LINE__, "s", + "stat-cache could not be setup, dieing."); + return -1; + } + +#ifdef HAVE_FAM_H + /* setup FAM */ + if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) { + if (0 != FAMOpen2(srv->stat_cache->fam, "lighttpd")) { + return -1; + } +#ifdef HAVE_FAMNOEXISTS + FAMNoExists(srv->stat_cache->fam); +#endif + + srv->stat_cache->fam_fcce_ndx = -1; + fdevent_register(srv->ev, FAMCONNECTION_GETFD(srv->stat_cache->fam), stat_cache_handle_fdevent, NULL); + fdevent_event_add(srv->ev, &(srv->stat_cache->fam_fcce_ndx), FAMCONNECTION_GETFD(srv->stat_cache->fam), FDEVENT_IN); + } +#endif + + /* get the current number of FDs */ srv->cur_fds = open("/dev/null", O_RDONLY); close(srv->cur_fds); diff --git a/src/stat_cache.c b/src/stat_cache.c index 5b9950a9..f12202e2 100644 --- a/src/stat_cache.c +++ b/src/stat_cache.c @@ -111,13 +111,6 @@ stat_cache *stat_cache_init(void) { fc->dir_name = buffer_init(); #ifdef HAVE_FAM_H fc->fam = calloc(1, sizeof(*fc->fam)); - - if (0 != FAMOpen2(fc->fam, "lighttpd")) { - return NULL; - } -#ifdef HAVE_FAMNOEXISTS - FAMNoExists(fc->fam); -#endif #endif #ifdef DEBUG_STAT_CACHE @@ -354,6 +347,7 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ stat_cache *sc; struct stat st; size_t k; + int fd; #ifdef DEBUG_STAT_CACHE size_t i; #endif @@ -452,20 +446,18 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ } } #endif - if (-1 == (con->conf.follow_symlink ? stat(name->ptr, &st) : lstat(name->ptr, &st))) { - /* stat() failed, ENOENT, ... and so on */ + /* try to open the file */ + if (-1 == (fd = open(name->ptr, O_RDONLY))) { return HANDLER_ERROR; } - if (S_ISREG(st.st_mode)) { - int fd; - /* see if we can open the file for reading */ - if (-1 == (fd = open(name->ptr, O_RDONLY))) { - return HANDLER_ERROR; - } + if (-1 == fstat(fd, &st)) { close(fd); + return HANDLER_ERROR; } + close(fd); + if (NULL == sce) { int osize = 0; @@ -498,6 +490,21 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ sce->st = st; sce->stat_ts = srv->cur_ts; + /* catch the obvious symlinks + * + * this is not a secure check as we still have a race-condition between + * the stat() and the open. We can only solve this by + * 1. open() the file + * 2. fstat() the fd + * + * and keeping the file open for the rest of the time. But this can + * only be done at network level. + * + * */ + if (S_ISLNK(st.st_mode) && !con->conf.follow_symlink) { + return HANDLER_ERROR; + } + if (S_ISREG(st.st_mode)) { /* determine mimetype */ buffer_reset(sce->content_type);