Linux/macOS下用stat可检查文件是否仅设写位(如-w-------),需按位判断S_IWUSR等与S_IRUSR、S_IXUSR组合;Windows无真正“只写”概念,std::filesystem::status无法区分只写与读写,不可靠。

Linux/macOS 下用 stat 检查文件权限位是否仅设了写位
只写权限在 POSIX 系统中是合法但罕见的组合:即文件权限中 W 位被置位,而 R 和 X 均未置位(如 ---------w------- 或更常见的是用户组其他三段中某一段为 ----w----)。C++ 标准库不直接暴露权限位判断逻辑,必须调用系统接口。
核心是读取 struct stat 中的 st_mode 字段,再按位与掩码判断:
-
S_IWUSR对应用户(owner)写权限 -
S_IWGRP对应组(group)写权限 -
S_IWOTH对应其他用户(others)写权限 - 只写 = 某类主体有
W且同时无R、无X
例如判断“用户是否只写”:
#include <sys/stat.h>
#include <iostream>
<p>bool isUserWriteOnly(const char* path) {
struct stat st;
if (stat(path, &st) != 0) return false;
return (st.st_mode & S_IWUSR) // 有写
&& !(st.st_mode & S_IRUSR) // 无读
&& !(st.st_mode & S_IXUSR); // 无执行
}
Windows 下无法真正实现“只写”文件权限
Windows ACL 模型中没有“只写”这一原生概念。即使你通过 SetFileAttributes 清除 FILE_ATTRIBUTE_READONLY,或用 SetSecurityDescriptor 显式授予 FILE_WRITE_DATA 却拒绝 FILE_READ_DATA,实际行为仍不可靠:
立即学习“C++免费学习笔记(深入)”;
- 大多数 Win32 API(如
CreateFile)在打开只写句柄时,若底层文件系统(NTFS)未显式禁读,仍可能允许读操作成功 - 某些工具(如资源管理器、PowerShell
Get-Item)根本不显示“只写”状态,只标“只读”或“无限制” - C++ 标准库
<filesystem>的status().permissions()在 Windows 上返回的是模拟值,不反映真实 DACL
所以,在 Windows 上不要依赖“只写”语义做安全控制;它既难检测,也难保证。
用 std::filesystem::status 判断会漏掉关键细节
C++17 的 std::filesystem 提供了跨平台接口,但它对权限的抽象过于粗粒度:
-
perms::owner_write只告诉你“写位是否开启”,不告诉你读/执行位是否关闭 - 它无法区分
-w-------和-rw-------—— 两者都返回owner_write为 true - 在 macOS 上甚至可能把 ACL 权限映射错误,导致误判
因此,除非你只要确认“能不能写”,否则别用 std::filesystem::status 判断“是否只写”。真要判断,老老实实调 stat(POSIX)或 GetNamedSecurityInfo(Windows,但慎用)。
注意 umask 和继承权限干扰真实判断
文件创建时的 umask 会屏蔽部分权限位,但已存在的文件权限是确定的。真正容易出错的是:
- 目录的执行位(
x)影响能否进入该目录查看/打开其下文件 —— 即使目标文件本身是----w----,若父目录无x,你根本stat不到它 - ACL 条目(如 Linux 的
setfacl)可能覆盖基础权限位,stat不返回 ACL,需额外调getfacl或acl_get_file - 挂载选项(如
noexec、nosuid)不影响stat结果,但会影响运行时行为
所以,一次 stat 调用只能告诉你基础权限位的状态,不能代表最终可执行的操作集合。尤其当涉及 ACL 或容器/沙箱环境时,“只写”几乎不可能靠单次检查确认。


















