diff options
author | Vas Crabb <cuavas@users.noreply.github.com> | 2021-08-22 09:06:15 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-22 09:06:15 +1000 |
commit | e8bbea1fc6e94e14768509d322f6c624403ffb36 (patch) | |
tree | 74dd1606a900d83de8aecff17a6737af4113308d /src/osd/modules | |
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')
-rw-r--r-- | src/osd/modules/debugger/debuggdbstub.cpp | 4 | ||||
-rw-r--r-- | src/osd/modules/debugger/debugimgui.cpp | 8 | ||||
-rw-r--r-- | src/osd/modules/file/posixdomain.cpp | 208 | ||||
-rw-r--r-- | src/osd/modules/file/posixfile.cpp | 166 | ||||
-rw-r--r-- | src/osd/modules/file/posixfile.h | 18 | ||||
-rw-r--r-- | src/osd/modules/file/posixptty.cpp | 57 | ||||
-rw-r--r-- | src/osd/modules/file/posixsocket.cpp | 187 | ||||
-rw-r--r-- | src/osd/modules/file/stdfile.cpp | 104 | ||||
-rw-r--r-- | src/osd/modules/file/winfile.cpp | 176 | ||||
-rw-r--r-- | src/osd/modules/file/winfile.h | 23 | ||||
-rw-r--r-- | src/osd/modules/file/winptty.cpp | 44 | ||||
-rw-r--r-- | src/osd/modules/file/winsocket.cpp | 130 | ||||
-rw-r--r-- | src/osd/modules/font/font_sdl.cpp | 6 | ||||
-rw-r--r-- | src/osd/modules/render/aviwrite.cpp | 4 | ||||
-rw-r--r-- | src/osd/modules/render/bgfx/texturemanager.cpp | 2 | ||||
-rw-r--r-- | src/osd/modules/render/d3d/d3dhlsl.cpp | 10 |
16 files changed, 518 insertions, 629 deletions
diff --git a/src/osd/modules/debugger/debuggdbstub.cpp b/src/osd/modules/debugger/debuggdbstub.cpp index 52289b9997d..6229e6ffba5 100644 --- a/src/osd/modules/debugger/debuggdbstub.cpp +++ b/src/osd/modules/debugger/debuggdbstub.cpp @@ -707,8 +707,8 @@ void debug_gdbstub::wait_for_debugger(device_t &device, bool firststop) #endif std::string socket_name = string_format("socket.localhost:%d", m_debugger_port); - osd_file::error filerr = m_socket.open(socket_name); - if ( filerr != osd_file::error::NONE ) + std::error_condition const filerr = m_socket.open(socket_name); + if ( filerr ) fatalerror("gdbstub: failed to start listening on port %d\n", m_debugger_port); osd_printf_info("gdbstub: listening on port %d\n", m_debugger_port); diff --git a/src/osd/modules/debugger/debugimgui.cpp b/src/osd/modules/debugger/debugimgui.cpp index 8c161792f9d..1046118899c 100644 --- a/src/osd/modules/debugger/debugimgui.cpp +++ b/src/osd/modules/debugger/debugimgui.cpp @@ -938,7 +938,7 @@ void debug_imgui::mount_image() { if(m_selected_file != nullptr) { - osd_file::error err; + std::error_condition err; switch(m_selected_file->type) { case file_entry_type::DRIVE: @@ -947,7 +947,7 @@ void debug_imgui::mount_image() util::zippath_directory::ptr dir; err = util::zippath_directory::open(m_selected_file->fullpath, dir); } - if(err == osd_file::error::NONE) + if(!err) { m_filelist_refresh = true; strcpy(m_path,m_selected_file->fullpath.c_str()); @@ -989,8 +989,8 @@ void debug_imgui::refresh_filelist() m_filelist_refresh = false; util::zippath_directory::ptr dir; - osd_file::error const err = util::zippath_directory::open(m_path,dir); - if(err == osd_file::error::NONE) + std::error_condition const err = util::zippath_directory::open(m_path,dir); + if(!err) { int x = 0; // add drives diff --git a/src/osd/modules/file/posixdomain.cpp b/src/osd/modules/file/posixdomain.cpp deleted file mode 100644 index 13d564d1738..00000000000 --- a/src/osd/modules/file/posixdomain.cpp +++ /dev/null @@ -1,208 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert, R. Belmont, Vas Crabb -//============================================================ -// -// sdldomain.c - SDL socket (unix) access functions -// -// SDLMAME by Olivier Galibert and R. Belmont -// -//============================================================ - -#include "posixfile.h" - -#include <cassert> -#include <cerrno> -#include <cstdio> -#include <cstring> - -#include <sys/select.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/time.h> -#include <unistd.h> -#include <fcntl.h> - - -namespace { -char const *const posixfile_domain_identifier = "domain."; - - -class posix_osd_domain : public osd_file -{ -public: - posix_osd_domain(posix_osd_domain const &) = delete; - posix_osd_domain(posix_osd_domain &&) = delete; - posix_osd_domain& operator=(posix_osd_domain const &) = delete; - posix_osd_domain& operator=(posix_osd_domain &&) = delete; - - posix_osd_domain(int sock, bool listening) - : m_sock(sock) - , m_listening(listening) - { - assert(m_sock >= 0); - } - - virtual ~posix_osd_domain() - { - ::close(m_sock); - } - - virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override - { - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(m_sock, &readfds); - - struct timeval timeout; - timeout.tv_sec = timeout.tv_usec = 0; - - if (select(m_sock + 1, &readfds, nullptr, nullptr, &timeout) < 0) - { - char line[80]; - std::sprintf(line, "%s : %s : %d ", __func__, __FILE__, __LINE__); - std::perror(line); - return errno_to_file_error(errno); - } - else if (FD_ISSET(m_sock, &readfds)) - { - if (!m_listening) - { - // connected socket - ssize_t const result = ::read(m_sock, buffer, count); - if (result < 0) - { - return errno_to_file_error(errno); - } - else - { - actual = std::uint32_t(size_t(result)); - return error::NONE; - } - } - else - { - // listening socket - int const accepted = ::accept(m_sock, nullptr, nullptr); - if (accepted < 0) - { - return errno_to_file_error(errno); - } - else - { - ::close(m_sock); - m_sock = accepted; - m_listening = false; - actual = 0; - - return error::NONE; - } - } - } - else - { - return error::FAILURE; - } - } - - virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override - { - ssize_t const result = ::write(m_sock, buffer, count); - if (result < 0) - return errno_to_file_error(errno); - - actual = std::uint32_t(size_t(result)); - return error::NONE; - } - - virtual error truncate(std::uint64_t offset) override - { - // doesn't make sense on socket - return error::INVALID_ACCESS; - } - - virtual error flush() override - { - // there's no simple way to flush buffers on a socket anyway - return error::NONE; - } - -private: - int m_sock; - bool m_listening; -}; - -} // anonymous namespace - - -bool posix_check_domain_path(std::string const &path) -{ - if (strncmp(path.c_str(), posixfile_domain_identifier, strlen(posixfile_domain_identifier)) == 0) - return true; - return false; -} - - -osd_file::error posix_open_domain(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) -{ - struct sockaddr_un sau; - memset(&sau, 0, sizeof(sau)); - sau.sun_family = AF_UNIX; - strncpy(sau.sun_path, &path.c_str()[strlen(posixfile_domain_identifier)], sizeof(sau.sun_path)-1); - - int const sock = ::socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - return errno_to_file_error(errno); - - fcntl(sock, F_SETFL, O_NONBLOCK); - - // listening socket support - if (openflags & OPEN_FLAG_CREATE) - { - if (::bind(sock, reinterpret_cast<struct sockaddr const *>(&sau), sizeof(struct sockaddr_un)) < 0) - { - int const err = errno; - ::close(sock); - return errno_to_file_error(err); - } - - // start to listen... - if (::listen(sock, 1) < 0) - { - int const err = errno; - ::close(sock); - return errno_to_file_error(err); - } - - // mark socket as "listening" - try - { - file = std::make_unique<posix_osd_domain>(sock, true); - filesize = 0; - return osd_file::error::NONE; - } - catch (...) - { - ::close(sock); - return osd_file::error::OUT_OF_MEMORY; - } - } - else - { - if (::connect(sock, reinterpret_cast<struct sockaddr const *>(&sau), sizeof(struct sockaddr_un)) < 0) - { - ::close(sock); - return osd_file::error::ACCESS_DENIED; // have to return this value or bitb won't try to bind on connect failure - } - try - { - file = std::make_unique<posix_osd_domain>(sock, false); - filesize = 0; - return osd_file::error::NONE; - } - catch (...) - { - ::close(sock); - return osd_file::error::OUT_OF_MEMORY; - } - } -} diff --git a/src/osd/modules/file/posixfile.cpp b/src/osd/modules/file/posixfile.cpp index ffdd4c4d477..b7c1cde7442 100644 --- a/src/osd/modules/file/posixfile.cpp +++ b/src/osd/modules/file/posixfile.cpp @@ -64,6 +64,7 @@ namespace { + //============================================================ // CONSTANTS //============================================================ @@ -85,7 +86,7 @@ public: posix_osd_file& operator=(posix_osd_file const &) = delete; posix_osd_file& operator=(posix_osd_file &&) = delete; - posix_osd_file(int fd) : m_fd(fd) + posix_osd_file(int fd) noexcept : m_fd(fd) { assert(m_fd >= 0); } @@ -95,7 +96,7 @@ public: ::close(m_fd); } - virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { ssize_t result; @@ -103,20 +104,20 @@ public: result = ::pread(m_fd, buffer, size_t(count), off_t(std::make_unsigned_t<off_t>(offset))); #elif defined(WIN32) || defined(SDLMAME_NO64BITIO) if (lseek(m_fd, off_t(std::make_unsigned_t<off_t>(offset)), SEEK_SET) < 0) - return errno_to_file_error(errno) + return std::error_condition(errno, std::generic_category()); result = ::read(m_fd, buffer, size_t(count)); #else result = ::pread64(m_fd, buffer, size_t(count), off64_t(offset)); #endif if (result < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); actual = std::uint32_t(std::size_t(result)); - return error::NONE; + return std::error_condition(); } - virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { ssize_t result; @@ -124,20 +125,20 @@ public: result = ::pwrite(m_fd, buffer, size_t(count), off_t(std::make_unsigned_t<off_t>(offset))); #elif defined(WIN32) || defined(SDLMAME_NO64BITIO) if (lseek(m_fd, off_t(std::make_unsigned_t<off_t>(offset)), SEEK_SET) < 0) - return errno_to_file_error(errno) + return std::error_condition(errno, std::generic_category()); result = ::write(m_fd, buffer, size_t(count)); #else result = ::pwrite64(m_fd, buffer, size_t(count), off64_t(offset)); #endif if (result < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); actual = std::uint32_t(std::size_t(result)); - return error::NONE; + return std::error_condition(); } - virtual error truncate(std::uint64_t offset) override + virtual std::error_condition truncate(std::uint64_t offset) noexcept override { int result; @@ -148,15 +149,15 @@ public: #endif if (result < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); - return error::NONE; + return std::error_condition(); } - virtual error flush() override + virtual std::error_condition flush() noexcept override { // no user-space buffering on unistd I/O - return error::NONE; + return std::error_condition(); } private: @@ -168,7 +169,7 @@ private: // is_path_separator //============================================================ -bool is_path_separator(char c) +bool is_path_separator(char c) noexcept { #if defined(WIN32) return (c == PATHSEPCH) || (c == INVPATHSEPCH); @@ -182,31 +183,36 @@ bool is_path_separator(char c) // create_path_recursive //============================================================ -osd_file::error create_path_recursive(std::string const &path) +std::error_condition create_path_recursive(std::string_view path) noexcept { // if there's still a separator, and it's not the root, nuke it and recurse auto const sep = path.rfind(PATHSEPCH); - if ((sep != std::string::npos) && (sep > 0) && (path[sep - 1] != PATHSEPCH)) + if ((sep != std::string_view::npos) && (sep > 0) && (path[sep - 1] != PATHSEPCH)) { - osd_file::error const err = create_path_recursive(path.substr(0, sep)); - if (err != osd_file::error::NONE) + std::error_condition err = create_path_recursive(path.substr(0, sep)); + if (err) return err; } + // need a NUL-terminated version of the subpath + std::string p; + try { p = path; } + catch (...) { return std::errc::not_enough_memory; } + // if the path already exists, we're done struct stat st; - if (!::stat(path.c_str(), &st)) - return osd_file::error::NONE; + if (!::stat(p.c_str(), &st)) + return std::error_condition(); // create the path #ifdef WIN32 - if (mkdir(path.c_str()) < 0) + if (mkdir(p.c_str()) < 0) #else - if (mkdir(path.c_str(), 0777) < 0) + if (mkdir(p.c_str(), 0777) < 0) #endif - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); else - return osd_file::error::NONE; + return std::error_condition(); } } // anonymous namespace @@ -216,7 +222,7 @@ osd_file::error create_path_recursive(std::string const &path) // osd_file::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 { std::string dst; if (posix_check_socket_path(path)) @@ -239,7 +245,7 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, } else { - return error::INVALID_ACCESS; + return std::errc::invalid_argument; } #if defined(WIN32) access |= O_BINARY; @@ -251,7 +257,8 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, for (auto it = dst.begin(); it != dst.end(); ++it) *it = (INVPATHSEPCH == *it) ? PATHSEPCH : *it; #endif - osd_subst_env(dst, dst); + try { osd_subst_env(dst, dst); } + catch (...) { return std::errc::not_enough_memory; } // attempt to open the file int fd = -1; @@ -263,6 +270,9 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, if (fd < 0) { + // save the error from the first attempt to open the file + std::error_condition openerr(errno, std::generic_category()); + // create the path if necessary if ((openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS)) { @@ -270,10 +280,10 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, if (pathsep != std::string::npos) { // create the path up to the file - osd_file::error const error = create_path_recursive(dst.substr(0, pathsep)); + std::error_condition const createrr = create_path_recursive(dst.substr(0, pathsep)); // attempt to reopen the file - if (error == osd_file::error::NONE) + if (!createrr) { #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__) fd = ::open(dst.c_str(), access, 0666); @@ -281,13 +291,17 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, fd = ::open64(dst.c_str(), access, 0666); #endif } + if (fd < 0) + { + openerr.assign(errno, std::generic_category()); + } } } // if we still failed, clean up and free if (fd < 0) { - return errno_to_file_error(errno); + return openerr; } } @@ -300,22 +314,20 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, if (::fstat64(fd, &st) < 0) #endif { - int const error = errno; + std::error_condition staterr(errno, std::generic_category()); ::close(fd); - return errno_to_file_error(error); + return staterr; } - filesize = std::uint64_t(std::make_unsigned_t<decltype(st.st_size)>(st.st_size)); - try - { - file = std::make_unique<posix_osd_file>(fd); - return error::NONE; - } - catch (...) + osd_file::ptr result(new (std::nothrow) posix_osd_file(fd)); + if (!result) { ::close(fd); - return error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } + file = std::move(result); + filesize = std::uint64_t(std::make_unsigned_t<decltype(st.st_size)>(st.st_size)); + return std::error_condition(); } @@ -323,9 +335,9 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, // osd_file::openpty //============================================================ -osd_file::error osd_file::openpty(ptr &file, std::string &name) +std::error_condition osd_file::openpty(ptr &file, std::string &name) noexcept { - std::uint64_t filesize; + std::uint64_t filesize; return posix_open_ptty(OPEN_FLAG_READ | OPEN_FLAG_WRITE, file, filesize, name); } @@ -334,12 +346,12 @@ osd_file::error osd_file::openpty(ptr &file, std::string &name) // osd_file::remove //============================================================ -osd_file::error osd_file::remove(std::string const &filename) +std::error_condition osd_file::remove(std::string const &filename) noexcept { if (::unlink(filename.c_str()) < -1) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); else - return error::NONE; + return std::error_condition(); } @@ -347,7 +359,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 { return false; // no, no way, huh-uh, forget it } @@ -389,7 +401,7 @@ std::unique_ptr<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 { try { @@ -398,49 +410,49 @@ osd_file::error osd_get_full_path(std::string &dst, std::string const &path) if (::_fullpath(&path_buffer[0], path.c_str(), MAX_PATH)) { dst = &path_buffer[0]; - return osd_file::error::NONE; + return std::error_condition(); } else { - return osd_file::error::FAILURE; + return std::errc::io_error; // TODO: better error reporting? } #else std::unique_ptr<char, void (*)(void *)> canonical(::realpath(path.c_str(), nullptr), &std::free); if (canonical) { dst = canonical.get(); - return osd_file::error::NONE; + return std::error_condition(); } std::vector<char> path_buffer(PATH_MAX); if (::realpath(path.c_str(), &path_buffer[0])) { dst = &path_buffer[0]; - return osd_file::error::NONE; + return std::error_condition(); } else if (path[0] == PATHSEPCH) { dst = path; - return osd_file::error::NONE; + return std::error_condition(); } else { while (!::getcwd(&path_buffer[0], path_buffer.size())) { if (errno != ERANGE) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); else path_buffer.resize(path_buffer.size() * 2); } dst.assign(&path_buffer[0]).push_back(PATHSEPCH); dst.append(path); - return osd_file::error::NONE; + return std::error_condition(); } #endif } catch (...) { - return osd_file::error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } } @@ -449,7 +461,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 { if (!path.empty() && is_path_separator(path[0])) return true; @@ -492,7 +504,7 @@ std::vector<std::string> osd_get_volume_names() // osd_is_valid_filename_char //============================================================ -bool osd_is_valid_filename_char(char32_t uchar) +bool osd_is_valid_filename_char(char32_t uchar) noexcept { // The only one that's actually invalid is the slash // The other two are just problematic because they're the escape character and path separator @@ -512,7 +524,7 @@ bool osd_is_valid_filename_char(char32_t uchar) // osd_is_valid_filepath_char //============================================================ -bool osd_is_valid_filepath_char(char32_t uchar) +bool osd_is_valid_filepath_char(char32_t uchar) noexcept { // One could argue that colon should be in here too because it functions as path separator return uchar >= 0x20 @@ -527,39 +539,3 @@ bool osd_is_valid_filepath_char(char32_t uchar) #endif && uchar_isvalid(uchar); } - - -//============================================================ -// errno_to_file_error -//============================================================ - -osd_file::error errno_to_file_error(int error) -{ - switch (error) - { - case 0: - return osd_file::error::NONE; - - case ENOENT: - case ENOTDIR: - return osd_file::error::NOT_FOUND; - - case EACCES: - case EROFS: -#ifndef WIN32 - case ETXTBSY: -#endif - case EEXIST: - case EPERM: - case EISDIR: - case EINVAL: - return osd_file::error::ACCESS_DENIED; - - case ENFILE: - case EMFILE: - return osd_file::error::TOO_MANY_FILES; - - default: - return osd_file::error::FAILURE; - } -} diff --git a/src/osd/modules/file/posixfile.h b/src/osd/modules/file/posixfile.h index d47c03d691e..eb6f010859e 100644 --- a/src/osd/modules/file/posixfile.h +++ b/src/osd/modules/file/posixfile.h @@ -7,25 +7,29 @@ // SDLMAME by Olivier Galibert and R. Belmont // //============================================================ +#ifndef MAME_OSD_MODULES_FILE_POSIXFILE_H +#define MAME_OSD_MODULES_FILE_POSIXFILE_H +#pragma once #include "osdfile.h" #include <cstdint> #include <string> +#include <system_error> //============================================================ // PROTOTYPES //============================================================ -bool posix_check_socket_path(std::string const &path); -osd_file::error posix_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize); +bool posix_check_socket_path(std::string const &path) noexcept; +std::error_condition posix_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept; -bool posix_check_domain_path(std::string const &path); -osd_file::error posix_open_domain(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize); +bool posix_check_domain_path(std::string const &path) noexcept; +std::error_condition posix_open_domain(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept; -bool posix_check_ptty_path(std::string const &path); -osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize, std::string &name); +bool posix_check_ptty_path(std::string const &path) noexcept; +std::error_condition posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize, std::string &name) noexcept; -osd_file::error errno_to_file_error(int error); +#endif // MAME_OSD_MODULES_FILE_POSIXFILE_H diff --git a/src/osd/modules/file/posixptty.cpp b/src/osd/modules/file/posixptty.cpp index 5ecb37057ad..57ff069a2ce 100644 --- a/src/osd/modules/file/posixptty.cpp +++ b/src/osd/modules/file/posixptty.cpp @@ -52,7 +52,7 @@ public: posix_osd_ptty& operator=(posix_osd_ptty const &) = delete; posix_osd_ptty& operator=(posix_osd_ptty &&) = delete; - posix_osd_ptty(int fd) : m_fd(fd) + posix_osd_ptty(int fd) noexcept : m_fd(fd) { assert(m_fd >= 0); } @@ -62,36 +62,36 @@ public: ::close(m_fd); } - virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { ssize_t const result = ::read(m_fd, buffer, count); if (result < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); actual = std::uint32_t(size_t(result)); - return error::NONE; + return std::error_condition(); } - virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { ssize_t const result = ::write(m_fd, buffer, count); if (result < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); actual = std::uint32_t(size_t(result)); - return error::NONE; + return std::error_condition(); } - virtual error truncate(std::uint64_t offset) override + virtual std::error_condition truncate(std::uint64_t offset) noexcept override { // doesn't make sense on ptty - return error::INVALID_ACCESS; + return std::errc::bad_file_descriptor; } - virtual error flush() override + virtual std::error_condition flush() noexcept override { // no userspace buffers on read/write - return error::NONE; + return std::error_condition(); } private: @@ -101,17 +101,18 @@ private: } // anonymous namespace -bool posix_check_ptty_path(std::string const &path) +bool posix_check_ptty_path(std::string const &path) noexcept { return strncmp(path.c_str(), posix_ptty_identifier, strlen(posix_ptty_identifier)) == 0; } -osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize, std::string &name) +std::error_condition posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize, std::string &name) noexcept { #if defined(__ANDROID__) - return osd_file::error::FAILURE; + return std::errc::not_supported; // TODO: revisit this error code #else // defined(__ANDROID__) + // TODO: handling of the slave path is insecure - should use ptsname_r/ttyname_r in a loop #if (defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__)) int access = O_NOCTTY; if (openflags & OPEN_FLAG_WRITE) @@ -119,11 +120,11 @@ osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, st else if (openflags & OPEN_FLAG_READ) access |= O_RDONLY; else - return osd_file::error::INVALID_ACCESS; + return std::errc::invalid_argument; int const masterfd = ::posix_openpt(access); if (masterfd < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); // grant access to slave device and check that it can be opened char const *slavepath; @@ -133,9 +134,9 @@ osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, st ((slavepath = ::ptsname(masterfd)) == nullptr) || ((slavefd = ::open(slavepath, O_RDWR | O_NOCTTY)) < 0)) { - int const err = errno; + std::error_condition err(errno, std::generic_category()); ::close(masterfd); - return errno_to_file_error(err); + return err; } // check that it's possible to stack BSD-compatibility STREAMS modules @@ -143,20 +144,20 @@ osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, st (::ioctl(slavefd, I_PUSH, "ldterm") < 0) || (::ioctl(slavefd, I_PUSH, "ttcompat") < 0)) { - int const err = errno; + std::error_condition err(errno, std::generic_category()); ::close(slavefd); ::close(masterfd); - return errno_to_file_error(err); + return err; } #else struct termios tios; std::memset(&tios, 0, sizeof(tios)); - ::cfmakeraw(&tios); + ::cfmakeraw(&tios); // TODO: this is a non-standard BSDism - should set flags some other way int masterfd = -1, slavefd = -1; char slavepath[PATH_MAX]; if (::openpty(&masterfd, &slavefd, slavepath, &tios, nullptr) < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); #endif ::close(slavefd); @@ -164,16 +165,16 @@ osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, st int const oldflags = ::fcntl(masterfd, F_GETFL, 0); if (oldflags < 0) { - int const err = errno; + std::error_condition err(errno, std::generic_category()); ::close(masterfd); - return errno_to_file_error(err); + return err; } if (::fcntl(masterfd, F_SETFL, oldflags | O_NONBLOCK) < 0) { - int const err = errno; + std::error_condition err(errno, std::generic_category()); ::close(masterfd); - return errno_to_file_error(err); + return err; } try @@ -181,12 +182,12 @@ osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, st name = slavepath; file = std::make_unique<posix_osd_ptty>(masterfd); filesize = 0; - return osd_file::error::NONE; + return std::error_condition(); } catch (...) { ::close(masterfd); - return osd_file::error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } #endif // defined(__ANDROID__) } diff --git a/src/osd/modules/file/posixsocket.cpp b/src/osd/modules/file/posixsocket.cpp index 2ce5ad05d5c..4770e91c6a9 100644 --- a/src/osd/modules/file/posixsocket.cpp +++ b/src/osd/modules/file/posixsocket.cpp @@ -2,7 +2,8 @@ // copyright-holders:Olivier Galibert, R. Belmont, Vas Crabb //============================================================ // -// sdlsocket.c - SDL socket (inet) access functions +// sdlsocket.c - SDL socket (inet, unix domain) access +// functions // // SDLMAME by Olivier Galibert and R. Belmont // @@ -16,17 +17,21 @@ #include <cstring> #include <arpa/inet.h> +#include <fcntl.h> #include <netdb.h> #include <netinet/in.h> #include <netinet/tcp.h> #include <sys/select.h> #include <sys/socket.h> #include <sys/time.h> +#include <sys/un.h> #include <unistd.h> namespace { + char const *const posixfile_socket_identifier = "socket."; +char const *const posixfile_domain_identifier = "domain."; class posix_osd_socket : public osd_file @@ -37,7 +42,7 @@ public: posix_osd_socket& operator=(posix_osd_socket const &) = delete; posix_osd_socket& operator=(posix_osd_socket &&) = delete; - posix_osd_socket(int sock, bool listening) + posix_osd_socket(int sock, bool listening) noexcept : m_sock(sock) , m_listening(listening) { @@ -49,7 +54,7 @@ public: ::close(m_sock); } - virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { fd_set readfds; FD_ZERO(&readfds); @@ -58,12 +63,9 @@ public: struct timeval timeout; timeout.tv_sec = timeout.tv_usec = 0; - if (select(m_sock + 1, &readfds, nullptr, nullptr, &timeout) < 0) + if (::select(m_sock + 1, &readfds, nullptr, nullptr, &timeout) < 0) { - char line[80]; - std::sprintf(line, "%s : %s : %d ", __func__, __FILE__, __LINE__); - std::perror(line); - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); } else if (FD_ISSET(m_sock, &readfds)) { @@ -73,12 +75,12 @@ public: ssize_t const result = ::read(m_sock, buffer, count); if (result < 0) { - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); } else { actual = std::uint32_t(size_t(result)); - return error::NONE; + return std::error_condition(); } } else @@ -87,7 +89,7 @@ public: int const accepted = ::accept(m_sock, nullptr, nullptr); if (accepted < 0) { - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); } else { @@ -96,36 +98,38 @@ public: m_listening = false; actual = 0; - return error::NONE; + return std::error_condition(); } } } else { - return error::FAILURE; + // no data available + actual = 0; + return std::error_condition(); } } - virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { ssize_t const result = ::write(m_sock, buffer, count); if (result < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); actual = std::uint32_t(size_t(result)); - return error::NONE; + return std::error_condition(); } - virtual error truncate(std::uint64_t offset) override + virtual std::error_condition truncate(std::uint64_t offset) noexcept override { // doesn't make sense on socket - return error::INVALID_ACCESS; + return std::errc::bad_file_descriptor; } - virtual error flush() override + virtual std::error_condition flush() noexcept override { // there's no simple way to flush buffers on a socket anyway - return error::NONE; + return std::error_condition(); } private: @@ -133,6 +137,54 @@ private: bool m_listening; }; + +template <typename T> +std::error_condition create_socket(T const &sa, int sock, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept +{ + osd_file::ptr result; + if (openflags & OPEN_FLAG_CREATE) + { + // listening socket support + // bind socket... + if (::bind(sock, reinterpret_cast<struct sockaddr const *>(&sa), sizeof(sa)) < 0) + { + std::error_condition binderr(errno, std::generic_category()); + ::close(sock); + return binderr; + } + + // start to listen... + if (::listen(sock, 1) < 0) + { + std::error_condition lstnerr(errno, std::generic_category()); + ::close(sock); + return lstnerr; + } + + // mark socket as "listening" + result.reset(new (std::nothrow) posix_osd_socket(sock, true)); + } + else + { + if (::connect(sock, reinterpret_cast<struct sockaddr const *>(&sa), sizeof(sa)) < 0) + { + std::error_condition connerr(errno, std::generic_category()); + ::close(sock); + return connerr; + } + result.reset(new (std::nothrow) posix_osd_socket(sock, false)); + } + + if (!result) + { + ::close(sock); + return std::errc::not_enough_memory; + } + file = std::move(result); + filesize = 0; + return std::error_condition(); +} + } // anonymous namespace @@ -141,7 +193,7 @@ private: specification has the format "socket." host ":" port. Host may be simple or fully qualified. Port must be between 1 and 65535. */ -bool posix_check_socket_path(std::string const &path) +bool posix_check_socket_path(std::string const &path) noexcept { if (strncmp(path.c_str(), posixfile_socket_identifier, strlen(posixfile_socket_identifier)) == 0 && strchr(path.c_str(), ':') != nullptr) return true; @@ -149,7 +201,15 @@ bool posix_check_socket_path(std::string const &path) } -osd_file::error posix_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) +bool posix_check_domain_path(std::string const &path) noexcept +{ + if (strncmp(path.c_str(), posixfile_domain_identifier, strlen(posixfile_domain_identifier)) == 0) + return true; + return false; +} + + +std::error_condition posix_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept { char hostname[256]; int port; @@ -157,7 +217,7 @@ osd_file::error posix_open_socket(std::string const &path, std::uint32_t openfla struct hostent const *const localhost = ::gethostbyname(hostname); if (!localhost) - return osd_file::error::NOT_FOUND; + return std::errc::no_such_file_or_directory; struct sockaddr_in sai; memset(&sai, 0, sizeof(sai)); @@ -167,75 +227,38 @@ osd_file::error posix_open_socket(std::string const &path, std::uint32_t openfla int const sock = ::socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); int const flag = 1; - if (::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char *>(&flag), sizeof(flag)) < 0) + if ((::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char *>(&flag), sizeof(flag)) < 0) || + (::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char *>(&flag), sizeof(flag)) < 0)) { - int const err = errno; + std::error_condition sockopterr(errno, std::generic_category()); ::close(sock); - return errno_to_file_error(err); + return sockopterr; } - if (::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char *>(&flag), sizeof(flag)) < 0) - { - int const err = errno; - ::close(sock); - return errno_to_file_error(err); - } + return create_socket(sai, sock, openflags, file, filesize); +} - // listening socket support - if (openflags & OPEN_FLAG_CREATE) - { - //printf("Listening for client at '%s' on port '%d'\n", hostname, port); - // bind socket... - if (::bind(sock, reinterpret_cast<struct sockaddr const *>(&sai), sizeof(struct sockaddr)) < 0) - { - int const err = errno; - ::close(sock); - return errno_to_file_error(err); - } +std::error_condition posix_open_domain(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept +{ + struct sockaddr_un sau; + memset(&sau, 0, sizeof(sau)); + sau.sun_family = AF_UNIX; + strncpy(sau.sun_path, &path.c_str()[strlen(posixfile_domain_identifier)], sizeof(sau.sun_path)-1); - // start to listen... - if (::listen(sock, 1) < 0) - { - int const err = errno; - ::close(sock); - return errno_to_file_error(err); - } + int const sock = ::socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) + return std::error_condition(errno, std::generic_category()); - // mark socket as "listening" - try - { - file = std::make_unique<posix_osd_socket>(sock, true); - filesize = 0; - return osd_file::error::NONE; - } - catch (...) - { - ::close(sock); - return osd_file::error::OUT_OF_MEMORY; - } - } - else + if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { - //printf("Connecting to server '%s' on port '%d'\n", hostname, port); - if (::connect(sock, reinterpret_cast<struct sockaddr const *>(&sai), sizeof(struct sockaddr)) < 0) - { - ::close(sock); - return osd_file::error::ACCESS_DENIED; // have to return this value or bitb won't try to bind on connect failure - } - try - { - file = std::make_unique<posix_osd_socket>(sock, false); - filesize = 0; - return osd_file::error::NONE; - } - catch (...) - { - ::close(sock); - return osd_file::error::OUT_OF_MEMORY; - } + std::error_condition cntlerr(errno, std::generic_category()); + ::close(sock); + return cntlerr; } + + return create_socket(sau, sock, openflags, file, filesize); } 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; diff --git a/src/osd/modules/file/winfile.cpp b/src/osd/modules/file/winfile.cpp index 4c265be613d..be4fa6f70c3 100644 --- a/src/osd/modules/file/winfile.cpp +++ b/src/osd/modules/file/winfile.cpp @@ -6,7 +6,6 @@ // //============================================================ - #include "winfile.h" // MAMEOS headers @@ -45,7 +44,7 @@ public: win_osd_file& operator=(win_osd_file const &) = delete; win_osd_file& operator=(win_osd_file &&) = delete; - win_osd_file(HANDLE handle) : m_handle(handle) + win_osd_file(HANDLE handle) noexcept : m_handle(handle) { assert(m_handle); assert(INVALID_HANDLE_VALUE != m_handle); @@ -57,7 +56,7 @@ public: CloseHandle(m_handle); } - 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 { // attempt to set the file pointer LARGE_INTEGER largeOffset; @@ -71,10 +70,10 @@ public: return win_error_to_file_error(GetLastError()); actual = result; - return error::NONE; + return std::error_condition(); } - virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override + virtual std::error_condition write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) noexcept override { // attempt to set the file pointer LARGE_INTEGER largeOffset; @@ -88,10 +87,10 @@ public: return win_error_to_file_error(GetLastError()); actual = result; - return error::NONE; + return std::error_condition(); } - virtual error truncate(std::uint64_t offset) override + virtual std::error_condition truncate(std::uint64_t offset) noexcept override { // attempt to set the file pointer LARGE_INTEGER largeOffset; @@ -103,13 +102,13 @@ public: if (!SetEndOfFile(m_handle)) return win_error_to_file_error(GetLastError()); else - return error::NONE; + return std::error_condition(); } - virtual error flush() override + virtual std::error_condition flush() noexcept override { // shouldn't be any userspace buffers on the file handle - return error::NONE; + return std::error_condition(); } private: @@ -162,11 +161,11 @@ DWORD create_path_recursive(TCHAR *path) // osd_open //============================================================ -osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, ptr &file, std::uint64_t &filesize) +std::error_condition osd_file::open(std::string const &orig_path, uint32_t openflags, ptr &file, std::uint64_t &filesize) noexcept { std::string path; try { osd_subst_env(path, orig_path); } - catch (...) { return error::OUT_OF_MEMORY; } + catch (...) { return std::errc::not_enough_memory; } if (win_check_socket_path(path)) return win_open_socket(path, openflags, file, filesize); @@ -174,10 +173,11 @@ osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, return win_open_ptty(path, openflags, file, filesize); // convert path to TCHAR - osd::text::tstring t_path = osd::text::to_tstring(path); + osd::text::tstring t_path; + try { t_path = osd::text::to_tstring(path); } + catch (...) { return std::errc::not_enough_memory; } - // convert the path into something Windows compatible (the actual interesting part appears - // to have been commented out???) + // convert the path into something Windows compatible (the actual interesting part appears to have been commented out???) for (auto iter = t_path.begin(); iter != t_path.end(); iter++) *iter = /* ('/' == *iter) ? '\\' : */ *iter; @@ -187,7 +187,8 @@ osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, { disposition = (!is_path_to_physical_drive(path.c_str()) && (openflags & OPEN_FLAG_CREATE)) ? CREATE_ALWAYS : OPEN_EXISTING; access = (openflags & OPEN_FLAG_READ) ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_WRITE; - if (is_path_to_physical_drive(path.c_str())) access |= GENERIC_READ; + if (is_path_to_physical_drive(path.c_str())) + access |= GENERIC_READ; sharemode = FILE_SHARE_READ; } else if (openflags & OPEN_FLAG_READ) @@ -198,7 +199,7 @@ osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, } else { - return error::INVALID_ACCESS; + return std::errc::invalid_argument; } // attempt to open the file @@ -262,17 +263,15 @@ osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, } } - try - { - file = std::make_unique<win_osd_file>(h); - filesize = (std::uint64_t(upper) << 32) | lower; - return error::NONE; - } - catch (...) + osd_file::ptr result(new (std::nothrow) win_osd_file(h)); + if (!result) { CloseHandle(h); - return error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } + file = std::move(result); + filesize = (std::uint64_t(upper) << 32) | lower; + return std::error_condition(); } @@ -281,9 +280,9 @@ osd_file::error osd_file::open(std::string const &orig_path, 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; // TODO: revisit this error code } @@ -292,11 +291,13 @@ 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 { - osd::text::tstring tempstr = osd::text::to_tstring(filename); + osd::text::tstring tempstr; + try { tempstr = osd::text::to_tstring(filename); } + catch (...) { return std::errc::not_enough_memory; } - error filerr = error::NONE; + std::error_condition filerr; if (!DeleteFile(tempstr.c_str())) filerr = win_error_to_file_error(GetLastError()); @@ -309,7 +310,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 { DISK_GEOMETRY dg; DWORD bytesRead; @@ -321,10 +322,17 @@ bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, return false; // do a create file on the drive - auto t_filename = osd::text::to_tstring(filename); - file = CreateFile(t_filename.c_str(), GENERIC_READ, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, nullptr); - if (file == INVALID_HANDLE_VALUE) + try + { + auto t_filename = osd::text::to_tstring(filename); + file = CreateFile(t_filename.c_str(), GENERIC_READ, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, nullptr); + if (file == INVALID_HANDLE_VALUE) + return false; + } + catch (...) + { return false; + } // device I/O control should return the geometry result = DeviceIoControl(file, IOCTL_DISK_GET_DRIVE_GEOMETRY, nullptr, 0, &dg, sizeof(dg), &bytesRead, nullptr); @@ -399,22 +407,29 @@ std::unique_ptr<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 { - // get the length of the full path - std::wstring const w_path(osd::text::to_wstring(path)); - DWORD const length(GetFullPathNameW(w_path.c_str(), 0, nullptr, nullptr)); - if (!length) - return win_error_to_file_error(GetLastError()); + try + { + // get the length of the full path + std::wstring const w_path(osd::text::to_wstring(path)); + DWORD const length(GetFullPathNameW(w_path.c_str(), 0, nullptr, nullptr)); + if (!length) + return win_error_to_file_error(GetLastError()); - // allocate a buffer and get the canonical path - std::unique_ptr<wchar_t []> buffer(std::make_unique<wchar_t []>(length)); - if (!GetFullPathNameW(w_path.c_str(), length, buffer.get(), nullptr)) - return win_error_to_file_error(GetLastError()); + // allocate a buffer and get the canonical path + std::unique_ptr<wchar_t []> buffer(std::make_unique<wchar_t []>(length)); + if (!GetFullPathNameW(w_path.c_str(), length, buffer.get(), nullptr)) + return win_error_to_file_error(GetLastError()); - // convert the result back to UTF-8 - osd::text::from_wstring(dst, buffer.get()); - return osd_file::error::NONE; + // convert the result back to UTF-8 + osd::text::from_wstring(dst, buffer.get()); + return std::error_condition(); + } + catch (...) + { + return std::errc::not_enough_memory; // the string conversions can throw bad_alloc + } } @@ -423,7 +438,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 { return !PathIsRelativeW(osd::text::to_wstring(path).c_str()); } @@ -493,7 +508,7 @@ std::vector<std::string> osd_get_volume_names() // osd_is_valid_filename_char //============================================================ -bool osd_is_valid_filename_char(char32_t uchar) +bool osd_is_valid_filename_char(char32_t uchar) noexcept { return osd_is_valid_filepath_char(uchar) && uchar != '/' @@ -507,7 +522,7 @@ bool osd_is_valid_filename_char(char32_t uchar) // osd_is_valid_filepath_char //============================================================ -bool osd_is_valid_filepath_char(char32_t uchar) +bool osd_is_valid_filepath_char(char32_t uchar) noexcept { return uchar >= 0x20 && uchar != '<' @@ -526,39 +541,62 @@ bool osd_is_valid_filepath_char(char32_t uchar) // win_error_to_file_error //============================================================ -osd_file::error win_error_to_file_error(DWORD error) +std::error_condition win_error_to_file_error(DWORD error) noexcept { - osd_file::error filerr; - - // convert a Windows error to a osd_file::error + // TODO: work out if there's a better way to do this switch (error) { case ERROR_SUCCESS: - filerr = osd_file::error::NONE; - break; + return std::error_condition(); + + case ERROR_INVALID_HANDLE: + return std::errc::bad_file_descriptor; case ERROR_OUTOFMEMORY: - filerr = osd_file::error::OUT_OF_MEMORY; - break; + return std::errc::not_enough_memory; + + case ERROR_NOT_SUPPORTED: + return std::errc::not_supported; case ERROR_FILE_NOT_FOUND: - case ERROR_FILENAME_EXCED_RANGE: case ERROR_PATH_NOT_FOUND: case ERROR_INVALID_NAME: - filerr = osd_file::error::NOT_FOUND; - break; + return std::errc::no_such_file_or_directory; - case ERROR_ACCESS_DENIED: - filerr = osd_file::error::ACCESS_DENIED; - break; + case ERROR_FILENAME_EXCED_RANGE: + return std::errc::filename_too_long; + case ERROR_ACCESS_DENIED: case ERROR_SHARING_VIOLATION: - filerr = osd_file::error::ALREADY_OPEN; - break; + return std::errc::permission_denied; + + case ERROR_ALREADY_EXISTS: + return std::errc::file_exists; + + case ERROR_TOO_MANY_OPEN_FILES: + return std::errc::too_many_files_open; + + case ERROR_WRITE_FAULT: + case ERROR_READ_FAULT: + return std::errc::io_error; + + case ERROR_HANDLE_DISK_FULL: + case ERROR_DISK_FULL: + return std::errc::no_space_on_device; + + case ERROR_PATH_BUSY: + case ERROR_BUSY: + return std::errc::device_or_resource_busy; + + case ERROR_FILE_TOO_LARGE: + return std::errc::file_too_large; + + case ERROR_INVALID_ACCESS: + case ERROR_NEGATIVE_SEEK: + case ERROR_BAD_ARGUMENTS: + return std::errc::invalid_argument; default: - filerr = osd_file::error::FAILURE; - break; + return std::error_condition(error, std::system_category()); } - return filerr; } diff --git a/src/osd/modules/file/winfile.h b/src/osd/modules/file/winfile.h index 927cb299545..83f0814733d 100644 --- a/src/osd/modules/file/winfile.h +++ b/src/osd/modules/file/winfile.h @@ -5,13 +5,16 @@ // winfile.h - File access functions // //============================================================ -#ifndef MAME_OSD_WINDOWS_WINFILE_H -#define MAME_OSD_WINDOWS_WINFILE_H +#ifndef MAME_OSD_MODULES_FILE_WINFILE_H +#define MAME_OSD_MODULES_FILE_WINFILE_H + +#pragma once #include "osdfile.h" #include <cstdint> #include <string> +#include <system_error> #include <winsock2.h> @@ -20,15 +23,15 @@ // PROTOTYPES //============================================================ -bool win_init_sockets(); -void win_cleanup_sockets(); +bool win_init_sockets() noexcept; +void win_cleanup_sockets() noexcept; -bool win_check_socket_path(std::string const &path); -osd_file::error win_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize); +bool win_check_socket_path(std::string const &path) noexcept; +std::error_condition win_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept; -bool win_check_ptty_path(std::string const &path); -osd_file::error win_open_ptty(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize); +bool win_check_ptty_path(std::string const &path) noexcept; +std::error_condition win_open_ptty(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept; -osd_file::error win_error_to_file_error(DWORD error); +std::error_condition win_error_to_file_error(DWORD error) noexcept; -#endif // MAME_OSD_WINDOWS_WINFILE_H +#endif // MAME_OSD_MODULES_FILE_WINFILE_H diff --git a/src/osd/modules/file/winptty.cpp b/src/osd/modules/file/winptty.cpp index 65650fd4bfe..7feeacce137 100644 --- a/src/osd/modules/file/winptty.cpp +++ b/src/osd/modules/file/winptty.cpp @@ -15,6 +15,7 @@ namespace { + char const *const winfile_ptty_identifier = "\\\\.\\pipe\\"; @@ -26,7 +27,7 @@ public: win_osd_ptty& operator=(win_osd_ptty const &) = delete; win_osd_ptty& operator=(win_osd_ptty &&) = delete; - win_osd_ptty(HANDLE handle) : m_handle(handle) + win_osd_ptty(HANDLE handle) noexcept : m_handle(handle) { assert(m_handle); assert(INVALID_HANDLE_VALUE != m_handle); @@ -39,36 +40,36 @@ public: CloseHandle(m_handle); } - virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { DWORD bytes_read; if (!ReadFile(m_handle, buffer, count, &bytes_read, nullptr)) return win_error_to_file_error(GetLastError()); actual = bytes_read; - return error::NONE; + return std::error_condition(); } - virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { DWORD bytes_written; if (!WriteFile(m_handle, buffer, count, &bytes_written, nullptr)) return win_error_to_file_error(GetLastError()); actual = bytes_written; - return error::NONE; + return std::error_condition(); } - virtual error truncate(std::uint64_t offset) override + virtual std::error_condition truncate(std::uint64_t offset) noexcept override { // doesn't make sense for a PTTY - return error::INVALID_ACCESS; + return std::errc::bad_file_descriptor; } - virtual error flush() override + virtual std::error_condition flush() noexcept override { // don't want to wait for client to read all data as implied by FlushFileBuffers - return error::NONE; + return std::error_condition(); } private: @@ -78,16 +79,18 @@ private: } // anonymous namespace -bool win_check_ptty_path(std::string const &path) +bool win_check_ptty_path(std::string const &path) noexcept { if (strncmp(path.c_str(), winfile_ptty_identifier, strlen(winfile_ptty_identifier)) == 0) return true; return false; } -osd_file::error win_open_ptty(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) +std::error_condition win_open_ptty(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept { - osd::text::tstring t_name = osd::text::to_tstring(path); + osd::text::tstring t_name; + try { t_name = osd::text::to_tstring(path); } + catch (...) { return std::errc::not_enough_memory; } HANDLE pipe = CreateFileW(t_name.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); @@ -96,23 +99,22 @@ osd_file::error win_open_ptty(std::string const &path, std::uint32_t openflags, if (openflags & OPEN_FLAG_CREATE) pipe = CreateNamedPipe(t_name.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT, 1, 32, 32, 0, nullptr); if (INVALID_HANDLE_VALUE == pipe) - return osd_file::error::ACCESS_DENIED; + return win_error_to_file_error(GetLastError()); } else { DWORD state = PIPE_NOWAIT; SetNamedPipeHandleState(pipe, &state, nullptr, nullptr); + // TODO: check for error? } - try - { - file = std::make_unique<win_osd_ptty>(pipe); - filesize = 0; - return osd_file::error::NONE; - } - catch (...) + osd_file::ptr result(new (std::nothrow) win_osd_ptty(pipe)); + if (!result) { CloseHandle(pipe); - return osd_file::error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } + file = std::move(result); + filesize = 0; + return std::error_condition(); } diff --git a/src/osd/modules/file/winsocket.cpp b/src/osd/modules/file/winsocket.cpp index 948e57db822..f818f3b1991 100644 --- a/src/osd/modules/file/winsocket.cpp +++ b/src/osd/modules/file/winsocket.cpp @@ -6,7 +6,6 @@ // //============================================================ - #include "winfile.h" // MAMEOS headers @@ -28,6 +27,7 @@ namespace { + char const *const winfile_socket_identifier = "socket."; @@ -39,7 +39,7 @@ public: win_osd_socket& operator=(win_osd_socket const &) = delete; win_osd_socket& operator=(win_osd_socket &&) = delete; - win_osd_socket(SOCKET s, bool l) + win_osd_socket(SOCKET s, bool l) noexcept : m_socket(s) , m_listening(l) { @@ -51,7 +51,7 @@ public: closesocket(m_socket); } - 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 { fd_set readfds; FD_ZERO(&readfds); @@ -62,10 +62,7 @@ public: if (select(m_socket + 1, &readfds, nullptr, nullptr, &timeout) < 0) { - char line[80]; - std::sprintf(line, "win_read_socket : %s : %d ", __FILE__, __LINE__); - std::perror(line); - return error::FAILURE; + return wsa_error_to_file_error(WSAGetLastError()); } else if (FD_ISSET(m_socket, &readfds)) { @@ -80,7 +77,7 @@ public: else { actual = result; - return error::NONE; + return std::error_condition(); } } else @@ -98,50 +95,82 @@ public: m_listening = false; actual = 0; - return error::NONE; + return std::error_condition(); } } } else { - return error::FAILURE; + // no data available + actual = 0; + return std::error_condition(); } } - virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override + virtual std::error_condition write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) noexcept override { auto const result = send(m_socket, reinterpret_cast<const char *>(buffer), length, 0); if (result < 0) return wsa_error_to_file_error(WSAGetLastError()); actual = result; - return error::NONE; + return std::error_condition(); } - virtual error truncate(std::uint64_t offset) override + virtual std::error_condition truncate(std::uint64_t offset) noexcept override { // doesn't make sense for a socket - return error::INVALID_ACCESS; + return std::errc::bad_file_descriptor; } - virtual error flush() override + virtual std::error_condition flush() noexcept override { // no buffers to flush - return error::NONE; + return std::error_condition(); } - static error wsa_error_to_file_error(int err) + static std::error_condition wsa_error_to_file_error(int err) { + // TODO: determine if there's a better way to do this switch (err) { - case 0: return error::NONE; - case WSAEACCES: return error::ACCESS_DENIED; - case WSAEADDRINUSE: return error::ALREADY_OPEN; - case WSAEADDRNOTAVAIL: return error::NOT_FOUND; - case WSAECONNREFUSED: return error::NOT_FOUND; - case WSAEHOSTUNREACH: return error::NOT_FOUND; - case WSAENETUNREACH: return error::NOT_FOUND; - default: return error::FAILURE; + case 0: return std::error_condition(); + case WSA_NOT_ENOUGH_MEMORY: return std::errc::not_enough_memory; + case WSA_INVALID_PARAMETER: return std::errc::invalid_argument; + case WSAEINTR: return std::errc::interrupted; + case WSAEBADF: return std::errc::bad_file_descriptor; + case WSAEACCES: return std::errc::permission_denied; + case WSAEFAULT: return std::errc::bad_address; + case WSAEINVAL: return std::errc::invalid_argument; + case WSAEMFILE: return std::errc::too_many_files_open; + case WSAENETRESET: return std::errc::network_reset; + case WSAECONNABORTED: return std::errc::connection_aborted; + case WSAEWOULDBLOCK: return std::errc::operation_would_block; + case WSAEINPROGRESS: return std::errc::operation_in_progress; + case WSAEALREADY: return std::errc::connection_already_in_progress; + case WSAENOTSOCK: return std::errc::not_a_socket; + case WSAEDESTADDRREQ: return std::errc::destination_address_required; + case WSAEMSGSIZE: return std::errc::message_size; + case WSAEPROTOTYPE: return std::errc::wrong_protocol_type; + case WSAENOPROTOOPT: return std::errc::no_protocol_option; + case WSAEPROTONOSUPPORT: return std::errc::protocol_not_supported; + case WSAEOPNOTSUPP: return std::errc::operation_not_supported; + case WSAEAFNOSUPPORT: return std::errc::address_family_not_supported; + case WSAEADDRINUSE: return std::errc::address_in_use; + case WSAEADDRNOTAVAIL: return std::errc::address_not_available; + case WSAENETDOWN: return std::errc::network_down; + case WSAENETUNREACH: return std::errc::network_unreachable; + case WSAECONNRESET: return std::errc::connection_reset; + case WSAENOBUFS: return std::errc::no_buffer_space; + case WSAEISCONN: return std::errc::already_connected; + case WSAENOTCONN: return std::errc::not_connected; + case WSAETIMEDOUT: return std::errc::timed_out; + case WSAECONNREFUSED: return std::errc::connection_refused; + case WSAEHOSTUNREACH: return std::errc::host_unreachable; + case WSAECANCELLED: return std::errc::operation_canceled; + + // TODO: better default error code? + default: return std::errc::io_error; } } @@ -153,7 +182,7 @@ private: } // anonymous namespace -bool win_init_sockets() +bool win_init_sockets() noexcept { WSADATA wsaData; WORD const version = MAKEWORD(2, 0); @@ -179,13 +208,13 @@ bool win_init_sockets() } -void win_cleanup_sockets() +void win_cleanup_sockets() noexcept { WSACleanup(); } -bool win_check_socket_path(std::string const &path) +bool win_check_socket_path(std::string const &path) noexcept { if (strncmp(path.c_str(), winfile_socket_identifier, strlen(winfile_socket_identifier)) == 0 && strchr(path.c_str(), ':') != nullptr) return true; @@ -193,7 +222,7 @@ bool win_check_socket_path(std::string const &path) } -osd_file::error win_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) +std::error_condition win_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept { char hostname[256]; int port; @@ -201,7 +230,7 @@ osd_file::error win_open_socket(std::string const &path, std::uint32_t openflags struct hostent const *const localhost = gethostbyname(hostname); if (!localhost) - return osd_file::error::NOT_FOUND; + return std::errc::no_such_file_or_directory; struct sockaddr_in sai; memset(&sai, 0, sizeof(sai)); @@ -222,11 +251,12 @@ osd_file::error win_open_socket(std::string const &path, std::uint32_t openflags } // listening socket support + osd_file::ptr result; if (openflags & OPEN_FLAG_CREATE) { //printf("Listening for client at '%s' on port '%d'\n", hostname, port); // bind socket... - if (bind(sock, reinterpret_cast<struct sockaddr const *>(&sai), sizeof(struct sockaddr)) == SOCKET_ERROR) + if (bind(sock, reinterpret_cast<struct sockaddr const *>(&sai), sizeof(sai)) == SOCKET_ERROR) { int const err = WSAGetLastError(); closesocket(sock); @@ -242,36 +272,26 @@ osd_file::error win_open_socket(std::string const &path, std::uint32_t openflags } // mark socket as "listening" - try - { - file = std::make_unique<win_osd_socket>(sock, true); - filesize = 0; - return osd_file::error::NONE; - } - catch (...) - { - closesocket(sock); - return osd_file::error::OUT_OF_MEMORY; - } + result.reset(new (std::nothrow) win_osd_socket(sock, true)); } else { //printf("Connecting to server '%s' on port '%d'\n", hostname, port); - if (connect(sock, reinterpret_cast<struct sockaddr const *>(&sai), sizeof(struct sockaddr)) == SOCKET_ERROR) - { - closesocket(sock); - return osd_file::error::ACCESS_DENIED; // have to return this value or bitb won't try to bind on connect failure - } - try - { - file = std::make_unique<win_osd_socket>(sock, false); - filesize = 0; - return osd_file::error::NONE; - } - catch (...) + if (connect(sock, reinterpret_cast<struct sockaddr const *>(&sai), sizeof(sai)) == SOCKET_ERROR) { + int const err = WSAGetLastError(); closesocket(sock); - return osd_file::error::OUT_OF_MEMORY; + return win_osd_socket::wsa_error_to_file_error(err); } + result.reset(new (std::nothrow) win_osd_socket(sock, false)); + } + + if (!result) + { + closesocket(sock); + return std::errc::not_enough_memory; } + file = std::move(result); + filesize = 0; + return std::error_condition(); } diff --git a/src/osd/modules/font/font_sdl.cpp b/src/osd/modules/font/font_sdl.cpp index a17b87cdc13..5cad4a3fab8 100644 --- a/src/osd/modules/font/font_sdl.cpp +++ b/src/osd/modules/font/font_sdl.cpp @@ -90,7 +90,7 @@ bool osd_font_sdl::open(std::string const &font_path, std::string const &_name, osd_printf_verbose("Searching font %s in -%s path/s\n", family, font_path); //emu_file file(options().font_path(), OPEN_FLAG_READ); emu_file file(font_path, OPEN_FLAG_READ); - if (file.open(family) == osd_file::error::NONE) + if (!file.open(family)) { std::string full_name = file.fullpath(); font = TTF_OpenFont_Magic(full_name, POINT_SIZE, 0); @@ -193,7 +193,7 @@ bool osd_font_sdl::get_bitmap(char32_t chnum, bitmap_argb32 &bitmap, std::int32_ osd_font_sdl::TTF_Font_ptr osd_font_sdl::TTF_OpenFont_Magic(std::string const &name, int fsize, long index) { emu_file file(OPEN_FLAG_READ); - if (file.open(name) == osd_file::error::NONE) + if (!file.open(name)) { unsigned char const ttf_magic[] = { 0x00, 0x01, 0x00, 0x00, 0x00 }; unsigned char const ttc1_magic[] = { 0x74, 0x74, 0x63, 0x66, 0x00, 0x01, 0x00, 0x00 }; @@ -214,7 +214,7 @@ osd_font_sdl::TTF_Font_ptr osd_font_sdl::TTF_OpenFont_Magic(std::string const &n bool osd_font_sdl::BDF_Check_Magic(std::string const &name) { emu_file file(OPEN_FLAG_READ); - if (file.open(name) == osd_file::error::NONE) + if (!file.open(name)) { unsigned char const magic[] = { 'S', 'T', 'A', 'R', 'T', 'F', 'O', 'N', 'T' }; unsigned char buffer[sizeof(magic)]; diff --git a/src/osd/modules/render/aviwrite.cpp b/src/osd/modules/render/aviwrite.cpp index aff5429446e..ec6ce21c543 100644 --- a/src/osd/modules/render/aviwrite.cpp +++ b/src/osd/modules/render/aviwrite.cpp @@ -80,12 +80,12 @@ void avi_write::begin_avi_recording(const char *name) // create a new temporary movie file emu_file tempfile(m_machine.options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - const osd_file::error filerr = (!name || !name[0] || !std::strcmp(name, OSDOPTVAL_AUTO)) + const std::error_condition filerr = (!name || !name[0] || !std::strcmp(name, OSDOPTVAL_AUTO)) ? m_machine.video().open_next(tempfile, "avi") : tempfile.open(name); // if we succeeded, make a copy of the name and create the real file over top - if (filerr == osd_file::error::NONE) + if (!filerr) { const std::string fullpath = tempfile.fullpath(); tempfile.close(); diff --git a/src/osd/modules/render/bgfx/texturemanager.cpp b/src/osd/modules/render/bgfx/texturemanager.cpp index 6c760c10203..f03d66e051a 100644 --- a/src/osd/modules/render/bgfx/texturemanager.cpp +++ b/src/osd/modules/render/bgfx/texturemanager.cpp @@ -59,7 +59,7 @@ bgfx_texture* texture_manager::create_png_texture(std::string path, std::string { bitmap_argb32 bitmap; emu_file file(path, OPEN_FLAG_READ); - if (file.open(file_name) == osd_file::error::NONE) + if (!file.open(file_name)) { render_load_png(bitmap, file); file.close(); diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp index 0137e23acce..6aa69383233 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.cpp +++ b/src/osd/modules/render/d3d/d3dhlsl.cpp @@ -353,8 +353,8 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface) } emu_file file(machine->options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - osd_file::error filerr = machine->video().open_next(file, "png"); - if (filerr != osd_file::error::NONE) + std::error_condition const filerr = machine->video().open_next(file, "png"); + if (filerr) return; // add two text entries describing the image @@ -722,7 +722,7 @@ int shaders::create_resources() osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result); emu_file file(machine->options().art_path(), OPEN_FLAG_READ); - if (file.open(options->shadow_mask_texture) == osd_file::error::NONE) + if (!file.open(options->shadow_mask_texture)) { render_load_png(shadow_bitmap, file); file.close(); @@ -747,7 +747,7 @@ int shaders::create_resources() d3d->get_texture_manager()->m_texture_list.push_back(std::move(tex)); } - if (file.open(options->lut_texture) == osd_file::error::NONE) + if (!file.open(options->lut_texture)) { render_load_png(lut_bitmap, file); file.close(); @@ -770,7 +770,7 @@ int shaders::create_resources() d3d->get_texture_manager()->m_texture_list.push_back(std::move(tex)); } - if (file.open(options->ui_lut_texture) == osd_file::error::NONE) + if (!file.open(options->ui_lut_texture)) { render_load_png(ui_lut_bitmap, file); file.close(); |