mirror of
https://github.com/php/php-src.git
synced 2024-12-12 19:33:31 +08:00
optimize phar filename extension detection to first search through known phars. This eliminates several stat/realpath calls for archives with lots of files
This commit is contained in:
parent
ae26f18c73
commit
f134a909c3
@ -380,7 +380,9 @@ int phar_open_loaded(char *fname, int fname_len, char *alias, int alias_len, int
|
||||
/* prevent any ".phar" without a stub getting through */
|
||||
if (!phar->halt_offset && !phar->is_brandnew) {
|
||||
if (PHAR_G(readonly) && FAILURE == zend_hash_find(&(phar->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1, (void **)&stub)) {
|
||||
spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname);
|
||||
if (error) {
|
||||
spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
@ -908,6 +910,16 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int
|
||||
phar_unixify_path_separators(mydata->fname, fname_len);
|
||||
#endif
|
||||
mydata->fname_len = fname_len;
|
||||
endbuffer = strrchr(mydata->fname, '/');
|
||||
if (endbuffer) {
|
||||
mydata->ext = memchr(endbuffer, '.', (mydata->fname + fname_len) - endbuffer);
|
||||
if (mydata->ext == endbuffer) {
|
||||
mydata->ext = memchr(endbuffer + 1, '.', (mydata->fname + fname_len) - endbuffer - 1);
|
||||
}
|
||||
if (mydata->ext) {
|
||||
mydata->ext_len = (mydata->fname + mydata->fname_len) - mydata->ext;
|
||||
}
|
||||
}
|
||||
mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len);
|
||||
mydata->alias_len = alias ? alias_len : fname_len;
|
||||
mydata->sig_flags = sig_flags;
|
||||
@ -1008,7 +1020,7 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a
|
||||
phar_archive_data *mydata;
|
||||
int register_alias;
|
||||
php_stream *fp;
|
||||
char *actual = NULL;
|
||||
char *actual = NULL, *p;
|
||||
|
||||
if (!pphar) {
|
||||
pphar = &mydata;
|
||||
@ -1068,7 +1080,17 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a
|
||||
#ifdef PHP_WIN32
|
||||
phar_unixify_path_separators(mydata->fname, fname_len);
|
||||
#endif
|
||||
|
||||
p = strrchr(mydata->fname, '/');
|
||||
if (p) {
|
||||
mydata->ext = memchr(p, '.', (mydata->fname + fname_len) - p);
|
||||
if (mydata->ext == p) {
|
||||
mydata->ext = memchr(p + 1, '.', (mydata->fname + fname_len) - p - 1);
|
||||
}
|
||||
if (mydata->ext) {
|
||||
mydata->ext_len = (mydata->fname + fname_len) - mydata->ext;
|
||||
}
|
||||
}
|
||||
|
||||
if (pphar) {
|
||||
*pphar = mydata;
|
||||
}
|
||||
@ -1508,6 +1530,53 @@ int phar_detect_phar_fname_ext(const char *filename, int check_length, const cha
|
||||
}
|
||||
}
|
||||
|
||||
if (zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) {
|
||||
phar_archive_data **pphar;
|
||||
|
||||
if (is_complete) {
|
||||
if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), filename, filename_len, (void **)&pphar)) {
|
||||
*ext_str = filename + (filename_len - (*pphar)->ext_len);
|
||||
woohoo:
|
||||
*ext_len = (*pphar)->ext_len;
|
||||
if (executable == 2) {
|
||||
return SUCCESS;
|
||||
}
|
||||
if (executable == 1 && !(*pphar)->is_data) {
|
||||
return SUCCESS;
|
||||
}
|
||||
if (!executable && (*pphar)->is_data) {
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
} else {
|
||||
char *key;
|
||||
uint keylen;
|
||||
ulong unused;
|
||||
|
||||
zend_hash_internal_pointer_reset(&(PHAR_GLOBALS->phar_fname_map));
|
||||
while (FAILURE != zend_hash_has_more_elements(&(PHAR_GLOBALS->phar_fname_map))) {
|
||||
if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&(PHAR_GLOBALS->phar_fname_map), &key, &keylen, &unused, 0, NULL)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (keylen > filename_len) {
|
||||
zend_hash_move_forward(&(PHAR_GLOBALS->phar_fname_map));
|
||||
continue;
|
||||
}
|
||||
if (!memcmp(filename, key, keylen) && (filename_len == keylen
|
||||
|| filename[keylen] == '/' || filename[keylen] == '\0')) {
|
||||
if (FAILURE == zend_hash_get_current_data(&(PHAR_GLOBALS->phar_fname_map), (void **) &pphar)) {
|
||||
break;
|
||||
}
|
||||
*ext_str = filename + (keylen - (*pphar)->ext_len);
|
||||
goto woohoo;
|
||||
}
|
||||
zend_hash_move_forward(&(PHAR_GLOBALS->phar_fname_map));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos = strchr(filename + 1, '.');
|
||||
next_extension:
|
||||
if (!pos) {
|
||||
|
@ -260,6 +260,9 @@ typedef struct _phar_entry_info {
|
||||
struct _phar_archive_data {
|
||||
char *fname;
|
||||
int fname_len;
|
||||
/* for phar_detect_fname_ext, this stores the location of the file extension within fname */
|
||||
char *ext;
|
||||
int ext_len;
|
||||
char *alias;
|
||||
int alias_len;
|
||||
char version[12];
|
||||
|
@ -1837,7 +1837,7 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c
|
||||
}
|
||||
|
||||
if (!phar->is_data) {
|
||||
if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &ext, &ext_len, 1, 1, 1 TSRMLS_CC)) {
|
||||
if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &(phar->ext_len), 1, 1, 1 TSRMLS_CC)) {
|
||||
efree(oldpath);
|
||||
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "phar \"%s\" has invalid extension %s", phar->fname, ext);
|
||||
return NULL;
|
||||
@ -1854,7 +1854,7 @@ static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool c
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &ext, &ext_len, 0, 1, 1 TSRMLS_CC)) {
|
||||
if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &(phar->ext_len), 0, 1, 1 TSRMLS_CC)) {
|
||||
efree(oldpath);
|
||||
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "data phar \"%s\" has invalid extension %s", phar->fname, ext);
|
||||
return NULL;
|
||||
|
@ -154,7 +154,7 @@ int phar_open_or_create_tar(char *fname, int fname_len, char *alias, int alias_l
|
||||
|
||||
int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, php_uint32 compression, char **error TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char buf[512], *actual_alias = NULL;
|
||||
char buf[512], *actual_alias = NULL, *p;
|
||||
phar_entry_info entry = {0};
|
||||
size_t pos = 0, read, totalsize;
|
||||
tar_header *hdr;
|
||||
@ -371,6 +371,16 @@ int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, i
|
||||
phar_unixify_path_separators(myphar->fname, fname_len);
|
||||
#endif
|
||||
myphar->fname_len = fname_len;
|
||||
p = strrchr(myphar->fname, '/');
|
||||
if (p) {
|
||||
myphar->ext = memchr(p, '.', (myphar->fname + fname_len) - p);
|
||||
if (myphar->ext == p) {
|
||||
myphar->ext = memchr(p + 1, '.', (myphar->fname + fname_len) - p - 1);
|
||||
}
|
||||
if (myphar->ext) {
|
||||
myphar->ext_len = (myphar->fname + fname_len) - p;
|
||||
}
|
||||
}
|
||||
myphar->fp = fp;
|
||||
phar_request_initialize(TSRMLS_C);
|
||||
if (SUCCESS != zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), myphar->fname, fname_len, (void*)&myphar, sizeof(phar_archive_data*), (void **)&actual)) {
|
||||
|
@ -212,7 +212,7 @@ A Phar stub cannot be set in a plain tar archive
|
||||
A Phar alias cannot be set in a plain tar archive
|
||||
A Phar stub cannot be set in a plain tar archive
|
||||
Cannot set signature algorithm, not possible with tar-based phar archives
|
||||
data phar "%sphar_convert_again2.phar.tgz.oops" has invalid extension .phar.tgz.oops
|
||||
phar "%sphar_convert_again2.tgz.oops" has invalid extension .tgz.oops
|
||||
data phar "%sphar_convert_again2.phar/.tgz.oops" has invalid extension .phar/.tgz.oops
|
||||
data phar "%sphar_convert_again2.phar.tgz.oops" has invalid extension phar.tgz.oops
|
||||
phar "%sphar_convert_again2.tgz.oops" has invalid extension tgz.oops
|
||||
data phar "%sphar_convert_again2.phar/.tgz.oops" has invalid extension phar/.tgz.oops
|
||||
===DONE===
|
||||
|
@ -152,7 +152,7 @@ int phar_open_zipfile(php_stream *fp, char *fname, int fname_len, char *alias, i
|
||||
php_uint16 i;
|
||||
phar_archive_data *mydata = NULL;
|
||||
phar_entry_info entry = {0};
|
||||
char *p = buf;
|
||||
char *p = buf, *ext;
|
||||
|
||||
size = php_stream_tell(fp);
|
||||
if (size > sizeof(locator) + 65536) {
|
||||
@ -231,6 +231,16 @@ foundit:
|
||||
#endif
|
||||
mydata->is_zip = 1;
|
||||
mydata->fname_len = fname_len;
|
||||
ext = strrchr(mydata->fname, '/');
|
||||
if (ext) {
|
||||
mydata->ext = memchr(ext, '.', (mydata->fname + fname_len) - ext);
|
||||
if (mydata->ext == ext) {
|
||||
mydata->ext = memchr(ext + 1, '.', (mydata->fname + fname_len) - ext - 1);
|
||||
}
|
||||
if (mydata->ext) {
|
||||
mydata->ext_len = (mydata->fname + fname_len) - mydata->ext;
|
||||
}
|
||||
}
|
||||
/* clean up on big-endian systems */
|
||||
/* seek to central directory */
|
||||
php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET);
|
||||
|
Loading…
Reference in New Issue
Block a user