This source file includes following definitions.
- zend_file_cache_flock
- zend_file_cache_flock
- zend_file_cache_mkdir
- zend_file_cache_serialize_interned
- zend_file_cache_unserialize_interned
- zend_file_cache_serialize_hash
- zend_file_cache_serialize_ast
- zend_file_cache_serialize_zval
- zend_file_cache_serialize_op_array
- zend_file_cache_serialize_func
- zend_file_cache_serialize_prop_info
- zend_file_cache_serialize_class
- zend_file_cache_serialize
- zend_file_cache_get_bin_file_path
- zend_file_cache_script_store
- zend_file_cache_unserialize_hash
- zend_file_cache_unserialize_ast
- zend_file_cache_unserialize_zval
- zend_file_cache_unserialize_op_array
- zend_file_cache_unserialize_func
- zend_file_cache_unserialize_prop_info
- zend_file_cache_unserialize_class
- zend_file_cache_unserialize
- zend_file_cache_script_load
- zend_file_cache_invalidate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include "zend.h"
20 #include "zend_virtual_cwd.h"
21 #include "zend_compile.h"
22 #include "zend_vm.h"
23 #include "zend_interfaces.h"
24
25 #include "php.h"
26
27 #ifdef HAVE_OPCACHE_FILE_CACHE
28
29 #include "ZendAccelerator.h"
30 #include "zend_file_cache.h"
31 #include "zend_shared_alloc.h"
32 #include "zend_accelerator_util_funcs.h"
33 #include "zend_accelerator_hash.h"
34
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38
39 #if HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 #ifdef HAVE_SYS_UIO_H
44 # include <sys/uio.h>
45 #endif
46
47 #ifdef HAVE_SYS_FILE_H
48 # include <sys/file.h>
49 #endif
50
51 #ifdef ZEND_WIN32
52 # define LOCK_SH 0
53 # define LOCK_EX 1
54 # define LOCK_UN 2
55 static int zend_file_cache_flock(int fd, int op)
56 {
57 OVERLAPPED offset = {0,0,0,0,NULL};
58 if (op == LOCK_EX) {
59 if (LockFileEx((HANDLE)_get_osfhandle(fd),
60 LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset) == TRUE) {
61 return 0;
62 }
63 } else if (op == LOCK_SH) {
64 if (LockFileEx((HANDLE)_get_osfhandle(fd),
65 0, 0, 1, 0, &offset) == TRUE) {
66 return 0;
67 }
68 } else if (op == LOCK_UN) {
69 if (UnlockFileEx((HANDLE)_get_osfhandle(fd),
70 0, 1, 0, &offset) == TRUE) {
71 return 0;
72 }
73 }
74 return -1;
75 }
76 #elif defined(HAVE_FLOCK)
77 # define zend_file_cache_flock flock
78 #else
79 # define LOCK_SH 0
80 # define LOCK_EX 1
81 # define LOCK_UN 2
82 static int zend_file_cache_flock(int fd, int type)
83 {
84 return 0;
85 }
86 #endif
87
88 #ifndef O_BINARY
89 # define O_BINARY 0
90 #endif
91
92 #define SUFFIX ".bin"
93
94 #define IS_SERIALIZED_INTERNED(ptr) \
95 ((size_t)(ptr) & Z_UL(1))
96 #define IS_SERIALIZED(ptr) \
97 ((char*)(ptr) < (char*)script->size)
98 #define IS_UNSERIALIZED(ptr) \
99 (((char*)(ptr) >= (char*)script->mem && (char*)(ptr) < (char*)script->mem + script->size) || \
100 IS_ACCEL_INTERNED(ptr))
101 #define SERIALIZE_PTR(ptr) do { \
102 if (ptr) { \
103 ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \
104 (ptr) = (void*)((char*)(ptr) - (char*)script->mem); \
105 } \
106 } while (0)
107 #define UNSERIALIZE_PTR(ptr) do { \
108 if (ptr) { \
109 ZEND_ASSERT(IS_SERIALIZED(ptr)); \
110 (ptr) = (void*)((char*)buf + (size_t)(ptr)); \
111 } \
112 } while (0)
113 #define SERIALIZE_STR(ptr) do { \
114 if (ptr) { \
115 if (IS_ACCEL_INTERNED(ptr)) { \
116 (ptr) = zend_file_cache_serialize_interned((zend_string*)(ptr), info); \
117 } else { \
118 ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \
119 \
120 if (EXPECTED(script->corrupted)) { \
121 GC_FLAGS(ptr) |= IS_STR_INTERNED; \
122 GC_FLAGS(ptr) &= ~IS_STR_PERMANENT; \
123 } \
124 (ptr) = (void*)((char*)(ptr) - (char*)script->mem); \
125 } \
126 } \
127 } while (0)
128 #define UNSERIALIZE_STR(ptr) do { \
129 if (ptr) { \
130 if (IS_SERIALIZED_INTERNED(ptr)) { \
131 (ptr) = (void*)zend_file_cache_unserialize_interned((zend_string*)(ptr), !script->corrupted); \
132 } else { \
133 ZEND_ASSERT(IS_SERIALIZED(ptr)); \
134 (ptr) = (void*)((char*)buf + (size_t)(ptr)); \
135 \
136 if (EXPECTED(!script->corrupted)) { \
137 GC_FLAGS(ptr) |= IS_STR_INTERNED | IS_STR_PERMANENT; \
138 } else { \
139 GC_FLAGS(ptr) |= IS_STR_INTERNED; \
140 GC_FLAGS(ptr) &= ~IS_STR_PERMANENT; \
141 } \
142 } \
143 } \
144 } while (0)
145
146 static const uint32_t uninitialized_bucket[-HT_MIN_MASK] =
147 {HT_INVALID_IDX, HT_INVALID_IDX};
148
149 typedef struct _zend_file_cache_metainfo {
150 char magic[8];
151 char system_id[32];
152 size_t mem_size;
153 size_t str_size;
154 size_t script_offset;
155 accel_time_t timestamp;
156 uint32_t checksum;
157 } zend_file_cache_metainfo;
158
159 static int zend_file_cache_mkdir(char *filename, size_t start)
160 {
161 char *s = filename + start;
162
163 while (*s) {
164 if (IS_SLASH(*s)) {
165 char old = *s;
166 *s = '\000';
167 if (mkdir(filename, S_IRWXU) < 0 && errno != EEXIST) {
168 *s = old;
169 return FAILURE;
170 }
171 *s = old;
172 }
173 s++;
174 }
175 return SUCCESS;
176 }
177
178 typedef void (*serialize_callback_t)(zval *zv,
179 zend_persistent_script *script,
180 zend_file_cache_metainfo *info,
181 void *buf);
182
183 typedef void (*unserialize_callback_t)(zval *zv,
184 zend_persistent_script *script,
185 void *buf);
186
187 static void zend_file_cache_serialize_zval(zval *zv,
188 zend_persistent_script *script,
189 zend_file_cache_metainfo *info,
190 void *buf);
191 static void zend_file_cache_unserialize_zval(zval *zv,
192 zend_persistent_script *script,
193 void *buf);
194
195 static void *zend_file_cache_serialize_interned(zend_string *str,
196 zend_file_cache_metainfo *info)
197 {
198 size_t len;
199 void *ret;
200
201
202 ret = zend_shared_alloc_get_xlat_entry(str);
203 if (ret) {
204 return ret;
205 }
206
207 len = ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(ZSTR_LEN(str)));
208 ret = (void*)(info->str_size | Z_UL(1));
209 zend_shared_alloc_register_xlat_entry(str, ret);
210 if (info->str_size + len > ZSTR_LEN((zend_string*)ZCG(mem))) {
211 size_t new_len = info->str_size + len;
212 ZCG(mem) = (void*)zend_string_realloc(
213 (zend_string*)ZCG(mem),
214 ((_ZSTR_HEADER_SIZE + 1 + new_len + 4095) & ~0xfff) - (_ZSTR_HEADER_SIZE + 1),
215 0);
216 }
217 memcpy(ZSTR_VAL((zend_string*)ZCG(mem)) + info->str_size, str, len);
218 info->str_size += len;
219 return ret;
220 }
221
222 static void *zend_file_cache_unserialize_interned(zend_string *str, int in_shm)
223 {
224 zend_string *ret;
225
226 str = (zend_string*)((char*)ZCG(mem) + ((size_t)(str) & ~Z_UL(1)));
227 if (in_shm) {
228 ret = accel_new_interned_string(str);
229 if (ret == str) {
230
231 GC_FLAGS(ret) |= IS_STR_INTERNED | IS_STR_PERMANENT;
232 }
233 } else {
234 ret = str;
235 GC_FLAGS(ret) |= IS_STR_INTERNED;
236 GC_FLAGS(ret) &= ~IS_STR_PERMANENT;
237 }
238 return ret;
239 }
240
241 static void zend_file_cache_serialize_hash(HashTable *ht,
242 zend_persistent_script *script,
243 zend_file_cache_metainfo *info,
244 void *buf,
245 serialize_callback_t func)
246 {
247 Bucket *p, *end;
248
249 if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
250 ht->arData = NULL;
251 return;
252 }
253 if (IS_SERIALIZED(ht->arData)) {
254 return;
255 }
256 SERIALIZE_PTR(ht->arData);
257 p = ht->arData;
258 UNSERIALIZE_PTR(p);
259 end = p + ht->nNumUsed;
260 while (p < end) {
261 if (Z_TYPE(p->val) != IS_UNDEF) {
262 SERIALIZE_STR(p->key);
263 func(&p->val, script, info, buf);
264 }
265 p++;
266 }
267 }
268
269 static zend_ast *zend_file_cache_serialize_ast(zend_ast *ast,
270 zend_persistent_script *script,
271 zend_file_cache_metainfo *info,
272 void *buf)
273 {
274 uint32_t i;
275 zend_ast *ret;
276
277 SERIALIZE_PTR(ast);
278 ret = ast;
279 UNSERIALIZE_PTR(ast);
280
281 if (ast->kind == ZEND_AST_ZVAL) {
282 zend_file_cache_serialize_zval(&((zend_ast_zval*)ast)->val, script, info, buf);
283 } else if (zend_ast_is_list(ast)) {
284 zend_ast_list *list = zend_ast_get_list(ast);
285 for (i = 0; i < list->children; i++) {
286 if (list->child[i]) {
287 list->child[i] = zend_file_cache_serialize_ast(list->child[i], script, info, buf);
288 }
289 }
290 } else {
291 uint32_t children = zend_ast_get_num_children(ast);
292 for (i = 0; i < children; i++) {
293 if (ast->child[i]) {
294 ast->child[i] = zend_file_cache_serialize_ast(ast->child[i], script, info, buf);
295 }
296 }
297 }
298 return ret;
299 }
300
301 static void zend_file_cache_serialize_zval(zval *zv,
302 zend_persistent_script *script,
303 zend_file_cache_metainfo *info,
304 void *buf)
305 {
306 switch (Z_TYPE_P(zv)) {
307 case IS_STRING:
308 case IS_CONSTANT:
309 if (!IS_SERIALIZED(Z_STR_P(zv))) {
310 SERIALIZE_STR(Z_STR_P(zv));
311 }
312 break;
313 case IS_ARRAY:
314 if (!IS_SERIALIZED(Z_ARR_P(zv))) {
315 HashTable *ht;
316
317 SERIALIZE_PTR(Z_ARR_P(zv));
318 ht = Z_ARR_P(zv);
319 UNSERIALIZE_PTR(ht);
320 zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval);
321 }
322 break;
323 case IS_REFERENCE:
324 if (!IS_SERIALIZED(Z_REF_P(zv))) {
325 zend_reference *ref;
326
327 SERIALIZE_PTR(Z_REF_P(zv));
328 ref = Z_REF_P(zv);
329 UNSERIALIZE_PTR(ref);
330 zend_file_cache_serialize_zval(&ref->val, script, info, buf);
331 }
332 break;
333 case IS_CONSTANT_AST:
334 if (!IS_SERIALIZED(Z_AST_P(zv))) {
335 zend_ast_ref *ast;
336
337 SERIALIZE_PTR(Z_AST_P(zv));
338 ast = Z_AST_P(zv);
339 UNSERIALIZE_PTR(ast);
340 if (!IS_SERIALIZED(ast->ast)) {
341 ast->ast = zend_file_cache_serialize_ast(ast->ast, script, info, buf);
342 }
343 }
344 break;
345 }
346 }
347
348 static void zend_file_cache_serialize_op_array(zend_op_array *op_array,
349 zend_persistent_script *script,
350 zend_file_cache_metainfo *info,
351 void *buf)
352 {
353 if (op_array->static_variables && !IS_SERIALIZED(op_array->static_variables)) {
354 HashTable *ht;
355
356 SERIALIZE_PTR(op_array->static_variables);
357 ht = op_array->static_variables;
358 UNSERIALIZE_PTR(ht);
359 zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval);
360 }
361
362 if (op_array->literals && !IS_SERIALIZED(op_array->literals)) {
363 zval *p, *end;
364
365 SERIALIZE_PTR(op_array->literals);
366 p = op_array->literals;
367 UNSERIALIZE_PTR(p);
368 end = p + op_array->last_literal;
369 while (p < end) {
370 zend_file_cache_serialize_zval(p, script, info, buf);
371 p++;
372 }
373 }
374
375 if (!IS_SERIALIZED(op_array->opcodes)) {
376 #if ZEND_USE_ABS_CONST_ADDR || ZEND_USE_ABS_JMP_ADDR
377 zend_op *opline, *end;
378
379 SERIALIZE_PTR(op_array->opcodes);
380 opline = op_array->opcodes;
381 UNSERIALIZE_PTR(opline);
382 end = opline + op_array->last;
383 while (opline < end) {
384 # if ZEND_USE_ABS_CONST_ADDR
385 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
386 SERIALIZE_PTR(opline->op1.zv);
387 }
388 if (ZEND_OP2_TYPE(opline) == IS_CONST) {
389 SERIALIZE_PTR(opline->op2.zv);
390 }
391 # endif
392 # if ZEND_USE_ABS_JMP_ADDR
393 switch (opline->opcode) {
394 case ZEND_JMP:
395 case ZEND_FAST_CALL:
396 case ZEND_DECLARE_ANON_CLASS:
397 case ZEND_DECLARE_ANON_INHERITED_CLASS:
398 SERIALIZE_PTR(opline->op1.jmp_addr);
399 break;
400 case ZEND_JMPZNZ:
401
402
403 case ZEND_JMPZ:
404 case ZEND_JMPNZ:
405 case ZEND_JMPZ_EX:
406 case ZEND_JMPNZ_EX:
407 case ZEND_JMP_SET:
408 case ZEND_COALESCE:
409 case ZEND_NEW:
410 case ZEND_FE_RESET_R:
411 case ZEND_FE_RESET_RW:
412 case ZEND_ASSERT_CHECK:
413 SERIALIZE_PTR(opline->op2.jmp_addr);
414 break;
415 case ZEND_FE_FETCH_R:
416 case ZEND_FE_FETCH_RW:
417
418 break;
419 }
420 # endif
421 opline++;
422 }
423 #else
424 SERIALIZE_PTR(op_array->opcodes);
425 #endif
426
427 if (op_array->arg_info) {
428 zend_arg_info *p, *end;
429 SERIALIZE_PTR(op_array->arg_info);
430 p = op_array->arg_info;
431 UNSERIALIZE_PTR(p);
432 end = p + op_array->num_args;
433 if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
434 p--;
435 }
436 if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
437 end++;
438 }
439 while (p < end) {
440 if (!IS_SERIALIZED(p->name)) {
441 SERIALIZE_STR(p->name);
442 }
443 if (!IS_SERIALIZED(p->class_name)) {
444 SERIALIZE_STR(p->class_name);
445 }
446 p++;
447 }
448 }
449
450 if (op_array->vars) {
451 zend_string **p, **end;
452
453 SERIALIZE_PTR(op_array->vars);
454 p = op_array->vars;
455 UNSERIALIZE_PTR(p);
456 end = p + op_array->last_var;
457 while (p < end) {
458 if (!IS_SERIALIZED(*p)) {
459 SERIALIZE_STR(*p);
460 }
461 p++;
462 }
463 }
464
465 SERIALIZE_STR(op_array->function_name);
466 SERIALIZE_STR(op_array->filename);
467 SERIALIZE_PTR(op_array->brk_cont_array);
468 SERIALIZE_PTR(op_array->scope);
469 SERIALIZE_STR(op_array->doc_comment);
470 SERIALIZE_PTR(op_array->try_catch_array);
471 SERIALIZE_PTR(op_array->prototype);
472 }
473 }
474
475 static void zend_file_cache_serialize_func(zval *zv,
476 zend_persistent_script *script,
477 zend_file_cache_metainfo *info,
478 void *buf)
479 {
480 zend_op_array *op_array;
481
482 SERIALIZE_PTR(Z_PTR_P(zv));
483 op_array = Z_PTR_P(zv);
484 UNSERIALIZE_PTR(op_array);
485 zend_file_cache_serialize_op_array(op_array, script, info, buf);
486 }
487
488 static void zend_file_cache_serialize_prop_info(zval *zv,
489 zend_persistent_script *script,
490 zend_file_cache_metainfo *info,
491 void *buf)
492 {
493 if (!IS_SERIALIZED(Z_PTR_P(zv))) {
494 zend_property_info *prop;
495
496 SERIALIZE_PTR(Z_PTR_P(zv));
497 prop = Z_PTR_P(zv);
498 UNSERIALIZE_PTR(prop);
499
500 if (prop->ce && !IS_SERIALIZED(prop->ce)) {
501 SERIALIZE_PTR(prop->ce);
502 }
503 if (prop->name && !IS_SERIALIZED(prop->name)) {
504 SERIALIZE_STR(prop->name);
505 }
506 if (prop->doc_comment && !IS_SERIALIZED(prop->doc_comment)) {
507 SERIALIZE_STR(prop->doc_comment);
508 }
509 }
510 }
511
512 static void zend_file_cache_serialize_class(zval *zv,
513 zend_persistent_script *script,
514 zend_file_cache_metainfo *info,
515 void *buf)
516 {
517 zend_class_entry *ce;
518
519 SERIALIZE_PTR(Z_PTR_P(zv));
520 ce = Z_PTR_P(zv);
521 UNSERIALIZE_PTR(ce);
522
523 SERIALIZE_STR(ce->name);
524 zend_file_cache_serialize_hash(&ce->function_table, script, info, buf, zend_file_cache_serialize_func);
525 if (ce->default_properties_table) {
526 zval *p, *end;
527
528 SERIALIZE_PTR(ce->default_properties_table);
529 p = ce->default_properties_table;
530 UNSERIALIZE_PTR(p);
531 end = p + ce->default_properties_count;
532 while (p < end) {
533 zend_file_cache_serialize_zval(p, script, info, buf);
534 p++;
535 }
536 }
537 if (ce->default_static_members_table) {
538 zval *p, *end;
539
540 SERIALIZE_PTR(ce->default_static_members_table);
541 p = ce->default_static_members_table;
542 UNSERIALIZE_PTR(p);
543 end = p + ce->default_static_members_count;
544 while (p < end) {
545 zend_file_cache_serialize_zval(p, script, info, buf);
546 p++;
547 }
548 }
549 zend_file_cache_serialize_hash(&ce->constants_table, script, info, buf, zend_file_cache_serialize_zval);
550 SERIALIZE_STR(ZEND_CE_FILENAME(ce));
551 SERIALIZE_STR(ZEND_CE_DOC_COMMENT(ce));
552 zend_file_cache_serialize_hash(&ce->properties_info, script, info, buf, zend_file_cache_serialize_prop_info);
553
554 if (ce->trait_aliases) {
555 zend_trait_alias **p, *q;
556
557 SERIALIZE_PTR(ce->trait_aliases);
558 p = ce->trait_aliases;
559 UNSERIALIZE_PTR(p);
560
561 while (*p) {
562 SERIALIZE_PTR(*p);
563 q = *p;
564 UNSERIALIZE_PTR(q);
565
566 if (q->trait_method) {
567 zend_trait_method_reference *m;
568
569 SERIALIZE_PTR(q->trait_method);
570 m = q->trait_method;
571 UNSERIALIZE_PTR(m);
572
573 if (m->method_name) {
574 SERIALIZE_STR(m->method_name);
575 }
576 if (m->class_name) {
577 SERIALIZE_STR(m->class_name);
578 }
579 }
580
581 if (q->alias) {
582 SERIALIZE_STR(q->alias);
583 }
584 p++;
585 }
586 }
587
588 if (ce->trait_precedences) {
589 zend_trait_precedence **p, *q;
590
591 SERIALIZE_PTR(ce->trait_precedences);
592 p = ce->trait_precedences;
593 UNSERIALIZE_PTR(p);
594
595 while (*p) {
596 SERIALIZE_PTR(*p);
597 q = *p;
598 UNSERIALIZE_PTR(q);
599
600 if (q->trait_method) {
601 zend_trait_method_reference *m;
602
603 SERIALIZE_PTR(q->trait_method);
604 m = q->trait_method;
605 UNSERIALIZE_PTR(m);
606
607 if (m->method_name) {
608 SERIALIZE_STR(m->method_name);
609 }
610 if (m->class_name) {
611 SERIALIZE_STR(m->class_name);
612 }
613 }
614
615 if (q->exclude_from_classes) {
616 zend_string **s;
617
618 SERIALIZE_PTR(q->exclude_from_classes);
619 s = (zend_string**)q->exclude_from_classes;
620 UNSERIALIZE_PTR(s);
621
622 while (*s) {
623 SERIALIZE_STR(*s);
624 s++;
625 }
626 }
627 p++;
628 }
629 }
630
631 SERIALIZE_PTR(ce->parent);
632 SERIALIZE_PTR(ce->constructor);
633 SERIALIZE_PTR(ce->destructor);
634 SERIALIZE_PTR(ce->clone);
635 SERIALIZE_PTR(ce->__get);
636 SERIALIZE_PTR(ce->__set);
637 SERIALIZE_PTR(ce->__call);
638 SERIALIZE_PTR(ce->serialize_func);
639 SERIALIZE_PTR(ce->unserialize_func);
640 SERIALIZE_PTR(ce->__isset);
641 SERIALIZE_PTR(ce->__unset);
642 SERIALIZE_PTR(ce->__tostring);
643 SERIALIZE_PTR(ce->__callstatic);
644 SERIALIZE_PTR(ce->__debugInfo);
645 }
646
647 static void zend_file_cache_serialize(zend_persistent_script *script,
648 zend_file_cache_metainfo *info,
649 void *buf)
650 {
651 zend_persistent_script *new_script;
652
653 memcpy(info->magic, "OPCACHE", 8);
654 memcpy(info->system_id, ZCG(system_id), 32);
655 info->mem_size = script->size;
656 info->str_size = 0;
657 info->script_offset = (char*)script - (char*)script->mem;
658 info->timestamp = script->timestamp;
659
660 memcpy(buf, script->mem, script->size);
661
662 new_script = (zend_persistent_script*)((char*)buf + info->script_offset);
663 SERIALIZE_STR(new_script->full_path);
664
665 zend_file_cache_serialize_hash(&new_script->class_table, script, info, buf, zend_file_cache_serialize_class);
666 zend_file_cache_serialize_hash(&new_script->function_table, script, info, buf, zend_file_cache_serialize_func);
667 zend_file_cache_serialize_op_array(&new_script->main_op_array, script, info, buf);
668
669 SERIALIZE_PTR(new_script->arena_mem);
670 new_script->mem = NULL;
671 }
672
673 static char *zend_file_cache_get_bin_file_path(zend_string *script_path)
674 {
675 size_t len;
676 char *filename;
677
678 len = strlen(ZCG(accel_directives).file_cache);
679 filename = emalloc(len + 33 + ZSTR_LEN(script_path) + sizeof(SUFFIX));
680 memcpy(filename, ZCG(accel_directives).file_cache, len);
681 #ifndef ZEND_WIN32
682 filename[len] = '/';
683 memcpy(filename + len + 1, ZCG(system_id), 32);
684 memcpy(filename + len + 33, ZSTR_VAL(script_path), ZSTR_LEN(script_path));
685 memcpy(filename + len + 33 + ZSTR_LEN(script_path), SUFFIX, sizeof(SUFFIX));
686 #else
687 filename[len] = '\\';
688 memcpy(filename + len + 1, ZCG(system_id), 32);
689 if (ZSTR_LEN(script_path) >= 2 && ':' == ZSTR_VAL(script_path)[1]) {
690
691 *(filename + len + 33) = '\\';
692 *(filename + len + 34) = ZSTR_VAL(script_path)[0];
693 memcpy(filename + len + 35, ZSTR_VAL(script_path) + 2, ZSTR_LEN(script_path) - 2);
694 memcpy(filename + len + 35 + ZSTR_LEN(script_path) - 2, SUFFIX, sizeof(SUFFIX));
695 } else {
696
697 memcpy(filename + len + 33, ZSTR_VAL(script_path), ZSTR_LEN(script_path));
698 memcpy(filename + len + 33 + ZSTR_LEN(script_path), SUFFIX, sizeof(SUFFIX));
699 }
700 #endif
701
702 return filename;
703 }
704
705 int zend_file_cache_script_store(zend_persistent_script *script, int in_shm)
706 {
707 int fd;
708 char *filename;
709 zend_file_cache_metainfo info;
710 #ifdef HAVE_SYS_UIO_H
711 struct iovec vec[3];
712 #endif
713 void *mem, *buf;
714
715 filename = zend_file_cache_get_bin_file_path(script->full_path);
716
717 if (zend_file_cache_mkdir(filename, strlen(ZCG(accel_directives).file_cache)) != SUCCESS) {
718 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot create directory for file '%s'\n", filename);
719 efree(filename);
720 return FAILURE;
721 }
722
723 #ifndef ZEND_WIN32
724 fd = open(filename, O_CREAT | O_EXCL | O_RDWR | O_BINARY, S_IRUSR | S_IWUSR);
725 #else
726 fd = open(filename, O_CREAT | O_EXCL | O_RDWR | O_BINARY, _S_IREAD | _S_IWRITE);
727 #endif
728 if (fd < 0) {
729 if (errno != EEXIST) {
730 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot create file '%s'\n", filename);
731 }
732 efree(filename);
733 return FAILURE;
734 }
735
736 if (zend_file_cache_flock(fd, LOCK_EX) != 0) {
737 close(fd);
738 efree(filename);
739 return FAILURE;
740 }
741
742 #ifdef __SSE2__
743
744 mem = emalloc(script->size + 64);
745 buf = (void*)(((zend_uintptr_t)mem + 63L) & ~63L);
746 #else
747 mem = buf = emalloc(script->size);
748 #endif
749
750 ZCG(mem) = zend_string_alloc(4096 - (_ZSTR_HEADER_SIZE + 1), 0);
751
752 zend_shared_alloc_init_xlat_table();
753 if (!in_shm) {
754 script->corrupted = 1;
755 }
756 zend_file_cache_serialize(script, &info, buf);
757 if (!in_shm) {
758 script->corrupted = 0;
759 }
760 zend_shared_alloc_destroy_xlat_table();
761
762 info.checksum = zend_adler32(ADLER32_INIT, buf, script->size);
763 info.checksum = zend_adler32(info.checksum, (signed char*)ZSTR_VAL((zend_string*)ZCG(mem)), info.str_size);
764
765 #ifdef HAVE_SYS_UIO_H
766 vec[0].iov_base = &info;
767 vec[0].iov_len = sizeof(info);
768 vec[1].iov_base = buf;
769 vec[1].iov_len = script->size;
770 vec[2].iov_base = ZSTR_VAL((zend_string*)ZCG(mem));
771 vec[2].iov_len = info.str_size;
772
773 if (writev(fd, vec, 3) != (ssize_t)(sizeof(info) + script->size + info.str_size)) {
774 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot write to file '%s'\n", filename);
775 zend_string_release((zend_string*)ZCG(mem));
776 efree(mem);
777 unlink(filename);
778 efree(filename);
779 return FAILURE;
780 }
781 #else
782 if (ZEND_LONG_MAX < (zend_long)(sizeof(info) + script->size + info.str_size) ||
783 write(fd, &info, sizeof(info)) != sizeof(info) ||
784 write(fd, buf, script->size) != script->size ||
785 write(fd, ((zend_string*)ZCG(mem))->val, info.str_size) != info.str_size
786 ) {
787 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot write to file '%s'\n", filename);
788 zend_string_release((zend_string*)ZCG(mem));
789 efree(mem);
790 unlink(filename);
791 efree(filename);
792 return FAILURE;
793 }
794 #endif
795
796 zend_string_release((zend_string*)ZCG(mem));
797 efree(mem);
798 if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
799 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
800 }
801 close(fd);
802 efree(filename);
803
804 return SUCCESS;
805 }
806
807 static void zend_file_cache_unserialize_hash(HashTable *ht,
808 zend_persistent_script *script,
809 void *buf,
810 unserialize_callback_t func,
811 dtor_func_t dtor)
812 {
813 Bucket *p, *end;
814
815 ht->pDestructor = dtor;
816 if (!(ht->u.flags & HASH_FLAG_INITIALIZED)) {
817 HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
818 return;
819 }
820 if (IS_UNSERIALIZED(ht->arData)) {
821 return;
822 }
823 UNSERIALIZE_PTR(ht->arData);
824 p = ht->arData;
825 end = p + ht->nNumUsed;
826 while (p < end) {
827 if (Z_TYPE(p->val) != IS_UNDEF) {
828 UNSERIALIZE_STR(p->key);
829 func(&p->val, script, buf);
830 }
831 p++;
832 }
833 }
834
835 static zend_ast *zend_file_cache_unserialize_ast(zend_ast *ast,
836 zend_persistent_script *script,
837 void *buf)
838 {
839 uint32_t i;
840
841 UNSERIALIZE_PTR(ast);
842
843 if (ast->kind == ZEND_AST_ZVAL) {
844 zend_file_cache_unserialize_zval(&((zend_ast_zval*)ast)->val, script, buf);
845 } else if (zend_ast_is_list(ast)) {
846 zend_ast_list *list = zend_ast_get_list(ast);
847 for (i = 0; i < list->children; i++) {
848 if (list->child[i]) {
849 list->child[i] = zend_file_cache_unserialize_ast(list->child[i], script, buf);
850 }
851 }
852 } else {
853 uint32_t children = zend_ast_get_num_children(ast);
854 for (i = 0; i < children; i++) {
855 if (ast->child[i]) {
856 ast->child[i] = zend_file_cache_unserialize_ast(ast->child[i], script, buf);
857 }
858 }
859 }
860 return ast;
861 }
862
863 static void zend_file_cache_unserialize_zval(zval *zv,
864 zend_persistent_script *script,
865 void *buf)
866 {
867 switch (Z_TYPE_P(zv)) {
868 case IS_STRING:
869 case IS_CONSTANT:
870 if (!IS_UNSERIALIZED(Z_STR_P(zv))) {
871 UNSERIALIZE_STR(Z_STR_P(zv));
872 }
873 break;
874 case IS_ARRAY:
875 if (!IS_UNSERIALIZED(Z_ARR_P(zv))) {
876 HashTable *ht;
877
878 UNSERIALIZE_PTR(Z_ARR_P(zv));
879 ht = Z_ARR_P(zv);
880 zend_file_cache_unserialize_hash(ht,
881 script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR);
882 }
883 break;
884 case IS_REFERENCE:
885 if (!IS_UNSERIALIZED(Z_REF_P(zv))) {
886 zend_reference *ref;
887
888 UNSERIALIZE_PTR(Z_REF_P(zv));
889 ref = Z_REF_P(zv);
890 zend_file_cache_unserialize_zval(&ref->val, script, buf);
891 }
892 break;
893 case IS_CONSTANT_AST:
894 if (!IS_UNSERIALIZED(Z_AST_P(zv))) {
895 zend_ast_ref *ast;
896
897 UNSERIALIZE_PTR(Z_AST_P(zv));
898 ast = Z_AST_P(zv);
899 if (!IS_UNSERIALIZED(ast->ast)) {
900 ast->ast = zend_file_cache_unserialize_ast(ast->ast, script, buf);
901 }
902 }
903 break;
904 }
905 }
906
907 static void zend_file_cache_unserialize_op_array(zend_op_array *op_array,
908 zend_persistent_script *script,
909 void *buf)
910 {
911 if (op_array->static_variables && !IS_UNSERIALIZED(op_array->static_variables)) {
912 HashTable *ht;
913
914 UNSERIALIZE_PTR(op_array->static_variables);
915 ht = op_array->static_variables;
916 zend_file_cache_unserialize_hash(ht,
917 script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR);
918 }
919
920 if (op_array->literals && !IS_UNSERIALIZED(op_array->literals)) {
921 zval *p, *end;
922
923 UNSERIALIZE_PTR(op_array->literals);
924 p = op_array->literals;
925 end = p + op_array->last_literal;
926 while (p < end) {
927 zend_file_cache_unserialize_zval(p, script, buf);
928 p++;
929 }
930 }
931
932 if (!IS_UNSERIALIZED(op_array->opcodes)) {
933 zend_op *opline, *end;
934
935 UNSERIALIZE_PTR(op_array->opcodes);
936 opline = op_array->opcodes;
937 end = opline + op_array->last;
938 while (opline < end) {
939 # if ZEND_USE_ABS_CONST_ADDR
940 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
941 UNSERIALIZE_PTR(opline->op1.zv);
942 }
943 if (ZEND_OP2_TYPE(opline) == IS_CONST) {
944 UNSERIALIZE_PTR(opline->op2.zv);
945 }
946 # endif
947 # if ZEND_USE_ABS_JMP_ADDR
948 switch (opline->opcode) {
949 case ZEND_JMP:
950 case ZEND_FAST_CALL:
951 case ZEND_DECLARE_ANON_CLASS:
952 case ZEND_DECLARE_ANON_INHERITED_CLASS:
953 UNSERIALIZE_PTR(opline->op1.jmp_addr);
954 break;
955 case ZEND_JMPZNZ:
956
957
958 case ZEND_JMPZ:
959 case ZEND_JMPNZ:
960 case ZEND_JMPZ_EX:
961 case ZEND_JMPNZ_EX:
962 case ZEND_JMP_SET:
963 case ZEND_COALESCE:
964 case ZEND_NEW:
965 case ZEND_FE_RESET_R:
966 case ZEND_FE_RESET_RW:
967 case ZEND_ASSERT_CHECK:
968 UNSERIALIZE_PTR(opline->op2.jmp_addr);
969 break;
970 case ZEND_FE_FETCH_R:
971 case ZEND_FE_FETCH_RW:
972
973 break;
974 }
975 # endif
976 ZEND_VM_SET_OPCODE_HANDLER(opline);
977 opline++;
978 }
979
980 if (op_array->arg_info) {
981 zend_arg_info *p, *end;
982 UNSERIALIZE_PTR(op_array->arg_info);
983 p = op_array->arg_info;
984 end = p + op_array->num_args;
985 if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
986 p--;
987 }
988 if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
989 end++;
990 }
991 while (p < end) {
992 if (!IS_UNSERIALIZED(p->name)) {
993 UNSERIALIZE_STR(p->name);
994 }
995 if (!IS_UNSERIALIZED(p->class_name)) {
996 UNSERIALIZE_STR(p->class_name);
997 }
998 p++;
999 }
1000 }
1001
1002 if (op_array->vars) {
1003 zend_string **p, **end;
1004
1005 UNSERIALIZE_PTR(op_array->vars);
1006 p = op_array->vars;
1007 end = p + op_array->last_var;
1008 while (p < end) {
1009 if (!IS_UNSERIALIZED(*p)) {
1010 UNSERIALIZE_STR(*p);
1011 }
1012 p++;
1013 }
1014 }
1015
1016 UNSERIALIZE_STR(op_array->function_name);
1017 UNSERIALIZE_STR(op_array->filename);
1018 UNSERIALIZE_PTR(op_array->brk_cont_array);
1019 UNSERIALIZE_PTR(op_array->scope);
1020 UNSERIALIZE_STR(op_array->doc_comment);
1021 UNSERIALIZE_PTR(op_array->try_catch_array);
1022 UNSERIALIZE_PTR(op_array->prototype);
1023 }
1024 }
1025
1026 static void zend_file_cache_unserialize_func(zval *zv,
1027 zend_persistent_script *script,
1028 void *buf)
1029 {
1030 zend_op_array *op_array;
1031
1032 UNSERIALIZE_PTR(Z_PTR_P(zv));
1033 op_array = Z_PTR_P(zv);
1034 zend_file_cache_unserialize_op_array(op_array, script, buf);
1035 }
1036
1037 static void zend_file_cache_unserialize_prop_info(zval *zv,
1038 zend_persistent_script *script,
1039 void *buf)
1040 {
1041 if (!IS_UNSERIALIZED(Z_PTR_P(zv))) {
1042 zend_property_info *prop;
1043
1044 UNSERIALIZE_PTR(Z_PTR_P(zv));
1045 prop = Z_PTR_P(zv);
1046
1047 if (prop->ce && !IS_UNSERIALIZED(prop->ce)) {
1048 UNSERIALIZE_PTR(prop->ce);
1049 }
1050 if (prop->name && !IS_UNSERIALIZED(prop->name)) {
1051 UNSERIALIZE_STR(prop->name);
1052 }
1053 if (prop->doc_comment && !IS_UNSERIALIZED(prop->doc_comment)) {
1054 UNSERIALIZE_STR(prop->doc_comment);
1055 }
1056 }
1057 }
1058
1059 static void zend_file_cache_unserialize_class(zval *zv,
1060 zend_persistent_script *script,
1061 void *buf)
1062 {
1063 zend_class_entry *ce;
1064
1065 UNSERIALIZE_PTR(Z_PTR_P(zv));
1066 ce = Z_PTR_P(zv);
1067
1068 UNSERIALIZE_STR(ce->name);
1069 zend_file_cache_unserialize_hash(&ce->function_table,
1070 script, buf, zend_file_cache_unserialize_func, ZEND_FUNCTION_DTOR);
1071 if (ce->default_properties_table) {
1072 zval *p, *end;
1073
1074 UNSERIALIZE_PTR(ce->default_properties_table);
1075 p = ce->default_properties_table;
1076 end = p + ce->default_properties_count;
1077 while (p < end) {
1078 zend_file_cache_unserialize_zval(p, script, buf);
1079 p++;
1080 }
1081 }
1082 if (ce->default_static_members_table) {
1083 zval *p, *end;
1084
1085 UNSERIALIZE_PTR(ce->default_static_members_table);
1086 p = ce->default_static_members_table;
1087 end = p + ce->default_static_members_count;
1088 while (p < end) {
1089 zend_file_cache_unserialize_zval(p, script, buf);
1090 p++;
1091 }
1092 }
1093 zend_file_cache_unserialize_hash(&ce->constants_table,
1094 script, buf, zend_file_cache_unserialize_zval, NULL);
1095 UNSERIALIZE_STR(ZEND_CE_FILENAME(ce));
1096 UNSERIALIZE_STR(ZEND_CE_DOC_COMMENT(ce));
1097 zend_file_cache_unserialize_hash(&ce->properties_info,
1098 script, buf, zend_file_cache_unserialize_prop_info, ZVAL_PTR_DTOR);
1099
1100 if (ce->trait_aliases) {
1101 zend_trait_alias **p, *q;
1102
1103 UNSERIALIZE_PTR(ce->trait_aliases);
1104 p = ce->trait_aliases;
1105
1106 while (*p) {
1107 UNSERIALIZE_PTR(*p);
1108 q = *p;
1109
1110 if (q->trait_method) {
1111 zend_trait_method_reference *m;
1112
1113 UNSERIALIZE_PTR(q->trait_method);
1114 m = q->trait_method;
1115
1116 if (m->method_name) {
1117 UNSERIALIZE_STR(m->method_name);
1118 }
1119 if (m->class_name) {
1120 UNSERIALIZE_STR(m->class_name);
1121 }
1122 }
1123
1124 if (q->alias) {
1125 UNSERIALIZE_STR(q->alias);
1126 }
1127 p++;
1128 }
1129 }
1130
1131 if (ce->trait_precedences) {
1132 zend_trait_precedence **p, *q;
1133
1134 UNSERIALIZE_PTR(ce->trait_precedences);
1135 p = ce->trait_precedences;
1136
1137 while (*p) {
1138 UNSERIALIZE_PTR(*p);
1139 q = *p;
1140
1141 if (q->trait_method) {
1142 zend_trait_method_reference *m;
1143
1144 UNSERIALIZE_PTR(q->trait_method);
1145 m = q->trait_method;
1146
1147 if (m->method_name) {
1148 UNSERIALIZE_STR(m->method_name);
1149 }
1150 if (m->class_name) {
1151 UNSERIALIZE_STR(m->class_name);
1152 }
1153 }
1154
1155 if (q->exclude_from_classes) {
1156 zend_string **s;
1157
1158 UNSERIALIZE_PTR(q->exclude_from_classes);
1159 s = (zend_string**)q->exclude_from_classes;
1160
1161 while (*s) {
1162 UNSERIALIZE_STR(*s);
1163 s++;
1164 }
1165 }
1166 p++;
1167 }
1168 }
1169
1170 UNSERIALIZE_PTR(ce->parent);
1171 UNSERIALIZE_PTR(ce->constructor);
1172 UNSERIALIZE_PTR(ce->destructor);
1173 UNSERIALIZE_PTR(ce->clone);
1174 UNSERIALIZE_PTR(ce->__get);
1175 UNSERIALIZE_PTR(ce->__set);
1176 UNSERIALIZE_PTR(ce->__call);
1177 UNSERIALIZE_PTR(ce->serialize_func);
1178 UNSERIALIZE_PTR(ce->unserialize_func);
1179 UNSERIALIZE_PTR(ce->__isset);
1180 UNSERIALIZE_PTR(ce->__unset);
1181 UNSERIALIZE_PTR(ce->__tostring);
1182 UNSERIALIZE_PTR(ce->__callstatic);
1183 UNSERIALIZE_PTR(ce->__debugInfo);
1184
1185 if (UNEXPECTED((ce->ce_flags & ZEND_ACC_ANON_CLASS))) {
1186 ce->serialize = zend_class_serialize_deny;
1187 ce->unserialize = zend_class_unserialize_deny;
1188 }
1189 }
1190
1191 static void zend_file_cache_unserialize(zend_persistent_script *script,
1192 void *buf)
1193 {
1194 script->mem = buf;
1195
1196 UNSERIALIZE_STR(script->full_path);
1197
1198 zend_file_cache_unserialize_hash(&script->class_table,
1199 script, buf, zend_file_cache_unserialize_class, ZEND_CLASS_DTOR);
1200 zend_file_cache_unserialize_hash(&script->function_table,
1201 script, buf, zend_file_cache_unserialize_func, ZEND_FUNCTION_DTOR);
1202 zend_file_cache_unserialize_op_array(&script->main_op_array, script, buf);
1203
1204 UNSERIALIZE_PTR(script->arena_mem);
1205 }
1206
1207 zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handle)
1208 {
1209 zend_string *full_path = file_handle->opened_path;
1210 int fd;
1211 char *filename;
1212 zend_persistent_script *script;
1213 zend_file_cache_metainfo info;
1214 zend_accel_hash_entry *bucket;
1215 void *mem, *checkpoint, *buf;
1216 int cache_it = 1;
1217
1218 if (!full_path) {
1219 return NULL;
1220 }
1221 filename = zend_file_cache_get_bin_file_path(full_path);
1222
1223 fd = open(filename, O_RDONLY | O_BINARY);
1224 if (fd < 0) {
1225 efree(filename);
1226 return NULL;
1227 }
1228
1229 if (zend_file_cache_flock(fd, LOCK_SH) != 0) {
1230 close(fd);
1231 efree(filename);
1232 return NULL;
1233 }
1234
1235 if (read(fd, &info, sizeof(info)) != sizeof(info)) {
1236 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s'\n", filename);
1237 zend_file_cache_flock(fd, LOCK_UN);
1238 close(fd);
1239 unlink(filename);
1240 efree(filename);
1241 return NULL;
1242 }
1243
1244
1245 if (memcmp(info.magic, "OPCACHE", 8) != 0) {
1246 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong header)\n", filename);
1247 zend_file_cache_flock(fd, LOCK_UN);
1248 close(fd);
1249 unlink(filename);
1250 efree(filename);
1251 return NULL;
1252 }
1253 if (memcmp(info.system_id, ZCG(system_id), 32) != 0) {
1254 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong \"system_id\")\n", filename);
1255 zend_file_cache_flock(fd, LOCK_UN);
1256 close(fd);
1257 unlink(filename);
1258 efree(filename);
1259 return NULL;
1260 }
1261
1262
1263 if (ZCG(accel_directives).validate_timestamps &&
1264 zend_get_file_handle_timestamp(file_handle, NULL) != info.timestamp) {
1265 if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
1266 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
1267 }
1268 close(fd);
1269 unlink(filename);
1270 efree(filename);
1271 return NULL;
1272 }
1273
1274 checkpoint = zend_arena_checkpoint(CG(arena));
1275 #ifdef __SSE2__
1276
1277 mem = zend_arena_alloc(&CG(arena), info.mem_size + info.str_size + 64);
1278 mem = (void*)(((zend_uintptr_t)mem + 63L) & ~63L);
1279 #else
1280 mem = zend_arena_alloc(&CG(arena), info.mem_size + info.str_size);
1281 #endif
1282
1283 if (read(fd, mem, info.mem_size + info.str_size) != (ssize_t)(info.mem_size + info.str_size)) {
1284 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s'\n", filename);
1285 zend_file_cache_flock(fd, LOCK_UN);
1286 close(fd);
1287 unlink(filename);
1288 zend_arena_release(&CG(arena), checkpoint);
1289 efree(filename);
1290 return NULL;
1291 }
1292 if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
1293 zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
1294 }
1295 close(fd);
1296
1297
1298 if (ZCG(accel_directives).file_cache_consistency_checks &&
1299 zend_adler32(ADLER32_INIT, mem, info.mem_size + info.str_size) != info.checksum) {
1300 zend_accel_error(ACCEL_LOG_WARNING, "corrupted file '%s'\n", filename);
1301 unlink(filename);
1302 zend_arena_release(&CG(arena), checkpoint);
1303 efree(filename);
1304 return NULL;
1305 }
1306
1307 if (!ZCG(accel_directives).file_cache_only &&
1308 !ZCSG(restart_in_progress) &&
1309 accelerator_shm_read_lock() == SUCCESS) {
1310
1311 zend_shared_alloc_lock();
1312
1313
1314
1315
1316 bucket = zend_accel_hash_find_entry(&ZCSG(hash), full_path);
1317 if (bucket) {
1318 script = (zend_persistent_script *)bucket->data;
1319 if (!script->corrupted) {
1320 zend_shared_alloc_unlock();
1321 zend_arena_release(&CG(arena), checkpoint);
1322 efree(filename);
1323 return script;
1324 }
1325 }
1326
1327 if (zend_accel_hash_is_full(&ZCSG(hash))) {
1328 zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
1329 ZSMMG(memory_exhausted) = 1;
1330 zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
1331 zend_shared_alloc_unlock();
1332 goto use_process_mem;
1333 }
1334
1335 #ifdef __SSE2__
1336
1337 buf = zend_shared_alloc(info.mem_size + 64);
1338 buf = (void*)(((zend_uintptr_t)buf + 63L) & ~63L);
1339 #else
1340 buf = zend_shared_alloc(info.mem_size);
1341 #endif
1342
1343 if (!buf) {
1344 zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
1345 zend_shared_alloc_unlock();
1346 goto use_process_mem;
1347 }
1348 memcpy(buf, mem, info.mem_size);
1349 } else {
1350 use_process_mem:
1351 buf = mem;
1352 cache_it = 0;
1353 }
1354
1355 ZCG(mem) = ((char*)mem + info.mem_size);
1356 script = (zend_persistent_script*)((char*)buf + info.script_offset);
1357 script->corrupted = !cache_it;
1358 zend_file_cache_unserialize(script, buf);
1359 script->corrupted = 0;
1360
1361 if (cache_it) {
1362 script->dynamic_members.checksum = zend_accel_script_checksum(script);
1363 script->dynamic_members.last_used = ZCG(request_time);
1364
1365 zend_accel_hash_update(&ZCSG(hash), ZSTR_VAL(script->full_path), ZSTR_LEN(script->full_path), 0, script);
1366
1367 zend_shared_alloc_unlock();
1368 zend_arena_release(&CG(arena), checkpoint);
1369 }
1370 efree(filename);
1371
1372 return script;
1373 }
1374
1375 void zend_file_cache_invalidate(zend_string *full_path)
1376 {
1377 char *filename;
1378
1379 filename = zend_file_cache_get_bin_file_path(full_path);
1380
1381 unlink(filename);
1382 efree(filename);
1383 }
1384
1385 #endif