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