diff options
author | 2016-06-25 03:00:31 +1000 | |
---|---|---|
committer | 2016-06-25 03:35:23 +1000 | |
commit | 5cee9e9bc4fe03dc561d3a7a87ecadcf89743e2b (patch) | |
tree | 84c962bcfb8f0fdfd73d6b4e317f140034958ce3 | |
parent | 20a95045e16ab69cfb13c6d3cf520e63aa553102 (diff) |
POSIX implementation for new directory read features, cleanup of Windows implementation, return directory handle as smart pointer, fix full build [Vas Crabb]
-rw-r--r-- | scripts/src/osd/sdl.lua | 3 | ||||
-rw-r--r-- | scripts/src/osd/windows.lua | 2 | ||||
-rw-r--r-- | src/devices/bus/nubus/nubus_image.cpp | 7 | ||||
-rw-r--r-- | src/devices/bus/nubus/nubus_image.h | 2 | ||||
-rw-r--r-- | src/emu/diimage.cpp | 6 | ||||
-rw-r--r-- | src/emu/fileio.cpp | 8 | ||||
-rw-r--r-- | src/emu/fileio.h | 6 | ||||
-rw-r--r-- | src/frontend/mame/clifront.cpp | 6 | ||||
-rw-r--r-- | src/frontend/mame/pluginopts.cpp | 7 | ||||
-rw-r--r-- | src/lib/util/zippath.cpp | 8 | ||||
-rw-r--r-- | src/osd/modules/file/posixdir.cpp | 293 | ||||
-rw-r--r-- | src/osd/modules/file/posixfile.cpp | 18 | ||||
-rw-r--r-- | src/osd/modules/file/windir.cpp (renamed from src/osd/windows/windir.cpp) | 142 | ||||
-rw-r--r-- | src/osd/modules/file/winfile.cpp | 8 | ||||
-rw-r--r-- | src/osd/modules/render/bgfx/chainentryreader.cpp | 6 | ||||
-rw-r--r-- | src/osd/modules/render/bgfx/chainmanager.cpp | 4 | ||||
-rw-r--r-- | src/osd/osdcore.h | 8 | ||||
-rw-r--r-- | src/osd/sdl/sdldir.cpp | 316 | ||||
-rw-r--r-- | src/tools/romcmp.cpp | 14 | ||||
-rw-r--r-- | src/tools/src2html.cpp | 16 |
20 files changed, 432 insertions, 448 deletions
diff --git a/scripts/src/osd/sdl.lua b/scripts/src/osd/sdl.lua index 7766b69873d..4094e48c6be 100644 --- a/scripts/src/osd/sdl.lua +++ b/scripts/src/osd/sdl.lua @@ -461,7 +461,6 @@ project ("ocore_" .. _OPTIONS["osd"]) MAME_DIR .. "src/osd/strconv.h", MAME_DIR .. "src/osd/osdsync.cpp", MAME_DIR .. "src/osd/osdsync.h", - MAME_DIR .. "src/osd/sdl/sdldir.cpp", MAME_DIR .. "src/osd/modules/osdmodule.cpp", MAME_DIR .. "src/osd/modules/osdmodule.h", MAME_DIR .. "src/osd/modules/lib/osdlib_" .. SDLOS_TARGETOS .. ".cpp", @@ -470,6 +469,7 @@ project ("ocore_" .. _OPTIONS["osd"]) if BASE_TARGETOS=="unix" then files { + MAME_DIR .. "src/osd/modules/file/posixdir.cpp", MAME_DIR .. "src/osd/modules/file/posixfile.cpp", MAME_DIR .. "src/osd/modules/file/posixfile.h", MAME_DIR .. "src/osd/modules/file/posixptty.cpp", @@ -480,6 +480,7 @@ project ("ocore_" .. _OPTIONS["osd"]) MAME_DIR .. "src/osd/windows", } files { + MAME_DIR .. "src/osd/modules/file/windir.cpp", MAME_DIR .. "src/osd/modules/file/winfile.cpp", MAME_DIR .. "src/osd/modules/file/winfile.h", MAME_DIR .. "src/osd/modules/file/winptty.cpp", diff --git a/scripts/src/osd/windows.lua b/scripts/src/osd/windows.lua index 9307c6dec71..a6e40c7aadc 100644 --- a/scripts/src/osd/windows.lua +++ b/scripts/src/osd/windows.lua @@ -244,13 +244,13 @@ project ("ocore_" .. _OPTIONS["osd"]) MAME_DIR .. "src/osd/osdsync.cpp", MAME_DIR .. "src/osd/osdsync.h", MAME_DIR .. "src/osd/windows/main.cpp", - MAME_DIR .. "src/osd/windows/windir.cpp", MAME_DIR .. "src/osd/windows/winutf8.cpp", MAME_DIR .. "src/osd/windows/winutf8.h", MAME_DIR .. "src/osd/windows/winutil.cpp", MAME_DIR .. "src/osd/windows/winutil.h", MAME_DIR .. "src/osd/modules/osdmodule.cpp", MAME_DIR .. "src/osd/modules/osdmodule.h", + MAME_DIR .. "src/osd/modules/file/windir.cpp", MAME_DIR .. "src/osd/modules/file/winfile.cpp", MAME_DIR .. "src/osd/modules/file/winfile.h", MAME_DIR .. "src/osd/modules/file/winptty.cpp", diff --git a/src/devices/bus/nubus/nubus_image.cpp b/src/devices/bus/nubus/nubus_image.cpp index d7752e3babc..2a13a9c8613 100644 --- a/src/devices/bus/nubus/nubus_image.cpp +++ b/src/devices/bus/nubus/nubus_image.cpp @@ -271,7 +271,7 @@ READ32_MEMBER( nubus_image_device::image_super_r ) WRITE32_MEMBER( nubus_image_device::file_cmd_w ) { - const osd_directory_entry *dp; + const osd::directory::entry *dp; char fullpath[1024]; UINT64 filesize; @@ -290,11 +290,10 @@ WRITE32_MEMBER( nubus_image_device::file_cmd_w ) } break; case kFileCmdGetFirstListing: - if(filectx.dirp) osd_closedir(filectx.dirp); - filectx.dirp = osd_opendir((const char *)filectx.curdir); + filectx.dirp = osd::directory::open((const char *)filectx.curdir); case kFileCmdGetNextListing: if (filectx.dirp) { - dp = osd_readdir(filectx.dirp); + dp = filectx.dirp->read(); if(dp) { strncpy((char*)filectx.filename, dp->name, sizeof(filectx.filename)); } else { diff --git a/src/devices/bus/nubus/nubus_image.h b/src/devices/bus/nubus/nubus_image.h index dda6e55fc02..6badecd4f0d 100644 --- a/src/devices/bus/nubus/nubus_image.h +++ b/src/devices/bus/nubus/nubus_image.h @@ -18,7 +18,7 @@ struct nbfilectx { UINT32 curcmd; UINT8 filename[128]; UINT8 curdir[1024]; - osd_directory *dirp; + osd::directory::ptr dirp; osd_file::ptr fd; UINT64 filelen; UINT32 bytecount; diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp index 9c6ed4f2013..b6c32826a5a 100644 --- a/src/emu/diimage.cpp +++ b/src/emu/diimage.cpp @@ -300,9 +300,9 @@ bool device_image_interface::try_change_working_directory(const char *subdir) bool done = false; auto directory = osd::directory::open(m_working_directory.c_str()); - if (directory != nullptr) + if (directory) { - while(!done && (entry = directory->read()) != nullptr) + while (!done && (entry = directory->read()) != nullptr) { if (!core_stricmp(subdir, entry->name)) { @@ -311,7 +311,7 @@ bool device_image_interface::try_change_working_directory(const char *subdir) } } - delete directory; + directory.reset(); } /* did we successfully identify the directory? */ diff --git a/src/emu/fileio.cpp b/src/emu/fileio.cpp index 55231dc845c..1fe26071acb 100644 --- a/src/emu/fileio.cpp +++ b/src/emu/fileio.cpp @@ -89,9 +89,6 @@ file_enumerator::file_enumerator(const char *searchpath) file_enumerator::~file_enumerator() { - // close anything open - if (m_curdir != nullptr) - delete m_curdir; } @@ -106,7 +103,7 @@ const osd::directory::entry *file_enumerator::next() while (1) { // if no open directory, get the next path - while (m_curdir == nullptr) + while (!m_curdir) { // if we fail to get anything more, we're done if (!m_iterator.next(m_pathbuffer)) @@ -122,8 +119,7 @@ const osd::directory::entry *file_enumerator::next() return result; // we're done; close this directory - delete m_curdir; - m_curdir = nullptr; + m_curdir.reset(); } } diff --git a/src/emu/fileio.h b/src/emu/fileio.h index d71b350559c..411e211d17b 100644 --- a/src/emu/fileio.h +++ b/src/emu/fileio.h @@ -67,9 +67,9 @@ public: private: // internal state - path_iterator m_iterator; - osd::directory *m_curdir; - std::string m_pathbuffer; + path_iterator m_iterator; + osd::directory::ptr m_curdir; + std::string m_pathbuffer; //int m_buflen; }; diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp index 6f0f319dc44..3679441957a 100644 --- a/src/frontend/mame/clifront.cpp +++ b/src/frontend/mame/clifront.cpp @@ -1810,8 +1810,8 @@ media_identifier::media_identifier(emu_options &options) void media_identifier::identify(const char *filename) { // first try to open as a directory - osd::directory *directory = osd::directory::open(filename); - if (directory != nullptr) + osd::directory::ptr directory = osd::directory::open(filename); + if (directory) { // iterate over all files in the directory for (const osd::directory::entry *entry = directory->read(); entry != nullptr; entry = directory->read()) @@ -1822,7 +1822,7 @@ void media_identifier::identify(const char *filename) } // close the directory and be done - delete directory; + directory.reset(); } // if that failed, and the filename ends with .zip, identify as a ZIP file diff --git a/src/frontend/mame/pluginopts.cpp b/src/frontend/mame/pluginopts.cpp index ad24cbbeef0..0dd9ca7bcf9 100644 --- a/src/frontend/mame/pluginopts.cpp +++ b/src/frontend/mame/pluginopts.cpp @@ -39,8 +39,8 @@ plugin_options::plugin_options() void plugin_options::parse_json(std::string path) { // first try to open as a directory - osd::directory *directory = osd::directory::open(path.c_str()); - if (directory != nullptr) + osd::directory::ptr directory = osd::directory::open(path); + if (directory) { // iterate over all files in the directory for (const osd::directory::entry *entry = directory->read(); entry != nullptr; entry = directory->read()) @@ -89,8 +89,5 @@ void plugin_options::parse_json(std::string path) } } } - - // close the directory and be done - delete directory; } } diff --git a/src/lib/util/zippath.cpp b/src/lib/util/zippath.cpp index 48a919a8cad..3322c1152cc 100644 --- a/src/lib/util/zippath.cpp +++ b/src/lib/util/zippath.cpp @@ -37,9 +37,9 @@ class zippath_directory public: zippath_directory() : returned_parent(false) - , directory(nullptr) + , directory() , called_zip_first(false) - , zipfile(nullptr) + , zipfile() , returned_dirlist() { } @@ -52,7 +52,7 @@ public: /* specific to normal directories */ /** @brief Pathname of the directory. */ - osd::directory *directory; + osd::directory::ptr directory; /* specific to ZIP directories */ /** @brief true to called zip first. */ @@ -840,7 +840,7 @@ done: void zippath_closedir(zippath_directory *directory) { if (directory->directory != nullptr) - delete directory->directory; + directory->directory.reset(); if (directory->zipfile != nullptr) directory->zipfile.reset(); diff --git a/src/osd/modules/file/posixdir.cpp b/src/osd/modules/file/posixdir.cpp new file mode 100644 index 00000000000..d08d6869c6c --- /dev/null +++ b/src/osd/modules/file/posixdir.cpp @@ -0,0 +1,293 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert, R. Belmont, Vas Crabb +//============================================================ +// +// sdldir.c - SDL core directory access functions +// +// SDLMAME by Olivier Galibert and R. Belmont +// +//============================================================ + + +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#ifdef __linux__ +#ifndef __USE_LARGEFILE64 +#define __USE_LARGEFILE64 +#endif +#ifndef __USE_BSD +#define __USE_BSD +#endif +#endif + +#ifdef WIN32 +#define _FILE_OFFSET_BITS 64 +#endif + +#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__bsdi__) && !defined(__DragonFly__) +#ifdef _XOPEN_SOURCE +#if _XOPEN_SOURCE < 500 +#undef _XOPEN_SOURCE +#endif +#endif +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 500 +#endif +#endif + +#undef _POSIX_C_SOURCE // to get DT_xxx on OS X + + +#include "osdcore.h" +#include "modules/lib/osdlib.h" +#include "util/strformat.h" + +#include <cctype> +#include <cstdlib> +#include <cstring> +#include <memory> +#include <string> +#include <utility> + +#include <dirent.h> +#include <sys/stat.h> +#include <sys/types.h> + + + +namespace osd { +namespace { +//============================================================ +// CONSTANTS +//============================================================ + +#if defined(WIN32) +constexpr char PATHSEPCH = '\\'; +constexpr char INVPATHSEPCH = '/'; +#else +constexpr char PATHSEPCH = '/'; +constexpr char INVPATHSEPCH = '\\'; +#endif + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(EMSCRIPTEN) || defined(__ANDROID__) || defined(WIN32) || defined(SDLMAME_NO64BITIO) +using sdl_dirent = struct dirent; +using sdl_stat = struct stat; +#define sdl_readdir readdir +#define sdl_stat_fn stat +#else +using sdl_dirent = struct dirent64; +using sdl_stat = struct stat64; +#define sdl_readdir readdir64 +#define sdl_stat_fn stat64 +#endif + +#define HAS_DT_XXX (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__)) + + + +//============================================================ +// TYPE DEFINITIONS +//============================================================ + +class posix_directory : public osd::directory +{ +public: + posix_directory(); + virtual ~posix_directory() override; + + virtual const entry *read() override; + + bool open(std::string const &dirname); + +private: + typedef std::unique_ptr<DIR, int (*)(DIR *)> dir_ptr; + + entry m_entry; + sdl_dirent *m_data; + dir_ptr m_fd; + std::string m_path; +}; + + +//============================================================ +// posix_directory::~posix_directory +//============================================================ + +posix_directory::posix_directory() + : m_entry() + , m_data(nullptr) + , m_fd(nullptr, &::closedir) + , m_path() +{ +} + + +//============================================================ +// posix_directory::~posix_directory +//============================================================ + +posix_directory::~posix_directory() +{ +} + + +//============================================================ +// posix_directory::read +//============================================================ + +const osd::directory::entry *posix_directory::read() +{ + m_data = sdl_readdir(m_fd.get()); + if (!m_data) + return nullptr; + + m_entry.name = m_data->d_name; + + sdl_stat st; + bool stat_err(0 > sdl_stat_fn(util::string_format("%s%c%s", m_path, PATHSEPCH, m_data->d_name).c_str(), &st)); + +#if HAS_DT_XXX + switch (m_data->d_type) + { + case DT_DIR: + m_entry.type = entry::entry_type::DIR; + break; + case DT_REG: + m_entry.type = entry::entry_type::FILE; + break; + case DT_LNK: + if (stat_err) + m_entry.type = entry::entry_type::OTHER; + else if (S_ISDIR(st.st_mode)) + m_entry.type = entry::entry_type::DIR; + else + m_entry.type = entry::entry_type::FILE; + break; + default: + m_entry.type = entry::entry_type::OTHER; + } +#else + if (stat_err) + m_entry.type = entry::entry_type::OTHER; + else if (S_ISDIR(st.st_mode)) + m_entry.type = entry::entry_type::DIR; + else + m_entry.type = entry::entry_type::FILE; +#endif + m_entry.size = stat_err ? 0 : std::uint64_t(std::make_unsigned_t<decltype(st.st_size)>(st.st_size)); + m_entry.last_modified = std::chrono::system_clock::from_time_t(st.st_mtime); + return &m_entry; +} + + +//============================================================ +// posix_directory::open +//============================================================ + +bool posix_directory::open(std::string const &dirname) +{ + assert(!m_fd); + + osd_subst_env(m_path, dirname); + m_fd.reset(::opendir(m_path.c_str())); + return bool(m_fd); +} + +} // anonymous namespace + + +//============================================================ +// osd::directory::open +//============================================================ + +directory::ptr directory::open(std::string const &dirname) +{ + ptr dir; + try { dir.reset(new posix_directory); } + catch (...) { return nullptr; } + + if (!dir->open(dirname)) + return nullptr; + + return dir; +} + +} // namespace osd + + +//============================================================ +// osd_subst_env +//============================================================ + +void osd_subst_env(std::string &dst, std::string const &src) +{ + std::string result, var; + auto start = src.begin(); + + // a leading tilde expands as $HOME + if ((src.end() != start) && ('~' == *start)) + { + char const *const home = std::getenv("HOME"); + if (home) + { + ++start; + if ((src.end() == start) || (osd::PATHSEPCH == *start)) + result.append(home); + else + result.push_back('~'); + } + } + + while (src.end() != start) + { + // find $ marking start of environment variable or end of string + auto it = start; + while ((src.end() != it) && ('$' != *it)) ++it; + if (start != it) result.append(start, it); + start = it; + + if (src.end() != start) + { + start = ++it; + if ((src.end() != start) && ('{' == *start)) + { + start = ++it; + for (++it; (src.end() != it) && ('}' != *it); ++it) { } + if (src.end() == it) + { + result.append("${").append(start, it); + start = it; + } + else + { + var.assign(start, it); + start = ++it; + const char *const exp = std::getenv(var.c_str()); + if (exp) + result.append(exp); + else + fprintf(stderr, "Warning: osd_subst_env variable %s not found.\n", var.c_str()); + } + } + else if ((src.end() != start) && (('_' == *start) || std::isalnum(*start))) + { + for (++it; (src.end() != it) && (('_' == *it) || std::isalnum(*it)); ++it) { } + var.assign(start, it); + start = it; + const char *const exp = std::getenv(var.c_str()); + if (exp) + result.append(exp); + else + fprintf(stderr, "Warning: osd_subst_env variable %s not found.\n", var.c_str()); + } + else + { + result.push_back('$'); + } + } + } + + dst = std::move(result); +} diff --git a/src/osd/modules/file/posixfile.cpp b/src/osd/modules/file/posixfile.cpp index 8c3d2860060..8b8dc004da0 100644 --- a/src/osd/modules/file/posixfile.cpp +++ b/src/osd/modules/file/posixfile.cpp @@ -14,8 +14,13 @@ #endif #ifdef __linux__ +#ifndef __USE_LARGEFILE64 #define __USE_LARGEFILE64 #endif +#ifndef __USE_BSD +#define __USE_BSD +#endif +#endif #ifdef WIN32 #define _FILE_OFFSET_BITS 64 @@ -337,7 +342,7 @@ int osd_get_physical_drive_geometry(const char *filename, UINT32 *cylinders, UIN // osd_stat //============================================================ -osd_directory_entry *osd_stat(const std::string &path) +std::unique_ptr<osd::directory::entry> osd_stat(const std::string &path) { #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__) struct stat st; @@ -350,13 +355,18 @@ osd_directory_entry *osd_stat(const std::string &path) // create an osd_directory_entry; be sure to make sure that the caller can // free all resources by just freeing the resulting osd_directory_entry - osd_directory_entry *const result = reinterpret_cast<osd_directory_entry *>(osd_malloc_array(sizeof(osd_directory_entry) + path.length() + 1)); + osd::directory::entry *result; + try { result = reinterpret_cast<osd::directory::entry *>(::operator new(sizeof(*result) + path.length() + 1)); } + catch (...) { return nullptr; } + new (result) osd::directory::entry; + std::strcpy(reinterpret_cast<char *>(result) + sizeof(*result), path.c_str()); result->name = reinterpret_cast<char *>(result) + sizeof(*result); - result->type = S_ISDIR(st.st_mode) ? ENTTYPE_DIR : ENTTYPE_FILE; + result->type = S_ISDIR(st.st_mode) ? osd::directory::entry::entry_type::DIR : osd::directory::entry::entry_type::FILE; result->size = std::uint64_t(std::make_unsigned_t<decltype(st.st_size)>(st.st_size)); + result->last_modified = std::chrono::system_clock::from_time_t(st.st_mtime); - return result; + return std::unique_ptr<osd::directory::entry>(result); } diff --git a/src/osd/windows/windir.cpp b/src/osd/modules/file/windir.cpp index 32c5ec232ae..e6eecfab4a2 100644 --- a/src/osd/windows/windir.cpp +++ b/src/osd/modules/file/windir.cpp @@ -12,10 +12,6 @@ #include <shlwapi.h> #include <tchar.h> -// standard C headers -#include <stdio.h> -#include <ctype.h> - // MAME headers #include "osdcore.h" @@ -23,84 +19,45 @@ #include "strconv.h" #include "winutil.h" - -//============================================================ -// TYPE DEFINITIONS -//============================================================ - -namespace -{ - class win_directory : public osd::directory - { - public: - win_directory(); - ~win_directory(); - - virtual const entry *read() override; - - HANDLE m_find; // handle to the finder - bool m_is_first; // true if this is the first entry - entry m_entry; // current entry's data - WIN32_FIND_DATA m_data; // current raw data - }; -}; +// standard C headers +#include <stdio.h> +#include <ctype.h> +#include <cassert> +#include <cstring> +namespace osd { +namespace { //============================================================ -// osd::directory::open +// TYPE DEFINITIONS //============================================================ -osd::directory *osd::directory::open(const char *dirname) +class win_directory : public directory { - win_directory *dir = nullptr; - TCHAR *t_dirname = nullptr; - TCHAR *dirfilter = nullptr; - size_t dirfilter_size; - - // allocate memory to hold the osd_tool_directory structure - dir = new win_directory(); - if (dir == nullptr) - goto error; - - // convert the path to TCHARs - t_dirname = tstring_from_utf8(dirname); - if (t_dirname == nullptr) - goto error; +public: + win_directory(); + virtual ~win_directory() override; - // append \*.* to the directory name - dirfilter_size = _tcslen(t_dirname) + 5; - dirfilter = (TCHAR *)malloc(dirfilter_size * sizeof(*dirfilter)); - if (dirfilter == nullptr) - goto error; - _sntprintf(dirfilter, dirfilter_size, TEXT("%s\\*.*"), t_dirname); + virtual const entry *read() override; - // attempt to find the first file - dir->m_find = FindFirstFileEx(dirfilter, FindExInfoStandard, &dir->m_data, FindExSearchNameMatch, nullptr, 0); - -error: - // cleanup - if (t_dirname != nullptr) - osd_free(t_dirname); - if (dirfilter != nullptr) - free(dirfilter); - if (dir != nullptr && dir->m_find == INVALID_HANDLE_VALUE) - { - delete dir; - dir = nullptr; - } - return dir; -} + bool open(std::string const &dirname); +private: + HANDLE m_find; // handle to the finder + bool m_is_first; // true if this is the first entry + entry m_entry; // current entry's data + WIN32_FIND_DATA m_data; // current raw data +}; //============================================================ // win_directory::win_directory //============================================================ win_directory::win_directory() - : m_find(INVALID_HANDLE_VALUE), m_is_first(true) + : m_find(INVALID_HANDLE_VALUE) + , m_is_first(true) { - memset(&m_entry, 0, sizeof(m_entry)); - memset(&m_data, 0, sizeof(m_data)); + std::memset(&m_data, 0, sizeof(m_data)); } @@ -122,7 +79,7 @@ win_directory::~win_directory() // win_directory::read //============================================================ -const osd::directory::entry *win_directory::read() +const directory::entry *win_directory::read() { // if we've previously allocated a name, free it now if (m_entry.name != nullptr) @@ -142,7 +99,56 @@ const osd::directory::entry *win_directory::read() // extract the data m_entry.name = utf8_from_tstring(m_data.cFileName); m_entry.type = win_attributes_to_entry_type(m_data.dwFileAttributes); - m_entry.size = m_data.nFileSizeLow | ((UINT64) m_data.nFileSizeHigh << 32); + m_entry.size = m_data.nFileSizeLow | (std::uint64_t(m_data.nFileSizeHigh) << 32); m_entry.last_modified = win_time_point_from_filetime(&m_data.ftLastWriteTime); return (m_entry.name != nullptr) ? &m_entry : nullptr; } + + +//============================================================ +// win_directory::open +//============================================================ + +bool win_directory::open(std::string const &dirname) +{ + assert(m_find == INVALID_HANDLE_VALUE); + + // convert the path to TCHARs + std::unique_ptr<TCHAR, void (*)(void *)> const t_dirname(tstring_from_utf8(dirname.c_str()), &osd_free); + if (!t_dirname) + return false; + + // append \*.* to the directory name + auto const dirfilter_size = _tcslen(t_dirname.get()) + 5; + std::unique_ptr<TCHAR []> dirfilter; + try { dirfilter.reset(new TCHAR[dirfilter_size]); } + catch (...) { return false; } + _sntprintf(dirfilter.get(), dirfilter_size, TEXT("%s\\*.*"), t_dirname.get()); + + // attempt to find the first file + m_find = FindFirstFileEx(dirfilter.get(), FindExInfoStandard, &m_data, FindExSearchNameMatch, nullptr, 0); + if (m_find == INVALID_HANDLE_VALUE) + return false; +} + +} // anonymous namespace + + +//============================================================ +// osd::directory::open +//============================================================ + +directory::ptr directory::open(std::string const &dirname) +{ + // allocate memory to hold the osd_tool_directory structure + ptr dir; + try { dir.reset(new win_directory()); } + catch (...) { return nullptr; } + + if (!dir->open(dirname)) + return false; + + return dir; +} + +} // namesapce osd diff --git a/src/osd/modules/file/winfile.cpp b/src/osd/modules/file/winfile.cpp index 13af3a025c8..c304259b915 100644 --- a/src/osd/modules/file/winfile.cpp +++ b/src/osd/modules/file/winfile.cpp @@ -381,9 +381,11 @@ std::unique_ptr<osd::directory::entry> osd_stat(const std::string &path) // create an osd::directory::entry; be sure to make sure that the caller can // free all resources by just freeing the resulting osd::directory::entry - osd::directory::entry *result = (osd::directory::entry *) ::operator new(sizeof(*result) + path.length() + 1); - if (!result) - return nullptr; + osd::directory::entry *result; + try { result = reinterpret_cast<osd::directory::entry *>(::operator new(sizeof(*result) + path.length() + 1)); } + catch (...) { return nullptr; } + new (result) osd::directory::entry; + strcpy(((char *) result) + sizeof(*result), path.c_str()); result->name = ((char *) result) + sizeof(*result); result->type = win_attributes_to_entry_type(find_data.dwFileAttributes); diff --git a/src/osd/modules/render/bgfx/chainentryreader.cpp b/src/osd/modules/render/bgfx/chainentryreader.cpp index c169a0cd441..278a795f6e7 100644 --- a/src/osd/modules/render/bgfx/chainentryreader.cpp +++ b/src/osd/modules/render/bgfx/chainentryreader.cpp @@ -115,8 +115,8 @@ bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, std::s directory_path += "/" + file_directory; } - osd::directory *directory = osd::directory::open(directory_path.c_str()); - if (directory != nullptr) + osd::directory::ptr directory = osd::directory::open(directory_path); + if (directory) { for (const osd::directory::entry *entry = directory->read(); entry != nullptr; entry = directory->read()) { @@ -159,8 +159,6 @@ bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, std::s } } } - - delete directory; } } } diff --git a/src/osd/modules/render/bgfx/chainmanager.cpp b/src/osd/modules/render/bgfx/chainmanager.cpp index eaf8297a4ee..d4c59f9bb6a 100644 --- a/src/osd/modules/render/bgfx/chainmanager.cpp +++ b/src/osd/modules/render/bgfx/chainmanager.cpp @@ -91,7 +91,7 @@ void chain_manager::destroy_unloaded_chains() void chain_manager::find_available_chains(std::string root, std::string path) { - osd::directory *directory = osd::directory::open((root + path).c_str()); + osd::directory::ptr directory = osd::directory::open(root + path); if (directory != nullptr) { for (const osd::directory::entry *entry = directory->read(); entry != nullptr; entry = directory->read()) @@ -128,8 +128,6 @@ void chain_manager::find_available_chains(std::string root, std::string path) } } } - - delete directory; } } diff --git a/src/osd/osdcore.h b/src/osd/osdcore.h index 137f49d58e9..141f3db55d9 100644 --- a/src/osd/osdcore.h +++ b/src/osd/osdcore.h @@ -21,11 +21,11 @@ #include "osdcomm.h" +#include <chrono> #include <cstdarg> #include <cstdint> #include <memory> #include <string> -#include <chrono> /*************************************************************************** @@ -304,6 +304,8 @@ namespace osd class directory { public: + typedef std::unique_ptr<directory> ptr; + // osd::directory::entry contains basic information about a file when iterating through // a directory class entry @@ -319,7 +321,7 @@ namespace osd const char * name; // name of the entry entry_type type; // type of the entry - UINT64 size; // size of the entry + std::uint64_t size; // size of the entry std::chrono::system_clock::time_point last_modified; // last modified time }; @@ -336,7 +338,7 @@ namespace osd // which contains opaque data necessary to traverse the directory; on // failure, this function should return nullptr // ----------------------------------------------------------------------------- - static directory *open(const char *dirname); + static ptr open(std::string const &dirname); // ----------------------------------------------------------------------------- // osd::directory::~directory: close an open directory diff --git a/src/osd/sdl/sdldir.cpp b/src/osd/sdl/sdldir.cpp deleted file mode 100644 index fcae732ed53..00000000000 --- a/src/osd/sdl/sdldir.cpp +++ /dev/null @@ -1,316 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert, R. Belmont -//============================================================ -// -// sdldir.c - SDL core directory access functions -// -// SDLMAME by Olivier Galibert and R. Belmont -// -//============================================================ - -#ifdef SDLMAME_WIN32 -#include "../windows/windir.cpp" -#else - -#ifndef _LARGEFILE64_SOURCE -#define _LARGEFILE64_SOURCE -#endif - -#ifdef SDLMAME_LINUX -#define __USE_LARGEFILE64 -#endif -#ifndef SDLMAME_BSD -#ifdef _XOPEN_SOURCE -#undef _XOPEN_SOURCE -#endif -#define _XOPEN_SOURCE 500 -#endif - -#include <cctype> -#include <cstdlib> -#include <utility> - -//#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#ifndef __USE_BSD -#define __USE_BSD // to get DT_xxx on Linux -#endif -#undef _POSIX_C_SOURCE // to get DT_xxx on OS X -#include <dirent.h> - -#include "osdcore.h" -#include "modules/lib/osdlib.h" - -#if defined(SDLMAME_WIN32) -#define PATHSEPCH '\\' -#define INVPATHSEPCH '/' -#else -#define PATHSEPCH '/' -#define INVPATHSEPCH '\\' -#endif - -#if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_HAIKU) || defined(SDLMAME_EMSCRIPTEN) || defined(SDLMAME_ANDROID) -typedef struct dirent sdl_dirent; -typedef struct stat sdl_stat; -#define sdl_readdir readdir -#define sdl_stat_fn stat -#else -typedef struct dirent64 sdl_dirent; -typedef struct stat64 sdl_stat; -#define sdl_readdir readdir64 -#define sdl_stat_fn stat64 -#endif - -#define HAS_DT_XXX defined(SDLMAME_LINUX) || defined(SDLMAME_BSD) || defined(SDLMAME_DARWIN) - -struct osd_directory -{ - osd_directory_entry ent; - sdl_dirent *data; - DIR *fd; - char *path; -}; - -static char *build_full_path(const char *path, const char *file) -{ - char *ret = (char *) osd_malloc_array(strlen(path)+strlen(file)+2); - char *p = ret; - - strcpy(p, path); - p += strlen(path); - *p++ = PATHSEPCH; - strcpy(p, file); - return ret; -} - - -#if HAS_DT_XXX -static osd_dir_entry_type get_attributes_enttype(int attributes, char *path) -{ - switch ( attributes ) - { - case DT_DIR: - return ENTTYPE_DIR; - - case DT_REG: - return ENTTYPE_FILE; - - case DT_LNK: - { - struct stat s; - - if ( stat(path, &s) != 0 ) - return ENTTYPE_OTHER; - else - return S_ISDIR(s.st_mode) ? ENTTYPE_DIR : ENTTYPE_FILE; - } - - default: - return ENTTYPE_OTHER; - } -} -#else - -static osd_dir_entry_type get_attributes_stat(const char *file) -{ - sdl_stat st; - if(sdl_stat_fn(file, &st)) - return (osd_dir_entry_type) 0; - - if (S_ISDIR(st.st_mode)) - return ENTTYPE_DIR; - else - return ENTTYPE_FILE; -} -#endif - -static UINT64 osd_get_file_size(const char *file) -{ - sdl_stat st; - if(sdl_stat_fn(file, &st)) - return 0; - return st.st_size; -} - -//============================================================ -// osd_opendir -//============================================================ - -osd_directory *osd_opendir(const char *dirname) -{ - osd_directory *dir = nullptr; - char *tmpstr, *envstr; - int i, j; - - dir = (osd_directory *) osd_malloc(sizeof(osd_directory)); - if (dir) - { - memset(dir, 0, sizeof(osd_directory)); - dir->fd = nullptr; - } - - tmpstr = (char *) osd_malloc_array(strlen(dirname)+1); - strcpy(tmpstr, dirname); - - if (tmpstr[0] == '$') - { - envstr = (char *) osd_malloc_array(strlen(tmpstr)+1); - - strcpy(envstr, tmpstr); - - i = 0; - while (envstr[i] != PATHSEPCH && envstr[i] != INVPATHSEPCH && envstr[i] != 0 && envstr[i] != '.') - { - i++; - } - - envstr[i] = '\0'; - - const char *envval = osd_getenv(&envstr[1]); - if (envval != nullptr) - { - j = strlen(envval) + strlen(tmpstr) + 1; - osd_free(tmpstr); - tmpstr = (char *) osd_malloc_array(j); - - // start with the value of $HOME - strcpy(tmpstr, envval); - // replace the null with a path separator again - envstr[i] = PATHSEPCH; - // append it - strcat(tmpstr, &envstr[i]); - } - else - fprintf(stderr, "Warning: osd_opendir environment variable %s not found.\n", envstr); - osd_free(envstr); - } - - dir->fd = opendir(tmpstr); - dir->path = tmpstr; - - if (dir && (dir->fd == nullptr)) - { - osd_free(dir->path); - osd_free(dir); - dir = nullptr; - } - - return dir; -} - - -//============================================================ -// osd_readdir -//============================================================ - -const osd_directory_entry *osd_readdir(osd_directory *dir) -{ - char *temp; - dir->data = sdl_readdir(dir->fd); - - if (dir->data == nullptr) - return nullptr; - - dir->ent.name = dir->data->d_name; - temp = build_full_path(dir->path, dir->data->d_name); - #if HAS_DT_XXX - dir->ent.type = get_attributes_enttype(dir->data->d_type, temp); - #else - dir->ent.type = get_attributes_stat(temp); - #endif - dir->ent.size = osd_get_file_size(temp); - osd_free(temp); - return &dir->ent; -} - - -//============================================================ -// osd_closedir -//============================================================ - -void osd_closedir(osd_directory *dir) -{ - if (dir->fd != nullptr) - closedir(dir->fd); - osd_free(dir->path); - osd_free(dir); -} - - -//============================================================ -// osd_subst_env -//============================================================ - -void osd_subst_env(std::string &dst, std::string const &src) -{ - std::string result, var; - auto start = src.begin(); - - // a leading tilde expands as $HOME - if ((src.end() != start) && ('~' == *start)) - { - char const *const home = std::getenv("HOME"); - if (home) - { - ++start; - if ((src.end() == start) || (PATHSEPCH == *start)) - result.append(home); - else - result.push_back('~'); - } - } - - while (src.end() != start) - { - // find $ marking start of environment variable or end of string - auto it = start; - while ((src.end() != it) && ('$' != *it)) ++it; - if (start != it) result.append(start, it); - start = it; - - if (src.end() != start) - { - start = ++it; - if ((src.end() != start) && ('{' == *start)) - { - start = ++it; - for (++it; (src.end() != it) && ('}' != *it); ++it) { } - if (src.end() == it) - { - result.append("${").append(start, it); - start = it; - } - else - { - var.assign(start, it); - start = ++it; - const char *const exp = std::getenv(var.c_str()); - if (exp) - result.append(exp); - else - fprintf(stderr, "Warning: osd_subst_env variable %s not found.\n", var.c_str()); - } - } - else if ((src.end() != start) && (('_' == *start) || std::isalnum(*start))) - { - for (++it; (src.end() != it) && (('_' == *it) || std::isalnum(*it)); ++it) { } - var.assign(start, it); - start = it; - const char *const exp = std::getenv(var.c_str()); - if (exp) - result.append(exp); - else - fprintf(stderr, "Warning: osd_subst_env variable %s not found.\n", var.c_str()); - } - else - { - result.push_back('$'); - } - } - } - - dst = std::move(result); -} - -#endif diff --git a/src/tools/romcmp.cpp b/src/tools/romcmp.cpp index 641667b6342..0545da64c64 100644 --- a/src/tools/romcmp.cpp +++ b/src/tools/romcmp.cpp @@ -448,22 +448,20 @@ static void printname(const fileinfo *file1,const fileinfo *file2,float score,in static int load_files(int i, int *found, const char *path) { - osd_directory *dir; - /* attempt to open as a directory first */ - dir = osd_opendir(path); - if (dir != nullptr) + auto dir = osd::directory::open(path); + if (dir) { - const osd_directory_entry *d; + const osd::directory::entry *d; /* load all files in directory */ - while ((d = osd_readdir(dir)) != nullptr) + while ((d = dir->read()) != nullptr) { const char *d_name = d->name; char buf[255+1]; sprintf(buf, "%s%c%s", path, PATH_DELIM, d_name); - if (d->type == ENTTYPE_FILE) + if (d->type == osd::directory::entry::entry_type::FILE) { UINT64 size = d->size; while (size && (size & 1) == 0) size >>= 1; @@ -484,7 +482,7 @@ static int load_files(int i, int *found, const char *path) } } } - osd_closedir(dir); + dir.reset(); } /* if not, try to open as a ZIP file */ diff --git a/src/tools/src2html.cpp b/src/tools/src2html.cpp index 38260a62879..9d89a7d220f 100644 --- a/src/tools/src2html.cpp +++ b/src/tools/src2html.cpp @@ -324,7 +324,7 @@ static int compare_list_entries(const void *p1, const void *p2) static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std::string &dstdir, std::string &tempheader, std::string &tempfooter) { - static const osd_dir_entry_type typelist[] = { ENTTYPE_DIR, ENTTYPE_FILE }; + static const osd::directory::entry::entry_type typelist[] = { osd::directory::entry::entry_type::DIR, osd::directory::entry::entry_type::FILE }; // extract a normalized subpath std::string srcdir_subpath; @@ -344,10 +344,10 @@ static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std: int result = 0; for (int entindex = 0; entindex < ARRAY_LENGTH(typelist) && result == 0; entindex++) { - osd_dir_entry_type entry_type = typelist[entindex]; + auto entry_type = typelist[entindex]; // open the directory and iterate through it - osd_directory *dir = osd_opendir(srcdir.c_str()); + auto dir = osd::directory::open(srcdir.c_str()); if (dir == nullptr) { result = 1; @@ -355,10 +355,10 @@ static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std: } // build up the list of files - const osd_directory_entry *entry; + const osd::directory::entry *entry; int found = 0; list_entry *list = nullptr; - while ((entry = osd_readdir(dir)) != nullptr) + while ((entry = dir->read()) != nullptr) if (entry->type == entry_type && entry->name[0] != '.') { auto lentry = new list_entry; @@ -369,7 +369,7 @@ static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std: } // close the directory - osd_closedir(dir); + dir.reset(); // skip if nothing found if (found == 0) @@ -398,7 +398,7 @@ static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std: { // add a header if (curlist == list) - indexfile->printf("\t<h2>%s</h2>\n\t<ul>\n", (entry_type == ENTTYPE_DIR) ? "Directories" : "Files"); + indexfile->printf("\t<h2>%s</h2>\n\t<ul>\n", (entry_type == osd::directory::entry::entry_type::DIR) ? "Directories" : "Files"); // build the source filename std::string srcfile; @@ -406,7 +406,7 @@ static int recurse_dir(int srcrootlen, int dstrootlen, std::string &srcdir, std: // if we have a file, output it std::string dstfile; - if (entry_type == ENTTYPE_FILE) + if (entry_type == osd::directory::entry::entry_type::FILE) { // make sure we care, first file_type type = FILE_TYPE_INVALID; |