pajoye Fri Jan 16 10:04:30 2009 UTC Modified files: /php-src/ext/standard link_win32.c basic_functions.c config.w32 php_link.h Log: - symlink, hardlink & co support (2/2) & (3/3)
http://cvs.php.net/viewvc.cgi/php-src/ext/standard/link_win32.c?r1=1.1&r2=1.2&diff_format=u Index: php-src/ext/standard/link_win32.c diff -u /dev/null php-src/ext/standard/link_win32.c:1.2 --- /dev/null Fri Jan 16 10:04:30 2009 +++ php-src/ext/standard/link_win32.c Fri Jan 16 10:04:29 2009 @@ -0,0 +1,276 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2009 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 | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | lice...@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Pierre A. Joye <pie...@php.net> | + +----------------------------------------------------------------------+ + */ + +/* $Id: link_win32.c,v 1.2 2009/01/16 10:04:29 pajoye Exp $ */ +#ifdef PHP_WIN32 + +#include "php.h" +#include "php_filestat.h" +#include "php_globals.h" + +#include <WinBase.h> + +#include <stdlib.h> + +#include <string.h> +#if HAVE_PWD_H +#include "win32/pwd.h" +#endif + +#if HAVE_GRP_H +#include "win32/grp.h" +#endif + +#include <errno.h> +#include <ctype.h> + +#include "php_link.h" +#include "php_string.h" + +/* +TODO: +- Create php_readlink, 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 +*/ + +/* {{{ proto string readlink(string filename) + Return the target of a symbolic link */ +PHP_FUNCTION(readlink) +{ + HINSTANCE kernel32; + char *link; + int link_len; + TCHAR Path[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; + } + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &link, &link_len) == FAILURE) { + return; + } + + if (OPENBASEDIR_CHECKPATH(link)) { + RETURN_FALSE; + } + + 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) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not open file (error %d)", GetLastError()); + RETURN_FALSE; + } + + dwRet = pGetFinalPathNameByHandle(hFile, Path, MAXPATHLEN, VOLUME_NAME_NT); + 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'; + + RETURN_STRING(Path, 1); +} +/* }}} */ + +/* {{{ proto int linkinfo(string filename) + Returns the st_dev field of the UNIX C stat structure describing the link */ +PHP_FUNCTION(linkinfo) +{ + char *link; + int link_len; + struct stat sb; + int ret; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &link, &link_len) == FAILURE) { + return; + } + + ret = VCWD_STAT(link, &sb); + if (ret == -1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno)); + RETURN_LONG(-1L); + } + + RETURN_LONG((long) sb.st_dev); +} +/* }}} */ + +/* {{{ proto int symlink(string target, string link) + Create a symbolic link */ +PHP_FUNCTION(symlink) +{ + char *topath, *frompath; + int topath_len, frompath_len; + BOOLEAN ret; + char source_p[MAXPATHLEN]; + char dest_p[MAXPATHLEN]; + char dirname[MAXPATHLEN]; + size_t len; + DWORD attr; + HINSTANCE kernel32; + typedef BOOLEAN (WINAPI *csla_func)( __in LPCSTR, __in LPCSTR, __in DWORD); + csla_func pCreateSymbolicLinkA; + + kernel32 = LoadLibrary("kernel32.dll"); + + if (kernel32) { + pCreateSymbolicLinkA = (csla_func)GetProcAddress(kernel32, "CreateSymbolicLinkA"); + if (pCreateSymbolicLinkA == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't call CreateSymbolicLinkA"); + RETURN_FALSE; + } + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't call get a handle on kernel32.dll"); + RETURN_FALSE; + } + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) { + return; + } + + if (!expand_filepath(frompath, source_p TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory"); + RETURN_FALSE; + } + + memcpy(dirname, source_p, sizeof(source_p)); + len = php_dirname(dirname, strlen(dirname)); + + if (!expand_filepath_ex(topath, dest_p, dirname, len TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory"); + RETURN_FALSE; + } + + if (php_stream_locate_url_wrapper(source_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) || + php_stream_locate_url_wrapper(dest_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ) + { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to symlink to a URL"); + RETURN_FALSE; + } + + if (OPENBASEDIR_CHECKPATH(dest_p)) { + RETURN_FALSE; + } + + if (OPENBASEDIR_CHECKPATH(source_p)) { + RETURN_FALSE; + } + + if ((attr = GetFileAttributes(topath)) == INVALID_FILE_ATTRIBUTES) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch file information(error %d)", GetLastError()); + RETURN_FALSE; + } + + /* For the source, an expanded path must be used (in ZTS an other thread could have changed the CWD). + * For the target the exact string given by the user must be used, relative or not, existing or not. + * The target is relative to the link itself, not to the CWD. */ + ret = pCreateSymbolicLinkA(source_p, topath, (attr & FILE_ATTRIBUTE_DIRECTORY ? 1 : 0)); + + if (!ret) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create symlink, error code(%d)", GetLastError()); + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto int link(string target, string link) + Create a hard link */ +PHP_FUNCTION(link) +{ + char *topath, *frompath; + int topath_len, frompath_len; + int ret; + char source_p[MAXPATHLEN]; + char dest_p[MAXPATHLEN]; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) { + return; + } + + if (!expand_filepath(frompath, source_p TSRMLS_CC) || !expand_filepath(topath, dest_p TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory"); + RETURN_FALSE; + } + + if (php_stream_locate_url_wrapper(source_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) || + php_stream_locate_url_wrapper(dest_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ) + { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to link to a URL"); + RETURN_FALSE; + } + + if (OPENBASEDIR_CHECKPATH(source_p)) { + RETURN_FALSE; + } + + if (OPENBASEDIR_CHECKPATH(dest_p)) { + RETURN_FALSE; + } + +#ifndef ZTS + ret = CreateHardLinkA(topath, frompath, NULL); +#else + ret = CreateHardLinkA(dest_p, source_p, NULL); +#endif + if (ret == -1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno)); + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ http://cvs.php.net/viewvc.cgi/php-src/ext/standard/basic_functions.c?r1=1.947&r2=1.948&diff_format=u Index: php-src/ext/standard/basic_functions.c diff -u php-src/ext/standard/basic_functions.c:1.947 php-src/ext/standard/basic_functions.c:1.948 --- php-src/ext/standard/basic_functions.c:1.947 Tue Jan 13 21:29:45 2009 +++ php-src/ext/standard/basic_functions.c Fri Jan 16 10:04:29 2009 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: basic_functions.c,v 1.947 2009/01/13 21:29:45 iliaa Exp $ */ +/* $Id: basic_functions.c,v 1.948 2009/01/16 10:04:29 pajoye Exp $ */ #include "php.h" #include "php_streams.h" @@ -1576,7 +1576,7 @@ ZEND_END_ARG_INFO() /* }}} */ /* {{{ link.c */ -#ifdef HAVE_SYMLINK +#if defined(HAVE_SYMLINK) || defined(PHP_WIN32) ZEND_BEGIN_ARG_INFO(arginfo_readlink, 0) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() @@ -2809,7 +2809,7 @@ PHP_FE(rawurldecode, arginfo_rawurldecode) PHP_FE(http_build_query, arginfo_http_build_query) -#ifdef HAVE_SYMLINK +#if defined(HAVE_SYMLINK) || defined(PHP_WIN32) PHP_FE(readlink, arginfo_readlink) PHP_FE(linkinfo, arginfo_linkinfo) PHP_FE(symlink, arginfo_symlink) http://cvs.php.net/viewvc.cgi/php-src/ext/standard/config.w32?r1=1.11&r2=1.12&diff_format=u Index: php-src/ext/standard/config.w32 diff -u php-src/ext/standard/config.w32:1.11 php-src/ext/standard/config.w32:1.12 --- php-src/ext/standard/config.w32:1.11 Tue Jan 6 20:44:56 2009 +++ php-src/ext/standard/config.w32 Fri Jan 16 10:04:29 2009 @@ -1,5 +1,5 @@ // vim:ft=javascript -// $Id: config.w32,v 1.11 2009/01/06 20:44:56 pajoye Exp $ +// $Id: config.w32,v 1.12 2009/01/16 10:04:29 pajoye Exp $ ARG_WITH("config-file-scan-dir", "Dir to check for additional php ini files", ""); @@ -16,7 +16,7 @@ crypt_freesec.c crypt_blowfish.c php_crypt_r.c \ cyr_convert.c datetime.c dir.c dl.c dns.c dns_win32.c exec.c \ file.c filestat.c formatted_print.c fsock.c head.c html.c image.c \ - info.c iptc.c lcg.c link.c mail.c math.c md5.c metaphone.c microtime.c \ + info.c iptc.c lcg.c link_win32.c mail.c math.c md5.c metaphone.c microtime.c \ pack.c pageinfo.c quot_print.c rand.c soundex.c \ string.c scanf.c syslog.c type.c uniqid.c url.c url_scanner.c var.c \ versioning.c assert.c strnatcmp.c levenshtein.c incomplete_class.c \ http://cvs.php.net/viewvc.cgi/php-src/ext/standard/php_link.h?r1=1.16&r2=1.17&diff_format=u Index: php-src/ext/standard/php_link.h diff -u php-src/ext/standard/php_link.h:1.16 php-src/ext/standard/php_link.h:1.17 --- php-src/ext/standard/php_link.h:1.16 Wed Dec 31 11:12:37 2008 +++ php-src/ext/standard/php_link.h Fri Jan 16 10:04:29 2009 @@ -16,12 +16,12 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_link.h,v 1.16 2008/12/31 11:12:37 sebastian Exp $ */ +/* $Id: php_link.h,v 1.17 2009/01/16 10:04:29 pajoye Exp $ */ #ifndef PHP_LINK_H #define PHP_LINK_H -#ifdef HAVE_SYMLINK +#if defined(HAVE_SYMLINK) || defined(PHP_WIN32) PHP_FUNCTION(link); PHP_FUNCTION(readlink);
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php