Annotation of embedaddon/php/ext/standard/link_win32.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
                      5:    | Copyright (c) 1997-2012 The PHP Group                                |
                      6:    +----------------------------------------------------------------------+
                      7:    | This source file is subject to version 3.01 of the PHP license,      |
                      8:    | that is bundled with this package in the file LICENSE, and is        |
                      9:    | available through the world-wide-web at the following url:           |
                     10:    | http://www.php.net/license/3_01.txt                                  |
                     11:    | If you did not receive a copy of the PHP license and are unable to   |
                     12:    | obtain it through the world-wide-web, please send a note to          |
                     13:    | license@php.net so we can mail you a copy immediately.               |
                     14:    +----------------------------------------------------------------------+
                     15:    | Author: Pierre A. Joye <pierre@php.net>                              |
                     16:    +----------------------------------------------------------------------+
                     17:  */
                     18: 
                     19: /* $Id: link_win32.c 321634 2012-01-01 13:15:04Z felipe $ */
                     20: #ifdef PHP_WIN32
                     21: 
                     22: #include "php.h"
                     23: #include "php_filestat.h"
                     24: #include "php_globals.h"
                     25: 
                     26: #include <WinBase.h>
                     27: 
                     28: #include <stdlib.h>
                     29: 
                     30: #include <string.h>
                     31: #if HAVE_PWD_H
                     32: #include "win32/pwd.h"
                     33: #endif
                     34: 
                     35: #if HAVE_GRP_H
                     36: #include "win32/grp.h"
                     37: #endif
                     38: 
                     39: #include <errno.h>
                     40: #include <ctype.h>
                     41: 
                     42: #include "safe_mode.h"
                     43: #include "php_link.h"
                     44: #include "php_string.h"
                     45: 
                     46: /*
                     47: TODO:
                     48: - Create php_readlink (done), php_link and php_symlink in win32/link.c
                     49: - Expose them (PHPAPI) so extensions developers can use them
                     50: - define link/readlink/symlink to their php_ equivalent and use them in ext/standart/link.c
                     51: - this file is then useless and we have a portable link API
                     52: */
                     53: 
                     54: /* {{{ proto string readlink(string filename)
                     55:    Return the target of a symbolic link */
                     56: PHP_FUNCTION(readlink)
                     57: {
                     58:        char *link;
                     59:        int link_len;
                     60:        char target[MAXPATHLEN];
                     61: 
                     62:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &link, &link_len) == FAILURE) {
                     63:                return;
                     64:        }
                     65: 
                     66:        if (OPENBASEDIR_CHECKPATH(link)) {
                     67:                RETURN_FALSE;
                     68:        }
                     69: 
                     70:        if (php_sys_readlink(link, target, MAXPATHLEN) == -1) {
                     71:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "readlink failed to read the symbolic link (%s), error %d)", link, GetLastError());
                     72:                RETURN_FALSE;
                     73:        }
                     74:        RETURN_STRING(target, 1);
                     75: }
                     76: /* }}} */
                     77: 
                     78: /* {{{ proto int linkinfo(string filename)
                     79:    Returns the st_dev field of the UNIX C stat structure describing the link */
                     80: PHP_FUNCTION(linkinfo)
                     81: {
                     82:        char *link;
                     83:        int link_len;
                     84:        struct stat sb;
                     85:        int ret;
                     86: 
                     87:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &link, &link_len) == FAILURE) {
                     88:                return;
                     89:        }
                     90: 
                     91:        ret = VCWD_STAT(link, &sb);
                     92:        if (ret == -1) {
                     93:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
                     94:                RETURN_LONG(-1L);
                     95:        }
                     96: 
                     97:        RETURN_LONG((long) sb.st_dev);
                     98: }
                     99: /* }}} */
                    100: 
                    101: /* {{{ proto int symlink(string target, string link)
                    102:    Create a symbolic link */
                    103: PHP_FUNCTION(symlink)
                    104: {
                    105:        char *topath, *frompath;
                    106:        int topath_len, frompath_len;
                    107:        BOOLEAN ret;
                    108:        char source_p[MAXPATHLEN];
                    109:        char dest_p[MAXPATHLEN];
                    110:        char dirname[MAXPATHLEN];
                    111:        size_t len;
                    112:        DWORD attr;
                    113:        HINSTANCE kernel32;
                    114:        typedef BOOLEAN (WINAPI *csla_func)(LPCSTR, LPCSTR, DWORD);
                    115:        csla_func pCreateSymbolicLinkA;
                    116: 
                    117:        kernel32 = LoadLibrary("kernel32.dll");
                    118: 
                    119:        if (kernel32) {
                    120:                pCreateSymbolicLinkA = (csla_func)GetProcAddress(kernel32, "CreateSymbolicLinkA");
                    121:                if (pCreateSymbolicLinkA == NULL) {
                    122:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't call CreateSymbolicLinkA");
                    123:                        RETURN_FALSE;
                    124:                }
                    125:        } else {
                    126:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't call get a handle on kernel32.dll");
                    127:                RETURN_FALSE;
                    128:        }
                    129: 
                    130:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
                    131:                return;
                    132:        }
                    133:        
                    134:        if (!expand_filepath(frompath, source_p TSRMLS_CC)) {
                    135:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
                    136:                RETURN_FALSE;
                    137:        }
                    138: 
                    139:        memcpy(dirname, source_p, sizeof(source_p));
                    140:        len = php_dirname(dirname, strlen(dirname));
                    141: 
                    142:        if (!expand_filepath_ex(topath, dest_p, dirname, len TSRMLS_CC)) {
                    143:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
                    144:                RETURN_FALSE;
                    145:        }
                    146: 
                    147:        if (php_stream_locate_url_wrapper(source_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ||
                    148:                php_stream_locate_url_wrapper(dest_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ) 
                    149:        {
                    150:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to symlink to a URL");
                    151:                RETURN_FALSE;
                    152:        }
                    153: 
                    154:        if (OPENBASEDIR_CHECKPATH(dest_p)) {
                    155:                RETURN_FALSE;
                    156:        }
                    157: 
                    158:        if (OPENBASEDIR_CHECKPATH(source_p)) {
                    159:                RETURN_FALSE;
                    160:        }
                    161: 
                    162:        if ((attr = GetFileAttributes(topath)) == INVALID_FILE_ATTRIBUTES) {
                    163:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not fetch file information(error %d)", GetLastError());
                    164:                        RETURN_FALSE;
                    165:        }
                    166: 
                    167:        /* For the source, an expanded path must be used (in ZTS an other thread could have changed the CWD).
                    168:         * For the target the exact string given by the user must be used, relative or not, existing or not.
                    169:         * The target is relative to the link itself, not to the CWD. */
                    170:        ret = pCreateSymbolicLinkA(source_p, topath, (attr & FILE_ATTRIBUTE_DIRECTORY ? 1 : 0));
                    171: 
                    172:        if (!ret) {
                    173:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create symlink, error code(%d)", GetLastError());
                    174:                RETURN_FALSE;
                    175:        }
                    176: 
                    177:        RETURN_TRUE;
                    178: }
                    179: /* }}} */
                    180: 
                    181: /* {{{ proto int link(string target, string link)
                    182:    Create a hard link */
                    183: PHP_FUNCTION(link)
                    184: {
                    185:        char *topath, *frompath;
                    186:        int topath_len, frompath_len;
                    187:        int ret;
                    188:        char source_p[MAXPATHLEN];
                    189:        char dest_p[MAXPATHLEN];
                    190: 
                    191:        /*First argument to link function is the target and hence should go to frompath
                    192:          Second argument to link function is the link itself and hence should go to topath */
                    193:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &frompath, &frompath_len, &topath, &topath_len) == FAILURE) {
                    194:                return;
                    195:        }
                    196: 
                    197:        if (!expand_filepath(frompath, source_p TSRMLS_CC) || !expand_filepath(topath, dest_p TSRMLS_CC)) {
                    198:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
                    199:                RETURN_FALSE;
                    200:        }
                    201: 
                    202:        if (php_stream_locate_url_wrapper(source_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ||
                    203:                php_stream_locate_url_wrapper(dest_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ) 
                    204:        {
                    205:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to link to a URL");
                    206:                RETURN_FALSE;
                    207:        }
                    208: 
                    209:        if (OPENBASEDIR_CHECKPATH(source_p)) {
                    210:                RETURN_FALSE;
                    211:        }
                    212: 
                    213:        if (OPENBASEDIR_CHECKPATH(dest_p)) {
                    214:                RETURN_FALSE;
                    215:        }
                    216: 
                    217: #ifndef ZTS
                    218:        ret = CreateHardLinkA(topath, frompath, NULL);
                    219: #else 
                    220:        ret = CreateHardLinkA(dest_p, source_p, NULL);  
                    221: #endif 
                    222: 
                    223:        if (ret == 0) {
                    224:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
                    225:                RETURN_FALSE;
                    226:        }
                    227: 
                    228:        RETURN_TRUE;
                    229: }
                    230: /* }}} */
                    231: 
                    232: #endif
                    233: 
                    234: /*
                    235:  * Local variables:
                    236:  * tab-width: 4
                    237:  * c-basic-offset: 4
                    238:  * End:
                    239:  * vim600: noet sw=4 ts=4 fdm=marker
                    240:  * vim<600: noet sw=4 ts=4
                    241:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>