Exemplo n.º 1
0
static ZEND_INI_MH(OnUpdateMemoryConsumption)
{
	zend_long *p;
	zend_long memsize;
#ifndef ZTS
	char *base = (char *) mh_arg2;
#else
	char *base = (char *) ts_resource(*((int *) mh_arg2));
#endif

	/* keep the compiler happy */
	(void)entry; (void)mh_arg2; (void)mh_arg3; (void)stage;

	p = (zend_long *) (base + (size_t)mh_arg1);
	memsize = atoi(new_value->val);
	/* sanity check we must use at least 8 MB */
	if (memsize < 8) {
		const char *new_new_value = "8";
		zend_ini_entry *ini_entry;

		memsize = 8;
		zend_accel_error(ACCEL_LOG_WARNING, "opcache.memory_consumption is set below the required 8MB.\n");
		zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal 8MB configuration.\n");

		if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives),
					"opcache.memory_consumption",
					sizeof("opcache.memory_consumption")-1)) == NULL) {
			return FAILURE;
		}

		ini_entry->value = zend_string_init(new_new_value, 1, 1);
	}
	*p = memsize * (1024 * 1024);
	return SUCCESS;
}
static ZEND_INI_MH(OnUpdateMaxWastedPercentage)
{
	double *p;
	long percentage;
#ifndef ZTS
	char *base = (char *) mh_arg2;
#else
	char *base = (char *) ts_resource(*((int *) mh_arg2));
#endif

	/* keep the compiler happy */
	(void)entry; (void)new_value_length; (void)mh_arg2; (void)mh_arg3; (void)stage;

	p = (double *) (base + (size_t)mh_arg1);
	percentage = atoi(new_value);

	if (percentage <= 0 || percentage > 50) {
		const char *new_new_value = "5";
		zend_ini_entry *ini_entry;

		percentage = 5;
		zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_wasted_percentage must be set between 1 and 50.\n");
		zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use 5%.\n");
		if (zend_hash_find(EG(ini_directives),
					"opcache.max_wasted_percentage",
					sizeof("opcache.max_wasted_percentage"),
					(void *) &ini_entry) == FAILURE) {
			return FAILURE;
		}
		ini_entry->value = strdup(new_new_value);
		ini_entry->value_length = strlen(new_new_value);
	}
	*p = (double)percentage / 100.0;
	return SUCCESS;
}
void zend_accel_hash_init(zend_accel_hash *accel_hash, zend_uint hash_size)
{
	uint i;

	for (i=0; i<num_prime_numbers; i++) {
		if (hash_size <= prime_numbers[i]) {
			hash_size = prime_numbers[i];
			break;
		}
	}

	accel_hash->num_entries = 0;
	accel_hash->num_direct_entries = 0;
	accel_hash->max_num_entries = hash_size;

	/* set up hash pointers table */
	accel_hash->hash_table = zend_shared_alloc(sizeof(zend_accel_hash_entry *)*accel_hash->max_num_entries);
	if (!accel_hash->hash_table) {
		zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
	}

	/* set up hash values table */
	accel_hash->hash_entries = zend_shared_alloc(sizeof(zend_accel_hash_entry)*accel_hash->max_num_entries);
	if (!accel_hash->hash_entries) {
		zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
	}
	memset(accel_hash->hash_table, 0, sizeof(zend_accel_hash_entry *)*accel_hash->max_num_entries);
}
static void blacklist_report_regexp_error(regex_t *comp_regex, int reg_err)
{
	char *errbuf;
	int errsize = regerror(reg_err, comp_regex, NULL, 0);
	errbuf = malloc(errsize);
	if (!errbuf) {
		zend_accel_error(ACCEL_LOG_ERROR, "Blacklist compilation: no memory\n");
		return;
	}
	regerror(reg_err, comp_regex, errbuf, errsize);
	zend_accel_error(ACCEL_LOG_ERROR, "Blacklist compilation: %s\n", errbuf);
	free(errbuf);
}
Exemplo n.º 5
0
void *zend_shared_alloc(size_t size)
{
	int i;
	unsigned int block_size = ZEND_ALIGNED_SIZE(size);

#if 1
	if (!ZCG(locked)) {
		zend_accel_error(ACCEL_LOG_ERROR, "Shared memory lock not obtained");
	}
#endif
	if (block_size > ZSMMG(shared_free)) { /* No hope to find a big-enough block */
		SHARED_ALLOC_FAILED();
		return NULL;
	}
	for (i = 0; i < ZSMMG(shared_segments_count); i++) {
		if (ZSMMG(shared_segments)[i]->size - ZSMMG(shared_segments)[i]->pos >= block_size) { /* found a valid block */
			void *retval = (void *) (((char *) ZSMMG(shared_segments)[i]->p) + ZSMMG(shared_segments)[i]->pos);

			ZSMMG(shared_segments)[i]->pos += block_size;
			ZSMMG(shared_free) -= block_size;
			memset(retval, 0, block_size);
			ZEND_ASSERT(((zend_uintptr_t)retval & 0x7) == 0); /* should be 8 byte aligned */
			return retval;
		}
	}
	SHARED_ALLOC_FAILED();
	return NULL;
}
Exemplo n.º 6
0
void zend_shared_alloc_lock(void)
{
#ifndef ZEND_WIN32

#ifdef ZTS
	tsrm_mutex_lock(zts_lock);
#endif

#if 0
	/* this will happen once per process, and will un-globalize mem_write_lock */
	if (mem_write_lock.l_pid == -1) {
		mem_write_lock.l_pid = getpid();
	}
#endif

	while (1) {
		if (fcntl(lock_file, F_SETLKW, &mem_write_lock) == -1) {
			if (errno == EINTR) {
				continue;
			}
			zend_accel_error(ACCEL_LOG_ERROR, "Cannot create lock - %s (%d)", strerror(errno), errno);
		}
		break;
	}
#else
	zend_shared_alloc_lock_win32();
#endif

	ZCG(locked) = 1;
}
Exemplo n.º 7
0
void zend_accel_override_file_functions(void)
{
	zend_function *old_function;
	if (ZCG(enabled) && accel_startup_ok && ZCG(accel_directives).file_override_enabled) {
#ifdef HAVE_OPCACHE_FILE_CACHE
		if (ZCG(accel_directives).file_cache_only) {
			zend_accel_error(ACCEL_LOG_WARNING, "file_override_enabled has no effect when file_cache_only is set");
			return;
		}
#endif
		/* override file_exists */
		if ((old_function = zend_hash_str_find_ptr(CG(function_table), "file_exists", sizeof("file_exists")-1)) != NULL) {
			orig_file_exists = old_function->internal_function.handler;
			old_function->internal_function.handler = accel_file_exists;
		}
		if ((old_function = zend_hash_str_find_ptr(CG(function_table), "is_file", sizeof("is_file")-1)) != NULL) {
			orig_is_file = old_function->internal_function.handler;
			old_function->internal_function.handler = accel_is_file;
		}
		if ((old_function = zend_hash_str_find_ptr(CG(function_table), "is_readable", sizeof("is_readable")-1)) != NULL) {
			orig_is_readable = old_function->internal_function.handler;
			old_function->internal_function.handler = accel_is_readable;
		}
	}
}
Exemplo n.º 8
0
void zend_shared_alloc_lock_win32(void)
{
	DWORD waitRes = WaitForSingleObject(memory_mutex, INFINITE);

	if (waitRes == WAIT_FAILED) {
		zend_accel_error(ACCEL_LOG_ERROR, "Cannot lock mutex");
	}
}
static ZEND_INI_MH(OnUpdateMaxAcceleratedFiles)
{
	long *p;
	long size;
#ifndef ZTS
	char *base = (char *) mh_arg2;
#else
	char *base = (char *) ts_resource(*((int *) mh_arg2));
#endif

	/* keep the compiler happy */
	(void)entry; (void)new_value_length; (void)mh_arg2; (void)mh_arg3; (void)stage;

	p = (long *) (base + (size_t)mh_arg1);
	size = atoi(new_value);
	/* sanity check we must use a value between MIN_ACCEL_FILES and MAX_ACCEL_FILES */

	if (size < MIN_ACCEL_FILES || size > MAX_ACCEL_FILES) {
		const char *new_new_value;
		zend_ini_entry *ini_entry;

		if (size < MIN_ACCEL_FILES) {
			size = MIN_ACCEL_FILES;
			new_new_value = TOKENTOSTR(MIN_ACCEL_FILES);
			zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_accelerated_files is set below the required minimum (%d).\n", MIN_ACCEL_FILES);
			zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal configuration.\n");
		}
		if (size > MAX_ACCEL_FILES) {
			size = MAX_ACCEL_FILES;
			new_new_value = TOKENTOSTR(MAX_ACCEL_FILES);
			zend_accel_error(ACCEL_LOG_WARNING, "opcache.max_accelerated_files is set above the limit (%d).\n", MAX_ACCEL_FILES);
			zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the maximal configuration.\n");
		}
		if (zend_hash_find(EG(ini_directives),
					"opcache.max_accelerated_files",
					sizeof("opcache.max_accelerated_files"),
					(void *) &ini_entry) == FAILURE) {
			return FAILURE;
		}
		ini_entry->value = strdup(new_new_value);
		ini_entry->value_length = strlen(new_new_value);
	}
	*p = size;
	return SUCCESS;
}
Exemplo n.º 10
0
void zend_shared_alloc_create_lock(void)
{
	memory_mutex = CreateMutex(NULL, FALSE, create_name_with_username(ACCEL_MUTEX_NAME));
	if (!memory_mutex) {
		zend_accel_error(ACCEL_LOG_FATAL, "Cannot create mutex");
		return;
	}
	ReleaseMutex(memory_mutex);
}
static ZEND_INI_MH(OnUpdateMemoryConsumption)
{
	long *p;
	long memsize;
#ifndef ZTS
	char *base = (char *) mh_arg2;
#else
	char *base = (char *) ts_resource(*((int *) mh_arg2));
#endif

	/* keep the compiler happy */
	(void)entry; (void)new_value_length; (void)mh_arg2; (void)mh_arg3; (void)stage;

	p = (long *) (base+(size_t) mh_arg1);
	memsize = atoi(new_value);
	/* sanity check we must use at least 8 MB */
	if (memsize < 8) {
		const char *new_new_value = "8";
		zend_ini_entry *ini_entry;

		memsize = 8;
		zend_accel_error(ACCEL_LOG_WARNING,"zend_optimizerplus.memory_consumption is set below the required 8MB.\n" );
		zend_accel_error(ACCEL_LOG_WARNING, ACCELERATOR_PRODUCT_NAME " will use the minimal 8MB cofiguration.\n" );

		if (zend_hash_find(EG(ini_directives),
					"zend_optimizerplus.memory_consumption",
					sizeof("zend_optimizerplus.memory_consumption"),
					(void *) &ini_entry)==FAILURE) {
			return FAILURE;
		}

		ini_entry->value = strdup(new_new_value);
		ini_entry->value_length = strlen(new_new_value);
	}
	*p = memsize * (1024 * 1024);
	return SUCCESS;
}
Exemplo n.º 12
0
void zend_shared_alloc_unlock(void)
{
	ZCG(locked) = 0;

#ifndef ZEND_WIN32
	if (fcntl(lock_file, F_SETLK, &mem_write_unlock) == -1) {
		zend_accel_error(ACCEL_LOG_ERROR, "Cannot remove lock - %s (%d)", strerror(errno), errno);
	}
#ifdef ZTS
	tsrm_mutex_unlock(zts_lock);
#endif
#else
	zend_shared_alloc_unlock_win32();
#endif
}
void zend_accel_blacklist_init(zend_blacklist *blacklist)
{
	blacklist->pos = 0;
	blacklist->size = ZEND_BLACKLIST_BLOCK_SIZE;

	if (blacklist->entries != NULL) {
		zend_accel_blacklist_shutdown(blacklist);
	}

	blacklist->entries = (zend_blacklist_entry *) calloc(sizeof(zend_blacklist_entry), blacklist->size);
	if (!blacklist->entries) {
		zend_accel_error(ACCEL_LOG_FATAL, "Blacklist initialization: no memory\n");
		return;
	}
	blacklist->regexp_list = NULL;
}
Exemplo n.º 14
0
void zend_shared_alloc_unlock(TSRMLS_D)
{
	/* Destroy translation table */
	zend_hash_destroy(&xlat_table);

	ZCG(locked) = 0;

#ifndef ZEND_WIN32
	if (fcntl(lock_file, F_SETLK, &mem_write_unlock) == -1) {
		zend_accel_error(ACCEL_LOG_ERROR, "Cannot remove lock - %s (%d)", strerror(errno), errno);
	}
#ifdef ZTS
	tsrm_mutex_unlock(zts_lock);
#endif
#else
	zend_shared_alloc_unlock_win32();
#endif
}
Exemplo n.º 15
0
void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
{
	glob_t globbuf;
	int    ret;
	unsigned int i;

	memset(&globbuf, 0, sizeof(glob_t));

	ret = glob(filename, 0, NULL, &globbuf);
#ifdef GLOB_NOMATCH
	if (ret == GLOB_NOMATCH || !globbuf.gl_pathc) {
#else
	if (!globbuf.gl_pathc) {
#endif
		zend_accel_error(ACCEL_LOG_WARNING, "No blacklist file found matching: %s\n", filename);
	} else {
		for(i=0 ; i<globbuf.gl_pathc; i++) {
			zend_accel_blacklist_loadone(blacklist, globbuf.gl_pathv[i]);
		}
		globfree(&globbuf);
	}
}
#endif

zend_bool zend_accel_blacklist_is_blacklisted(zend_blacklist *blacklist, char *verify_path)
{
	int ret = 0;
	zend_regexp_list *regexp_list_it = blacklist->regexp_list;

	if (regexp_list_it == NULL) {
		return 0;
	}
	while (regexp_list_it != NULL) {
		if (regexec(&(regexp_list_it->comp_regex), verify_path, 0, NULL, 0) == 0) {
			ret = 1;
			break;
		}
		regexp_list_it = regexp_list_it->next;
	}
	return ret;
}
Exemplo n.º 16
0
void zend_shared_alloc_create_lock(void)
{
	int val;

#ifdef ZTS
    zts_lock = tsrm_mutex_alloc();
#endif

	sprintf(lockfile_name, "%s/%sXXXXXX", TMP_DIR, SEM_FILENAME_PREFIX);
	lock_file = mkstemp(lockfile_name);
	fchmod(lock_file, 0666);

	if (lock_file == -1) {
		zend_accel_error(ACCEL_LOG_FATAL, "Unable to create lock file: %s (%d)", strerror(errno), errno);
	}
	val = fcntl(lock_file, F_GETFD, 0);
	val |= FD_CLOEXEC;
	fcntl(lock_file, F_SETFD, val);

	unlink(lockfile_name);
}
Exemplo n.º 17
0
void zend_shared_alloc_lock(TSRMLS_D)
{
#ifndef ZEND_WIN32

#ifdef ZTS
	tsrm_mutex_lock(zts_lock);
#endif

#if 0
	/* this will happen once per process, and will un-globalize mem_write_lock */
	if (mem_write_lock.l_pid == -1) {
		mem_write_lock.l_pid = getpid();
	}
#endif

	while (1) {
		if (fcntl(lock_file, F_SETLKW, &mem_write_lock) == -1) {
			if (errno == EINTR) {
				continue;
			}
			zend_accel_error(ACCEL_LOG_ERROR, "Cannot create lock - %s (%d)", strerror(errno), errno);
		}
		break;
	}
#else
	zend_shared_alloc_lock_win32();
#endif

	ZCG(locked) = 1;

	/* Prepare translation table
	 *
	 * Make it persistent so that it uses malloc() and allocated blocks
	 * won't be taken from space which is freed by efree in memdup.
	 * Otherwise it leads to false matches in memdup check.
	 */
	zend_hash_init(&xlat_table, 100, NULL, NULL, 1);
}
Exemplo n.º 18
0
static void zend_win_error_message(int type, char *msg, int err)
{
	LPVOID lpMsgBuf;
	FILE *fp;
	HANDLE h;
	char *ev_msgs[2];

	FormatMessage(
		FORMAT_MESSAGE_ALLOCATE_BUFFER |
		FORMAT_MESSAGE_FROM_SYSTEM |
		FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		err,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
		(LPTSTR) &lpMsgBuf,
		0,
		NULL
	);

	h = RegisterEventSource(NULL, TEXT(ACCEL_EVENT_SOURCE));
	ev_msgs[0] = msg;
	ev_msgs[1] = lpMsgBuf;
	ReportEvent(h,				  // event log handle
            EVENTLOG_ERROR_TYPE,  // event type
            0,                    // category zero
            err,				  // event identifier
            NULL,                 // no user security identifier
            2,                    // one substitution string
            0,                    // no data
            ev_msgs,              // pointer to string array
            NULL);                // pointer to data
	DeregisterEventSource(h);

	LocalFree( lpMsgBuf );

	zend_accel_error(type, msg);
}
Exemplo n.º 19
0
static ZEND_INI_MH(OnUpdateFileCache)
{
	if (new_value) {
		if (!ZSTR_LEN(new_value)) {
			new_value = NULL;
		} else {
			zend_stat_t buf;

		    if (!IS_ABSOLUTE_PATH(ZSTR_VAL(new_value), ZSTR_LEN(new_value)) ||
			    zend_stat(ZSTR_VAL(new_value), &buf) != 0 ||
			    !S_ISDIR(buf.st_mode) ||
#ifndef ZEND_WIN32
				access(ZSTR_VAL(new_value), R_OK | W_OK | X_OK) != 0) {
#else
				_access(ZSTR_VAL(new_value), 06) != 0) {
#endif
				zend_accel_error(ACCEL_LOG_WARNING, "opcache.file_cache must be a full path of accessable directory.\n");
				new_value = NULL;
			}
		}
	}
	OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
	return SUCCESS;
}
Exemplo n.º 20
0
void *zend_shared_alloc(size_t size)
{
	int i;
	unsigned int block_size = size + sizeof(zend_shared_memory_block_header);
	TSRMLS_FETCH();

#if 1
	if (!ZCG(locked)) {
		zend_accel_error(ACCEL_LOG_ERROR, "Shared memory lock not obtained");
	}
#endif
	if (block_size > ZSMMG(shared_free)) { /* No hope to find a big-enough block */
		SHARED_ALLOC_FAILED();
		return NULL;
	}
	for (i = 0; i < ZSMMG(shared_segments_count); i++) {
		if (ZSMMG(shared_segments)[i]->size - ZSMMG(shared_segments)[i]->pos >= block_size) { /* found a valid block */
			zend_shared_memory_block_header *p = (zend_shared_memory_block_header *) (((char *) ZSMMG(shared_segments)[i]->p) + ZSMMG(shared_segments)[i]->pos);
			int remainder = block_size % PLATFORM_ALIGNMENT;
			void *retval;

			if (remainder != 0) {
				size += PLATFORM_ALIGNMENT - remainder;
				block_size += PLATFORM_ALIGNMENT - remainder;
			}
			ZSMMG(shared_segments)[i]->pos += block_size;
			ZSMMG(shared_free) -= block_size;
			p->size = size;
			retval = ((char *) p) + sizeof(zend_shared_memory_block_header);
			memset(retval, 0, size);
			return retval;
		}
	}
	SHARED_ALLOC_FAILED();
	return NULL;
}
Exemplo n.º 21
0
int zend_file_cache_script_store(zend_persistent_script *script, int in_shm)
{
	int fd;
	char *filename;
	zend_file_cache_metainfo info;
#ifdef HAVE_SYS_UIO_H
	struct iovec vec[3];
#endif
	void *mem, *buf;

	filename = zend_file_cache_get_bin_file_path(script->script.filename);

	if (zend_file_cache_mkdir(filename, strlen(ZCG(accel_directives).file_cache)) != SUCCESS) {
		zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot create directory for file '%s'\n", filename);
		efree(filename);
		return FAILURE;
	}

#ifndef ZEND_WIN32
	fd = open(filename, O_CREAT | O_EXCL | O_RDWR | O_BINARY, S_IRUSR | S_IWUSR);
#else
	fd = open(filename, O_CREAT | O_EXCL | O_RDWR | O_BINARY, _S_IREAD | _S_IWRITE);
#endif
	if (fd < 0) {
		if (errno != EEXIST) {
			zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot create file '%s'\n", filename);
		}
		efree(filename);
		return FAILURE;
	}

	if (zend_file_cache_flock(fd, LOCK_EX) != 0) {
		close(fd);
		efree(filename);
		return FAILURE;
	}

#ifdef __SSE2__
	/* Align to 64-byte boundary */
	mem = emalloc(script->size + 64);
	buf = (void*)(((zend_uintptr_t)mem + 63L) & ~63L);
#else
	mem = buf = emalloc(script->size);
#endif

	ZCG(mem) = zend_string_alloc(4096 - (_ZSTR_HEADER_SIZE + 1), 0);

	zend_shared_alloc_init_xlat_table();
	if (!in_shm) {
		script->corrupted = 1; /* used to check if script restored to SHM or process memory */
	}
	zend_file_cache_serialize(script, &info, buf);
	if (!in_shm) {
		script->corrupted = 0;
	}
	zend_shared_alloc_destroy_xlat_table();

	info.checksum = zend_adler32(ADLER32_INIT, buf, script->size);
	info.checksum = zend_adler32(info.checksum, (signed char*)ZSTR_VAL((zend_string*)ZCG(mem)), info.str_size);

#ifdef HAVE_SYS_UIO_H
	vec[0].iov_base = &info;
	vec[0].iov_len = sizeof(info);
	vec[1].iov_base = buf;
	vec[1].iov_len = script->size;
	vec[2].iov_base = ZSTR_VAL((zend_string*)ZCG(mem));
	vec[2].iov_len = info.str_size;

	if (writev(fd, vec, 3) != (ssize_t)(sizeof(info) + script->size + info.str_size)) {
		zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot write to file '%s'\n", filename);
		zend_string_release((zend_string*)ZCG(mem));
		efree(mem);
		unlink(filename);
		efree(filename);
		return FAILURE;
	}
#else
	if (ZEND_LONG_MAX < (zend_long)(sizeof(info) + script->size + info.str_size) ||
		write(fd, &info, sizeof(info)) != sizeof(info) ||
		write(fd, buf, script->size) != script->size ||
		write(fd, ((zend_string*)ZCG(mem))->val, info.str_size) != info.str_size
		) {
		zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot write to file '%s'\n", filename);
		zend_string_release((zend_string*)ZCG(mem));
		efree(mem);
		unlink(filename);
		efree(filename);
		return FAILURE;
	}
#endif

	zend_string_release((zend_string*)ZCG(mem));
	efree(mem);
	if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
		zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
	}
	close(fd);
	efree(filename);

	return SUCCESS;
}
Exemplo n.º 22
0
zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handle)
{
	zend_string *full_path = file_handle->opened_path;
	int fd;
	char *filename;
	zend_persistent_script *script;
	zend_file_cache_metainfo info;
	zend_accel_hash_entry *bucket;
	void *mem, *checkpoint, *buf;
	int cache_it = 1;

	if (!full_path) {
		return NULL;
	}
	filename = zend_file_cache_get_bin_file_path(full_path);

	fd = open(filename, O_RDONLY | O_BINARY);
	if (fd < 0) {
		efree(filename);
		return NULL;
	}

	if (zend_file_cache_flock(fd, LOCK_SH) != 0) {
		close(fd);
		efree(filename);
		return NULL;
	}

	if (read(fd, &info, sizeof(info)) != sizeof(info)) {
		zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s'\n", filename);
		zend_file_cache_flock(fd, LOCK_UN);
		close(fd);
		unlink(filename);
		efree(filename);
		return NULL;
	}

	/* verify header */
	if (memcmp(info.magic, "OPCACHE", 8) != 0) {
		zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong header)\n", filename);
		zend_file_cache_flock(fd, LOCK_UN);
		close(fd);
		unlink(filename);
		efree(filename);
		return NULL;
	}
	if (memcmp(info.system_id, ZCG(system_id), 32) != 0) {
		zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong \"system_id\")\n", filename);
		zend_file_cache_flock(fd, LOCK_UN);
		close(fd);
		unlink(filename);
		efree(filename);
		return NULL;
	}

	/* verify timestamp */
	if (ZCG(accel_directives).validate_timestamps &&
	    zend_get_file_handle_timestamp(file_handle, NULL) != info.timestamp) {
		if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
			zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
		}
		close(fd);
		unlink(filename);
		efree(filename);
		return NULL;
	}

	checkpoint = zend_arena_checkpoint(CG(arena));
