summaryrefslogtreecommitdiff
path: root/TSRM/tsrm_virtual_cwd.c
diff options
context:
space:
mode:
Diffstat (limited to 'TSRM/tsrm_virtual_cwd.c')
-rw-r--r--TSRM/tsrm_virtual_cwd.c388
1 files changed, 281 insertions, 107 deletions
diff --git a/TSRM/tsrm_virtual_cwd.c b/TSRM/tsrm_virtual_cwd.c
index 5918b85e6..d364c46b3 100644
--- a/TSRM/tsrm_virtual_cwd.c
+++ b/TSRM/tsrm_virtual_cwd.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2006 The PHP Group |
+ | Copyright (c) 1997-2007 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: tsrm_virtual_cwd.c,v 1.74.2.9.2.9 2006/10/06 14:03:19 tony2001 Exp $ */
+/* $Id: tsrm_virtual_cwd.c,v 1.74.2.9.2.26 2007/04/12 15:28:58 dmitry Exp $ */
#include <sys/types.h>
#include <sys/stat.h>
@@ -35,11 +35,6 @@
#ifdef TSRM_WIN32
#include <io.h>
#include "tsrm_win32.h"
-# if HAVE_NEWAPIS_H
-# define WANT_GETLONGPATHNAME_WRAPPER
-# define COMPILE_NEWAPIS_STUBS
-# include <NewAPIs.h>
-# endif
#endif
#ifdef NETWARE
@@ -140,11 +135,93 @@ static int php_check_dots(const char *element, int n)
#define CWD_STATE_FREE(s) \
free((s)->cwd);
+#ifdef TSRM_WIN32
+CWD_API int php_sys_stat(const char *path, struct stat *buf)
+{
+ WIN32_FILE_ATTRIBUTE_DATA data;
+ __int64 t;
+
+ if (!GetFileAttributesEx(path, GetFileExInfoStandard, &data)) {
+ return stat(path, buf);
+ }
+
+ if (path[1] == ':') {
+ if (path[0] >= 'A' && path[0] <= 'Z') {
+ buf->st_dev = buf->st_rdev = path[0] - 'A';
+ } else {
+ buf->st_dev = buf->st_rdev = path[0] - 'a';
+ }
+ } else {
+ char cur_path[MAXPATHLEN+1];
+ DWORD len = sizeof(cur_path);
+ char *tmp = cur_path;
+
+ while(1) {
+ DWORD r = GetCurrentDirectory(len, tmp);
+ if (r < len) {
+ if (tmp[1] == ':') {
+ if (path[0] >= 'A' && path[0] <= 'Z') {
+ buf->st_dev = buf->st_rdev = path[0] - 'A';
+ } else {
+ buf->st_dev = buf->st_rdev = path[0] - 'a';
+ }
+ } else {
+ buf->st_dev = buf->st_rdev = -1;
+ }
+ break;
+ } else if (!r) {
+ buf->st_dev = buf->st_rdev = -1;
+ break;
+ } else {
+ len = r+1;
+ tmp = (char*)malloc(len);
+ }
+ }
+ if (tmp != cur_path) {
+ free(tmp);
+ }
+ }
+ buf->st_uid = buf->st_gid = buf->st_ino = 0;
+ buf->st_mode = (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? (S_IFDIR|S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6)) : S_IFREG;
+ buf->st_mode |= (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6)) : (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6)|S_IWRITE|(S_IWRITE>>3)|(S_IWRITE>>6));
+ if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
+ int len = strlen(path);
+
+ if (path[len-4] == '.') {
+ if (_memicmp(path+len-3, "exe", 3) == 0 ||
+ _memicmp(path+len-3, "com", 3) == 0 ||
+ _memicmp(path+len-3, "bat", 3) == 0 ||
+ _memicmp(path+len-3, "cmd", 3) == 0) {
+ buf->st_mode |= (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6));
+ }
+ }
+ }
+ buf->st_nlink = 1;
+ t = data.nFileSizeHigh;
+ t = t << 32;
+ t |= data.nFileSizeLow;
+ buf->st_size = t;
+ t = data.ftLastAccessTime.dwHighDateTime;
+ t = t << 32;
+ t |= data.ftLastAccessTime.dwLowDateTime;
+ buf->st_atime = (unsigned long)((t / 10000000) - 11644473600);
+ t = data.ftCreationTime.dwHighDateTime;
+ t = t << 32;
+ t |= data.ftCreationTime.dwLowDateTime;
+ buf->st_ctime = (unsigned long)((t / 10000000) - 11644473600);
+ t = data.ftLastWriteTime.dwHighDateTime;
+ t = t << 32;
+ t |= data.ftLastWriteTime.dwLowDateTime;
+ buf->st_mtime = (unsigned long)((t / 10000000) - 11644473600);
+ return 0;
+}
+#endif
+
static int php_is_dir_ok(const cwd_state *state)
{
struct stat buf;
- if (stat(state->cwd, &buf) == 0 && S_ISDIR(buf.st_mode))
+ if (php_sys_stat(state->cwd, &buf) == 0 && S_ISDIR(buf.st_mode))
return (0);
return (1);
@@ -154,7 +231,7 @@ static int php_is_file_ok(const cwd_state *state)
{
struct stat buf;
- if (stat(state->cwd, &buf) == 0 && S_ISREG(buf.st_mode))
+ if (php_sys_stat(state->cwd, &buf) == 0 && S_ISREG(buf.st_mode))
return (0);
return (1);
@@ -172,18 +249,7 @@ static void cwd_globals_ctor(virtual_cwd_globals *cwd_globals TSRMLS_DC)
static void cwd_globals_dtor(virtual_cwd_globals *cwd_globals TSRMLS_DC)
{
CWD_STATE_FREE(&cwd_globals->cwd);
- {
- 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);
- }
- }
- }
+ realpath_cache_clean(TSRMLS_C);
}
static char *tsrm_strndup(const char *s, size_t length)
@@ -306,14 +372,51 @@ CWD_API char *virtual_getcwd(char *buf, size_t size TSRMLS_DC)
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;
+ register unsigned long h;
+ const char *e = path + path_len;
+
+ for (h = 2166136261U; path < e;) {
+ h *= 16777619;
+ h ^= *path++;
+ }
+
+ return h;
+}
+
+CWD_API void realpath_cache_clean(TSRMLS_D)
+{
+ int i;
+
+ for (i = 0; i < sizeof(CWDG(realpath_cache))/sizeof(CWDG(realpath_cache)[0]); i++) {
+ realpath_cache_bucket *p = CWDG(realpath_cache)[i];
+ while (p != NULL) {
+ realpath_cache_bucket *r = p;
+ p = p->next;
+ free(r);
+ }
+ CWDG(realpath_cache)[i] = NULL;
+ }
+ CWDG(realpath_cache_size) = 0;
+}
+
+CWD_API void realpath_cache_del(const char *path, int path_len 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 (key == (*bucket)->key && path_len == (*bucket)->path_len &&
+ memcmp(path, (*bucket)->path, path_len) == 0) {
+ 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);
+ return;
+ } else {
+ bucket = &(*bucket)->next;
+ }
+ }
}
static inline void realpath_cache_add(const char *path, int path_len, const char *realpath, int realpath_len, time_t t TSRMLS_DC)
@@ -334,7 +437,7 @@ static inline void realpath_cache_add(const char *path, int path_len, const char
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;
+ CWDG(realpath_cache_size) += size;
}
}
@@ -371,7 +474,11 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func
realpath_cache_bucket *bucket;
time_t t = 0;
int ret;
+ int use_cache;
+ int use_relative_path = 0;
TSRMLS_FETCH();
+
+ use_cache = ((use_realpath != CWD_EXPAND) && CWDG(realpath_cache_size_limit));
if (path_length == 0)
return (0);
@@ -385,27 +492,32 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func
/* 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) && (state->cwd_length > 0)) {
- int orig_path_len;
- int state_cwd_length = state->cwd_length;
+ 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;
#ifdef TSRM_WIN32
- if (IS_SLASH(path[0])) {
- state_cwd_length = 2;
- }
+ if (IS_SLASH(path[0])) {
+ state_cwd_length = 2;
+ }
#endif
- orig_path_len = path_length + state_cwd_length + 1;
- if (orig_path_len >= MAXPATHLEN) {
- return 1;
+ orig_path_len = path_length + state_cwd_length + 1;
+ if (orig_path_len >= 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);
+ path = orig_path;
+ path_length = orig_path_len;
}
- 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;
}
- if (use_realpath && CWDG(realpath_cache_size_limit)) {
+ if (use_cache) {
t = CWDG(realpath_cache_ttl)?time(NULL):0;
if ((bucket = realpath_cache_find(path, path_length, t TSRMLS_CC)) != NULL) {
int len = bucket->realpath_len;
@@ -425,11 +537,14 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func
}
}
- if (use_realpath) {
+ 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 */
+ if (use_realpath == CWD_REALPATH) {
+ return 1;
+ }
goto no_realpath;
}
CWD_STATE_COPY(&old_state, state);
@@ -442,15 +557,19 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func
#endif
} else {
char *ptr, *path_copy, *free_path;
- char *tok = NULL;
+ char *tok;
int ptr_length;
-
+#ifdef TSRM_WIN32
+ int is_unc;
+#endif
no_realpath:
free_path = path_copy = tsrm_strndup(path, path_length);
CWD_STATE_COPY(&old_state, state);
-#ifdef TSRM_WIN32
+#ifdef TSRM_WIN32
+ 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]);
@@ -464,6 +583,7 @@ no_realpath:
state->cwd[1] = '\0';
state->cwd_length = 1;
path_copy += 2;
+ is_unc = 2;
} else {
#endif
state->cwd = (char *) realloc(state->cwd, 1);
@@ -473,6 +593,7 @@ no_realpath:
}
#endif
+ tok = NULL;
ptr = tsrm_strtok_r(path_copy, TOKENIZER_STRING, &tok);
while (ptr) {
ptr_length = strlen(ptr);
@@ -480,6 +601,12 @@ no_realpath:
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;
#define PREVIOUS state->cwd[state->cwd_length - 1]
@@ -499,37 +626,42 @@ no_realpath:
state->cwd_length--;
}
} else if (!IS_DIRECTORY_CURRENT(ptr, ptr_length)) {
- state->cwd = (char *) realloc(state->cwd, state->cwd_length+ptr_length+1+1);
+ 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;
- }
+ /* 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;
- }
+ /*
+ 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;
+ state->cwd[state->cwd_length++] = DEFAULT_SLASH;
#endif
+ }
memcpy(&state->cwd[state->cwd_length], ptr, ptr_length+1);
#ifdef TSRM_WIN32
- if (use_realpath) {
+ if (use_realpath != CWD_EXPAND) {
WIN32_FIND_DATA data;
HANDLE hFind;
@@ -542,6 +674,15 @@ no_realpath:
memcpy(&state->cwd[state->cwd_length], data.cFileName, length+1);
ptr_length = length;
FindClose(hFind);
+ ret = 0;
+ } else if (use_realpath == CWD_REALPATH) {
+ if (is_unc) {
+ /* skip share name */
+ is_unc--;
+ ret = 0;
+ } else {
+ ret = 1;
+ }
}
}
#endif
@@ -553,6 +694,12 @@ no_realpath:
free(free_path);
+ if ((use_realpath == CWD_REALPATH) && ret) {
+ CWD_STATE_FREE(state);
+ *state = old_state;
+ return 1;
+ }
+
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;
@@ -561,7 +708,7 @@ no_realpath:
}
}
- if (use_realpath && CWDG(realpath_cache_size_limit)) {
+ if (use_cache) {
realpath_cache_add(path, path_length, state->cwd, state->cwd_length, t TSRMLS_CC);
}
@@ -582,7 +729,7 @@ no_realpath:
CWD_API int virtual_chdir(const char *path TSRMLS_DC)
{
- return virtual_file_ex(&CWDG(cwd), path, php_is_dir_ok, 1)?-1:0;
+ return virtual_file_ex(&CWDG(cwd), path, php_is_dir_ok, CWD_REALPATH)?-1:0;
}
CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path TSRMLS_DC) TSRMLS_DC)
@@ -624,7 +771,7 @@ CWD_API char *virtual_realpath(const char *path, char *real_path TSRMLS_DC)
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, path, NULL, 1)==0) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)==0) {
int len = new_state.cwd_length>MAXPATHLEN-1?MAXPATHLEN-1:new_state.cwd_length;
memcpy(real_path, new_state.cwd, len);
@@ -645,7 +792,7 @@ CWD_API int virtual_filepath_ex(const char *path, char **filepath, verify_path_f
int retval;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- retval = virtual_file_ex(&new_state, path, verify_path, 1);
+ retval = virtual_file_ex(&new_state, path, verify_path, CWD_FILEPATH);
*filepath = new_state.cwd;
@@ -668,7 +815,8 @@ CWD_API FILE *virtual_fopen(const char *path, const char *mode TSRMLS_DC)
}
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, path, NULL, 1)) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
+ CWD_STATE_FREE(&new_state);
return NULL;
}
@@ -684,7 +832,8 @@ CWD_API int virtual_access(const char *pathname, int mode TSRMLS_DC)
int ret;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, pathname, NULL, 1)) {
+ if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH)) {
+ CWD_STATE_FREE(&new_state);
return -1;
}
@@ -707,7 +856,8 @@ CWD_API int virtual_utime(const char *filename, struct utimbuf *buf TSRMLS_DC)
int ret;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, filename, NULL, 0)) {
+ if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
+ CWD_STATE_FREE(&new_state);
return -1;
}
@@ -724,7 +874,8 @@ CWD_API int virtual_chmod(const char *filename, mode_t mode TSRMLS_DC)
int ret;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, filename, NULL, 1)) {
+ if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
+ CWD_STATE_FREE(&new_state);
return -1;
}
@@ -741,7 +892,8 @@ CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int li
int ret;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, filename, NULL, 0)) {
+ if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {
+ CWD_STATE_FREE(&new_state);
return -1;
}
@@ -766,7 +918,8 @@ CWD_API int virtual_open(const char *path TSRMLS_DC, int flags, ...)
int f;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, path, NULL, 1)) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
+ CWD_STATE_FREE(&new_state);
return -1;
}
@@ -792,7 +945,8 @@ CWD_API int virtual_creat(const char *path, mode_t mode TSRMLS_DC)
int f;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, path, NULL, 1)) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) {
+ CWD_STATE_FREE(&new_state);
return -1;
}
@@ -809,13 +963,16 @@ CWD_API int virtual_rename(char *oldname, char *newname TSRMLS_DC)
int retval;
CWD_STATE_COPY(&old_state, &CWDG(cwd));
- if (virtual_file_ex(&old_state, oldname, NULL, 0)) {
+ if (virtual_file_ex(&old_state, oldname, NULL, CWD_REALPATH)) {
+ CWD_STATE_FREE(&old_state);
return -1;
}
oldname = old_state.cwd;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, newname, NULL, 0)) {
+ if (virtual_file_ex(&new_state, newname, NULL, CWD_FILEPATH)) {
+ CWD_STATE_FREE(&old_state);
+ CWD_STATE_FREE(&new_state);
return -1;
}
newname = new_state.cwd;
@@ -834,11 +991,12 @@ CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC)
int retval;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, path, NULL, 1)) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
+ CWD_STATE_FREE(&new_state);
return -1;
}
- retval = stat(new_state.cwd, buf);
+ retval = php_sys_stat(new_state.cwd, buf);
CWD_STATE_FREE(&new_state);
return retval;
@@ -851,7 +1009,8 @@ CWD_API int virtual_lstat(const char *path, struct stat *buf TSRMLS_DC)
int retval;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, path, NULL, 0)) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
+ CWD_STATE_FREE(&new_state);
return -1;
}
@@ -868,7 +1027,8 @@ CWD_API int virtual_unlink(const char *path TSRMLS_DC)
int retval;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, path, NULL, 0)) {
+ if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND)) {
+ CWD_STATE_FREE(&new_state);
return -1;
}
@@ -884,7 +1044,8 @@ CWD_API int virtual_mkdir(const char *pathname, mode_t mode TSRMLS_DC)
int retval;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, pathname, NULL, 1)) {
+ if (virtual_file_ex(&new_state, pathname, NULL, CWD_FILEPATH)) {
+ CWD_STATE_FREE(&new_state);
return -1;
}
@@ -903,7 +1064,8 @@ CWD_API int virtual_rmdir(const char *pathname TSRMLS_DC)
int retval;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, pathname, NULL, 0)) {
+ if (virtual_file_ex(&new_state, pathname, NULL, CWD_EXPAND)) {
+ CWD_STATE_FREE(&new_state);
return -1;
}
@@ -923,7 +1085,8 @@ CWD_API DIR *virtual_opendir(const char *pathname TSRMLS_DC)
DIR *retval;
CWD_STATE_COPY(&new_state, &CWDG(cwd));
- if (virtual_file_ex(&new_state, pathname, NULL, 1)) {
+ if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH)) {
+ CWD_STATE_FREE(&new_state);
return NULL;
}
@@ -1033,25 +1196,36 @@ CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC)
#endif
-/* On AIX & Tru64 when a file does not exist realpath() returns
- * NULL, and sets errno to ENOENT. Unlike in other libc implementations
- * the destination is not filled and remains undefined. Therefor, we
- * must populate it manually using strcpy as done on systems with no
- * realpath() function.
- */
-#if defined(__osf__) || defined(_AIX)
-char *php_realpath_hack(const char *src, char *dest)
+CWD_API char *tsrm_realpath(const char *path, char *real_path TSRMLS_DC)
{
- char *ret;
+ cwd_state new_state;
+ char cwd[MAXPATHLEN];
- if ((ret = realpath(src, dest)) == NULL && errno == ENOENT) {
- return strcpy(dest, src);
+ if (!IS_ABSOLUTE_PATH(path, strlen(path)) &&
+ VCWD_GETCWD(cwd, MAXPATHLEN)) {
+ new_state.cwd = strdup(cwd);
+ new_state.cwd_length = strlen(cwd);
} else {
- return ret;
+ new_state.cwd = (char*)malloc(1);
+ new_state.cwd[0] = '\0';
+ new_state.cwd_length = 0;
}
-}
-#endif
+ if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) {
+ free(new_state.cwd);
+ return NULL;
+ }
+
+ if (real_path) {
+ int copy_len = new_state.cwd_length>MAXPATHLEN-1 ? MAXPATHLEN-1 : new_state.cwd_length;
+ memcpy(real_path, new_state.cwd, copy_len);
+ real_path[copy_len] = '\0';
+ free(new_state.cwd);
+ return real_path;
+ } else {
+ return new_state.cwd;
+ }
+}
/*