1 /*
2    +----------------------------------------------------------------------+
3    | Zend OPcache                                                         |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 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    | https://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    |          Zeev Suraski <zeev@php.net>                                 |
17    |          Stanislav Malyshev <stas@zend.com>                          |
18    |          Dmitry Stogov <dmitry@php.net>                              |
19    +----------------------------------------------------------------------+
20 */
21 
22 #include <time.h>
23 
24 #include "php.h"
25 #include "ZendAccelerator.h"
26 #include "zend_API.h"
27 #include "zend_shared_alloc.h"
28 #include "zend_accelerator_blacklist.h"
29 #include "php_ini.h"
30 #include "SAPI.h"
31 #include "zend_virtual_cwd.h"
32 #include "ext/standard/info.h"
33 #include "ext/standard/php_filestat.h"
34 #include "opcache_arginfo.h"
35 
36 #if HAVE_JIT
37 #include "jit/zend_jit.h"
38 #endif
39 
40 #define STRING_NOT_NULL(s) (NULL == (s)?"":s)
41 #define MIN_ACCEL_FILES 200
42 #define MAX_ACCEL_FILES 1000000
43 #define TOKENTOSTR(X) #X
44 
45 static zif_handler orig_file_exists = NULL;
46 static zif_handler orig_is_file = NULL;
47 static zif_handler orig_is_readable = NULL;
48 
validate_api_restriction(void)49 static int validate_api_restriction(void)
50 {
51 	if (ZCG(accel_directives).restrict_api && *ZCG(accel_directives).restrict_api) {
52 		size_t len = strlen(ZCG(accel_directives).restrict_api);
53 
54 		if (!SG(request_info).path_translated ||
55 		    strlen(SG(request_info).path_translated) < len ||
56 		    memcmp(SG(request_info).path_translated, ZCG(accel_directives).restrict_api, len) != 0) {
57 			zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " API is restricted by \"restrict_api\" configuration directive");
58 			return 0;
59 		}
60 	}
61 	return 1;
62 }
63 
ZEND_INI_MH(OnUpdateMemoryConsumption)64 static ZEND_INI_MH(OnUpdateMemoryConsumption)
65 {
66 	zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
67 	zend_long memsize = atoi(ZSTR_VAL(new_value));
68 	/* sanity check we must use at least 8 MB */
69 	if (memsize < 8) {
70 		zend_accel_error(ACCEL_LOG_WARNING, "opcache.memory_consumption is set below the required 8MB.\n");
71 		return FAILURE;
72 	}
73 	if (UNEXPECTED(memsize > ZEND_LONG_MAX / (1024 * 1024))) {
74 		*p = ZEND_LONG_MAX & ~(1024 * 1024 - 1);
75 	} else {
76 		*p = memsize * (1024 * 1024);
77 	}
78 	return SUCCESS;
79 }
80 
ZEND_INI_MH(OnUpdateMaxAcceleratedFiles)81 static ZEND_INI_MH(OnUpdateMaxAcceleratedFiles)
82 {
83 	zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
84 	zend_long size = atoi(ZSTR_VAL(new_value));
85 	/* sanity check we must use a value between MIN_ACCEL_FILES and MAX_ACCEL_FILES */
86 	if (size < MIN_ACCEL_FILES) {
87 		zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_accelerated_files is set below the required minimum (%d).\n", MIN_ACCEL_FILES);
88 		return FAILURE;
89 	}
90 	if (size > MAX_ACCEL_FILES) {
91 		zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_accelerated_files is set above the limit (%d).\n", MAX_ACCEL_FILES);
92 		return FAILURE;
93 	}
94 	*p = size;
95 	return SUCCESS;
96 }
97 
ZEND_INI_MH(OnUpdateMaxWastedPercentage)98 static ZEND_INI_MH(OnUpdateMaxWastedPercentage)
99 {
100 	double *p = (double *) ZEND_INI_GET_ADDR();
101 	zend_long percentage = atoi(ZSTR_VAL(new_value));
102 
103 	if (percentage <= 0 || percentage > 50) {
104 		zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_wasted_percentage must be set between 1 and 50.\n");
105 		return FAILURE;
106 	}
107 	*p = (double)percentage / 100.0;
108 	return SUCCESS;
109 }
110 
ZEND_INI_MH(OnUpdateConsistencyChecks)111 static ZEND_INI_MH(OnUpdateConsistencyChecks)
112 {
113 	zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
114 	zend_long consistency_checks = atoi(ZSTR_VAL(new_value));
115 
116 	if (consistency_checks != 0) {
117 		zend_accel_error(ACCEL_LOG_WARNING, "opcache.consistency_checks is reset back to 0 because it does not work properly (see GH-8065, GH-10624).\n");
118 		return FAILURE;
119 	}
120 	*p = 0;
121 	return SUCCESS;
122 }
123 
ZEND_INI_MH(OnEnable)124 static ZEND_INI_MH(OnEnable)
125 {
126 	if (stage == ZEND_INI_STAGE_STARTUP ||
127 	    stage == ZEND_INI_STAGE_SHUTDOWN ||
128 	    stage == ZEND_INI_STAGE_DEACTIVATE) {
129 		return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
130 	} else {
131 		/* It may be only temporary disabled */
132 		bool *p = (bool *) ZEND_INI_GET_ADDR();
133 		if (zend_ini_parse_bool(new_value)) {
134 			zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " can't be temporary enabled (it may be only disabled till the end of request)");
135 			return FAILURE;
136 		} else {
137 			*p = 0;
138 			ZCG(accelerator_enabled) = 0;
139 			return SUCCESS;
140 		}
141 	}
142 }
143 
ZEND_INI_MH(OnUpdateFileCache)144 static ZEND_INI_MH(OnUpdateFileCache)
145 {
146 	if (new_value) {
147 		if (!ZSTR_LEN(new_value)) {
148 			new_value = NULL;
149 		} else {
150 			zend_stat_t buf;
151 
152 		    if (!IS_ABSOLUTE_PATH(ZSTR_VAL(new_value), ZSTR_LEN(new_value)) ||
153 			    zend_stat(ZSTR_VAL(new_value), &buf) != 0 ||
154 			    !S_ISDIR(buf.st_mode) ||
155 #ifndef ZEND_WIN32
156 				access(ZSTR_VAL(new_value), R_OK | W_OK | X_OK) != 0) {
157 #else
158 				_access(ZSTR_VAL(new_value), 06) != 0) {
159 #endif
160 				zend_accel_error(ACCEL_LOG_WARNING, "opcache.file_cache must be a full path of accessible directory.\n");
161 				new_value = NULL;
162 			}
163 		}
164 	}
165 	OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
166 	return SUCCESS;
167 }
168 
169 #ifdef HAVE_JIT
170 static ZEND_INI_MH(OnUpdateJit)
171 {
172 	if (zend_jit_config(new_value, stage) == SUCCESS) {
173 		return OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
174 	}
175 	return FAILURE;
176 }
177 
178 static ZEND_INI_MH(OnUpdateJitDebug)
179 {
180 	zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
181 	zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
182 
183 	if (zend_jit_debug_config(*p, val, stage) == SUCCESS) {
184 		*p = val;
185 		return SUCCESS;
186 	}
187 	return FAILURE;
188 }
189 
190 static ZEND_INI_MH(OnUpdateCounter)
191 {
192 	zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
193 	if (val >= 0 && val < 256) {
194 		zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
195 		*p = val;
196 		return SUCCESS;
197 	}
198 	zend_error(E_WARNING, "Invalid \"%s\" setting. Should be between 0 and 256", ZSTR_VAL(entry->name));
199 	return FAILURE;
200 }
201 
202 static ZEND_INI_MH(OnUpdateUnrollC)
203 {
204 	zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
205 	if (val > 0 && val < ZEND_JIT_TRACE_MAX_CALL_DEPTH) {
206 		zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
207 		*p = val;
208 		return SUCCESS;
209 	}
210 	zend_error(E_WARNING, "Invalid \"%s\" setting. Should be between 1 and %d", ZSTR_VAL(entry->name),
211 		ZEND_JIT_TRACE_MAX_CALL_DEPTH);
212 	return FAILURE;
213 }
214 
215 static ZEND_INI_MH(OnUpdateUnrollR)
216 {
217 	zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
218 	if (val >= 0 && val < ZEND_JIT_TRACE_MAX_RET_DEPTH) {
219 		zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
220 		*p = val;
221 		return SUCCESS;
222 	}
223 	zend_error(E_WARNING, "Invalid \"%s\" setting. Should be between 0 and %d", ZSTR_VAL(entry->name),
224 		ZEND_JIT_TRACE_MAX_RET_DEPTH);
225 	return FAILURE;
226 }
227 
228 static ZEND_INI_MH(OnUpdateUnrollL)
229 {
230 	zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
231 	if (val > 0 && val < ZEND_JIT_TRACE_MAX_LOOPS_UNROLL) {
232 		zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
233 		*p = val;
234 		return SUCCESS;
235 	}
236 	zend_error(E_WARNING, "Invalid \"%s\" setting. Should be between 1 and %d", ZSTR_VAL(entry->name),
237 		ZEND_JIT_TRACE_MAX_LOOPS_UNROLL);
238 	return FAILURE;
239 }
240 #endif
241 
242 ZEND_INI_BEGIN()
243 	STD_PHP_INI_BOOLEAN("opcache.enable"             , "1", PHP_INI_ALL,    OnEnable,     enabled                             , zend_accel_globals, accel_globals)
244 	STD_PHP_INI_BOOLEAN("opcache.use_cwd"            , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.use_cwd            , zend_accel_globals, accel_globals)
245 	STD_PHP_INI_BOOLEAN("opcache.validate_timestamps", "1", PHP_INI_ALL   , OnUpdateBool, accel_directives.validate_timestamps, zend_accel_globals, accel_globals)
246 	STD_PHP_INI_BOOLEAN("opcache.validate_permission", "0", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.validate_permission, zend_accel_globals, accel_globals)
247 #ifndef ZEND_WIN32
248 	STD_PHP_INI_BOOLEAN("opcache.validate_root"      , "0", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.validate_root      , zend_accel_globals, accel_globals)
249 #endif
250 	STD_PHP_INI_BOOLEAN("opcache.dups_fix"           , "0", PHP_INI_ALL   , OnUpdateBool, accel_directives.ignore_dups        , zend_accel_globals, accel_globals)
251 	STD_PHP_INI_BOOLEAN("opcache.revalidate_path"    , "0", PHP_INI_ALL   , OnUpdateBool, accel_directives.revalidate_path    , zend_accel_globals, accel_globals)
252 
253 	STD_PHP_INI_ENTRY("opcache.log_verbosity_level"   , "1"   , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.log_verbosity_level,       zend_accel_globals, accel_globals)
254 	STD_PHP_INI_ENTRY("opcache.memory_consumption"    , "128"  , PHP_INI_SYSTEM, OnUpdateMemoryConsumption,    accel_directives.memory_consumption,        zend_accel_globals, accel_globals)
255 	STD_PHP_INI_ENTRY("opcache.interned_strings_buffer", "8"  , PHP_INI_SYSTEM, OnUpdateLong,                 accel_directives.interned_strings_buffer,   zend_accel_globals, accel_globals)
256 	STD_PHP_INI_ENTRY("opcache.max_accelerated_files" , "10000", PHP_INI_SYSTEM, OnUpdateMaxAcceleratedFiles,	 accel_directives.max_accelerated_files,     zend_accel_globals, accel_globals)
257 	STD_PHP_INI_ENTRY("opcache.max_wasted_percentage" , "5"   , PHP_INI_SYSTEM, OnUpdateMaxWastedPercentage,	 accel_directives.max_wasted_percentage,     zend_accel_globals, accel_globals)
258 	STD_PHP_INI_ENTRY("opcache.consistency_checks"    , "0"   , PHP_INI_ALL   , OnUpdateConsistencyChecks,	     accel_directives.consistency_checks,        zend_accel_globals, accel_globals)
259 	STD_PHP_INI_ENTRY("opcache.force_restart_timeout" , "180" , PHP_INI_SYSTEM, OnUpdateLong,	             accel_directives.force_restart_timeout,     zend_accel_globals, accel_globals)
260 	STD_PHP_INI_ENTRY("opcache.revalidate_freq"       , "2"   , PHP_INI_ALL   , OnUpdateLong,	             accel_directives.revalidate_freq,           zend_accel_globals, accel_globals)
261 	STD_PHP_INI_ENTRY("opcache.file_update_protection", "2"   , PHP_INI_ALL   , OnUpdateLong,                accel_directives.file_update_protection,    zend_accel_globals, accel_globals)
262 	STD_PHP_INI_ENTRY("opcache.preferred_memory_model", ""    , PHP_INI_SYSTEM, OnUpdateStringUnempty,       accel_directives.memory_model,              zend_accel_globals, accel_globals)
263 	STD_PHP_INI_ENTRY("opcache.blacklist_filename"    , ""    , PHP_INI_SYSTEM, OnUpdateString,	             accel_directives.user_blacklist_filename,   zend_accel_globals, accel_globals)
264 	STD_PHP_INI_ENTRY("opcache.max_file_size"         , "0"   , PHP_INI_SYSTEM, OnUpdateLong,	             accel_directives.max_file_size,             zend_accel_globals, accel_globals)
265 
266 	STD_PHP_INI_BOOLEAN("opcache.protect_memory"        , "0"  , PHP_INI_SYSTEM, OnUpdateBool,                  accel_directives.protect_memory,            zend_accel_globals, accel_globals)
267 	STD_PHP_INI_BOOLEAN("opcache.save_comments"         , "1"  , PHP_INI_SYSTEM, OnUpdateBool,                  accel_directives.save_comments,             zend_accel_globals, accel_globals)
268 	STD_PHP_INI_BOOLEAN("opcache.record_warnings"       , "0"  , PHP_INI_SYSTEM, OnUpdateBool,                  accel_directives.record_warnings,           zend_accel_globals, accel_globals)
269 
270 	STD_PHP_INI_ENTRY("opcache.optimization_level"    , DEFAULT_OPTIMIZATION_LEVEL , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.optimization_level,   zend_accel_globals, accel_globals)
271 	STD_PHP_INI_ENTRY("opcache.opt_debug_level"       , "0"      , PHP_INI_SYSTEM, OnUpdateLong,             accel_directives.opt_debug_level,            zend_accel_globals, accel_globals)
272 	STD_PHP_INI_BOOLEAN("opcache.enable_file_override"	, "0"   , PHP_INI_SYSTEM, OnUpdateBool,              accel_directives.file_override_enabled,     zend_accel_globals, accel_globals)
273 	STD_PHP_INI_BOOLEAN("opcache.enable_cli"             , "0"   , PHP_INI_SYSTEM, OnUpdateBool,              accel_directives.enable_cli,                zend_accel_globals, accel_globals)
274 	STD_PHP_INI_ENTRY("opcache.error_log"                , ""    , PHP_INI_SYSTEM, OnUpdateString,	         accel_directives.error_log,                 zend_accel_globals, accel_globals)
275 	STD_PHP_INI_ENTRY("opcache.restrict_api"             , ""    , PHP_INI_SYSTEM, OnUpdateString,	         accel_directives.restrict_api,              zend_accel_globals, accel_globals)
276 
277 #ifndef ZEND_WIN32
278 	STD_PHP_INI_ENTRY("opcache.lockfile_path"             , "/tmp"    , PHP_INI_SYSTEM, OnUpdateString,           accel_directives.lockfile_path,              zend_accel_globals, accel_globals)
279 #else
280 	STD_PHP_INI_ENTRY("opcache.mmap_base", NULL, PHP_INI_SYSTEM,	OnUpdateString,	                             accel_directives.mmap_base,                 zend_accel_globals, accel_globals)
281 #endif
282 
283 	STD_PHP_INI_ENTRY("opcache.file_cache"                    , NULL  , PHP_INI_SYSTEM, OnUpdateFileCache, accel_directives.file_cache,                    zend_accel_globals, accel_globals)
284 	STD_PHP_INI_BOOLEAN("opcache.file_cache_only"               , "0"   , PHP_INI_SYSTEM, OnUpdateBool,	   accel_directives.file_cache_only,               zend_accel_globals, accel_globals)
285 	STD_PHP_INI_BOOLEAN("opcache.file_cache_consistency_checks" , "1"   , PHP_INI_SYSTEM, OnUpdateBool,	   accel_directives.file_cache_consistency_checks, zend_accel_globals, accel_globals)
286 #if ENABLE_FILE_CACHE_FALLBACK
287 	STD_PHP_INI_BOOLEAN("opcache.file_cache_fallback"           , "1"   , PHP_INI_SYSTEM, OnUpdateBool,	   accel_directives.file_cache_fallback,           zend_accel_globals, accel_globals)
288 #endif
289 #ifdef HAVE_HUGE_CODE_PAGES
290 	STD_PHP_INI_BOOLEAN("opcache.huge_code_pages"             , "0"   , PHP_INI_SYSTEM, OnUpdateBool,      accel_directives.huge_code_pages,               zend_accel_globals, accel_globals)
291 #endif
292 	STD_PHP_INI_ENTRY("opcache.preload"                       , ""    , PHP_INI_SYSTEM, OnUpdateStringUnempty,    accel_directives.preload,                zend_accel_globals, accel_globals)
293 #ifndef ZEND_WIN32
294 	STD_PHP_INI_ENTRY("opcache.preload_user"                  , ""    , PHP_INI_SYSTEM, OnUpdateStringUnempty,    accel_directives.preload_user,           zend_accel_globals, accel_globals)
295 #endif
296 #if ZEND_WIN32
297 	STD_PHP_INI_ENTRY("opcache.cache_id"                      , ""    , PHP_INI_SYSTEM, OnUpdateString,           accel_directives.cache_id,               zend_accel_globals, accel_globals)
298 #endif
299 #ifdef HAVE_JIT
300 	STD_PHP_INI_ENTRY("opcache.jit"                           , "tracing",                    PHP_INI_ALL,    OnUpdateJit,      options,               zend_jit_globals, jit_globals)
301 	STD_PHP_INI_ENTRY("opcache.jit_buffer_size"               , ZEND_JIT_DEFAULT_BUFFER_SIZE, PHP_INI_SYSTEM, OnUpdateLong,     buffer_size,           zend_jit_globals, jit_globals)
302 	STD_PHP_INI_ENTRY("opcache.jit_debug"                     , "0",                          PHP_INI_ALL,    OnUpdateJitDebug, debug,                 zend_jit_globals, jit_globals)
303 	STD_PHP_INI_ENTRY("opcache.jit_bisect_limit"              , "0",                          PHP_INI_ALL,    OnUpdateLong,     bisect_limit,          zend_jit_globals, jit_globals)
304 	STD_PHP_INI_ENTRY("opcache.jit_prof_threshold"            , "0.005",                      PHP_INI_ALL,    OnUpdateReal,     prof_threshold,        zend_jit_globals, jit_globals)
305 	STD_PHP_INI_ENTRY("opcache.jit_max_root_traces"           , "1024",                       PHP_INI_SYSTEM, OnUpdateLong,     max_root_traces,       zend_jit_globals, jit_globals)
306 	STD_PHP_INI_ENTRY("opcache.jit_max_side_traces"           , "128",                        PHP_INI_SYSTEM, OnUpdateLong,     max_side_traces,       zend_jit_globals, jit_globals)
307 	STD_PHP_INI_ENTRY("opcache.jit_max_exit_counters"         , "8192",                       PHP_INI_SYSTEM, OnUpdateLong,     max_exit_counters,     zend_jit_globals, jit_globals)
308 	STD_PHP_INI_ENTRY("opcache.jit_hot_loop"                  , "64",                         PHP_INI_SYSTEM, OnUpdateCounter,  hot_loop,              zend_jit_globals, jit_globals)
309 	STD_PHP_INI_ENTRY("opcache.jit_hot_func"                  , "127",                        PHP_INI_SYSTEM, OnUpdateCounter,  hot_func,              zend_jit_globals, jit_globals)
310 	STD_PHP_INI_ENTRY("opcache.jit_hot_return"                , "8",                          PHP_INI_SYSTEM, OnUpdateCounter,  hot_return,            zend_jit_globals, jit_globals)
311 	STD_PHP_INI_ENTRY("opcache.jit_hot_side_exit"             , "8",                          PHP_INI_ALL,    OnUpdateCounter,  hot_side_exit,         zend_jit_globals, jit_globals)
312 	STD_PHP_INI_ENTRY("opcache.jit_blacklist_root_trace"      , "16",                         PHP_INI_ALL,    OnUpdateCounter,  blacklist_root_trace,  zend_jit_globals, jit_globals)
313 	STD_PHP_INI_ENTRY("opcache.jit_blacklist_side_trace"      , "8",                          PHP_INI_ALL,    OnUpdateCounter,  blacklist_side_trace,  zend_jit_globals, jit_globals)
314 	STD_PHP_INI_ENTRY("opcache.jit_max_loop_unrolls"          , "8",                          PHP_INI_ALL,    OnUpdateUnrollL,  max_loop_unrolls,      zend_jit_globals, jit_globals)
315 	STD_PHP_INI_ENTRY("opcache.jit_max_recursive_calls"       , "2",                          PHP_INI_ALL,    OnUpdateUnrollC,  max_recursive_calls,   zend_jit_globals, jit_globals)
316 	STD_PHP_INI_ENTRY("opcache.jit_max_recursive_returns"     , "2",                          PHP_INI_ALL,    OnUpdateUnrollR,  max_recursive_returns, zend_jit_globals, jit_globals)
317 	STD_PHP_INI_ENTRY("opcache.jit_max_polymorphic_calls"     , "2",                          PHP_INI_ALL,    OnUpdateLong,     max_polymorphic_calls, zend_jit_globals, jit_globals)
318 #endif
319 ZEND_INI_END()
320 
321 static int filename_is_in_cache(zend_string *filename)
322 {
323 	zend_string *key;
324 
325 	key = accel_make_persistent_key(filename);
326 	if (key != NULL) {
327 		zend_persistent_script *persistent_script = zend_accel_hash_find(&ZCSG(hash), key);
328 		if (persistent_script && !persistent_script->corrupted) {
329 			if (ZCG(accel_directives).validate_timestamps) {
330 				zend_file_handle handle;
331 				int ret;
332 
333 				zend_stream_init_filename_ex(&handle, filename);
334 				ret = validate_timestamp_and_record_ex(persistent_script, &handle) == SUCCESS
335 					? 1 : 0;
336 				zend_destroy_file_handle(&handle);
337 				return ret;
338 			}
339 
340 			return 1;
341 		}
342 	}
343 
344 	return 0;
345 }
346 
347 static int accel_file_in_cache(INTERNAL_FUNCTION_PARAMETERS)
348 {
349 	if (ZEND_NUM_ARGS() == 1) {
350 		zval *zv = ZEND_CALL_ARG(execute_data , 1);
351 
352 		if (Z_TYPE_P(zv) == IS_STRING && Z_STRLEN_P(zv) != 0) {
353 			return filename_is_in_cache(Z_STR_P(zv));
354 		}
355 	}
356 	return 0;
357 }
358 
359 static ZEND_NAMED_FUNCTION(accel_file_exists)
360 {
361 	if (accel_file_in_cache(INTERNAL_FUNCTION_PARAM_PASSTHRU)) {
362 		RETURN_TRUE;
363 	} else {
364 		orig_file_exists(INTERNAL_FUNCTION_PARAM_PASSTHRU);
365 	}
366 }
367 
368 static ZEND_NAMED_FUNCTION(accel_is_file)
369 {
370 	if (accel_file_in_cache(INTERNAL_FUNCTION_PARAM_PASSTHRU)) {
371 		RETURN_TRUE;
372 	} else {
373 		orig_is_file(INTERNAL_FUNCTION_PARAM_PASSTHRU);
374 	}
375 }
376 
377 static ZEND_NAMED_FUNCTION(accel_is_readable)
378 {
379 	if (accel_file_in_cache(INTERNAL_FUNCTION_PARAM_PASSTHRU)) {
380 		RETURN_TRUE;
381 	} else {
382 		orig_is_readable(INTERNAL_FUNCTION_PARAM_PASSTHRU);
383 	}
384 }
385 
386 static ZEND_MINIT_FUNCTION(zend_accelerator)
387 {
388 	(void)type; /* keep the compiler happy */
389 
390 	REGISTER_INI_ENTRIES();
391 
392 	return SUCCESS;
393 }
394 
395 void zend_accel_override_file_functions(void)
396 {
397 	zend_function *old_function;
398 	if (ZCG(enabled) && accel_startup_ok && ZCG(accel_directives).file_override_enabled) {
399 		if (file_cache_only) {
400 			zend_accel_error(ACCEL_LOG_WARNING, "file_override_enabled has no effect when file_cache_only is set");
401 			return;
402 		}
403 		/* override file_exists */
404 		if ((old_function = zend_hash_str_find_ptr(CG(function_table), "file_exists", sizeof("file_exists")-1)) != NULL) {
405 			orig_file_exists = old_function->internal_function.handler;
406 			old_function->internal_function.handler = accel_file_exists;
407 		}
408 		if ((old_function = zend_hash_str_find_ptr(CG(function_table), "is_file", sizeof("is_file")-1)) != NULL) {
409 			orig_is_file = old_function->internal_function.handler;
410 			old_function->internal_function.handler = accel_is_file;
411 		}
412 		if ((old_function = zend_hash_str_find_ptr(CG(function_table), "is_readable", sizeof("is_readable")-1)) != NULL) {
413 			orig_is_readable = old_function->internal_function.handler;
414 			old_function->internal_function.handler = accel_is_readable;
415 		}
416 	}
417 }
418 
419 static ZEND_MSHUTDOWN_FUNCTION(zend_accelerator)
420 {
421 	(void)type; /* keep the compiler happy */
422 
423 	UNREGISTER_INI_ENTRIES();
424 	accel_shutdown();
425 	return SUCCESS;
426 }
427 
428 void zend_accel_info(ZEND_MODULE_INFO_FUNC_ARGS)
429 {
430 	php_info_print_table_start();
431 
432 	if (ZCG(accelerator_enabled) || file_cache_only) {
433 		php_info_print_table_row(2, "Opcode Caching", "Up and Running");
434 	} else {
435 		php_info_print_table_row(2, "Opcode Caching", "Disabled");
436 	}
437 	if (ZCG(enabled) && accel_startup_ok && ZCG(accel_directives).optimization_level) {
438 		php_info_print_table_row(2, "Optimization", "Enabled");
439 	} else {
440 		php_info_print_table_row(2, "Optimization", "Disabled");
441 	}
442 	if (!file_cache_only) {
443 		php_info_print_table_row(2, "SHM Cache", "Enabled");
444 	} else {
445 		php_info_print_table_row(2, "SHM Cache", "Disabled");
446 	}
447 	if (ZCG(accel_directives).file_cache) {
448 		php_info_print_table_row(2, "File Cache", "Enabled");
449 	} else {
450 		php_info_print_table_row(2, "File Cache", "Disabled");
451 	}
452 #if HAVE_JIT
453 	if (JIT_G(enabled)) {
454 		if (JIT_G(on)) {
455 			php_info_print_table_row(2, "JIT", "On");
456 		} else {
457 			php_info_print_table_row(2, "JIT", "Off");
458 		}
459 	} else {
460 		php_info_print_table_row(2, "JIT", "Disabled");
461 	}
462 #else
463 	php_info_print_table_row(2, "JIT", "Not Available");
464 #endif
465 	if (file_cache_only) {
466 		if (!accel_startup_ok || zps_api_failure_reason) {
467 			php_info_print_table_row(2, "Startup Failed", zps_api_failure_reason);
468 		} else {
469 			php_info_print_table_row(2, "Startup", "OK");
470 		}
471 	} else
472 	if (ZCG(enabled)) {
473 		if (!accel_startup_ok || zps_api_failure_reason) {
474 			php_info_print_table_row(2, "Startup Failed", zps_api_failure_reason);
475 		} else {
476 			char buf[32];
477 			php_info_print_table_row(2, "Startup", "OK");
478 			php_info_print_table_row(2, "Shared memory model", zend_accel_get_shared_model());
479 			snprintf(buf, sizeof(buf), ZEND_ULONG_FMT, ZCSG(hits));
480 			php_info_print_table_row(2, "Cache hits", buf);
481 			snprintf(buf, sizeof(buf), ZEND_ULONG_FMT, ZSMMG(memory_exhausted)?ZCSG(misses):ZCSG(misses)-ZCSG(blacklist_misses));
482 			php_info_print_table_row(2, "Cache misses", buf);
483 			snprintf(buf, sizeof(buf), ZEND_LONG_FMT, ZCG(accel_directives).memory_consumption-zend_shared_alloc_get_free_memory()-ZSMMG(wasted_shared_memory));
484 			php_info_print_table_row(2, "Used memory", buf);
485 			snprintf(buf, sizeof(buf), "%zu", zend_shared_alloc_get_free_memory());
486 			php_info_print_table_row(2, "Free memory", buf);
487 			snprintf(buf, sizeof(buf), "%zu", ZSMMG(wasted_shared_memory));
488 			php_info_print_table_row(2, "Wasted memory", buf);
489 			if (ZCSG(interned_strings).start && ZCSG(interned_strings).end) {
490 				snprintf(buf, sizeof(buf), "%zu", (size_t)((char*)ZCSG(interned_strings).top - (char*)(accel_shared_globals + 1)));
491 				php_info_print_table_row(2, "Interned Strings Used memory", buf);
492 				snprintf(buf, sizeof(buf), "%zu", (size_t)((char*)ZCSG(interned_strings).end - (char*)ZCSG(interned_strings).top));
493 				php_info_print_table_row(2, "Interned Strings Free memory", buf);
494 			}
495 			snprintf(buf, sizeof(buf), "%" PRIu32, ZCSG(hash).num_direct_entries);
496 			php_info_print_table_row(2, "Cached scripts", buf);
497 			snprintf(buf, sizeof(buf), "%" PRIu32, ZCSG(hash).num_entries);
498 			php_info_print_table_row(2, "Cached keys", buf);
499 			snprintf(buf, sizeof(buf), "%" PRIu32, ZCSG(hash).max_num_entries);
500 			php_info_print_table_row(2, "Max keys", buf);
501 			snprintf(buf, sizeof(buf), ZEND_ULONG_FMT, ZCSG(oom_restarts));
502 			php_info_print_table_row(2, "OOM restarts", buf);
503 			snprintf(buf, sizeof(buf), ZEND_ULONG_FMT, ZCSG(hash_restarts));
504 			php_info_print_table_row(2, "Hash keys restarts", buf);
505 			snprintf(buf, sizeof(buf), ZEND_ULONG_FMT, ZCSG(manual_restarts));
506 			php_info_print_table_row(2, "Manual restarts", buf);
507 		}
508 	}
509 
510 	php_info_print_table_end();
511 	DISPLAY_INI_ENTRIES();
512 }
513 
514 static zend_module_entry accel_module_entry = {
515 	STANDARD_MODULE_HEADER,
516 	ACCELERATOR_PRODUCT_NAME,
517 	ext_functions,
518 	ZEND_MINIT(zend_accelerator),
519 	ZEND_MSHUTDOWN(zend_accelerator),
520 	accel_activate,
521 	NULL,
522 	zend_accel_info,
523 	PHP_VERSION,
524 	NO_MODULE_GLOBALS,
525 	accel_post_deactivate,
526 	STANDARD_MODULE_PROPERTIES_EX
527 };
528 
529 int start_accel_module(void)
530 {
531 	return zend_startup_module(&accel_module_entry);
532 }
533 
534 /* {{{ Get the scripts which are accelerated by ZendAccelerator */
535 static int accelerator_get_scripts(zval *return_value)
536 {
537 	uint32_t i;
538 	zval persistent_script_report;
539 	zend_accel_hash_entry *cache_entry;
540 	struct tm *ta;
541 	struct timeval exec_time;
542 	struct timeval fetch_time;
543 
544 	if (!ZCG(accelerator_enabled) || accelerator_shm_read_lock() != SUCCESS) {
545 		return 0;
546 	}
547 
548 	array_init(return_value);
549 	for (i = 0; i<ZCSG(hash).max_num_entries; i++) {
550 		for (cache_entry = ZCSG(hash).hash_table[i]; cache_entry; cache_entry = cache_entry->next) {
551 			zend_persistent_script *script;
552 			char *str;
553 			size_t len;
554 
555 			if (cache_entry->indirect) continue;
556 
557 			script = (zend_persistent_script *)cache_entry->data;
558 
559 			array_init(&persistent_script_report);
560 			add_assoc_str(&persistent_script_report, "full_path", zend_string_dup(script->script.filename, 0));
561 			add_assoc_long(&persistent_script_report, "hits", (zend_long)script->dynamic_members.hits);
562 			add_assoc_long(&persistent_script_report, "memory_consumption", script->dynamic_members.memory_consumption);
563 			ta = localtime(&script->dynamic_members.last_used);
564 			str = asctime(ta);
565 			len = strlen(str);
566 			if (len > 0 && str[len - 1] == '\n') len--;
567 			add_assoc_stringl(&persistent_script_report, "last_used", str, len);
568 			add_assoc_long(&persistent_script_report, "last_used_timestamp", script->dynamic_members.last_used);
569 			if (ZCG(accel_directives).validate_timestamps) {
570 				add_assoc_long(&persistent_script_report, "timestamp", (zend_long)script->timestamp);
571 			}
572 			timerclear(&exec_time);
573 			timerclear(&fetch_time);
574 
575 			zend_hash_update(Z_ARRVAL_P(return_value), cache_entry->key, &persistent_script_report);
576 		}
577 	}
578 	accelerator_shm_read_unlock();
579 
580 	return 1;
581 }
582 
583 /* {{{ Obtain statistics information regarding code acceleration */
584 ZEND_FUNCTION(opcache_get_status)
585 {
586 	zend_long reqs;
587 	zval memory_usage, statistics, scripts;
588 	bool fetch_scripts = 1;
589 
590 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &fetch_scripts) == FAILURE) {
591 		RETURN_THROWS();
592 	}
593 
594 	if (!validate_api_restriction()) {
595 		RETURN_FALSE;
596 	}
597 
598 	if (!accel_startup_ok) {
599 		RETURN_FALSE;
600 	}
601 
602 	array_init(return_value);
603 
604 	/* Trivia */
605 	add_assoc_bool(return_value, "opcache_enabled", ZCG(accelerator_enabled));
606 
607 	if (ZCG(accel_directives).file_cache) {
608 		add_assoc_string(return_value, "file_cache", ZCG(accel_directives).file_cache);
609 	}
610 	if (file_cache_only) {
611 		add_assoc_bool(return_value, "file_cache_only", 1);
612 		return;
613 	}
614 
615 	add_assoc_bool(return_value, "cache_full", ZSMMG(memory_exhausted));
616 	add_assoc_bool(return_value, "restart_pending", ZCSG(restart_pending));
617 	add_assoc_bool(return_value, "restart_in_progress", ZCSG(restart_in_progress));
618 
619 	/* Memory usage statistics */
620 	array_init(&memory_usage);
621 	add_assoc_long(&memory_usage, "used_memory", ZCG(accel_directives).memory_consumption-zend_shared_alloc_get_free_memory()-ZSMMG(wasted_shared_memory));
622 	add_assoc_long(&memory_usage, "free_memory", zend_shared_alloc_get_free_memory());
623 	add_assoc_long(&memory_usage, "wasted_memory", ZSMMG(wasted_shared_memory));
624 	add_assoc_double(&memory_usage, "current_wasted_percentage", (((double) ZSMMG(wasted_shared_memory))/ZCG(accel_directives).memory_consumption)*100.0);
625 	add_assoc_zval(return_value, "memory_usage", &memory_usage);
626 
627 	if (ZCSG(interned_strings).start && ZCSG(interned_strings).end) {
628 		zval interned_strings_usage;
629 
630 		array_init(&interned_strings_usage);
631 		add_assoc_long(&interned_strings_usage, "buffer_size", (char*)ZCSG(interned_strings).end - (char*)(accel_shared_globals + 1));
632 		add_assoc_long(&interned_strings_usage, "used_memory", (char*)ZCSG(interned_strings).top - (char*)(accel_shared_globals + 1));
633 		add_assoc_long(&interned_strings_usage, "free_memory", (char*)ZCSG(interned_strings).end - (char*)ZCSG(interned_strings).top);
634 		add_assoc_long(&interned_strings_usage, "number_of_strings", ZCSG(interned_strings).nNumOfElements);
635 		add_assoc_zval(return_value, "interned_strings_usage", &interned_strings_usage);
636 	}
637 
638 	/* Accelerator statistics */
639 	array_init(&statistics);
640 	add_assoc_long(&statistics, "num_cached_scripts", ZCSG(hash).num_direct_entries);
641 	add_assoc_long(&statistics, "num_cached_keys",    ZCSG(hash).num_entries);
642 	add_assoc_long(&statistics, "max_cached_keys",    ZCSG(hash).max_num_entries);
643 	add_assoc_long(&statistics, "hits", (zend_long)ZCSG(hits));
644 	add_assoc_long(&statistics, "start_time", ZCSG(start_time));
645 	add_assoc_long(&statistics, "last_restart_time", ZCSG(last_restart_time));
646 	add_assoc_long(&statistics, "oom_restarts", ZCSG(oom_restarts));
647 	add_assoc_long(&statistics, "hash_restarts", ZCSG(hash_restarts));
648 	add_assoc_long(&statistics, "manual_restarts", ZCSG(manual_restarts));
649 	add_assoc_long(&statistics, "misses", ZSMMG(memory_exhausted)?ZCSG(misses):ZCSG(misses)-ZCSG(blacklist_misses));
650 	add_assoc_long(&statistics, "blacklist_misses", ZCSG(blacklist_misses));
651 	reqs = ZCSG(hits)+ZCSG(misses);
652 	add_assoc_double(&statistics, "blacklist_miss_ratio", reqs?(((double) ZCSG(blacklist_misses))/reqs)*100.0:0);
653 	add_assoc_double(&statistics, "opcache_hit_rate", reqs?(((double) ZCSG(hits))/reqs)*100.0:0);
654 	add_assoc_zval(return_value, "opcache_statistics", &statistics);
655 
656 	if (ZCSG(preload_script)) {
657 		array_init(&statistics);
658 
659 		add_assoc_long(&statistics, "memory_consumption", ZCSG(preload_script)->dynamic_members.memory_consumption);
660 
661 		if (zend_hash_num_elements(&ZCSG(preload_script)->script.function_table)) {
662 			zend_op_array *op_array;
663 
664 			array_init(&scripts);
665 			ZEND_HASH_FOREACH_PTR(&ZCSG(preload_script)->script.function_table, op_array) {
666 				add_next_index_str(&scripts, op_array->function_name);
667 			} ZEND_HASH_FOREACH_END();
668 			add_assoc_zval(&statistics, "functions", &scripts);
669 		}
670 
671 		if (zend_hash_num_elements(&ZCSG(preload_script)->script.class_table)) {
672 			zend_class_entry *ce;
673 			zend_string *key;
674 
675 			array_init(&scripts);
676 			ZEND_HASH_FOREACH_STR_KEY_PTR(&ZCSG(preload_script)->script.class_table, key, ce) {
677 				if (ce->refcount > 1 && !zend_string_equals_ci(key, ce->name)) {
678 					add_next_index_str(&scripts, key);
679 				} else {
680 					add_next_index_str(&scripts, ce->name);
681 				}
682 			} ZEND_HASH_FOREACH_END();
683 			add_assoc_zval(&statistics, "classes", &scripts);
684 		}
685 
686 		if (ZCSG(saved_scripts)) {
687 			zend_persistent_script **p = ZCSG(saved_scripts);
688 
689 			array_init(&scripts);
690 			while (*p) {
691 				add_next_index_str(&scripts, (*p)->script.filename);
692 				p++;
693 			}
694 			add_assoc_zval(&statistics, "scripts", &scripts);
695 		}
696 		add_assoc_zval(return_value, "preload_statistics", &statistics);
697 	}
698 
699 	if (fetch_scripts) {
700 		/* accelerated scripts */
701 		if (accelerator_get_scripts(&scripts)) {
702 			add_assoc_zval(return_value, "scripts", &scripts);
703 		}
704 	}
705 #if HAVE_JIT
706 	zend_jit_status(return_value);
707 #endif
708 }
709 
710 static int add_blacklist_path(zend_blacklist_entry *p, zval *return_value)
711 {
712 	add_next_index_stringl(return_value, p->path, p->path_length);
713 	return 0;
714 }
715 
716 /* {{{ Obtain configuration information */
717 ZEND_FUNCTION(opcache_get_configuration)
718 {
719 	zval directives, version, blacklist;
720 
721 	if (zend_parse_parameters_none() == FAILURE) {
722 		RETURN_THROWS();
723 	}
724 
725 	if (!validate_api_restriction()) {
726 		RETURN_FALSE;
727 	}
728 
729 	array_init(return_value);
730 
731 	/* directives */
732 	array_init(&directives);
733 	add_assoc_bool(&directives, "opcache.enable",              ZCG(enabled));
734 	add_assoc_bool(&directives, "opcache.enable_cli",          ZCG(accel_directives).enable_cli);
735 	add_assoc_bool(&directives, "opcache.use_cwd",             ZCG(accel_directives).use_cwd);
736 	add_assoc_bool(&directives, "opcache.validate_timestamps", ZCG(accel_directives).validate_timestamps);
737 	add_assoc_bool(&directives, "opcache.validate_permission", ZCG(accel_directives).validate_permission);
738 #ifndef ZEND_WIN32
739 	add_assoc_bool(&directives, "opcache.validate_root",       ZCG(accel_directives).validate_root);
740 #endif
741 	add_assoc_bool(&directives, "opcache.dups_fix",            ZCG(accel_directives).ignore_dups);
742 	add_assoc_bool(&directives, "opcache.revalidate_path",     ZCG(accel_directives).revalidate_path);
743 
744 	add_assoc_long(&directives,   "opcache.log_verbosity_level",    ZCG(accel_directives).log_verbosity_level);
745 	add_assoc_long(&directives,	 "opcache.memory_consumption",     ZCG(accel_directives).memory_consumption);
746 	add_assoc_long(&directives,	 "opcache.interned_strings_buffer",ZCG(accel_directives).interned_strings_buffer);
747 	add_assoc_long(&directives, 	 "opcache.max_accelerated_files",  ZCG(accel_directives).max_accelerated_files);
748 	add_assoc_double(&directives, "opcache.max_wasted_percentage",  ZCG(accel_directives).max_wasted_percentage);
749 	add_assoc_long(&directives, 	 "opcache.consistency_checks",     ZCG(accel_directives).consistency_checks);
750 	add_assoc_long(&directives, 	 "opcache.force_restart_timeout",  ZCG(accel_directives).force_restart_timeout);
751 	add_assoc_long(&directives, 	 "opcache.revalidate_freq",        ZCG(accel_directives).revalidate_freq);
752 	add_assoc_string(&directives, "opcache.preferred_memory_model", STRING_NOT_NULL(ZCG(accel_directives).memory_model));
753 	add_assoc_string(&directives, "opcache.blacklist_filename",     STRING_NOT_NULL(ZCG(accel_directives).user_blacklist_filename));
754 	add_assoc_long(&directives,   "opcache.max_file_size",          ZCG(accel_directives).max_file_size);
755 	add_assoc_string(&directives, "opcache.error_log",              STRING_NOT_NULL(ZCG(accel_directives).error_log));
756 
757 	add_assoc_bool(&directives,   "opcache.protect_memory",         ZCG(accel_directives).protect_memory);
758 	add_assoc_bool(&directives,   "opcache.save_comments",          ZCG(accel_directives).save_comments);
759 	add_assoc_bool(&directives,   "opcache.record_warnings",        ZCG(accel_directives).record_warnings);
760 	add_assoc_bool(&directives,   "opcache.enable_file_override",   ZCG(accel_directives).file_override_enabled);
761 	add_assoc_long(&directives, 	 "opcache.optimization_level",     ZCG(accel_directives).optimization_level);
762 
763 #ifndef ZEND_WIN32
764 	add_assoc_string(&directives, "opcache.lockfile_path",          STRING_NOT_NULL(ZCG(accel_directives).lockfile_path));
765 #else
766 	add_assoc_string(&directives, "opcache.mmap_base",              STRING_NOT_NULL(ZCG(accel_directives).mmap_base));
767 #endif
768 
769 	add_assoc_string(&directives, "opcache.file_cache",                    ZCG(accel_directives).file_cache ? ZCG(accel_directives).file_cache : "");
770 	add_assoc_bool(&directives,   "opcache.file_cache_only",               ZCG(accel_directives).file_cache_only);
771 	add_assoc_bool(&directives,   "opcache.file_cache_consistency_checks", ZCG(accel_directives).file_cache_consistency_checks);
772 #if ENABLE_FILE_CACHE_FALLBACK
773 	add_assoc_bool(&directives,   "opcache.file_cache_fallback",           ZCG(accel_directives).file_cache_fallback);
774 #endif
775 
776 	add_assoc_long(&directives,   "opcache.file_update_protection",  ZCG(accel_directives).file_update_protection);
777 	add_assoc_long(&directives,   "opcache.opt_debug_level",         ZCG(accel_directives).opt_debug_level);
778 	add_assoc_string(&directives, "opcache.restrict_api",            STRING_NOT_NULL(ZCG(accel_directives).restrict_api));
779 #ifdef HAVE_HUGE_CODE_PAGES
780 	add_assoc_bool(&directives,   "opcache.huge_code_pages",         ZCG(accel_directives).huge_code_pages);
781 #endif
782 	add_assoc_string(&directives, "opcache.preload", STRING_NOT_NULL(ZCG(accel_directives).preload));
783 #ifndef ZEND_WIN32
784 	add_assoc_string(&directives, "opcache.preload_user", STRING_NOT_NULL(ZCG(accel_directives).preload_user));
785 #endif
786 #if ZEND_WIN32
787 	add_assoc_string(&directives, "opcache.cache_id", STRING_NOT_NULL(ZCG(accel_directives).cache_id));
788 #endif
789 #ifdef HAVE_JIT
790 	add_assoc_string(&directives, "opcache.jit", JIT_G(options));
791 	add_assoc_long(&directives,   "opcache.jit_buffer_size", JIT_G(buffer_size));
792 	add_assoc_long(&directives,   "opcache.jit_debug", JIT_G(debug));
793 	add_assoc_long(&directives,   "opcache.jit_bisect_limit", JIT_G(bisect_limit));
794 	add_assoc_long(&directives,   "opcache.jit_blacklist_root_trace", JIT_G(blacklist_root_trace));
795 	add_assoc_long(&directives,   "opcache.jit_blacklist_side_trace", JIT_G(blacklist_side_trace));
796 	add_assoc_long(&directives,   "opcache.jit_hot_func", JIT_G(hot_func));
797 	add_assoc_long(&directives,   "opcache.jit_hot_loop", JIT_G(hot_loop));
798 	add_assoc_long(&directives,   "opcache.jit_hot_return", JIT_G(hot_return));
799 	add_assoc_long(&directives,   "opcache.jit_hot_side_exit", JIT_G(hot_side_exit));
800 	add_assoc_long(&directives,   "opcache.jit_max_exit_counters", JIT_G(max_exit_counters));
801 	add_assoc_long(&directives,   "opcache.jit_max_loop_unrolls", JIT_G(max_loop_unrolls));
802 	add_assoc_long(&directives,   "opcache.jit_max_polymorphic_calls", JIT_G(max_polymorphic_calls));
803 	add_assoc_long(&directives,   "opcache.jit_max_recursive_calls", JIT_G(max_recursive_calls));
804 	add_assoc_long(&directives,   "opcache.jit_max_recursive_returns", JIT_G(max_recursive_returns));
805 	add_assoc_long(&directives,   "opcache.jit_max_root_traces", JIT_G(max_root_traces));
806 	add_assoc_long(&directives,   "opcache.jit_max_side_traces", JIT_G(max_side_traces));
807 	add_assoc_long(&directives,   "opcache.jit_prof_threshold", JIT_G(prof_threshold));
808 #endif
809 
810 	add_assoc_zval(return_value, "directives", &directives);
811 
812 	/*version */
813 	array_init(&version);
814 	add_assoc_string(&version, "version", PHP_VERSION);
815 	add_assoc_string(&version, "opcache_product_name", ACCELERATOR_PRODUCT_NAME);
816 	add_assoc_zval(return_value, "version", &version);
817 
818 	/* blacklist */
819 	array_init(&blacklist);
820 	zend_accel_blacklist_apply(&accel_blacklist, add_blacklist_path, &blacklist);
821 	add_assoc_zval(return_value, "blacklist", &blacklist);
822 }
823 
824 /* {{{ Request that the contents of the opcode cache to be reset */
825 ZEND_FUNCTION(opcache_reset)
826 {
827 	if (zend_parse_parameters_none() == FAILURE) {
828 		RETURN_THROWS();
829 	}
830 
831 	if (!validate_api_restriction()) {
832 		RETURN_FALSE;
833 	}
834 
835 	if ((!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled))
836 #if ENABLE_FILE_CACHE_FALLBACK
837 	&& !fallback_process
838 #endif
839 	) {
840 		RETURN_FALSE;
841 	}
842 
843 	/* exclusive lock */
844 	zend_shared_alloc_lock();
845 	zend_accel_schedule_restart(ACCEL_RESTART_USER);
846 	zend_shared_alloc_unlock();
847 	RETURN_TRUE;
848 }
849 
850 /* {{{ Invalidates cached script (in necessary or forced) */
851 ZEND_FUNCTION(opcache_invalidate)
852 {
853 	zend_string *script_name;
854 	bool force = 0;
855 
856 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|b", &script_name, &force) == FAILURE) {
857 		RETURN_THROWS();
858 	}
859 
860 	if (!validate_api_restriction()) {
861 		RETURN_FALSE;
862 	}
863 
864 	if (zend_accel_invalidate(script_name, force) == SUCCESS) {
865 		RETURN_TRUE;
866 	} else {
867 		RETURN_FALSE;
868 	}
869 }
870 
871 ZEND_FUNCTION(opcache_compile_file)
872 {
873 	zend_string *script_name;
874 	zend_file_handle handle;
875 	zend_op_array *op_array = NULL;
876 	zend_execute_data *orig_execute_data = NULL;
877 	uint32_t orig_compiler_options;
878 
879 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &script_name) == FAILURE) {
880 		RETURN_THROWS();
881 	}
882 
883 	if (!accel_startup_ok) {
884 		zend_error(E_NOTICE, ACCELERATOR_PRODUCT_NAME " has not been properly started, can't compile file");
885 		RETURN_FALSE;
886 	}
887 
888 	zend_stream_init_filename_ex(&handle, script_name);
889 
890 	orig_execute_data = EG(current_execute_data);
891 	orig_compiler_options = CG(compiler_options);
892 	CG(compiler_options) |= ZEND_COMPILE_WITHOUT_EXECUTION;
893 
894 	if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
895 		/* During preloading, a failure in opcache_compile_file() should result in an overall
896 		 * preloading failure. Otherwise we may include partially compiled files in the preload
897 		 * state. */
898 		op_array = persistent_compile_file(&handle, ZEND_INCLUDE);
899 	} else {
900 		zend_try {
901 			op_array = persistent_compile_file(&handle, ZEND_INCLUDE);
902 		} zend_catch {
903 			EG(current_execute_data) = orig_execute_data;
904 			zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " could not compile file %s", ZSTR_VAL(handle.filename));
905 		} zend_end_try();
906 	}
907 
908 	CG(compiler_options) = orig_compiler_options;
909 
910 	if(op_array != NULL) {
911 		destroy_op_array(op_array);
912 		efree(op_array);
913 		RETVAL_TRUE;
914 	} else {
915 		RETVAL_FALSE;
916 	}
917 	zend_destroy_file_handle(&handle);
918 }
919 
920 /* {{{ Return true if the script is cached in OPCache, false if it is not cached or if OPCache is not running. */
921 ZEND_FUNCTION(opcache_is_script_cached)
922 {
923 	zend_string *script_name;
924 
925 	ZEND_PARSE_PARAMETERS_START(1, 1)
926 		Z_PARAM_STR(script_name)
927 	ZEND_PARSE_PARAMETERS_END();
928 
929 	if (!validate_api_restriction()) {
930 		RETURN_FALSE;
931 	}
932 
933 	if (!ZCG(accelerator_enabled)) {
934 		RETURN_FALSE;
935 	}
936 
937 	RETURN_BOOL(filename_is_in_cache(script_name));
938 }
939