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