最可靠方式是调用GetVolumeInformation检查FILE_READ_ONLY_VOLUME标志(Windows)或组合statfs与BLKROGET ioctl(Linux),需先将路径归一化至挂载点根路径,避免依赖文件系统类型字符串。

Windows 下用 GetVolumeInformation 判断卷是否只读
直接调用 GetVolumeInformation 是最可靠的方式,它能返回底层卷的只读标志(FILE_READ_ONLY_VOLUME),这个标志对物理只读光盘、挂载的 ISO 镜像(如 Windows 10+ 原生挂载或 Daemon Tools)都有效。
注意:不能靠文件属性(GetFileAttributes)判断——ISO 挂载后里面的文件可能显示为“普通”,但整个卷是只读的。
- 先用
PathGetDriveNumber或手动提取盘符(如"D:\foo.txt"→"D:"),再拼上"\\"构成根路径("D:\") - 调用
GetVolumeInformation,检查返回的dwFileSystemFlags是否包含FILE_READ_ONLY_VOLUME - 如果路径本身不带盘符(如相对路径或 UNC),需先用
GetFullPathName解析成绝对路径再提取盘符
Linux 下通过 statfs + ioctl 检测块设备只读状态
Linux 没有统一的“卷只读”API,得组合两层信息:先确认挂载点是否只读(statfs.f_flags & ST_RDONLY),再验证底层块设备是否物理只读(BLKROGET ioctl)。
仅靠 statfs 不够——有些 FUSE 挂载(如 archivemount)可能报告只读,但不是介质特性;而某些只读 ISO 挂载(如 mount -o loop,ro)会正确反映 ST_RDONLY。
立即学习“C++免费学习笔记(深入)”;
- 用
statfs(path, &buf)获取挂载信息,buf.f_flags & ST_RDONLY为真才继续 - 从
/proc/mounts或findmnt查该挂载点对应的块设备(如/dev/sr0或 loop 设备/dev/loop2) - 打开该设备文件,调用
ioctl(fd, BLKROGET, &readonly);若readonly == 1,基本可确认是只读介质或只读镜像
跨平台时避免依赖文件系统类型字符串
有人试图用 GetVolumeInformation 的 lpFileSystemNameBuffer(如识别 "CDFS" 或 "UDF")来推断只读,这不可靠:现代 Windows 挂载 ISO 默认用 "NTFS"(虚拟卷格式),而部分 UDF 光盘可能被格式化为可写。
同理,Linux 下检查 /proc/mounts 中的文件系统类型(cdfs、iso9660、udf)只能作为辅助线索,不能替代只读标志检测。
-
CDFS和iso9660通常只读,但存在可重写的 CD-RW + UDF 1.5 场景 -
ntfs或exfat卷挂载为只读,未必是光盘——可能是管理员手动mount -o ro - 真正要回答“是否指向只读光盘或 ISO 镜像”,核心是“是否无法写入”,而非“是什么格式”
容易忽略的边界情况
路径指向的是符号链接、挂载点子目录、或网络共享路径时,判断逻辑会失效。必须确保最终解析到的是本地挂载点根路径,而不是任意中间节点。
- Windows:
GetFinalPathNameByHandle配合FILE_FLAG_BACKUP_SEMANTICS打开目录句柄,再获取真实卷路径 - Linux:用
realpath(path, NULL)得到绝对路径后,再用stat查st_dev,与/proc/mounts中各挂载点的设备号比对,锁定对应挂载项 - 如果路径在 WSL 中,且指向 Windows 挂载的 ISO(如
/mnt/d/),实际走的是 Windows API 层,应优先调用 Windows 的卷查询逻辑
真正难的不是调 API,而是把任意路径归一化到它所属的挂载点或卷,并在多层抽象(物理设备 → 块设备 → 文件系统 → 挂载选项)中准确定位只读性的来源。


















