summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules
diff options
context:
space:
mode:
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
commite8bbea1fc6e94e14768509d322f6c624403ffb36 (patch)
tree74dd1606a900d83de8aecff17a6737af4113308d /src/osd/modules
parente319bde5fc3696d7f48f62b15b6366c4377fe5d1 (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.cpp4
-rw-r--r--src/osd/modules/debugger/debugimgui.cpp8
-rw-r--r--src/osd/modules/file/posixdomain.cpp208
-rw-r--r--src/osd/modules/file/posixfile.cpp166
-rw-r--r--src/osd/modules/file/posixfile.h18
-rw-r--r--src/osd/modules/file/posixptty.cpp57
-rw-r--r--src/osd/modules/file/posixsocket.cpp187
-rw-r--r--src/osd/modules/file/stdfile.cpp104
-rw-r--r--src/osd/modules/file/winfile.cpp176
-rw-r--r--src/osd/modules/file/winfile.h23
-rw-r--r--src/osd/modules/file/winptty.cpp44
-rw-r--r--src/osd/modules/file/winsocket.cpp130
-rw-r--r--src/osd/modules/font/font_sdl.cpp6
-rw-r--r--src/osd/modules/render/aviwrite.cpp4
-rw-r--r--src/osd/modules/render/bgfx/texturemanager.cpp2
-rw-r--r--src/osd/modules/render/d3d/d3dhlsl.cpp10
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();