dmitry          Tue Aug 12 08:01:24 2008 UTC

  Modified files:              (Branch: PHP_5_3)
    /php-src    NEWS 
    /TSRM       tsrm_virtual_cwd.c tsrm_virtual_cwd.h 
  Log:
  - Added system independent realpath() implementation which caches 
intermediate directories in realpath-cache
  - Fixed bug #45044 (relative paths not resolved correctly)
  - Fixed bug #43817 (opendir() fails on Windows directories with parent 
directory unaccessible).
  [DOC] The semantic of realpath() on BSD and Windows is changed. Now it should 
work exactly in the same way as on Linux (POSIX.1-2001)
  
  
http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.965.2.263&r2=1.2027.2.547.2.965.2.264&diff_format=u
Index: php-src/NEWS
diff -u php-src/NEWS:1.2027.2.547.2.965.2.263 
php-src/NEWS:1.2027.2.547.2.965.2.264
--- php-src/NEWS:1.2027.2.547.2.965.2.263       Mon Aug 11 12:33:56 2008
+++ php-src/NEWS        Tue Aug 12 08:01:23 2008
@@ -5,6 +5,8 @@
 
 - Changed session_start() to return false when session startup fails. (Jani)
 
+- Added system independent realpath() implementation which caches intermediate
+  directories in realpath-cache (Dmitry)
 - Added optional clear_realpath_cache and filename parameters to
   clearstatcache(). (Jani, Arnaud)
 - Added litespeed SAPI module. (George Wang)
@@ -22,8 +24,11 @@
 - Fixed bug #45636 (fileinfo ext duplicate strndup). (Derick)
 - Fixed bug #45545 (DateInterval has 4 char limitation for ISO durations).
   (Derick)
+- Fixed bug #45044 (relative paths not resolved correctly). (Dmitry)
 - Fixed bug #44100 (Inconsistent handling of static array declarations with
   duplicate keys). (Dmitry)
+- Fixed bug #43817 (opendir() fails on Windows directories with parent
+  directory unaccessible). (Dmitry)
 - Fixed bug #43008 (php://filter uris ignore url encoded filternames and can't
   handle slashes). (Arnaud)
 
http://cvs.php.net/viewvc.cgi/TSRM/tsrm_virtual_cwd.c?r1=1.74.2.9.2.35.2.7&r2=1.74.2.9.2.35.2.8&diff_format=u
Index: TSRM/tsrm_virtual_cwd.c
diff -u TSRM/tsrm_virtual_cwd.c:1.74.2.9.2.35.2.7 
TSRM/tsrm_virtual_cwd.c:1.74.2.9.2.35.2.8
--- TSRM/tsrm_virtual_cwd.c:1.74.2.9.2.35.2.7   Tue May 20 07:41:35 2008
+++ TSRM/tsrm_virtual_cwd.c     Tue Aug 12 08:01:24 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: tsrm_virtual_cwd.c,v 1.74.2.9.2.35.2.7 2008/05/20 07:41:35 dmitry Exp 
$ */
+/* $Id: tsrm_virtual_cwd.c,v 1.74.2.9.2.35.2.8 2008/08/12 08:01:24 dmitry Exp 
$ */
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -257,22 +257,6 @@
 }
 /* }}} */
 
-static char *tsrm_strndup(const char *s, size_t length) /* {{{ */
-{
-    char *p;
-
-    p = (char *) malloc(length+1);
-    if (!p) {
-        return (char *)NULL;
-    }
-    if (length) {
-        memcpy(p,s,length);
-    }
-    p[length]=0;
-    return p;
-}
-/* }}} */
-
 CWD_API void virtual_cwd_startup(void) /* {{{ */
 {
        char cwd[MAXPATHLEN];
@@ -431,9 +415,17 @@
 }
 /* }}} */
 
