| | 3523 | static startup_func_t xc_last_ext_startup; |
| | 3524 | static int xc_zend_startup_last(zend_extension *extension) /* {{{ */ |
| | 3525 | { |
| | 3526 | zend_extension *ext = zend_get_extension(XCACHE_NAME); |
| | 3527 | if (ext) { |
| | 3528 | zend_error(E_WARNING, "Module '" XCACHE_NAME "' already loaded"); |
| | 3529 | } |
| | 3530 | /* restore */ |
| | 3531 | extension->startup = xc_last_ext_startup; |
| | 3532 | if (extension->startup) { |
| | 3533 | if (extension->startup(extension) != SUCCESS) { |
| | 3534 | return FAILURE; |
| | 3535 | } |
| | 3536 | } |
| | 3537 | assert(xc_llist_zend_extension); |
| | 3538 | xcache_llist_prepend(&zend_extensions, xc_llist_zend_extension); |
| | 3539 | return SUCCESS; |
| | 3540 | } |
| | 3541 | /* }}} */ |
| | 3542 | static int xc_zend_startup(zend_extension *extension) /* {{{ */ |
| | 3543 | { |
| | 3544 | if (!origin_compile_file) { |
| | 3545 | origin_compile_file = zend_compile_file; |
| | 3546 | zend_compile_file = xc_check_initial_compile_file; |
| | 3547 | } |
| | 3548 | |
| | 3549 | if (zend_llist_count(&zend_extensions) > 1) { |
| | 3550 | zend_llist_position lpos; |
| | 3551 | zend_extension *ext; |
| | 3552 | |
| | 3553 | xc_llist_zend_extension = xcache_llist_get_element_by_zend_extension(&zend_extensions, XCACHE_NAME); |
| | 3554 | if (xc_llist_zend_extension != zend_extensions.head) { |
| | 3555 | zend_error(E_WARNING, "XCache failed to load itself as the first zend_extension. compatibility downgraded"); |
| | 3556 | } |
| | 3557 | /* hide myself */ |
| | 3558 | xcache_llist_unlink(&zend_extensions, xc_llist_zend_extension); |
| | 3559 | |
| | 3560 | ext = (zend_extension *) zend_llist_get_last_ex(&zend_extensions, &lpos); |
| | 3561 | assert(ext && ext != (zend_extension *) xc_llist_zend_extension->data); |
| | 3562 | xc_last_ext_startup = ext->startup; |
| | 3563 | ext->startup = xc_zend_startup_last; |
| | 3564 | } |
| | 3565 | return SUCCESS; |
| | 3566 | } |
| | 3567 | /* }}} */ |
| | 3568 | static void xc_zend_shutdown(zend_extension *extension) /* {{{ */ |
| | 3569 | { |
| | 3570 | } |
| | 3571 | /* }}} */ |
| | 3572 | /* {{{ zend extension definition structure */ |
| | 3573 | static zend_extension zend_extension_entry = { |
| | 3574 | XCACHE_NAME, |
| | 3575 | XCACHE_VERSION, |
| | 3576 | XCACHE_AUTHOR, |
| | 3577 | XCACHE_URL, |
| | 3578 | XCACHE_COPYRIGHT, |
| | 3579 | xc_zend_startup, |
| | 3580 | xc_zend_shutdown, |
| | 3581 | NULL, /* activate_func_t */ |
| | 3582 | NULL, /* deactivate_func_t */ |
| | 3583 | NULL, /* message_handler_func_t */ |
| | 3584 | NULL, /* op_array_handler_func_t */ |
| | 3585 | NULL, /* statement_handler_func_t */ |
| | 3586 | NULL, /* fcall_begin_handler_func_t */ |
| | 3587 | NULL, /* fcall_end_handler_func_t */ |
| | 3588 | NULL, /* op_array_ctor_func_t */ |
| | 3589 | NULL, /* op_array_dtor_func_t */ |
| | 3590 | STANDARD_ZEND_EXTENSION_PROPERTIES |
| | 3591 | }; |
| | 3592 | /* }}} */ |
| | 3593 | |
| 3550 | | |
| 3551 | | static PHP_INI_MH(xc_OnUpdateDummy) |
| 3552 | | { |
| 3553 | | return SUCCESS; |
| 3554 | | } |
| 3555 | | |
| 3556 | | static PHP_INI_MH(xc_OnUpdateULong) |
| 3557 | | { |
| 3558 | | zend_ulong *p = (zend_ulong *) mh_arg1; |
| 3559 | | |
| 3560 | | *p = (zend_ulong) atoi(new_value); |
| 3561 | | return SUCCESS; |
| 3562 | | } |
| 3563 | | |
| 3564 | | static PHP_INI_MH(xc_OnUpdateBool) |
| 3565 | | { |
| 3566 | | zend_bool *p = (zend_bool *)mh_arg1; |
| 3567 | | |
| 3568 | | if (strncasecmp("on", new_value, sizeof("on"))) { |
| 3569 | | *p = (zend_bool) atoi(new_value); |
| 3570 | | } |
| 3571 | | else { |
| 3572 | | *p = (zend_bool) 1; |
| 3573 | | } |
| 3574 | | return SUCCESS; |
| 3575 | | } |
| 3576 | | |
| 3577 | | static PHP_INI_MH(xc_OnUpdateString) |
| 3578 | | { |
| 3579 | | char **p = (char**)mh_arg1; |
| 3580 | | if (*p) { |
| 3581 | | pefree(*p, 1); |
| 3582 | | } |
| 3583 | | *p = pemalloc(strlen(new_value) + 1, 1); |
| 3584 | | strcpy(*p, new_value); |
| 3585 | | return SUCCESS; |
| 3586 | | } |
| 3587 | | |
| 3588 | | #ifndef ZEND_ENGINE_2 |
| 3589 | | #define OnUpdateLong OnUpdateInt |
| 3590 | | #endif |
| 3591 | | |
| 3598 | | PHP_INI_ENTRY1 ("xcache.mmap_path", DEFAULT_PATH, PHP_INI_SYSTEM, xc_OnUpdateString, &xc_mmap_path) |
| 3599 | | PHP_INI_ENTRY1 ("xcache.coredump_directory", "", PHP_INI_SYSTEM, xc_OnUpdateString, &xc_coredump_dir) |
| 3600 | | PHP_INI_ENTRY1 ("xcache.disable_on_crash", "0", PHP_INI_SYSTEM, xc_OnUpdateBool, &xc_disable_on_crash) |
| 3601 | | PHP_INI_ENTRY1 ("xcache.test", "0", PHP_INI_SYSTEM, xc_OnUpdateBool, &xc_test) |
| 3602 | | PHP_INI_ENTRY1 ("xcache.readonly_protection", "0", PHP_INI_SYSTEM, xc_OnUpdateBool, &xc_readonly_protection) |
| | 3601 | PHP_INI_ENTRY1 ("xcache.mmap_path", DEFAULT_PATH, PHP_INI_SYSTEM, xcache_OnUpdateString, &xc_mmap_path) |
| | 3602 | PHP_INI_ENTRY1 ("xcache.coredump_directory", "", PHP_INI_SYSTEM, xcache_OnUpdateString, &xc_coredump_dir) |
| | 3603 | PHP_INI_ENTRY1 ("xcache.disable_on_crash", "0", PHP_INI_SYSTEM, xcache_OnUpdateBool, &xc_disable_on_crash) |
| | 3604 | PHP_INI_ENTRY1 ("xcache.test", "0", PHP_INI_SYSTEM, xcache_OnUpdateBool, &xc_test) |
| | 3605 | PHP_INI_ENTRY1 ("xcache.readonly_protection", "0", PHP_INI_SYSTEM, xcache_OnUpdateBool, &xc_readonly_protection) |
| 3604 | | PHP_INI_ENTRY1 ("xcache.size", "0", PHP_INI_SYSTEM, xc_OnUpdateDummy, NULL) |
| 3605 | | PHP_INI_ENTRY1 ("xcache.count", "1", PHP_INI_SYSTEM, xc_OnUpdateDummy, NULL) |
| 3606 | | PHP_INI_ENTRY1 ("xcache.slots", "8K", PHP_INI_SYSTEM, xc_OnUpdateDummy, NULL) |
| 3607 | | PHP_INI_ENTRY1 ("xcache.shm_scheme", "mmap", PHP_INI_SYSTEM, xc_OnUpdateString, &xc_shm_scheme) |
| 3608 | | PHP_INI_ENTRY1 ("xcache.ttl", "0", PHP_INI_SYSTEM, xc_OnUpdateULong, &xc_php_ttl) |
| 3609 | | PHP_INI_ENTRY1 ("xcache.gc_interval", "0", PHP_INI_SYSTEM, xc_OnUpdateULong, &xc_php_gc_interval) |
| | 3607 | PHP_INI_ENTRY1 ("xcache.size", "0", PHP_INI_SYSTEM, xcache_OnUpdateDummy, NULL) |
| | 3608 | PHP_INI_ENTRY1 ("xcache.count", "1", PHP_INI_SYSTEM, xcache_OnUpdateDummy, NULL) |
| | 3609 | PHP_INI_ENTRY1 ("xcache.slots", "8K", PHP_INI_SYSTEM, xcache_OnUpdateDummy, NULL) |
| | 3610 | PHP_INI_ENTRY1 ("xcache.shm_scheme", "mmap", PHP_INI_SYSTEM, xcache_OnUpdateString, &xc_shm_scheme) |
| | 3611 | PHP_INI_ENTRY1 ("xcache.ttl", "0", PHP_INI_SYSTEM, xcache_OnUpdateULong, &xc_php_ttl) |
| | 3612 | PHP_INI_ENTRY1 ("xcache.gc_interval", "0", PHP_INI_SYSTEM, xcache_OnUpdateULong, &xc_php_gc_interval) |
| 3611 | | PHP_INI_ENTRY1 ("xcache.var_size", "0", PHP_INI_SYSTEM, xc_OnUpdateDummy, NULL) |
| 3612 | | PHP_INI_ENTRY1 ("xcache.var_count", "1", PHP_INI_SYSTEM, xc_OnUpdateDummy, NULL) |
| 3613 | | PHP_INI_ENTRY1 ("xcache.var_slots", "8K", PHP_INI_SYSTEM, xc_OnUpdateDummy, NULL) |
| 3614 | | PHP_INI_ENTRY1 ("xcache.var_maxttl", "0", PHP_INI_SYSTEM, xc_OnUpdateULong, &xc_var_maxttl) |
| 3615 | | PHP_INI_ENTRY1 ("xcache.var_gc_interval", "120", PHP_INI_SYSTEM, xc_OnUpdateULong, &xc_var_gc_interval) |
| | 3614 | PHP_INI_ENTRY1 ("xcache.var_size", "0", PHP_INI_SYSTEM, xcache_OnUpdateDummy, NULL) |
| | 3615 | PHP_INI_ENTRY1 ("xcache.var_count", "1", PHP_INI_SYSTEM, xcache_OnUpdateDummy, NULL) |
| | 3616 | PHP_INI_ENTRY1 ("xcache.var_slots", "8K", PHP_INI_SYSTEM, xcache_OnUpdateDummy, NULL) |
| | 3617 | PHP_INI_ENTRY1 ("xcache.var_maxttl", "0", PHP_INI_SYSTEM, xcache_OnUpdateULong, &xc_var_maxttl) |
| | 3618 | PHP_INI_ENTRY1 ("xcache.var_gc_interval", "120", PHP_INI_SYSTEM, xcache_OnUpdateULong, &xc_var_gc_interval) |
| 3704 | | } |
| 3705 | | /* }}} */ |
| 3706 | | /* {{{ extension startup */ |
| 3707 | | static void xc_zend_extension_register(zend_extension *new_extension, DL_HANDLE handle) |
| 3708 | | { |
| 3709 | | zend_extension extension; |
| 3710 | | |
| 3711 | | extension = *new_extension; |
| 3712 | | extension.handle = handle; |
| 3713 | | |
| 3714 | | zend_extension_dispatch_message(ZEND_EXTMSG_NEW_EXTENSION, &extension); |
| 3715 | | |
| 3716 | | zend_llist_prepend_element(&zend_extensions, &extension); |
| 3717 | | TRACE("%s", "registered"); |
| 3718 | | } |
| 3719 | | |
| 3720 | | static zend_llist_element *xc_llist_get_element_by_zend_extension(zend_llist *l, const char *extension_name) |
| 3721 | | { |
| 3722 | | zend_llist_element *element; |
| 3723 | | |
| 3724 | | for (element = zend_extensions.head; element; element = element->next) { |
| 3725 | | zend_extension *extension = (zend_extension *) element->data; |
| 3726 | | |
| 3727 | | if (!strcmp(extension->name, extension_name)) { |
| 3728 | | return element; |
| 3729 | | } |
| 3730 | | } |
| 3731 | | return NULL; |
| 3732 | | } |
| 3733 | | |
| 3734 | | static void xc_llist_prepend(zend_llist *l, zend_llist_element *element) |
| 3735 | | { |
| 3736 | | element->next = l->head; |
| 3737 | | element->prev = NULL; |
| 3738 | | if (l->head) { |
| 3739 | | l->head->prev = element; |
| 3740 | | } |
| 3741 | | else { |
| 3742 | | l->tail = element; |
| 3743 | | } |
| 3744 | | l->head = element; |
| 3745 | | ++l->count; |
| 3746 | | } |
| 3747 | | |
| 3748 | | static void xc_llist_unlink(zend_llist *l, zend_llist_element *element) |
| 3749 | | { |
| 3750 | | if ((element)->prev) { |
| 3751 | | (element)->prev->next = (element)->next; |
| 3752 | | } |
| 3753 | | else { |
| 3754 | | (l)->head = (element)->next; |
| 3755 | | } |
| 3756 | | |
| 3757 | | if ((element)->next) { |
| 3758 | | (element)->next->prev = (element)->prev; |
| 3759 | | } |
| 3760 | | else { |
| 3761 | | (l)->tail = (element)->prev; |
| 3762 | | } |
| 3763 | | |
| 3764 | | --l->count; |
| 3765 | | } |
| 3766 | | |
| 3767 | | static int xc_zend_extension_startup(zend_extension *extension) |
| 3768 | | { |
| 3769 | | if (extension->startup) { |
| 3770 | | if (extension->startup(extension) != SUCCESS) { |
| 3771 | | return FAILURE; |
| 3772 | | } |
| 3773 | | } |
| 3774 | | return SUCCESS; |
| 3775 | | } |
| 3776 | | /* }}} */ |
| 3777 | | static int xc_ptr_compare_func(void *p1, void *p2) /* {{{ */ |
| 3778 | | { |
| 3779 | | return p1 == p2; |
| 3780 | | } |
| 3781 | | /* }}} */ |
| 3782 | | static int xc_zend_remove_extension(zend_extension *extension) /* {{{ */ |
| 3783 | | { |
| 3784 | | llist_dtor_func_t dtor; |
| 3785 | | |
| 3786 | | assert(extension); |
| 3787 | | dtor = zend_extensions.dtor; /* avoid dtor */ |
| 3788 | | zend_extensions.dtor = NULL; |
| 3789 | | zend_llist_del_element(&zend_extensions, extension, xc_ptr_compare_func); |
| 3790 | | zend_extensions.dtor = dtor; |
| 3791 | | return SUCCESS; |
| 4061 | | static startup_func_t xc_last_ext_startup; |
| 4062 | | static int xc_zend_startup_last(zend_extension *extension) /* {{{ */ |
| 4063 | | { |
| 4064 | | zend_extension *ext = zend_get_extension(XCACHE_NAME); |
| 4065 | | if (ext) { |
| 4066 | | zend_error(E_WARNING, "Module '" XCACHE_NAME "' already loaded"); |
| 4067 | | } |
| 4068 | | /* restore */ |
| 4069 | | extension->startup = xc_last_ext_startup; |
| 4070 | | if (extension->startup) { |
| 4071 | | if (extension->startup(extension) != SUCCESS) { |
| 4072 | | return FAILURE; |
| 4073 | | } |
| 4074 | | } |
| 4075 | | assert(xc_llist_zend_extension); |
| 4076 | | xc_llist_prepend(&zend_extensions, xc_llist_zend_extension); |
| 4077 | | if (!xc_module_gotup) { |
| 4078 | | return zend_startup_module(&xcache_module_entry); |
| 4079 | | } |
| 4080 | | return SUCCESS; |
| 4081 | | } |
| 4082 | | /* }}} */ |
| 4083 | | ZEND_DLEXPORT int xcache_zend_startup(zend_extension *extension) /* {{{ */ |
| 4084 | | { |
| 4085 | | xc_zend_extension_gotup = 1; |
| 4086 | | |
| 4087 | | if (!origin_compile_file) { |
| 4088 | | origin_compile_file = zend_compile_file; |
| 4089 | | zend_compile_file = xc_check_initial_compile_file; |
| 4090 | | } |
| 4091 | | |
| 4092 | | if (zend_llist_count(&zend_extensions) > 1) { |
| 4093 | | zend_llist_position lpos; |
| 4094 | | zend_extension *ext; |
| 4095 | | |
| 4096 | | xc_llist_zend_extension = xc_llist_get_element_by_zend_extension(&zend_extensions, XCACHE_NAME); |
| 4097 | | if (xc_llist_zend_extension != zend_extensions.head) { |
| 4098 | | zend_error(E_WARNING, "XCache must be loaded as the first zend_extension for maximum compatibility"); |
| 4099 | | } |
| 4100 | | /* hide myself */ |
| 4101 | | xc_llist_unlink(&zend_extensions, xc_llist_zend_extension); |
| 4102 | | |
| 4103 | | ext = (zend_extension *) zend_llist_get_last_ex(&zend_extensions, &lpos); |
| 4104 | | assert(ext && ext != (zend_extension *) xc_llist_zend_extension->data); |
| 4105 | | xc_last_ext_startup = ext->startup; |
| 4106 | | ext->startup = xc_zend_startup_last; |
| 4107 | | } |
| 4108 | | else if (!xc_module_gotup) { |
| 4109 | | return zend_startup_module(&xcache_module_entry); |
| 4110 | | } |
| 4111 | | return SUCCESS; |
| 4112 | | } |
| 4113 | | /* }}} */ |
| 4114 | | ZEND_DLEXPORT void xcache_zend_shutdown(zend_extension *extension) /* {{{ */ |
| 4115 | | { |
| 4116 | | /* empty */ |
| 4117 | | } |
| 4118 | | /* }}} */ |
| 4119 | | ZEND_DLEXPORT void xcache_statement_handler(zend_op_array *op_array) /* {{{ */ |
| 4120 | | { |
| 4121 | | #ifdef HAVE_XCACHE_COVERAGER |
| 4122 | | xc_coverager_handle_ext_stmt(op_array, ZEND_EXT_STMT); |
| 4123 | | #endif |
| 4124 | | } |
| 4125 | | /* }}} */ |
| 4126 | | ZEND_DLEXPORT void xcache_fcall_begin_handler(zend_op_array *op_array) /* {{{ */ |
| 4127 | | { |
| 4128 | | #if 0 |
| 4129 | | xc_coverager_handle_ext_stmt(op_array, ZEND_EXT_FCALL_BEGIN); |
| 4130 | | #endif |
| 4131 | | } |
| 4132 | | /* }}} */ |
| 4133 | | ZEND_DLEXPORT void xcache_fcall_end_handler(zend_op_array *op_array) /* {{{ */ |
| 4134 | | { |
| 4135 | | #if 0 |
| 4136 | | xc_coverager_handle_ext_stmt(op_array, ZEND_EXT_FCALL_END); |
| 4137 | | #endif |
| 4138 | | } |
| 4139 | | /* }}} */ |
| 4140 | | /* {{{ zend extension definition structure */ |
| 4141 | | ZEND_DLEXPORT zend_extension zend_extension_entry = { |
| 4142 | | XCACHE_NAME, |
| 4143 | | XCACHE_VERSION, |
| 4144 | | XCACHE_AUTHOR, |
| 4145 | | XCACHE_URL, |
| 4146 | | XCACHE_COPYRIGHT, |
| 4147 | | xcache_zend_startup, |
| 4148 | | xcache_zend_shutdown, |
| 4149 | | NULL, /* activate_func_t */ |
| 4150 | | NULL, /* deactivate_func_t */ |
| 4151 | | NULL, /* message_handler_func_t */ |
| 4152 | | #ifdef HAVE_XCACHE_OPTIMIZER |
| 4153 | | xc_optimizer_op_array_handler, |
| 4154 | | #else |
| 4155 | | NULL, /* op_array_handler_func_t */ |
| 4156 | | #endif |
| 4157 | | xcache_statement_handler, |
| 4158 | | xcache_fcall_begin_handler, |
| 4159 | | xcache_fcall_end_handler, |
| 4160 | | NULL, /* op_array_ctor_func_t */ |
| 4161 | | NULL, /* op_array_dtor_func_t */ |
| 4162 | | STANDARD_ZEND_EXTENSION_PROPERTIES |
| 4163 | | }; |
| 4164 | | |
| 4165 | | #ifndef ZEND_EXT_API |
| 4166 | | # define ZEND_EXT_API ZEND_DLEXPORT |
| 4167 | | #endif |
| 4168 | | #if COMPILE_DL_XCACHE |
| 4169 | | ZEND_EXTENSION(); |
| 4170 | | #endif |
| 4171 | | /* }}} */ |