cvs: TSRM / tsrm_virtual_cwd.c tsrm_virtual_cwd.h

"Dmitry Stogov" <[email protected]>
Newsgroups gmane.comp.php.cvs.zend,gmane.comp.php.documentation.general
Message-ID <cvsdmitry1218528104@cvsserver>
dmitry		Tue Aug 12 08:01:44 2008 UTC

  Modified files:              
    /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)

-- 
Zend Engine CVS Mailing List (http://cvs.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
dmitry-20080812080144.txt (text/plain, 20 KB)
http://cvs.php.net/viewvc.cgi/TSRM/tsrm_virtual_cwd.c?r1=1.123&r2=1.124&diff_format=u
Index: TSRM/tsrm_virtual_cwd.c
diff -u TSRM/tsrm_virtual_cwd.c:1.123 TSRM/tsrm_virtual_cwd.c:1.124
--- TSRM/tsrm_virtual_cwd.c:1.123	Tue May 20 07:41:48 2008
+++ TSRM/tsrm_virtual_cwd.c	Tue Aug 12 08:01:44 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: tsrm_virtual_cwd.c,v 1.123 2008/05/20 07:41:48 dmitry Exp $ */
+/* $Id: tsrm_virtual_cwd.c,v 1.124 2008/08/12 08:01:44 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,351 @@
 }
 /* }}} */
 
-/* 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.68&r2=1.69&diff_format=u
Index: TSRM/tsrm_virtual_cwd.h
diff -u TSRM/tsrm_virtual_cwd.h:1.68 TSRM/tsrm_virtual_cwd.h:1.69
--- TSRM/tsrm_virtual_cwd.h:1.68	Fri May  2 14:16:40 2008
+++ TSRM/tsrm_virtual_cwd.h	Tue Aug 12 08:01:44 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: tsrm_virtual_cwd.h,v 1.68 2008/05/02 14:16:40 derick Exp $ */
+/* $Id: tsrm_virtual_cwd.h,v 1.69 2008/08/12 08:01:44 dmitry Exp $ */
 
 #ifndef VIRTUAL_CWD_H
 #define VIRTUAL_CWD_H
@@ -225,6 +225,7 @@
 	int                            path_len;
 	char                          *realpath;
 	int                            realpath_len;
+	int                            is_dir;
 	time_t                         expires;
 	struct _realpath_cache_bucket *next;	
 } realpath_cache_bucket;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.