php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login

Patch add_php_sys_readlink for SPL related Bug #51804

Patch version 2010-09-06 15:14 UTC

Return to Bug #51804 | Download this patch
Patch Revisions:

Developer: pajoye@php.net

Index: ext/spl/spl_directory.c
===================================================================
--- ext/spl/spl_directory.c	(revision 303054)
+++ ext/spl/spl_directory.c	(working copy)
@@ -1050,10 +1050,25 @@
 
 	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling TSRMLS_CC);
 
-#ifdef HAVE_SYMLINK
+#ifdef PHP_WIN32
+	if (!IS_ABSOLUTE_PATH(intern->file_name, intern->file_name_len)) {
+		char expanded_path[MAXPATHLEN];
+
+		if (!expand_filepath(intern->file_name, expanded_path TSRMLS_CC)) {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
+			RETURN_FALSE;
+		}
+		ret = php_sys_readlink(expanded_path, buff, MAXPATHLEN - 1);
+	} else {
+		ret = php_sys_readlink(intern->file_name, buff,  MAXPATHLEN-1);
+	}
+
+#else
+# ifdef HAVE_SYMLINK
 	ret = readlink(intern->file_name, buff, MAXPATHLEN-1);
-#else
+# else
 	ret = -1; /* always fail if not implemented */
+# endif
 #endif
 
 	if (ret == -1) {
Index: TSRM/tsrm_virtual_cwd.c
===================================================================
--- TSRM/tsrm_virtual_cwd.c	(revision 303054)
+++ TSRM/tsrm_virtual_cwd.c	(working copy)
@@ -207,6 +207,61 @@
 	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;
Index: TSRM/tsrm_virtual_cwd.h
===================================================================
--- TSRM/tsrm_virtual_cwd.h	(revision 303054)
+++ TSRM/tsrm_virtual_cwd.h	(working copy)
@@ -133,9 +133,13 @@
 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)
+# define php_sys_readlink(link, target, target_len) 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 {
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Thu Apr 17 01:01:56 2014 UTC