summaryrefslogtreecommitdiff
path: root/Zend/zend_virtual_cwd.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_virtual_cwd.c')
-rw-r--r--Zend/zend_virtual_cwd.c245
1 files changed, 165 insertions, 80 deletions
diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c
index 4dbbb5ea5b..7861e95334 100644
--- a/Zend/zend_virtual_cwd.c
+++ b/Zend/zend_virtual_cwd.c
@@ -218,38 +218,31 @@ static inline time_t FileTimeToUnixTime(const FILETIME *FileTime)
}
CWD_API int php_sys_readlink(const char *link, char *target, size_t target_len){ /* {{{ */
- HINSTANCE kernel32;
HANDLE hFile;
DWORD dwRet;
+ wchar_t *linkw = php_win32_ioutil_any_to_w(link), targetw[MAXPATHLEN];
+ size_t _tmp_len;
+ char *_tmp;
- typedef BOOL (WINAPI *gfpnh_func)(HANDLE, LPTSTR, DWORD, DWORD);
- gfpnh_func pGetFinalPathNameByHandle;
-
- if (!target_len) {
+ if (!linkw) {
return -1;
}
- kernel32 = LoadLibrary("kernel32.dll");
-
- if (kernel32) {
- pGetFinalPathNameByHandle = (gfpnh_func)GetProcAddress(kernel32, "GetFinalPathNameByHandleA");
- if (pGetFinalPathNameByHandle == NULL) {
- return -1;
- }
- } else {
+ if (!target_len) {
+ free(linkw);
return -1;
}
- hFile = CreateFile(link, // file to open
+ hFile = CreateFileW(linkw, // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_FLAG_BACKUP_SEMANTICS, // normal file
NULL); // no attr. template
-
if( hFile == INVALID_HANDLE_VALUE) {
- return -1;
+ free(linkw);
+ return -1;
}
/* Despite MSDN has documented it won't to, the length returned by
@@ -258,12 +251,24 @@ CWD_API int php_sys_readlink(const char *link, char *target, size_t target_len){
with VS2012 and earlier, and seems not to be fixed till
now. Thus, correcting target_len so it's suddenly don't
overflown. */
- dwRet = pGetFinalPathNameByHandle(hFile, target, target_len - 1, VOLUME_NAME_DOS);
+ dwRet = GetFinalPathNameByHandleW(hFile, targetw, MAXPATHLEN, VOLUME_NAME_DOS);
if(dwRet >= target_len || dwRet >= MAXPATHLEN || dwRet == 0) {
+ free(linkw);
+ CloseHandle(hFile);
return -1;
}
+ _tmp = php_win32_ioutil_conv_w_to_any(targetw, dwRet, &_tmp_len);
+ if (!_tmp || _tmp_len >= MAXPATHLEN) {
+ CloseHandle(hFile);
+ free(linkw);
+ return -1;
+ }
+ memcpy(target, _tmp, _tmp_len);
+ free(_tmp);
+
CloseHandle(hFile);
+ free(linkw);
if(dwRet > 4) {
/* Skip first 4 characters if they are "\??\" */
@@ -295,9 +300,22 @@ CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat) /* {{
LARGE_INTEGER t;
const size_t path_len = strlen(path);
ALLOCA_FLAG(use_heap_large);
+ wchar_t *pathw = php_win32_ioutil_any_to_w(path);
+
+ if (!pathw) {
+ return -1;
+ }
- if (!GetFileAttributesEx(path, GetFileExInfoStandard, &data)) {
- return zend_stat(path, buf);
+ if (!GetFileAttributesExW(pathw, GetFileExInfoStandard, &data)) {
+ int ret;
+#if ZEND_ENABLE_ZVAL_LONG64
+ ret = _wstat64(pathw, buf);
+#else
+ ret = _wstat(pathw, (struct _stat32 *)buf);
+#endif
+ free(pathw);
+
+ return ret;
}
if (path_len >= 1 && path[1] == ':') {
@@ -309,18 +327,18 @@ CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat) /* {{
} else if (IS_UNC_PATH(path, path_len)) {
buf->st_dev = buf->st_rdev = 0;
} else {
- char cur_path[MAXPATHLEN+1];
+ wchar_t cur_path[MAXPATHLEN+1];
DWORD len = sizeof(cur_path);
- char *tmp = cur_path;
+ wchar_t *tmp = cur_path;
while(1) {
- DWORD r = GetCurrentDirectory(len, tmp);
+ DWORD r = GetCurrentDirectoryW(len, tmp);
if (r < len) {
- if (tmp[1] == ':') {
- if (path[0] >= 'A' && path[0] <= 'Z') {
- buf->st_dev = buf->st_rdev = path[0] - 'A';
+ if (tmp[1] == L':') {
+ if (pathw[0] >= L'A' && pathw[0] <= L'Z') {
+ buf->st_dev = buf->st_rdev = pathw[0] - L'A';
} else {
- buf->st_dev = buf->st_rdev = path[0] - 'a';
+ buf->st_dev = buf->st_rdev = pathw[0] - L'a';
}
} else {
buf->st_dev = buf->st_rdev = -1;
@@ -331,7 +349,7 @@ CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat) /* {{
break;
} else {
len = r+1;
- tmp = (char*)malloc(len);
+ tmp = (wchar_t*)malloc(len*sizeof(wchar_t));
}
}
if (tmp != cur_path) {
@@ -347,8 +365,9 @@ CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat) /* {{
REPARSE_DATA_BUFFER * pbuffer;
DWORD retlength = 0;
- hLink = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ hLink = CreateFileW(pathw, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL);
if(hLink == INVALID_HANDLE_VALUE) {
+ free(pathw);
return -1;
}
@@ -356,6 +375,7 @@ CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat) /* {{
if(!DeviceIoControl(hLink, FSCTL_GET_REPARSE_POINT, NULL, 0, pbuffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &retlength, NULL)) {
free_alloca(pbuffer, use_heap_large);
CloseHandle(hLink);
+ free(pathw);
return -1;
}
@@ -399,6 +419,9 @@ CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat) /* {{
buf->st_atime = FileTimeToUnixTime(&data.ftLastAccessTime);
buf->st_ctime = FileTimeToUnixTime(&data.ftCreationTime);
buf->st_mtime = FileTimeToUnixTime(&data.ftLastWriteTime);
+
+ free(pathw);
+
return 0;
}
/* }}} */
@@ -778,9 +801,13 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
int i, j, save;
int directory = 0;
#ifdef ZEND_WIN32
- WIN32_FIND_DATA data;
- HANDLE hFind;
+ WIN32_FIND_DATAW dataw;
+ HANDLE hFind = INVALID_HANDLE_VALUE;
ALLOCA_FLAG(use_heap_large)
+ wchar_t *pathw = NULL;
+#define FREE_PATHW() \
+ do { free(pathw); } while(0);
+
#else
zend_stat_t st;
#endif
@@ -873,17 +900,23 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
}
#ifdef ZEND_WIN32
- if (save && (hFind = FindFirstFile(path, &data)) == INVALID_HANDLE_VALUE) {
- if (use_realpath == CWD_REALPATH) {
- /* file not found */
+ if (save) {
+ pathw = php_win32_ioutil_any_to_w(path);
+ if (!pathw) {
return -1;
}
- /* continue resolution anyway but don't save result in the cache */
- save = 0;
- }
-
- if (save) {
- FindClose(hFind);
+ hFind = FindFirstFileW(pathw, &dataw);
+ if (INVALID_HANDLE_VALUE == hFind) {
+ if (use_realpath == CWD_REALPATH) {
+ /* file not found */
+ FREE_PATHW()
+ return -1;
+ }
+ /* continue resolution anyway but don't save result in the cache */
+ save = 0;
+ } else {
+ FindClose(hFind);
+ }
}
tmp = do_alloca(len+1, use_heap);
@@ -891,7 +924,8 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
if(save &&
!(IS_UNC_PATH(path, len) && len >= 3 && path[2] != '?') &&
- (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
+ (dataw.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
+ ) {
/* File is a reparse point. Get the target */
HANDLE hLink = NULL;
REPARSE_DATA_BUFFER * pbuffer;
@@ -899,28 +933,35 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
int bufindex = 0, isabsolute = 0;
wchar_t * reparsetarget;
BOOL isVolume = FALSE;
- char printname[MAX_PATH];
- char substitutename[MAX_PATH];
+ char *printname = NULL, *substitutename = NULL;
int printname_len, substitutename_len;
int substitutename_off = 0;
if(++(*ll) > LINK_MAX) {
+ free_alloca(tmp, use_heap);
+ FREE_PATHW()
return -1;
}
- hLink = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ hLink = CreateFileW(pathw, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL);
if(hLink == INVALID_HANDLE_VALUE) {
+ free_alloca(tmp, use_heap);
+ FREE_PATHW()
return -1;
}
pbuffer = (REPARSE_DATA_BUFFER *)do_alloca(MAXIMUM_REPARSE_DATA_BUFFER_SIZE, use_heap_large);
if (pbuffer == NULL) {
CloseHandle(hLink);
+ free_alloca(tmp, use_heap);
+ FREE_PATHW()
return -1;
}
if(!DeviceIoControl(hLink, FSCTL_GET_REPARSE_POINT, NULL, 0, pbuffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &retlength, NULL)) {
free_alloca(pbuffer, use_heap_large);
+ free_alloca(tmp, use_heap);
CloseHandle(hLink);
+ FREE_PATHW()
return -1;
}
@@ -930,60 +971,63 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
reparsetarget = pbuffer->SymbolicLinkReparseBuffer.ReparseTarget;
printname_len = pbuffer->MountPointReparseBuffer.PrintNameLength / sizeof(WCHAR);
isabsolute = (pbuffer->SymbolicLinkReparseBuffer.Flags == 0) ? 1 : 0;
- if (!WideCharToMultiByte(CP_THREAD_ACP, 0,
- reparsetarget + pbuffer->MountPointReparseBuffer.PrintNameOffset / sizeof(WCHAR),
- printname_len + 1,
- printname, MAX_PATH, NULL, NULL
- )) {
+ printname = php_win32_ioutil_w_to_any(reparsetarget + pbuffer->MountPointReparseBuffer.PrintNameOffset / sizeof(WCHAR));
+ if (!printname) {
free_alloca(pbuffer, use_heap_large);
+ free_alloca(tmp, use_heap);
+ FREE_PATHW()
return -1;
- };
- printname_len = pbuffer->MountPointReparseBuffer.PrintNameLength / sizeof(WCHAR);
- printname[printname_len] = 0;
+ }
substitutename_len = pbuffer->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
- if (!WideCharToMultiByte(CP_THREAD_ACP, 0,
- reparsetarget + pbuffer->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR),
- substitutename_len + 1,
- substitutename, MAX_PATH, NULL, NULL
- )) {
+ substitutename = php_win32_ioutil_w_to_any(reparsetarget + pbuffer->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR));
+ if (!substitutename) {
free_alloca(pbuffer, use_heap_large);
+ free_alloca(tmp, use_heap);
+ free(printname);
+ FREE_PATHW()
return -1;
- };
- substitutename[substitutename_len] = 0;
+ }
}
else if(pbuffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
isabsolute = 1;
reparsetarget = pbuffer->MountPointReparseBuffer.ReparseTarget;
printname_len = pbuffer->MountPointReparseBuffer.PrintNameLength / sizeof(WCHAR);
- if (!WideCharToMultiByte(CP_THREAD_ACP, 0,
- reparsetarget + pbuffer->MountPointReparseBuffer.PrintNameOffset / sizeof(WCHAR),
- printname_len + 1,
- printname, MAX_PATH, NULL, NULL
- )) {
+ printname = php_win32_ioutil_w_to_any(reparsetarget + pbuffer->MountPointReparseBuffer.PrintNameOffset / sizeof(WCHAR));
+ if (!printname) {
free_alloca(pbuffer, use_heap_large);
+ free_alloca(tmp, use_heap);
+ FREE_PATHW()
return -1;
- };
- printname[pbuffer->MountPointReparseBuffer.PrintNameLength / sizeof(WCHAR)] = 0;
+ }
+
substitutename_len = pbuffer->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
- if (!WideCharToMultiByte(CP_THREAD_ACP, 0,
- reparsetarget + pbuffer->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR),
- substitutename_len + 1,
- substitutename, MAX_PATH, NULL, NULL
- )) {
+ substitutename = php_win32_ioutil_w_to_any(reparsetarget + pbuffer->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR));
+ if (!substitutename) {
free_alloca(pbuffer, use_heap_large);
+ free_alloca(tmp, use_heap);
+ free(printname);
+ FREE_PATHW()
return -1;
- };
- substitutename[substitutename_len] = 0;
+ }
}
else if (pbuffer->ReparseTag == IO_REPARSE_TAG_DEDUP) {
isabsolute = 1;
+ substitutename = malloc((len + 1) * sizeof(char));
+ if (!substitutename) {
+ free_alloca(pbuffer, use_heap_large);
+ free_alloca(tmp, use_heap);
+ FREE_PATHW()
+ return -1;
+ }
memcpy(substitutename, path, len + 1);
substitutename_len = len;
} else {
/* XXX this might be not the end, restart handling with REPARSE_GUID_DATA_BUFFER should be implemented. */
free_alloca(pbuffer, use_heap_large);
+ free_alloca(tmp, use_heap);
+ FREE_PATHW()
return -1;
}
@@ -1028,6 +1072,8 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
fprintf(stderr, "resolved: %s ", path);
#endif
free_alloca(pbuffer, use_heap_large);
+ free(printname);
+ free(substitutename);
if(isabsolute == 1) {
if (!((j == 3) && (path[1] == ':') && (path[2] == '\\'))) {
@@ -1035,6 +1081,7 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
j = tsrm_realpath_r(path, 0, j, ll, t, 0, is_dir, &directory);
if(j < 0) {
free_alloca(tmp, use_heap);
+ FREE_PATHW()
return -1;
}
}
@@ -1042,6 +1089,7 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
else {
if(i + j >= MAXPATHLEN - 1) {
free_alloca(tmp, use_heap);
+ FREE_PATHW()
return -1;
}
@@ -1051,10 +1099,11 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
j = tsrm_realpath_r(path, start, i + j, ll, t, use_realpath, is_dir, &directory);
if(j < 0) {
free_alloca(tmp, use_heap);
+ FREE_PATHW()
return -1;
}
}
- directory = (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+ directory = (dataw.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
if(link_is_dir) {
*link_is_dir = directory;
@@ -1062,9 +1111,11 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
}
else {
if (save) {
- directory = (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ directory = (dataw.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
if (is_dir && !directory) {
/* not a directory */
+ free_alloca(tmp, use_heap);
+ FREE_PATHW()
return -1;
}
}
@@ -1141,11 +1192,20 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
#ifdef ZEND_WIN32
if (j < 0 || j + len - i >= MAXPATHLEN-1) {
free_alloca(tmp, use_heap);
+ FREE_PATHW()
return -1;
}
if (save) {
- i = (int)strlen(data.cFileName);
- memcpy(path+j, data.cFileName, i+1);
+ size_t sz;
+ char *tmp_path = php_win32_ioutil_conv_w_to_any(dataw.cFileName, PHP_WIN32_CP_IGNORE_LEN, &sz);
+ if (!tmp_path) {
+ free_alloca(tmp, use_heap);
+ FREE_PATHW()
+ return -1;
+ }
+ i = (int)sz;
+ memcpy(path+j, tmp_path, i+1);
+ free(tmp_path);
j += i;
} else {
/* use the original file or directory name as it wasn't found */
@@ -1169,6 +1229,10 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
}
free_alloca(tmp, use_heap);
+#ifdef ZEND_WIN32
+ FREE_PATHW()
+#undef FREE_PATHW
+#endif
return j;
}
}
@@ -1502,7 +1566,11 @@ CWD_API FILE *virtual_fopen(const char *path, const char *mode) /* {{{ */
return NULL;
}
+#ifdef ZEND_WIN32
+ f = php_win32_ioutil_fopen(new_state.cwd, mode);
+#else
f = fopen(new_state.cwd, mode);
+#endif
CWD_STATE_FREE_ERR(&new_state);
@@ -1580,9 +1648,11 @@ CWD_API int virtual_chmod(const char *filename, mode_t mode) /* {{{ */
if (_tmp & _S_IWRITE) {
mode |= _S_IWRITE;
}
+ ret = php_win32_ioutil_chmod(new_state.cwd, mode);
}
-#endif
+#else
ret = chmod(new_state.cwd, mode);
+#endif
CWD_STATE_FREE_ERR(&new_state);
return ret;
@@ -1636,9 +1706,17 @@ CWD_API int virtual_open(const char *path, int flags, ...) /* {{{ */
mode = (mode_t) va_arg(arg, int);
va_end(arg);
+#ifdef ZEND_WIN32
+ f = php_win32_ioutil_open(new_state.cwd, flags, mode);
+#else
f = open(new_state.cwd, flags, mode);
+#endif
} else {
+#ifdef ZEND_WIN32
+ f = php_win32_ioutil_open(new_state.cwd, flags);
+#else
f = open(new_state.cwd, flags);
+#endif
}
CWD_STATE_FREE_ERR(&new_state);
return f;
@@ -1688,7 +1766,7 @@ CWD_API int virtual_rename(const char *oldname, const char *newname) /* {{{ */
MoveFileEx has to be used */
#ifdef ZEND_WIN32
/* MoveFileEx returns 0 on failure, other way 'round for this function */
- retval = (MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING|MOVEFILE_COPY_ALLOWED) == 0) ? -1 : 0;
+ retval = php_win32_ioutil_rename(oldname, newname);
#else
retval = rename(oldname, newname);
#endif
@@ -1747,7 +1825,11 @@ CWD_API int virtual_unlink(const char *path) /* {{{ */
return -1;
}
+#ifdef ZEND_WIN32
+ retval = php_win32_ioutil_unlink(new_state.cwd);
+#else
retval = unlink(new_state.cwd);
+#endif
CWD_STATE_FREE_ERR(&new_state);
return retval;
@@ -1766,7 +1848,7 @@ CWD_API int virtual_mkdir(const char *pathname, mode_t mode) /* {{{ */
}
#ifdef ZEND_WIN32
- retval = mkdir(new_state.cwd);
+ retval = php_win32_ioutil_mkdir(new_state.cwd, mode);
#else
retval = mkdir(new_state.cwd, mode);
#endif
@@ -1786,8 +1868,11 @@ CWD_API int virtual_rmdir(const char *pathname) /* {{{ */
return -1;
}
+#ifdef ZEND_WIN32
+ retval = php_win32_ioutil_rmdir(new_state.cwd);
+#else
retval = rmdir(new_state.cwd);
-
+#endif
CWD_STATE_FREE_ERR(&new_state);
return retval;
}