Packages (macOS): prefers getdirentries64

This commit is contained in:
Carter Li
2026-09-29 13:36:32 +08:00
parent ffbf4ec7ac
commit 6ff7925f45
+71
View File
@@ -134,6 +134,77 @@ uint32_t ffPackagesGetNumElements(const char* dirname, bool isdir) {
return num_elements;
}
#elif __APPLE__
#pragma clang diagnostic ignored "-Wdeprecated-declarations" // syscall
#include <sys/syscall.h>
uint32_t ffPackagesGetNumElements(const char* dirname, bool isdir) {
FF_AUTO_CLOSE_FD int fd = open(dirname, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
if (fd < 0) {
return 0;
}
alignas(struct dirent) uint8_t bytes[64 * 1024];
off_t seek = 0;
uint32_t num_elements = 0;
const size_t nameOffset = offsetof(struct dirent, d_name);
for (;;) {
// getdirentries64 stores its EOF indicator in the final four bytes.
uint32_t* eofFlag = (uint32_t*) (bytes + sizeof(bytes) - sizeof(uint32_t));
*eofFlag = 0;
long bytesRead = syscall(SYS_getdirentries64, fd, bytes, sizeof(bytes), &seek);
if (bytesRead < 0) {
if (errno == EINTR) {
continue;
}
break;
}
if (bytesRead == 0 || (size_t) bytesRead > sizeof(bytes)) {
break;
}
size_t remaining = (size_t) bytesRead;
struct dirent* entry = (struct dirent*) bytes;
while (remaining >= nameOffset + 1) {
assert(((uintptr_t) entry) % alignof(struct dirent) == 0);
if (entry->d_reclen < nameOffset + 1 || entry->d_reclen > remaining ||
entry->d_namlen >= entry->d_reclen - nameOffset) {
remaining = 0;
break;
}
const char* name = (const char*) entry + nameOffset;
if (entry->d_ino != 0 && name[0] != '.') {
bool ok = false;
if (__builtin_expect(entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK, true)) {
ok = entry->d_type == (isdir ? DT_DIR : DT_REG);
} else {
struct stat stbuf;
if (fstatat(fd, name, &stbuf, 0) == 0) {
ok = isdir ? S_ISDIR(stbuf.st_mode) : S_ISREG(stbuf.st_mode);
}
}
num_elements += ok;
}
remaining -= entry->d_reclen;
entry = (struct dirent*) ((uint8_t*) entry + entry->d_reclen);
}
if ((size_t) bytesRead <= sizeof(bytes) - sizeof(uint32_t) && *eofFlag == 1) {
break;
}
}
return num_elements;
}
#elif !_WIN32
uint32_t ffPackagesGetNumElements(const char* dirname, bool isdir) {
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(dirname);