root/Zend/zend_extensions.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zend_load_extension
  2. zend_register_extension
  3. zend_extension_shutdown
  4. zend_extension_startup
  5. zend_startup_extensions_mechanism
  6. zend_startup_extensions
  7. zend_shutdown_extensions
  8. zend_extension_dtor
  9. zend_extension_message_dispatcher
  10. zend_extension_dispatch_message
  11. zend_get_resource_handle
  12. zend_get_extension
  13. zend_extension_op_array_persist_calc_handler
  14. zend_extension_op_array_persist_handler
  15. zend_extensions_op_array_persist_calc
  16. zend_extensions_op_array_persist

   1 /*
   2    +----------------------------------------------------------------------+
   3    | Zend Engine                                                          |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt.                                |
  11    | If you did not receive a copy of the Zend license and are unable to  |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@zend.com so we can mail you a copy immediately.              |
  14    +----------------------------------------------------------------------+
  15    | Authors: Andi Gutmans <andi@zend.com>                                |
  16    |          Zeev Suraski <zeev@zend.com>                                |
  17    +----------------------------------------------------------------------+
  18 */
  19 
  20 /* $Id$ */
  21 
  22 #include "zend_extensions.h"
  23 
  24 ZEND_API zend_llist zend_extensions;
  25 ZEND_API uint32_t zend_extension_flags = 0;
  26 static int last_resource_number;
  27 
  28 int zend_load_extension(const char *path)
  29 {
  30 #if ZEND_EXTENSIONS_SUPPORT
  31         DL_HANDLE handle;
  32         zend_extension *new_extension;
  33         zend_extension_version_info *extension_version_info;
  34 
  35         handle = DL_LOAD(path);
  36         if (!handle) {
  37 #ifndef ZEND_WIN32
  38                 fprintf(stderr, "Failed loading %s:  %s\n", path, DL_ERROR());
  39 #else
  40                 fprintf(stderr, "Failed loading %s\n", path);
  41                 /* See http://support.microsoft.com/kb/190351 */
  42                 fflush(stderr);
  43 #endif
  44                 return FAILURE;
  45         }
  46 
  47         extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "extension_version_info");
  48         if (!extension_version_info) {
  49                 extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "_extension_version_info");
  50         }
  51         new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "zend_extension_entry");
  52         if (!new_extension) {
  53                 new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "_zend_extension_entry");
  54         }
  55         if (!extension_version_info || !new_extension) {
  56                 fprintf(stderr, "%s doesn't appear to be a valid Zend extension\n", path);
  57 /* See http://support.microsoft.com/kb/190351 */
  58 #ifdef ZEND_WIN32
  59                 fflush(stderr);
  60 #endif
  61                 DL_UNLOAD(handle);
  62                 return FAILURE;
  63         }
  64 
  65 
  66         /* allow extension to proclaim compatibility with any Zend version */
  67         if (extension_version_info->zend_extension_api_no != ZEND_EXTENSION_API_NO &&(!new_extension->api_no_check || new_extension->api_no_check(ZEND_EXTENSION_API_NO) != SUCCESS)) {
  68                 if (extension_version_info->zend_extension_api_no > ZEND_EXTENSION_API_NO) {
  69                         fprintf(stderr, "%s requires Zend Engine API version %d.\n"
  70                                         "The Zend Engine API version %d which is installed, is outdated.\n\n",
  71                                         new_extension->name,
  72                                         extension_version_info->zend_extension_api_no,
  73                                         ZEND_EXTENSION_API_NO);
  74 /* See http://support.microsoft.com/kb/190351 */
  75 #ifdef ZEND_WIN32
  76                         fflush(stderr);
  77 #endif
  78                         DL_UNLOAD(handle);
  79                         return FAILURE;
  80                 } else if (extension_version_info->zend_extension_api_no < ZEND_EXTENSION_API_NO) {
  81                         fprintf(stderr, "%s requires Zend Engine API version %d.\n"
  82                                         "The Zend Engine API version %d which is installed, is newer.\n"
  83                                         "Contact %s at %s for a later version of %s.\n\n",
  84                                         new_extension->name,
  85                                         extension_version_info->zend_extension_api_no,
  86                                         ZEND_EXTENSION_API_NO,
  87                                         new_extension->author,
  88                                         new_extension->URL,
  89                                         new_extension->name);
  90 /* See http://support.microsoft.com/kb/190351 */
  91 #ifdef ZEND_WIN32
  92                         fflush(stderr);
  93 #endif
  94                         DL_UNLOAD(handle);
  95                         return FAILURE;
  96                 }
  97         } else if (strcmp(ZEND_EXTENSION_BUILD_ID, extension_version_info->build_id) &&
  98                    (!new_extension->build_id_check || new_extension->build_id_check(ZEND_EXTENSION_BUILD_ID) != SUCCESS)) {
  99                 fprintf(stderr, "Cannot load %s - it was built with configuration %s, whereas running engine is %s\n",
 100                                         new_extension->name, extension_version_info->build_id, ZEND_EXTENSION_BUILD_ID);
 101 /* See http://support.microsoft.com/kb/190351 */
 102 #ifdef ZEND_WIN32
 103                 fflush(stderr);
 104 #endif
 105                 DL_UNLOAD(handle);
 106                 return FAILURE;
 107         } else if (zend_get_extension(new_extension->name)) {
 108                 fprintf(stderr, "Cannot load %s - it was already loaded\n", new_extension->name);
 109 /* See http://support.microsoft.com/kb/190351 */
 110 #ifdef ZEND_WIN32
 111                 fflush(stderr);
 112 #endif
 113                 DL_UNLOAD(handle);
 114                 return FAILURE;
 115         } else if (zend_get_extension(new_extension->name)) {
 116                 fprintf(stderr, "Cannot load %s - extension already loaded\n", new_extension->name);
 117 /* See http://support.microsoft.com/kb/190351 */
 118 #ifdef PHP_WIN32
 119                 fflush(stderr);
 120 #endif
 121                 DL_UNLOAD(handle);
 122                 return FAILURE;
 123         }
 124 
 125         return zend_register_extension(new_extension, handle);
 126 #else
 127         fprintf(stderr, "Extensions are not supported on this platform.\n");
 128 /* See http://support.microsoft.com/kb/190351 */
 129 #ifdef ZEND_WIN32
 130         fflush(stderr);
 131 #endif
 132         return FAILURE;
 133 #endif
 134 }
 135 
 136 
 137 int zend_register_extension(zend_extension *new_extension, DL_HANDLE handle)
 138 {
 139 #if ZEND_EXTENSIONS_SUPPORT
 140         zend_extension extension;
 141 
 142         extension = *new_extension;
 143         extension.handle = handle;
 144 
 145         zend_extension_dispatch_message(ZEND_EXTMSG_NEW_EXTENSION, &extension);
 146 
 147         zend_llist_add_element(&zend_extensions, &extension);
 148 
 149         if (extension.op_array_ctor) {
 150                 zend_extension_flags |= ZEND_EXTENSIONS_HAVE_OP_ARRAY_CTOR;
 151         }
 152         if (extension.op_array_dtor) {
 153                 zend_extension_flags |= ZEND_EXTENSIONS_HAVE_OP_ARRAY_DTOR;
 154         }
 155         if (extension.op_array_handler) {
 156                 zend_extension_flags |= ZEND_EXTENSIONS_HAVE_OP_ARRAY_HANDLER;
 157         }
 158         if (extension.op_array_persist_calc) {
 159                 zend_extension_flags |= ZEND_EXTENSIONS_HAVE_OP_ARRAY_PERSIST_CALC;
 160         }
 161         if (extension.op_array_persist) {
 162                 zend_extension_flags |= ZEND_EXTENSIONS_HAVE_OP_ARRAY_PERSIST;
 163         }
 164         /*fprintf(stderr, "Loaded %s, version %s\n", extension.name, extension.version);*/
 165 #endif
 166 
 167         return SUCCESS;
 168 }
 169 
 170 
 171 static void zend_extension_shutdown(zend_extension *extension)
 172 {
 173 #if ZEND_EXTENSIONS_SUPPORT
 174         if (extension->shutdown) {
 175                 extension->shutdown(extension);
 176         }
 177 #endif
 178 }
 179 
 180 static int zend_extension_startup(zend_extension *extension)
 181 {
 182 #if ZEND_EXTENSIONS_SUPPORT
 183         if (extension->startup) {
 184                 if (extension->startup(extension)!=SUCCESS) {
 185                         return 1;
 186                 }
 187                 zend_append_version_info(extension);
 188         }
 189 #endif
 190         return 0;
 191 }
 192 
 193 
 194 int zend_startup_extensions_mechanism()
 195 {
 196         /* Startup extensions mechanism */
 197         zend_llist_init(&zend_extensions, sizeof(zend_extension), (void (*)(void *)) zend_extension_dtor, 1);
 198         last_resource_number = 0;
 199         return SUCCESS;
 200 }
 201 
 202 
 203 int zend_startup_extensions()
 204 {
 205         zend_llist_apply_with_del(&zend_extensions, (int (*)(void *)) zend_extension_startup);
 206         return SUCCESS;
 207 }
 208 
 209 
 210 void zend_shutdown_extensions(void)
 211 {
 212         zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_shutdown);
 213         zend_llist_destroy(&zend_extensions);
 214 }
 215 
 216 
 217 void zend_extension_dtor(zend_extension *extension)
 218 {
 219 #if ZEND_EXTENSIONS_SUPPORT && !ZEND_DEBUG
 220         if (extension->handle && !getenv("ZEND_DONT_UNLOAD_MODULES")) {
 221                 DL_UNLOAD(extension->handle);
 222         }
 223 #endif
 224 }
 225 
 226 
 227 static void zend_extension_message_dispatcher(const zend_extension *extension, int num_args, va_list args)
 228 {
 229         int message;
 230         void *arg;
 231 
 232         if (!extension->message_handler || num_args!=2) {
 233                 return;
 234         }
 235         message = va_arg(args, int);
 236         arg = va_arg(args, void *);
 237         extension->message_handler(message, arg);
 238 }
 239 
 240 
 241 ZEND_API void zend_extension_dispatch_message(int message, void *arg)
 242 {
 243         zend_llist_apply_with_arguments(&zend_extensions, (llist_apply_with_args_func_t) zend_extension_message_dispatcher, 2, message, arg);
 244 }
 245 
 246 
 247 ZEND_API int zend_get_resource_handle(zend_extension *extension)
 248 {
 249         if (last_resource_number<ZEND_MAX_RESERVED_RESOURCES) {
 250                 extension->resource_number = last_resource_number;
 251                 return last_resource_number++;
 252         } else {
 253                 return -1;
 254         }
 255 }
 256 
 257 
 258 ZEND_API zend_extension *zend_get_extension(const char *extension_name)
 259 {
 260         zend_llist_element *element;
 261 
 262         for (element = zend_extensions.head; element; element = element->next) {
 263                 zend_extension *extension = (zend_extension *) element->data;
 264 
 265                 if (!strcmp(extension->name, extension_name)) {
 266                         return extension;
 267                 }
 268         }
 269         return NULL;
 270 }
 271 
 272 typedef struct _zend_extension_persist_data {
 273         zend_op_array *op_array;
 274         size_t         size;
 275         char          *mem;
 276 } zend_extension_persist_data;
 277 
 278 static void zend_extension_op_array_persist_calc_handler(zend_extension *extension, zend_extension_persist_data *data)
 279 {
 280         if (extension->op_array_persist_calc) {
 281                 data->size += extension->op_array_persist_calc(data->op_array);
 282         }
 283 }
 284 
 285 static void zend_extension_op_array_persist_handler(zend_extension *extension, zend_extension_persist_data *data)
 286 {
 287         if (extension->op_array_persist) {
 288                 size_t size = extension->op_array_persist(data->op_array, data->mem);
 289                 if (size) {
 290                         data->mem = (void*)((char*)data->mem + size);
 291                         data->size += size;
 292                 }
 293         }
 294 }
 295 
 296 ZEND_API size_t zend_extensions_op_array_persist_calc(zend_op_array *op_array)
 297 {
 298         if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_PERSIST_CALC) {
 299                 zend_extension_persist_data data;
 300 
 301                 data.op_array = op_array;
 302                 data.size = 0;
 303                 data.mem  = NULL;
 304                 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_persist_calc_handler, &data);
 305                 return data.size;
 306         }
 307         return 0;
 308 }
 309 
 310 ZEND_API size_t zend_extensions_op_array_persist(zend_op_array *op_array, void *mem)
 311 {
 312         if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_PERSIST) {
 313                 zend_extension_persist_data data;
 314 
 315                 data.op_array = op_array;
 316                 data.size = 0;
 317                 data.mem  = mem;
 318                 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_persist_handler, &data);
 319                 return data.size;
 320         }
 321         return 0;
 322 }
 323 
 324 /*
 325  * Local variables:
 326  * tab-width: 4
 327  * c-basic-offset: 4
 328  * indent-tabs-mode: t
 329  * End:
 330  */

/* [<][>][^][v][top][bottom][index][help] */