From 0240c75dbdb6e30c46e00a428549cdc5a7e76339 Mon Sep 17 00:00:00 2001 From: xXJsonDeruloXx Date: Sun, 4 Oct 2026 15:33:41 -0400 Subject: [PATCH] Fix Steam directory cache for large listings --- tools/linuxfs/preload/readdir_cache.c | 28 +++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/tools/linuxfs/preload/readdir_cache.c b/tools/linuxfs/preload/readdir_cache.c index a5112fa0a..b0dd2d118 100644 --- a/tools/linuxfs/preload/readdir_cache.c +++ b/tools/linuxfs/preload/readdir_cache.c @@ -13,7 +13,6 @@ #define FUSE_SUPER_MAGIC 0x65735546 #define CACHE_SLOTS 32 -#define MAX_ENTRIES 4096 #define CACHE_TTL_NS 2000000000ULL struct listing { @@ -123,11 +122,26 @@ static struct listing *listing_for(DIR *dir) { struct listing *slot = available_listing(); if (!slot) return NULL; - struct dirent64 *entries = calloc(MAX_ENTRIES, sizeof(*entries)); + size_t capacity = 64; + struct dirent64 *entries = malloc(capacity * sizeof(*entries)); if (!entries) return NULL; size_t count = 0; int error = 0; - while (count < MAX_ENTRIES) { + for (;;) { + if (count == capacity) { + if (capacity > SIZE_MAX / 2 / sizeof(*entries)) { + error = ENOMEM; + break; + } + size_t next_capacity = capacity * 2; + struct dirent64 *grown = realloc(entries, next_capacity * sizeof(*entries)); + if (!grown) { + error = ENOMEM; + break; + } + entries = grown; + capacity = next_capacity; + } errno = 0; struct dirent64 *entry = real_readdir64(dir); if (!entry) { @@ -135,12 +149,13 @@ static struct listing *listing_for(DIR *dir) { break; } size_t bytes = entry->d_reclen < sizeof(*entry) ? entry->d_reclen : sizeof(*entry); + memset(&entries[count], 0, sizeof(*entries)); memcpy(&entries[count++], entry, bytes); } real_rewinddir(dir); struct stat after; - if (count == MAX_ENTRIES || error || fstat(fd, &after) != 0 || + if (error || fstat(fd, &after) != 0 || before.st_dev != after.st_dev || before.st_ino != after.st_ino || before.st_mtim.tv_sec != after.st_mtim.tv_sec || before.st_mtim.tv_nsec != after.st_mtim.tv_nsec || @@ -193,6 +208,11 @@ struct dirent64 *readdir64(DIR *dir) { return real_readdir64(dir); } +/* 32- and 64-bit dirent layouts are identical in the supported 64-bit runtimes. */ +struct dirent *readdir(DIR *dir) { + return (struct dirent *)readdir64(dir); +} + int closedir(DIR *dir) { pthread_once(&hooks_once, init_hooks); if (!real_closedir) { errno = ENOSYS; return -1; }