某些类型的伪文件(例如 procfs 和 sysfs 虚拟文件系统中的许多伪文件)没有文件大小(stat
返回st_size
== 0)并且不SEEK_END
支持fseek
.这些文件系统对象(例如 )的/proc/cpuinfo
行为更像 FIFO,而不是常规的随机访问文件。不幸的是,他们也对文件类型撒了谎:他们的st_mode
字段包括S_IFREG
位,这意味着常规文件,而不是S_IFIFO
位。
这会导致试图“更智能”地管理数据的输入代码出现问题,并且有许多关于工具在查看/proc/*
文件时挂起的报告。
我正在开发其中一个工具,它有一个通用的流输入系统,可以从用户指定的各种来源获取流。我还可以处理非随机访问流,例如纯粹“顺序”的管道和套接字,并且用于它们的相同技术也适用于 procfs/sysfs/其他虚拟文件系统对象 - 但我必须能够明确地告诉当我看着一个的时候。
给定 FILE 指针、文件描述符或文件路径名,我如何在 C 中确定我是否正在查看这些麻烦的伪文件对象之一? (注意:仅检查以 /proc 开头的路径是不够的,因为可以任意安装文件系统。我需要操作系统告诉我是否可以信任文件的st_size
和SEEK_END
。)是否有一个合理的可移植解决方案现代*尼克斯?
(这是一个编程问题;如果需要,请随意将其迁移到 SO。)
答案1
如果您stat
使用文件描述符,结果报告的大小为 0,则要么该文件为空,要么大小未知。如果文件是空的,那么玩游戏就没有多大意义来更有效地读取它。
因此,如果大小未知,则必须使用备用代码路径,如果文件为空,则使用备用代码路径应该不成问题。
我警告不要尝试仅根据文件名诊断文件类型,因为这将使您面临诱饵和切换攻击(或错误)。在成功打开文件之前,不应尝试找出任何内容,然后应确保直接或间接使用文件描述符,而不是名称,因为名称可能不再与文件关联。相同的文件。
希望有帮助。
答案2
检查路径只是第二个好主意。您可以改为检查文件系统(设备):st_dev=makedev(0, 14)
。如果主编号为 0,则为proc
、sys
等。
即使内核也无法确定文件的性质。想象一个 FUSE 安装座,其中包含/proc
.内核会假设一个普通的文件系统,而它是一个伪文件系统,存在您想要避免的问题。
但如果您知道这SEEK_END
不起作用,为什么不使用它进行测试呢?