From aa0ccfed3610025b537bc5f8a4ef653c6018dd3b Mon Sep 17 00:00:00 2001 From: Wanderingss <1624155937@qq.com> Date: Tue, 22 Sep 2026 01:28:14 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DFatFs=E5=8E=9F=E5=AD=90?= =?UTF-8?q?=E5=86=99=EF=BC=9Af=5Frename=E4=B8=8D=E8=A6=86=E7=9B=96?= =?UTF-8?q?=E6=97=A2=E6=9C=89=E7=9B=AE=E6=A0=87=E9=A1=BB=E5=85=88unlink?= =?UTF-8?q?=E5=86=8Drename=EF=BC=8CE-01=E5=8F=B0=E6=9E=B6=E6=9A=B4?= =?UTF-8?q?=E9=9C=B2=E8=AE=BE=E5=A4=87=E7=AB=AF=E4=B8=80=E5=88=87=E8=A6=86?= =?UTF-8?q?=E7=9B=96=E5=86=99=E9=9D=99=E9=BB=98=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/cfg_file_store_mcu.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/App/cfg_file_store_mcu.c b/App/cfg_file_store_mcu.c index 15dba6b0..493a7c7a 100644 --- a/App/cfg_file_store_mcu.c +++ b/App/cfg_file_store_mcu.c @@ -10,6 +10,9 @@ * v1.0 2026-09-14 王建锋 创建初始版本 * v1.1 2026-09-18 王建锋 增 cfg_store_alloc / cfg_store_free / cfg_store_heap_free: * 共享核心临时缓冲改走 FreeRTOS 堆(P0-1,MicroLIB C 堆仅 512B) + * v1.2 2026-09-22 王建锋 原子写修复:rename 前先 unlink 已存在目标——本 FatFs + * 移植 f_rename 不覆盖既有目标(FR_EXIST),旧实现一切 + * "目标存在的覆盖写"必然失败(E-01 台架验证暴露) */ /* 头文件包含区 */ @@ -60,7 +63,7 @@ int cfg_store_read(const char *p_path, uint8_t *p_buf, size_t cap, size_t *p_nre } /* - * 函数功能:原子写文件(先写 /config.TMP,成功后 f_rename 覆盖目标) + * 函数功能:原子写文件(先写 /config.TMP,成功后 unlink 既有目标 + f_rename 替换) * 入口参数:p_path - 目标文件路径 const char * * p_buf - 待写数据(不可为 NULL) const uint8_t * * len - 数据长度 size_t @@ -85,6 +88,14 @@ int cfg_store_write_atomic(const char *p_path, const uint8_t *p_buf, size_t len) (void)f_unlink(s_path_tmp); return -1; } + /* 本 FatFs 移植的 f_rename 对已存在目标返回 FR_EXIST、不覆盖(ff.c + * "new name already in use" 检查,上游同语义)——"目标存在的覆盖写"必须先 + * unlink 目标再 rename。2026-09-22 台架实证(E-01 验证暴露):缺本步时 + * 一切非首启写(UI 保存/模板重建)静默失败,模拟器后端(POSIX rename + * 覆盖语义)照不出。unlink→rename 非原子窗口掉电 = 配置文件暂失, + * 开机 load 按"首启"重建工厂模板——与函数失败语义一致,丢失边界 = + * 本次进行中的保存内容(目标原值本就是待覆盖的旧代数据) */ + (void)f_unlink(p_path); /* 目标不存在返回 FR_NO_FILE,无害 */ fr = f_rename(s_path_tmp, p_path); if (fr != FR_OK) { (void)f_unlink(s_path_tmp);