xref: /PHP-7.3/Zend/zend_virtual_cwd.h (revision 9afce019)
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    | Authors: Andi Gutmans <andi@php.net>                                 |
16    |          Sascha Schumann <sascha@schumann.cx>                        |
17    |          Pierre Joye <pierre@php.net>                                |
18    +----------------------------------------------------------------------+
19 */
20 
21 #ifndef VIRTUAL_CWD_H
22 #define VIRTUAL_CWD_H
23 
24 #include "TSRM.h"
25 #include "tsrm_config_common.h"
26 
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <ctype.h>
30 
31 #ifdef HAVE_UTIME_H
32 #include <utime.h>
33 #endif
34 
35 #ifdef HAVE_STDARG_H
36 #include <stdarg.h>
37 #endif
38 
39 #ifdef ZTS
40 #define VIRTUAL_DIR
41 #endif
42 
43 #ifndef ZEND_WIN32
44 #include <unistd.h>
45 #else
46 #include <direct.h>
47 #endif
48 
49 #if defined(__osf__) || defined(_AIX)
50 #include <errno.h>
51 #endif
52 
53 #ifdef ZEND_WIN32
54 #include "readdir.h"
55 #include <sys/utime.h>
56 #include "win32/ioutil.h"
57 /* mode_t isn't defined on Windows */
58 typedef unsigned short mode_t;
59 
60 #define DEFAULT_SLASH '\\'
61 #define DEFAULT_DIR_SEPARATOR	';'
62 #define IS_SLASH(c)	((c) == '/' || (c) == '\\')
63 #define IS_SLASH_P(c)	(*(c) == '/' || \
64         (*(c) == '\\' && !IsDBCSLeadByte(*(c-1))))
65 
66 /* COPY_WHEN_ABSOLUTE is 2 under Win32 because by chance both regular absolute paths
67    in the file system and UNC paths need copying of two characters */
68 #define COPY_WHEN_ABSOLUTE(path) 2
69 #define IS_UNC_PATH(path, len) \
70 	(len >= 2 && IS_SLASH(path[0]) && IS_SLASH(path[1]))
71 #define IS_ABSOLUTE_PATH(path, len) \
72 	(len >= 2 && (/* is local */isalpha(path[0]) && path[1] == ':' || /* is UNC */IS_SLASH(path[0]) && IS_SLASH(path[1])))
73 
74 #else
75 #ifdef HAVE_DIRENT_H
76 #include <dirent.h>
77 #endif
78 
79 #define DEFAULT_SLASH '/'
80 
81 #ifdef __riscos__
82 #define DEFAULT_DIR_SEPARATOR  ';'
83 #else
84 #define DEFAULT_DIR_SEPARATOR  ':'
85 #endif
86 
87 #define IS_SLASH(c)	((c) == '/')
88 #define IS_SLASH_P(c)	(*(c) == '/')
89 
90 #endif
91 
92 
93 #ifndef COPY_WHEN_ABSOLUTE
94 #define COPY_WHEN_ABSOLUTE(path) 0
95 #endif
96 
97 #ifndef IS_ABSOLUTE_PATH
98 #define IS_ABSOLUTE_PATH(path, len) \
99 	(IS_SLASH(path[0]))
100 #endif
101 
102 #ifdef TSRM_EXPORTS
103 #define CWD_EXPORTS
104 #endif
105 
106 #ifdef ZEND_WIN32
107 #	ifdef CWD_EXPORTS
108 #		define CWD_API __declspec(dllexport)
109 #	else
110 #		define CWD_API __declspec(dllimport)
111 #	endif
112 #elif defined(__GNUC__) && __GNUC__ >= 4
113 #	define CWD_API __attribute__ ((visibility("default")))
114 #else
115 #	define CWD_API
116 #endif
117 
118 #ifdef ZEND_WIN32
119 CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat);
120 # define php_sys_stat(path, buf) php_sys_stat_ex(path, buf, 0)
121 # define php_sys_lstat(path, buf) php_sys_stat_ex(path, buf, 1)
122 CWD_API ssize_t php_sys_readlink(const char *link, char *target, size_t target_len);
123 #else
124 # define php_sys_stat stat
125 # define php_sys_lstat lstat
126 # ifdef HAVE_SYMLINK
127 # define php_sys_readlink(link, target, target_len) readlink(link, target, target_len)
128 # endif
129 #endif
130 
131 typedef struct _cwd_state {
132 	char *cwd;
133 	size_t cwd_length;
134 } cwd_state;
135 
136 typedef int (*verify_path_func)(const cwd_state *);
137 
138 CWD_API void virtual_cwd_startup(void);
139 CWD_API void virtual_cwd_shutdown(void);
140 CWD_API int virtual_cwd_activate(void);
141 CWD_API int virtual_cwd_deactivate(void);
142 CWD_API char *virtual_getcwd_ex(size_t *length);
143 CWD_API char *virtual_getcwd(char *buf, size_t size);
144 CWD_API int virtual_chdir(const char *path);
145 CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path));
146 CWD_API int virtual_filepath(const char *path, char **filepath);
147 CWD_API int virtual_filepath_ex(const char *path, char **filepath, verify_path_func verify_path);
148 CWD_API char *virtual_realpath(const char *path, char *real_path);
149 CWD_API FILE *virtual_fopen(const char *path, const char *mode);
150 CWD_API int virtual_open(const char *path, int flags, ...);
151 CWD_API int virtual_creat(const char *path, mode_t mode);
152 CWD_API int virtual_rename(const char *oldname, const char *newname);
153 CWD_API int virtual_stat(const char *path, zend_stat_t *buf);
154 CWD_API int virtual_lstat(const char *path, zend_stat_t *buf);
155 CWD_API int virtual_unlink(const char *path);
156 CWD_API int virtual_mkdir(const char *pathname, mode_t mode);
157 CWD_API int virtual_rmdir(const char *pathname);
158 CWD_API DIR *virtual_opendir(const char *pathname);
159 CWD_API FILE *virtual_popen(const char *command, const char *type);
160 CWD_API int virtual_access(const char *pathname, int mode);
161 
162 #if HAVE_UTIME
163 CWD_API int virtual_utime(const char *filename, struct utimbuf *buf);
164 #endif
165 CWD_API int virtual_chmod(const char *filename, mode_t mode);
166 #if !defined(ZEND_WIN32)
167 CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int link);
168 #endif
169 
170 /* One of the following constants must be used as the last argument
171    in virtual_file_ex() call. */
172 
173 #define CWD_EXPAND   0 /* expand "." and ".." but don't resolve symlinks     */
174 #define CWD_FILEPATH 1 /* resolve symlinks if file is exist otherwise expand */
175 #define CWD_REALPATH 2 /* call realpath(), resolve symlinks. File must exist */
176 
177 CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath);
178 
179 CWD_API char *tsrm_realpath(const char *path, char *real_path);
180 
181 #define REALPATH_CACHE_TTL  (2*60) /* 2 minutes */
182 #define REALPATH_CACHE_SIZE 0      /* disabled while php.ini isn't loaded */
183 
184 typedef struct _realpath_cache_bucket {
185 	zend_ulong                    key;
186 	char                          *path;
187 	char                          *realpath;
188 	struct _realpath_cache_bucket *next;
189 	time_t                         expires;
190 	uint16_t                       path_len;
191 	uint16_t                       realpath_len;
192 	uint8_t                        is_dir:1;
193 #ifdef ZEND_WIN32
194 	uint8_t                        is_rvalid:1;
195 	uint8_t                        is_readable:1;
196 	uint8_t                        is_wvalid:1;
197 	uint8_t                        is_writable:1;
198 #endif
199 } realpath_cache_bucket;
200 
201 typedef struct _virtual_cwd_globals {
202 	cwd_state cwd;
203 	zend_long                   realpath_cache_size;
204 	zend_long                   realpath_cache_size_limit;
205 	zend_long                   realpath_cache_ttl;
206 	realpath_cache_bucket *realpath_cache[1024];
207 } virtual_cwd_globals;
208 
209 #ifdef ZTS
210 extern ts_rsrc_id cwd_globals_id;
211 # define CWDG(v) ZEND_TSRMG(cwd_globals_id, virtual_cwd_globals *, v)
212 #else
213 extern virtual_cwd_globals cwd_globals;
214 # define CWDG(v) (cwd_globals.v)
215 #endif
216 
217 CWD_API void realpath_cache_clean(void);
218 CWD_API void realpath_cache_del(const char *path, size_t path_len);
219 CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, size_t path_len, time_t t);
220 CWD_API zend_long realpath_cache_size(void);
221 CWD_API zend_long realpath_cache_max_buckets(void);
222 CWD_API realpath_cache_bucket** realpath_cache_get_buckets(void);
223 
224 #ifdef CWD_EXPORTS
225 extern void virtual_cwd_main_cwd_init(uint8_t);
226 #endif
227 
228 /* The actual macros to be used in programs using TSRM
229  * If the program defines VIRTUAL_DIR it will use the
230  * virtual_* functions
231  */
232 
233 #ifdef VIRTUAL_DIR
234 
235 #define VCWD_GETCWD(buff, size) virtual_getcwd(buff, size)
236 #define VCWD_FOPEN(path, mode) virtual_fopen(path, mode)
237 /* Because open() has two modes, we have to macros to replace it */
238 #define VCWD_OPEN(path, flags) virtual_open(path, flags)
239 #define VCWD_OPEN_MODE(path, flags, mode) virtual_open(path, flags, mode)
240 #define VCWD_CREAT(path, mode) virtual_creat(path, mode)
241 #define VCWD_CHDIR(path) virtual_chdir(path)
242 #define VCWD_CHDIR_FILE(path) virtual_chdir_file(path, virtual_chdir)
243 #define VCWD_GETWD(buf)
244 #define VCWD_REALPATH(path, real_path) virtual_realpath(path, real_path)
245 #define VCWD_RENAME(oldname, newname) virtual_rename(oldname, newname)
246 #define VCWD_STAT(path, buff) virtual_stat(path, buff)
247 # define VCWD_LSTAT(path, buff) virtual_lstat(path, buff)
248 #define VCWD_UNLINK(path) virtual_unlink(path)
249 #define VCWD_MKDIR(pathname, mode) virtual_mkdir(pathname, mode)
250 #define VCWD_RMDIR(pathname) virtual_rmdir(pathname)
251 #define VCWD_OPENDIR(pathname) virtual_opendir(pathname)
252 #define VCWD_POPEN(command, type) virtual_popen(command, type)
253 #define VCWD_ACCESS(pathname, mode) virtual_access(pathname, mode)
254 #if HAVE_UTIME
255 #define VCWD_UTIME(path, time) virtual_utime(path, time)
256 #endif
257 #define VCWD_CHMOD(path, mode) virtual_chmod(path, mode)
258 #if !defined(ZEND_WIN32)
259 #define VCWD_CHOWN(path, owner, group) virtual_chown(path, owner, group, 0)
260 #if HAVE_LCHOWN
261 #define VCWD_LCHOWN(path, owner, group) virtual_chown(path, owner, group, 1)
262 #endif
263 #endif
264 
265 #else
266 
267 #define VCWD_CREAT(path, mode) creat(path, mode)
268 /* rename on windows will fail if newname already exists.
269    MoveFileEx has to be used */
270 #if defined(ZEND_WIN32)
271 #define VCWD_FOPEN(path, mode)  php_win32_ioutil_fopen(path, mode)
272 #define VCWD_OPEN(path, flags) php_win32_ioutil_open(path, flags)
273 #define VCWD_OPEN_MODE(path, flags, mode) php_win32_ioutil_open(path, flags, mode)
274 # define VCWD_RENAME(oldname, newname) php_win32_ioutil_rename(oldname, newname)
275 #define VCWD_MKDIR(pathname, mode) php_win32_ioutil_mkdir(pathname, mode)
276 #define VCWD_RMDIR(pathname) php_win32_ioutil_rmdir(pathname)
277 #define VCWD_UNLINK(path) php_win32_ioutil_unlink(path)
278 #define VCWD_CHDIR(path) php_win32_ioutil_chdir(path)
279 #define VCWD_ACCESS(pathname, mode) tsrm_win32_access(pathname, mode)
280 #define VCWD_GETCWD(buff, size) php_win32_ioutil_getcwd(buff, size)
281 #define VCWD_CHMOD(path, mode) php_win32_ioutil_chmod(path, mode)
282 #else
283 #define VCWD_FOPEN(path, mode)  fopen(path, mode)
284 #define VCWD_OPEN(path, flags) open(path, flags)
285 #define VCWD_OPEN_MODE(path, flags, mode)	open(path, flags, mode)
286 # define VCWD_RENAME(oldname, newname) rename(oldname, newname)
287 #define VCWD_MKDIR(pathname, mode) mkdir(pathname, mode)
288 #define VCWD_RMDIR(pathname) rmdir(pathname)
289 #define VCWD_UNLINK(path) unlink(path)
290 #define VCWD_CHDIR(path) chdir(path)
291 #define VCWD_ACCESS(pathname, mode) access(pathname, mode)
292 #define VCWD_GETCWD(buff, size) getcwd(buff, size)
293 #define VCWD_CHMOD(path, mode) chmod(path, mode)
294 #endif
295 
296 #define VCWD_CHDIR_FILE(path) virtual_chdir_file(path, chdir)
297 #define VCWD_GETWD(buf) getwd(buf)
298 #define VCWD_STAT(path, buff) php_sys_stat(path, buff)
299 #define VCWD_LSTAT(path, buff) lstat(path, buff)
300 #define VCWD_OPENDIR(pathname) opendir(pathname)
301 #define VCWD_POPEN(command, type) popen(command, type)
302 
303 #define VCWD_REALPATH(path, real_path) tsrm_realpath(path, real_path)
304 
305 #if HAVE_UTIME
306 # ifdef ZEND_WIN32
307 #  define VCWD_UTIME(path, time) win32_utime(path, time)
308 # else
309 #  define VCWD_UTIME(path, time) utime(path, time)
310 # endif
311 #endif
312 
313 #if !defined(ZEND_WIN32)
314 #define VCWD_CHOWN(path, owner, group) chown(path, owner, group)
315 #if HAVE_LCHOWN
316 #define VCWD_LCHOWN(path, owner, group) lchown(path, owner, group)
317 #endif
318 #endif
319 
320 #endif
321 
322 /* Global stat declarations */
323 #ifndef _S_IFDIR
324 #define _S_IFDIR S_IFDIR
325 #endif
326 
327 #ifndef _S_IFREG
328 #define _S_IFREG S_IFREG
329 #endif
330 
331 #ifndef S_IFLNK
332 #define _IFLNK  0120000	/* symbolic link */
333 #define S_IFLNK _IFLNK
334 #endif
335 
336 #ifndef S_ISDIR
337 #define S_ISDIR(mode)	(((mode)&S_IFMT) == S_IFDIR)
338 #endif
339 
340 #ifndef S_ISREG
341 #define S_ISREG(mode)	(((mode)&S_IFMT) == S_IFREG)
342 #endif
343 
344 #ifndef S_ISLNK
345 #define S_ISLNK(mode)	(((mode)&S_IFMT) == S_IFLNK)
346 #endif
347 
348 #ifndef S_IXROOT
349 #define S_IXROOT ( S_IXUSR | S_IXGRP | S_IXOTH )
350 #endif
351 
352 /* XXX should be _S_IFIFO? */
353 #ifndef S_IFIFO
354 #define	_IFIFO  0010000	/* fifo */
355 #define S_IFIFO	_IFIFO
356 #endif
357 
358 #ifndef S_IFBLK
359 #define	_IFBLK  0060000	/* block special */
360 #define S_IFBLK	_IFBLK
361 #endif
362 
363 #endif /* VIRTUAL_CWD_H */
364 
365 /*
366  * Local variables:
367  * tab-width: 4
368  * c-basic-offset: 4
369  * indent-tabs-mode: t
370  * End:
371  * vim600: sw=4 ts=4 fdm=marker
372  * vim<600: sw=4 ts=4
373  */
374