xref: /PHP-7.2/ext/phar/func_interceptors.c (revision 60a69dae)
1 /*
2   +----------------------------------------------------------------------+
3   | phar php single-file executable PHP extension                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 2005-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: Gregory Beaver <cellog@php.net>                             |
16   +----------------------------------------------------------------------+
17 */
18 
19 /* $Id$ */
20 
21 #include "phar_internal.h"
22 
23 #define PHAR_FUNC(name) \
24 	static PHP_NAMED_FUNCTION(name)
25 
PHAR_FUNC(phar_opendir)26 PHAR_FUNC(phar_opendir) /* {{{ */
27 {
28 	char *filename;
29 	size_t filename_len;
30 	zval *zcontext = NULL;
31 
32 	if (!PHAR_G(intercepted)) {
33 		goto skip_phar;
34 	}
35 
36 	if ((PHAR_G(phar_fname_map.u.flags) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
37 		&& !cached_phars.u.flags) {
38 		goto skip_phar;
39 	}
40 
41 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|z", &filename, &filename_len, &zcontext) == FAILURE) {
42 		return;
43 	}
44 
45 	if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
46 		char *arch, *entry, *fname;
47 		int arch_len, entry_len, fname_len;
48 		fname = (char*)zend_get_executed_filename();
49 
50 		/* we are checking for existence of a file within the relative path.  Chances are good that this is
51 		   retrieving something from within the phar archive */
52 
53 		if (strncasecmp(fname, "phar://", 7)) {
54 			goto skip_phar;
55 		}
56 		fname_len = strlen(fname);
57 		if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
58 			php_stream_context *context = NULL;
59 			php_stream *stream;
60 			char *name;
61 
62 			efree(entry);
63 			entry = estrndup(filename, filename_len);
64 			/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
65 			entry_len = filename_len;
66 			/* retrieving a file within the current directory, so use this if possible */
67 			entry = phar_fix_filepath(entry, &entry_len, 1);
68 
69 			if (entry[0] == '/') {
70 				spprintf(&name, 4096, "phar://%s%s", arch, entry);
71 			} else {
72 				spprintf(&name, 4096, "phar://%s/%s", arch, entry);
73 			}
74 			efree(entry);
75 			efree(arch);
76 			if (zcontext) {
77 				context = php_stream_context_from_zval(zcontext, 0);
78 			}
79 			stream = php_stream_opendir(name, REPORT_ERRORS, context);
80 			efree(name);
81 			if (!stream) {
82 				RETURN_FALSE;
83 			}
84 			php_stream_to_zval(stream, return_value);
85 			return;
86 		}
87 	}
88 skip_phar:
89 	PHAR_G(orig_opendir)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
90 	return;
91 }
92 /* }}} */
93 
PHAR_FUNC(phar_file_get_contents)94 PHAR_FUNC(phar_file_get_contents) /* {{{ */
95 {
96 	char *filename;
97 	size_t filename_len;
98 	zend_string *contents;
99 	zend_bool use_include_path = 0;
100 	php_stream *stream;
101 	zend_long offset = -1;
102 	zend_long maxlen = PHP_STREAM_COPY_ALL;
103 	zval *zcontext = NULL;
104 
105 	if (!PHAR_G(intercepted)) {
106 		goto skip_phar;
107 	}
108 
109 	if ((PHAR_G(phar_fname_map.u.flags) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
110 		&& !cached_phars.u.flags) {
111 		goto skip_phar;
112 	}
113 
114 	/* Parse arguments */
115 	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p|br!ll", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen) == FAILURE) {
116 		goto skip_phar;
117 	}
118 
119 	if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
120 		char *arch, *entry, *fname;
121 		zend_string *entry_str = NULL;
122 		int arch_len, entry_len, fname_len;
123 		php_stream_context *context = NULL;
124 
125 		fname = (char*)zend_get_executed_filename();
126 
127 		if (strncasecmp(fname, "phar://", 7)) {
128 			goto skip_phar;
129 		}
130 		fname_len = strlen(fname);
131 		if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
132 			char *name;
133 			phar_archive_data *phar;
134 
135 			efree(entry);
136 			entry = filename;
137 			/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
138 			entry_len = filename_len;
139 
140 			if (ZEND_NUM_ARGS() == 5 && maxlen < 0) {
141 				efree(arch);
142 				php_error_docref(NULL, E_WARNING, "length must be greater than or equal to zero");
143 				RETURN_FALSE;
144 			}
145 
146 			/* retrieving a file defaults to within the current directory, so use this if possible */
147 			if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
148 				efree(arch);
149 				goto skip_phar;
150 			}
151 			if (use_include_path) {
152 				if ((entry_str = phar_find_in_include_path(entry, entry_len, NULL))) {
153 					name = ZSTR_VAL(entry_str);
154 					goto phar_it;
155 				} else {
156 					/* this file is not in the phar, use the original path */
157 					efree(arch);
158 					goto skip_phar;
159 				}
160 			} else {
161 				entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
162 				if (entry[0] == '/') {
163 					if (!zend_hash_str_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
164 						/* this file is not in the phar, use the original path */
165 notfound:
166 						efree(arch);
167 						efree(entry);
168 						goto skip_phar;
169 					}
170 				} else {
171 					if (!zend_hash_str_exists(&(phar->manifest), entry, entry_len)) {
172 						goto notfound;
173 					}
174 				}
175 				/* auto-convert to phar:// */
176 				if (entry[0] == '/') {
177 					spprintf(&name, 4096, "phar://%s%s", arch, entry);
178 				} else {
179 					spprintf(&name, 4096, "phar://%s/%s", arch, entry);
180 				}
181 				if (entry != filename) {
182 					efree(entry);
183 				}
184 			}
185 
186 phar_it:
187 			efree(arch);
188 			if (zcontext) {
189 				context = php_stream_context_from_zval(zcontext, 0);
190 			}
191 			stream = php_stream_open_wrapper_ex(name, "rb", 0 | REPORT_ERRORS, NULL, context);
192 			if (entry_str) {
193 				zend_string_release(entry_str);
194 			} else {
195 				efree(name);
196 			}
197 
198 			if (!stream) {
199 				RETURN_FALSE;
200 			}
201 
202 			if (offset > 0 && php_stream_seek(stream, offset, SEEK_SET) < 0) {
203 				php_error_docref(NULL, E_WARNING, "Failed to seek to position " ZEND_LONG_FMT " in the stream", offset);
204 				php_stream_close(stream);
205 				RETURN_FALSE;
206 			}
207 
208 			/* uses mmap if possible */
209 			contents = php_stream_copy_to_mem(stream, maxlen, 0);
210 			if (contents && ZSTR_LEN(contents) > 0) {
211 				RETVAL_STR(contents);
212 			} else if (contents) {
213 				zend_string_release(contents);
214 				RETVAL_EMPTY_STRING();
215 			} else {
216 				RETVAL_FALSE;
217 			}
218 
219 			php_stream_close(stream);
220 			return;
221 		}
222 	}
223 skip_phar:
224 	PHAR_G(orig_file_get_contents)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
225 	return;
226 }
227 /* }}} */
228 
PHAR_FUNC(phar_readfile)229 PHAR_FUNC(phar_readfile) /* {{{ */
230 {
231 	char *filename;
232 	size_t filename_len;
233 	int size = 0;
234 	zend_bool use_include_path = 0;
235 	zval *zcontext = NULL;
236 	php_stream *stream;
237 
238 	if (!PHAR_G(intercepted)) {
239 		goto skip_phar;
240 	}
241 
242 	if ((PHAR_G(phar_fname_map.u.flags) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
243 		&& !cached_phars.u.flags) {
244 		goto skip_phar;
245 	}
246 	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
247 		goto skip_phar;
248 	}
249 	if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
250 		char *arch, *entry, *fname;
251 		zend_string *entry_str = NULL;
252 		int arch_len, entry_len, fname_len;
253 		php_stream_context *context = NULL;
254 		char *name;
255 		phar_archive_data *phar;
256 		fname = (char*)zend_get_executed_filename();
257 
258 		if (strncasecmp(fname, "phar://", 7)) {
259 			goto skip_phar;
260 		}
261 		fname_len = strlen(fname);
262 		if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
263 			goto skip_phar;
264 		}
265 
266 		efree(entry);
267 		entry = filename;
268 		/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
269 		entry_len = filename_len;
270 		/* retrieving a file defaults to within the current directory, so use this if possible */
271 		if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
272 			efree(arch);
273 			goto skip_phar;
274 		}
275 		if (use_include_path) {
276 			if (!(entry_str = phar_find_in_include_path(entry, entry_len, NULL))) {
277 				/* this file is not in the phar, use the original path */
278 				efree(arch);
279 				goto skip_phar;
280 			} else {
281 				name = ZSTR_VAL(entry_str);
282 			}
283 		} else {
284 			entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
285 			if (entry[0] == '/') {
286 				if (!zend_hash_str_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
287 					/* this file is not in the phar, use the original path */
288 notfound:
289 					efree(entry);
290 					efree(arch);
291 					goto skip_phar;
292 				}
293 			} else {
294 				if (!zend_hash_str_exists(&(phar->manifest), entry, entry_len)) {
295 					goto notfound;
296 				}
297 			}
298 			/* auto-convert to phar:// */
299 			if (entry[0] == '/') {
300 				spprintf(&name, 4096, "phar://%s%s", arch, entry);
301 			} else {
302 				spprintf(&name, 4096, "phar://%s/%s", arch, entry);
303 			}
304 			efree(entry);
305 		}
306 
307 		efree(arch);
308 		context = php_stream_context_from_zval(zcontext, 0);
309 		stream = php_stream_open_wrapper_ex(name, "rb", 0 | REPORT_ERRORS, NULL, context);
310 		if (entry_str) {
311 			zend_string_release(entry_str);
312 		} else {
313 			efree(name);
314 		}
315 		if (stream == NULL) {
316 			RETURN_FALSE;
317 		}
318 		size = php_stream_passthru(stream);
319 		php_stream_close(stream);
320 		RETURN_LONG(size);
321 	}
322 
323 skip_phar:
324 	PHAR_G(orig_readfile)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
325 	return;
326 
327 }
328 /* }}} */
329 
PHAR_FUNC(phar_fopen)330 PHAR_FUNC(phar_fopen) /* {{{ */
331 {
332 	char *filename, *mode;
333 	size_t filename_len, mode_len;
334 	zend_bool use_include_path = 0;
335 	zval *zcontext = NULL;
336 	php_stream *stream;
337 
338 	if (!PHAR_G(intercepted)) {
339 		goto skip_phar;
340 	}
341 
342 	if ((PHAR_G(phar_fname_map.u.flags) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
343 		&& !cached_phars.u.flags) {
344 		/* no need to check, include_path not even specified in fopen/ no active phars */
345 		goto skip_phar;
346 	}
347 	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "ps|br", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
348 		goto skip_phar;
349 	}
350 	if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
351 		char *arch, *entry, *fname;
352 		zend_string *entry_str = NULL;
353 		int arch_len, entry_len, fname_len;
354 		php_stream_context *context = NULL;
355 		char *name;
356 		phar_archive_data *phar;
357 		fname = (char*)zend_get_executed_filename();
358 
359 		if (strncasecmp(fname, "phar://", 7)) {
360 			goto skip_phar;
361 		}
362 		fname_len = strlen(fname);
363 		if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
364 			goto skip_phar;
365 		}
366 
367 		efree(entry);
368 		entry = filename;
369 		/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
370 		entry_len = filename_len;
371 		/* retrieving a file defaults to within the current directory, so use this if possible */
372 		if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
373 			efree(arch);
374 			goto skip_phar;
375 		}
376 		if (use_include_path) {
377 			if (!(entry_str = phar_find_in_include_path(entry, entry_len, NULL))) {
378 				/* this file is not in the phar, use the original path */
379 				efree(arch);
380 				goto skip_phar;
381 			} else {
382 				name = ZSTR_VAL(entry_str);
383 			}
384 		} else {
385 			entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
386 			if (entry[0] == '/') {
387 				if (!zend_hash_str_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
388 					/* this file is not in the phar, use the original path */
389 notfound:
390 					efree(entry);
391 					efree(arch);
392 					goto skip_phar;
393 				}
394 			} else {
395 				if (!zend_hash_str_exists(&(phar->manifest), entry, entry_len)) {
396 					/* this file is not in the phar, use the original path */
397 					goto notfound;
398 				}
399 			}
400 			/* auto-convert to phar:// */
401 			if (entry[0] == '/') {
402 				spprintf(&name, 4096, "phar://%s%s", arch, entry);
403 			} else {
404 				spprintf(&name, 4096, "phar://%s/%s", arch, entry);
405 			}
406 			efree(entry);
407 		}
408 
409 		efree(arch);
410 		context = php_stream_context_from_zval(zcontext, 0);
411 		stream = php_stream_open_wrapper_ex(name, mode, 0 | REPORT_ERRORS, NULL, context);
412 		if (entry_str) {
413 			zend_string_release(entry_str);
414 		} else {
415 			efree(name);
416 		}
417 		if (stream == NULL) {
418 			RETURN_FALSE;
419 		}
420 		php_stream_to_zval(stream, return_value);
421 		if (zcontext) {
422 			Z_ADDREF_P(zcontext);
423 		}
424 		return;
425 	}
426 skip_phar:
427 	PHAR_G(orig_fopen)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
428 	return;
429 }
430 /* }}} */
431 
432 #define IS_LINK_OPERATION(__t) ((__t) == FS_TYPE || (__t) == FS_IS_LINK || (__t) == FS_LSTAT)
433 #define IS_EXISTS_CHECK(__t) ((__t) == FS_EXISTS  || (__t) == FS_IS_W || (__t) == FS_IS_R || (__t) == FS_IS_X || (__t) == FS_IS_FILE || (__t) == FS_IS_DIR || (__t) == FS_IS_LINK)
434 #define IS_ABLE_CHECK(__t) ((__t) == FS_IS_R || (__t) == FS_IS_W || (__t) == FS_IS_X)
435 #define IS_ACCESS_CHECK(__t) (IS_ABLE_CHECK(type) || (__t) == FS_EXISTS)
436 
437 /* {{{ php_stat
438  */
phar_fancy_stat(zend_stat_t * stat_sb,int type,zval * return_value)439 static void phar_fancy_stat(zend_stat_t *stat_sb, int type, zval *return_value)
440 {
441 	zval stat_dev, stat_ino, stat_mode, stat_nlink, stat_uid, stat_gid, stat_rdev,
442 		 stat_size, stat_atime, stat_mtime, stat_ctime, stat_blksize, stat_blocks;
443 	int rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */
444 	char *stat_sb_names[13] = {
445 		"dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
446 		"size", "atime", "mtime", "ctime", "blksize", "blocks"
447 	};
448 
449 	if (type >= FS_IS_W && type <= FS_IS_X) {
450 		if(stat_sb->st_uid==getuid()) {
451 			rmask=S_IRUSR;
452 			wmask=S_IWUSR;
453 			xmask=S_IXUSR;
454 		} else if(stat_sb->st_gid==getgid()) {
455 			rmask=S_IRGRP;
456 			wmask=S_IWGRP;
457 			xmask=S_IXGRP;
458 		} else {
459 			int   groups, n, i;
460 			gid_t *gids;
461 
462 			groups = getgroups(0, NULL);
463 			if(groups > 0) {
464 				gids=(gid_t *)safe_emalloc(groups, sizeof(gid_t), 0);
465 				n=getgroups(groups, gids);
466 				for(i=0;i<n;++i){
467 					if(stat_sb->st_gid==gids[i]) {
468 						rmask=S_IRGRP;
469 						wmask=S_IWGRP;
470 						xmask=S_IXGRP;
471 						break;
472 					}
473 				}
474 				efree(gids);
475 			}
476 		}
477 	}
478 
479 	switch (type) {
480 	case FS_PERMS:
481 		RETURN_LONG((zend_long)stat_sb->st_mode);
482 	case FS_INODE:
483 		RETURN_LONG((zend_long)stat_sb->st_ino);
484 	case FS_SIZE:
485 		RETURN_LONG((zend_long)stat_sb->st_size);
486 	case FS_OWNER:
487 		RETURN_LONG((zend_long)stat_sb->st_uid);
488 	case FS_GROUP:
489 		RETURN_LONG((zend_long)stat_sb->st_gid);
490 	case FS_ATIME:
491 		RETURN_LONG((zend_long)stat_sb->st_atime);
492 	case FS_MTIME:
493 		RETURN_LONG((zend_long)stat_sb->st_mtime);
494 	case FS_CTIME:
495 		RETURN_LONG((zend_long)stat_sb->st_ctime);
496 	case FS_TYPE:
497 		if (S_ISLNK(stat_sb->st_mode)) {
498 			RETURN_STRING("link");
499 		}
500 		switch(stat_sb->st_mode & S_IFMT) {
501 		case S_IFDIR: RETURN_STRING("dir");
502 		case S_IFREG: RETURN_STRING("file");
503 		}
504 		php_error_docref(NULL, E_NOTICE, "Unknown file type (%u)", stat_sb->st_mode & S_IFMT);
505 		RETURN_STRING("unknown");
506 	case FS_IS_W:
507 		RETURN_BOOL((stat_sb->st_mode & wmask) != 0);
508 	case FS_IS_R:
509 		RETURN_BOOL((stat_sb->st_mode&rmask)!=0);
510 	case FS_IS_X:
511 		RETURN_BOOL((stat_sb->st_mode&xmask)!=0 && !S_ISDIR(stat_sb->st_mode));
512 	case FS_IS_FILE:
513 		RETURN_BOOL(S_ISREG(stat_sb->st_mode));
514 	case FS_IS_DIR:
515 		RETURN_BOOL(S_ISDIR(stat_sb->st_mode));
516 	case FS_IS_LINK:
517 		RETURN_BOOL(S_ISLNK(stat_sb->st_mode));
518 	case FS_EXISTS:
519 		RETURN_TRUE; /* the false case was done earlier */
520 	case FS_LSTAT:
521 		/* FALLTHROUGH */
522 	case FS_STAT:
523 		array_init(return_value);
524 
525 		ZVAL_LONG(&stat_dev, stat_sb->st_dev);
526 		ZVAL_LONG(&stat_ino, stat_sb->st_ino);
527 		ZVAL_LONG(&stat_mode, stat_sb->st_mode);
528 		ZVAL_LONG(&stat_nlink, stat_sb->st_nlink);
529 		ZVAL_LONG(&stat_uid, stat_sb->st_uid);
530 		ZVAL_LONG(&stat_gid, stat_sb->st_gid);
531 #ifdef HAVE_ST_RDEV
532 		ZVAL_LONG(&stat_rdev, stat_sb->st_rdev);
533 #else
534 		ZVAL_LONG(&stat_rdev, -1);
535 #endif
536 		ZVAL_LONG(&stat_size, stat_sb->st_size);
537 		ZVAL_LONG(&stat_atime, stat_sb->st_atime);
538 		ZVAL_LONG(&stat_mtime, stat_sb->st_mtime);
539 		ZVAL_LONG(&stat_ctime, stat_sb->st_ctime);
540 #ifdef HAVE_ST_BLKSIZE
541 		ZVAL_LONG(&stat_blksize, stat_sb->st_blksize);
542 #else
543 		ZVAL_LONG(&stat_blksize,-1);
544 #endif
545 #ifdef HAVE_ST_BLOCKS
546 		ZVAL_LONG(&stat_blocks, stat_sb->st_blocks);
547 #else
548 		ZVAL_LONG(&stat_blocks,-1);
549 #endif
550 		/* Store numeric indexes in proper order */
551 		zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_dev);
552 		zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_ino);
553 		zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_mode);
554 		zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_nlink);
555 		zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_uid);
556 		zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_gid);
557 
558 		zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_rdev);
559 		zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_size);
560 		zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_atime);
561 		zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_mtime);
562 		zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_ctime);
563 		zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_blksize);
564 		zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_blocks);
565 
566 		/* Store string indexes referencing the same zval*/
567 		zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[0], strlen(stat_sb_names[0]), &stat_dev);
568 		zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[1], strlen(stat_sb_names[1]), &stat_ino);
569 		zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[2], strlen(stat_sb_names[2]), &stat_mode);
570 		zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[3], strlen(stat_sb_names[3]), &stat_nlink);
571 		zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[4], strlen(stat_sb_names[4]), &stat_uid);
572 		zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[5], strlen(stat_sb_names[5]), &stat_gid);
573 		zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[6], strlen(stat_sb_names[6]), &stat_rdev);
574 		zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[7], strlen(stat_sb_names[7]), &stat_size);
575 		zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[8], strlen(stat_sb_names[8]), &stat_atime);
576 		zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[9], strlen(stat_sb_names[9]), &stat_mtime);
577 		zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[10], strlen(stat_sb_names[10]), &stat_ctime);
578 		zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[11], strlen(stat_sb_names[11]), &stat_blksize);
579 		zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[12], strlen(stat_sb_names[12]), &stat_blocks);
580 
581 		return;
582 	}
583 	php_error_docref(NULL, E_WARNING, "Didn't understand stat call");
584 	RETURN_FALSE;
585 }
586 /* }}} */
587 
phar_file_stat(const char * filename,size_t filename_length,int type,zif_handler orig_stat_func,INTERNAL_FUNCTION_PARAMETERS)588 static void phar_file_stat(const char *filename, size_t filename_length, int type, zif_handler orig_stat_func, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
589 {
590 	if (!filename_length) {
591 		RETURN_FALSE;
592 	}
593 
594 	if (!IS_ABSOLUTE_PATH(filename, filename_length) && !strstr(filename, "://")) {
595 		char *arch, *entry, *fname;
596 		int arch_len, entry_len, fname_len;
597 		zend_stat_t sb = {0};
598 		phar_entry_info *data = NULL;
599 		phar_archive_data *phar;
600 
601 		fname = (char*)zend_get_executed_filename();
602 
603 		/* we are checking for existence of a file within the relative path.  Chances are good that this is
604 		   retrieving something from within the phar archive */
605 
606 		if (strncasecmp(fname, "phar://", 7)) {
607 			goto skip_phar;
608 		}
609 		fname_len = strlen(fname);
610 		if (PHAR_G(last_phar) && fname_len - 7 >= PHAR_G(last_phar_name_len) && !memcmp(fname + 7, PHAR_G(last_phar_name), PHAR_G(last_phar_name_len))) {
611 			arch = estrndup(PHAR_G(last_phar_name), PHAR_G(last_phar_name_len));
612 			arch_len = PHAR_G(last_phar_name_len);
613 			entry = estrndup(filename, filename_length);
614 			/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
615 			entry_len = (int) filename_length;
616 			phar = PHAR_G(last_phar);
617 			goto splitted;
618 		}
619 		if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
620 
621 			efree(entry);
622 			entry = estrndup(filename, filename_length);
623 			/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
624 			entry_len = (int) filename_length;
625 			if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
626 				efree(arch);
627 				efree(entry);
628 				goto skip_phar;
629 			}
630 splitted:
631 			entry = phar_fix_filepath(entry, &entry_len, 1);
632 			if (entry[0] == '/') {
633 				if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
634 					efree(entry);
635 					goto stat_entry;
636 				}
637 				goto notfound;
638 			}
639 			if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
640 				efree(entry);
641 				goto stat_entry;
642 			}
643 			if (zend_hash_str_exists(&(phar->virtual_dirs), entry, entry_len)) {
644 				efree(entry);
645 				efree(arch);
646 				if (IS_EXISTS_CHECK(type)) {
647 					RETURN_TRUE;
648 				}
649 				sb.st_size = 0;
650 				sb.st_mode = 0777;
651 				sb.st_mode |= S_IFDIR; /* regular directory */
652 				sb.st_mtime = phar->max_timestamp;
653 				sb.st_atime = phar->max_timestamp;
654 				sb.st_ctime = phar->max_timestamp;
655 				goto statme_baby;
656 			} else {
657 				char *save;
658 				int save_len;
659 
660 notfound:
661 				efree(entry);
662 				save = PHAR_G(cwd);
663 				save_len = PHAR_G(cwd_len);
664 				/* this file is not in the current directory, use the original path */
665 				entry = estrndup(filename, filename_length);
666 				entry_len = filename_length;
667 				PHAR_G(cwd) = "/";
668 				PHAR_G(cwd_len) = 0;
669 				/* clean path without cwd */
670 				entry = phar_fix_filepath(entry, &entry_len, 1);
671 				if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
672 					PHAR_G(cwd) = save;
673 					PHAR_G(cwd_len) = save_len;
674 					efree(entry);
675 					if (IS_EXISTS_CHECK(type)) {
676 						efree(arch);
677 						RETURN_TRUE;
678 					}
679 					goto stat_entry;
680 				}
681 				if (zend_hash_str_exists(&(phar->virtual_dirs), entry + 1, entry_len - 1)) {
682 					PHAR_G(cwd) = save;
683 					PHAR_G(cwd_len) = save_len;
684 					efree(entry);
685 					efree(arch);
686 					if (IS_EXISTS_CHECK(type)) {
687 						RETURN_TRUE;
688 					}
689 					sb.st_size = 0;
690 					sb.st_mode = 0777;
691 					sb.st_mode |= S_IFDIR; /* regular directory */
692 					sb.st_mtime = phar->max_timestamp;
693 					sb.st_atime = phar->max_timestamp;
694 					sb.st_ctime = phar->max_timestamp;
695 					goto statme_baby;
696 				}
697 				PHAR_G(cwd) = save;
698 				PHAR_G(cwd_len) = save_len;
699 				efree(entry);
700 				efree(arch);
701 				/* Error Occurred */
702 				if (!IS_EXISTS_CHECK(type)) {
703 					php_error_docref(NULL, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename);
704 				}
705 				RETURN_FALSE;
706 			}
707 stat_entry:
708 			efree(arch);
709 			if (!data->is_dir) {
710 				sb.st_size = data->uncompressed_filesize;
711 				sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
712 				if (data->link) {
713 					sb.st_mode |= S_IFREG|S_IFLNK; /* regular file */
714 				} else {
715 					sb.st_mode |= S_IFREG; /* regular file */
716 				}
717 				/* timestamp is just the timestamp when this was added to the phar */
718 				sb.st_mtime = data->timestamp;
719 				sb.st_atime = data->timestamp;
720 				sb.st_ctime = data->timestamp;
721 			} else {
722 				sb.st_size = 0;
723 				sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
724 				sb.st_mode |= S_IFDIR; /* regular directory */
725 				if (data->link) {
726 					sb.st_mode |= S_IFLNK;
727 				}
728 				/* timestamp is just the timestamp when this was added to the phar */
729 				sb.st_mtime = data->timestamp;
730 				sb.st_atime = data->timestamp;
731 				sb.st_ctime = data->timestamp;
732 			}
733 
734 statme_baby:
735 			if (!phar->is_writeable) {
736 				sb.st_mode = (sb.st_mode & 0555) | (sb.st_mode & ~0777);
737 			}
738 
739 			sb.st_nlink = 1;
740 			sb.st_rdev = -1;
741 			/* this is only for APC, so use /dev/null device - no chance of conflict there! */
742 			sb.st_dev = 0xc;
743 			/* generate unique inode number for alias/filename, so no phars will conflict */
744 			if (data) {
745 				sb.st_ino = data->inode;
746 			}
747 #ifndef PHP_WIN32
748 			sb.st_blksize = -1;
749 			sb.st_blocks = -1;
750 #endif
751 			phar_fancy_stat(&sb, type, return_value);
752 			return;
753 		}
754 	}
755 skip_phar:
756 	orig_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU);
757 	return;
758 }
759 /* }}} */
760 
761 #define PharFileFunction(fname, funcnum, orig) \
762 ZEND_NAMED_FUNCTION(fname) { \
763 	if (!PHAR_G(intercepted)) { \
764 		PHAR_G(orig)(INTERNAL_FUNCTION_PARAM_PASSTHRU); \
765 	} else { \
766 		char *filename; \
767 		size_t filename_len; \
768 		\
769 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) { \
770 			return; \
771 		} \
772 		\
773 		phar_file_stat(filename, filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \
774 	} \
775 }
776 /* }}} */
777 
778 /* {{{ proto int fileperms(string filename)
779    Get file permissions */
PharFileFunction(phar_fileperms,FS_PERMS,orig_fileperms)780 PharFileFunction(phar_fileperms, FS_PERMS, orig_fileperms)
781 /* }}} */
782 
783 /* {{{ proto int fileinode(string filename)
784    Get file inode */
785 PharFileFunction(phar_fileinode, FS_INODE, orig_fileinode)
786 /* }}} */
787 
788 /* {{{ proto int filesize(string filename)
789    Get file size */
790 PharFileFunction(phar_filesize, FS_SIZE, orig_filesize)
791 /* }}} */
792 
793 /* {{{ proto int fileowner(string filename)
794    Get file owner */
795 PharFileFunction(phar_fileowner, FS_OWNER, orig_fileowner)
796 /* }}} */
797 
798 /* {{{ proto int filegroup(string filename)
799    Get file group */
800 PharFileFunction(phar_filegroup, FS_GROUP, orig_filegroup)
801 /* }}} */
802 
803 /* {{{ proto int fileatime(string filename)
804    Get last access time of file */
805 PharFileFunction(phar_fileatime, FS_ATIME, orig_fileatime)
806 /* }}} */
807 
808 /* {{{ proto int filemtime(string filename)
809    Get last modification time of file */
810 PharFileFunction(phar_filemtime, FS_MTIME, orig_filemtime)
811 /* }}} */
812 
813 /* {{{ proto int filectime(string filename)
814    Get inode modification time of file */
815 PharFileFunction(phar_filectime, FS_CTIME, orig_filectime)
816 /* }}} */
817 
818 /* {{{ proto string filetype(string filename)
819    Get file type */
820 PharFileFunction(phar_filetype, FS_TYPE, orig_filetype)
821 /* }}} */
822 
823 /* {{{ proto bool is_writable(string filename)
824    Returns true if file can be written */
825 PharFileFunction(phar_is_writable, FS_IS_W, orig_is_writable)
826 /* }}} */
827 
828 /* {{{ proto bool is_readable(string filename)
829    Returns true if file can be read */
830 PharFileFunction(phar_is_readable, FS_IS_R, orig_is_readable)
831 /* }}} */
832 
833 /* {{{ proto bool is_executable(string filename)
834    Returns true if file is executable */
835 PharFileFunction(phar_is_executable, FS_IS_X, orig_is_executable)
836 /* }}} */
837 
838 /* {{{ proto bool file_exists(string filename)
839    Returns true if filename exists */
840 PharFileFunction(phar_file_exists, FS_EXISTS, orig_file_exists)
841 /* }}} */
842 
843 /* {{{ proto bool is_dir(string filename)
844    Returns true if file is directory */
845 PharFileFunction(phar_is_dir, FS_IS_DIR, orig_is_dir)
846 /* }}} */
847 
848 PHAR_FUNC(phar_is_file) /* {{{ */
849 {
850 	char *filename;
851 	size_t filename_len;
852 
853 	if (!PHAR_G(intercepted)) {
854 		goto skip_phar;
855 	}
856 
857 	if ((PHAR_G(phar_fname_map.u.flags) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
858 		&& !cached_phars.u.flags) {
859 		goto skip_phar;
860 	}
861 	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) {
862 		goto skip_phar;
863 	}
864 	if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
865 		char *arch, *entry, *fname;
866 		int arch_len, entry_len, fname_len;
867 		fname = (char*)zend_get_executed_filename();
868 
869 		/* we are checking for existence of a file within the relative path.  Chances are good that this is
870 		   retrieving something from within the phar archive */
871 
872 		if (strncasecmp(fname, "phar://", 7)) {
873 			goto skip_phar;
874 		}
875 		fname_len = strlen(fname);
876 		if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
877 			phar_archive_data *phar;
878 
879 			efree(entry);
880 			entry = filename;
881 			/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
882 			entry_len = filename_len;
883 			/* retrieving a file within the current directory, so use this if possible */
884 			if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
885 				phar_entry_info *etemp;
886 
887 				entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
888 				if (entry[0] == '/') {
889 					if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
890 						/* this file is not in the current directory, use the original path */
891 found_it:
892 						efree(entry);
893 						efree(arch);
894 						RETURN_BOOL(!etemp->is_dir);
895 					}
896 				} else {
897 					if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
898 						goto found_it;
899 					}
900 				}
901 			}
902 			if (entry != filename) {
903 				efree(entry);
904 			}
905 			efree(arch);
906 			RETURN_FALSE;
907 		}
908 	}
909 skip_phar:
910 	PHAR_G(orig_is_file)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
911 	return;
912 }
913 /* }}} */
914 
PHAR_FUNC(phar_is_link)915 PHAR_FUNC(phar_is_link) /* {{{ */
916 {
917 	char *filename;
918 	size_t filename_len;
919 
920 	if (!PHAR_G(intercepted)) {
921 		goto skip_phar;
922 	}
923 
924 	if ((PHAR_G(phar_fname_map.u.flags) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
925 		&& !cached_phars.u.flags) {
926 		goto skip_phar;
927 	}
928 	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) {
929 		goto skip_phar;
930 	}
931 	if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
932 		char *arch, *entry, *fname;
933 		int arch_len, entry_len, fname_len;
934 		fname = (char*)zend_get_executed_filename();
935 
936 		/* we are checking for existence of a file within the relative path.  Chances are good that this is
937 		   retrieving something from within the phar archive */
938 
939 		if (strncasecmp(fname, "phar://", 7)) {
940 			goto skip_phar;
941 		}
942 		fname_len = strlen(fname);
943 		if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
944 			phar_archive_data *phar;
945 
946 			efree(entry);
947 			entry = filename;
948 			/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
949 			entry_len = filename_len;
950 			/* retrieving a file within the current directory, so use this if possible */
951 			if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
952 				phar_entry_info *etemp;
953 
954 				entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
955 				if (entry[0] == '/') {
956 					if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
957 						/* this file is not in the current directory, use the original path */
958 found_it:
959 						efree(entry);
960 						efree(arch);
961 						RETURN_BOOL(etemp->link);
962 					}
963 				} else {
964 					if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
965 						goto found_it;
966 					}
967 				}
968 			}
969 			efree(entry);
970 			efree(arch);
971 			RETURN_FALSE;
972 		}
973 	}
974 skip_phar:
975 	PHAR_G(orig_is_link)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
976 	return;
977 }
978 /* }}} */
979 
980 /* {{{ proto array lstat(string filename)
981    Give information about a file or symbolic link */
PharFileFunction(phar_lstat,FS_LSTAT,orig_lstat)982 PharFileFunction(phar_lstat, FS_LSTAT, orig_lstat)
983 /* }}} */
984 
985 /* {{{ proto array stat(string filename)
986    Give information about a file */
987 PharFileFunction(phar_stat, FS_STAT, orig_stat)
988 /* }}} */
989 
990 /* {{{ void phar_intercept_functions(void) */
991 void phar_intercept_functions(void)
992 {
993 	if (!PHAR_G(request_init)) {
994 		PHAR_G(cwd) = NULL;
995 		PHAR_G(cwd_len) = 0;
996 	}
997 	PHAR_G(intercepted) = 1;
998 }
999 /* }}} */
1000 
1001 /* {{{ void phar_release_functions(void) */
phar_release_functions(void)1002 void phar_release_functions(void)
1003 {
1004 	PHAR_G(intercepted) = 0;
1005 }
1006 /* }}} */
1007 
1008 /* {{{ void phar_intercept_functions_init(void) */
1009 #define PHAR_INTERCEPT(func) \
1010 	PHAR_G(orig_##func) = NULL; \
1011 	if (NULL != (orig = zend_hash_str_find_ptr(CG(function_table), #func, sizeof(#func)-1))) { \
1012 		PHAR_G(orig_##func) = orig->internal_function.handler; \
1013 		orig->internal_function.handler = phar_##func; \
1014 	}
1015 
phar_intercept_functions_init(void)1016 void phar_intercept_functions_init(void)
1017 {
1018 	zend_function *orig;
1019 
1020 	PHAR_INTERCEPT(fopen);
1021 	PHAR_INTERCEPT(file_get_contents);
1022 	PHAR_INTERCEPT(is_file);
1023 	PHAR_INTERCEPT(is_link);
1024 	PHAR_INTERCEPT(is_dir);
1025 	PHAR_INTERCEPT(opendir);
1026 	PHAR_INTERCEPT(file_exists);
1027 	PHAR_INTERCEPT(fileperms);
1028 	PHAR_INTERCEPT(fileinode);
1029 	PHAR_INTERCEPT(filesize);
1030 	PHAR_INTERCEPT(fileowner);
1031 	PHAR_INTERCEPT(filegroup);
1032 	PHAR_INTERCEPT(fileatime);
1033 	PHAR_INTERCEPT(filemtime);
1034 	PHAR_INTERCEPT(filectime);
1035 	PHAR_INTERCEPT(filetype);
1036 	PHAR_INTERCEPT(is_writable);
1037 	PHAR_INTERCEPT(is_readable);
1038 	PHAR_INTERCEPT(is_executable);
1039 	PHAR_INTERCEPT(lstat);
1040 	PHAR_INTERCEPT(stat);
1041 	PHAR_INTERCEPT(readfile);
1042 	PHAR_G(intercepted) = 0;
1043 }
1044 /* }}} */
1045 
1046 /* {{{ void phar_intercept_functions_shutdown(void) */
1047 #define PHAR_RELEASE(func) \
1048 	if (PHAR_G(orig_##func) && NULL != (orig = zend_hash_str_find_ptr(CG(function_table), #func, sizeof(#func)-1))) { \
1049 		orig->internal_function.handler = PHAR_G(orig_##func); \
1050 	} \
1051 	PHAR_G(orig_##func) = NULL;
1052 
phar_intercept_functions_shutdown(void)1053 void phar_intercept_functions_shutdown(void)
1054 {
1055 	zend_function *orig;
1056 
1057 	PHAR_RELEASE(fopen);
1058 	PHAR_RELEASE(file_get_contents);
1059 	PHAR_RELEASE(is_file);
1060 	PHAR_RELEASE(is_dir);
1061 	PHAR_RELEASE(opendir);
1062 	PHAR_RELEASE(file_exists);
1063 	PHAR_RELEASE(fileperms);
1064 	PHAR_RELEASE(fileinode);
1065 	PHAR_RELEASE(filesize);
1066 	PHAR_RELEASE(fileowner);
1067 	PHAR_RELEASE(filegroup);
1068 	PHAR_RELEASE(fileatime);
1069 	PHAR_RELEASE(filemtime);
1070 	PHAR_RELEASE(filectime);
1071 	PHAR_RELEASE(filetype);
1072 	PHAR_RELEASE(is_writable);
1073 	PHAR_RELEASE(is_readable);
1074 	PHAR_RELEASE(is_executable);
1075 	PHAR_RELEASE(lstat);
1076 	PHAR_RELEASE(stat);
1077 	PHAR_RELEASE(readfile);
1078 	PHAR_G(intercepted) = 0;
1079 }
1080 /* }}} */
1081 
1082 static struct _phar_orig_functions {
1083 	zif_handler orig_fopen;
1084 	zif_handler orig_file_get_contents;
1085 	zif_handler orig_is_file;
1086 	zif_handler orig_is_link;
1087 	zif_handler orig_is_dir;
1088 	zif_handler orig_opendir;
1089 	zif_handler orig_file_exists;
1090 	zif_handler orig_fileperms;
1091 	zif_handler orig_fileinode;
1092 	zif_handler orig_filesize;
1093 	zif_handler orig_fileowner;
1094 	zif_handler orig_filegroup;
1095 	zif_handler orig_fileatime;
1096 	zif_handler orig_filemtime;
1097 	zif_handler orig_filectime;
1098 	zif_handler orig_filetype;
1099 	zif_handler orig_is_writable;
1100 	zif_handler orig_is_readable;
1101 	zif_handler orig_is_executable;
1102 	zif_handler orig_lstat;
1103 	zif_handler orig_readfile;
1104 	zif_handler orig_stat;
1105 } phar_orig_functions = {NULL};
1106 
phar_save_orig_functions(void)1107 void phar_save_orig_functions(void) /* {{{ */
1108 {
1109 	phar_orig_functions.orig_fopen             = PHAR_G(orig_fopen);
1110 	phar_orig_functions.orig_file_get_contents = PHAR_G(orig_file_get_contents);
1111 	phar_orig_functions.orig_is_file           = PHAR_G(orig_is_file);
1112 	phar_orig_functions.orig_is_link           = PHAR_G(orig_is_link);
1113 	phar_orig_functions.orig_is_dir            = PHAR_G(orig_is_dir);
1114 	phar_orig_functions.orig_opendir           = PHAR_G(orig_opendir);
1115 	phar_orig_functions.orig_file_exists       = PHAR_G(orig_file_exists);
1116 	phar_orig_functions.orig_fileperms         = PHAR_G(orig_fileperms);
1117 	phar_orig_functions.orig_fileinode         = PHAR_G(orig_fileinode);
1118 	phar_orig_functions.orig_filesize          = PHAR_G(orig_filesize);
1119 	phar_orig_functions.orig_fileowner         = PHAR_G(orig_fileowner);
1120 	phar_orig_functions.orig_filegroup         = PHAR_G(orig_filegroup);
1121 	phar_orig_functions.orig_fileatime         = PHAR_G(orig_fileatime);
1122 	phar_orig_functions.orig_filemtime         = PHAR_G(orig_filemtime);
1123 	phar_orig_functions.orig_filectime         = PHAR_G(orig_filectime);
1124 	phar_orig_functions.orig_filetype          = PHAR_G(orig_filetype);
1125 	phar_orig_functions.orig_is_writable       = PHAR_G(orig_is_writable);
1126 	phar_orig_functions.orig_is_readable       = PHAR_G(orig_is_readable);
1127 	phar_orig_functions.orig_is_executable     = PHAR_G(orig_is_executable);
1128 	phar_orig_functions.orig_lstat             = PHAR_G(orig_lstat);
1129 	phar_orig_functions.orig_readfile          = PHAR_G(orig_readfile);
1130 	phar_orig_functions.orig_stat              = PHAR_G(orig_stat);
1131 }
1132 /* }}} */
1133 
phar_restore_orig_functions(void)1134 void phar_restore_orig_functions(void) /* {{{ */
1135 {
1136 	PHAR_G(orig_fopen)             = phar_orig_functions.orig_fopen;
1137 	PHAR_G(orig_file_get_contents) = phar_orig_functions.orig_file_get_contents;
1138 	PHAR_G(orig_is_file)           = phar_orig_functions.orig_is_file;
1139 	PHAR_G(orig_is_link)           = phar_orig_functions.orig_is_link;
1140 	PHAR_G(orig_is_dir)            = phar_orig_functions.orig_is_dir;
1141 	PHAR_G(orig_opendir)           = phar_orig_functions.orig_opendir;
1142 	PHAR_G(orig_file_exists)       = phar_orig_functions.orig_file_exists;
1143 	PHAR_G(orig_fileperms)         = phar_orig_functions.orig_fileperms;
1144 	PHAR_G(orig_fileinode)         = phar_orig_functions.orig_fileinode;
1145 	PHAR_G(orig_filesize)          = phar_orig_functions.orig_filesize;
1146 	PHAR_G(orig_fileowner)         = phar_orig_functions.orig_fileowner;
1147 	PHAR_G(orig_filegroup)         = phar_orig_functions.orig_filegroup;
1148 	PHAR_G(orig_fileatime)         = phar_orig_functions.orig_fileatime;
1149 	PHAR_G(orig_filemtime)         = phar_orig_functions.orig_filemtime;
1150 	PHAR_G(orig_filectime)         = phar_orig_functions.orig_filectime;
1151 	PHAR_G(orig_filetype)          = phar_orig_functions.orig_filetype;
1152 	PHAR_G(orig_is_writable)       = phar_orig_functions.orig_is_writable;
1153 	PHAR_G(orig_is_readable)       = phar_orig_functions.orig_is_readable;
1154 	PHAR_G(orig_is_executable)     = phar_orig_functions.orig_is_executable;
1155 	PHAR_G(orig_lstat)             = phar_orig_functions.orig_lstat;
1156 	PHAR_G(orig_readfile)          = phar_orig_functions.orig_readfile;
1157 	PHAR_G(orig_stat)              = phar_orig_functions.orig_stat;
1158 }
1159 /* }}} */
1160 
1161 /*
1162  * Local variables:
1163  * tab-width: 4
1164  * c-basic-offset: 4
1165  * End:
1166  * vim600: noet sw=4 ts=4 fdm=marker
1167  * vim<600: noet sw=4 ts=4
1168  */
1169