Program Listing for File disk_io.cpp
↰ Return to documentation for file (disk_io.cpp)
#include <array>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <format>
#include "disk_io.hpp"
std::string errno_msg(int errn)
{
constexpr static auto SIZE = std::size_t{256};
std::array<char, SIZE> buffer{};
if (strerror_r(errn, buffer.data(), sizeof(buffer)) != nullptr) {
return "Unknown error";
}
return {buffer.data()};
}
DiskIO::DiskIO(const std::string& filename, size_t block_size, std::string_view op, bool is_fifo)
: m_filename(filename), m_block_size(block_size), m_fd(-1), m_fstream(nullptr)
{
if (m_filename.empty()){
ers::warning(felix_log::disk_io_issue(ERS_HERE, "Filename is empty. File/Fifo not opened."));
return;
}
if (is_fifo){
ERS_INFO(std::format("Opening fifo {}", m_filename));
open_fifo(op);
} else {
ERS_INFO(std::format("Opening file {}", m_filename));
open_file(op);
}
}
DiskIO::~DiskIO()
{
if (m_fstream){
fclose(m_fstream);
}
}
void DiskIO::open_file(std::string_view op)
{
m_fstream = fopen(m_filename.c_str(), op.data());
if (!m_fstream){
ers::error(felix_log::disk_io_issue(ERS_HERE, std::format("cannot open file {}. {}", m_filename.c_str(), errno_msg(errno).c_str())));
}
m_fd = fileno(m_fstream);
if (m_fd == -1){
ers::error(felix_log::disk_io_issue(ERS_HERE, std::format("cannot get file descriptor for {}. {}", m_filename.c_str(), errno_msg(errno).c_str())));
}
}
void DiskIO::open_fifo(std::string_view op)
{
int ret = mkfifo(m_filename.c_str(), 0666);
if (ret != 0 and errno != EEXIST){
ers::error(felix_log::disk_io_issue(ERS_HERE, std::format("cannot create fifo {}. {}", m_filename.c_str(), errno_msg(errno).c_str())));
}
int trick_fd = open(m_filename.c_str(), O_RDONLY | O_NONBLOCK);
m_fd = open(m_filename.c_str(), O_RDWR | O_NONBLOCK);
if (m_fd == -1){
ers::error(felix_log::disk_io_issue(ERS_HERE, std::format("cannot open file {}. {}", m_filename.c_str(), errno_msg(errno).c_str())));
}
m_fstream = fdopen(m_fd, op.data());
if (!m_fstream){
ers::error(felix_log::disk_io_issue(ERS_HERE, std::format("cannot get stream from open fifo {}. {}", m_filename.c_str(), errno_msg(errno).c_str())));
}
close(trick_fd);
}
bool DiskIO::is_eof()
{
return static_cast<bool>(feof(m_fstream));
}
int DiskIO::reset_position()
{
return fseek(m_fstream, 0, SEEK_SET);
}
size_t DiskIO::block_read(void *to_read, size_t max_blocks)
{
size_t read = 0;
if ( m_fstream ){
read = fread(to_read, m_block_size, max_blocks, m_fstream);
}
return read;
}
size_t DiskIO::block_write(const void *to_write, size_t max_blocks)
{
size_t written = 0;
if ( m_fstream ){
written = fwrite(to_write, m_block_size, max_blocks, m_fstream);
fflush(m_fstream);
} else {
written = max_blocks;
}
return written;
}
size_t DiskIO::byte_read(void* to_read, size_t bytes)
{
if ( m_fd == -1 ){
return 0;
} else {
return read(m_fd, to_read, bytes);
}
}
size_t DiskIO::byte_write(void* to_write, size_t bytes)
{
if ( m_fd == -1 ){
return bytes;
} else {
return write(m_fd, to_write, bytes);
}
}