andi            Mon Oct  4 20:42:25 2004 EDT

  Modified files:              
    /TSRM       tsrm_virtual_cwd.c tsrm_virtual_cwd.h 
    /php-src/main       SAPI.c main.c 
  Log:
  - Apply realpath() cache patch. We don't use it if we're in safe_mode and
  - friends (which are quite slow anyway).
  - If it proves to be stable I'll remove the #ifdef's in a few weeks.
  
  
http://cvs.php.net/diff.php/TSRM/tsrm_virtual_cwd.c?r1=1.62&r2=1.63&ty=u
Index: TSRM/tsrm_virtual_cwd.c
diff -u TSRM/tsrm_virtual_cwd.c:1.62 TSRM/tsrm_virtual_cwd.c:1.63
--- TSRM/tsrm_virtual_cwd.c:1.62        Tue Mar  9 09:56:34 2004
+++ TSRM/tsrm_virtual_cwd.c     Mon Oct  4 20:42:25 2004
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: tsrm_virtual_cwd.c,v 1.62 2004/03/09 14:56:34 iliaa Exp $ */
+/* $Id: tsrm_virtual_cwd.c,v 1.63 2004/10/05 00:42:25 andi Exp $ */
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -60,9 +60,9 @@
 #endif
 
 #ifdef ZTS
-static ts_rsrc_id cwd_globals_id;
+ts_rsrc_id cwd_globals_id;
 #else
-static virtual_cwd_globals cwd_globals;
+virtual_cwd_globals cwd_globals;
 #endif
 
 cwd_state main_cwd_state; /* True global */
@@ -175,11 +175,31 @@
 static void cwd_globals_ctor(virtual_cwd_globals *cwd_globals TSRMLS_DC)
 {
        CWD_STATE_COPY(&cwd_globals->cwd, &main_cwd_state);
+#ifdef REALPATH_CACHE
+       cwd_globals->realpath_cache_size = 0;
+       cwd_globals->realpath_cache_size_limit = REALPATH_CACHE_SIZE;
+       cwd_globals->realpath_cache_ttl = REALPATH_CACHE_TTL;
+       memset(cwd_globals->realpath_cache, 0, sizeof(cwd_globals->realpath_cache));
+#endif
 }
 
 static void cwd_globals_dtor(virtual_cwd_globals *cwd_globals TSRMLS_DC)
 {
        CWD_STATE_FREE(&cwd_globals->cwd);
+#ifdef REALPATH_CACHE
+       {
+               int i;
+
+               for (i = 0; i < 
sizeof(cwd_globals->realpath_cache)/sizeof(cwd_globals->realpath_cache[0]); i++) {
+                       realpath_cache_bucket *p = cwd_globals->realpath_cache[i];
+                       while (p != NULL) {
+                               realpath_cache_bucket *r = p;
+                               p = p->next;
+                               free(r);
+                       }
+               }
+       }
+#endif
 }
 
 static char *tsrm_strndup(const char *s, size_t length)
@@ -287,6 +307,65 @@
        return buf;
 }
 
