Skip to content

Commit 368767f

Browse files
committed
Cache d_type in directory entry
1 parent efb94fb commit 368767f

File tree

7 files changed

+37
-0
lines changed

7 files changed

+37
-0
lines changed

UPGRADING.INTERNALS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ PHP 8.3 INTERNALS UPGRADE NOTES
6767
- zend_set_user_opcode_handler
6868
- zend_ssa_inference
6969
* Removed unused macros PHP_FNV1_32A_INIT and PHP_FNV1A_64_INIT. See GH-11114.
70+
* _php_stream_dirent now has an extra d_type field that is used to store the
71+
directory entry type. This can be used to avoid additional stat calls for
72+
types when the type is already known.
7073

7174
========================
7275
2. Build system changes

Zend/zend_virtual_cwd.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ typedef unsigned short mode_t;
8787
#else
8888
#ifdef HAVE_DIRENT_H
8989
#include <dirent.h>
90+
91+
#ifndef DT_UNKNOWN
92+
# define DT_UNKNOWN 0
93+
#endif
94+
#ifndef DT_DIR
95+
# define DT_DIR 4
96+
#endif
97+
#ifndef DT_REG
98+
# define DT_REG 8
99+
#endif
90100
#endif
91101

92102
#define DEFAULT_SLASH '/'

ext/spl/spl_directory.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,6 +1485,11 @@ PHP_METHOD(RecursiveDirectoryIterator, hasChildren)
14851485
if (spl_filesystem_is_invalid_or_dot(intern->u.dir.entry.d_name)) {
14861486
RETURN_FALSE;
14871487
} else {
1488+
if (intern->u.dir.entry.d_type == DT_DIR) {
1489+
RETURN_TRUE;
1490+
} else if (intern->u.dir.entry.d_type == DT_REG) {
1491+
RETURN_FALSE;
1492+
}
14881493
if (spl_filesystem_object_get_file_name(intern) == FAILURE) {
14891494
RETURN_THROWS();
14901495
}

main/php_streams.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ typedef struct _php_stream_dirent {
112112
#else
113113
char d_name[MAXPATHLEN];
114114
#endif
115+
unsigned char d_type;
115116
} php_stream_dirent;
116117

117118
/* operations on streams that are file-handles */

main/streams/plain_wrapper.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,11 @@ static ssize_t php_plain_files_dirstream_read(php_stream *stream, char *buf, siz
10321032
result = readdir(dir);
10331033
if (result) {
10341034
PHP_STRLCPY(ent->d_name, result->d_name, sizeof(ent->d_name), strlen(result->d_name));
1035+
#ifdef _DIRENT_HAVE_D_TYPE
1036+
ent->d_type = result->d_type;
1037+
#else
1038+
ent->d_type = DT_UNKNOWN;
1039+
#endif
10351040
return sizeof(php_stream_dirent);
10361041
}
10371042
return 0;

win32/readdir.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,13 @@ struct dirent *readdir(DIR *dp)
120120

121121
dp->dent.d_ino = 1;
122122
dp->dent.d_off = dp->offset;
123+
if (dp->fileinfo.dwFileAttributes & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DEVICE)) {
124+
dp->dent.d_type = DT_UNKNOWN; /* conservative */
125+
} else if (dp->fileinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
126+
dp->dent.d_type = DT_DIR;
127+
} else {
128+
dp->dent.d_type = DT_REG;
129+
}
123130

124131
return &(dp->dent);
125132
}/*}}}*/

win32/readdir.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,17 @@ extern "C" {
1515

1616
#include "ioutil.h"
1717

18+
#define _DIRENT_HAVE_D_TYPE
19+
#define DT_UNKNOWN 0
20+
#define DT_DIR 4
21+
#define DT_REG 8
22+
1823
/* struct dirent - same as Unix */
1924
struct dirent {
2025
long d_ino; /* inode (always 1 in WIN32) */
2126
off_t d_off; /* offset to this dirent */
2227
unsigned short d_reclen; /* length of d_name */
28+
unsigned char d_type;
2329
char d_name[1]; /* null terminated filename in the current encoding, glyph number <= 255 wchar_t's + \0 byte */
2430
};
2531

0 commit comments

Comments
 (0)