fix: fix filesystem stack regression

This commit is contained in:
2026-03-28 17:44:15 +01:00
parent 5049d6529d
commit d2bd28c5d7
2 changed files with 138 additions and 29 deletions
+74 -13
View File
@@ -672,6 +672,79 @@ namespace Fs::Fat32 {
return count;
}
static int ReadDirectoryNames(int inst, uint32_t dirCluster,
char outNames[MaxDirEntries][MaxNameLen],
int maxEntries) {
auto& self = g_instances[inst];
uint16_t lfnBuf[MaxNameLen];
bool hasLfn = false;
int count = 0;
uint32_t cluster = dirCluster;
while (!IsEndOfChain(cluster) && count < maxEntries) {
if (!ReadCluster(self, cluster)) break;
int perCluster = (int)(self.clusterSize / 32);
for (int i = 0; i < perCluster && count < maxEntries; i++) {
uint8_t* e = self.clusterBuf + i * 32;
if (e[0] == 0x00) return count;
if (e[0] == 0xE5) { hasLfn = false; continue; }
uint8_t attr = e[11];
if (attr == ATTR_LFN) {
uint8_t seq = e[0];
int seqNum = seq & 0x1F;
if (seq & 0x40) {
for (int k = 0; k < MaxNameLen; k++) lfnBuf[k] = 0;
hasLfn = true;
}
if (hasLfn && seqNum >= 1 && seqNum <= 20) {
uint16_t chars[13];
ExtractLfnChars(e, chars);
int offset = (seqNum - 1) * 13;
for (int k = 0; k < 13 && offset + k < MaxNameLen; k++) {
lfnBuf[offset + k] = chars[k];
}
}
continue;
}
if (attr & ATTR_VOLUME_ID) { hasLfn = false; continue; }
if (hasLfn) {
Utf16ToAscii(lfnBuf, MaxNameLen, outNames[count]);
} else {
ParseShortName(e, outNames[count]);
}
hasLfn = false;
if (outNames[count][0] == '.' &&
(outNames[count][1] == '\0' ||
(outNames[count][1] == '.' && outNames[count][2] == '\0'))) {
continue;
}
int len = 0;
while (outNames[count][len] && len < MaxNameLen - 2) len++;
if ((attr & ATTR_DIRECTORY) && len < MaxNameLen - 1) {
outNames[count][len++] = '/';
outNames[count][len] = '\0';
}
count++;
}
cluster = GetNextCluster(self, cluster);
}
return count;
}
// =========================================================================
// Case-insensitive string comparison
// =========================================================================
@@ -932,23 +1005,11 @@ namespace Fs::Fat32 {
if (!TraversePath(inst, path, &dirEntry)) return -1;
if (!(dirEntry.attributes & ATTR_DIRECTORY)) return -1;
ParsedEntry entries[MaxDirEntries];
int limit = maxEntries < MaxDirEntries ? maxEntries : MaxDirEntries;
int count = ReadDirectory(inst, dirEntry.firstCluster, entries, limit);
int count = ReadDirectoryNames(inst, dirEntry.firstCluster, self.dirNames, limit);
// Copy names into persistent cache
self.dirNameCount = count;
for (int i = 0; i < count; i++) {
int j = 0;
while (entries[i].name[j] && j < MaxNameLen - 2) {
self.dirNames[i][j] = entries[i].name[j];
j++;
}
// Append trailing '/' for directories so userspace can distinguish them
if ((entries[i].attributes & ATTR_DIRECTORY) && j < MaxNameLen - 1) {
self.dirNames[i][j++] = '/';
}
self.dirNames[i][j] = '\0';
outNames[i] = self.dirNames[i];
}