1 /* 2 +----------------------------------------------------------------------+ 3 | PHP Version 5 | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1997-2014 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 char *virtual_getcwd_ex(size_t *length TSRMLS_DC); 155 CWD_API char *virtual_getcwd(char *buf, size_t size TSRMLS_DC); 156 CWD_API int virtual_chdir(const char *path TSRMLS_DC); 157 CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path TSRMLS_DC) TSRMLS_DC); 158 CWD_API int virtual_filepath(const char *path, char **filepath TSRMLS_DC); 159 CWD_API int virtual_filepath_ex(const char *path, char **filepath, verify_path_func verify_path TSRMLS_DC); 160 CWD_API char *virtual_realpath(const char *path, char *real_path TSRMLS_DC); 161 CWD_API FILE *virtual_fopen(const char *path, const char *mode TSRMLS_DC); 162 CWD_API int virtual_open(const char *path TSRMLS_DC, int flags, ...); 163 CWD_API int virtual_creat(const char *path, mode_t mode TSRMLS_DC); 164 CWD_API int virtual_rename(char *oldname, char *newname TSRMLS_DC); 165 CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC); 166 CWD_API int virtual_lstat(const char *path, struct stat *buf TSRMLS_DC); 167 CWD_API int virtual_unlink(const char *path TSRMLS_DC); 168 CWD_API int virtual_mkdir(const char *pathname, mode_t mode TSRMLS_DC); 169 CWD_API int virtual_rmdir(const char *pathname TSRMLS_DC); 170 CWD_API DIR *virtual_opendir(const char *pathname TSRMLS_DC); 171 CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC); 172 CWD_API int virtual_access(const char *pathname, int mode TSRMLS_DC); 173 #if defined(TSRM_WIN32) 174 /* these are not defined in win32 headers */ 175 #ifndef W_OK 176 #define W_OK 0x02 177 #endif 178 #ifndef R_OK 179 #define R_OK 0x04 180 #endif 181 #ifndef X_OK 182 #define X_OK 0x01 183 #endif 184 #ifndef F_OK 185 #define F_OK 0x00 186 #endif 187 #endif 188 189 #if HAVE_UTIME 190 CWD_API int virtual_utime(const char *filename, struct utimbuf *buf TSRMLS_DC); 191 #endif 192 CWD_API int virtual_chmod(const char *filename, mode_t mode TSRMLS_DC); 193 #if !defined(TSRM_WIN32) && !defined(NETWARE) 194 CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int link TSRMLS_DC); 195 #endif 196 197 /* One of the following constants must be used as the last argument 198 in virtual_file_ex() call. */ 199 200 #define CWD_EXPAND 0 /* expand "." and ".." but dont resolve symlinks */ 201 #define CWD_FILEPATH 1 /* resolve symlinks if file is exist otherwise expand */ 202 #define CWD_REALPATH 2 /* call realpath(), resolve symlinks. File must exist */ 203 204 CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath TSRMLS_DC); 205 206 CWD_API char *tsrm_realpath(const char *path, char *real_path TSRMLS_DC); 207 208 #define REALPATH_CACHE_TTL (2*60) /* 2 minutes */ 209 #define REALPATH_CACHE_SIZE 0 /* disabled while php.ini isn't loaded */ 210 211 typedef struct _realpath_cache_bucket { 212 unsigned long key; 213 char *path; 214 int path_len; 215 char *realpath; 216 int realpath_len; 217 int is_dir; 218 time_t expires; 219 #ifdef PHP_WIN32 220 unsigned char is_rvalid; 221 unsigned char is_readable; 222 unsigned char is_wvalid; 223 unsigned char is_writable; 224 #endif 225 struct _realpath_cache_bucket *next; 226 } realpath_cache_bucket; 227 228 typedef struct _virtual_cwd_globals { 229 cwd_state cwd; 230 long realpath_cache_size; 231 long realpath_cache_size_limit; 232 long realpath_cache_ttl; 233 realpath_cache_bucket *realpath_cache[1024]; 234 } virtual_cwd_globals; 235 236 #ifdef ZTS 237 extern ts_rsrc_id cwd_globals_id; 238 # define CWDG(v) TSRMG(cwd_globals_id, virtual_cwd_globals *, v) 239 #else 240 extern virtual_cwd_globals cwd_globals; 241 # define CWDG(v) (cwd_globals.v) 242 #endif 243 244 CWD_API void realpath_cache_clean(TSRMLS_D); 245 CWD_API void realpath_cache_del(const char *path, int path_len TSRMLS_DC); 246 CWD_API realpath_cache_bucket* realpath_cache_lookup(const char *path, int path_len, time_t t TSRMLS_DC); 247 CWD_API int realpath_cache_size(TSRMLS_D); 248 CWD_API int realpath_cache_max_buckets(TSRMLS_D); 249 CWD_API realpath_cache_bucket** realpath_cache_get_buckets(TSRMLS_D); 250 251 /* The actual macros to be used in programs using TSRM 252 * If the program defines VIRTUAL_DIR it will use the 253 * virtual_* functions 254 */ 255 256 #ifdef VIRTUAL_DIR 257 258 #define VCWD_GETCWD(buff, size) virtual_getcwd(buff, size TSRMLS_CC) 259 #define VCWD_FOPEN(path, mode) virtual_fopen(path, mode TSRMLS_CC) 260 /* Because open() has two modes, we have to macros to replace it */ 261 #define VCWD_OPEN(path, flags) virtual_open(path TSRMLS_CC, flags) 262 #define VCWD_OPEN_MODE(path, flags, mode) virtual_open(path TSRMLS_CC, flags, mode) 263 #define VCWD_CREAT(path, mode) virtual_creat(path, mode TSRMLS_CC) 264 #define VCWD_CHDIR(path) virtual_chdir(path TSRMLS_CC) 265 #define VCWD_CHDIR_FILE(path) virtual_chdir_file(path, virtual_chdir TSRMLS_CC) 266 #define VCWD_GETWD(buf) 267 #define VCWD_REALPATH(path, real_path) virtual_realpath(path, real_path TSRMLS_CC) 268 #define VCWD_RENAME(oldname, newname) virtual_rename(oldname, newname TSRMLS_CC) 269 #define VCWD_STAT(path, buff) virtual_stat(path, buff TSRMLS_CC) 270 # define VCWD_LSTAT(path, buff) virtual_lstat(path, buff TSRMLS_CC) 271 #define VCWD_UNLINK(path) virtual_unlink(path TSRMLS_CC) 272 #define VCWD_MKDIR(pathname, mode) virtual_mkdir(pathname, mode TSRMLS_CC) 273 #define VCWD_RMDIR(pathname) virtual_rmdir(pathname TSRMLS_CC) 274 #define VCWD_OPENDIR(pathname) virtual_opendir(pathname TSRMLS_CC) 275 #define VCWD_POPEN(command, type) virtual_popen(command, type TSRMLS_CC) 276 #define VCWD_ACCESS(pathname, mode) virtual_access(pathname, mode TSRMLS_CC) 277 #if HAVE_UTIME 278 #define VCWD_UTIME(path, time) virtual_utime(path, time TSRMLS_CC) 279 #endif 280 #define VCWD_CHMOD(path, mode) virtual_chmod(path, mode TSRMLS_CC) 281 #if !defined(TSRM_WIN32) && !defined(NETWARE) 282 #define VCWD_CHOWN(path, owner, group) virtual_chown(path, owner, group, 0 TSRMLS_CC) 283 #if HAVE_LCHOWN 284 #define VCWD_LCHOWN(path, owner, group) virtual_chown(path, owner, group, 1 TSRMLS_CC) 285 #endif 286 #endif 287 288 #else 289 290 #define VCWD_GETCWD(buff, size) getcwd(buff, size) 291 #define VCWD_FOPEN(path, mode) fopen(path, mode) 292 #define VCWD_OPEN(path, flags) open(path, flags) 293 #define VCWD_OPEN_MODE(path, flags, mode) open(path, flags, mode) 294 #define VCWD_CREAT(path, mode) creat(path, mode) 295 /* rename on windows will fail if newname already exists. 296 MoveFileEx has to be used */ 297 #if defined(TSRM_WIN32) 298 # define VCWD_RENAME(oldname, newname) (MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING|MOVEFILE_COPY_ALLOWED) == 0 ? -1 : 0) 299 #else 300 # define VCWD_RENAME(oldname, newname) rename(oldname, newname) 301 #endif 302 #define VCWD_CHDIR(path) chdir(path) 303 #define VCWD_CHDIR_FILE(path) virtual_chdir_file(path, chdir) 304 #define VCWD_GETWD(buf) getwd(buf) 305 #define VCWD_STAT(path, buff) php_sys_stat(path, buff) 306 #define VCWD_LSTAT(path, buff) lstat(path, buff) 307 #define VCWD_UNLINK(path) unlink(path) 308 #define VCWD_MKDIR(pathname, mode) mkdir(pathname, mode) 309 #define VCWD_RMDIR(pathname) rmdir(pathname) 310 #define VCWD_OPENDIR(pathname) opendir(pathname) 311 #define VCWD_POPEN(command, type) popen(command, type) 312 #if defined(TSRM_WIN32) 313 #define VCWD_ACCESS(pathname, mode) tsrm_win32_access(pathname, mode TSRMLS_CC) 314 #else 315 #define VCWD_ACCESS(pathname, mode) access(pathname, mode) 316 #endif 317 318 #define VCWD_REALPATH(path, real_path) tsrm_realpath(path, real_path TSRMLS_CC) 319 320 #if HAVE_UTIME 321 # ifdef TSRM_WIN32 322 # define VCWD_UTIME(path, time) win32_utime(path, time) 323 # else 324 # define VCWD_UTIME(path, time) utime(path, time) 325 # endif 326 #endif 327 328 #define VCWD_CHMOD(path, mode) chmod(path, mode) 329 #if !defined(TSRM_WIN32) && !defined(NETWARE) 330 #define VCWD_CHOWN(path, owner, group) chown(path, owner, group) 331 #if HAVE_LCHOWN 332 #define VCWD_LCHOWN(path, owner, group) lchown(path, owner, group) 333 #endif 334 #endif 335 336 #endif 337 338 #endif /* VIRTUAL_CWD_H */ 339