-static inline void realpath_cache_add(const char *path, int path_len, const 
char *realpath, int realpath_len, time_t t TSRMLS_DC) /* {{{ */
+static inline void realpath_cache_add(const char *path, int path_len, const 
char *realpath, int realpath_len, int is_dir, time_t t TSRMLS_DC) /* {{{ */
 {
-       long size = sizeof(realpath_cache_bucket) + path_len + 1 + realpath_len 
+ 1;
+       long size = sizeof(realpath_cache_bucket) + path_len + 1;
+       int same = 1;
+       
+       if (realpath_len != path_len ||
+           memcmp(path, realpath, path_len) != 0) {
+               size += realpath_len + 1;
+               same = 0;
+       }
+
        if (CWDG(realpath_cache_size) + size <= 
CWDG(realpath_cache_size_limit)) {
                realpath_cache_bucket *bucket = malloc(size);
                unsigned long n;
@@ -442,9 +434,14 @@
                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);
+               if (same) {
+                       bucket->realpath = bucket->path;
+               } else {
+                       bucket->realpath = bucket->path + (path_len + 1);
+                       memcpy(bucket->realpath, realpath, realpath_len+1);
+               }
                bucket->realpath_len = realpath_len;
+               bucket->is_dir = is_dir;
                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];
@@ -477,290 +474,352 @@
 }
 /* }}} */
 
