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