+#ifdef REALPATH_CACHE
+static inline unsigned long realpath_cache_key(const char *path, int path_len)
+{
+  register unsigned long h;
+
+  const char *e = path + path_len;
+  for (h = 2166136261U; path < e; ) {
+    h *= 16777619;
+    h ^= *path++;
+  }
+  return h;
+}
+
+static inline void realpath_cache_add(const char *path, int path_len, const char 
*realpath, int realpath_len, time_t t TSRMLS_DC)
+{
+       long size = sizeof(realpath_cache_bucket) + path_len + 1 + realpath_len + 1;
+       if (CWDG(realpath_cache_size) + size <= CWDG(realpath_cache_size_limit)) {
+               realpath_cache_bucket *bucket = malloc(size);
+               unsigned long n;
+       
+               bucket->key = realpath_cache_key(path, path_len);
+               bucket->path = (char*)bucket + sizeof(realpath_cache_bucket);
+               memcpy(bucket->path, path, path_len+1);
+               bucket->path_len = path_len;
+               bucket->realpath = bucket->path + (path_len + 1);
+               memcpy(bucket->realpath, realpath, realpath_len+1);
+               bucket->realpath_len = realpath_len;
+               bucket->expires = t + CWDG(realpath_cache_ttl);
+               n = bucket->key % (sizeof(CWDG(realpath_cache)) / 
sizeof(CWDG(realpath_cache)[0]));
+               bucket->next = CWDG(realpath_cache)[n];
+               CWDG(realpath_cache)[n] = bucket;
+         CWDG(realpath_cache_size) += size;
+       }
+}
+
+static inline realpath_cache_bucket* realpath_cache_find(const char *path, int 
path_len, time_t t TSRMLS_DC)
+{
+       unsigned long key = realpath_cache_key(path, path_len);
+       unsigned long n = key % (sizeof(CWDG(realpath_cache)) / 
sizeof(CWDG(realpath_cache)[0]));
+       realpath_cache_bucket **bucket = &CWDG(realpath_cache)[n];
+
+       while (*bucket != NULL) {
+               if (CWDG(realpath_cache_ttl) && (*bucket)->expires < t) {
+                       realpath_cache_bucket *r = *bucket;
+                 *bucket = (*bucket)->next;
+                 CWDG(realpath_cache_size) -= sizeof(realpath_cache_bucket) + 
r->path_len + 1 + r->realpath_len + 1;
+                 free(r);
+               } else if (key == (*bucket)->key && path_len == (*bucket)->path_len &&
+                          memcmp(path, (*bucket)->path, path_len) == 0) {
+                       return *bucket;
+               } else {
+                       *bucket = (*bucket)->next;
+               }
+       }
+       return NULL;
+}
+#endif
+
+
 /* Resolve path relatively to state and put the real path into state */
 /* returns 0 for ok, 1 for error */
 CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func 
verify_path, int use_realpath)
@@ -295,7 +374,7 @@
        char *ptr, *path_copy;
        char *tok = NULL;
        int ptr_length;
-       cwd_state *old_state;
+       cwd_state old_state;
        int ret = 0;
        int copy_amount = -1;
        char *free_path;
@@ -305,10 +384,50 @@
 #else
        char *new_path;
 #endif
+#ifdef REALPATH_CACHE
+       char orig_path[MAXPATHLEN];
+       int orig_path_len;
+       realpath_cache_bucket *bucket;
+       time_t t;
+       TSRMLS_FETCH();
+#endif
 
        if (path_length == 0) 
                return (0);
 