-/* 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) /* {{{ */
+#define LINK_MAX 32
+
+static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, 
int use_realpath, int is_dir TSRMLS_DC) /* {{{ */
 {
-       int path_length = strlen(path);
-       cwd_state old_state;
-       char orig_path[MAXPATHLEN];
-       realpath_cache_bucket *bucket;
-       time_t t = 0;
-       int ret;
-       int use_cache;
-       int use_relative_path = 0;
+       int i, j, save;
+       int directory = 0;
 #ifdef TSRM_WIN32
-       int is_unc;
-       int exists;
+       WIN32_FIND_DATA data;
+       HANDLE hFind;
+#else
+       struct stat st;
 #endif
-       TSRMLS_FETCH();
-
-       use_cache = ((use_realpath != CWD_EXPAND) && 
CWDG(realpath_cache_size_limit));
-
-       if (path_length == 0) 
-               return (1);
-       if (path_length >= MAXPATHLEN)
-               return (1);
+       realpath_cache_bucket *bucket;
+       char *tmp;
+       TSRM_ALLOCA_FLAG(use_heap);
 
-#if VIRTUAL_CWD_DEBUG
-               fprintf(stderr,"cwd = %s path = %s\n", state->cwd, path);
-#endif
+       while (1) {
+               if (len <= start) {
+                       return start;
+               }
 
-       /* cwd_length can be 0 when getcwd() fails.
-        * This can happen under solaris when a dir does not have read 
permissions
-        * but *does* have execute permissions */
-       if (!IS_ABSOLUTE_PATH(path, path_length)) {
-               if (state->cwd_length == 0) {
-                       use_cache = 0;
-                       use_relative_path = 1;
-               } else {
-                       int orig_path_len;
-                       int state_cwd_length = state->cwd_length;
+               i = len;
+               while (i > start && !IS_SLASH(path[i-1])) {
+                       i--;
+               }
 
-#ifdef TSRM_WIN32
-                       if (IS_SLASH(path[0])) {
-                               state_cwd_length = 2;
+               if (i == len ||
+                       (i == len - 1 && path[i] == '.')) {
+                       /* remove double slashes and '.' */
+                       len = i - 1;
+                       is_dir = 1;
+                       continue;
+               } else if (i == len - 2 && path[i] == '.' && path[i+1] == '.') {
+                       /* remove '..' and previous directory */
+                       if (i - 1 <= start) {
+                               return start ? start : len;
                        }
-#endif
-                       orig_path_len = path_length + state_cwd_length + 1;
-                       if (orig_path_len >= MAXPATHLEN) {
-                               return 1;
+                       j = tsrm_realpath_r(path, start, i-1, ll, t, 
use_realpath, 1 TSRMLS_CC);
+                       if (j > start) {
+                               j--;
+                               while (j > start && !IS_SLASH(path[j])) {
+                                       j--;
+                               }
+                               if (!start) {
+                                       /* leading '..' must not be removed in 
case of relative path */
+                                       if (j == 0 && path[0] == '.' && path[1] 
== '.' &&
+                                           IS_SLASH(path[2])) {
+                                               path[3] = '.';
+                                               path[4] = '.';
+                                               path[5] = DEFAULT_SLASH;
+                                               j = 5;
+                                       } else if (j > 0 && 
+                                              path[j+1] == '.' && path[j+2] == 
'.' &&
+                                              IS_SLASH(path[j+3])) {
+                                               j += 4;
+                                               path[j++] = '.';
+                                               path[j++] = '.';
+                                               path[j] = DEFAULT_SLASH;
+                                       }
+                               }
+                       } else if (!start && !j) {
+                               /* leading '..' must not be removed in case of 
relative path */
+                               path[0] = '.';
+                               path[1] = '.';
+                               path[2] = DEFAULT_SLASH;
+                               j = 2;
                        }
-                       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);
-                       path = orig_path;
-                       path_length = orig_path_len; 
+                       return j;
                }
-       }
+       
+               path[len] = 0;
 
-       if (use_cache) {
-               t = CWDG(realpath_cache_ttl)?time(0):0;
-               if ((bucket = realpath_cache_find(path, path_length, 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;
+               save = (use_realpath != CWD_EXPAND);
+
+               if (start && save && CWDG(realpath_cache_size_limit)) {
+                       /* cache lookup for absolute path */
+                       if (!*t) {
+                               *t = time(0);
                        }
+                   if ((bucket = realpath_cache_find(path, len, *t TSRMLS_CC)) 
!= NULL) {
+                       if (is_dir && !bucket->is_dir) {
+                                       /* not a directory */
+                                       return -1;
+                       } else {
+                                       memcpy(path, bucket->realpath, 
bucket->realpath_len + 1);
+                                   return bucket->realpath_len;
+                               }
+               }
                }
-       }
 
-       if (use_realpath != CWD_EXPAND) {
-#if !defined(TSRM_WIN32) && !defined(NETWARE)
-               char resolved_path[MAXPATHLEN];
-
-               if (!realpath(path, resolved_path)) {  /* Note: Not threadsafe 
on older *BSD's */
+#ifdef TSRM_WIN32
+               if (save && (hFind = FindFirstFile(path, &data)) == 
INVALID_HANDLE_VALUE) {
                        if (use_realpath == CWD_REALPATH) {
-                               return 1;
+                               /* file not found */
+                               return -1;
                        }
-                       goto no_realpath;
+                       /* continue resolution anyway but don't save result in 
the cache */
+                       save = 0;
                }
-               use_realpath = CWD_REALPATH;
-               CWD_STATE_COPY(&old_state, state);
-
-               state->cwd_length = strlen(resolved_path);
-               state->cwd = (char *) realloc(state->cwd, state->cwd_length+1);
-               memcpy(state->cwd, resolved_path, state->cwd_length+1);
+               if (save) {
+                       directory = (data.dwFileAttributes & 
FILE_ATTRIBUTE_DIRECTORY) != 0;
+                       if (is_dir && !directory) {
+                               /* not a directory */
+                               FindClose(hFind);
+                               return -1;
+                       }
+               }
+               tmp = tsrm_do_alloca(len+1, use_heap);
+               memcpy(tmp, path, len+1);
+#elif defined(NETWARE)
+               save = 0;
+               tmp = tsrm_do_alloca(len+1, use_heap);
+               memcpy(tmp, path, len+1);
 #else
-               goto no_realpath;
-#endif
-       } else {
-               char *ptr, *path_copy, *free_path;
-               char *tok;
-               int ptr_length;
-no_realpath:
-
-#ifdef TSRM_WIN32
-               if (memchr(path, '*', path_length) ||
-                   memchr(path, '?', path_length)) {
-                       return 1;
+               if (save && lstat(path, &st) < 0) {
+                       if (use_realpath == CWD_REALPATH) {
+                               /* file not found */
+                               return -1;
+                       }
+                       /* continue resolution anyway but don't save result in 
the cache */
+                       save = 0;
                }
-#endif
 
-               free_path = path_copy = tsrm_strndup(path, path_length);
-               CWD_STATE_COPY(&old_state, state);
+               tmp = tsrm_do_alloca(len+1, use_heap);
+               memcpy(tmp, path, len+1);
 
-#ifdef TSRM_WIN32
-               exists = (use_realpath != CWD_EXPAND);
-               ret = 0;
-               is_unc = 0;
-               if (path_length >= 2 && path[1] == ':') {                       
-                       state->cwd = (char *) realloc(state->cwd, 2 + 1);
-                       state->cwd[0] = toupper(path[0]);
-                       state->cwd[1] = ':';
-                       state->cwd[2] = '\0';
-                       state->cwd_length = 2;
-                       path_copy += 2;
-               } else if (IS_UNC_PATH(path, path_length)) {
-                       state->cwd = (char *) realloc(state->cwd, 1 + 1);
-                       state->cwd[0] = DEFAULT_SLASH;
-                       state->cwd[1] = '\0';
-                       state->cwd_length = 1;
-                       path_copy += 2;
-                       is_unc = 2;
+               if (save && S_ISLNK(st.st_mode)) {
+                       if (++(*ll) > LINK_MAX || (j = readlink(tmp, path, 
MAXPATHLEN)) < 0) {
+                           /* too many links or broken symlinks */
+                               tsrm_free_alloca(tmp, use_heap);
+                               return -1;
+                       }
+                       path[j] = 0;
+                       if (IS_ABSOLUTE_PATH(path, j)) {
+                               j = tsrm_realpath_r(path, 1, j, ll, t, 
use_realpath, is_dir TSRMLS_CC);
+                               if (j < 0) {
+                                       tsrm_free_alloca(tmp, use_heap);
+                                       return -1;
+                               }
+                       } else {
+                           if (i + j >= MAXPATHLEN-1) {
+                                       tsrm_free_alloca(tmp, use_heap);
+                                       return -1; /* buffer overflow */
+                           }
+                               memmove(path+i, path, j+1);
+                               memcpy(path, tmp, i-1);
+                               path[i-1] = DEFAULT_SLASH;
+                               j = tsrm_realpath_r(path, start, i + j, ll, t, 
use_realpath, is_dir TSRMLS_CC);
+                               if (j < 0) {
+                                       tsrm_free_alloca(tmp, use_heap);
+                                       return -1;
+                               }
+                       }
                } else {
+                       if (save) {
+                               directory = S_ISDIR(st.st_mode);
+                               if (is_dir && !directory) {
+                                       /* not a directory */
+                                       return -1;
+                               }
+                       }
 #endif
-                       state->cwd = (char *) realloc(state->cwd, 1);
-                       state->cwd[0] = '\0';
-                       state->cwd_length = 0;
+                       if (i - 1 <= start) {
+                               j = start;
+                       } else {
+                               /* some leading directories may be unaccessable 
*/
+                               j = tsrm_realpath_r(path, start, i-1, ll, t, 
save ? CWD_FILEPATH : use_realpath, 1 TSRMLS_CC);
+                               if (j > start) {
+                                       path[j++] = DEFAULT_SLASH;
+                               }
+                       }
 #ifdef TSRM_WIN32
+                       if (j < 0 || j + len - i >= MAXPATHLEN-1) {
+                               tsrm_free_alloca(tmp, use_heap);
+                               if (save) FindClose(hFind);
+                               return -1;
+                       }
+                       if (save) {
+                               memcpy(path+j, data.cFileName, len-i+1);
+                               FindClose(hFind);
+                       } else {
+                               /* use the original file or directory name as 
it wasn't found */
+                               memcpy(path+j, tmp+i, len-i+1);
+                       }
+                       j += (len-i);
+#else
+                       if (j < 0 || j + len - i >= MAXPATHLEN-1) {
+                               tsrm_free_alloca(tmp, use_heap);
+                               return -1;
+                       }
+                       memcpy(path+j, tmp+i, len-i+1);
+                       j += (len-i);
                }
 #endif
-               
-               tok = NULL;
-               ptr = tsrm_strtok_r(path_copy, TOKENIZER_STRING, &tok);
-               while (ptr) {
-                       ptr_length = strlen(ptr);
-
-                       if (IS_DIRECTORY_UP(ptr, ptr_length)) {
-                               char save;
-
-                               if (use_relative_path) {
-                                       CWD_STATE_FREE(state);
-                                       *state = old_state;
-                                       return 1;
-                               }
 
-                               save = DEFAULT_SLASH;
+               if (save && start && CWDG(realpath_cache_size_limit)) {
+                       /* save absolute path in the cache */
+                       realpath_cache_add(tmp, len, path, j, directory, *t 
TSRMLS_CC);
+               }
 
-#define PREVIOUS state->cwd[state->cwd_length - 1]
+               tsrm_free_alloca(tmp, use_heap);
+               return j;
+       }
+}
+/* }}} */
 
-                               while (IS_ABSOLUTE_PATH(state->cwd, 
state->cwd_length) &&
-                                               !IS_SLASH(PREVIOUS)) {
-                                       save = PREVIOUS;
-                                       PREVIOUS = '\0';
-                                       state->cwd_length--;
-                               }
+/* 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) /* {{{ */
+{
+       int path_length = strlen(path);
+       char resolved_path[MAXPATHLEN];
+       int start = 1;
+       int ll = 0;
+       time_t t;
+       int ret;
+       int add_slash;
+       TSRMLS_FETCH();
 
-                               if (!IS_ABSOLUTE_PATH(state->cwd, 
state->cwd_length)) {
-                                       state->cwd[state->cwd_length++] = save;
-                                       state->cwd[state->cwd_length] = '\0';
-                               } else {
-                                       PREVIOUS = '\0';
-                                       state->cwd_length--;
-                               }
-                       } else if (!IS_DIRECTORY_CURRENT(ptr, ptr_length)) {
-                               if (use_relative_path) {
-                                       state->cwd = (char *) 
realloc(state->cwd, state->cwd_length+ptr_length+1);
-                                       use_relative_path = 0;
-                               } else {
-                                       state->cwd = (char *) 
realloc(state->cwd, state->cwd_length+ptr_length+1+1);
-#ifdef TSRM_WIN32
-                                       /* Windows 9x will consider C:\\Foo as 
a network path. Avoid it. */
-                                       if (state->cwd_length < 2 ||
-                                           
(state->cwd[state->cwd_length-1]!='\\' && state->cwd[state->cwd_length-1]!='/') 
||
-                                                       
IsDBCSLeadByte(state->cwd[state->cwd_length-2])) {
-                                               state->cwd[state->cwd_length++] 
= DEFAULT_SLASH;
-                                       }
-#elif defined(NETWARE)
-                                       /* 
-                                       Below code keeps appending to 
state->cwd a File system seperator
-                                       cases where this appending should not 
happen is given below,
-                                       a) sys: should just be left as it is
-                                       b) sys:system should just be left as it 
is,
-                                               Colon is allowed only in the 
first token as volume names alone can have the : in their names.
-                                               Files and Directories cannot 
have : in their names
-                                               So the check goes like this,
-                                               For second token and above 
simply append the DEFAULT_SLASH to the state->cwd.
-                                               For first token check for the 
existence of : 
-                                               if it exists don't append the 
DEFAULT_SLASH to the state->cwd.
-                                       */
-                                       if(((state->cwd_length == 0) && 
(strchr(ptr, ':') == NULL)) || (state->cwd_length > 0)) {
-                                               state->cwd[state->cwd_length++] 
= DEFAULT_SLASH;
-                                       }
-#else
-                                       state->cwd[state->cwd_length++] = 
DEFAULT_SLASH;
+       if (path_length == 0 || path_length >= MAXPATHLEN-1) {
+               return 1;
+       }
+
+#if VIRTUAL_CWD_DEBUG
+       fprintf(stderr,"cwd = %s path = %s\n", state->cwd, path);
 #endif
-                               }
-                               memcpy(&state->cwd[state->cwd_length], ptr, 
ptr_length+1);
+
+       /* cwd_length can be 0 when getcwd() fails.
+        * This can happen under solaris when a dir does not have read 
permissions
+        * but *does* have execute permissions */
+       if (!IS_ABSOLUTE_PATH(path, path_length)) {
+               if (state->cwd_length == 0) {
+                       /* resolve relative path */
+                       start = 0;
+                       memcpy(resolved_path , path, path_length + 1);
+               } else {
+                       int state_cwd_length = state->cwd_length;
 
 #ifdef TSRM_WIN32
-                               if (use_realpath != CWD_EXPAND) {
-                                       WIN32_FIND_DATA data;
-                                       HANDLE hFind;
-
-                                       if ((hFind = FindFirstFile(state->cwd, 
&data)) != INVALID_HANDLE_VALUE) {
-                                               int length = 
strlen(data.cFileName);
-
-                                               if (length != ptr_length) {
-                                                       state->cwd = (char *) 
realloc(state->cwd, state->cwd_length+length+1);
-                                               }
-                                               
memcpy(&state->cwd[state->cwd_length], data.cFileName, length+1);
-                                               ptr_length = length;
-                                               FindClose(hFind);
-                                               ret = 0;
-                                       } else {
-                                               if (is_unc) {
-                                                       /* skip share name */
-                                                       is_unc--;
-                                                       ret = 0;
-                                               } else {
-                                                       exists = 0;
-                                                       if (use_realpath == 
CWD_REALPATH) {
-                                                               ret = 1;
-                                                       }
-                                               }
-                                       }
-                               }
+                       if (IS_SLASH(path[0])) {
+                               state_cwd_length = 2;
+                       }
 #endif
-
-                               state->cwd_length += ptr_length;
+                       if (path_length + state_cwd_length + 1 >= MAXPATHLEN-1) 
{
+                               return 1;
                        }
-                       ptr = tsrm_strtok_r(NULL, TOKENIZER_STRING, &tok);
+                       memcpy(resolved_path, state->cwd, state_cwd_length);
+                       resolved_path[state_cwd_length] = DEFAULT_SLASH;
+                       memcpy(resolved_path + state_cwd_length + 1, path, 
path_length + 1);
+                       path_length += state_cwd_length + 1;
                }
+       } else {                
+               memcpy(resolved_path , path, path_length + 1);
+       } 
 
-               free(free_path);
+#ifdef TSRM_WIN32
+       if (memchr(resolved_path, '*', path_length) ||
+           memchr(resolved_path, '?', path_length)) {
+               return 1;
+       }
+#endif
 
-               if (use_realpath == CWD_REALPATH) {
-                       if (ret) {
-                               CWD_STATE_FREE(state);
-                               *state = old_state;                             
        
-                               return 1;
+#ifdef TSRM_WIN32
+       if (IS_UNC_PATH(resolved_path, path_length)) {
+               /* skip UNC name */
+               resolved_path[0] = DEFAULT_SLASH;
+               resolved_path[1] = DEFAULT_SLASH;
+               start = 2;
+               while (!IS_SLASH(resolved_path[start])) {
+                       if (resolved_path[start] == 0) {
+                               goto verify;
                        }
-               } else {
-#if defined(TSRM_WIN32) || defined(NETWARE)
-                       if (path[path_length-1] == '\\' || path[path_length-1] 
== '/') {
-#else 
-                       if (path[path_length-1] == '/') {
-#endif
-                               state->cwd = (char*)realloc(state->cwd, 
state->cwd_length + 2);
-                               state->cwd[state->cwd_length++] = DEFAULT_SLASH;
-                               state->cwd[state->cwd_length] = 0;
+                       resolved_path[start] = toupper(resolved_path[start]);
+                       start++;
+               }
+               resolved_path[start++] = DEFAULT_SLASH;
+               while (!IS_SLASH(resolved_path[start])) {
+                       if (resolved_path[start] == 0) {
+                               goto verify;
                        }
+                       resolved_path[start] = toupper(resolved_path[start]);
+                       start++;
+               }
+               resolved_path[start++] = DEFAULT_SLASH;
+       } else if (IS_ABSOLUTE_PATH(resolved_path, path_length)) {
+               /* skip DRIVE name */
+               resolved_path[0] = toupper(resolved_path[0]);
+               resolved_path[2] = DEFAULT_SLASH;
+               start = 3;
+       }
+#elif defined(NETWARE)
+       if (IS_ABSOLUTE_PATH(resolved_path, path_length)) {
+               /* skip VOLUME name */
+               start = 0;
+               while (start != ':') {
+                       if (resolved_path[start] == 0) return -1;
+                       start++;
                }
+               start++;
+               if (!IS_SLASH(resolved_path[start])) return -1;
+               resolved_path[start++] = DEFAULT_SLASH;
+       }
+#endif
+
 
-               if (state->cwd_length == COPY_WHEN_ABSOLUTE(state->cwd)) {
-                       state->cwd = (char *) realloc(state->cwd, 
state->cwd_length+1+1);
-                       state->cwd[state->cwd_length] = DEFAULT_SLASH;
-                       state->cwd[state->cwd_length+1] = '\0';
-                       state->cwd_length++;
+       add_slash = (use_realpath != CWD_REALPATH) && path_length > 0 && 
IS_SLASH(resolved_path[path_length-1]);        
+       t = CWDG(realpath_cache_ttl) ? 0 : -1;
+       path_length = tsrm_realpath_r(resolved_path, start, path_length, &ll, 
&t, use_realpath, 0 TSRMLS_CC);
+       
+       if (path_length < 0) {
+               return 1;
+       }
+       
+       if (!start && !path_length) {
+               resolved_path[path_length++] = '.';
+       }
+       if (add_slash && path_length && 
!IS_SLASH(resolved_path[path_length-1])) {
+               if (path_length >= MAXPATHLEN-1) {
+                       return -1;
                }
+               resolved_path[path_length++] = DEFAULT_SLASH;
        }
+       resolved_path[path_length] = 0;
 
-       /* Store existent file in realpath cache. */
 #ifdef TSRM_WIN32
-       if (use_cache && !is_unc && exists) {
-#else
-       if (use_cache && (use_realpath == CWD_REALPATH)) {
+verify:
 #endif
-               realpath_cache_add(path, path_length, state->cwd, 
state->cwd_length, t TSRMLS_CC);
-       }
+       if (verify_path) {
+               cwd_state old_state;
 
-       if (verify_path && verify_path(state)) {
-               CWD_STATE_FREE(state);
-               *state = old_state;
-               ret = 1;
+               CWD_STATE_COPY(&old_state, state);
+               state->cwd_length = path_length;
+               state->cwd = (char *) realloc(state->cwd, state->cwd_length+1);
+               memcpy(state->cwd, resolved_path, state->cwd_length+1);
+               if (verify_path(state)) {
+                       CWD_STATE_FREE(state);
+                       *state = old_state;
+                       ret = 1;
+               } else {
+                       CWD_STATE_FREE(&old_state);
+                       ret = 0;
+               }
        } else {
-               CWD_STATE_FREE(&old_state);
+               state->cwd_length = path_length;
+               state->cwd = (char *) realloc(state->cwd, state->cwd_length+1);
+               memcpy(state->cwd, resolved_path, state->cwd_length+1);
                ret = 0;
        }
        
http://cvs.php.net/viewvc.cgi/TSRM/tsrm_virtual_cwd.h?r1=1.48.2.5.2.8.2.4&r2=1.48.2.5.2.8.2.5&diff_format=u
Index: TSRM/tsrm_virtual_cwd.h
diff -u TSRM/tsrm_virtual_cwd.h:1.48.2.5.2.8.2.4 
TSRM/tsrm_virtual_cwd.h:1.48.2.5.2.8.2.5
--- TSRM/tsrm_virtual_cwd.h:1.48.2.5.2.8.2.4    Fri May  2 14:07:26 2008
+++ TSRM/tsrm_virtual_cwd.h     Tue Aug 12 08:01:24 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: tsrm_virtual_cwd.h,v 1.48.2.5.2.8.2.4 2008/05/02 14:07:26 derick Exp $ 
*/
+/* $Id: tsrm_virtual_cwd.h,v 1.48.2.5.2.8.2.5 2008/08/12 08:01:24 dmitry Exp $ 
*/
 
 #ifndef VIRTUAL_CWD_H
 #define VIRTUAL_CWD_H
@@ -208,6 +208,7 @@
        int                            path_len;
        char                          *realpath;
        int                            realpath_len;
+       int                            is_dir;
        time_t                         expires;
        struct _realpath_cache_bucket *next;    
 } realpath_cache_bucket;

Reply via email to