/*
TODO:
-- Create php_readlink, php_link and php_symlink in win32/link.c
+- Create php_readlink (done), php_link and php_symlink in win32/link.c
- Expose them (PHPAPI) so extensions developers can use them
- define link/readlink/symlink to their php_ equivalent and use them in ext/standart/link.c
- this file is then useless and we have a portable link API
Return the target of a symbolic link */
PHP_FUNCTION(readlink)
{
- HINSTANCE kernel32;
char *link;
int link_len;
- TCHAR Path[MAXPATHLEN];
- char path_resolved[MAXPATHLEN];
- 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) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't call GetFinalPathNameByHandleA");
- RETURN_FALSE;
- }
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't call get a handle on kernel32.dll");
- RETURN_FALSE;
- }
+ char target[MAXPATHLEN];
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &link, &link_len) == FAILURE) {
return;
}
- if (php_check_open_basedir(link TSRMLS_CC)) {
+ if (OPENBASEDIR_CHECKPATH(link)) {
RETURN_FALSE;
}
- if (!expand_filepath(link, path_resolved TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
- RETURN_FALSE;
- }
- hFile = CreateFile(path_resolved, // 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) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not open file (error %d)", GetLastError());
- RETURN_FALSE;
- }
-
- dwRet = pGetFinalPathNameByHandle(hFile, Path, MAXPATHLEN, VOLUME_NAME_DOS);
- if(dwRet >= MAXPATHLEN) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't resolve the full path, the path exceeds the MAX_PATH_LEN (%d) limit", MAXPATHLEN);
- RETURN_FALSE;
- }
-
- CloseHandle(hFile);
- /* Append NULL to the end of the string */
- Path[dwRet] = '\0';
-
- if(dwRet > 4) {
- /* Skip first 4 characters if they are "\??\" */
- if(Path[0] == '\\' && Path[1] == '\\' && Path[2] == '?' && Path[3] == '\\') {
- RETURN_STRING(Path + 4, 1);
- }
- } else {
- RETURN_STRING(Path, 1);
+ if (php_sys_readlink(link, target, MAXPATHLEN) == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "readlink failed to read the symbolic link (%s), error %d)", link, GetLastError());
}
+ RETURN_STRING(target, 1);
}
/* }}} */