Back to index

php5  5.3.10
link.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:                                                              |
00016    +----------------------------------------------------------------------+
00017  */
00018 
00019 /* $Id: link.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #include "php.h"
00022 #include "php_filestat.h"
00023 #include "php_globals.h"
00024 
00025 #ifdef HAVE_SYMLINK
00026 
00027 #include <stdlib.h>
00028 #if HAVE_UNISTD_H
00029 #include <unistd.h>
00030 #endif
00031 #include <sys/stat.h>
00032 #include <string.h>
00033 #if HAVE_PWD_H
00034 #ifdef PHP_WIN32
00035 #include "win32/pwd.h"
00036 #else
00037 #include <pwd.h>
00038 #endif
00039 #endif
00040 #if HAVE_GRP_H
00041 #ifdef PHP_WIN32
00042 #include "win32/grp.h"
00043 #else
00044 #include <grp.h>
00045 #endif
00046 #endif
00047 #include <errno.h>
00048 #include <ctype.h>
00049 
00050 #include "safe_mode.h"
00051 #include "php_link.h"
00052 #include "php_string.h"
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 buff[MAXPATHLEN];
00061        int ret;
00062 
00063        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &link, &link_len) == FAILURE) {
00064               return;
00065        }
00066 
00067        if (strlen(link) != link_len) {
00068               RETURN_FALSE;
00069        }
00070 
00071        if (PG(safe_mode) && !php_checkuid(link, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
00072               RETURN_FALSE;
00073        }
00074 
00075        if (php_check_open_basedir(link TSRMLS_CC)) {
00076               RETURN_FALSE;
00077        }
00078 
00079        ret = php_sys_readlink(link, buff, MAXPATHLEN-1);
00080 
00081        if (ret == -1) {
00082               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
00083               RETURN_FALSE;
00084        }
00085        /* Append NULL to the end of the string */
00086        buff[ret] = '\0';
00087 
00088        RETURN_STRING(buff, 1);
00089 }
00090 /* }}} */
00091 
00092 /* {{{ proto int linkinfo(string filename)
00093    Returns the st_dev field of the UNIX C stat structure describing the link */
00094 PHP_FUNCTION(linkinfo)
00095 {
00096        char *link;
00097        int link_len;
00098        struct stat sb;
00099        int ret;
00100 
00101        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &link, &link_len) == FAILURE) {
00102               return;
00103        }
00104 
00105        ret = VCWD_LSTAT(link, &sb);
00106        if (ret == -1) {
00107               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
00108               RETURN_LONG(-1L);
00109        }
00110 
00111        RETURN_LONG((long) sb.st_dev);
00112 }
00113 /* }}} */
00114 
00115 /* {{{ proto int symlink(string target, string link)
00116    Create a symbolic link */
00117 PHP_FUNCTION(symlink)
00118 {
00119        char *topath, *frompath;
00120        int topath_len, frompath_len;
00121        int ret;
00122        char source_p[MAXPATHLEN];
00123        char dest_p[MAXPATHLEN];
00124        char dirname[MAXPATHLEN];
00125        size_t len;
00126 
00127        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
00128               return;
00129        }
00130 
00131        if (strlen(topath) != topath_len) {
00132               RETURN_FALSE;
00133        }
00134 
00135        if (strlen(frompath) != frompath_len) {
00136               RETURN_FALSE;
00137        }
00138        
00139        if (!expand_filepath(frompath, source_p TSRMLS_CC)) {
00140               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
00141               RETURN_FALSE;
00142        }
00143 
00144        memcpy(dirname, source_p, sizeof(source_p));
00145        len = php_dirname(dirname, strlen(dirname));
00146 
00147        if (!expand_filepath_ex(topath, dest_p, dirname, len TSRMLS_CC)) {
00148               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
00149               RETURN_FALSE;
00150        }
00151 
00152        if (php_stream_locate_url_wrapper(source_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ||
00153               php_stream_locate_url_wrapper(dest_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ) 
00154        {
00155               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to symlink to a URL");
00156               RETURN_FALSE;
00157        }
00158 
00159        if (PG(safe_mode) && !php_checkuid(dest_p, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
00160               RETURN_FALSE;
00161        }
00162 
00163        if (PG(safe_mode) && !php_checkuid(source_p, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
00164               RETURN_FALSE;
00165        }
00166 
00167        if (php_check_open_basedir(dest_p TSRMLS_CC)) {
00168               RETURN_FALSE;
00169        }
00170 
00171        if (php_check_open_basedir(source_p TSRMLS_CC)) {
00172               RETURN_FALSE;
00173        }
00174 
00175        /* For the source, an expanded path must be used (in ZTS an other thread could have changed the CWD).
00176         * For the target the exact string given by the user must be used, relative or not, existing or not.
00177         * The target is relative to the link itself, not to the CWD. */
00178        ret = symlink(topath, source_p);
00179 
00180        if (ret == -1) {
00181               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
00182               RETURN_FALSE;
00183        }
00184 
00185        RETURN_TRUE;
00186 }
00187 /* }}} */
00188 
00189 /* {{{ proto int link(string target, string link)
00190    Create a hard link */
00191 PHP_FUNCTION(link)
00192 {
00193        char *topath, *frompath;
00194        int topath_len, frompath_len;
00195        int ret;
00196        char source_p[MAXPATHLEN];
00197        char dest_p[MAXPATHLEN];
00198 
00199        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
00200               return;
00201        }
00202 
00203        if (strlen(topath) != topath_len) {
00204               RETURN_FALSE;
00205        }
00206 
00207        if (strlen(frompath) != frompath_len) {
00208               RETURN_FALSE;
00209        }
00210 
00211        if (!expand_filepath(frompath, source_p TSRMLS_CC) || !expand_filepath(topath, dest_p TSRMLS_CC)) {
00212               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
00213               RETURN_FALSE;
00214        }
00215 
00216        if (php_stream_locate_url_wrapper(source_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ||
00217               php_stream_locate_url_wrapper(dest_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ) 
00218        {
00219               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to link to a URL");
00220               RETURN_FALSE;
00221        }
00222 
00223        if (PG(safe_mode) && !php_checkuid(dest_p, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
00224               RETURN_FALSE;
00225        }
00226 
00227        if (PG(safe_mode) && !php_checkuid(source_p, NULL, CHECKUID_CHECK_FILE_AND_DIR)) {
00228               RETURN_FALSE;
00229        }
00230 
00231        if (php_check_open_basedir(dest_p TSRMLS_CC)) {
00232               RETURN_FALSE;
00233        }
00234 
00235        if (php_check_open_basedir(source_p TSRMLS_CC)) {
00236               RETURN_FALSE;
00237        }
00238 
00239 #ifndef ZTS
00240        ret = link(topath, frompath);
00241 #else 
00242        ret = link(dest_p, source_p);      
00243 #endif 
00244        if (ret == -1) {
00245               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
00246               RETURN_FALSE;
00247        }
00248 
00249        RETURN_TRUE;
00250 }
00251 /* }}} */
00252 
00253 #endif
00254 
00255 /*
00256  * Local variables:
00257  * tab-width: 4
00258  * c-basic-offset: 4
00259  * End:
00260  * vim600: noet sw=4 ts=4 fdm=marker
00261  * vim<600: noet sw=4 ts=4
00262  */