假设Linux,或更普遍的POSIX兼容系统,是否有现成的方法来检查打开具有给定名称的文件是否会成功?最乐观的是,我正在寻求使用与open(2)
int test_open(const char *pathname, int flags);
根据预期成功或失败的open(2)
系统调用使用相同的参数返回结果,但而不实际创建或打开任何文件。它应该是适当的许可(可在专有软件项目中重用)开源。
open(2)
manual page列出了open(2)
失败的许多原因。一个errno
值可以解码多个原因,而errno
在Linux和POSIX之间是不同的。但粗略地说:
errno
逐项列出的以下案例最为相关:EACCESS
,EEXIST
,ENOENT
,EISDIR
,{{1} (POSIX和Linux)。ENOTDIR
,ELOOP
,EMFILE
,ENFILE
,ENAMETOOLONG
,ENODEV
,ENXIO
,{{ 1}},EOVERFLOW
,EPERM
,EROFS
(POSIX添加ETXTBSY
)。EWOULDBLOCK
,EAGAIN
,ENOMEM
(POSIX添加EINTR
,ENOSPC
)。(我现在无法快速找到EIO
的在线POSIX手册页,我个人指的是我的Linux机器上安装的POSIX手册页 - 我会在找到在线链接时编辑问题。)
背景和期望:我的应用程序/系统配置架构要求在永久存储输入值之前验证输入值。只有在执行验证和存储步骤之后,文件才会用于写入。接受错误值会带来巨大的不便(同时尝试实际更改以使用错误的文件路径会干扰操作)。我不能或不想为这种特殊情况做出例外(它只是一百多个配置值中的一个)。
我宁愿不通过创建文件(ENOSR
包含open()
的标志)来为验证引入副作用。 很明显,我所寻求的检查无法在最常见的情况下100%可靠地实现,这是我将可能的错误条件分为三组的根本原因。我们可以通过分析目录权限,目录的存在以及是否已经存在阻碍打开文件的相同名称以及文件名是否有意义(我的组)来进行非常有根据的猜测 1条件)。 (第2组检查符号链接的数量,文件描述符限制,名称长度限制,open()
权限,文件系统的可写性,以及可能O_CREAT
和POSIX O_NOATIME
个案例,但是它们更加繁琐,可能不那么便携,并且除非是恶意输入,否则预计不太可能发生,这是将它们归类为不太重要的原因。)
P.S。我现在添加了标签EWOULDBLOCK
,这是我的编程语言,但语言不太相关。
答案 0 :(得分:3)
没有防止故障的方法,因为(正如Jite评论的那样)其他一些进程可能已经改变了环境(例如删除了父目录,或者填满了文件系统,超出了磁盘配额,....在您的test_open
和更远的open
或creat
系统调用之间。或者磁盘(或包含文件系统的介质,例如某些USB记忆棒)可能已烧毁或已被拔掉。
好的做法是检查open
的结果,并在失败时使用errno
。
您之前可以使用access
检查一些事情。但既然没有防止故障的方法,为什么要这么麻烦?
您可以使用realpath(3)函数验证文件路径的目录部分....但即使这样也没用,其他一些进程可能已经创建或删除了test_open
和open
之间的目录真实{{1}}