【问题标题】:Check if file is a named pipe (fifo) in C++检查文件是否是 C++ 中的命名管道 (fifo)
【发布时间】:2014-01-30 22:32:56
【问题描述】:

我有一个程序使用 C++ 从文件“foo”中读取:

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

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

我使用 python 发现了完全相同的问题: Check if file is a named pipe (fifo) in python?我可以在 C++ 中做类似的事情吗?

【问题讨论】:

    标签: c++ fifo


    【解决方案1】:

    来自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 的出色 answer,以及 Brian 对它的评论。

    【讨论】:

    • 还有S_ISFIFO(st.st_mode),这是一个测试管道或FIFO特殊文件的宏。目前尚不清楚您可以将管道与 FIFO 区分开来。
    【解决方案2】:

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

    【讨论】:

    • 使用stat 然后fopen 会导致TOCTTOU 漏洞。如果这是一个安全问题,最好的解决方案是open non-blocking 然后fstatfdopen
    • 我认为非阻塞 open() 意味着随后的 read() 调用是非阻塞的。但是查看手册页确认open() 本身也变得非阻塞。
    【解决方案3】:

    在现代 C++ 中也有 filesystem library,它从 C++17 开始可用 #include <experimental/filesystem>,在 C++14 中它是 experimental #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 链接。

    【讨论】:

      猜你喜欢
      • 2012-01-23
      • 2017-06-23
      • 1970-01-01
      • 1970-01-01
      • 2021-06-09
      • 1970-01-01
      • 2015-11-15
      • 1970-01-01
      • 2013-05-19
      相关资源
      最近更新 更多