diff options
Diffstat (limited to 'Zend/zend_virtual_cwd.c')
-rw-r--r-- | Zend/zend_virtual_cwd.c | 276 |
1 files changed, 10 insertions, 266 deletions
diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c index 220e14b675..d1ec9e35ff 100644 --- a/Zend/zend_virtual_cwd.c +++ b/Zend/zend_virtual_cwd.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 7 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2018 The PHP Group | + | Copyright (c) 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 | @@ -70,6 +70,9 @@ # ifndef VOLUME_NAME_DOS # define VOLUME_NAME_DOS 0x0 # endif + +# include <winioctl.h> +# include <winnt.h> #endif #ifndef HAVE_REALPATH @@ -87,6 +90,7 @@ MUTEX_T cwd_mutex; #ifdef ZTS ts_rsrc_id cwd_globals_id; +size_t cwd_globals_offset; #else virtual_cwd_globals cwd_globals; #endif @@ -120,259 +124,6 @@ static cwd_state main_cwd_state; /* True global */ # define CWD_STATE_FREE_ERR(state) CWD_STATE_FREE(state) #endif -#ifdef ZEND_WIN32 - -#ifdef CTL_CODE -#undef CTL_CODE -#endif -#define CTL_CODE(DeviceType,Function,Method,Access) (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) -#define FILE_DEVICE_FILE_SYSTEM 0x00000009 -#define METHOD_BUFFERED 0 -#define FILE_ANY_ACCESS 0 -#define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 ) - -typedef struct { - unsigned long ReparseTag; - unsigned short ReparseDataLength; - unsigned short Reserved; - union { - struct { - unsigned short SubstituteNameOffset; - unsigned short SubstituteNameLength; - unsigned short PrintNameOffset; - unsigned short PrintNameLength; - unsigned long Flags; - wchar_t ReparseTarget[1]; - } SymbolicLinkReparseBuffer; - struct { - unsigned short SubstituteNameOffset; - unsigned short SubstituteNameLength; - unsigned short PrintNameOffset; - unsigned short PrintNameLength; - wchar_t ReparseTarget[1]; - } MountPointReparseBuffer; - struct { - unsigned char ReparseTarget[1]; - } GenericReparseBuffer; - }; -} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; - -#define SECS_BETWEEN_EPOCHS (__int64)11644473600 -#define SECS_TO_100NS (__int64)10000000 -static inline time_t FileTimeToUnixTime(const FILETIME *FileTime) -{ - __int64 UnixTime; - SYSTEMTIME SystemTime; - FileTimeToSystemTime(FileTime, &SystemTime); - - UnixTime = ((__int64)FileTime->dwHighDateTime << 32) + - FileTime->dwLowDateTime; - - UnixTime -= (SECS_BETWEEN_EPOCHS * SECS_TO_100NS); - - UnixTime /= SECS_TO_100NS; /* now convert to seconds */ - - if ((time_t)UnixTime != UnixTime) { - UnixTime = 0; - } - return (time_t)UnixTime; -} - -CWD_API ssize_t php_sys_readlink(const char *link, char *target, size_t target_len){ /* {{{ */ - HANDLE hFile; - wchar_t *linkw = php_win32_ioutil_any_to_w(link), targetw[MAXPATHLEN]; - size_t ret_len, targetw_len, offset = 0; - char *ret; - - if (!linkw) { - return -1; - } - - if (!target_len) { - free(linkw); - return -1; - } - - hFile = CreateFileW(linkw, // file to open - 0, // query possible attributes - PHP_WIN32_IOUTIL_DEFAULT_SHARE_MODE, - NULL, // default security - OPEN_EXISTING, // existing file only - FILE_FLAG_BACKUP_SEMANTICS, // normal file - NULL); // no attr. template - if( hFile == INVALID_HANDLE_VALUE) { - free(linkw); - return -1; - } - - /* Despite MSDN has documented it won't to, the length returned by - GetFinalPathNameByHandleA includes the length of the - null terminator. This behavior is at least reproducible - with VS2012 and earlier, and seems not to be fixed till - now. Thus, correcting target_len so it's suddenly don't - overflown. */ - targetw_len = GetFinalPathNameByHandleW(hFile, targetw, MAXPATHLEN, VOLUME_NAME_DOS); - if(targetw_len >= target_len || targetw_len >= MAXPATHLEN || targetw_len == 0) { - free(linkw); - CloseHandle(hFile); - return -1; - } - - if(targetw_len > 4) { - /* Skip first 4 characters if they are "\\?\" */ - if(targetw[0] == L'\\' && targetw[1] == L'\\' && targetw[2] == L'?' && targetw[3] == L'\\') { - offset = 4; - - /* \\?\UNC\ */ - if (targetw_len > 7 && targetw[4] == L'U' && targetw[5] == L'N' && targetw[6] == L'C') { - offset += 2; - targetw[offset] = L'\\'; - } - } - } - - ret = php_win32_ioutil_conv_w_to_any(targetw + offset, targetw_len - offset, &ret_len); - if (!ret || ret_len >= MAXPATHLEN) { - CloseHandle(hFile); - free(linkw); - free(ret); - return -1; - } - memcpy(target, ret, ret_len + 1); - - free(ret); - CloseHandle(hFile); - free(linkw); - - return (ssize_t)ret_len; -} -/* }}} */ - -CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat) /* {{{ */ -{ - WIN32_FILE_ATTRIBUTE_DATA data; - LARGE_INTEGER t; - size_t pathw_len = 0; - ALLOCA_FLAG(use_heap_large) - wchar_t *pathw = php_win32_ioutil_conv_any_to_w(path, PHP_WIN32_CP_IGNORE_LEN, &pathw_len); - - if (!pathw) { - return -1; - } - - 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 (pathw_len >= 1 && pathw[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 = pathw[0] - L'a'; - } - } else if (PHP_WIN32_IOUTIL_IS_UNC(pathw, pathw_len)) { - buf->st_dev = buf->st_rdev = 0; - } else { - wchar_t cur_path[MAXPATHLEN+1]; - - if (NULL != _wgetcwd(cur_path, sizeof(cur_path)/sizeof(wchar_t))) { - if (cur_path[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 = pathw[0] - L'a'; - } - } else { - buf->st_dev = buf->st_rdev = -1; - } - } else { - buf->st_dev = buf->st_rdev = -1; - } - } - - buf->st_uid = buf->st_gid = buf->st_ino = 0; - - if (lstat && data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - /* File is a reparse point. Get the target */ - HANDLE hLink = NULL; - REPARSE_DATA_BUFFER * pbuffer; - DWORD retlength = 0; - - hLink = CreateFileW(pathw, - FILE_READ_ATTRIBUTES, - PHP_WIN32_IOUTIL_DEFAULT_SHARE_MODE, - NULL, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, - NULL); - if(hLink == INVALID_HANDLE_VALUE) { - free(pathw); - return -1; - } - - pbuffer = (REPARSE_DATA_BUFFER *)do_alloca(MAXIMUM_REPARSE_DATA_BUFFER_SIZE, use_heap_large); - 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; - } - - CloseHandle(hLink); - - if(pbuffer->ReparseTag == IO_REPARSE_TAG_SYMLINK) { - buf->st_mode = S_IFLNK; - 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 0 /* Not used yet */ - else if(pbuffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { - buf->st_mode |=; - } -#endif - free_alloca(pbuffer, use_heap_large); - } else { - 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) { - if (pathw_len >= 4 && pathw[pathw_len-4] == L'.') { - if (_wcsnicmp(pathw+pathw_len-3, L"exe", 3) == 0 || - _wcsnicmp(pathw+pathw_len-3, L"com", 3) == 0 || - _wcsnicmp(pathw+pathw_len-3, L"bat", 3) == 0 || - _wcsnicmp(pathw+pathw_len-3, L"cmd", 3) == 0) { - buf->st_mode |= (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6)); - } - } - } - - buf->st_nlink = 1; - t.HighPart = data.nFileSizeHigh; - t.LowPart = data.nFileSizeLow; - /* It's an overflow on 32 bit, however it won't fix as long - as zend_long is 32 bit. */ - buf->st_size = (zend_long)t.QuadPart; - buf->st_atime = FileTimeToUnixTime(&data.ftLastAccessTime); - buf->st_ctime = FileTimeToUnixTime(&data.ftCreationTime); - buf->st_mtime = FileTimeToUnixTime(&data.ftLastWriteTime); - - free(pathw); - - return 0; -} -/* }}} */ -#endif - static int php_is_dir_ok(const cwd_state *state) /* {{{ */ { zend_stat_t buf; @@ -445,7 +196,7 @@ CWD_API void virtual_cwd_startup(void) /* {{{ */ { virtual_cwd_main_cwd_init(0); #ifdef ZTS - ts_allocate_id(&cwd_globals_id, sizeof(virtual_cwd_globals), (ts_allocate_ctor) cwd_globals_ctor, (ts_allocate_dtor) cwd_globals_dtor); + ts_allocate_fast_id(&cwd_globals_id, &cwd_globals_offset, sizeof(virtual_cwd_globals), (ts_allocate_ctor) cwd_globals_ctor, (ts_allocate_dtor) cwd_globals_dtor); #else cwd_globals_ctor(&cwd_globals); #endif @@ -877,7 +628,7 @@ retry_reparse_tag_cloud: ) { /* File is a reparse point. Get the target */ HANDLE hLink = NULL; - REPARSE_DATA_BUFFER * pbuffer; + PHP_WIN32_IOUTIL_REPARSE_DATA_BUFFER * pbuffer; DWORD retlength = 0; size_t bufindex = 0; uint8_t isabsolute = 0; @@ -910,7 +661,7 @@ retry_reparse_tag_cloud: return (size_t)-1; } - pbuffer = (REPARSE_DATA_BUFFER *)do_alloca(MAXIMUM_REPARSE_DATA_BUFFER_SIZE, use_heap_large); + pbuffer = (PHP_WIN32_IOUTIL_REPARSE_DATA_BUFFER *)do_alloca(MAXIMUM_REPARSE_DATA_BUFFER_SIZE, use_heap_large); if (pbuffer == NULL) { CloseHandle(hLink); free_alloca(tmp, use_heap); @@ -944,7 +695,7 @@ retry_reparse_tag_cloud: if(pbuffer->ReparseTag == IO_REPARSE_TAG_SYMLINK) { may_retry_reparse_point = 1; reparsetarget = pbuffer->SymbolicLinkReparseBuffer.ReparseTarget; - isabsolute = (pbuffer->SymbolicLinkReparseBuffer.Flags == 0) ? 1 : 0; + isabsolute = pbuffer->SymbolicLinkReparseBuffer.Flags == 0; #if VIRTUAL_CWD_DEBUG printname = php_win32_ioutil_w_to_any(reparsetarget + pbuffer->MountPointReparseBuffer.PrintNameOffset / sizeof(WCHAR)); if (!printname) { @@ -1268,7 +1019,7 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func if (!path_length || path_length >= MAXPATHLEN-1) { #ifdef ZEND_WIN32 - _set_errno(EINVAL); + SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER); #else errno = EINVAL; #endif @@ -1986,10 +1737,3 @@ CWD_API char *tsrm_realpath(const char *path, char *real_path) /* {{{ */ } } /* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - */ |