#pragma once #include #include #include #include #include "common.hpp" #include "utils/scope.hpp" LEMONBUDDY_NS namespace file_util { /** * RAII file wrapper */ class file_ptr { public: /** * Constructor: open file handler */ explicit file_ptr(const string& path, const string& mode = "a+") : m_path(string(path)), m_mode(string(mode)) { m_ptr = fopen(m_path.c_str(), m_mode.c_str()); } /** * Destructor: close file handler */ ~file_ptr() { if (m_ptr != nullptr) fclose(m_ptr); } /** * Logical operator testing if the file handler was created */ operator bool() { return m_ptr != nullptr; } /** * Call operator returning a pointer to the file handler */ FILE* operator()() { return m_ptr; } protected: FILE* m_ptr = nullptr; string m_path; string m_mode; }; /** * Checks if the given file exist */ inline auto exists(string filename) { struct stat buffer; return stat(filename.c_str(), &buffer) == 0; } /** * Gets the contents of the given file */ inline auto get_contents(string filename) { try { std::ifstream ifs(filename); string contents((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); return contents; } catch (std::ios_base::failure& e) { return string{""}; } } /** * Puts the given file descriptor into blocking mode */ inline auto set_block(int fd) { int flags = fcntl(fd, F_GETFL, 0); flags &= ~O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) == -1) throw system_error("Failed to unset O_NONBLOCK"); } /** * Puts the given file descriptor into non-blocking mode */ inline auto set_nonblock(int fd) { int flags = fcntl(fd, F_GETFL, 0); flags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) == -1) throw system_error("Failed to set O_NONBLOCK"); } /** * Checks if the given file is a named pipe */ inline auto is_fifo(string filename) { auto fileptr = make_unique(filename); int fd = fileno((*fileptr)()); struct stat statbuf; fstat(fd, &statbuf); return S_ISFIFO(statbuf.st_mode); } } LEMONBUDDY_NS_END