Back to index

php5  5.3.10
link_win32.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Author: Pierre A. Joye <pierre@php.net>                              |
00016    +----------------------------------------------------------------------+
00017  */
00018 
00019 /* $Id: link_win32.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 #ifdef PHP_WIN32
00021 
00022 #include "php.h"
00023 #include "php_filestat.h"
00024 #include "php_globals.h"
00025 
00026 #include <WinBase.h>
00027 
00028 #include <stdlib.h>
00029 
00030 #include <string.h>
00031 #if HAVE_PWD_H
00032 #include "win32/pwd.h"
00033 #endif
00034 
00035 #if HAVE_GRP_H
00036 #include "win32/grp.h"
00037 #endif
00038 
00039 #include <errno.h>
00040 #include <ctype.h>
00041 
00042 #include "safe_mode.h"
00043 #include "php_link.h"
00044 #include "php_string.h"
00045 
00046 /*
00047 TODO:
00048 - Create php_readlink (done), php_link and php_symlink in win32/link.c
00049 - Expose them (PHPAPI) so extensions developers can use them
00050 - define link/readlink/symlink to their php_ equivalent and use them in ext/standart/link.c
00051 - this file is then useless and we have a portable link API
00052 */
00053 
00054 /* {{{ proto string readlink(string filename)
00055    Return the target of a symbolic link */
00056 PHP_FUNCTION(readlink)
00057 {
00058        char *link;
00059        int link_len;
00060        char target[MAXPATHLEN];
00061 
00062        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &link, &link_len) == FAILURE) {
00063               return;
00064        }
00065 
00066        if (OPENBASEDIR_CHECKPATH(link)) {
00067               RETURN_FALSE;
00068        }
00069 
00070        if (php_sys_readlink(link, target, MAXPATHLEN) == -1) {
00071               php_error_docref(NULL TSRMLS_CC, E_WARNING, "readlink failed to read the symbolic link (%s), error %d)", link, GetLastError());
00072               RETURN_FALSE;
00073        }
00074        RETURN_STRING(target, 1);
00075 }
00076 /* }}} */
00077 
00078 /* {{{ proto int linkinfo(string filename)
00079    Returns the st_dev field of the UNIX C stat structure describing the link */
00080 PHP_FUNCTION(linkinfo)
00081 {
00082        char *link;
00083        int link_len;
00084        struct stat sb;
00085        int ret;
00086 
00087        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &link, &link_len) == FAILURE) {
00088               return;
00089        }
00090 
00091        ret = VCWD_STAT(link, &sb);
00092        if (ret == -1) {
00093               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
00094               RETURN_LONG(-1L);
00095        }
00096 
00097        RETURN_LONG((long) sb.st_dev);
00098 }
00099 /* }}} */
00100 
00101 /* {{{ proto int symlink(string target, string link)
00102    Create a symbolic link */
00103 PHP_FUNCTION(symlink)
00104 {
00105        char *topath, *frompath;
00106        int topath_len, frompath_len;
00107        BOOLEAN ret;
00108        char source_p[MAXPATHLEN];
00109        char dest_p[MAXPATHLEN];
00110        char dirname[MAXPATHLEN];
00111        size_t len;
00112        DWORD attr;
00113        HINSTANCE kernel32;
00114        typedef BOOLEAN (WINAPI *csla_func)(LPCSTR, LPCSTR, DWORD);
00115        csla_func pCreateSymbolicLinkA;
00116 
00117        kernel32 = LoadLibrary("kernel32.dll");
00118 
00119        if (kernel32) {
00120               pCreateSymbolicLinkA = (csla_func)GetProcAddress(kernel32, "CreateSymbolicLinkA");
00121               if (pCreateSymbolicLinkA == NULL) {
00122                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't call CreateSymbolicLinkA");
00123                      RETURN_FALSE;
00124               }
00125        } else {
00126               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't call get a handle on kernel32.dll");
00127               RETURN_FALSE;
00128        }
00129 
00130        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
00131               return;
00132        }
00133        
00134        if (!expand_filepath(frompath, source_p TSRMLS_CC)) {
00135               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
00136               RETURN_FALSE;
00137        }
00138 
00139        memcpy(dirname, source_p, sizeof(source_p));
00140        len = php_dirname(dirname, strlen(dirname));
00141 
00142        if (!expand_filepath_ex(topath, dest_p, dirname, len TSRMLS_CC)) {
00143               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
00144               RETURN_FALSE;
00145        }
00146 
00147        if (php_stream_locate_url_wrapper(source_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ||
00148               php_stream_locate_url_wrapper(dest_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ) 
00149        {
00150               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to symlink to a URL");
00151               RETURN_FALSE;
00152        }
00153 
00154        if (OPENBASEDIR_CHECKPATH(dest_p)) {
00155               RETURN_FALSE;
00156        }
00157 
00158        if (OPENBASEDIR_CHECKPATH(source_p)) {
00159               RETURN_FALSE;
00160        }
00161 
00162        if ((attr = GetFileAttributes(topath)) == INVALID_FILE_ATTRIBUTES) {
00163                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch file information(error %d)", GetLastError());
00164                      RETURN_FALSE;
00165        }
00166 
00167        /* For the source, an expanded path must be used (in ZTS an other thread could have changed the CWD).
00168         * For the target the exact string given by the user must be used, relative or not, existing or not.
00169         * The target is relative to the link itself, not to the CWD. */
00170        ret = pCreateSymbolicLinkA(source_p, topath, (attr & FILE_ATTRIBUTE_DIRECTORY ? 1 : 0));
00171 
00172        if (!ret) {
00173               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create symlink, error code(%d)", GetLastError());
00174               RETURN_FALSE;
00175        }
00176 
00177        RETURN_TRUE;
00178 }
00179 /* }}} */
00180 
00181 /* {{{ proto int link(string target, string link)
00182    Create a hard link */
00183 PHP_FUNCTION(link)
00184 {
00185        char *topath, *frompath;
00186        int topath_len, frompath_len;
00187        int ret;
00188        char source_p[MAXPATHLEN];
00189        char dest_p[MAXPATHLEN];
00190 
00191        /*First argument to link function is the target and hence should go to frompath
00192          Second argument to link function is the link itself and hence should go to topath */
00193        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &frompath, &frompath_len, &topath, &topath_len) == FAILURE) {
00194               return;
00195        }
00196 
00197        if (!expand_filepath(frompath, source_p TSRMLS_CC) || !expand_filepath(topath, dest_p TSRMLS_CC)) {
00198               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
00199               RETURN_FALSE;
00200        }
00201 
00202        if (php_stream_locate_url_wrapper(source_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ||
00203               php_stream_locate_url_wrapper(dest_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ) 
00204        {
00205               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to link to a URL");
00206               RETURN_FALSE;
00207        }
00208 
00209        if (OPENBASEDIR_CHECKPATH(source_p)) {
00210               RETURN_FALSE;
00211        }
00212 
00213        if (OPENBASEDIR_CHECKPATH(dest_p)) {
00214               RETURN_FALSE;
00215        }
00216 
00217 #ifndef ZTS
00218        ret = CreateHardLinkA(topath, frompath, NULL);
00219 #else 
00220        ret = CreateHardLinkA(dest_p, source_p, NULL);   
00221 #endif 
00222 
00223        if (ret == 0) {
00224               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
00225               RETURN_FALSE;
00226        }
00227 
00228        RETURN_TRUE;
00229 }
00230 /* }}} */
00231 
00232 #endif
00233 
00234 /*
00235  * Local variables:
00236  * tab-width: 4
00237  * c-basic-offset: 4
00238  * End:
00239  * vim600: noet sw=4 ts=4 fdm=marker
00240  * vim<600: noet sw=4 ts=4
00241  */