Reputation: 165
I have a program reading from a file "foo" using C++ using:
pFile = fopen ("foo" , "r");
I want it to stop executing the rest of the function if the file is a named pipe. Is there a way to check if the file is a named pipe before opening it?
I found the exact same question using python: Check if file is a named pipe (fifo) in python? Can I do something similar in C++?
Upvotes: 6
Views: 8022
Reputation: 313
In modern C++ there is also filesystem library, it is available since C++17 #include <experimental/filesystem>
, in C++14 it was experimental #include <experimental/filesystem>
So you can you use is_fifo() now. filesystem::path
class is constructible from std::string
, which is construcible from const char*
, so filesystem::is_fifo("/path/to/file")
will work as expected. But this version can throw an exception, so bool is_fifo( const std::filesystem::path& p, std::error_code& ec ) noexcept;
is your choice.
#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;
}
And don't forget this notice:
GNU implementation prior to 9.1 requires linking with
-lstdc++fs
and LLVM implementation prior to LLVM 9.0 requires linking with-lc++fs
.
Upvotes: 0
Reputation: 9972
From man 2 stat
:
int fstat(int filedes, struct stat *buf);
...The following POSIX macros are defined to check the file type using the st_mode field:
S_ISFIFO(m) FIFO (named pipe)?
So struct stat st; ... !fstat(fileno(pFile, &st) && S_ISFIFO(st.st_mode)
should work.
Edit: See also SzG's excellent answer, and Brian's comment to it.
Upvotes: 9
Reputation: 12629
It might be a bit too late to stop the execution AFTER fopen()
. It's because the open()
syscall will block until someone has opened the FIFO for writing. Instead, use the stat()
syscall (on Unix/Linux) before fopen()
to find out.
Upvotes: 2