Files
MeowOS-For-R3P2/patch_v2/files_app/logic/fsx.h
T
MeowOS c187b7bce3 feat(files): 新增外置系统文件管理器 os.meow.files (agent-183) — 目录浏览(虚拟化列表/空态)+文本预览(≤256KB截断)+删除/重命名/新建/属性(BottomSheet+IME);路径写操作限 TF 卡内(拒 .. 越界);多文件结构(app.c+ui/{browser,viewer}.c+ui/common/chrome.c+logic/fsx.c) 按批次②范本
files md5 6f6b0a6d; 0 warning; 宿主 test_fsx 全过(路径安全/格式化/排序/虚拟化/写操作/文本嗅探); qemu 离屏冒烟通过
SDK 缺口记录: listview 仅单行 label(本 App 用 custom 画布自绘行); common 档字库中文缺字(未声明 fonts:full)
真机待验证: 列表渲染/滚动手感/IME 重命名/弹窗交互
2026-08-31 04:03:56 +08:00

119 lines
5.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* logic/fsx.h — 文件管理器业务逻辑接口(纯 C,不依赖 meow_ui.h / meow_view)。
*
* 分层契约(沿用 hello_app/logic/logic.h 的约定):
* - UI→业务 = 纯函数命令 + 查询(fsx_*);业务不回调 UI,UI 按返回值/err 自绘。
* - 本模块只含 libc + 标准头,因此可宿主编译(gcc 直接测),也可交叉编译进 MIPS 应用。
*
* 宿主可验证的纯逻辑(test/test_fsx.c 驱动):
* - 路径安全:fsx_within_sd / fsx_join / fsx_sanitize_name / fsx_is_root / fsx_basename
* - 展示格式化:fsx_fmt_size / fsx_fmt_time
* - 列表数据源:fsx_visible_range(虚拟化可见行)/ fsx_sort_entries(目录优先)
* - 目录枚举/写操作:fsx_scan_dir / fsx_delete / fsx_rename_into / fsx_mkdir / fsx_stat_path
* (这些做真 IO,仍可宿主测:指向临时目录)
*/
#ifndef FSX_H
#define FSX_H
#include <stddef.h>
/* TF 卡根(挂载点)。写操作只允许在它之下。
* 允许编译期 -DFSX_SD_ROOT=... 覆写(宿主测试指向临时目录,便于测写操作)。 */
#ifndef FSX_SD_ROOT
#define FSX_SD_ROOT "/usr/data/mnt/sd_0"
#endif
#define FSX_MAX_NAME 256 /* 文件名/路径分量上限(exFAT 255 字节)×... 保守 */
#define FSX_MAX_PATH 512 /* 一条完整路径上限 */
#define FSX_MAX_ENTRIES 1024/* 单目录缓存项上限(大目录截断 + 列表虚拟化只画可见行) */
/* 返回码(等价负 errno;0=成功)。与 errno 数值一致,便于 App 判空态/权限态。 */
#define FSX_ERR_IO (-1)
#define FSX_ERR_NOENT (-2) /* 路径不存在(卡不在/目录被移除) */
#define FSX_ERR_EACCES (-13) /* 权限拒绝 */
#define FSX_ERR_ENOTDIR (-20) /* 不是目录 */
/* 单个目录项快照(App 持有数组;fsx_scan_dir 填充)。 */
typedef struct fsx_entry {
char name[FSX_MAX_NAME]; /* 文件名(不含路径) */
char path[FSX_MAX_PATH]; /* 绝对路径(在卡内,fsx_join 构造) */
int is_dir; /* 1=目录 */
int is_link; /* 1=符号链接(v1 视为文件,不追链) */
long long size; /* 字节(目录=0) */
long long mtime; /* 修改时间(Unix 秒) */
} fsx_entry;
/* ============================================================ */
/* 路径安全(纯逻辑,写操作红线) */
/* ============================================================ */
/* 1=path 严格落在 FSX_SD_ROOT 之下(或等于根),且不含任何 ".." 分量。
* 拒绝 "/usr/data/mnt/sd_0evil" 这类前缀伪装,也拒绝 "../" 越界。 */
int fsx_within_sd(const char *path);
/* 1=path 精确等于 FSX_SD_ROOT。 */
int fsx_is_root(const char *path);
/* 安全拼接:base + "/" + name → out。name 须无 '/'、非 ".."、非空(通常已 sanitize)。
* 返回 0=成功;-1=参数非法/输出超长。 */
int fsx_join(const char *base, const char *name, char *out, int outsz);
/* 校验+清洗新建/重命名名(供 mkdir/rename):拒绝空/超长/含 '/'、'\\'、':'、以 '.' 开头、
* 含 ".."、含控制字符。清洗后拷入 out 并去尾随空白。返回 0=合法;负数=非法(-EINVAL)。 */
int fsx_sanitize_name(const char *name, char *out, int outsz);
/* 返回 path 最后一个 '/' 之后的分量(借用指针,不改写)。 */
const char *fsx_basename(const char *path);
/* 拷贝 path 的目录部分(去掉最后分量)到 out;根目录返回 FSX_SD_ROOT。返回 0=成功。 */
int fsx_dirname(const char *path, char *out, int outsz);
/* ============================================================ */
/* 展示格式化(纯逻辑) */
/* ============================================================ */
/* "123 B" / "1.2 KB" / "3.4 MB" / "1.2 GB"。 */
void fsx_fmt_size(long long size, char *out, int outsz);
/* "YYYY-MM-DD HH:MM"(本地时区)。 */
void fsx_fmt_time(long long mtime, char *out, int outsz);
/* ============================================================ */
/* 目录枚举 / 排序 / 虚拟化(列表数据源) */
/* ============================================================ */
/* 扫 path 目录到 entries[0..max),目录优先 + 名称升序。*out_count=读到的项数。
* 超过 max 截断(大目录:只缓存前 max 项,配合虚拟化渲染)。
* 返回 0=成功;<0=负 errno(-2=无卡/不存在;-13=权限)。空目录=0 且 count=0。 */
int fsx_scan_dir(const char *path, fsx_entry *entries, int max, int *out_count);
/* 目录优先,其次 name 升序(strcmp,字节序)。 */
void fsx_sort_entries(fsx_entry *entries, int n);
/* 虚拟化:给定总行数/行高/滚动/视口高,算可见 [first,last)。越界安全。 */
void fsx_visible_range(int count, int item_h, int scroll, int viewport_h,
int *first, int *last);
/* 最大滚动偏移:max(0, count*item_h - viewport_h)。 */
int fsx_max_scroll(int count, int item_h, int viewport_h);
/* ============================================================ */
/* 写/查操作(全部先 fsx_within_sd 校验;0=成功,<0=负 errno) */
/* ============================================================ */
/* 删除:目录(须空)rmdir,否则 unlink。 */
int fsx_delete(const char *path);
/* 重命名 *path 为 *new_name(同名目录下)。目标已存在→-EEXIST。 */
int fsx_rename_into(const char *path, const char *new_name);
/* 在 base 目录下新建子目录 name。 */
int fsx_mkdir(const char *base, const char *name);
/* stat 一个路径填 entry(lstat,不追符号链)。0=成功,<0=负 errno。 */
int fsx_stat_path(const char *path, fsx_entry *out);
/* 简单文本判定:按扩展名白名单(用于读预览)。1=视为文本。 */
int fsx_is_text_path(const char *path);
#endif /* FSX_H */