root/ext/standard/link_win32.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. PHP_FUNCTION
  2. PHP_FUNCTION
  3. PHP_FUNCTION
  4. PHP_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 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$ */
  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 "php_link.h"
  43 #include "php_string.h"
  44 
  45 /*
  46 TODO:
  47 - Create php_readlink (done), php_link and php_symlink in win32/link.c
  48 - Expose them (PHPAPI) so extensions developers can use them
  49 - define link/readlink/symlink to their php_ equivalent and use them in ext/standart/link.c
  50 - this file is then useless and we have a portable link API
  51 */
  52 
  53 #ifndef VOLUME_NAME_NT
  54 #define VOLUME_NAME_NT 0x2
  55 #endif
  56 
  57 #ifndef VOLUME_NAME_DOS
  58 #define VOLUME_NAME_DOS 0x0
  59 #endif
  60 
  61 /* {{{ proto string readlink(string filename)
  62    Return the target of a symbolic link */
  63 PHP_FUNCTION(readlink)
  64 {
  65         char *link;
  66         size_t link_len;
  67         char target[MAXPATHLEN];
  68 
  69         if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &link, &link_len) == FAILURE) {
  70                 return;
  71         }
  72 
  73         if (OPENBASEDIR_CHECKPATH(link)) {
  74                 RETURN_FALSE;
  75         }
  76 
  77         if (php_sys_readlink(link, target, MAXPATHLEN) == -1) {
  78                 php_error_docref(NULL, E_WARNING, "readlink failed to read the symbolic link (%s), error %d)", link, GetLastError());
  79                 RETURN_FALSE;
  80         }
  81         RETURN_STRING(target);
  82 }
  83 /* }}} */
  84 
  85 /* {{{ proto int linkinfo(string filename)
  86    Returns the st_dev field of the UNIX C stat structure describing the link */
  87 PHP_FUNCTION(linkinfo)
  88 {
  89         char *link;
  90         size_t link_len;
  91         zend_stat_t sb;
  92         int ret;
  93 
  94         if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &link, &link_len) == FAILURE) {
  95                 return;
  96         }
  97 
  98         ret = VCWD_STAT(link, &sb);
  99         if (ret == -1) {
 100                 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
 101                 RETURN_LONG(Z_L(-1));
 102         }
 103 
 104         RETURN_LONG((zend_long) sb.st_dev);
 105 }
 106 /* }}} */
 107 
 108 /* {{{ proto int symlink(string target, string link)
 109    Create a symbolic link */
 110 PHP_FUNCTION(symlink)
 111 {
 112         char *topath, *frompath;
 113         size_t topath_len, frompath_len;
 114         BOOLEAN ret;
 115         char source_p[MAXPATHLEN];
 116         char dest_p[MAXPATHLEN];
 117         char dirname[MAXPATHLEN];
 118         size_t len;
 119         DWORD attr;
 120         HINSTANCE kernel32;
 121         typedef BOOLEAN (WINAPI *csla_func)(LPCSTR, LPCSTR, DWORD);
 122         csla_func pCreateSymbolicLinkA;
 123 
 124         kernel32 = LoadLibrary("kernel32.dll");
 125 
 126         if (kernel32) {
 127                 pCreateSymbolicLinkA = (csla_func)GetProcAddress(kernel32, "CreateSymbolicLinkA");
 128                 if (pCreateSymbolicLinkA == NULL) {
 129                         php_error_docref(NULL, E_WARNING, "Can't call CreateSymbolicLinkA");
 130                         RETURN_FALSE;
 131                 }
 132         } else {
 133                 php_error_docref(NULL, E_WARNING, "Can't call get a handle on kernel32.dll");
 134                 RETURN_FALSE;
 135         }
 136 
 137         if (zend_parse_parameters(ZEND_NUM_ARGS(), "pp", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
 138                 return;
 139         }
 140 
 141         if (!expand_filepath(frompath, source_p)) {
 142                 php_error_docref(NULL, E_WARNING, "No such file or directory");
 143                 RETURN_FALSE;
 144         }
 145 
 146         memcpy(dirname, source_p, sizeof(source_p));
 147         len = php_dirname(dirname, strlen(dirname));
 148 
 149         if (!expand_filepath_ex(topath, dest_p, dirname, len)) {
 150                 php_error_docref(NULL, E_WARNING, "No such file or directory");
 151                 RETURN_FALSE;
 152         }
 153 
 154         if (php_stream_locate_url_wrapper(source_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY) ||
 155                 php_stream_locate_url_wrapper(dest_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY) )
 156         {
 157                 php_error_docref(NULL, E_WARNING, "Unable to symlink to a URL");
 158                 RETURN_FALSE;
 159         }
 160 
 161         if (OPENBASEDIR_CHECKPATH(dest_p)) {
 162                 RETURN_FALSE;
 163         }
 164 
 165         if (OPENBASEDIR_CHECKPATH(source_p)) {
 166                 RETURN_FALSE;
 167         }
 168 
 169         if ((attr = GetFileAttributes(topath)) == INVALID_FILE_ATTRIBUTES) {
 170                         php_error_docref(NULL, E_WARNING, "Could not fetch file information(error %d)", GetLastError());
 171                         RETURN_FALSE;
 172         }
 173 
 174         /* For the source, an expanded path must be used (in ZTS an other thread could have changed the CWD).
 175          * For the target the exact string given by the user must be used, relative or not, existing or not.
 176          * The target is relative to the link itself, not to the CWD. */
 177         ret = pCreateSymbolicLinkA(source_p, topath, (attr & FILE_ATTRIBUTE_DIRECTORY ? 1 : 0));
 178 
 179         if (!ret) {
 180                 php_error_docref(NULL, E_WARNING, "Cannot create symlink, error code(%d)", GetLastError());
 181                 RETURN_FALSE;
 182         }
 183 
 184         RETURN_TRUE;
 185 }
 186 /* }}} */
 187 
 188 /* {{{ proto int link(string target, string link)
 189    Create a hard link */
 190 PHP_FUNCTION(link)
 191 {
 192         char *topath, *frompath;
 193         size_t topath_len, frompath_len;
 194         int ret;
 195         char source_p[MAXPATHLEN];
 196         char dest_p[MAXPATHLEN];
 197 
 198         /*First argument to link function is the target and hence should go to frompath
 199           Second argument to link function is the link itself and hence should go to topath */
 200         if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &frompath, &frompath_len, &topath, &topath_len) == FAILURE) {
 201                 return;
 202         }
 203 
 204         if (!expand_filepath(frompath, source_p) || !expand_filepath(topath, dest_p)) {
 205                 php_error_docref(NULL, E_WARNING, "No such file or directory");
 206                 RETURN_FALSE;
 207         }
 208 
 209         if (php_stream_locate_url_wrapper(source_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY) ||
 210                 php_stream_locate_url_wrapper(dest_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY) )
 211         {
 212                 php_error_docref(NULL, E_WARNING, "Unable to link to a URL");
 213                 RETURN_FALSE;
 214         }
 215 
 216         if (OPENBASEDIR_CHECKPATH(source_p)) {
 217                 RETURN_FALSE;
 218         }
 219 
 220         if (OPENBASEDIR_CHECKPATH(dest_p)) {
 221                 RETURN_FALSE;
 222         }
 223 
 224 #ifndef ZTS
 225         ret = CreateHardLinkA(topath, frompath, NULL);
 226 #else
 227         ret = CreateHardLinkA(dest_p, source_p, NULL);
 228 #endif
 229 
 230         if (ret == 0) {
 231                 php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
 232                 RETURN_FALSE;
 233         }
 234 
 235         RETURN_TRUE;
 236 }
 237 /* }}} */
 238 
 239 #endif
 240 
 241 /*
 242  * Local variables:
 243  * tab-width: 4
 244  * c-basic-offset: 4
 245  * End:
 246  * vim600: noet sw=4 ts=4 fdm=marker
 247  * vim<600: noet sw=4 ts=4
 248  */

/* [<][>][^][v][top][bottom][index][help] */