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