+#ifdef REALPATH_CACHE
+       if (use_realpath && CWDG(realpath_cache_size_limit)) {
+               if (IS_ABSOLUTE_PATH(path, path_length) || (state->cwd_length < 1)) {
+                       memcpy(orig_path, path, path_length+1);
+                       orig_path_len = path_length;
+               } else {
+                       orig_path_len = path_length + state->cwd_length + 1;
+                       if (orig_path_len+1 > MAXPATHLEN) {
+                               return 1;
+                       }
+                       memcpy(orig_path, state->cwd, state->cwd_length);
+                       orig_path[state->cwd_length] = DEFAULT_SLASH;
+                       memcpy(orig_path + state->cwd_length + 1, path, path_length + 
1);
+               }
+               t = CWDG(realpath_cache_ttl)?time(NULL):0;
+               if ((bucket = realpath_cache_find(orig_path, orig_path_len, t 
TSRMLS_CC)) != NULL) {            
+                       int len = bucket->realpath_len;
+
+                       CWD_STATE_COPY(&old_state, state);
+                       state->cwd = (char *) realloc(state->cwd, len+1);
+                       memcpy(state->cwd, bucket->realpath, len+1);
+                       state->cwd_length = len;
+                       if (verify_path && verify_path(state)) {
+                               CWD_STATE_FREE(state);
+                               *state = old_state;
+                               return 1;
+                       } else {
+                               CWD_STATE_FREE(&old_state);
+                               return 0;
+                       }
+               }
+       }
+#endif
 #if !defined(TSRM_WIN32) && !defined(NETWARE)
        /* cwd_length can be 0 when getcwd() fails.
         * This can happen under solaris when a dir does not have read permissions
@@ -364,8 +483,7 @@
 #endif
        free_path = path_copy = tsrm_strndup(path, path_length);
 
-       old_state = (cwd_state *) malloc(sizeof(cwd_state));
-       CWD_STATE_COPY(old_state, state);
+       CWD_STATE_COPY(&old_state, state);
 #if VIRTUAL_CWD_DEBUG
        fprintf(stderr,"cwd = %s path = %s\n", state->cwd, path);
 #endif
@@ -385,7 +503,7 @@
                                memcpy(state->cwd, path_copy, copy_amount);
                                path_copy += copy_amount;
                        } else {
-                               memcpy(state->cwd, old_state->cwd, copy_amount);
+                               memcpy(state->cwd, old_state.cwd, copy_amount);
                        }
                }
                state->cwd[copy_amount] = '\0';
@@ -453,24 +571,28 @@
                state->cwd_length = path_length;
        }
 
-       if (verify_path && verify_path(state)) {
-               CWD_STATE_FREE(state);
+#ifdef TSRM_WIN32
+       if (new_path) {
+               free(new_path);
+       }
+#endif
+       free(free_path);
 
-               *state = *old_state;
+#ifdef REALPATH_CACHE
+       if (ret == 0 && use_realpath && CWDG(realpath_cache_size_limit)) {
+               realpath_cache_add(orig_path, orig_path_len, state->cwd, 
state->cwd_length, t TSRMLS_CC);
+       }
+#endif
 
+       if (verify_path && verify_path(state)) {
+               CWD_STATE_FREE(state);
+               *state = old_state;
                ret = 1;
        } else {
-               CWD_STATE_FREE(old_state);
+               CWD_STATE_FREE(&old_state);
                ret = 0;
        }
        
-       free(old_state);
-#ifdef TSRM_WIN32
-       if (new_path) {
-               free(new_path);
-       }
-#endif
-       free(free_path);
 #if VIRTUAL_CWD_DEBUG
        fprintf (stderr, "virtual_file_ex() = %s\n",state->cwd);
 #endif
http://cvs.php.net/diff.php/TSRM/tsrm_virtual_cwd.h?r1=1.42&r2=1.43&ty=u
Index: TSRM/tsrm_virtual_cwd.h
diff -u TSRM/tsrm_virtual_cwd.h:1.42 TSRM/tsrm_virtual_cwd.h:1.43
--- TSRM/tsrm_virtual_cwd.h:1.42        Thu Jan  8 12:31:46 2004
+++ TSRM/tsrm_virtual_cwd.h     Mon Oct  4 20:42:25 2004
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: tsrm_virtual_cwd.h,v 1.42 2004/01/08 17:31:46 sniper Exp $ */
+/* $Id: tsrm_virtual_cwd.h,v 1.43 2004/10/05 00:42:25 andi Exp $ */
 
 #ifndef VIRTUAL_CWD_H
 #define VIRTUAL_CWD_H
@@ -200,13 +200,37 @@
 
 CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func 
verify_path, int use_realpath);
 
+#define REALPATH_CACHE
+#define REALPATH_CACHE_TTL  (2*60) /* 2 minutes */
+#define REALPATH_CACHE_SIZE 0      /* disabled while php.ini isn't loaded */
+
+#ifdef REALPATH_CACHE
+typedef struct _realpath_cache_bucket {
+       unsigned long                  key;
+       char                          *path;
+       int                            path_len;
+       char                          *realpath;
+       int                            realpath_len;
+       time_t                         expires;
+       struct _realpath_cache_bucket *next;    
+} realpath_cache_bucket;
+#endif
+
 typedef struct _virtual_cwd_globals {
        cwd_state cwd;
+#ifdef REALPATH_CACHE
+       long                   realpath_cache_size;
+       long                   realpath_cache_size_limit;
+       long                   realpath_cache_ttl;
+       realpath_cache_bucket *realpath_cache[1024];
+#endif
 } virtual_cwd_globals;
 
 #ifdef ZTS
