windows 无真正只写权限,file_attribute_readonly 是只读开关;linux 的-w-权限理论上存在但实际不可用,真实可写性须通过open()试探而非stat()判断。

只写权限在 Windows 和 Linux 上根本不是一回事
Windows 没有“只写”(write-only)这种独立权限位,FILE_ATTRIBUTE_READONLY 是只读标记,设了它就真不能写;而 Linux 的文件权限模型里,w 位表示“可写”,但不隐含“不可读”——也就是说,一个文件可以同时有 rw- 或 -w-,但后者在实际中几乎不会存在:内核允许创建 -w- 文件,但大多数 shell 工具(如 ls)甚至不显示它,且 open() 时若无读权限,很多标准库函数(如 fstat()、read())会直接失败,导致程序行为异常。所以,“判断是否只写”本质上是个伪需求——你真正要确认的,通常是“能否写入但无法读取”。
用 access() 或 stat() 判断 Linux 下的写权限是否独立生效
Linux 下不能靠 stat.st_mode & S_IWUSR 单独下结论,因为即使该位为真,若进程没权限进入父目录(缺少执行权限),open(O_WRONLY) 仍会失败。更可靠的做法是尝试以 O_WRONLY | O_NONBLOCK 打开:
int fd = open("path/to/file", O_WRONLY | O_NONBLOCK);
if (fd == -1) {
if (errno == EACCES) {
// 权限拒绝:可能无写权限,或父目录不可执行
} else if (errno == ENOENT) {
// 文件不存在(注意:这和权限无关)
}
} else {
close(fd);
// 可写;但不确定是否可读——需额外试 <code>open(..., O_RDONLY)</code>
}
-
O_NONBLOCK避免阻塞(尤其对 FIFO/设备文件) - 必须检查
errno而非仅返回值,EACCES才代表权限问题 - 不要省略父目录的
x权限验证——可用access(dirname(path), X_OK)
Windows 下 GetFileAttributes() 只能告诉你是否被标记为只读
Windows 的“只写”概念不存在,GetFileAttributes() 返回的 FILE_ATTRIBUTE_READONLY 是一个布尔标记:如果置位,CreateFile() 用 GENERIC_WRITE 会失败(除非同时指定 FILE_ATTRIBUTE_READONLY 并调用 SetFileAttributes() 先清除它)。所以实际逻辑是:
DWORD attr = GetFileAttributes(L"myfile.txt");
if (attr == INVALID_FILE_ATTRIBUTES) {
// 文件不存在或访问被拒
} else if (attr & FILE_ATTRIBUTE_READONLY) {
// 不能写(除非先清除该属性)
} else {
// 可写(但仍需考虑 ACL、UAC、加密等其他限制)
}
-
FILE_ATTRIBUTE_READONLY不等于 Linux 的r--:它只是个开关,不影响读操作 - 即使未设只读,也可能因 DACL 拒绝写入——
GetFileAttributes()完全不反映 ACL - 若需精确控制,得用
GetNamedSecurityInfo()+GetEffectiveRightsFromAcl(),但代价高、极少必要
跨平台代码别硬造“只写判断”,优先按实际用途拆解
99% 的场景里,你并不是真需要“只写”,而是想确认:“这个文件我能安全覆盖写入吗?”或者“我能否追加日志而不意外读取内容?”。这时候应分情况处理:
- 覆盖写入 → 尝试
open(..., O_WRONLY | O_TRUNC)或fopen(..., "wb"),捕获失败原因 - 追加写入 → 用
O_WRONLY | O_APPEND,它不要求读权限,且原子性强 - 避免误读敏感内容 → 不依赖权限位,而是确保打开时不带
O_RDONLY或"r"模式 - 日志类场景 → 直接用
open(..., O_WRONLY | O_APPEND | O_CREAT, 0644),让系统决定权限,而非反向推导
权限位本身是粗粒度提示,真实可写性必须通过系统调用试探;而“只写”这个状态,在绝大多数现代文件系统上既难构造,也难可靠检测。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











