getfileattributes 返回位掩码而非布尔值,需用按位与检测属性;stat 的 st_mode 反映 posix 权限,隐藏仅是文件名约定;跨平台应分离接口,避免语义混淆。

Windows 下用 GetFileAttributes 读取文件系统属性
在 Windows 平台,最直接的方式是调用 WinAPI 的 GetFileAttributes。它返回一个整型值,每一位代表一种属性(比如只读、隐藏、目录、系统文件等),不是布尔值,而是位掩码。
常见误用是直接拿返回值跟 TRUE 比较——这会掩盖真实状态。正确做法是用按位与(&)检测特定位:
DWORD attrs = GetFileAttributes(L"config.txt");
if (attrs == INVALID_FILE_ATTRIBUTES) {
// 文件不存在或无访问权限
}
if (attrs & FILE_ATTRIBUTE_READONLY) {
// 是只读
}
if (attrs & FILE_ATTRIBUTE_HIDDEN) {
// 是隐藏
}
-
FILE_ATTRIBUTE_READONLY、FILE_ATTRIBUTE_HIDDEN、FILE_ATTRIBUTE_SYSTEM等宏定义在winbase.h(通常通过windows.h引入) - 宽字符路径(
L"...")是必须的;传 ANSI 字符串会触发窄版函数,但已不推荐且易出错 - 该函数不支持符号链接解引用——如果传入的是链接,返回的是链接自身的属性,不是目标文件的
Linux/macOS 下用 stat 查看 st_mode 中的权限位
POSIX 系统没有“隐藏”“只读”这种 Windows 风格的元属性,但可通过 stat 结合文件权限和扩展属性间接判断。
所谓“只读”,实际对应的是文件权限位中是否缺少写权限(S_IWUSR 等);而“隐藏”在 Unix 里只是文件名以 . 开头的约定,不属于系统属性,stat 根本不记录它。
struct stat sb;
if (stat("config.txt", &sb) == 0) {
bool is_readonly_for_owner = !(sb.st_mode & S_IWUSR);
bool is_hidden_by_convention = (strncmp("config.txt", ".", 1) == 0);
}
-
st_mode是一个整数,需用S_IRUSR、S_IWGRP等宏提取权限位,不能直接比较数值 - 注意:即使文件权限为
rw-r--r--,用户仍可能因父目录无写权限而无法修改——stat不反映这种运行时限制 - macOS 上可额外用
getattrlist或xattr读取com.apple.FinderInfo获取 Finder 标记(如“隐藏”复选框),但这属于扩展属性,非标准 POSIX 行为
C++ 跨平台封装要注意什么
没有标准库函数能统一处理 Windows 属性和 Unix 权限语义。强行抽象容易误导使用者——比如把 is_hidden() 在 Linux 返回 name[0] == '.',看似方便,实则混淆了“约定”和“系统属性”的本质区别。
- 优先暴露底层差异:提供
get_windows_attributes()和get_posix_permissions()两个独立接口,比塞进一个get_file_flags()更诚实 - 避免用
std::filesystem::status()的permissions枚举替代属性判断——它只映射 POSIX 权限,对FILE_ATTRIBUTE_HIDDEN完全无感知 - 若项目必须跨平台隐藏逻辑,建议在业务层统一约定:Windows 用属性标记,Linux/macOS 用文件名前缀 + 可选扩展属性,不要指望系统 API 自动对齐
容易被忽略的权限/属性边界情况
属性读取本身不校验访问权限,但某些场景下结果不可靠:
- NTFS 卷上启用了“访问控制列表(ACL)”时,即使文件标记为只读,拥有
WRITE_DAC权限的进程仍可修改其属性——GetFileAttributes返回的仍是旧值,不代表当前能否写入 - Linux 上,root 用户可绕过所有权限检查;普通用户执行
stat时,只要对路径中任一父目录有执行权(x),就能获取最终文件的st_mode,哪怕文件本身权限是-------- - 符号链接、挂载点、网络文件系统(如 SMB/NFS)可能返回不一致的属性;例如 NFS 服务器未开启
nohide,客户端看到的st_mode可能被服务端截断或模拟
真正决定“能不能改”的从来不是属性值本身,而是当前进程的有效 UID/GID + 所在路径的 ACL + 文件系统策略。属性只是提示,不是锁。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











