Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:39797 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 31904 invoked from network); 9 Aug 2008 15:28:27 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 9 Aug 2008 15:28:27 -0000 Authentication-Results: pb1.pair.com smtp.mail=dmitry@zend.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=dmitry@zend.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain zend.com designates 212.25.124.163 as permitted sender) X-PHP-List-Original-Sender: dmitry@zend.com X-Host-Fingerprint: 212.25.124.163 il-gw1.zend.com Windows 2000 SP4, XP SP1 Received: from [212.25.124.163] ([212.25.124.163:22684] helo=il-gw1.zend.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 99/92-17923-997BD984 for ; Sat, 09 Aug 2008 11:28:26 -0400 Received: from [10.1.10.26] ([10.1.10.26]) by il-gw1.zend.com with Microsoft SMTPSVC(6.0.3790.3959); Sat, 9 Aug 2008 18:29:08 +0300 Message-ID: <489DB787.8060508@zend.com> Date: Sat, 09 Aug 2008 19:28:07 +0400 User-Agent: Thunderbird 2.0.0.16 (Windows/20080708) MIME-Version: 1.0 To: Rasmus Lerdorf CC: Hannes Magnusson , Arnaud Le Blanc , internals@lists.php.net, Felipe Pena , Christian Stocker , Andi Gutmans , Stanislav Malyshev References: <4899C4B4.3060902@liip.ch> <1218138548.5346.3.camel@felipe> <489B5285.1070000@lerdorf.com> <200808072237.01841.arnaud.lb@gmail.com> <7f3ed2c30808080011l3c62d416k7fd9b4dd455df99e@mail.gmail.com> <489C6BBA.8030101@zend.com> <489CBDD8.6070502@lerdorf.com> <489CBE81.5030003@lerdorf.com> In-Reply-To: <489CBE81.5030003@lerdorf.com> Content-Type: multipart/mixed; boundary="------------040008020209040305040507" X-OriginalArrivalTime: 09 Aug 2008 15:29:09.0210 (UTC) FILETIME=[AADFDBA0:01C8FA34] Subject: Re: [PHP-DEV] include bug in 5.3 From: dmitry@zend.com (Dmitry Stogov) --------------040008020209040305040507 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit The improved patch fixes all the issues I found during testing. However I wasn't able to test it on NETWARE and on Solaris with relative paths. Please test it as much as possible. I'm going to commit it on Tuesday in case of no objections. Thanks. Dmitry. Rasmus Lerdorf wrote: > Rasmus Lerdorf wrote: >> Dmitry Stogov wrote: >>> Hi, >>> >>> The attached patch is going to fix the problem. >>> It implements its own realpath() function, so we won't depend on system >>> anymore. It also improve realpath cache usage by caching intermediate >>> results. >> >> Very nice. The intermediate caching is going to drastically reduce the >> amount of memory we need for the cache. I have seen a number of cases >> where sites had to increase the realpath cache size by quite a bit. > > Oh, and on top of that we also get a big performance improvement for > include_path misses since we no longer have to re-stat every component > of the docroot on every miss. > > -Rasmus --------------040008020209040305040507 Content-Type: text/plain; name="realpath-5.3-080809.diff.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="realpath-5.3-080809.diff.txt" ? TSRM/autom4te.cache ? TSRM/stamp-h1 ? TSRM/tsrm_virtual_cwd-0.c ? TSRM/tsrm_virtual_cwd-1.c ? TSRM/tsrm_virtual_cwd-2.c Index: NEWS =================================================================== RCS file: /repository/php-src/NEWS,v retrieving revision 1.2027.2.547.2.965.2.259 diff -u -p -d -r1.2027.2.547.2.965.2.259 NEWS --- NEWS 8 Aug 2008 18:46:20 -0000 1.2027.2.547.2.965.2.259 +++ NEWS 9 Aug 2008 14:52:58 -0000 @@ -5,6 +5,8 @@ PHP - Changed session_start() to return false when session startup fails. (Jani) +- Added system independent realpth() implementation which caches intermediate + results in realpath-cache (Dmitry) - Added optional clear_realpath_cache and filename parameters to clearstatcache(). (Jani, Arnaud) - Added litespeed SAPI module. (George Wang) @@ -21,8 +23,11 @@ PHP - 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) Index: TSRM/tsrm_virtual_cwd.c =================================================================== RCS file: /repository/TSRM/tsrm_virtual_cwd.c,v retrieving revision 1.74.2.9.2.35.2.7 diff -u -p -d -r1.74.2.9.2.35.2.7 tsrm_virtual_cwd.c --- TSRM/tsrm_virtual_cwd.c 20 May 2008 07:41:35 -0000 1.74.2.9.2.35.2.7 +++ TSRM/tsrm_virtual_cwd.c 9 Aug 2008 14:52:59 -0000 @@ -257,22 +257,6 @@ static void cwd_globals_dtor(virtual_cwd } /* }}} */ -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 @@ CWD_API void realpath_cache_del(const ch } /* }}} */ -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 @@ static inline void realpath_cache_add(co 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 @@ static inline realpath_cache_bucket* rea } /* }}} */ -/* 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; + save = (use_realpath != CWD_EXPAND); - 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; + 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 */ + 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; - } + 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); + } - save = DEFAULT_SLASH; + tsrm_free_alloca(tmp, use_heap); + return j; + } +} +/* }}} */ -#define PREVIOUS state->cwd[state->cwd_length - 1] +/* 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(); - while (IS_ABSOLUTE_PATH(state->cwd, state->cwd_length) && - !IS_SLASH(PREVIOUS)) { - save = PREVIOUS; - PREVIOUS = '\0'; - state->cwd_length--; - } + if (path_length == 0 || path_length >= MAXPATHLEN-1) { + return 1; + } - 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 VIRTUAL_CWD_DEBUG + fprintf(stderr,"cwd = %s path = %s\n", state->cwd, path); #endif - } - memcpy(&state->cwd[state->cwd_length], ptr, ptr_length+1); - -#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); + /* 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; - 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; - } - } - } - } +#ifdef TSRM_WIN32 + 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; } Index: TSRM/tsrm_virtual_cwd.h =================================================================== RCS file: /repository/TSRM/tsrm_virtual_cwd.h,v retrieving revision 1.48.2.5.2.8.2.4 diff -u -p -d -r1.48.2.5.2.8.2.4 tsrm_virtual_cwd.h --- TSRM/tsrm_virtual_cwd.h 2 May 2008 14:07:26 -0000 1.48.2.5.2.8.2.4 +++ TSRM/tsrm_virtual_cwd.h 9 Aug 2008 14:52:59 -0000 @@ -208,6 +208,7 @@ typedef struct _realpath_cache_bucket { int path_len; char *realpath; int realpath_len; + int is_dir; time_t expires; struct _realpath_cache_bucket *next; } realpath_cache_bucket; --------------040008020209040305040507--