+extern ts_rsrc_id cwd_globals_id;
 # define CWDG(v) TSRMG(cwd_globals_id, virtual_cwd_globals *, v)
 #else
+extern virtual_cwd_globals cwd_globals;
 # define CWDG(v) (cwd_globals.v)
 #endif
 
http://cvs.php.net/diff.php/php-src/main/SAPI.c?r1=1.190&r2=1.191&ty=u
Index: php-src/main/SAPI.c
diff -u php-src/main/SAPI.c:1.190 php-src/main/SAPI.c:1.191
--- php-src/main/SAPI.c:1.190   Thu Aug 19 16:26:39 2004
+++ php-src/main/SAPI.c Mon Oct  4 20:42:25 2004
@@ -18,7 +18,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: SAPI.c,v 1.190 2004/08/19 20:26:39 bfrance Exp $ */
+/* $Id: SAPI.c,v 1.191 2004/10/05 00:42:25 andi Exp $ */
 
 #include <ctype.h>
 #include <sys/stat.h>
@@ -79,9 +79,7 @@
        sapi_globals_ctor(&sapi_globals TSRMLS_CC);
 #endif
 
-#ifdef VIRTUAL_DIR
        virtual_cwd_startup(); /* Could use shutdown to free the main cwd but it would 
just slow it down for CGI */
-#endif
 
 #ifdef PHP_WIN32
        tsrm_win32_startup();
@@ -93,9 +91,8 @@
 SAPI_API void sapi_shutdown(void)
 {
        reentrancy_shutdown();
-#ifdef VIRTUAL_DIR
+
        virtual_cwd_shutdown();
-#endif
 
 #ifdef PHP_WIN32
        tsrm_win32_shutdown();
http://cvs.php.net/diff.php/php-src/main/main.c?r1=1.610&r2=1.611&ty=u
Index: php-src/main/main.c
diff -u php-src/main/main.c:1.610 php-src/main/main.c:1.611
--- php-src/main/main.c:1.610   Wed Sep 29 06:36:24 2004
+++ php-src/main/main.c Mon Oct  4 20:42:25 2004
@@ -18,7 +18,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: main.c,v 1.610 2004/09/29 10:36:24 hyanantha Exp $ */
+/* $Id: main.c,v 1.611 2004/10/05 00:42:25 andi Exp $ */
 
 /* {{{ includes
  */
@@ -322,7 +322,10 @@
 
        STD_PHP_INI_BOOLEAN("allow_url_fopen",          "1",            
PHP_INI_SYSTEM,         OnUpdateBool,                   allow_url_fopen,               
         php_core_globals,       core_globals)
        STD_PHP_INI_BOOLEAN("always_populate_raw_post_data",            "0",           
 PHP_INI_SYSTEM|PHP_INI_PERDIR,          OnUpdateBool,                   
always_populate_raw_post_data,                  php_core_globals,       core_globals)
-
+#ifdef REALPATH_CACHE
+       STD_PHP_INI_ENTRY("realpath_cache_size", "16K", PHP_INI_SYSTEM, OnUpdateLong, 
realpath_cache_size_limit, virtual_cwd_globals, cwd_globals)
+       STD_PHP_INI_ENTRY("realpath_cache_ttl", "120", PHP_INI_SYSTEM, OnUpdateLong, 
realpath_cache_ttl, virtual_cwd_globals, cwd_globals)
+#endif
 PHP_INI_END()
 /* }}} */
 
@@ -1385,6 +1388,11 @@
 
        REGISTER_INI_ENTRIES();
        zend_register_standard_ini_entries(TSRMLS_C);
+
+       /* Disable realpath cache if safe_mode or open_basedir are set */
+       if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) {
+               CWDG(realpath_cache_size_limit) = 0;
+       }
 
        /* initialize stream wrappers registry
         * (this uses configuration parameters from php.ini)

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to