#define HAVE_UTIME 1
#define HAVE_ALLOCA 1
-#define HAVE_REALPATH 1
#include <malloc.h>
#include <stdlib.h>
}
}/*}}}*/
-TSRM_API char *realpath(char *orig_path, char *buffer)
-{/*{{{*/
- int ret = GetFullPathName(orig_path, _MAX_PATH, buffer, NULL);
- if(!ret || ret > _MAX_PATH) {
- return NULL;
- }
- return buffer;
-}/*}}}*/
-
#if HAVE_UTIME
static zend_always_inline void UnixTimeToFileTime(time_t t, LPFILETIME pft) /* {{{ */
{
TSRM_API void *shmat(int key, const void *shmaddr, int flags);
TSRM_API int shmdt(const void *shmaddr);
TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf);
-
-TSRM_API char *realpath(char *orig_path, char *buffer);
#endif
/*
}
/* }}} */
+#ifdef ZEND_WIN32
+static size_t tsrm_win32_realpath_quick(char *path, size_t len, time_t *t) /* {{{ */
+{
+ char tmp_resolved_path[MAXPATHLEN];
+ int tmp_resolved_path_len;
+ BY_HANDLE_FILE_INFORMATION info;
+ realpath_cache_bucket *bucket;
+
+ if (!*t) {
+ *t = time(0);
+ }
+
+ if (CWDG(realpath_cache_size_limit) && (bucket = realpath_cache_find(path, len, *t)) != NULL) {
+ memcpy(path, bucket->realpath, bucket->realpath_len + 1);
+ return bucket->realpath_len;
+ }
+
+#if 0
+ if (!php_win32_ioutil_realpath_ex0(resolved_path, tmp_resolved_path, &info)) {
+ if (CWD_REALPATH == use_realpath) {
+ DWORD err = GetLastError();
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ return 1;
+ } else {
+ /* Fallback to expand only to retain BC. */
+ path_length = tsrm_realpath_r(resolved_path, start, path_length, &ll, &t, use_realpath, 0, NULL);
+ }
+ } else {
+#endif
+
+ if (!php_win32_ioutil_realpath_ex0(path, tmp_resolved_path, &info)) {
+ DWORD err = GetLastError();
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ return (size_t)-1;
+ }
+
+ tmp_resolved_path_len = strlen(tmp_resolved_path);
+ if (CWDG(realpath_cache_size_limit)) {
+ realpath_cache_add(path, len, tmp_resolved_path, tmp_resolved_path_len, info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY, *t);
+ }
+ memmove(path, tmp_resolved_path, tmp_resolved_path_len + 1);
+
+ return tmp_resolved_path_len;
+}
+/* }}} */
+#endif
+
/* Resolve path relatively to state and put the real path into state */
/* returns 0 for ok, 1 for error */
CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath) /* {{{ */
{
size_t path_length = strlen(path);
- char resolved_path[MAXPATHLEN];
+ char resolved_path[MAXPATHLEN] = {0};
size_t start = 1;
int ll = 0;
time_t t;
add_slash = (use_realpath != CWD_REALPATH) && path_length > 0 && IS_SLASH(resolved_path[path_length-1]);
t = CWDG(realpath_cache_ttl) ? 0 : -1;
+#ifdef ZEND_WIN32
+ if (CWD_EXPAND != use_realpath) {
+ size_t tmp_len = tsrm_win32_realpath_quick(resolved_path, path_length, &t);
+ if ((size_t)-1 != tmp_len) {
+ path_length = tmp_len;
+ } else {
+ DWORD err = GetLastError();
+ /* The access denied error can mean something completely else,
+ fallback to complicated way. */
+ if (CWD_REALPATH == use_realpath && ERROR_ACCESS_DENIED != err) {
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ return 1;
+ }
+ path_length = tsrm_realpath_r(resolved_path, start, path_length, &ll, &t, use_realpath, 0, NULL);
+ }
+ } else {
+ path_length = tsrm_realpath_r(resolved_path, start, path_length, &ll, &t, use_realpath, 0, NULL);
+ }
+#else
path_length = tsrm_realpath_r(resolved_path, start, path_length, &ll, &t, use_realpath, 0, NULL);
+#endif
if (path_length == (size_t)-1) {
errno = ENOENT;
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;
#include "zend_call_graph.h"
#include "zend_func_info.h"
#include "zend_inference.h"
+#ifdef _WIN32
+#include "win32/ioutil.h"
+#endif
typedef uint32_t (*info_func_t)(const zend_call_info *call_info, const zend_ssa *ssa);
#ifdef PHP_WIN32
#include "win32/php_win32_globals.h"
#include "win32/time.h"
+#include "win32/ioutil.h"
#endif
typedef struct yy_buffer_state *YY_BUFFER_STATE;
# include "win32/param.h"
# include "win32/winutil.h"
# include "win32/fnmatch.h"
+# include "win32/ioutil.h"
#else
# if HAVE_SYS_PARAM_H
# include <sys/param.h>
var_dump(realpath_cache_size());
$data = realpath_cache_get();
-var_dump($data[__DIR__]);
+var_dump($data[__FILE__]);
echo "Done\n";
?>
["key"]=>
%s(%d%s)
["is_dir"]=>
- bool(true)
+ bool(false)
["realpath"]=>
- string(%d) "%sfile"
+ string(%d) "%sphp"
["expires"]=>
int(%d)
["is_rvalid"]=>
return ret;
}/*}}}*/
+static size_t php_win32_ioutil_realpath_h(HANDLE *h, wchar_t **resolved)
+{/*{{{*/
+ wchar_t ret[PHP_WIN32_IOUTIL_MAXPATHLEN], *ret_real;
+ DWORD ret_len, ret_real_len;
+
+ ret_len = GetFinalPathNameByHandleW(h, ret, PHP_WIN32_IOUTIL_MAXPATHLEN-1, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
+ if (0 == ret_len) {
+ DWORD err = GetLastError();
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ return (size_t)-1;
+ } else if (ret_len > PHP_WIN32_IOUTIL_MAXPATHLEN) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return (size_t)-1;
+ }
+
+ if (NULL == *resolved) {
+ /* ret is expected to be either NULL or a buffer of capable size. */
+ *resolved = (wchar_t *) malloc((ret_len + 1)*sizeof(wchar_t));
+ if (!*resolved) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_NOT_ENOUGH_MEMORY);
+ return (size_t)-1;
+ }
+ }
+
+ ret_real = ret;
+ ret_real_len = ret_len;
+ if (0 == wcsncmp(ret, PHP_WIN32_IOUTIL_UNC_PATH_PREFIXW, PHP_WIN32_IOUTIL_UNC_PATH_PREFIX_LENW)) {
+ ret_real += (PHP_WIN32_IOUTIL_UNC_PATH_PREFIX_LENW - 2);
+ ret_real[0] = L'\\';
+ ret_real_len -= (PHP_WIN32_IOUTIL_UNC_PATH_PREFIX_LENW - 2);
+ } else if (PHP_WIN32_IOUTIL_IS_LONG_PATHW(ret, ret_len)) {
+ ret_real += PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW;
+ ret_real_len -= PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW;
+ }
+ memmove(*resolved, ret_real, (ret_real_len+1)*sizeof(wchar_t));
+
+ return ret_real_len;
+}/*}}}*/
+
+PW32IO wchar_t *php_win32_ioutil_realpath_w(const wchar_t *path, wchar_t *resolved)
+{/*{{{*/
+ return php_win32_ioutil_realpath_w_ex0(path, resolved, NULL);
+}/*}}}*/
+
+PW32IO wchar_t *php_win32_ioutil_realpath_w_ex0(const wchar_t *path, wchar_t *resolved, PBY_HANDLE_FILE_INFORMATION info)
+{/*{{{*/
+ HANDLE h;
+ size_t ret_len;
+
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(path, NULL, 0)
+
+ h = CreateFileW(path,
+ 0,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+ if (INVALID_HANDLE_VALUE == h) {
+ DWORD err = GetLastError();
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ return NULL;
+ }
+
+ ret_len = php_win32_ioutil_realpath_h(h, &resolved);
+ if ((size_t)-1 == ret_len) {
+ DWORD err = GetLastError();
+ CloseHandle(h);
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ return NULL;
+ }
+
+ if (NULL != info && !GetFileInformationByHandle(h, info)) {
+ DWORD err = GetLastError();
+ CloseHandle(h);
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ return NULL;
+ }
+
+ CloseHandle(h);
+
+ return resolved;
+}/*}}}*/
+
+PW32IO char *realpath(const char *path, char *resolved)
+{/*{{{*/
+ return php_win32_ioutil_realpath(path, resolved);
+}/*}}}*/
+
/*
* Local variables:
* tab-width: 4
PW32IO int php_win32_ioutil_access_w(const wchar_t *path, mode_t mode);
PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode);
PW32IO FILE *php_win32_ioutil_fopen_w(const wchar_t *path, const wchar_t *mode);
+PW32IO wchar_t *php_win32_ioutil_realpath_w(const wchar_t *path, wchar_t *resolved);
+PW32IO wchar_t *php_win32_ioutil_realpath_w_ex0(const wchar_t *path, wchar_t *resolved, PBY_HANDLE_FILE_INFORMATION info);
__forceinline static int php_win32_ioutil_access(const char *path, mode_t mode)
{/*{{{*/
return ret;
}/*}}}*/
+#define HAVE_REALPATH 1
+PW32IO char *realpath(const char *path, char *resolved);
+
+__forceinline static char *php_win32_ioutil_realpath_ex0(const char *path, char *resolved, PBY_HANDLE_FILE_INFORMATION info)
+{/*{{{*/
+ wchar_t retw[PHP_WIN32_IOUTIL_MAXPATHLEN];
+ char *reta;
+ size_t reta_len;
+
+ PHP_WIN32_IOUTIL_INIT_W(path)
+ if (!pathw) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ if (NULL == php_win32_ioutil_realpath_w_ex0(pathw, retw, info)) {
+ DWORD err = GetLastError();
+ PHP_WIN32_IOUTIL_CLEANUP_W()
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ return NULL;
+ }
+
+ reta = php_win32_cp_conv_w_to_any(retw, PHP_WIN32_CP_IGNORE_LEN, &reta_len);
+ if (!reta || reta_len > PHP_WIN32_IOUTIL_MAXPATHLEN) {
+ DWORD err = GetLastError();
+ PHP_WIN32_IOUTIL_CLEANUP_W()
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ return NULL;
+ }
+
+ if (NULL == resolved) {
+ /* ret is expected to be either NULL or a buffer of capable size. */
+ resolved = (char *) malloc(reta_len + 1);
+ if (!resolved) {
+ free(reta);
+ PHP_WIN32_IOUTIL_CLEANUP_W()
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+ }
+ memmove(resolved, reta, reta_len+1);
+
+ PHP_WIN32_IOUTIL_CLEANUP_W()
+ free(reta);
+
+ return resolved;
+}/*}}}*/
+
+__forceinline static char *php_win32_ioutil_realpath(const char *path, char *resolved)
+{/*{{{*/
+ return php_win32_ioutil_realpath_ex0(path, resolved, NULL);
+}/*}}}*/
+
#ifdef __cplusplus
}
#endif