#ifdef __SSE2__
	/* Align to 64-byte boundary */
	mem = zend_arena_alloc(&CG(arena), info.mem_size + info.str_size + 64);
	mem = (void*)(((zend_uintptr_t)mem + 63L) & ~63L);
#else
	mem = zend_arena_alloc(&CG(arena), info.mem_size + info.str_size);
#endif

	if (read(fd, mem, info.mem_size + info.str_size) != (ssize_t)(info.mem_size + info.str_size)) {
		zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s'\n", filename);
		zend_file_cache_flock(fd, LOCK_UN);
		close(fd);
		unlink(filename);
		zend_arena_release(&CG(arena), checkpoint);
		efree(filename);
		return NULL;
	}
	if (zend_file_cache_flock(fd, LOCK_UN) != 0) {
		zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename);
	}
	close(fd);

	/* verify checksum */
	if (ZCG(accel_directives).file_cache_consistency_checks &&
	    zend_adler32(ADLER32_INIT, mem, info.mem_size + info.str_size) != info.checksum) {
		zend_accel_error(ACCEL_LOG_WARNING, "corrupted file '%s'\n", filename);
		unlink(filename);
		zend_arena_release(&CG(arena), checkpoint);
		efree(filename);
		return NULL;
	}

	if (!ZCG(accel_directives).file_cache_only &&
	    !ZCSG(restart_in_progress) &&
	    accelerator_shm_read_lock() == SUCCESS) {
		/* exclusive lock */
		zend_shared_alloc_lock();

		/* Check if we still need to put the file into the cache (may be it was
		 * already stored by another process. This final check is done under
		 * exclusive lock) */
		bucket = zend_accel_hash_find_entry(&ZCSG(hash), full_path);
		if (bucket) {
			script = (zend_persistent_script *)bucket->data;
			if (!script->corrupted) {
				zend_shared_alloc_unlock();
				zend_arena_release(&CG(arena), checkpoint);
				efree(filename);
				return script;
			}
		}

		if (zend_accel_hash_is_full(&ZCSG(hash))) {
			zend_accel_error(ACCEL_LOG_DEBUG, "No more entries in hash table!");
			ZSMMG(memory_exhausted) = 1;
			zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_HASH);
			zend_shared_alloc_unlock();
			goto use_process_mem;
		}

