FatFs短名解析拒绝点加DEBUG打印并台架实证+AGENTS.md固化严格8.3命名约束

This commit is contained in:
2026-09-20 17:06:51 +08:00
parent be6cd046a2
commit 9bb5a8dcae
2 changed files with 46 additions and 5 deletions
+45 -5
View File
@@ -23,6 +23,21 @@
#include "ff.h" /* Declarations of FatFs API */
#include "diskio.h" /* Declarations of device I/O functions */
/* 项目定制(2026-09-20,".fschk 无限重格式化"事故复盘):
* FF_USE_LFN=0 时 f_open/f_create/f_unlink/f_mkdir 等一切文件 API
* 最终都汇聚到 create_short() 做 8.3 短名解析——这是名字合法性的
* 唯一咽喉点。在拒绝瞬间打印名字片段+原因,让"非法文件名"这类
* 纯 RAM 判定错误从开机日志直接可见,不再需要拿错误码反查枚举表。
* 注意:字符串字面量必须纯 ASCII(ARMCC 对无 BOM 文件按 CP936 解析)。 */
#if FF_USE_LFN == 0
#define DBG_TAG "[FATFS]"
#include "dbg_log.h"
#define FF_DBG_SFN_REJECT(why, seg, ch) \
DBG_ERROR("SFN reject (%s) seg='%.24s' bad_ch=0x%02X" \
" - strict 8.3 only: body<=8 ext<=3 no leading dot", \
(why), (seg), (int)(ch))
#endif
/*--------------------------------------------------------------------------
@@ -2993,7 +3008,12 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not cr
if (c != '.' || si >= 3) break;
sfn[i++] = c;
}
if (!IsSeparator(c) && c > ' ') return FR_INVALID_NAME;
if (!IsSeparator(c) && c > ' ') {
#if FF_USE_LFN == 0
FF_DBG_SFN_REJECT("heading dot", p, c);
#endif
return FR_INVALID_NAME;
}
*path = p + si; /* Return pointer to the next segment */
sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of the path */
return FR_OK;
@@ -3007,7 +3027,12 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not cr
break;
}
if (c == '.' || i >= ni) { /* End of body or field overflow? */
if (ni == 11 || c != '.') return FR_INVALID_NAME; /* Field overflow or invalid dot? */
if (ni == 11 || c != '.') {
#if FF_USE_LFN == 0
FF_DBG_SFN_REJECT("ext overflow or bad dot", p, c);
#endif
return FR_INVALID_NAME; /* Field overflow or invalid dot? */
}
i = 8; ni = 11; /* Enter file extension field */
continue;
}
@@ -3022,17 +3047,32 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not cr
#endif
if (dbc_1st(c)) { /* Check if it is a DBC 1st byte */
d = (BYTE)p[si++]; /* Get 2nd byte */
if (!dbc_2nd(d) || i >= ni - 1) return FR_INVALID_NAME; /* Reject invalid DBC */
if (!dbc_2nd(d) || i >= ni - 1) {
#if FF_USE_LFN == 0
FF_DBG_SFN_REJECT("invalid DBC", p, c);
#endif
return FR_INVALID_NAME; /* Reject invalid DBC */
}
sfn[i++] = c;
sfn[i++] = d;
} else { /* SBC */
if (strchr("*+,:;<=>[]|\"\?\x7F", (int)c)) return FR_INVALID_NAME; /* Reject illegal chrs for SFN */
if (strchr("*+,:;<=>[]|\"\?\x7F", (int)c)) {
#if FF_USE_LFN == 0
FF_DBG_SFN_REJECT("illegal char", p, c);
#endif
return FR_INVALID_NAME; /* Reject illegal chrs for SFN */
}
if (IsLower(c)) c -= 0x20; /* To upper */
sfn[i++] = c;
}
}
*path = &p[si]; /* Return pointer to the next segment */
if (i == 0) return FR_INVALID_NAME; /* Reject nul string */
if (i == 0) {
#if FF_USE_LFN == 0
FF_DBG_SFN_REJECT("empty name", p, c);
#endif
return FR_INVALID_NAME; /* Reject nul string */
}
if (sfn[0] == DDEM) sfn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */
sfn[NSFLAG] = (c <= ' ' || p[si] <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */