From bf0a5ea7452032ca09d71835c548d9d5db398850 Mon Sep 17 00:00:00 2001 From: Pierre Joye Date: Fri, 10 Sep 2010 14:01:44 +0000 Subject: [PATCH] - add php_sys_readlink --- TSRM/tsrm_virtual_cwd.c | 54 +++++++++++++++++++++++++++++++++++++++++ TSRM/tsrm_virtual_cwd.h | 4 +++ UPGRADING.INTERNALS | 7 ++++++ 3 files changed, 65 insertions(+) diff --git a/TSRM/tsrm_virtual_cwd.c b/TSRM/tsrm_virtual_cwd.c index 48aeeb59c20d0..25d56f2a80858 100644 --- a/TSRM/tsrm_virtual_cwd.c +++ b/TSRM/tsrm_virtual_cwd.c @@ -207,6 +207,60 @@ static inline time_t FileTimeToUnixTime(const FILETIME FileTime) return (time_t)UnixTime; } +CWD_API int php_sys_readlink(const char *link, char *target, size_t target_len){ /* {{{ */ + HINSTANCE kernel32; + HANDLE hFile; + DWORD dwRet; + + typedef BOOL (WINAPI *gfpnh_func)(HANDLE, LPTSTR, DWORD, DWORD); + gfpnh_func pGetFinalPathNameByHandle; + + kernel32 = LoadLibrary("kernel32.dll"); + + if (kernel32) { + pGetFinalPathNameByHandle = (gfpnh_func)GetProcAddress(kernel32, "GetFinalPathNameByHandleA"); + if (pGetFinalPathNameByHandle == NULL) { + return -1; + } + } else { + return -1; + } + + hFile = CreateFile(link, // 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; + } + + dwRet = pGetFinalPathNameByHandle(hFile, target, MAXPATHLEN, VOLUME_NAME_DOS); + if(dwRet >= MAXPATHLEN) { + return -1; + } + + CloseHandle(hFile); + + if(dwRet > 4) { + /* Skip first 4 characters if they are "\??\" */ + if(target[0] == '\\' && target[1] == '\\' && target[2] == '?' && target[3] == '\\') { + char tmp[MAXPATHLEN]; + + dwRet -= 4; + memcpy(tmp, target + 4, dwRet); + memcpy(target, tmp, dwRet); + } + } + + target[dwRet] = '\0'; + return dwRet; +} +/* }}} */ + CWD_API int php_sys_stat_ex(const char *path, struct stat *buf, int lstat) /* {{{ */ { WIN32_FILE_ATTRIBUTE_DATA data; diff --git a/TSRM/tsrm_virtual_cwd.h b/TSRM/tsrm_virtual_cwd.h index 44ed99e345aa6..b26d2234af3f0 100644 --- a/TSRM/tsrm_virtual_cwd.h +++ b/TSRM/tsrm_virtual_cwd.h @@ -133,9 +133,13 @@ typedef unsigned short mode_t; CWD_API int php_sys_stat_ex(const char *path, struct stat *buf, int lstat); # define php_sys_stat(path, buf) php_sys_stat_ex(path, buf, 0) # define php_sys_lstat(path, buf) php_sys_stat_ex(path, buf, 1) +CWD_API int php_sys_readlink(link, target, target_len); #else # define php_sys_stat stat # define php_sys_lstat lstat +# ifdef HAVE_SYMLINK +# define php_sys_readlink(link, target, target_len) readlink(link, target, target_len) +# endif #endif typedef struct _cwd_state { diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 79572eb2e9d74..d86dfc6f6b18f 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -20,3 +20,10 @@ lstat is now available on all platforms. On unix-like platform php_sys_lstat is an alias to lstat (when avaible). On Windows it is now available using php_sys_lstat. php_sys_stat and php_sys_lstat usage is recommended instead of calling lstat directly, to ensure portability. + + b. readlink support + +readlink is now available on all platforms. On unix-like platform +php_sys_readlink is an alias to readlink (when avaible). On Windows it is now +available using php_sys_readlink. php_sys_readlink usage is recommended +instead of calling readlink directly, to ensure portability.