#ifdef __SSE2__
		/* Align to 64-byte boundary */
		buf = zend_shared_alloc(info.mem_size + 64);
		buf = (void*)(((zend_uintptr_t)buf + 63L) & ~63L);
#else
		buf = zend_shared_alloc(info.mem_size);
#endif

		if (!buf) {
			zend_accel_schedule_restart_if_necessary(ACCEL_RESTART_OOM);
			zend_shared_alloc_unlock();
			goto use_process_mem;
		}
		memcpy(buf, mem, info.mem_size);
	} else {
use_process_mem:
		buf = mem;
		cache_it = 0;
	}

	ZCG(mem) = ((char*)mem + info.mem_size);
	script = (zend_persistent_script*)((char*)buf + info.script_offset);
	script->corrupted = !cache_it; /* used to check if script restored to SHM or process memory */
	zend_file_cache_unserialize(script, buf);
	script->corrupted = 0;

	if (cache_it) {
		script->dynamic_members.checksum = zend_accel_script_checksum(script);
		script->dynamic_members.last_used = ZCG(request_time);

		zend_accel_hash_update(&ZCSG(hash), ZSTR_VAL(script->script.filename), ZSTR_LEN(script->script.filename), 0, script);

		zend_shared_alloc_unlock();
		zend_arena_release(&CG(arena), checkpoint);
	}
	efree(filename);

	return script;
}
Exemplo n.º 23
0
static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist)
{
	int i, reg_err;
	zend_regexp_list **regexp_list_it, *it;
	char regexp[12*1024], *p, *end, *c, *backtrack = NULL;

	if (blacklist->pos == 0) {
		/* we have no blacklist to talk about */
		return;
	}

	regexp_list_it = &(blacklist->regexp_list);

	regexp[0] = '^';
	regexp[1] = '(';
	p = regexp + 2;
	end = regexp + sizeof(regexp) - sizeof("[^\\\\]*)\0");

	for (i = 0; i < blacklist->pos; ) {
		c = blacklist->entries[i].path;
		if (p + blacklist->entries[i].path_length < end) {
			while (*c && p < end) {
				switch (*c) {
					case '?':
						c++;
#ifdef ZEND_WIN32
				 		p[0] = '[';			/* * => [^\\] on Win32 */
					 	p[1] = '^';
					 	p[2] = '\\';
					 	p[3] = '\\';
					 	p[4] = ']';
						p += 5;
#else
					 	p[0] = '[';			/* * => [^/] on *nix */
					 	p[1] = '^';
					 	p[2] = '/';
					 	p[3] = ']';
						p += 4;
#endif
						break;
					case '*':
						c++;
						if (*c == '*') {
							c++;
						 	p[0] = '.';			/* ** => .* */
							p[1] = '*';
							p += 2;
						} else {
#ifdef ZEND_WIN32
						 	p[0] = '[';			/* * => [^\\]* on Win32 */
						 	p[1] = '^';
						 	p[2] = '\\';
						 	p[3] = '\\';
						 	p[4] = ']';
						 	p[5] = '*';
							p += 6;
#else
						 	p[0] = '[';			/* * => [^/]* on *nix */
						 	p[1] = '^';
						 	p[2] = '/';
						 	p[3] = ']';
						 	p[4] = '*';
							p += 5;
#endif
						}
						break;
					case '^':
					case '.':
					case '[':
					case ']':
					case '$':
					case '(':
					case ')':
					case '|':
					case '+':
					case '{':
					case '}':
					case '\\':
						*p++ = '\\';
						/* break missing intentionally */
					default:
						*p++ = *c++;
				}
			}
		}

		if (*c || i == blacklist->pos - 1) {
			if (*c) {
				if (!backtrack) {
					zend_accel_error(ACCEL_LOG_ERROR, "Too long blacklist entry\n");
				}
				p = backtrack;
			} else {
				i++;
			}
			*p++ = ')';
			*p++ = '\0';

			it = (zend_regexp_list*)malloc(sizeof(zend_regexp_list));
			if (!it) {
				zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n");
				return;
			}
			it->next = NULL;

			if ((reg_err = regcomp(&it->comp_regex, regexp, REGEX_MODE)) != 0) {
				blacklist_report_regexp_error(&it->comp_regex, reg_err);
			}
			/* prepare for the next iteration */
			p = regexp + 2;
			*regexp_list_it = it;
			regexp_list_it = &it->next;
		} else {
			backtrack = p;
			*p++ = '|';
			i++;
		}
	}
}
void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename)
{
	char buf[MAXPATHLEN+1], real_path[MAXPATHLEN+1];
	FILE *fp;
	int path_length;
	TSRMLS_FETCH();

	if ((fp=fopen(filename, "r"))==NULL) {
		zend_accel_error(ACCEL_LOG_WARNING, "Cannot load blacklist file: %s\n", filename);
		return;
	}

	zend_accel_error(ACCEL_LOG_DEBUG,"Loading blacklist file:  '%s'", filename);

	memset(buf, 0, sizeof(buf));
	memset(real_path, 0, sizeof(real_path));

	while (fgets(buf, MAXPATHLEN, fp)!=NULL) {
		char *path_dup, *pbuf;
		path_length = strlen(buf);
		if (path_length > 0 && buf[path_length-1]=='\n') {
			buf[--path_length] = 0;
			if (path_length > 0 && buf[path_length-1]=='\r') {
				buf[--path_length] = 0;
			}
		}

		/* Strip ctrl-m prefix */
		pbuf = &buf[0];
		while(*pbuf == '\r') {
			*pbuf++ = 0;
			path_length--;
		}

		/* strip \" */
		if( pbuf[0] == '\"' && pbuf[path_length-1]== '\"' ){
			*pbuf++ = 0;
			path_length-=2;
		}

		if (path_length==0) {
			continue;
		}

		path_dup = zend_strndup(pbuf, path_length);
		expand_filepath(path_dup, real_path TSRMLS_CC);
		path_length = strlen(real_path);

		free(path_dup);

		zend_accel_blacklist_allocate(blacklist);
		blacklist->entries[blacklist->pos].path_length = path_length;
		blacklist->entries[blacklist->pos].path = (char *) malloc(path_length+1);
		if (!blacklist->entries[blacklist->pos].path) {
			zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n");
			return;
		}
		blacklist->entries[blacklist->pos].id = blacklist->pos;
		memcpy(blacklist->entries[blacklist->pos].path, real_path, path_length+1);
		blacklist->pos++;
	}
	fclose(fp);
	zend_accel_blacklist_update_regexp(blacklist);
}
static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist)
{
	int i, end=0, j, rlen=6, clen, reg_err;
	char *regexp;
	zend_regexp_list **regexp_list_it, *it;

	if (blacklist->pos == 0) {
		/* we have no blacklist to talk about */
		return;
	}

	regexp_list_it = &(blacklist->regexp_list);
	for (i=0; i<blacklist->pos; i++) {
		rlen += blacklist->entries[i].path_length*2+2;

		/* don't create a regexp buffer bigger than 12K)*/
		if((i+1 == blacklist->pos) || ((rlen+blacklist->entries[i+1].path_length*2+2)>(12*1024) ) ) {
			regexp = (char *)malloc(rlen);
			if (!regexp) {
				zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n");
				return;
			}
			regexp[0] = '^';
			regexp[1] = '(';

			clen=2;
			for (j=end; j<=i ;j++) {

				int c;
				if (j!=end) {
					regexp[clen++] = '|';
				}
				/* copy mangled filename */
				for(c=0; c<blacklist->entries[j].path_length; c++) {
					if(strchr("^.[]$()|*+?{}\\", blacklist->entries[j].path[c])) {
						regexp[clen++] = '\\';
					}
					regexp[clen++] = blacklist->entries[j].path[c];
				}
			}
			regexp[clen++] = ')';
			regexp[clen] = '\0';

			it = (zend_regexp_list*)malloc(sizeof(zend_regexp_list));
			if (!it) {
				zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n");
				return;
			}
			it->next = NULL;

			if ((reg_err = regcomp(&it->comp_regex, regexp, REGEX_MODE)) != 0) {
				blacklist_report_regexp_error(&it->comp_regex, reg_err);
			}
			/* prepare for the next iteration */
			free(regexp);
			end = i+1;
			rlen = 6;
			*regexp_list_it = it;
			regexp_list_it = &it->next;
		}
	}
}
Exemplo n.º 26
0
int zend_shared_alloc_startup(size_t requested_size)
{
	zend_shared_segment **tmp_shared_segments;
	size_t shared_segments_array_size;
	zend_smm_shared_globals tmp_shared_globals, *p_tmp_shared_globals;
	char *error_in = NULL;
	const zend_shared_memory_handler_entry *he;
	int res = ALLOC_FAILURE;


	/* shared_free must be valid before we call zend_shared_alloc()
	 * - make it temporarily point to a local variable
	 */
	smm_shared_globals = &tmp_shared_globals;
	ZSMMG(shared_free) = requested_size; /* goes to tmp_shared_globals.shared_free */

	zend_shared_alloc_create_lock();

	if (ZCG(accel_directives).memory_model && ZCG(accel_directives).memory_model[0]) {
		char *model = ZCG(accel_directives).memory_model;
		/* "cgi" is really "shm"... */
		if (strncmp(ZCG(accel_directives).memory_model, "cgi", sizeof("cgi")) == 0) {
			model = "shm";
		}

		for (he = handler_table; he->name; he++) {
			if (strcmp(model, he->name) == 0) {
				res = zend_shared_alloc_try(he, requested_size, &ZSMMG(shared_segments), &ZSMMG(shared_segments_count), &error_in);
				if (res) {
					/* this model works! */
				}
				break;
			}
		}
	}

	if (res == FAILED_REATTACHED) {
		smm_shared_globals = NULL;
		return res;
	}
#if ENABLE_FILE_CACHE_FALLBACK
	if (ALLOC_FALLBACK == res) {
		return ALLOC_FALLBACK;
	}
#endif

	if (!g_shared_alloc_handler) {
		/* try memory handlers in order */
		for (he = handler_table; he->name; he++) {
			res = zend_shared_alloc_try(he, requested_size, &ZSMMG(shared_segments), &ZSMMG(shared_segments_count), &error_in);
			if (res) {
				/* this model works! */
				break;
			}
		}
	}

	if (!g_shared_alloc_handler) {
		no_memory_bailout(requested_size, error_in);
		return ALLOC_FAILURE;
	}

	if (res == SUCCESSFULLY_REATTACHED) {
		return res;
	}
#if ENABLE_FILE_CACHE_FALLBACK
	if (ALLOC_FALLBACK == res) {
		return ALLOC_FALLBACK;
	}
#endif

	shared_segments_array_size = ZSMMG(shared_segments_count) * S_H(segment_type_size)();

	/* move shared_segments and shared_free to shared memory */
	ZCG(locked) = 1; /* no need to perform a real lock at this point */
	p_tmp_shared_globals = (zend_smm_shared_globals *) zend_shared_alloc(sizeof(zend_smm_shared_globals));
	if (!p_tmp_shared_globals) {
		zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
		return ALLOC_FAILURE;;
	}

	tmp_shared_segments = zend_shared_alloc(shared_segments_array_size + ZSMMG(shared_segments_count) * sizeof(void *));
	if (!tmp_shared_segments) {
		zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
		return ALLOC_FAILURE;;
	}

	copy_shared_segments(tmp_shared_segments, ZSMMG(shared_segments)[0], ZSMMG(shared_segments_count), S_H(segment_type_size)());

	*p_tmp_shared_globals = tmp_shared_globals;
	smm_shared_globals = p_tmp_shared_globals;

	free(ZSMMG(shared_segments));
	ZSMMG(shared_segments) = tmp_shared_segments;

	ZSMMG(shared_memory_state).positions = (int *)zend_shared_alloc(sizeof(int) * ZSMMG(shared_segments_count));
	if (!ZSMMG(shared_memory_state).positions) {
		zend_accel_error(ACCEL_LOG_FATAL, "Insufficient shared memory!");
		return ALLOC_FAILURE;;
	}

	ZCG(locked) = 0;

	return res;
}
Exemplo n.º 27
0
static void no_memory_bailout(size_t allocate_size, char *error)
{
	zend_accel_error(ACCEL_LOG_FATAL, "Unable to allocate shared memory segment of %ld bytes: %s: %s (%d)", allocate_size, error?error:"unknown", strerror(errno), errno );
}