source: eaccelerator/trunk/eaccelerator.c @ 267

Revision 267, 75.9 KB checked in by hans, 4 years ago (diff)

Skip disk cache creation and clean/clear actions when operating in shm_only mode. This fixes ticket #165

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2   +----------------------------------------------------------------------+
3   | eAccelerator project                                                 |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 2004 - 2006 eAccelerator                               |
6   | http://eaccelerator.net                                                                                      |
7   +----------------------------------------------------------------------+
8   | This program is free software; you can redistribute it and/or        |
9   | modify it under the terms of the GNU General Public License          |
10   | as published by the Free Software Foundation; either version 2       |
11   | of the License, or (at your option) any later version.               |
12   |                                                                      |
13   | This program is distributed in the hope that it will be useful,      |
14   | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
15   | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
16   | GNU General Public License for more details.                         |
17   |                                                                      |
18   | You should have received a copy of the GNU General Public License    |
19   | along with this program; if not, write to the Free Software          |
20   | Foundation, Inc., 59 Temple Place - Suite 330, Boston,               |
21   | MA  02111-1307, USA.                                                 |
22   |                                                                      |
23   | A copy is availble at http://www.gnu.org/copyleft/gpl.txt            |
24   +----------------------------------------------------------------------+
25   $Id$
26*/
27
28#include "eaccelerator.h"
29#include "eaccelerator_version.h"
30
31#ifdef HAVE_EACCELERATOR
32
33#include "opcodes.h"
34
35#include "zend.h"
36#include "zend_API.h"
37#include "zend_extensions.h"
38
39#include "debug.h"
40#include "shm.h"
41#include "session.h"
42#include "content.h"
43#include "cache.h"
44#include "ea_store.h"
45#include "ea_restore.h"
46#include "ea_info.h"
47#include "ea_dasm.h"
48
49#include <sys/types.h>
50#include <sys/stat.h>
51#ifdef ZEND_WIN32
52#  include "win32/time.h"
53#  include <time.h>
54#  include <sys/utime.h>
55#else
56#  include <sys/file.h>
57#  include <sys/time.h>
58#  include <utime.h>
59#endif
60#include <fcntl.h>
61
62#ifndef O_BINARY
63#  define O_BINARY 0
64#endif
65
66#include "php.h"
67#include "php_ini.h"
68#include "php_logos.h"
69#include "main/fopen_wrappers.h"
70#include "ext/standard/info.h"
71#include "ext/standard/php_incomplete_class.h"
72#include "ext/standard/md5.h"
73
74#include "SAPI.h"
75
76#define MAX_DUP_STR_LEN 256
77
78/* Globals (different for each process/thread) */
79ZEND_DECLARE_MODULE_GLOBALS(eaccelerator)
80
81/* Globals (common for each process/thread) */
82static long ea_shm_size = 0;
83long ea_shm_max = 0;
84static long ea_shm_ttl = 0;
85static long ea_shm_prune_period = 0;
86extern long eaccelerator_debug;
87static zend_bool eaccelerator_check_mtime = 1;
88zend_bool eaccelerator_scripts_shm_only = 0;
89
90eaccelerator_mm* eaccelerator_mm_instance = NULL;
91static int eaccelerator_is_zend_extension = 0;
92static int eaccelerator_is_extension      = 0;
93zend_extension* ZendOptimizer = NULL;
94
95static HashTable eaccelerator_global_function_table;
96static HashTable eaccelerator_global_class_table;
97
98int binary_eaccelerator_version;
99int binary_php_version;
100int binary_zend_version;
101
102#ifdef ZEND_ENGINE_2
103/* pointer to the properties_info hashtable destructor */
104extern dtor_func_t properties_info_dtor;
105#endif
106
107/* saved original functions */
108static zend_op_array *(*mm_saved_zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
109
110#ifdef DEBUG
111static void (*mm_saved_zend_execute)(zend_op_array *op_array TSRMLS_DC);
112#endif
113
114/* external declarations */
115PHPAPI void php_stripslashes(char *str, int *len TSRMLS_DC);
116
117ZEND_DLEXPORT zend_op_array* eaccelerator_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC);
118
119/******************************************************************************/
120/* hash mm functions                                                          */
121/******************************************************************************/
122
123/* Find a script entry with the given hash key */
124static ea_cache_entry* hash_find_mm(const char  *key,
125                                    struct stat *buf,
126                                    int         *nreloads,
127                                    time_t      ttl) {
128  unsigned int hv, slot;
129  ea_cache_entry *p, *q;
130
131#ifdef EACCELERATOR_USE_INODE
132  hv = buf->st_dev + buf->st_ino;
133#else
134  hv = zend_get_hash_value(key, strlen(key));
135#endif
136  slot = hv & EA_HASH_MAX;
137
138  EACCELERATOR_LOCK_RW();
139  q = NULL;
140  p = eaccelerator_mm_instance->hash[slot];
141  while (p != NULL) {
142#ifdef EACCELERATOR_USE_INODE
143    if (p->st_dev == buf->st_dev && p->st_ino == buf->st_ino) {
144      struct stat buf2;
145      if ((eaccelerator_check_mtime &&
146          (buf->st_mtime != p->mtime || buf->st_size != p->filesize)) ||
147          (strcmp(p->realfilename, key) != 0 &&
148           (stat(p->realfilename,&buf2) != 0 ||
149           buf2.st_dev != buf->st_dev ||
150           buf2.st_ino != buf->st_ino))) {
151#else
152    if ((p->hv == hv) && (strcmp(p->realfilename, key) == 0)) {
153      if (eaccelerator_check_mtime &&
154          (buf->st_mtime != p->mtime || buf->st_size != p->filesize)) {
155#endif
156        /* key is invalid. Remove it. */
157        *nreloads = p->nreloads+1;
158        if (q == NULL) {
159          eaccelerator_mm_instance->hash[slot] = p->next;
160        } else {
161          q->next = p->next;
162        }
163        eaccelerator_mm_instance->hash_cnt--;
164        if (p->use_cnt > 0) {
165          /* key is used by other process/thred. Shedule it to remove */
166          p->removed = 1;
167          p->next = eaccelerator_mm_instance->removed;
168          eaccelerator_mm_instance->removed = p;
169          eaccelerator_mm_instance->rem_cnt++;
170          EACCELERATOR_UNLOCK_RW();
171          return NULL;
172        } else {
173          /* key is unused. Remove it. */
174          eaccelerator_free_nolock(p);
175          EACCELERATOR_UNLOCK_RW();
176          return NULL;
177        }
178      } else {
179        /* key is valid */
180        p->nhits++;
181        p->use_cnt++;
182        p->ttl = ttl;
183        EACCELERATOR_UNLOCK_RW();
184        return p;
185      }
186    }
187    q = p;
188    p = p->next;
189  }
190  EACCELERATOR_UNLOCK_RW();
191  return NULL;
192}
193
194/* Add a new entry to the hashtable */
195static void hash_add_mm(ea_cache_entry *x) {
196  ea_cache_entry *p,*q;
197  unsigned int slot;
198#ifdef EACCELERATOR_USE_INODE
199  slot = (x->st_dev + x->st_ino) & EA_HASH_MAX;
200#else
201  x->hv = zend_get_hash_value(x->realfilename, strlen(x->realfilename));
202  slot = x->hv & EA_HASH_MAX;
203#endif
204
205  EACCELERATOR_LOCK_RW();
206  x->next = eaccelerator_mm_instance->hash[slot];
207  eaccelerator_mm_instance->hash[slot] = x;
208  eaccelerator_mm_instance->hash_cnt++;
209  q = x;
210  p = x->next;
211  while (p != NULL) {
212#ifdef EACCELERATOR_USE_INODE
213    if ((p->st_dev == x->st_dev) && (p->st_ino == x->st_ino)) {
214#else
215    if ((p->hv == x->hv) &&
216        (strcmp(p->realfilename, x->realfilename) == 0)) {
217#endif
218      q->next = p->next;
219      eaccelerator_mm_instance->hash_cnt--;
220      eaccelerator_mm_instance->hash[slot]->nreloads += p->nreloads;
221      if (p->use_cnt > 0) {
222        /* key is used by other process/thred. Shedule it to remove */
223        p->removed = 1;
224        p->next = eaccelerator_mm_instance->removed;
225        eaccelerator_mm_instance->removed = p;
226        eaccelerator_mm_instance->rem_cnt++;
227        EACCELERATOR_UNLOCK_RW();
228        return;
229      } else {
230        /* key is unused. Remove it. */
231        eaccelerator_free_nolock(p);
232        EACCELERATOR_UNLOCK_RW();
233        return;
234      }
235    }
236    q = p;
237    p = p->next;
238  }
239  EACCELERATOR_UNLOCK_RW();
240}
241
242/* Initialise the shared memory */
243static int init_mm(TSRMLS_D) {
244  pid_t  owner = getpid();
245  MM     *mm;
246  size_t total;
247  char   mm_path[MAXPATHLEN];
248
249#ifdef ZEND_WIN32
250    snprintf(mm_path, MAXPATHLEN, "%s.%s", EACCELERATOR_MM_FILE, sapi_module.name);
251#else
252    snprintf(mm_path, MAXPATHLEN, "%s.%s%d", EACCELERATOR_MM_FILE, sapi_module.name, owner);
253#endif
254/*  snprintf(mm_path, MAXPATHLEN, "%s.%s%d", EACCELERATOR_MM_FILE, sapi_module.name, geteuid());*/
255  if ((eaccelerator_mm_instance = (eaccelerator_mm*)mm_attach(ea_shm_size*1024*1024, mm_path)) != NULL) {
256#ifdef ZTS
257    ea_mutex = tsrm_mutex_alloc();
258#endif
259    return SUCCESS;
260  }
261  mm = mm_create(ea_shm_size*1024*1024, mm_path);
262  if (!mm) {
263    return FAILURE;
264  }
265#ifdef ZEND_WIN32
266  DBG(ea_debug_printf, (EA_DEBUG, "init_mm [%d]\n", owner));
267#else
268  DBG(ea_debug_printf, (EA_DEBUG, "init_mm [%d,%d]\n", owner, getppid()));
269#endif
270#ifdef ZTS
271  ea_mutex = tsrm_mutex_alloc();
272#endif
273  total = mm_available(mm);
274  eaccelerator_mm_instance = mm_malloc_lock(mm, sizeof(*eaccelerator_mm_instance));
275  if (!eaccelerator_mm_instance) {
276    return FAILURE;
277  }
278  mm_set_attach(mm, eaccelerator_mm_instance);
279  memset(eaccelerator_mm_instance, 0, sizeof(*eaccelerator_mm_instance));
280  eaccelerator_mm_instance->owner = owner;
281  eaccelerator_mm_instance->mm    = mm;
282  eaccelerator_mm_instance->total = total;
283  eaccelerator_mm_instance->hash_cnt = 0;
284  eaccelerator_mm_instance->rem_cnt  = 0;
285  eaccelerator_mm_instance->enabled = 1;
286  eaccelerator_mm_instance->optimizer_enabled = 1;
287  eaccelerator_mm_instance->removed = NULL;
288  eaccelerator_mm_instance->locks = NULL;
289  eaccelerator_mm_instance->user_hash_cnt = 0;
290  eaccelerator_mm_instance->last_prune = time(0);
291  EACCELERATOR_PROTECT();
292  return SUCCESS;
293}
294
295/* Clean up the shared memory */
296static void shutdown_mm(TSRMLS_D) {
297  if (eaccelerator_mm_instance) {
298#ifdef ZEND_WIN32
299    if (eaccelerator_mm_instance->owner == getpid()) {
300#else
301    if (getpgrp() == getpid()) {
302#endif
303      MM *mm = eaccelerator_mm_instance->mm;
304#ifdef ZEND_WIN32
305      DBG(ea_debug_printf, (EA_DEBUG, "shutdown_mm [%d]\n", getpid()));
306#else
307      DBG(ea_debug_printf, (EA_DEBUG, "shutdown_mm [%d,%d]\n", getpid(), getppid()));
308#endif
309#ifdef ZTS
310      tsrm_mutex_free(ea_mutex);
311#endif
312      if (mm) {
313        mm_destroy(mm);
314      }
315      eaccelerator_mm_instance = NULL;
316    }
317  }
318}
319
320
321static int encode_version(const char *s) {
322  unsigned int v1 = 0;
323  unsigned int v2 = 0;
324  unsigned int v3 = 0;
325  unsigned int c;
326  char m = '.';
327  sscanf(s, "%u.%u%c%u",&v1,&v2,&m,&v3);
328  switch (m) {
329    case  'a': c = 0; break;
330    case  'b': c = 1; break;
331    case  '.': c = 2; break;
332    case  's': c = 15; break;
333    default: c = 2;
334  }
335  return ((v1 & 0xf) << 20) |
336         ((v2 & 0xff) << 12) |
337         ((c & 0xf) << 8) |
338         (v3 & 0xff);
339}
340
341/* This function isn't used. So disable it for now
342static void decode_version(char *version, int v) {
343  int t = (v & 0x000f00) >> 8;
344  char c;
345  switch (t) {
346    case  0: c = 'a'; break;
347    case  1: c = 'b'; break;
348    case  2: c = '.'; break;
349    case 15: c = 's'; break;
350    default: c = '.';
351  }
352  snprintf(version, 16, "%d.%d%c%d", (v & 0xf00000) >> 20,
353                                     (v & 0x0ff000) >> 12,
354                                     c,
355                                     (v & 0x0000ff));
356}
357*/
358
359static char num2hex[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
360
361#ifdef EACCELERATOR_USE_INODE
362static int eaccelerator_inode_key(char* s, dev_t dev, ino_t ino TSRMLS_DC) {
363  int n, i;
364  snprintf(s, MAXPATHLEN-1, "%s/", EAG(cache_dir));
365  n = strlen(s);
366  for (i = 1; i <= EACCELERATOR_HASH_LEVEL && n < MAXPATHLEN - 1; i++) {
367    s[n++] = num2hex[(ino >> (i*4)) & 0xf];
368    s[n++] = '/';
369  }
370  s[n] = 0;
371  strlcat(s, "eaccelerator-", MAXPATHLEN-1);
372  n += sizeof("eaccelerator-") - 1;
373  while (dev > 0) {
374    if (n >= MAXPATHLEN) return 0;
375    s[n++] = (dev % 10) +'0';
376    dev /= 10;
377  }
378  if (n >= MAXPATHLEN) return 0;
379  s[n++] = '.';
380  while (ino > 0) {
381    if (n >= MAXPATHLEN) return 0;
382    s[n++] = (ino % 10) +'0';
383    ino /= 10;
384  }
385  if (n >= MAXPATHLEN) return 0;
386  s[n++] = '\000';
387  return 1;
388}
389#endif
390
391/* Function to create a hash key when filenames are used */
392int eaccelerator_md5(char* s, const char* prefix, const char* key TSRMLS_DC) {
393#if defined(PHP_MAJOR_VERSION) && defined(PHP_MINOR_VERSION) && \
394    ((PHP_MAJOR_VERSION > 4) || (PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION > 1))
395  char md5str[33];
396  PHP_MD5_CTX context;
397  unsigned char digest[16];
398  int i;
399  int n;
400
401  md5str[0] = '\0';
402  PHP_MD5Init(&context);
403  PHP_MD5Update(&context, (unsigned char*)key, strlen(key));
404  PHP_MD5Final(digest, &context);
405  make_digest(md5str, digest);
406  snprintf(s, MAXPATHLEN-1, "%s/", EAG(cache_dir));
407  n = strlen(s);
408  for (i = 0; i < EACCELERATOR_HASH_LEVEL && n < MAXPATHLEN - 1; i++) {
409    s[n++] = md5str[i];
410    s[n++] = '/';
411  }
412  s[n] = 0;
413  snprintf(s, MAXPATHLEN-1, "%s%s%s", s, prefix, md5str);
414  return 1;
415#else
416  zval retval;
417  zval md5;
418  zval param;
419  zval *params[1];
420
421  ZVAL_STRING(&md5, "md5", 0);
422  INIT_ZVAL(param);
423  params[0] = &param;
424  ZVAL_STRING(params[0], (char*)key, 0);
425  if (call_user_function(CG(function_table), (zval**)NULL, &md5, &retval, 1, params TSRMLS_CC) == SUCCESS &&
426      Z_TYPE(retval) == IS_STRING && Z_STRLEN(retval) == 32) {
427    strncpy(s, EAG(cache_dir), MAXPATHLEN-1);
428    strlcat(s, prefix, MAXPATHLEN);
429    strlcat(s, Z_STRVAL(retval), MAXPATHLEN);
430    zval_dtor(&retval);
431    return 1;
432  }
433  s[0] ='\0';
434#endif
435  return 0;
436}
437
438/* Remove expired keys, content and scripts from the cache */
439void eaccelerator_prune(time_t t) {
440  unsigned int i;
441
442  EACCELERATOR_LOCK_RW();
443  eaccelerator_mm_instance->last_prune = t;
444  for (i = 0; i < EA_HASH_SIZE; i++) {
445    ea_cache_entry **p = &eaccelerator_mm_instance->hash[i];
446    while (*p != NULL) {
447      struct stat buf;
448      if (((*p)->ttl != 0 && (*p)->ttl < t && (*p)->use_cnt <= 0) ||
449          stat((*p)->realfilename,&buf) != 0 ||
450#ifdef EACCELERATOR_USE_INODE
451          (*p)->st_dev != buf.st_dev ||
452          (*p)->st_ino != buf.st_ino ||
453#endif
454          (*p)->mtime != buf.st_mtime ||
455          (*p)->filesize != buf.st_size) {
456        ea_cache_entry *r = *p;
457        *p = (*p)->next;
458        eaccelerator_mm_instance->hash_cnt--;
459        eaccelerator_free_nolock(r);
460      } else {
461        p = &(*p)->next;
462      }
463    }
464  }
465  EACCELERATOR_UNLOCK_RW();
466}
467
468/* Allocate a new cache chunk */
469void* eaccelerator_malloc2(size_t size TSRMLS_DC) {
470  void *p = NULL;
471  time_t t;
472
473  if (eaccelerator_gc(TSRMLS_C) > 0) {
474    p = eaccelerator_malloc(size);
475    if (p != NULL) {
476      return p;
477    }
478  }
479  if (ea_shm_prune_period > 0) {
480    t = time(0);
481    if (t - eaccelerator_mm_instance->last_prune > ea_shm_prune_period) {
482      eaccelerator_prune(t);
483      p = eaccelerator_malloc(size);
484    }
485  }
486  return p;
487}
488
489#define EACCELERATOR_CRC32(crc, ch)   (crc = (crc >> 8) ^ crc32tab[(crc ^ (ch)) & 0xff])
490
491static const unsigned int crc32tab[256] = {
492  0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
493  0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
494  0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
495  0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
496  0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
497  0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
498  0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
499  0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
500  0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
501  0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
502  0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
503  0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
504  0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
505  0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
506  0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
507  0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
508  0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
509  0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
510  0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
511  0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
512  0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
513  0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
514  0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
515  0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
516  0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
517  0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
518  0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
519  0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
520  0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
521  0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
522  0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
523  0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
524  0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
525  0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
526  0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
527  0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
528  0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
529  0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
530  0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
531  0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
532  0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
533  0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
534  0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
535  0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
536  0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
537  0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
538  0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
539  0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
540  0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
541  0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
542  0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
543  0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
544  0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
545  0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
546  0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
547  0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
548  0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
549  0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
550  0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
551  0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
552  0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
553  0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
554  0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
555  0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
556};
557
558unsigned int eaccelerator_crc32(const char *p, size_t n) {
559  unsigned int crc = ~0;
560  for (; n--; ++p) {
561    EACCELERATOR_CRC32(crc, *p);
562  }
563  return ~crc;
564}
565
566/******************************************************************************/
567/* Cache file functions.                                                                                                          */
568/******************************************************************************/
569
570/* Retrieve a cache entry from the cache directory */
571static ea_cache_entry* hash_find_file(const char  *key, struct stat *buf TSRMLS_DC) {
572  int f;
573  char s[MAXPATHLEN];
574  ea_file_header hdr;
575  ea_cache_entry *p;
576  int use_shm = 1;
577
578#ifdef EACCELERATOR_USE_INODE
579  struct stat buf2;
580
581  if (!eaccelerator_inode_key(s, buf->st_dev, buf->st_ino TSRMLS_CC)) {
582    return NULL;
583  }
584#else
585  if (!eaccelerator_md5(s, "/eaccelerator-", key TSRMLS_CC)) {
586    return NULL;
587  }
588#endif
589
590  if ((f = open(s, O_RDONLY | O_BINARY)) > 0) {
591    EACCELERATOR_FLOCK(f, LOCK_SH);
592    if (read(f, &hdr, sizeof(hdr)) != sizeof(hdr)) {
593      EACCELERATOR_FLOCK(f, LOCK_UN);
594      close(f);
595      return NULL;
596    }
597    if (strncmp(hdr.magic, EA_MAGIC, 8) != 0 ||
598        hdr.eaccelerator_version != binary_eaccelerator_version ||
599        hdr.zend_version != binary_zend_version ||
600        hdr.php_version != binary_php_version) {
601      EACCELERATOR_FLOCK(f, LOCK_UN);
602      close(f);
603      unlink(s);
604      return NULL;
605    }
606    p = eaccelerator_malloc(hdr.size);
607    if (p == NULL) {
608      p = eaccelerator_malloc2(hdr.size TSRMLS_CC);
609    }
610    if (p == NULL) {
611      p = emalloc(hdr.size);
612      use_shm = 0;
613    }
614    if (p == NULL) {
615      EACCELERATOR_FLOCK(f, LOCK_UN);
616      close(f);
617      return NULL;
618    }
619    if (read(f, p, hdr.size) != hdr.size ||
620        p->size != hdr.size ||
621        hdr.crc32 != eaccelerator_crc32((const char*)p,p->size)) {
622      EACCELERATOR_FLOCK(f, LOCK_UN);
623      close(f);
624      unlink(s);
625      if (use_shm) eaccelerator_free(p); else efree(p);
626      return NULL;
627    }
628    EACCELERATOR_FLOCK(f, LOCK_UN);
629    close(f);
630#ifdef EACCELERATOR_USE_INODE
631    if (p->st_dev != buf->st_dev || p->st_ino != buf->st_ino) {
632#else
633    if (strcmp(key,p->realfilename) != 0) {
634#endif
635      if (use_shm) eaccelerator_free(p); else efree(p);
636      return NULL;
637    }
638    if ((eaccelerator_check_mtime &&
639        (buf->st_mtime != p->mtime || buf->st_size != p->filesize))
640#ifdef EACCELERATOR_USE_INODE
641        ||
642        (strcmp(p->realfilename, key) != 0 &&
643         (stat(p->realfilename,&buf2) != 0 ||
644         buf2.st_dev != buf->st_dev ||
645         buf2.st_ino != buf->st_ino))
646#endif
647       ) {
648      /* key is invalid. Remove it. */
649      if (use_shm) eaccelerator_free(p); else efree(p);
650      unlink(s);
651      return NULL;
652    }
653    eaccelerator_fixup(p TSRMLS_CC);
654    if (use_shm) {
655      p->nhits    = 1;
656      p->nreloads = 1;
657      p->use_cnt  = 1;
658      p->removed  = 0;
659      if (ea_shm_ttl > 0) {
660        p->ttl = time(0) + ea_shm_ttl;
661      } else {
662        p->ttl = 0;
663      }
664      hash_add_mm(p);
665    } else {
666      p->use_cnt  = 0;
667      p->removed  = 1;
668    }
669    return p;
670  }
671  return NULL;
672}
673
674/* Add a cache entry to the cache directory */
675static int hash_add_file(ea_cache_entry *p TSRMLS_DC) {
676  int f;
677  int ret = 0;
678  char s[MAXPATHLEN];
679  ea_file_header hdr;
680
681#ifdef EACCELERATOR_USE_INODE
682  if (!eaccelerator_inode_key(s, p->st_dev, p->st_ino TSRMLS_CC)) {
683    return 0;
684  }
685#else
686  if (!eaccelerator_md5(s, "/eaccelerator-", p->realfilename TSRMLS_CC)) {
687    return 0;
688  }
689#endif
690
691  unlink(s);
692  f = open(s, O_CREAT | O_WRONLY | O_EXCL | O_BINARY, S_IRUSR | S_IWUSR);
693  if (f > 0) {
694    EACCELERATOR_FLOCK(f, LOCK_EX);
695    strncpy(hdr.magic, EA_MAGIC, 8);
696    hdr.eaccelerator_version = binary_eaccelerator_version;
697    hdr.zend_version    = binary_zend_version;
698    hdr.php_version     = binary_php_version;
699    hdr.size  = p->size;
700    hdr.mtime = p->mtime;
701    p->next = p;
702    hdr.crc32 = eaccelerator_crc32((const char*)p,p->size);
703    ret = (write(f, &hdr, sizeof(hdr)) == sizeof(hdr));
704    if (ret) ret = (write(f, p, p->size) == p->size);
705    EACCELERATOR_FLOCK(f, LOCK_UN);
706    close(f);
707  } else {
708    ea_debug_log("EACCELERATOR: Open for write failed for \"%s\": %s\n", s, strerror(errno));
709  }
710  return ret;
711}
712
713/* called after succesful compilation, from eaccelerator_compile file */
714/* Adds the data from the compilation of the script to the cache */
715static int eaccelerator_store(char* key, struct stat *buf, int nreloads,
716                         zend_op_array* op_array,
717                         Bucket* f, Bucket *c TSRMLS_DC) {
718  ea_cache_entry *p;
719  int len = strlen(key);
720  int use_shm = 1;
721  int ret = 0;
722  int size = 0;
723
724  zend_try {
725    size = calc_size(key, op_array, f, c TSRMLS_CC);
726  } zend_catch {
727    size =  0;
728  } zend_end_try();
729  if (size == 0) {
730    return 0;
731  }
732  DBG(ea_debug_printf, (EA_DEBUG, "[%d] eaccelerator_store: calc_size returned %d, mm=%x", getpid(), size, eaccelerator_mm_instance->mm));
733  EACCELERATOR_UNPROTECT();
734  EAG(mem) = eaccelerator_malloc(size);
735  if (EAG(mem) == NULL) {
736    EAG(mem) = eaccelerator_malloc2(size TSRMLS_CC);
737  }
738  if (!EAG(mem) && !eaccelerator_scripts_shm_only) {
739    EACCELERATOR_PROTECT();
740    EAG(mem) = emalloc(size);
741    use_shm = 0;
742  }
743  if (EAG(mem)) {
744    memset(EAG(mem), 0, size);
745    p = eaccelerator_store_int(key, len, op_array, f, c TSRMLS_CC);
746    p->mtime    = buf->st_mtime;
747    p->filesize = buf->st_size;
748    p->size     = size;
749    p->nreloads = nreloads;
750#ifdef EACCELERATOR_USE_INODE
751    p->st_dev   = buf->st_dev;
752    p->st_ino   = buf->st_ino;
753#endif
754    if (use_shm) {
755      if (ea_shm_ttl > 0) {
756        p->ttl = time(0) + ea_shm_ttl;
757      } else {
758        p->ttl = 0;
759      }
760      if (!eaccelerator_scripts_shm_only) {
761        hash_add_file(p TSRMLS_CC);
762      }
763      hash_add_mm(p);
764      EACCELERATOR_PROTECT();
765      ret = 1;
766    } else {
767      ret =  hash_add_file(p TSRMLS_CC);
768      efree(p);
769    }
770  }
771  return ret;
772}
773
774/* Try to restore a file from the cache. If the file isn't found in memory, the
775   the disk cache is checked */
776static zend_op_array* eaccelerator_restore(char *realname, struct stat *buf,
777                                      int *nreloads, time_t compile_time TSRMLS_DC) {
778  ea_cache_entry *p;
779  zend_op_array *op_array = NULL;
780
781  *nreloads = 1;
782  EACCELERATOR_UNPROTECT();
783  p = hash_find_mm(realname, buf, nreloads, ((ea_shm_ttl > 0)?(compile_time + ea_shm_ttl):0));
784  if (p == NULL && !eaccelerator_scripts_shm_only) {
785    p = hash_find_file(realname, buf TSRMLS_CC);
786  }
787  EACCELERATOR_PROTECT();
788  if (p != NULL && p->op_array != NULL) {
789    EAG(class_entry) = NULL;
790    op_array = restore_op_array(NULL, p->op_array TSRMLS_CC);
791    if (op_array != NULL) {
792      ea_fc_entry *e;
793      ea_used_entry *used = emalloc(sizeof(ea_used_entry));
794      used->entry  = p;
795      used->next   = (ea_used_entry*)EAG(used_entries);
796      EAG(used_entries) = (void*)used;
797      EAG(mem) = op_array->filename;
798            /* only restore the classes and functions when we restore this script
799             * for the first time.
800             */
801      if (!zend_hash_exists(&EAG(restored), p->realfilename, strlen(p->realfilename))) {
802              for (e = p->c_head; e!=NULL; e = e->next) {
803          restore_class(e TSRMLS_CC);
804        }
805        for (e = p->f_head; e!=NULL; e = e->next) {
806          restore_function(e TSRMLS_CC);
807        }
808                    zend_hash_add(&EAG(restored), p->realfilename, strlen(p->realfilename), NULL, 0, NULL); 
809            }
810            EAG(mem) = p->realfilename;
811    }
812  }
813  return op_array;
814}
815
816/*
817 * Only files matching user specified conditions should be cached.
818 *
819 * TODO - check the algorithm (fl)
820 */
821static int match(const char* name, const char* pat) {
822  char p,k;
823  int ok, neg;
824 
825  while (1) {
826    p = *pat++;
827    if (p == '\0') {
828      return (*name == '\0');
829    } else if (p == '*') {
830      if (*pat == '\0') {
831        return 1;
832      }
833      do {
834        if (match(name, pat)) {
835          return 1;
836        }
837      } while (*name++ != '\0');
838      return 0;
839    } else if (p == '?') {
840      if (*name++ == '\0') {
841        return 0;
842      }
843    } else if (p == '[') {
844      ok = 0;
845      if ((k = *name++) == '\0') {
846        return 0;
847      }
848      if ((neg = (*pat == '!')) != '\0') {
849        ++pat;
850      }
851      while ((p = *pat++) != ']') {
852        if (*pat == '-') {
853          if (p <= k && k <= pat[1]) {
854            ok = 1;
855          }
856          pat += 2;
857        } else {
858          if (p == '\\') {
859            p = *pat++;
860            if (p == '\0') {
861              p ='\\';
862              pat--;
863            }
864          }
865          if (p == k) {
866            ok = 1;
867          }
868        }
869      }
870      if (ok == neg) {
871        return 0;
872      }
873    } else {
874      if (p == '\\') {
875        p = *pat++;
876        if (p == '\0') {
877          p ='\\';
878          pat--;
879        }
880      }
881      if (*name++ != p) {
882        return 0;
883      }
884    }
885  }
886  return (*name == '\0');
887}
888
889/* Check if the file is ok to cache */
890static int eaccelerator_ok_to_cache(char *realname TSRMLS_DC) {
891  ea_cond_entry *p;
892  int ok;
893  if (EAG(cond_list) == NULL) {
894    return 1;
895  }
896
897  /* if "realname" matches to any pattern started with "!" then ignore it */
898  for (p = EAG(cond_list); p != NULL; p = p->next) {
899    if (p->not && match(realname, p->str)) {
900      return 0;
901    }
902  }
903
904  /* else if it matches to any pattern not started with "!" then accept it */
905  ok = 1;
906  for (p = EAG(cond_list); p != NULL; p = p->next) {
907    if (!p->not) {
908      ok = 0;
909      if (match(realname, p->str)) {
910        return 1;
911      }
912    }
913  }
914  return ok;
915}
916
917static int eaccelerator_stat(zend_file_handle *file_handle,
918                        char* realname, struct stat* buf TSRMLS_DC) {
919#ifdef EACCELERATOR_USE_INODE
920#ifndef ZEND_WIN32
921  if (file_handle->type == ZEND_HANDLE_FP && file_handle->handle.fp != NULL) {
922    if (fstat(fileno(file_handle->handle.fp), buf) == 0 && S_ISREG(buf->st_mode)) {
923      if (file_handle->opened_path != NULL) {
924        strcpy(realname, file_handle->opened_path);
925      }
926      return 0;
927    }
928  } else
929#endif
930  if (file_handle->opened_path != NULL) {
931    if (stat(file_handle->opened_path, buf) == 0 && S_ISREG(buf->st_mode)) {
932       strcpy(realname,file_handle->opened_path);
933       return 0;
934    }
935  } else if (PG(include_path) == NULL ||
936                         file_handle->filename[0] == '.' ||
937             IS_SLASH(file_handle->filename[0]) ||
938             IS_ABSOLUTE_PATH(file_handle->filename,strlen(file_handle->filename))) {
939    if (stat(file_handle->filename, buf) == 0 && S_ISREG(buf->st_mode)) {
940       return 0;
941    }
942  } else {
943    char* ptr = PG(include_path);
944    char* end;
945    int   len;
946    char  tryname[MAXPATHLEN];
947    int   filename_len = strlen(file_handle->filename);
948
949    while (ptr && *ptr) {
950      end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
951      if (end != NULL) {
952        len = end - ptr;
953        end++;
954      } else {
955        len = strlen(ptr);
956        end = ptr + len;
957      }
958      if (len + filename_len + 2 < MAXPATHLEN) {
959        memcpy(tryname, ptr, len);
960        tryname[len] = '/';
961        memcpy(tryname + len + 1, file_handle->filename, filename_len);
962        tryname[len + filename_len + 1] = '\0';
963        if (stat(tryname, buf) == 0 && S_ISREG(buf->st_mode)) {
964          return 0;
965        }
966      }
967      ptr = end;
968    }
969
970        if (zend_is_executing(TSRMLS_C)) {
971        int tryname_length;
972                strncpy(tryname, zend_get_executed_filename(TSRMLS_C), MAXPATHLEN);
973                tryname[MAXPATHLEN - 1] = 0;
974                tryname_length = strlen(tryname);
975
976                while (tryname_length >= 0 && !IS_SLASH(tryname[tryname_length])) {
977                        tryname_length--;
978                }
979                if (tryname_length > 0 && tryname[0] != '[' // [no active file]
980                        && tryname_length + filename_len + 1 < MAXPATHLEN)
981                {
982                        strncpy(tryname + tryname_length + 1, file_handle->filename, filename_len + 1);
983                        if (stat(tryname, buf) == 0 && S_ISREG(buf->st_mode)) {
984                                return 0;
985                        }
986                }
987        }
988  }
989  return -1;
990#else
991  if (file_handle->opened_path != NULL) {
992    strcpy(realname,file_handle->opened_path);
993#ifndef ZEND_WIN32
994    if (file_handle->type == ZEND_HANDLE_FP && file_handle->handle.fp != NULL) {
995      if (!eaccelerator_check_mtime) {
996        return 0;
997      } else if (fstat(fileno(file_handle->handle.fp), buf) == 0 && S_ISREG(buf->st_mode)) {
998        return 0;
999      } else {
1000        return -1;
1001      }
1002    } else {
1003      if (!eaccelerator_check_mtime) {
1004        return 0;
1005      } else if (stat(realname, buf) == 0 && S_ISREG(buf->st_mode)) {
1006        return 0;
1007      } else {
1008        return -1;
1009      }
1010    }
1011#else
1012    if (!eaccelerator_check_mtime) {
1013      return 0;
1014    } else if (stat(realname, buf) == 0 && S_ISREG(buf->st_mode)) {
1015      return 0;
1016    } else {
1017      return -1;
1018    }
1019#endif
1020  } else if (file_handle->filename == NULL) {
1021    return -1;
1022  } else if (PG(include_path) == NULL ||
1023             file_handle->filename[0] == '.' ||
1024             IS_SLASH(file_handle->filename[0]) ||
1025             IS_ABSOLUTE_PATH(file_handle->filename,strlen(file_handle->filename))) {
1026    if (VCWD_REALPATH(file_handle->filename, realname)) {
1027      if (!eaccelerator_check_mtime) {
1028        return 0;
1029      } else if (stat(realname, buf) == 0 && S_ISREG(buf->st_mode)) {
1030        return 0;
1031      } else {
1032        return -1;
1033      }
1034    }
1035  } else {
1036    char* ptr = PG(include_path);
1037    char* end;
1038    int   len;
1039    char  tryname[MAXPATHLEN];
1040    int   filename_len = strlen(file_handle->filename);
1041
1042    while (ptr && *ptr) {
1043      end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
1044      if (end != NULL) {
1045        len = end - ptr;
1046        end++;
1047      } else {
1048        len = strlen(ptr);
1049        end = ptr + len;
1050      }
1051      if (len+filename_len+2 < MAXPATHLEN) {
1052        memcpy(tryname, ptr, len);
1053        tryname[len] = '/';
1054        memcpy(tryname + len + 1, file_handle->filename, filename_len);
1055        tryname[len + filename_len + 1] = '\0';
1056        if (VCWD_REALPATH(tryname, realname)) {
1057#ifdef ZEND_WIN32
1058          if (stat(realname, buf) == 0 && S_ISREG(buf->st_mode)) {
1059            return 0;
1060          }
1061#else
1062          if (!eaccelerator_check_mtime) {
1063            return 0;
1064          } else if (stat(realname, buf) == 0 && S_ISREG(buf->st_mode)) {
1065            return 0;
1066          } else {
1067            return -1;
1068          }
1069#endif
1070        }
1071      }
1072      ptr = end;
1073    }
1074  }
1075  return -1;
1076#endif
1077}
1078
1079/*
1080 * Intercept compilation of PHP file.  If we already have the file in
1081 * our cache, restore it.  Otherwise call the original Zend compilation
1082 * function and store the compiled zend_op_array in out cache.
1083 * This function is called again for each PHP file included in the
1084 * main PHP file.
1085 */
1086ZEND_DLEXPORT zend_op_array* eaccelerator_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) {
1087  zend_op_array *t;
1088  struct stat buf;
1089  char  realname[MAXPATHLEN];
1090  int   nreloads;
1091  time_t compile_time;
1092  int stat_result = 0;
1093#ifdef DEBUG
1094  struct timeval tv_start;
1095#endif
1096  int ok_to_cache = 0;
1097
1098#ifdef EACCELERATOR_USE_INODE
1099  realname[0] = '\000';
1100#endif
1101
1102  DBG(ea_debug_start_time, (&tv_start));
1103  DBG(ea_debug_printf, (EA_DEBUG, "[%d] Enter COMPILE\n",getpid()));
1104  DBG(ea_debug_printf, (EA_DEBUG, "[%d] compile_file: \"%s\"\n",getpid(), file_handle->filename));
1105#ifdef DEBUG
1106  EAG(xpad)+=2;
1107#endif
1108
1109  compile_time = time(0);
1110  stat_result = eaccelerator_stat(file_handle, realname, &buf TSRMLS_CC);
1111  if (buf.st_mtime >= compile_time && eaccelerator_debug > 0) {
1112        ea_debug_log("EACCELERATOR: Warning: \"%s\" is cached but it's mtime is in the future.\n", file_handle->filename);
1113  }
1114
1115  ok_to_cache = eaccelerator_ok_to_cache(file_handle->filename TSRMLS_CC);
1116 
1117  // eAccelerator isn't working, so just compile the file
1118  if (!EAG(enabled) || (eaccelerator_mm_instance == NULL) ||
1119      !eaccelerator_mm_instance->enabled || file_handle == NULL ||
1120      file_handle->filename == NULL || stat_result != 0 || !ok_to_cache) {
1121    DBG(ea_debug_printf, (EA_DEBUG, "\t[%d] compile_file: compiling\n", getpid()));
1122    t = mm_saved_zend_compile_file(file_handle, type TSRMLS_CC);
1123    DBG(ea_debug_printf, (EA_TEST_PERFORMANCE, "\t[%d] compile_file: end (%ld)\n", getpid(), ea_debug_elapsed_time(&tv_start)));
1124    DBG(ea_debug_printf, (EA_DEBUG, "\t[%d] compile_file: end\n", getpid()));
1125#ifdef DEBUG
1126    EAG(xpad)-=2;
1127#endif
1128    DBG(ea_debug_printf, (EA_DEBUG, "[%d] Leave COMPILE\n", getpid()));
1129    return t;
1130  }
1131
1132  /* only restore file when open_basedir allows it */
1133  if (php_check_open_basedir(file_handle->filename TSRMLS_CC)) {
1134    zend_error(E_ERROR, "Can't load %s, open_basedir restriction.", file_handle->filename);
1135  }
1136
1137  t = eaccelerator_restore(realname, &buf, &nreloads, compile_time TSRMLS_CC);
1138
1139// segv74: really cheap work around to auto_global problem.
1140//         it makes just in time to every time.
1141#ifdef ZEND_ENGINE_2
1142  zend_is_auto_global("_GET", sizeof("_GET")-1 TSRMLS_CC);
1143  zend_is_auto_global("_POST", sizeof("_POST")-1 TSRMLS_CC);
1144  zend_is_auto_global("_COOKIE", sizeof("_COOKIE")-1 TSRMLS_CC);
1145  zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
1146  zend_is_auto_global("_ENV", sizeof("_ENV")-1 TSRMLS_CC);
1147  zend_is_auto_global("_REQUEST", sizeof("_REQUEST")-1 TSRMLS_CC);
1148  zend_is_auto_global("_FILES", sizeof("_FILES")-1 TSRMLS_CC);
1149#endif
1150
1151  if (t != NULL) { // restore from cache
1152#ifdef DEBUG
1153    ea_debug_log("[%d] EACCELERATOR hit: \"%s\"\n", getpid(), t->filename);
1154#else
1155    ea_debug_log("EACCELERATOR hit: \"%s\"\n", t->filename);
1156#endif
1157
1158    zend_llist_add_element(&CG(open_files), file_handle);
1159#ifdef ZEND_ENGINE_2
1160    if (file_handle->opened_path == NULL && file_handle->type != ZEND_HANDLE_STREAM) {
1161      file_handle->handle.stream.handle = (void*)1;
1162      file_handle->opened_path = EAG(mem);
1163#else
1164    if (file_handle->opened_path == NULL && file_handle->type != ZEND_HANDLE_FP) {
1165      int dummy = 1;
1166      file_handle->opened_path = EAG(mem);
1167      zend_hash_add(&EG(included_files), file_handle->opened_path, strlen(file_handle->opened_path)+1, (void *)&dummy, sizeof(int), NULL);
1168      file_handle->handle.fp = NULL;
1169#endif
1170    }
1171    DBG(ea_debug_printf, (EA_TEST_PERFORMANCE, "\t[%d] compile_file: restored (%ld)\n", getpid(), ea_debug_elapsed_time(&tv_start)));
1172    DBG(ea_debug_printf, (EA_DEBUG, "\t[%d] compile_file: restored\n", getpid()));
1173#ifdef DEBUG
1174    EAG(xpad)-=2;
1175#endif
1176    DBG(ea_debug_printf, (EA_DEBUG, "[%d] Leave COMPILE\n", getpid()));
1177    return t;
1178  } else { // not in cache or must be recompiled
1179    Bucket *function_table_tail;
1180    Bucket *class_table_tail;
1181    HashTable* orig_function_table;
1182    HashTable* orig_class_table;
1183    HashTable* orig_eg_class_table = NULL;
1184    HashTable tmp_function_table;
1185    HashTable tmp_class_table;
1186    zend_function tmp_func;
1187    zend_class_entry tmp_class;
1188    int ea_bailout;
1189
1190#ifdef DEBUG
1191    ea_debug_printf(EA_DEBUG, "\t[%d] compile_file: marking\n", getpid());
1192    if (CG(class_table) != EG(class_table)) {
1193      ea_debug_printf(EA_DEBUG, "\t[%d] oops, CG(class_table)[%08x] != EG(class_table)[%08x]\n", getpid(), CG(class_table), EG(class_table));
1194      ea_debug_log_hashkeys("CG(class_table)\n", CG(class_table));
1195      ea_debug_log_hashkeys("EG(class_table)\n", EG(class_table));
1196    } else {
1197      ea_debug_printf(EA_DEBUG, "\t[%d] OKAY. That what I thought, CG(class_table)[%08x] == EG(class_table)[%08x]\n", getpid(), CG(class_table), EG(class_table));
1198      ea_debug_log_hashkeys("CG(class_table)\n", CG(class_table));
1199    }
1200#endif
1201
1202    /* Storing global pre-compiled functions and classes */
1203    function_table_tail = CG(function_table)->pListTail;
1204    class_table_tail = CG(class_table)->pListTail;
1205
1206    DBG(ea_debug_printf, (EA_TEST_PERFORMANCE, "\t[%d] compile_file: compiling (%ld)\n", getpid(), ea_debug_elapsed_time(&tv_start)));
1207   
1208    if (EAG(optimizer_enabled) && eaccelerator_mm_instance->optimizer_enabled) {
1209      EAG(compiler) = 1;
1210    }
1211
1212        /* try to compile the script */
1213    ea_bailout = 0;
1214    zend_try {
1215      t = mm_saved_zend_compile_file(file_handle, type TSRMLS_CC);
1216    } zend_catch {
1217      ea_bailout = 1;
1218    } zend_end_try();
1219    if (ea_bailout) {
1220      zend_bailout();
1221    }
1222    DBG(ea_debug_log_hashkeys, ("class_table\n", CG(class_table)));
1223
1224    EAG(compiler) = 0;
1225    if (t != NULL && file_handle->opened_path != NULL && (eaccelerator_check_mtime ||
1226         ((stat(file_handle->opened_path, &buf) == 0) && S_ISREG(buf.st_mode)))) {
1227      DBG(ea_debug_printf, (EA_TEST_PERFORMANCE, "\t[%d] compile_file: storing in cache (%ld)\n", getpid(), ea_debug_elapsed_time(&tv_start)));
1228      DBG(ea_debug_printf, (EA_DEBUG, "\t[%d] compile_file: storing in cache\n", getpid()));
1229      function_table_tail = function_table_tail ? function_table_tail->pListNext : CG(function_table)->pListHead;
1230      class_table_tail = class_table_tail ? class_table_tail->pListNext : CG(class_table)->pListHead;
1231      if (eaccelerator_store(file_handle->opened_path, &buf, nreloads, t, function_table_tail, class_table_tail TSRMLS_CC)) {
1232#ifdef DEBUG
1233        ea_debug_log("[%d] EACCELERATOR %s: \"%s\"\n", getpid(), (nreloads == 1) ? "cached" : "re-cached", file_handle->opened_path);
1234#else
1235        ea_debug_log("EACCELERATOR %s: \"%s\"\n", (nreloads == 1) ? "cached" : "re-cached", file_handle->opened_path);
1236#endif
1237      } else {
1238#ifdef DEBUG
1239        ea_debug_log("[%d] EACCELERATOR can't cache: \"%s\"\n", getpid(), file_handle->opened_path);
1240#else
1241        ea_debug_log("EACCELERATOR can't cache: \"%s\"\n", file_handle->opened_path);
1242#endif
1243      }
1244    } else {
1245      function_table_tail = function_table_tail ? function_table_tail->pListNext : CG(function_table)->pListHead;
1246      class_table_tail = class_table_tail ? class_table_tail->pListNext : CG(class_table)->pListHead;
1247    }
1248  }
1249  DBG(ea_debug_printf, (EA_TEST_PERFORMANCE, "\t[%d] compile_file: end (%ld)\n", getpid(), ea_debug_elapsed_time(&tv_start)));
1250  DBG(ea_debug_printf, (EA_DEBUG, "\t[%d] compile_file: end\n", getpid()));
1251#ifdef DEBUG
1252  EAG(xpad)-=2;
1253#endif
1254  DBG(ea_debug_printf, (EA_DEBUG, "[%d] Leave COMPILE\n", getpid()));
1255  return t;
1256}
1257
1258#ifdef DEBUG
1259static void profile_execute(zend_op_array *op_array TSRMLS_DC)
1260{
1261  int i;
1262  struct timeval tv_start;
1263  long usec;
1264
1265  for (i=0;i<EAG(profile_level);i++)
1266    DBG(ea_debug_put, (EA_PROFILE_OPCODES, "  "));
1267  ea_debug_printf(EA_PROFILE_OPCODES, "enter profile_execute: %s:%s\n", op_array->filename, op_array->function_name);
1268  ea_debug_start_time(&tv_start);
1269  EAG(self_time)[EAG(profile_level)] = 0;
1270  EAG(profile_level)++;
1271  ea_debug_printf(EA_PROFILE_OPCODES, "About to enter zend_execute...\n");
1272  mm_saved_zend_execute(op_array TSRMLS_CC);
1273  ea_debug_printf(EA_PROFILE_OPCODES, "Finished zend_execute...\n");
1274  usec = ea_debug_elapsed_time(&tv_start);
1275  EAG(profile_level)--;
1276  if (EAG(profile_level) > 0)
1277    EAG(self_time)[EAG(profile_level)-1] += usec;
1278  for (i=0;i<EAG(profile_level);i++)
1279    DBG(ea_debug_put, (EA_PROFILE_OPCODES, "  "));
1280  ea_debug_printf(EA_PROFILE_OPCODES, "leave profile_execute: %s:%s (%ld,%ld)\n", op_array->filename, op_array->function_name, usec, usec-EAG(self_time)[EAG(profile_level)]);
1281}
1282
1283ZEND_DLEXPORT zend_op_array* profile_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) {
1284  zend_op_array *t;
1285  int i;
1286  struct timeval tv_start;
1287  long usec;
1288
1289  ea_debug_start_time(&tv_start);
1290  EAG(self_time)[EAG(profile_level)] = 0;
1291  t = eaccelerator_compile_file(file_handle, type TSRMLS_CC);
1292  usec = ea_debug_elapsed_time(&tv_start);
1293  if (EAG(profile_level) > 0)
1294    EAG(self_time)[EAG(profile_level)-1] += usec;
1295  for (i=0;i<EAG(profile_level);i++)
1296    DBG(ea_debug_put, (EA_PROFILE_OPCODES, "  "));
1297  ea_debug_printf(EA_DEBUG, "zend_op_array compile: %s (%ld)\n", file_handle->filename, usec);
1298  return t;
1299}
1300
1301#endif  /* DEBUG */
1302
1303/* Format Bytes */
1304void format_size(char* s, unsigned int size, int legend) {
1305  unsigned int i = 0;
1306  unsigned int n = 0;
1307  char ch;
1308  do {
1309    if ((n != 0) && (n % 3 == 0)) {
1310      s[i++] = ',';
1311    }
1312    s[i++] = (char)((int)'0' + (size % 10));
1313    n++;
1314    size = size / 10;
1315  } while (size != 0);
1316  s[i] = '\0';
1317  n = 0; i--;
1318  while (n < i) {
1319    ch = s[n];
1320    s[n] = s[i];
1321    s[i] = ch;
1322    n++, i--;
1323  }
1324  if (legend) {
1325    strcat(s, " Bytes");
1326  }
1327}
1328
1329/* eAccelerator entry for phpinfo() */
1330PHP_MINFO_FUNCTION(eaccelerator) {
1331  char s[32];
1332
1333  php_info_print_table_start();
1334  php_info_print_table_header(2, "eAccelerator support", "enabled");
1335  php_info_print_table_row(2, "Version", EACCELERATOR_VERSION);
1336  php_info_print_table_row(2, "Caching Enabled", (EAG(enabled) && (eaccelerator_mm_instance != NULL) &&
1337              eaccelerator_mm_instance->enabled)?"true":"false");
1338  php_info_print_table_row(2, "Optimizer Enabled", (EAG(optimizer_enabled) &&
1339              (eaccelerator_mm_instance != NULL) && eaccelerator_mm_instance->optimizer_enabled)?"true":"false");
1340  if (eaccelerator_mm_instance != NULL) {
1341    size_t available;
1342    EACCELERATOR_UNPROTECT();
1343    available = mm_available(eaccelerator_mm_instance->mm);
1344    EACCELERATOR_LOCK_RD();
1345    EACCELERATOR_PROTECT();
1346    format_size(s, eaccelerator_mm_instance->total, 1);
1347    php_info_print_table_row(2, "Memory Size", s);
1348    format_size(s, available, 1);
1349    php_info_print_table_row(2, "Memory Available", s);
1350    format_size(s, eaccelerator_mm_instance->total - available, 1);
1351    php_info_print_table_row(2, "Memory Allocated", s);
1352    snprintf(s, 32, "%u", eaccelerator_mm_instance->hash_cnt);
1353    php_info_print_table_row(2, "Cached Scripts", s);
1354    snprintf(s, 32, "%u", eaccelerator_mm_instance->rem_cnt);
1355    php_info_print_table_row(2, "Removed Scripts", s);
1356    snprintf(s, 32, "%u", eaccelerator_mm_instance->user_hash_cnt);
1357    php_info_print_table_row(2, "Cached Keys", s);
1358    EACCELERATOR_UNPROTECT();
1359    EACCELERATOR_UNLOCK_RD();
1360    EACCELERATOR_PROTECT();
1361  }
1362  php_info_print_table_end();
1363
1364  DISPLAY_INI_ENTRIES();
1365}
1366
1367/******************************************************************************/
1368/*
1369 * Begin of dynamic loadable module interfaces.
1370 * There are two interfaces:
1371 *  - standard php module,
1372 *  - zend extension.
1373 */
1374PHP_INI_MH(eaccelerator_filter) {
1375  ea_cond_entry *p, *q;
1376  char *s = new_value;
1377  char *ss;
1378  int  not;
1379  for (p = EAG(cond_list); p != NULL; p = q) {
1380    q = p->next;
1381    if (p->str) {
1382      free(p->str);
1383    }
1384    free(p);
1385  }
1386  EAG(cond_list) = NULL;
1387  while (*s) {
1388    for (; *s == ' ' || *s == '\t'; s++)
1389      ;
1390    if (*s == 0)
1391      break;
1392    if (*s == '!') {
1393      s++;
1394      not = 1;
1395    } else {
1396      not = 0;
1397    }
1398    ss = s;
1399    for (; *s && *s != ' ' && *s != '\t'; s++)
1400      ;
1401    if ((s > ss) && *ss) {
1402      p = (ea_cond_entry *)malloc(sizeof(ea_cond_entry));
1403      if (p == NULL)
1404        break;
1405      p->not = not;
1406      p->len = s-ss;
1407      p->str = malloc(p->len+1);
1408      memcpy(p->str, ss, p->len);
1409      p->str[p->len] = 0;
1410      p->next = EAG(cond_list);
1411      EAG(cond_list) = p;
1412    }
1413  }
1414  return SUCCESS;
1415}
1416
1417static PHP_INI_MH(eaccelerator_OnUpdateLong) {
1418  long *p = (long*)mh_arg1;
1419  *p = zend_atoi(new_value, new_value_length);
1420  return SUCCESS;
1421}
1422
1423static PHP_INI_MH(eaccelerator_OnUpdateBool) {
1424  zend_bool *p = (zend_bool*)mh_arg1;
1425  if (strncasecmp("on", new_value, sizeof("on"))) {
1426    *p = (zend_bool) atoi(new_value);
1427  } else {
1428    *p = (zend_bool) 1;
1429  }
1430  return SUCCESS;
1431}
1432
1433#ifndef ZEND_ENGINE_2
1434#define OnUpdateLong OnUpdateInt
1435#endif
1436
1437PHP_INI_BEGIN()
1438STD_PHP_INI_ENTRY("eaccelerator.enable",         "1", PHP_INI_ALL, OnUpdateBool, enabled, zend_eaccelerator_globals, eaccelerator_globals)
1439STD_PHP_INI_ENTRY("eaccelerator.optimizer",      "1", PHP_INI_ALL, OnUpdateBool, optimizer_enabled, zend_eaccelerator_globals, eaccelerator_globals)
1440STD_PHP_INI_ENTRY("eaccelerator.compress",       "1", PHP_INI_ALL, OnUpdateBool, compression_enabled, zend_eaccelerator_globals, eaccelerator_globals)
1441STD_PHP_INI_ENTRY("eaccelerator.compress_level", "9", PHP_INI_ALL, OnUpdateLong, compress_level, zend_eaccelerator_globals, eaccelerator_globals)                 
1442ZEND_INI_ENTRY1("eaccelerator.shm_size",        "0", PHP_INI_SYSTEM, eaccelerator_OnUpdateLong, &ea_shm_size)
1443ZEND_INI_ENTRY1("eaccelerator.shm_max",         "0", PHP_INI_SYSTEM, eaccelerator_OnUpdateLong, &ea_shm_max)
1444ZEND_INI_ENTRY1("eaccelerator.shm_ttl",         "0", PHP_INI_SYSTEM, eaccelerator_OnUpdateLong, &ea_shm_ttl)
1445ZEND_INI_ENTRY1("eaccelerator.shm_prune_period", "0", PHP_INI_SYSTEM, eaccelerator_OnUpdateLong, &ea_shm_prune_period)
1446ZEND_INI_ENTRY1("eaccelerator.debug",           "1", PHP_INI_SYSTEM, eaccelerator_OnUpdateLong, &eaccelerator_debug)
1447STD_PHP_INI_ENTRY("eaccelerator.log_file",      "", PHP_INI_SYSTEM, OnUpdateString, eaccelerator_log_file, zend_eaccelerator_globals, eaccelerator_globals)
1448ZEND_INI_ENTRY1("eaccelerator.check_mtime",     "1", PHP_INI_SYSTEM, eaccelerator_OnUpdateBool, &eaccelerator_check_mtime)
1449ZEND_INI_ENTRY1("eaccelerator.shm_only",        "0", PHP_INI_SYSTEM, eaccelerator_OnUpdateBool, &eaccelerator_scripts_shm_only)
1450#ifdef WITH_EACCELERATOR_SHM
1451ZEND_INI_ENTRY("eaccelerator.keys",             "shm_and_disk", PHP_INI_SYSTEM, eaccelerator_OnUpdateKeysCachePlace)
1452#endif
1453#ifdef WITH_EACCELERATOR_SESSIONS
1454ZEND_INI_ENTRY("eaccelerator.sessions",         "shm_and_disk", PHP_INI_SYSTEM, eaccelerator_OnUpdateSessionCachePlace)
1455#endif
1456#ifdef WITH_EACCELERATOR_CONTENT_CACHING
1457ZEND_INI_ENTRY("eaccelerator.content",          "shm_and_disk", PHP_INI_SYSTEM, eaccelerator_OnUpdateContentCachePlace)
1458#endif
1459#ifdef WITH_EACCELERATOR_INFO
1460STD_PHP_INI_ENTRY("eaccelerator.allowed_admin_path",       "", PHP_INI_SYSTEM, OnUpdateString, allowed_admin_path, zend_eaccelerator_globals, eaccelerator_globals)
1461#endif
1462STD_PHP_INI_ENTRY("eaccelerator.cache_dir",      "/tmp/eaccelerator", PHP_INI_SYSTEM, OnUpdateString, cache_dir, zend_eaccelerator_globals, eaccelerator_globals)
1463PHP_INI_ENTRY("eaccelerator.filter",             "",  PHP_INI_ALL, eaccelerator_filter)
1464STD_PHP_INI_ENTRY("eaccelerator.name_space",      "", PHP_INI_SYSTEM, OnUpdateString, name_space, zend_eaccelerator_globals, eaccelerator_globals)
1465PHP_INI_END()
1466
1467static void eaccelerator_clean_request(TSRMLS_D) {
1468  ea_used_entry  *p = (ea_used_entry*)EAG(used_entries);
1469  if (eaccelerator_mm_instance != NULL) {
1470    EACCELERATOR_UNPROTECT();
1471    mm_unlock(eaccelerator_mm_instance->mm);
1472    if (p != NULL || eaccelerator_mm_instance->locks != NULL) {
1473      EACCELERATOR_LOCK_RW();
1474      while (p != NULL) {
1475        p->entry->use_cnt--;
1476        if (p->entry->removed && p->entry->use_cnt <= 0) {
1477          if (eaccelerator_mm_instance->removed == p->entry) {
1478            eaccelerator_mm_instance->removed = p->entry->next;
1479            eaccelerator_mm_instance->rem_cnt--;
1480            eaccelerator_free_nolock(p->entry);
1481            p->entry = NULL;
1482          } else {
1483            ea_cache_entry *q = eaccelerator_mm_instance->removed;
1484            while (q != NULL && q->next != p->entry) {
1485              q = q->next;
1486            }
1487            if (q != NULL) {
1488              q->next = p->entry->next;
1489              eaccelerator_mm_instance->rem_cnt--;
1490              eaccelerator_free_nolock(p->entry);
1491              p->entry = NULL;
1492            }
1493          }
1494        }
1495        p = p->next;
1496      }
1497      if (eaccelerator_mm_instance->locks != NULL) {
1498        pid_t    pid    = getpid();
1499#ifdef ZTS
1500        THREAD_T thread = tsrm_thread_id();
1501#endif
1502        ea_lock_entry** p = &eaccelerator_mm_instance->locks;
1503        while ((*p) != NULL) {
1504#ifdef ZTS
1505          if ((*p)->pid == pid && (*p)->thread == thread) {
1506#else
1507          if ((*p)->pid == pid) {
1508#endif
1509            ea_lock_entry* x = *p;
1510            *p = (*p)->next;
1511            eaccelerator_free_nolock(x);
1512          } else {
1513            p = &(*p)->next;
1514          }
1515        }
1516      }
1517      EACCELERATOR_UNLOCK_RW();
1518    }
1519    EACCELERATOR_PROTECT();
1520    p = (ea_used_entry*)EAG(used_entries);
1521    while (p != NULL) {
1522      ea_used_entry* r = p;
1523      p = p->next;
1524      if (r->entry != NULL && r->entry->use_cnt < 0) {
1525        efree(r->entry);
1526      }
1527      efree(r);
1528    }
1529  }
1530  EAG(used_entries) = NULL;
1531  EAG(in_request) = 0;
1532}
1533
1534#if (__GNUC__ >= 3) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 91))
1535static void __attribute__((destructor)) eaccelerator_clean_shutdown(void)
1536#else
1537void _fini(void)
1538#endif
1539{
1540  if (eaccelerator_mm_instance != NULL) {
1541    TSRMLS_FETCH();
1542    if (EAG(in_request)) {
1543      fflush(stdout);
1544      fflush(stderr);
1545      eaccelerator_clean_request(TSRMLS_C);
1546      if (EG(active_op_array)) {
1547        DBG(ea_debug_error, ("[%d] EACCELERATOR: PHP unclean shutdown on opline %ld of %s() at %s:%u\n\n",
1548          getpid(),
1549          (long)(active_opline-EG(active_op_array)->opcodes),
1550          get_active_function_name(TSRMLS_C),
1551          zend_get_executed_filename(TSRMLS_C),
1552          zend_get_executed_lineno(TSRMLS_C)));
1553      } else {
1554        DBG(ea_debug_error, ("[%d] EACCELERATOR: PHP unclean shutdown\n\n",getpid()));
1555      }
1556    }
1557  }
1558}
1559
1560/* signal handlers */
1561#ifdef WITH_EACCELERATOR_CRASH_DETECTION
1562static void eaccelerator_crash_handler(int dummy) {
1563  TSRMLS_FETCH();
1564  fflush(stdout);
1565  fflush(stderr);
1566#ifdef SIGSEGV
1567  if (EAG(original_sigsegv_handler) != eaccelerator_crash_handler) {
1568    signal(SIGSEGV, EAG(original_sigsegv_handler));
1569  } else {
1570    signal(SIGSEGV, SIG_DFL);
1571  }
1572#endif
1573#ifdef SIGFPE
1574  if (EAG(original_sigfpe_handler) != eaccelerator_crash_handler) {
1575    signal(SIGFPE, EAG(original_sigfpe_handler));
1576  } else {
1577    signal(SIGFPE, SIG_DFL);
1578  }
1579#endif
1580#ifdef SIGBUS
1581  if (EAG(original_sigbus_handler) != eaccelerator_crash_handler) {
1582    signal(SIGBUS, EAG(original_sigbus_handler));
1583  } else {
1584    signal(SIGBUS, SIG_DFL);
1585  }
1586#endif
1587#ifdef SIGILL
1588  if (EAG(original_sigill_handler) != eaccelerator_crash_handler) {
1589    signal(SIGILL, EAG(original_sigill_handler));
1590  } else {
1591    signal(SIGILL, SIG_DFL);
1592  }
1593#endif
1594#ifdef SIGABRT
1595  if (EAG(original_sigabrt_handler) != eaccelerator_crash_handler) {
1596    signal(SIGABRT, EAG(original_sigabrt_handler));
1597  } else {
1598    signal(SIGABRT, SIG_DFL);
1599  }
1600#endif
1601  eaccelerator_clean_request(TSRMLS_C);
1602  if (EG(active_op_array)) {
1603    fprintf(stderr, "[%d] EACCELERATOR: PHP crashed on opline %ld of %s() at %s:%u\n\n",
1604      getpid(),
1605      (long)(active_opline-EG(active_op_array)->opcodes),
1606      get_active_function_name(TSRMLS_C),
1607      zend_get_executed_filename(TSRMLS_C),
1608      zend_get_executed_lineno(TSRMLS_C));
1609  } else {
1610    fprintf(stderr, "[%d] EACCELERATOR: PHP crashed\n\n",getpid());
1611  }
1612#if !defined(WIN32) && !defined(NETWARE)
1613  kill(getpid(), dummy);
1614#else
1615  raise(dummy);
1616#endif
1617}
1618#endif
1619
1620static void eaccelerator_init_globals(zend_eaccelerator_globals *eaccelerator_globals)
1621{
1622  eaccelerator_globals->used_entries      = NULL;
1623  eaccelerator_globals->enabled           = 1;
1624  eaccelerator_globals->cache_dir         = NULL;
1625  eaccelerator_globals->optimizer_enabled = 1;
1626  eaccelerator_globals->compiler          = 0;
1627  eaccelerator_globals->cond_list         = NULL;
1628  eaccelerator_globals->content_headers   = NULL;
1629#ifdef WITH_EACCELERATOR_SESSIONS
1630  eaccelerator_globals->session           = NULL;
1631#endif
1632  eaccelerator_globals->eaccelerator_log_file = '\000';
1633  eaccelerator_globals->name_space        = '\000';
1634  eaccelerator_globals->hostname[0]       = '\000';
1635  eaccelerator_globals->in_request        = 0;
1636  eaccelerator_globals->allowed_admin_path= NULL;
1637}
1638
1639static void eaccelerator_globals_dtor(zend_eaccelerator_globals *eaccelerator_globals)
1640{
1641  ea_cond_entry *p, *q;
1642
1643  for (p = eaccelerator_globals->cond_list; p != NULL; p = q) {
1644    q = p->next;
1645    if (p->str) {
1646      free(p->str);
1647    }
1648    free(p);
1649  }
1650  eaccelerator_globals->cond_list = NULL;
1651}
1652
1653static void register_eaccelerator_as_zend_extension();
1654
1655static int eaccelerator_check_php_version(TSRMLS_D) {
1656  zval v;
1657  int ret = 0;
1658  if (zend_get_constant("PHP_VERSION", sizeof("PHP_VERSION")-1, &v TSRMLS_CC)) {
1659    if (Z_TYPE(v) == IS_STRING &&
1660        Z_STRLEN(v) == sizeof(PHP_VERSION)-1 &&
1661        strcmp(Z_STRVAL(v),PHP_VERSION) == 0) {
1662      ret = 1;
1663    } else {
1664      zend_error(E_CORE_WARNING,"[%s] This build of \"%s\" was compiled for PHP version %s. Rebuild it for your PHP version (%s) or download precompiled binaries.\n", EACCELERATOR_EXTENSION_NAME,EACCELERATOR_EXTENSION_NAME,PHP_VERSION,Z_STRVAL(v));
1665    }
1666    zval_dtor(&v);
1667  } else {
1668    zend_error(E_CORE_WARNING,"[%s] This build of \"%s\" was compiled for PHP version %s. Rebuild it for your PHP version.\n", EACCELERATOR_EXTENSION_NAME,EACCELERATOR_EXTENSION_NAME,PHP_VERSION);
1669  }
1670  return ret;
1671}
1672
1673static void make_hash_dirs(char *fullpath, int lvl) {
1674  int j;
1675  int n = strlen(fullpath);
1676  mode_t old_umask = umask(0);
1677 
1678  if (lvl < 1)
1679    return;
1680  if (fullpath[n-1] != '/')
1681    fullpath[n++] = '/';
1682 
1683  for (j = 0; j < 16; j++) {
1684    fullpath[n] = num2hex[j];       
1685    fullpath[n+1] = 0;
1686    mkdir(fullpath, 0777);
1687    make_hash_dirs(fullpath, lvl-1);
1688  }
1689  fullpath[n+2] = 0;
1690  umask(old_umask);
1691}
1692
1693
1694PHP_MINIT_FUNCTION(eaccelerator) {
1695  char fullpath[MAXPATHLEN];
1696
1697  if (type == MODULE_PERSISTENT) {
1698#ifndef ZEND_WIN32
1699    if (strcmp(sapi_module.name,"apache") == 0) {
1700      if (getpid() != getpgrp()) {
1701        return SUCCESS;
1702      }
1703    }
1704#endif
1705  }
1706  if (!eaccelerator_check_php_version(TSRMLS_C)) {
1707    return FAILURE;
1708  }
1709  ZEND_INIT_MODULE_GLOBALS(eaccelerator, eaccelerator_init_globals, NULL);
1710  REGISTER_INI_ENTRIES();
1711  REGISTER_STRING_CONSTANT("EACCELERATOR_VERSION", EACCELERATOR_VERSION, CONST_CS | CONST_PERSISTENT);
1712  REGISTER_LONG_CONSTANT("EACCELERATOR_SHM_AND_DISK", ea_shm_and_disk, CONST_CS | CONST_PERSISTENT);
1713  REGISTER_LONG_CONSTANT("EACCELERATOR_SHM", ea_shm, CONST_CS | CONST_PERSISTENT);
1714  REGISTER_LONG_CONSTANT("EACCELERATOR_SHM_ONLY", ea_shm_only, CONST_CS | CONST_PERSISTENT);
1715  REGISTER_LONG_CONSTANT("EACCELERATOR_DISK_ONLY", ea_disk_only, CONST_CS | CONST_PERSISTENT);
1716  REGISTER_LONG_CONSTANT("EACCELERATOR_NONE", ea_none, CONST_CS | CONST_PERSISTENT);
1717  binary_eaccelerator_version = encode_version(EACCELERATOR_VERSION);
1718  binary_php_version = encode_version(PHP_VERSION);
1719  binary_zend_version = encode_version(ZEND_VERSION);
1720  eaccelerator_is_extension = 1;
1721
1722  ea_debug_init(TSRMLS_C);
1723
1724  if(!eaccelerator_scripts_shm_only) {
1725    snprintf(fullpath, MAXPATHLEN-1, "%s/", EAG(cache_dir));
1726    make_hash_dirs(fullpath, EACCELERATOR_HASH_LEVEL);
1727  }
1728
1729  if (type == MODULE_PERSISTENT &&
1730      strcmp(sapi_module.name, "cgi") != 0 &&
1731      strcmp(sapi_module.name, "cli") != 0) {
1732    DBG(ea_debug_put, (EA_DEBUG, "\n=======================================\n"));
1733    DBG(ea_debug_printf, (EA_DEBUG, "[%d] EACCELERATOR STARTED\n", getpid()));
1734    DBG(ea_debug_put, (EA_DEBUG, "=======================================\n"));
1735
1736    if (init_mm(TSRMLS_C) == FAILURE) {
1737      zend_error(E_CORE_WARNING,"[%s] Can not create shared memory area", EACCELERATOR_EXTENSION_NAME);
1738      return FAILURE;
1739    }
1740    mm_saved_zend_compile_file = zend_compile_file;
1741
1742#ifdef DEBUG
1743    zend_compile_file = profile_compile_file;
1744    mm_saved_zend_execute = zend_execute;
1745    zend_execute = profile_execute;
1746#else
1747    zend_compile_file = eaccelerator_compile_file;
1748#endif
1749  }
1750 
1751#ifdef WITH_EACCELERATOR_SESSIONS
1752  eaccelerator_register_session();
1753#endif
1754#ifdef WITH_EACCELERATOR_CONTENT_CACHING
1755  eaccelerator_content_cache_startup();
1756#endif
1757  if (!eaccelerator_is_zend_extension) {
1758    register_eaccelerator_as_zend_extension();
1759  }
1760 
1761#ifdef ZEND_ENGINE_2
1762  /* cache the properties_info destructor */
1763  properties_info_dtor = get_zend_destroy_property_info(TSRMLS_C);
1764#endif
1765  return SUCCESS;
1766}
1767
1768PHP_MSHUTDOWN_FUNCTION(eaccelerator) {
1769  if (eaccelerator_mm_instance == NULL || !eaccelerator_is_extension) {
1770    return SUCCESS;
1771  }
1772  zend_compile_file = mm_saved_zend_compile_file;
1773#ifdef WITH_EACCELERATOR_CONTENT_CACHING
1774  eaccelerator_content_cache_shutdown();
1775#endif
1776  shutdown_mm(TSRMLS_C);
1777  DBG(ea_debug_put, (EA_DEBUG, "========================================\n"));
1778  DBG(ea_debug_printf, (EA_DEBUG, "[%d] EACCELERATOR STOPPED\n", getpid()));
1779  DBG(ea_debug_put, (EA_DEBUG, "========================================\n\n"));
1780  ea_debug_shutdown();
1781  UNREGISTER_INI_ENTRIES();
1782#ifdef ZTS
1783  ts_free_id(eaccelerator_globals_id);
1784#else
1785  eaccelerator_globals_dtor(&eaccelerator_globals TSRMLS_CC);
1786#endif
1787  eaccelerator_is_zend_extension = 0;
1788  eaccelerator_is_extension = 0;
1789  return SUCCESS;
1790}
1791
1792PHP_RINIT_FUNCTION(eaccelerator)
1793{
1794  union {
1795                zval **v;
1796    void *ptr;
1797  } server_vars, hostname;
1798
1799        if (eaccelerator_mm_instance == NULL) {
1800                return SUCCESS;
1801        }
1802
1803        /*
1804         * Initialization on first call, comes from eaccelerator_zend_startup().
1805         */
1806        if (eaccelerator_global_function_table.nTableSize == 0) {
1807                zend_function tmp_func;
1808                zend_class_entry tmp_class;
1809
1810                zend_hash_init_ex(&eaccelerator_global_function_table, 100, NULL, NULL, 1, 0);
1811                zend_hash_copy(&eaccelerator_global_function_table, CG(function_table), NULL,
1812                        &tmp_func, sizeof(zend_function));
1813               
1814                zend_hash_init_ex(&eaccelerator_global_class_table, 10, NULL, NULL, 1, 0);
1815                zend_hash_copy(&eaccelerator_global_class_table, CG(class_table), NULL,
1816                        &tmp_class, sizeof(zend_class_entry));
1817        }
1818
1819        DBG(ea_debug_printf, (EA_DEBUG, "[%d] Enter RINIT\n",getpid()));
1820        DBG(ea_debug_put, (EA_PROFILE_OPCODES, "\n========================================\n"));
1821
1822        EAG(in_request) = 1;
1823        EAG(used_entries) = NULL;
1824        EAG(compiler) = 0;
1825        EAG(refcount_helper) = 1;
1826        EAG(compress_content) = 1;
1827        EAG(content_headers) = NULL;
1828
1829        /* Storing Host Name */
1830        EAG(hostname)[0] = '\000';
1831  if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), &server_vars.ptr) == SUCCESS &&
1832                        Z_TYPE_PP(server_vars.v) == IS_ARRAY &&
1833                        zend_hash_find(Z_ARRVAL_PP(server_vars.v), "SERVER_NAME", sizeof("SERVER_NAME"), &hostname.ptr)==SUCCESS &&
1834                        Z_TYPE_PP(hostname.v) == IS_STRING && Z_STRLEN_PP(hostname.v) > 0) {
1835                if (sizeof(EAG(hostname)) > Z_STRLEN_PP(hostname.v)) {
1836                        memcpy(EAG(hostname),Z_STRVAL_PP(hostname.v),Z_STRLEN_PP(hostname.v)+1);
1837                } else {
1838                        memcpy(EAG(hostname),Z_STRVAL_PP(hostname.v),sizeof(EAG(hostname))-1);
1839                        EAG(hostname)[sizeof(EAG(hostname))-1] = '\000';
1840                }
1841  }
1842
1843        zend_hash_init(&EAG(restored), 0, NULL, NULL, 0);
1844
1845        DBG(ea_debug_printf, (EA_DEBUG, "[%d] Leave RINIT\n",getpid()));
1846#ifdef DEBUG
1847        EAG(xpad) = 0;
1848        EAG(profile_level) = 0;
1849#endif
1850
1851#ifdef WITH_EACCELERATOR_CRASH_DETECTION
1852#ifdef SIGSEGV
1853        EAG(original_sigsegv_handler) = signal(SIGSEGV, eaccelerator_crash_handler);
1854#endif
1855#ifdef SIGFPE
1856        EAG(original_sigfpe_handler) = signal(SIGFPE, eaccelerator_crash_handler);
1857#endif
1858#ifdef SIGBUS
1859        EAG(original_sigbus_handler) = signal(SIGBUS, eaccelerator_crash_handler);
1860#endif
1861#ifdef SIGILL
1862        EAG(original_sigill_handler) = signal(SIGILL, eaccelerator_crash_handler);
1863#endif
1864#ifdef SIGABRT
1865        EAG(original_sigabrt_handler) = signal(SIGABRT, eaccelerator_crash_handler);
1866#endif
1867#endif
1868        return SUCCESS;
1869}
1870
1871PHP_RSHUTDOWN_FUNCTION(eaccelerator)
1872{
1873        if (eaccelerator_mm_instance == NULL) {
1874                return SUCCESS;
1875        }
1876        zend_hash_destroy(&EAG(restored));
1877#ifdef WITH_EACCELERATOR_CRASH_DETECTION
1878#ifdef SIGSEGV
1879        if (EAG(original_sigsegv_handler) != eaccelerator_crash_handler) {
1880                signal(SIGSEGV, EAG(original_sigsegv_handler));
1881        } else {
1882                signal(SIGSEGV, SIG_DFL);
1883        }
1884#endif
1885#ifdef SIGFPE
1886        if (EAG(original_sigfpe_handler) != eaccelerator_crash_handler) {
1887                signal(SIGFPE, EAG(original_sigfpe_handler));
1888        } else {
1889                signal(SIGFPE, SIG_DFL);
1890        }
1891#endif
1892#ifdef SIGBUS
1893        if (EAG(original_sigbus_handler) != eaccelerator_crash_handler) {
1894                signal(SIGBUS, EAG(original_sigbus_handler));
1895        } else {
1896                signal(SIGBUS, SIG_DFL);
1897        }
1898#endif
1899#ifdef SIGILL
1900        if (EAG(original_sigill_handler) != eaccelerator_crash_handler) {
1901                signal(SIGILL, EAG(original_sigill_handler));
1902        } else {
1903                signal(SIGILL, SIG_DFL);
1904        }
1905#endif
1906#ifdef SIGABRT
1907        if (EAG(original_sigabrt_handler) != eaccelerator_crash_handler) {
1908                signal(SIGABRT, EAG(original_sigabrt_handler));
1909        } else {
1910                signal(SIGABRT, SIG_DFL);
1911        }
1912#endif
1913#endif
1914        DBG(ea_debug_printf, (EA_DEBUG, "[%d] Enter RSHUTDOWN\n",getpid()));
1915        eaccelerator_clean_request(TSRMLS_C);
1916        DBG(ea_debug_printf, (EA_DEBUG, "[%d] Leave RSHUTDOWN\n",getpid()));
1917        return SUCCESS;
1918}
1919
1920#ifdef ZEND_ENGINE_2
1921ZEND_BEGIN_ARG_INFO(eaccelerator_second_arg_force_ref, 0)
1922  ZEND_ARG_PASS_INFO(0)
1923  ZEND_ARG_PASS_INFO(1)
1924ZEND_END_ARG_INFO();
1925#else
1926static unsigned char eaccelerator_second_arg_force_ref[] = {2, BYREF_NONE, BYREF_FORCE};
1927#endif
1928
1929function_entry eaccelerator_functions[] = {
1930#ifdef WITH_EACCELERATOR_SHM
1931  PHP_FE(eaccelerator_put, NULL)
1932  PHP_FE(eaccelerator_get, NULL)
1933  PHP_FE(eaccelerator_rm, NULL)
1934  PHP_FE(eaccelerator_gc, NULL)
1935  PHP_FE(eaccelerator_lock, NULL)
1936  PHP_FE(eaccelerator_unlock, NULL)
1937#endif
1938#ifdef WITH_EACCELERATOR_INFO
1939  PHP_FE(eaccelerator_caching, NULL)
1940  #ifdef WITH_EACCELERATOR_OPTIMIZER
1941  PHP_FE(eaccelerator_optimizer, NULL)
1942  #endif
1943  PHP_FE(eaccelerator_clear, NULL)
1944  PHP_FE(eaccelerator_clean, NULL)
1945  PHP_FE(eaccelerator_info, NULL)
1946  PHP_FE(eaccelerator_purge, NULL)
1947  PHP_FE(eaccelerator_cached_scripts, NULL)
1948  PHP_FE(eaccelerator_removed_scripts, NULL)
1949  PHP_FE(eaccelerator_list_keys, NULL)
1950#endif
1951#ifdef WITH_EACCELERATOR_CONTENT_CACHING
1952  PHP_FE(_eaccelerator_output_handler, NULL)
1953  PHP_FE(eaccelerator_cache_page, NULL)
1954  PHP_FE(eaccelerator_rm_page, NULL)
1955  PHP_FE(eaccelerator_cache_output, NULL)
1956  PHP_FE(eaccelerator_cache_result, NULL)
1957#endif
1958#ifdef WITH_EACCELERATOR_DISASSEMBLER
1959  PHP_FE(eaccelerator_dasm_file, NULL)
1960#endif
1961#ifdef ZEND_ENGINE_2
1962  {NULL, NULL, NULL, 0U, 0U}
1963#else
1964  {NULL, NULL, NULL}
1965#endif
1966};
1967
1968zend_module_entry eaccelerator_module_entry = {
1969#if ZEND_MODULE_API_NO >= 20010901
1970  STANDARD_MODULE_HEADER,
1971#endif
1972  EACCELERATOR_EXTENSION_NAME,
1973  eaccelerator_functions,
1974  PHP_MINIT(eaccelerator),
1975  PHP_MSHUTDOWN(eaccelerator),
1976  PHP_RINIT(eaccelerator),
1977  PHP_RSHUTDOWN(eaccelerator),
1978  PHP_MINFO(eaccelerator),
1979#if ZEND_MODULE_API_NO >= 20010901
1980  EACCELERATOR_VERSION,          /* extension version number (string) */
1981#endif
1982  STANDARD_MODULE_PROPERTIES
1983};
1984
1985#if defined(COMPILE_DL_EACCELERATOR)
1986ZEND_GET_MODULE(eaccelerator)
1987#endif
1988
1989static startup_func_t last_startup;
1990static zend_llist_element *eaccelerator_el;
1991
1992static const unsigned char eaccelerator_logo[] = {
1993      71,  73,  70,  56,  57,  97,  88,   0,  31,   0,
1994     213,   0,   0, 150, 153, 196, 237, 168,  86, 187,
1995     206, 230,   4,   4,   4, 108, 110, 144,  99, 144,
1996     199, 136, 138, 184,  87,  88, 109, 165, 165, 167,
1997     163, 166, 202, 240, 151,  44, 149,  91,  21, 225,
1998     225, 229,   4,  76, 164, 252, 215, 171, 255, 255,
1999     255, 212, 212, 224, 241, 200, 149, 141, 144, 192,
2000     216, 216, 226, 251, 230, 205, 192, 193, 218, 207,
2001     221, 238, 181, 188, 216, 130, 132, 168, 150, 152,
2002     185, 152, 152, 154, 180, 181, 198, 215, 184, 147,
2003      40, 102, 177, 224, 232, 242, 244, 244, 244, 235,
2004     236, 239, 118, 121, 157, 193, 193, 194, 146, 148,
2005     174, 181, 143,  96, 154, 183, 219, 156, 159, 200,
2006     126, 128, 170, 174, 175, 193,  65,  39,   7, 232,
2007     214, 192, 254, 241, 226, 246, 246, 248, 108,  65,
2008      13, 142, 144, 185, 252, 224, 189, 138, 171, 213,
2009      69, 122, 188, 239, 244, 249,  48,  49,  60, 176,
2010     178, 209, 200, 201, 222, 252, 252, 253, 251, 251,
2011     251, 162, 163, 187, 208, 208, 213, 169, 171, 205,
2012     241, 234, 225, 255, 252, 249, 254, 248, 241, 140,
2013     142, 169, 249, 186, 111,  33, 249,   4,   0,   0,
2014       0,   0,   0,  44,   0,   0,   0,   0,  88,   0,
2015      31,   0,   0,   6, 255,  64, 137, 112,  72,  44,
2016      26, 143, 200, 164, 114, 201,  92,  62, 158, 208,
2017     168, 116,  74, 173,  90, 175, 216, 108,  85, 168,
2018     237, 122, 191,  15,  25, 163, 118, 209, 153,   0,
2019      68, 128,  73, 119, 169,  49, 100,  86,  46, 120,
2020      78, 127, 216,  60,  21,  93,  83,   8, 208,  85,
2021      60,  54,  83, 114, 117, 132,  89,  32,  23,  38,
2022      73,  38, 103,  72,  38,  23,  32,  82, 123, 146,
2023     147,  69, 106,   9,  52,  21,  19,  53, 137, 138,
2024      51,  51, 156, 141,  21, 100,  52,   9, 148, 166,
2025     123,   0, 106, 126,  16,  21, 104,  67, 169, 106,
2026     140,   9,   3, 159, 140,  18, 176, 182,   0,  23,
2027      21, 101,  67,  21,  80,  32,  52, 192,  52,  44,
2028       6,  16,  15,   6,  23,  44,  81,  24,  81,  25,
2029      81, 194,  80,  25,   6,  18,  12,  80,  23,  15,
2030     169,  15, 172, 155, 105,  33,   7,   4, 158,  46,
2031       0,  33,   3,   7,   7,  51,   7, 139, 231, 225,
2032       7,  25, 124,  23,  23,  52, 190,  19,   4, 205,
2033      44,  27,   4,   4,  19,  57,  15,  33,  15,  32,
2034      54,  64, 168, 241,   0,   5,  10,  28, 255,  54,
2035     160, 120, 128, 163, 160,  65,   2,  15, 244, 229,
2036     200, 113, 162,  26,   4,  20, 252,  22, 130, 128,
2037      48,  98, 131,  30,  34,  38, 102, 208,  58,  64,
2038     203,   4,  73, 115,   3,   6, 184, 152,  69,  75,
2039     228,   1,  87,  38,  80, 204,  19, 242, 235,   9,
2040      54,  31,   4,  78, 212, 152, 192, 128,   1,   8,
2041     255,  31,  79,  78, 108,  99, 245, 239,  24,   3,
2042     136,  16,  32, 212, 139,  24,  34,  83,   8,   3,
2043      62,  33, 128,  56,  90,   3,  68, 136,  17, 173,
2044     138, 176,  76,  16, 114,  64,   2, 145,   4,   0,
2045     136, 196, 128, 129,  22, 215, 146,  66,  50, 224,
2046     248,  40,  33, 147,  62,   2,  11,  39, 120, 120,
2047      48, 162,  33,  10,   2,  44,  62,  64, 156, 144,
2048     244,  31, 129,  17,  12,  31, 240, 157, 240,  76,
2049     238, 131,  12,   4, 160, 110,   4,   1, 130, 192,
2050       6,   6,  33, 112, 212,  48, 226, 195, 220,  25,
2051     145,  95, 189, 118,  77,  64,  50, 236, 172,  79,
2052      66,  92, 140,  96,  11,   0,  71,  78,  12,  39,
2053      12, 108, 200,  71,  32,  68, 190,  16,  38,  70,
2054      56,  54, 120,  87,  71, 136,  16,  25,  70,  36,
2055     160, 141,  65,  33,  10,  12,  57,  13,  36, 240,
2056     173,  15,  64,   2,  31,  58, 186, 189,  34,  96,
2057     238,  86,  73,  90, 198,  75, 146,  12,   1, 128,
2058     249, 203, 208,  62,  74,   9,  49,  96,   0,   3,
2059      53,   9,   6,  78, 220,  78, 141, 218, 251, 137,
2060      19, 168, 199, 163, 230,  46, 254, 246, 120, 247,
2061     169, 193, 183, 127, 234,  34,  67,   6,  63,  51,
2062     249, 156,  12,  55, 160, 181,  57, 114, 255, 137,
2063      52,   3, 127,  62,  12, 129,  65, 118,  74, 112,
2064     247,  29, 120, 219,  81, 163, 224, 130, 224,  61,
2065      40, 225, 130,  15, 222, 162,  74,  60, 160, 116,
2066     181,  95,   6,  36, 189, 212, 255, 225, 103,  39,
2067      97, 224,  74, 119, 186, 157,  98, 162,  18, 169,
2068     172,  65,   3,  13,  40, 184, 178, 149,  14,   9,
2069     160,  97,   2,  87,  18, 204, 104,  66,  89,  51,
2070      24,  23, 163,  16,  62, 132, 224, 195,  90,  39,
2071       6, 121, 132,  37,  58, 176, 136, 195,  59,  46,
2072     152, 133,  98, 135, 174,   8, 129, 129, 143,  56,
2073      36, 160,  93,  33,  84,  82,  97,   3,  11,  12,
2074     136, 128,   3,  66, 227,  44,  49,   2, 110,  67,
2075     248, 224, 131,   6,  34,  48, 176, 204,   3, 131,
2076      84, 169, 230,  19,  44, 128, 144, 195,   6,  71,
2077     190, 179,   4,  26,  46, 136, 169,   1,  10,  57,
2078     236, 192,   2,  15,  79, 164, 185, 166, 154,  55,
2079     124, 192, 192, 155,   8, 228,  54, 130,  11, 136,
2080     134,  86, 167, 152,  99,  34, 176,  65,  14,  12,
2081     124,  16,   8,  20, 126,  62, 176,   2,   5,  20,
2082     188, 160, 233, 166, 155,  58, 224, 105,   4,  61,
2083     252,  73,  69, 160,  59,  12,  42,   2,  10,   8,
2084      32, 160, 193, 170, 171, 166, 138, 130,   8, 144,
2085     238, 240,   1, 159, 145,  72,   0,   5,  15,  20,
2086      56,  16,  65,   4,  63,   4, 224, 171,   2,   1,
2087       0, 171, 192, 176, 195,   6,  32, 234,  21, 129,
2088     126,  48,  85,  79, 204,  50,  43, 235,   7,  55,
2089     196,  97, 171, 165, 159, 254, 240, 195, 176,  63,
2090     188, 240,   0, 173,  80, 244, 192, 194, 153,   2,
2091     192, 113, 236, 184, 114, 172,  96, 174, 185, 152,
2092      82, 160, 255, 133,   7,  13,  20, 240, 132,  12,
2093       5, 196,  80, 192,  92,  15, 192,  32, 175,   0,
2094      15,  88,  16, 195, 190,  22, 148, 224, 238,  19,
2095     250, 242,  27, 176, 188, 226, 198, 128, 205, 190,
2096     252, 202,  96, 111,   1, 248,  62, 128, 112,   1,
2097      22,  80, 106, 235,  11,  14,  80, 188, 107, 175,
2098     190, 250, 106,  45, 198,   1, 144, 192, 193,  19,
2099       5,  52, 208,  64,  24,  29, 116,  96, 111,   3,
2100     240,  54,   0,  67, 200,   2,   8, 160,  50,  12,
2101      30, 216,  11, 133, 203,  48, 192,  76,  51,  12,
2102     237,  62, 112,  65, 187,  54, 216, 107, 178,   7,
2103      49, 168,  28,  52, 190, 237, 194,  80, 178, 196,
2104      43, 108,  28, 172,   2,  11, 120, 204, 193, 211,
2105      17, 112, 176, 235, 211,  28, 236, 240,  68,   7,
2106      33, 151, 128, 179, 184,  45,  55,  32,  64, 180,
2107      22, 120, 224, 114, 203,  10, 199,  48, 179, 215,
2108     225, 186,  12, 178, 217,  33, 163,  92, 175, 217,
2109      22, 120, 125, 131,  13, 242,  62, 224, 117, 189,
2110      35, 247,  41, 129,   3, 196,  50, 189,  64,  11,
2111      36, 216,  48, 183,  29,  79,   4,  98, 195, 164,
2112      46, 119,  80, 180, 217, 103,  75, 225, 178, 200,
2113       2, 200, 252, 196, 227, 104, 139,  44, 242,   5,
2114      50,  52, 160,  56,  12, 111,  63, 160, 246,  19,
2115     246, 218,  96, 121, 206, 122, 191, 224, 247, 223,
2116      45, 164, 238, 244, 174, 172,  63, 173, 238,   3,
2117       5, 152,  28,  50, 206,  17,  43,  76, 154,  51,
2118     232,  93,  67,  33, 185, 231, 121, 243,  46,  64,
2119      12,  29,  60,  80, 130, 208, 193, 203, 204,  46,
2120     231,  50,  96, 109, 119, 205,  13, 208, 139, 166,
2121     173,  42, 144, 176,  64,  10, 212,  87, 159, 250,
2122       2, 216, 103, 191, 192,  14, 129, 168, 252, 132,
2123     202,  33,   7,  93, 188, 230, 138, 139, 221,   0,
2124     191,  56, 239, 203, 240, 249,  49,  88, 160, 118,
2125     220,  43, 155, 189, 115, 204, 140, 227, 172, 120,
2126     243, 118, 135, 139, 245, 164, 149,  78,  74, 248,
2127     220, 130, 187, 193, 224,  30,  16,  51, 113, 149,
2128     160,   4,  54, 208,  90,   9, 102,  86,  51,  56,
2129     196, 172, 102,  98, 171,  25,  12,  74, 240,  64,
2130     152, 197, 204,  38,  53, 139,  88, 189,  90, 182,
2131     192, 201, 213, 236,  76,  48, 179, 129,   5,  96,
2132     166, 183, 113, 153,  80,  77,  66,  74, 161,  10,
2133      41,  17,   4,   0,  59,   0 };
2134 
2135static int eaccelerator_last_startup(zend_extension *extension) {
2136  int ret;
2137  extension->startup = last_startup;
2138  ret = extension->startup(extension);
2139  zend_extensions.count++;
2140  eaccelerator_el->next = zend_extensions.head;
2141  eaccelerator_el->prev = NULL;
2142  zend_extensions.head->prev = eaccelerator_el;
2143  zend_extensions.head = eaccelerator_el;
2144  if (ZendOptimizer) {
2145    if ((ZendOptimizer = zend_get_extension("Zend Optimizer")) != NULL) {
2146      ZendOptimizer->op_array_handler = NULL;
2147    }
2148  }
2149  return ret;
2150}
2151
2152/*
2153static int eaccelerator_ioncube_startup(zend_extension *extension) {
2154  int ret;
2155  zend_extension* last_ext = (zend_extension*)zend_extensions.tail->data;
2156  extension->startup = last_startup;
2157  ret = extension->startup(extension);
2158  last_startup = last_ext->startup;
2159  last_ext->startup = eaccelerator_last_startup;
2160  return ret;
2161}
2162*/
2163
2164
2165ZEND_DLEXPORT int eaccelerator_zend_startup(zend_extension *extension) {
2166 eaccelerator_is_zend_extension = 1;
2167  eaccelerator_el   = NULL;
2168  last_startup = NULL;
2169
2170  if (!eaccelerator_is_extension) {
2171    if (zend_startup_module(&eaccelerator_module_entry) != SUCCESS) {
2172      return FAILURE;
2173    }
2174  }
2175
2176  if (zend_llist_count(&zend_extensions) > 1) {
2177    zend_llist_element *p = zend_extensions.head;
2178    while (p != NULL) {
2179      zend_extension* ext = (zend_extension*)(p->data);
2180      if (strcmp(ext->name, EACCELERATOR_EXTENSION_NAME) == 0) {
2181        /* temporary removing eAccelerator extension */
2182        zend_extension* last_ext = (zend_extension*)zend_extensions.tail->data;
2183        if (eaccelerator_el != NULL) {
2184          zend_error(E_CORE_ERROR,"[%s] %s %s can not be loaded twice",
2185                   EACCELERATOR_EXTENSION_NAME,
2186                   EACCELERATOR_EXTENSION_NAME,
2187                   EACCELERATOR_VERSION);
2188          exit(1);
2189        }
2190        if (last_ext != ext) {
2191          eaccelerator_el = p;
2192          last_startup = last_ext->startup;
2193          last_ext->startup = eaccelerator_last_startup;
2194          zend_extensions.count--;
2195          if (p->prev != NULL) {
2196            p->prev->next = p->next;
2197          } else {
2198            zend_extensions.head = p->next;
2199          }
2200          if (p->next != NULL) {
2201            p->next->prev = p->prev;
2202          } else {
2203            zend_extensions.tail = p->prev;
2204          }
2205        }
2206      } else if (strcmp(ext->name, "Zend Extension Manager") == 0 ||
2207                 strcmp(ext->name, "Zend Optimizer") == 0) {
2208        /* Disable ZendOptimizer Optimizations */
2209        ZendOptimizer = ext;
2210        ext->op_array_handler = NULL;
2211      }
2212      p = p->next;
2213    }
2214  }
2215
2216  php_register_info_logo(EACCELERATOR_VERSION_GUID, "text/plain", (unsigned char*)EACCELERATOR_VERSION_STRING, sizeof(EACCELERATOR_VERSION_STRING));
2217  php_register_info_logo(EACCELERATOR_LOGO_GUID,    "image/gif",  (unsigned char*)eaccelerator_logo, sizeof(eaccelerator_logo));
2218
2219  /*
2220   * HOESH: on apache restart there was some
2221   * problem with CG(class_table) in the latest PHP
2222   * versions. Initialization moved to eaccelerator_compile_file()
2223   * depends on the value below.
2224   */
2225  eaccelerator_global_function_table.nTableSize = 0;
2226
2227  return SUCCESS;
2228}
2229
2230#ifndef ZEND_EXT_API
2231#  define ZEND_EXT_API    ZEND_DLEXPORT
2232#endif
2233
2234ZEND_EXTENSION();
2235
2236ZEND_DLEXPORT zend_extension zend_extension_entry = {
2237  EACCELERATOR_EXTENSION_NAME,
2238  EACCELERATOR_VERSION,
2239  "eAccelerator",
2240  "http://eaccelerator.net",
2241  "Copyright (c) 2004-2006 eAccelerator",
2242  eaccelerator_zend_startup,
2243  NULL,
2244  NULL,   /* void (*activate)() */
2245  NULL,   /* void (*deactivate)() */
2246  NULL,   /* void (*message_handle)(int message, void *arg) */
2247#ifdef WITH_EACCELERATOR_OPTIMIZER
2248  eaccelerator_optimize,   /* void (*op_array_handler)(zend_op_array *o_a); */
2249#else
2250  NULL,   /* void (*op_array_handler)(zend_op_array *o_a); */
2251#endif
2252  NULL,   /* void (*statement_handler)(zend_op_array *o_a); */
2253  NULL,   /* void (*fcall_begin_handler)(zend_op_array *o_a); */
2254  NULL,   /* void (*fcall_end_handler)(zend_op_array *o_a); */
2255  NULL,   /* void (*op_array_ctor)(zend_op_array *o_a); */
2256  NULL,   /* void (*op_array_dtor)(zend_op_array *o_a); */
2257#ifdef COMPAT_ZEND_EXTENSION_PROPERTIES
2258  NULL,   /* api_no_check */
2259  COMPAT_ZEND_EXTENSION_PROPERTIES
2260#else
2261  STANDARD_ZEND_EXTENSION_PROPERTIES
2262#endif
2263};
2264
2265static zend_extension eaccelerator_extension_entry = {
2266  EACCELERATOR_EXTENSION_NAME,
2267  EACCELERATOR_VERSION,
2268  "eAccelerator",
2269  "http://eaccelerator.net",
2270  "Copyright (c) 2004-2006 eAccelerator",
2271  eaccelerator_zend_startup,
2272  NULL,
2273  NULL,   /* void (*activate)() */
2274  NULL,   /* void (*deactivate)() */
2275  NULL,   /* void (*message_handle)(int message, void *arg) */
2276#ifdef WITH_EACCELERATOR_OPTIMIZER
2277  eaccelerator_optimize,   /* void (*op_array_handler)(zend_op_array *o_a); */
2278#else
2279  NULL,   /* void (*op_array_handler)(zend_op_array *o_a); */
2280#endif
2281  NULL,   /* void (*statement_handler)(zend_op_array *o_a); */
2282  NULL,   /* void (*fcall_begin_handler)(zend_op_array *o_a); */
2283  NULL,   /* void (*fcall_end_handler)(zend_op_array *o_a); */
2284  NULL,   /* void (*op_array_ctor)(zend_op_array *o_a); */
2285  NULL,   /* void (*op_array_dtor)(zend_op_array *o_a); */
2286#ifdef COMPAT_ZEND_EXTENSION_PROPERTIES
2287  NULL,   /* api_no_check */
2288  COMPAT_ZEND_EXTENSION_PROPERTIES
2289#else
2290  STANDARD_ZEND_EXTENSION_PROPERTIES
2291#endif
2292};
2293
2294static void register_eaccelerator_as_zend_extension() {
2295  zend_extension extension = eaccelerator_extension_entry;
2296  extension.handle = 0;
2297  zend_llist_prepend_element(&zend_extensions, &extension);
2298}
2299
2300/******************************************************************************/
2301
2302#endif  /* #ifdef HAVE_EACCELERATOR */
2303
2304/*
2305 * Local variables:
2306 * tab-width: 2
2307 * c-basic-offset: 2
2308 * End:
2309 * vim600: noet sw=2 ts=2 fdm=marker
2310 * vim<600: noet sw=2 ts=2
2311 */
Note: See TracBrowser for help on using the repository browser.