不可靠。access()仅检查文件系统权限位,无法识别挂载点只读(ro)等内核级限制,即使返回可写,open()仍可能因erofs失败;应优先用statvfs()检测st_rdonly标志,再结合access()和实际写操作验证。

用 access() 检查路径所在挂载点的写入权限是否可靠?
不可靠。access() 只检查当前进程对指定路径的权限(基于 UID/GID 和文件/目录的 mode),但无法判断底层文件系统是否只读(例如 mount -o ro /mnt/data)。即使路径本身可写、父目录可遍历,若整个挂载点被设为只读,open(..., O_WRONLY) 仍会失败并返回 EROFS。
典型错误现象:access(path.c_str(), W_OK) 返回 0,但后续 std::ofstream 构造或 open() 却报错 errno == EROFS。
- Linux 下必须结合挂载信息判断,不能只信
access() -
statvfs()是更接近本质的手段——它能拿到文件系统级别的标志位 - Windows 不适用此方案,需用
GetVolumeInformation()查FILE_READ_ONLY_VOLUME
Linux:用 statvfs() 判断挂载点是否只读
statvfs() 获取文件系统统计信息,其中 f_flag 字段包含 ST_RDONLY 标志。关键点是:必须传入**路径所在挂载点的任意路径**(不一定是目标路径本身,但不能是符号链接跨挂载点)。
实操建议:
- 先调用
realpath(path.c_str(), nullptr)消除软链和相对路径干扰 - 再用
statvfs()对该绝对路径执行查询(内核自动定位到其所属挂载点) - 检查
vs.f_flag & ST_RDONLY是否为真;若为真,则该挂载点只读 - 注意:
statvfs()成功返回 0,失败才返回 -1 并设errno
示例片段:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
struct statvfs vs;
if (statvfs(real_path.c_str(), &vs) == 0) {
if (vs.f_flag & ST_RDONLY) {
// 文件系统只读
}
}
Linux 下如何获取路径所属挂载点?
多数情况下不需要显式找挂载点——statvfs() 自动处理。但如果你需要调试或日志记录,可用 findmnt 命令验证:
findmnt -n -o SOURCE,TARGET,FSTYPE,OPTIONS /path/to/dir- 重点看
OPTIONS是否含ro(只读)或rw(可读写) - 注意:某些文件系统(如 overlayfs、tmpfs)可能无传统挂载点,但
statvfs()仍有效
不要依赖 /proc/mounts 手动解析——容易漏掉 bind mount 或 namespace 隔离场景。
为什么不能只检查目标路径的 stat() mode?
stat() 返回的是文件或目录自身的权限位(如 st_mode & S_IWUSR),它完全不反映文件系统级限制。一个 root 创建的 drwxr-xr-x 目录,在只读挂载下依然无法 mkdir 或 touch。
- 常见误判场景:容器内 /tmp 映射自宿主机只读卷;NFS 挂载点服务端设为只读;USB 设备被内核标记为只读(
dmesg | grep readonly可见) - 真正可靠的判断顺序是:
statvfs() → 检查 ST_RDONLY → 再 fallback 到 access() 做用户级权限补检
- 如果既要写又要保证原子性(如
rename() 替换),还需确认挂载点支持该操作(<code>ST_NOSUID等不影响写,但ST_NOEXEC不影响)
实际工程中,最稳妥的做法是:先 statvfs() 排除只读文件系统,再 access() 确认用户权限,最后尝试最小写操作(如 open(..., O_WRONLY|O_CREAT|O_EXCL))并捕获 EROFS/EACCES —— 因为挂载选项和 DAC/SELinux 规则可能动态变化。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










