Hi, Here's the last attempt at streams support in include_path.
After siccing callgrind on the patch, I'm confident it meets performance requirements. Even in the worst case, it is significantly faster than PHP 5.2, and insignificantly slower (1%) than the current CVS. This patch is optimized so that it is: 1% faster than the current implementation for include/require 1% slower than current include_once/require_once implementation It also fixes a compile warning caused by missing cast from const char * to char * Greg
Index: Zend/zend_vm_def.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_def.h,v retrieving revision 1.59.2.29.2.48.2.41 diff -u -r1.59.2.29.2.48.2.41 zend_vm_def.h --- Zend/zend_vm_def.h 5 Mar 2008 13:34:12 -0000 1.59.2.29.2.48.2.41 +++ Zend/zend_vm_def.h 8 Mar 2008 18:35:06 -0000 @@ -3091,8 +3091,19 @@ } break; case ZEND_INCLUDE: - case ZEND_REQUIRE: - new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC); + case ZEND_REQUIRE: { + char *resolved_path; + + resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC); + if (resolved_path) { + zval rz; + ZVAL_STRINGL(&rz, resolved_path, strlen(resolved_path), 0); + new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), &rz TSRMLS_CC); + efree(resolved_path); + } else { + new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC); + } + } break; case ZEND_EVAL: { char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC); Index: Zend/zend_vm_execute.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_execute.h,v retrieving revision 1.62.2.30.2.49.2.40 diff -u -r1.62.2.30.2.49.2.40 zend_vm_execute.h --- Zend/zend_vm_execute.h 5 Mar 2008 13:34:12 -0000 1.62.2.30.2.49.2.40 +++ Zend/zend_vm_execute.h 8 Mar 2008 18:35:22 -0000 @@ -1700,8 +1700,19 @@ } break; case ZEND_INCLUDE: - case ZEND_REQUIRE: - new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC); + case ZEND_REQUIRE: { + char *resolved_path; + + resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC); + if (resolved_path) { + zval rz; + ZVAL_STRINGL(&rz, resolved_path, strlen(resolved_path), 0); + new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), &rz TSRMLS_CC); + efree(resolved_path); + } else { + new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC); + } + } break; case ZEND_EVAL: { char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC); @@ -4885,8 +4896,19 @@ } break; case ZEND_INCLUDE: - case ZEND_REQUIRE: - new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC); + case ZEND_REQUIRE: { + char *resolved_path; + + resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC); + if (resolved_path) { + zval rz; + ZVAL_STRINGL(&rz, resolved_path, strlen(resolved_path), 0); + new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), &rz TSRMLS_CC); + efree(resolved_path); + } else { + new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC); + } + } break; case ZEND_EVAL: { char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC); @@ -8101,8 +8123,19 @@ } break; case ZEND_INCLUDE: - case ZEND_REQUIRE: - new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC); + case ZEND_REQUIRE: { + char *resolved_path; + + resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC); + if (resolved_path) { + zval rz; + ZVAL_STRINGL(&rz, resolved_path, strlen(resolved_path), 0); + new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), &rz TSRMLS_CC); + efree(resolved_path); + } else { + new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC); + } + } break; case ZEND_EVAL: { char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC); @@ -21781,8 +21814,19 @@ } break; case ZEND_INCLUDE: - case ZEND_REQUIRE: - new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC); + case ZEND_REQUIRE: { + char *resolved_path; + + resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC); + if (resolved_path) { + zval rz; + ZVAL_STRINGL(&rz, resolved_path, strlen(resolved_path), 0); + new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), &rz TSRMLS_CC); + efree(resolved_path); + } else { + new_op_array = compile_filename(Z_LVAL(opline->op2.u.constant), inc_filename TSRMLS_CC); + } + } break; case ZEND_EVAL: { char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC); Index: main/fopen_wrappers.c =================================================================== RCS file: /repository/php-src/main/fopen_wrappers.c,v retrieving revision 1.175.2.3.2.13.2.7 diff -u -r1.175.2.3.2.13.2.7 fopen_wrappers.c --- main/fopen_wrappers.c 5 Mar 2008 13:34:12 -0000 1.175.2.3.2.13.2.7 +++ main/fopen_wrappers.c 8 Mar 2008 18:35:36 -0000 @@ -447,6 +447,9 @@ char resolved_path[MAXPATHLEN]; char trypath[MAXPATHLEN]; char *ptr, *end; + php_stream_wrapper *wrapper; + const char *p; + int n = 0; if (!filename) { return NULL; @@ -462,21 +465,52 @@ return NULL; } } + /* test for stream wrappers and return */ + for (p = filename; p - filename < filename_length && (isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'); p++) { + n++; + } + + if (n < filename_length - 3 && (*p == ':') && (!strncmp("//", p+1, 2) || ( filename_length > 4 && !memcmp("data", filename, 4)))) { + /* found stream wrapper, this is an absolute path until stream wrappers implement realpath */ + return estrndup(filename, filename_length); + } - ptr = path; + ptr = (char *) path; while (ptr && *ptr) { + int len, is_stream_wrapper = 0, maybe_stream = 1; + end = strchr(ptr, DEFAULT_DIR_SEPARATOR); +#ifndef PHP_WIN32 + /* search for stream wrapper */ + if (end - ptr <= 1) { + maybe_stream = 0; + goto not_stream; + } + for (p = ptr, n = 0; p < end && (isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'); p++) { + n++; + } + + if (n == end - ptr && *p && !strncmp("//", p+1, 2)) { + is_stream_wrapper = 1; + /* seek to real end of include_path portion */ + end = strchr(end + 1, DEFAULT_DIR_SEPARATOR); + } else { + maybe_stream = 0; + } +not_stream: +#endif if (end) { if ((end-ptr) + 1 + filename_length + 1 >= MAXPATHLEN) { ptr = end + 1; continue; } memcpy(trypath, ptr, end-ptr); + len = end-ptr; trypath[end-ptr] = '/'; memcpy(trypath+(end-ptr)+1, filename, filename_length+1); ptr = end+1; } else { - int len = strlen(ptr); + len = strlen(ptr); if (len + 1 + filename_length + 1 >= MAXPATHLEN) { break; @@ -486,6 +520,35 @@ memcpy(trypath+len+1, filename, filename_length+1); ptr = NULL; } + + if (!is_stream_wrapper && maybe_stream) { + /* search for stream wrapper */ + for (p = trypath, n = 0; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { + n++; + } + } + + if (is_stream_wrapper || (n < len - 3 && (*p == ':') && (n > 1) && (!strncmp("//", p+1, 2) || !memcmp("data", trypath, 4)))) { + char *actual; + + wrapper = php_stream_locate_url_wrapper(trypath, &actual, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC); + if (wrapper == &php_plain_files_wrapper) { + strncpy(trypath, actual, MAXPATHLEN); + } else if (!wrapper) { + /* if wrapper is NULL, there was a mal-formed include_path stream wrapper, so skip this ptr */ + continue; + } else { + if (wrapper->wops->url_stat) { + php_stream_statbuf ssb; + + if (SUCCESS == wrapper->wops->url_stat(wrapper, trypath, 0, &ssb, NULL TSRMLS_CC)) { + return estrdup(trypath); + } + } + continue; + } + } + if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) { return estrdup(resolved_path); } @@ -496,6 +559,8 @@ if (zend_is_executing(TSRMLS_C)) { char *exec_fname = zend_get_executed_filename(TSRMLS_C); int exec_fname_length = strlen(exec_fname); + const char *p; + int n = 0; while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length])); if (exec_fname && exec_fname[0] != '[' && @@ -503,6 +568,26 @@ exec_fname_length + 1 + filename_length + 1 < MAXPATHLEN) { memcpy(trypath, exec_fname, exec_fname_length + 1); memcpy(trypath+exec_fname_length + 1, filename, filename_length+1); + + /* search for stream wrapper */ + for (p = trypath; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { + n++; + } + if (n < exec_fname_length - 3 && (*p == ':') && (n > 1) && (!strncmp("//", p+1, 2) || !memcmp("data", trypath, 4))) { + char *actual; + + wrapper = php_stream_locate_url_wrapper(trypath, &actual, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC); + if (wrapper == &php_plain_files_wrapper) { + /* this should never technically happen, but we'll leave it here for completeness */ + strncpy(trypath, actual, MAXPATHLEN); + } else if (!wrapper) { + /* if wrapper is NULL, there was a mal-formed include_path stream wrapper + this also should be impossible */ + return NULL; + } else { + return estrdup(trypath); + } + } if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) { return estrdup(resolved_path); }
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php