link.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  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: |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id$ */
  19. #include "php.h"
  20. #include "php_filestat.h"
  21. #include "php_globals.h"
  22. #ifdef HAVE_SYMLINK
  23. #include <stdlib.h>
  24. #if HAVE_UNISTD_H
  25. #include <unistd.h>
  26. #endif
  27. #include <sys/stat.h>
  28. #include <string.h>
  29. #if HAVE_PWD_H
  30. #ifdef PHP_WIN32
  31. #include "win32/pwd.h"
  32. #else
  33. #include <pwd.h>
  34. #endif
  35. #endif
  36. #if HAVE_GRP_H
  37. #ifdef PHP_WIN32
  38. #include "win32/grp.h"
  39. #else
  40. #include <grp.h>
  41. #endif
  42. #endif
  43. #include <errno.h>
  44. #include <ctype.h>
  45. #include "php_link.h"
  46. #include "php_string.h"
  47. /* {{{ proto string readlink(string filename)
  48. Return the target of a symbolic link */
  49. PHP_FUNCTION(readlink)
  50. {
  51. char *link;
  52. int link_len;
  53. char buff[MAXPATHLEN];
  54. int ret;
  55. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &link, &link_len) == FAILURE) {
  56. return;
  57. }
  58. if (php_check_open_basedir(link TSRMLS_CC)) {
  59. RETURN_FALSE;
  60. }
  61. ret = php_sys_readlink(link, buff, MAXPATHLEN-1);
  62. if (ret == -1) {
  63. php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
  64. RETURN_FALSE;
  65. }
  66. /* Append NULL to the end of the string */
  67. buff[ret] = '\0';
  68. RETURN_STRING(buff, 1);
  69. }
  70. /* }}} */
  71. /* {{{ proto int linkinfo(string filename)
  72. Returns the st_dev field of the UNIX C stat structure describing the link */
  73. PHP_FUNCTION(linkinfo)
  74. {
  75. char *link;
  76. char *dirname;
  77. int link_len, dir_len;
  78. struct stat sb;
  79. int ret;
  80. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &link, &link_len) == FAILURE) {
  81. return;
  82. }
  83. dirname = estrndup(link, link_len);
  84. dir_len = php_dirname(dirname, link_len);
  85. if (php_check_open_basedir(dirname TSRMLS_CC)) {
  86. efree(dirname);
  87. RETURN_FALSE;
  88. }
  89. ret = VCWD_LSTAT(link, &sb);
  90. if (ret == -1) {
  91. php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
  92. efree(dirname);
  93. RETURN_LONG(-1L);
  94. }
  95. efree(dirname);
  96. RETURN_LONG((long) sb.st_dev);
  97. }
  98. /* }}} */
  99. /* {{{ proto int symlink(string target, string link)
  100. Create a symbolic link */
  101. PHP_FUNCTION(symlink)
  102. {
  103. char *topath, *frompath;
  104. int topath_len, frompath_len;
  105. int ret;
  106. char source_p[MAXPATHLEN];
  107. char dest_p[MAXPATHLEN];
  108. char dirname[MAXPATHLEN];
  109. size_t len;
  110. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
  111. return;
  112. }
  113. if (!expand_filepath(frompath, source_p TSRMLS_CC)) {
  114. php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
  115. RETURN_FALSE;
  116. }
  117. memcpy(dirname, source_p, sizeof(source_p));
  118. len = php_dirname(dirname, strlen(dirname));
  119. if (!expand_filepath_ex(topath, dest_p, dirname, len TSRMLS_CC)) {
  120. php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
  121. RETURN_FALSE;
  122. }
  123. if (php_stream_locate_url_wrapper(source_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ||
  124. php_stream_locate_url_wrapper(dest_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) )
  125. {
  126. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to symlink to a URL");
  127. RETURN_FALSE;
  128. }
  129. if (php_check_open_basedir(dest_p TSRMLS_CC)) {
  130. RETURN_FALSE;
  131. }
  132. if (php_check_open_basedir(source_p TSRMLS_CC)) {
  133. RETURN_FALSE;
  134. }
  135. /* For the source, an expanded path must be used (in ZTS an other thread could have changed the CWD).
  136. * For the target the exact string given by the user must be used, relative or not, existing or not.
  137. * The target is relative to the link itself, not to the CWD. */
  138. ret = symlink(topath, source_p);
  139. if (ret == -1) {
  140. php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
  141. RETURN_FALSE;
  142. }
  143. RETURN_TRUE;
  144. }
  145. /* }}} */
  146. /* {{{ proto int link(string target, string link)
  147. Create a hard link */
  148. PHP_FUNCTION(link)
  149. {
  150. char *topath, *frompath;
  151. int topath_len, frompath_len;
  152. int ret;
  153. char source_p[MAXPATHLEN];
  154. char dest_p[MAXPATHLEN];
  155. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
  156. return;
  157. }
  158. if (!expand_filepath(frompath, source_p TSRMLS_CC) || !expand_filepath(topath, dest_p TSRMLS_CC)) {
  159. php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such file or directory");
  160. RETURN_FALSE;
  161. }
  162. if (php_stream_locate_url_wrapper(source_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ||
  163. php_stream_locate_url_wrapper(dest_p, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) )
  164. {
  165. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to link to a URL");
  166. RETURN_FALSE;
  167. }
  168. if (php_check_open_basedir(dest_p TSRMLS_CC)) {
  169. RETURN_FALSE;
  170. }
  171. if (php_check_open_basedir(source_p TSRMLS_CC)) {
  172. RETURN_FALSE;
  173. }
  174. #ifndef ZTS
  175. ret = link(topath, frompath);
  176. #else
  177. ret = link(dest_p, source_p);
  178. #endif
  179. if (ret == -1) {
  180. php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
  181. RETURN_FALSE;
  182. }
  183. RETURN_TRUE;
  184. }
  185. /* }}} */
  186. #endif
  187. /*
  188. * Local variables:
  189. * tab-width: 4
  190. * c-basic-offset: 4
  191. * End:
  192. * vim600: noet sw=4 ts=4 fdm=marker
  193. * vim<600: noet sw=4 ts=4
  194. */