mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +02:00
Cache d_type in directory entry
This commit is contained in:
parent
00c1e7bf0f
commit
0b2e6bc2b0
11 changed files with 41 additions and 0 deletions
|
@ -67,6 +67,9 @@ PHP 8.3 INTERNALS UPGRADE NOTES
|
||||||
- zend_set_user_opcode_handler
|
- zend_set_user_opcode_handler
|
||||||
- zend_ssa_inference
|
- zend_ssa_inference
|
||||||
* Removed unused macros PHP_FNV1_32A_INIT and PHP_FNV1A_64_INIT. See GH-11114.
|
* Removed unused macros PHP_FNV1_32A_INIT and PHP_FNV1A_64_INIT. See GH-11114.
|
||||||
|
* _php_stream_dirent now has an extra d_type field that is used to store the
|
||||||
|
directory entry type. This can be used to avoid additional stat calls for
|
||||||
|
types when the type is already known.
|
||||||
|
|
||||||
========================
|
========================
|
||||||
2. Build system changes
|
2. Build system changes
|
||||||
|
|
|
@ -87,6 +87,16 @@ typedef unsigned short mode_t;
|
||||||
#else
|
#else
|
||||||
#ifdef HAVE_DIRENT_H
|
#ifdef HAVE_DIRENT_H
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#ifndef DT_UNKNOWN
|
||||||
|
# define DT_UNKNOWN 0
|
||||||
|
#endif
|
||||||
|
#ifndef DT_DIR
|
||||||
|
# define DT_DIR 4
|
||||||
|
#endif
|
||||||
|
#ifndef DT_REG
|
||||||
|
# define DT_REG 8
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEFAULT_SLASH '/'
|
#define DEFAULT_SLASH '/'
|
||||||
|
|
|
@ -108,6 +108,7 @@ static ssize_t phar_dir_read(php_stream *stream, char *buf, size_t count) /* {{{
|
||||||
memset(buf, 0, sizeof(php_stream_dirent));
|
memset(buf, 0, sizeof(php_stream_dirent));
|
||||||
memcpy(((php_stream_dirent *) buf)->d_name, ZSTR_VAL(str_key), to_read);
|
memcpy(((php_stream_dirent *) buf)->d_name, ZSTR_VAL(str_key), to_read);
|
||||||
((php_stream_dirent *) buf)->d_name[to_read + 1] = '\0';
|
((php_stream_dirent *) buf)->d_name[to_read + 1] = '\0';
|
||||||
|
((php_stream_dirent *) buf)->d_type = DT_UNKNOWN;
|
||||||
|
|
||||||
return sizeof(php_stream_dirent);
|
return sizeof(php_stream_dirent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1485,6 +1485,11 @@ PHP_METHOD(RecursiveDirectoryIterator, hasChildren)
|
||||||
if (spl_filesystem_is_invalid_or_dot(intern->u.dir.entry.d_name)) {
|
if (spl_filesystem_is_invalid_or_dot(intern->u.dir.entry.d_name)) {
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
} else {
|
} else {
|
||||||
|
if (intern->u.dir.entry.d_type == DT_DIR) {
|
||||||
|
RETURN_TRUE;
|
||||||
|
} else if (intern->u.dir.entry.d_type == DT_REG) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
if (spl_filesystem_object_get_file_name(intern) == FAILURE) {
|
if (spl_filesystem_object_get_file_name(intern) == FAILURE) {
|
||||||
RETURN_THROWS();
|
RETURN_THROWS();
|
||||||
}
|
}
|
||||||
|
|
|
@ -629,6 +629,7 @@ static ssize_t php_ftp_dirstream_read(php_stream *stream, char *buf, size_t coun
|
||||||
memcpy(ent->d_name, ZSTR_VAL(basename), tmp_len);
|
memcpy(ent->d_name, ZSTR_VAL(basename), tmp_len);
|
||||||
ent->d_name[tmp_len - 1] = '\0';
|
ent->d_name[tmp_len - 1] = '\0';
|
||||||
zend_string_release_ex(basename, 0);
|
zend_string_release_ex(basename, 0);
|
||||||
|
ent->d_type = DT_UNKNOWN;
|
||||||
|
|
||||||
/* Trim off trailing whitespace characters */
|
/* Trim off trailing whitespace characters */
|
||||||
while (tmp_len > 0 &&
|
while (tmp_len > 0 &&
|
||||||
|
|
|
@ -112,6 +112,7 @@ typedef struct _php_stream_dirent {
|
||||||
#else
|
#else
|
||||||
char d_name[MAXPATHLEN];
|
char d_name[MAXPATHLEN];
|
||||||
#endif
|
#endif
|
||||||
|
unsigned char d_type;
|
||||||
} php_stream_dirent;
|
} php_stream_dirent;
|
||||||
|
|
||||||
/* operations on streams that are file-handles */
|
/* operations on streams that are file-handles */
|
||||||
|
|
|
@ -150,6 +150,7 @@ static ssize_t php_glob_stream_read(php_stream *stream, char *buf, size_t count)
|
||||||
php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[index], pglob->flags & GLOB_APPEND, &path);
|
php_glob_stream_path_split(pglob, pglob->glob.gl_pathv[index], pglob->flags & GLOB_APPEND, &path);
|
||||||
++pglob->index;
|
++pglob->index;
|
||||||
PHP_STRLCPY(ent->d_name, path, sizeof(ent->d_name), strlen(path));
|
PHP_STRLCPY(ent->d_name, path, sizeof(ent->d_name), strlen(path));
|
||||||
|
ent->d_type = DT_UNKNOWN;
|
||||||
return sizeof(php_stream_dirent);
|
return sizeof(php_stream_dirent);
|
||||||
}
|
}
|
||||||
pglob->index = glob_result_count;
|
pglob->index = glob_result_count;
|
||||||
|
|
|
@ -1032,6 +1032,11 @@ static ssize_t php_plain_files_dirstream_read(php_stream *stream, char *buf, siz
|
||||||
result = readdir(dir);
|
result = readdir(dir);
|
||||||
if (result) {
|
if (result) {
|
||||||
PHP_STRLCPY(ent->d_name, result->d_name, sizeof(ent->d_name), strlen(result->d_name));
|
PHP_STRLCPY(ent->d_name, result->d_name, sizeof(ent->d_name), strlen(result->d_name));
|
||||||
|
#ifdef _DIRENT_HAVE_D_TYPE
|
||||||
|
ent->d_type = result->d_type;
|
||||||
|
#else
|
||||||
|
ent->d_type = DT_UNKNOWN;
|
||||||
|
#endif
|
||||||
return sizeof(php_stream_dirent);
|
return sizeof(php_stream_dirent);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1320,6 +1320,7 @@ static ssize_t php_userstreamop_readdir(php_stream *stream, char *buf, size_t co
|
||||||
if (call_result == SUCCESS && Z_TYPE(retval) != IS_FALSE && Z_TYPE(retval) != IS_TRUE) {
|
if (call_result == SUCCESS && Z_TYPE(retval) != IS_FALSE && Z_TYPE(retval) != IS_TRUE) {
|
||||||
convert_to_string(&retval);
|
convert_to_string(&retval);
|
||||||
PHP_STRLCPY(ent->d_name, Z_STRVAL(retval), sizeof(ent->d_name), Z_STRLEN(retval));
|
PHP_STRLCPY(ent->d_name, Z_STRVAL(retval), sizeof(ent->d_name), Z_STRLEN(retval));
|
||||||
|
ent->d_type = DT_UNKNOWN;
|
||||||
|
|
||||||
didread = sizeof(php_stream_dirent);
|
didread = sizeof(php_stream_dirent);
|
||||||
} else if (call_result == FAILURE) {
|
} else if (call_result == FAILURE) {
|
||||||
|
|
|
@ -120,6 +120,13 @@ struct dirent *readdir(DIR *dp)
|
||||||
|
|
||||||
dp->dent.d_ino = 1;
|
dp->dent.d_ino = 1;
|
||||||
dp->dent.d_off = dp->offset;
|
dp->dent.d_off = dp->offset;
|
||||||
|
if (dp->fileinfo.dwFileAttributes & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DEVICE)) {
|
||||||
|
dp->dent.d_type = DT_UNKNOWN; /* conservative */
|
||||||
|
} else if (dp->fileinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||||
|
dp->dent.d_type = DT_DIR;
|
||||||
|
} else {
|
||||||
|
dp->dent.d_type = DT_REG;
|
||||||
|
}
|
||||||
|
|
||||||
return &(dp->dent);
|
return &(dp->dent);
|
||||||
}/*}}}*/
|
}/*}}}*/
|
||||||
|
|
|
@ -15,11 +15,17 @@ extern "C" {
|
||||||
|
|
||||||
#include "ioutil.h"
|
#include "ioutil.h"
|
||||||
|
|
||||||
|
#define _DIRENT_HAVE_D_TYPE
|
||||||
|
#define DT_UNKNOWN 0
|
||||||
|
#define DT_DIR 4
|
||||||
|
#define DT_REG 8
|
||||||
|
|
||||||
/* struct dirent - same as Unix */
|
/* struct dirent - same as Unix */
|
||||||
struct dirent {
|
struct dirent {
|
||||||
long d_ino; /* inode (always 1 in WIN32) */
|
long d_ino; /* inode (always 1 in WIN32) */
|
||||||
off_t d_off; /* offset to this dirent */
|
off_t d_off; /* offset to this dirent */
|
||||||
unsigned short d_reclen; /* length of d_name */
|
unsigned short d_reclen; /* length of d_name */
|
||||||
|
unsigned char d_type;
|
||||||
char d_name[1]; /* null terminated filename in the current encoding, glyph number <= 255 wchar_t's + \0 byte */
|
char d_name[1]; /* null terminated filename in the current encoding, glyph number <= 255 wchar_t's + \0 byte */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue