From 5cee9e9bc4fe03dc561d3a7a87ecadcf89743e2b Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sat, 25 Jun 2016 03:00:31 +1000 Subject: POSIX implementation for new directory read features, cleanup of Windows implementation, return directory handle as smart pointer, fix full build [Vas Crabb] --- src/osd/modules/file/posixdir.cpp | 293 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 src/osd/modules/file/posixdir.cpp (limited to 'src/osd/modules/file/posixdir.cpp') 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 +#include +#include +#include +#include +#include + +#include +#include +#include + + + +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_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(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); +} -- cgit v1.2.3-70-g09d2 From b3491464e41b6afea81e188fe6a350d4f778854b Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 24 Jun 2016 21:24:28 +0200 Subject: This worked by pure luck (nw) --- src/osd/modules/file/posixdir.cpp | 10 +++++----- src/osd/modules/file/windir.cpp | 14 ++++++++------ src/osd/osdcore.h | 4 ++++ 3 files changed, 17 insertions(+), 11 deletions(-) (limited to 'src/osd/modules/file/posixdir.cpp') diff --git a/src/osd/modules/file/posixdir.cpp b/src/osd/modules/file/posixdir.cpp index d08d6869c6c..3141de45b16 100644 --- a/src/osd/modules/file/posixdir.cpp +++ b/src/osd/modules/file/posixdir.cpp @@ -99,7 +99,7 @@ public: virtual const entry *read() override; - bool open(std::string const &dirname); + virtual bool opendir(std::string const &dirname) override; private: typedef std::unique_ptr dir_ptr; @@ -183,10 +183,10 @@ const osd::directory::entry *posix_directory::read() //============================================================ -// posix_directory::open +// posix_directory::opendir //============================================================ -bool posix_directory::open(std::string const &dirname) +bool posix_directory::opendir(std::string const &dirname) { assert(!m_fd); @@ -205,10 +205,10 @@ bool posix_directory::open(std::string const &dirname) directory::ptr directory::open(std::string const &dirname) { ptr dir; - try { dir.reset(new posix_directory); } + try { dir = std::make_unique(); } catch (...) { return nullptr; } - if (!dir->open(dirname)) + if (!dir->opendir(dirname)) return nullptr; return dir; diff --git a/src/osd/modules/file/windir.cpp b/src/osd/modules/file/windir.cpp index e6eecfab4a2..1694929492d 100644 --- a/src/osd/modules/file/windir.cpp +++ b/src/osd/modules/file/windir.cpp @@ -40,7 +40,7 @@ public: virtual const entry *read() override; - bool open(std::string const &dirname); + virtual bool opendir(std::string const &dirname) override; private: HANDLE m_find; // handle to the finder @@ -106,10 +106,10 @@ const directory::entry *win_directory::read() //============================================================ -// win_directory::open +// win_directory::opendir //============================================================ -bool win_directory::open(std::string const &dirname) +bool win_directory::opendir(std::string const &dirname) { assert(m_find == INVALID_HANDLE_VALUE); @@ -121,7 +121,7 @@ bool win_directory::open(std::string const &dirname) // append \*.* to the directory name auto const dirfilter_size = _tcslen(t_dirname.get()) + 5; std::unique_ptr dirfilter; - try { dirfilter.reset(new TCHAR[dirfilter_size]); } + try { dirfilter = std::make_unique(dirfilter_size); } catch (...) { return false; } _sntprintf(dirfilter.get(), dirfilter_size, TEXT("%s\\*.*"), t_dirname.get()); @@ -129,6 +129,8 @@ bool win_directory::open(std::string const &dirname) m_find = FindFirstFileEx(dirfilter.get(), FindExInfoStandard, &m_data, FindExSearchNameMatch, nullptr, 0); if (m_find == INVALID_HANDLE_VALUE) return false; + + return true; } } // anonymous namespace @@ -142,10 +144,10 @@ 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()); } + try { dir = std::make_unique(); } catch (...) { return nullptr; } - if (!dir->open(dirname)) + if (!dir->opendir(dirname)) return false; return dir; diff --git a/src/osd/osdcore.h b/src/osd/osdcore.h index 141f3db55d9..8c4b32b3a5d 100644 --- a/src/osd/osdcore.h +++ b/src/osd/osdcore.h @@ -319,6 +319,7 @@ namespace osd OTHER }; + entry() : name(nullptr), type(entry_type::NONE), size(0) {} const char * name; // name of the entry entry_type type; // type of the entry std::uint64_t size; // size of the entry @@ -355,6 +356,9 @@ namespace osd // present // ----------------------------------------------------------------------------- virtual const entry *read() = 0; + + protected: + virtual bool opendir(std::string const &dirname) = 0; }; }; -- cgit v1.2.3-70-g09d2