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 "disk_io.hpp"
#include "log.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()){
        LOG_WARN("Filename is empty. File/Fifo not opened.");
        return;
    }

    if (is_fifo){
        LOG_INFO("Opening fifo %s", m_filename.c_str());
        open_fifo(op);
    } else {
        LOG_INFO("Opening file %s", m_filename.c_str());
        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){
        LOG_ERR("cannot open file %s. %s", m_filename.c_str(), errno_msg(errno).c_str());
    }
    m_fd = fileno(m_fstream);
    if (m_fd == -1){
        LOG_ERR("cannot get file descriptor for %s. %s", 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){
        LOG_ERR("cannot create fifo %s. %s", 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){
        LOG_ERR("cannot open file %s. %s", m_filename.c_str(), errno_msg(errno).c_str());
    }
    m_fstream = fdopen(m_fd, op.data());
    if (!m_fstream){
        LOG_ERR("cannot get stream from open fifo %s. %s", 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);
    }
}