检查文件是否是C++中的命名管道 (fifo)

Check if file is a named pipe (fifo) in C++

本文关键字:管道 fifo 文件 是否是 C++ 检查      更新时间:2023-10-16

我有一个程序使用C++从文件"foo"读取

pFile = fopen ("foo" , "r");

如果文件是命名管道,我希望它停止执行函数的其余部分。有没有办法在打开文件之前检查文件是否是命名管道?

我使用python发现了完全相同的问题: 检查文件是否是 python 中的命名管道 (fifo)?我可以在C++做类似的事情吗?

man 2 stat

int fstat(int filedes, struct stat *buf);

。定义了以下 POSIX 宏以使用 st_mode 字段检查文件类型:

S_ISFIFO(m) FIFO (named pipe)?

所以struct stat st; ... !fstat(fileno(pFile, &st) && S_ISFIFO(st.st_mode)应该工作。

编辑:另请参阅SzG的出色回答,以及Brian对此的评论。

fopen()之后停止执行可能为时已晚。这是因为open()系统调用将阻塞,直到有人打开 FIFO 进行写入。相反,在fopen()之前使用stat()系统调用(在Unix/Linux上)来找出答案。

在现代C++中,还有文件系统库,它从 C++17#include <experimental/filesystem>开始可用,在 C++14 年它是实验性的#include <experimental/filesystem>

所以你现在可以使用 is_fifo()。filesystem::path类可以从std::string构造,这是可以从const char*解释的,所以filesystem::is_fifo("/path/to/file")将按预期工作。但是此版本可能会引发异常,因此bool is_fifo( const std::filesystem::path& p, std::error_code& ec ) noexcept;是您的选择。

#if __cplusplus >= 201703L
#include <filesystem>
namespace filesystem = std::filesystem;
#else
#include <experimental/filesystem>
namespace filesystem = std::experimental::filesystem;
#endif
bool is_fifo(const char *path)
{
std::error_code ec;
bool res = filesystem::is_fifo(path, ec);
if (ec.value() != 0)
std::cerr << ec.message() << std::endl;
return res;
}

并且不要忘记此通知:

9.1 之前的 GNU 实现需要与-lstdc++fs链接,LLVM 9.0 之前的 LLVM 实现需要与-lc++fs链接。