fix(fat32): 以 . / .. 结尾的路径会误开第一个子目录

dir_open_path 在 follow_path 返回后仍按“父目录中的最后一项”回读目录项。
当路径以 “.” 或 “..” 结尾时,follow_path 已经把 dp 打开成目标目录,
这段回读会把目标目录的第一个子项当成最终项再打开:

  根目录 cd .. → full=/.. → follow_path 打开根 → 回读根的第一项 APP
  → 实际进入 /APP,于是 ls 显示的是 app 里的 helloworld.asm。

现在检测末尾的 “.” / “..”,与根路径一样直接返回已打开的 dp。
This commit is contained in:
TermiNexus committed 2026-10-26 23:10:38 +08:00
1 parent 329a60b123
commit f43951c1f8
1 file changed
+21 -1
+21 -1
View File
@@ -1329,11 +1329,31 @@ class volinfo:
if path[pi] == '/' or path[pi] == '\\': pi += 1
while path[pi] == '/' or path[pi] == '\\': pi += 1
is_root: int = 1 if path[pi] == 0 else 0
# 路径末尾是 "." / ".." 时,follow_path 已经把 dp 打开成目标目录本身。
# 不能再按"父目录中的最后一项"去回读目录项:那会把目标目录的第一个子项
# 当成最终项打开(例如根目录 cd .. 会误入第一个子目录 APP)。
last: int = 0
lp: int = 0
while path[lp] != 0:
if path[lp] != '/' and path[lp] != '\\':
last = lp
lp += 1
ends_special: int = 0
if path[last] == '.':
if last == 0:
ends_special = 1
elif path[last - 1] == '/' or path[last - 1] == '\\':
ends_special = 1
elif path[last - 1] == '.':
if last == 1:
ends_special = 1
elif path[last - 2] == '/' or path[last - 2] == '\\':
ends_special = 1
lfn_buf: [256]uint16
string.memset(&lfn_buf, 0, 256 * 2)
res: FRESULT = self.follow_path(&dp, path, uint16*(&lfn_buf[0]))
if res != FRESULT.FR_OK: return res
if is_root: return FRESULT.FR_OK
if is_root or ends_special: return FRESULT.FR_OK
entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE))
entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE
res_wr: FRESULT = self.win_read(entry_sector)