diff options
author | 2021-08-22 09:06:15 +1000 | |
---|---|---|
committer | 2021-08-22 09:06:15 +1000 | |
commit | e8bbea1fc6e94e14768509d322f6c624403ffb36 (patch) | |
tree | 74dd1606a900d83de8aecff17a6737af4113308d /src/osd/modules/file/stdfile.cpp | |
parent | e319bde5fc3696d7f48f62b15b6366c4377fe5d1 (diff) |
formats, osd, util: Started refactoring file I/O stuff. (#8456)
Added more modern generic I/O interfaces with implementation backed by stdio, osd_file and core_file, replacing io_generic. Also replaced core_file's build-in zlib compression with a filter.
unzip.cpp, un7z.cpp: Added option to supply abstract I/O interface rather than filename.
Converted osd_file, core_file, archive_file, chd_file and device_image_interface to use std::error_condition rather than their own error enums.
Allow mounting TI-99 RPK from inside archives.
Diffstat (limited to 'src/osd/modules/file/stdfile.cpp')
-rw-r--r-- | src/osd/modules/file/stdfile.cpp | 104 |
1 files changed, 67 insertions, 37 deletions
diff --git a/src/osd/modules/file/stdfile.cpp b/src/osd/modules/file/stdfile.cpp index 96d7e53ebbe..4fd4662b884 100644 --- a/src/osd/modules/file/stdfile.cpp +++ b/src/osd/modules/file/stdfile.cpp @@ -10,12 +10,14 @@ #include "osdfile.h" #include <cassert> +#include <cerrno> #include <cstdint> #include <cstdio> #include <cstdlib> +#include <limits> #include <string> -#include <cstdio> // for fileno +#include <stdio.h> // for fileno #include <unistd.h> // for ftruncate @@ -25,7 +27,10 @@ class std_osd_file : public osd_file { public: - std_osd_file(FILE *f) : m_file(f) { assert(m_file); } + std_osd_file(FILE *f) noexcept : m_file(f) + { + assert(m_file); + } //============================================================ // osd_close @@ -34,59 +39,81 @@ public: virtual ~std_osd_file() override { // close the file handle - if (m_file) std::fclose(m_file); + if (m_file) + std::fclose(m_file); } //============================================================ // osd_read //============================================================ - virtual error read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override + virtual std::error_condition read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) noexcept override { - // seek to the new location; note that most fseek implementations are limited to 32 bits + // seek to the new location; note that most fseek implementations are limited to the range of long int + if (std::numeric_limits<long>::max() < offset) + return std::errc::invalid_argument; if (std::fseek(m_file, offset, SEEK_SET) < 0) - return error::FAILURE; + return std::error_condition(errno, std::generic_category()); // perform the read std::size_t const count = std::fread(buffer, 1, length, m_file); + if ((count < length) && std::ferror(m_file)) + { + std::clearerr(m_file); + return std::error_condition(errno, std::generic_category()); + } actual = count; - return error::NONE; + return std::error_condition(); } //============================================================ // osd_write //============================================================ - virtual error write(const void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override + virtual std::error_condition write(const void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) noexcept override { - // seek to the new location; note that most fseek implementations are limited to 32 bits + // seek to the new location; note that most fseek implementations are limited to the range of long int + if (std::numeric_limits<long>::max() < offset) + return std::errc::invalid_argument; if (std::fseek(m_file, offset, SEEK_SET) < 0) - return error::FAILURE; + return std::error_condition(errno, std::generic_category()); // perform the write std::size_t const count = std::fwrite(buffer, 1, length, m_file); + if (count < length) + { + std::clearerr(m_file); + return std::error_condition(errno, std::generic_category()); + } actual = count; - return error::NONE; + return std::error_condition(); } //============================================================ // osd_truncate //============================================================ - error truncate(std::uint64_t offset) override + virtual std::error_condition truncate(std::uint64_t offset) noexcept override { - return (ftruncate(fileno(m_file), offset) < 0) ? error::FAILURE : error::NONE; + // this is present in POSIX but not C/C++ + if (::ftruncate(::fileno(m_file), offset) < 0) + return std::error_condition(errno, std::generic_category()); + else + return std::error_condition(); } //============================================================ // osd_fflush //============================================================ - virtual error flush() override + virtual std::error_condition flush() noexcept override { - return (std::fflush(m_file) == EOF) ? error::FAILURE : error::NONE; + if (!std::fflush(m_file)) + return std::error_condition(); + else + return std::error_condition(errno, std::generic_category()); } private: @@ -100,7 +127,7 @@ private: // osd_open //============================================================ -osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize) +std::error_condition osd_file::open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize) noexcept { // based on the flags, choose a mode const char *mode; @@ -114,12 +141,12 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, else if (openflags & OPEN_FLAG_READ) mode = "rb"; else - return error::INVALID_ACCESS; + return std::errc::invalid_argument; // open the file FILE *const fileptr = std::fopen(path.c_str(), mode); if (!fileptr) - return error::NOT_FOUND; + return std::error_condition(errno, std::generic_category()); // get the size -- note that most fseek/ftell implementations are limited to 32 bits long length; @@ -127,21 +154,20 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, ((length = std::ftell(fileptr)) < 0) || (std::fseek(fileptr, 0, SEEK_SET) < 0)) { + std::error_condition err(errno, std::generic_category()); std::fclose(fileptr); - return error::FAILURE; + return err; } - try - { - file = std::make_unique<std_osd_file>(fileptr); - filesize = std::int64_t(length); - return error::NONE; - } - catch (...) + osd_file::ptr result(new (std::nothrow) std_osd_file(fileptr)); + if (!result) { std::fclose(fileptr); - return error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } + file = std::move(result); + filesize = std::int64_t(length); + return std::error_condition(); } @@ -149,9 +175,9 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, // osd_openpty //============================================================ -osd_file::error osd_file::openpty(ptr &file, std::string &name) +std::error_condition osd_file::openpty(ptr &file, std::string &name) noexcept { - return error::FAILURE; + return std::errc::not_supported; } @@ -159,9 +185,12 @@ osd_file::error osd_file::openpty(ptr &file, std::string &name) // osd_rmfile //============================================================ -osd_file::error osd_file::remove(std::string const &filename) +std::error_condition osd_file::remove(std::string const &filename) noexcept { - return (std::remove(filename.c_str()) < 0) ? error::FAILURE : error::NONE; + if (!std::remove(filename.c_str())) + return std::error_condition(); + else + return std::error_condition(errno, std::generic_category()); } @@ -169,7 +198,7 @@ osd_file::error osd_file::remove(std::string const &filename) // osd_get_physical_drive_geometry //============================================================ -bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, uint32_t *heads, uint32_t *sectors, uint32_t *bps) +bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, uint32_t *heads, uint32_t *sectors, uint32_t *bps) noexcept { // there is no standard way of doing this, so we always return false, indicating // that a given path is not a physical drive @@ -181,7 +210,7 @@ bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, // osd_uchar_from_osdchar //============================================================ -int osd_uchar_from_osdchar(char32_t *uchar, const char *osdchar, size_t count) +int osd_uchar_from_osdchar(char32_t *uchar, const char *osdchar, size_t count) noexcept { // we assume a standard 1:1 mapping of characters to the first 256 unicode characters *uchar = (uint8_t)*osdchar; @@ -221,13 +250,14 @@ osd_directory_entry *osd_stat(const std::string &path) // osd_get_full_path //============================================================ -osd_file::error osd_get_full_path(std::string &dst, std::string const &path) +std::error_condition osd_get_full_path(std::string &dst, std::string const &path) noexcept { // derive the full path of the file in an allocated string // for now just fake it since we don't presume any underlying file system - dst = path; + try { dst = path; } + catch (...) { return std::errc::not_enough_memory; } - return osd_file::error::NONE; + return std::error_condition(); } @@ -235,7 +265,7 @@ osd_file::error osd_get_full_path(std::string &dst, std::string const &path) // osd_is_absolute_path //============================================================ -bool osd_is_absolute_path(std::string const &path) +bool osd_is_absolute_path(std::string const &path) noexcept { // assume no for everything return false; |