diff --git a/src/emucore/FSNode.cxx b/src/emucore/FSNode.cxx index 11cf9727a..99f3e9686 100644 --- a/src/emucore/FSNode.cxx +++ b/src/emucore/FSNode.cxx @@ -69,12 +69,6 @@ FSNode& FSNode::operator/=(const string& path) #endif } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool FSNode::exists() const -{ - return _realNode ? _realNode->exists() : false; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool FSNode::getAllChildren(FSList& fslist, ListMode mode, const NameFilter& filter, @@ -290,64 +284,6 @@ string FSNode::getPathWithExt(const string& ext) const return (pos != string::npos) ? s.replace(pos, string::npos, ext) : s + ext; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool FSNode::hasParent() const -{ - return _realNode ? _realNode->hasParent() : false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FSNode FSNode::getParent() const -{ - if (!_realNode) - return *this; - - AbstractFSNodePtr node = _realNode->getParent(); - return node ? FSNode(node) : *this; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool FSNode::isDirectory() const -{ - return _realNode ? _realNode->isDirectory() : false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool FSNode::isFile() const -{ - return _realNode ? _realNode->isFile() : false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool FSNode::isReadable() const -{ - return _realNode ? _realNode->isReadable() : false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool FSNode::isWritable() const -{ - return _realNode ? _realNode->isWritable() : false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool FSNode::makeDir() -{ - return (_realNode && !_realNode->exists()) ? _realNode->makeDir() : false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool FSNode::rename(const string& newfile) -{ - return (_realNode && _realNode->exists()) ? _realNode->rename(newfile) : false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -size_t FSNode::getSize() const -{ - return (_realNode && _realNode->exists()) ? _realNode->getSize() : 0; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - size_t FSNode::read(ByteBuffer& buffer, size_t size) const { @@ -395,3 +331,67 @@ size_t FSNode::write(const stringstream& buffer) const return 0; } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +size_t FSNode::getSize() const +{ + return (_realNode && _realNode->exists()) ? _realNode->getSize() : 0; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FSNode::hasParent() const +{ + return _realNode ? _realNode->hasParent() : false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +FSNode FSNode::getParent() const +{ + if (!_realNode) + return *this; + + AbstractFSNodePtr node = _realNode->getParent(); + return node ? FSNode(node) : *this; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FSNode::exists() const +{ + return _realNode ? _realNode->exists() : false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FSNode::isDirectory() const +{ + return _realNode ? _realNode->isDirectory() : false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FSNode::isFile() const +{ + return _realNode ? _realNode->isFile() : false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FSNode::isReadable() const +{ + return _realNode ? _realNode->isReadable() : false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FSNode::isWritable() const +{ + return _realNode ? _realNode->isWritable() : false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FSNode::makeDir() +{ + return (_realNode && !_realNode->exists()) ? _realNode->makeDir() : false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FSNode::rename(const string& newfile) +{ + return (_realNode && _realNode->exists()) ? _realNode->rename(newfile) : false; +} diff --git a/src/emucore/FSNode.hxx b/src/emucore/FSNode.hxx index efdc9b75c..e55bdaf9d 100644 --- a/src/emucore/FSNode.hxx +++ b/src/emucore/FSNode.hxx @@ -28,9 +28,6 @@ * in a portable fashion. To this end, multiple or single roots have to be * supported (compare Unix with a single root, Windows with multiple roots C:, * D:, ...). - * - * To this end, we abstract away from paths; implementations can be based on - * paths (and it's left to them whether / or \ or : is the path separator :-). */ class FSNode; @@ -52,11 +49,7 @@ class FSList : public vector { }; class FSNode { public: - #ifdef BSPF_WINDOWS - static constexpr char PATH_SEPARATOR = '\\'; - #else - static constexpr char PATH_SEPARATOR = '/'; - #endif + static constexpr char PATH_SEPARATOR = fs::path::preferred_separator; public: /** diff --git a/src/unix/FSNodePOSIX.cxx b/src/unix/FSNodePOSIX.cxx index d351a3a78..5b3c8513b 100644 --- a/src/unix/FSNodePOSIX.cxx +++ b/src/unix/FSNodePOSIX.cxx @@ -35,7 +35,7 @@ FSNodePOSIX::FSNodePOSIX(const string& path, bool verify) : _path{path.length() > 0 ? path : "~"} // Default to home directory { // Expand '~' to the HOME environment variable - if(_path[0] == '~') + if (_path[0] == '~') { #if defined(BSPF_WINDOWS) @@ -45,20 +45,21 @@ FSNodePOSIX::FSNodePOSIX(const string& path, bool verify) if (home != nullptr) _path.replace(0, 1, home); } - // Get absolute path (only used for relative directories) - else if(_path[0] == '.') - { - std::array buf; - if(realpath(_path.c_str(), buf.data())) - _path = buf.data(); - } - _fspath = _path; + + if (fs::exists(_fspath)) // get absolute path whenever possible + _fspath = fs::canonical(_fspath); + _path = _fspath.string(); _displayName = lastPathComponent(_path); - if(verify) + if (verify) setFlags(); + + // Add a trailing slash, if necessary + if (_isDirectory && _path.length() > 0 && + _path[_path.length()-1] != FSNode::PATH_SEPARATOR) + _path += FSNode::PATH_SEPARATOR; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -98,11 +99,12 @@ string FSNodePOSIX::getShortPath() const #endif const string& home = env_home != nullptr ? env_home : EmptyString; - if(home != EmptyString && BSPF::startsWithIgnoreCase(_path, home)) + if (home != EmptyString && BSPF::startsWithIgnoreCase(_path, home)) { string path = "~"; const char* offset = _path.c_str() + home.size(); - if(*offset != '/') path += "/"; + if(*offset != FSNode::PATH_SEPARATOR) + path += FSNode::PATH_SEPARATOR; path += offset; return path; } @@ -177,8 +179,6 @@ size_t FSNodePOSIX::read(ByteBuffer& buffer, size_t size) const } else throw runtime_error("File open/read error"); - - return 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -196,8 +196,6 @@ size_t FSNodePOSIX::read(stringstream& buffer) const } else throw runtime_error("File open/read error"); - - return 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -212,8 +210,6 @@ size_t FSNodePOSIX::write(const ByteBuffer& buffer, size_t size) const } else throw runtime_error("File open/write error"); - - return 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -228,56 +224,51 @@ size_t FSNodePOSIX::write(const stringstream& buffer) const } else throw runtime_error("File open/write error"); - - return 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool FSNodePOSIX::makeDir() { - if(mkdir(_path.c_str(), 0777) == 0) + if (!(exists() && _isDirectory) && fs::create_directory(_fspath)) { - // Get absolute path - std::array buf; - if(realpath(_path.c_str(), buf.data())) - _path = buf.data(); - + _fspath = fs::canonical(_fspath); + _path = _fspath.string(); _displayName = lastPathComponent(_path); + setFlags(); // Add a trailing slash, if necessary - if (_path.length() > 0 && _path[_path.length()-1] != '/') - _path += '/'; + if (_path.length() > 0 && _path[_path.length()-1] != FSNode::PATH_SEPARATOR) + _path += FSNode::PATH_SEPARATOR; return true; } - else - return false; + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool FSNodePOSIX::rename(const string& newfile) { - if(std::rename(_path.c_str(), newfile.c_str()) == 0) + fs::path newpath = newfile; + + std::error_code ec; + fs::rename(_fspath, newpath, ec); + if (!ec) { - _path = newfile; - - // Get absolute path - std::array buf; - if(realpath(_path.c_str(), buf.data())) - _path = buf.data(); - + _fspath = fs::canonical(newpath); + _path = _fspath.string(); _displayName = lastPathComponent(_path); + setFlags(); // Add a trailing slash, if necessary - if (_isDirectory && _path.length() > 0 && _path[_path.length()-1] != '/') - _path += '/'; + if (_isDirectory && _path.length() > 0 && + _path[_path.length()-1] != FSNode::PATH_SEPARATOR) + _path += FSNode::PATH_SEPARATOR; return true; } - else - return false; + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/unix/FSNodePOSIX.hxx b/src/unix/FSNodePOSIX.hxx index 8fb6f8265..5dc90b7fd 100644 --- a/src/unix/FSNodePOSIX.hxx +++ b/src/unix/FSNodePOSIX.hxx @@ -20,24 +20,6 @@ #include "FSNode.hxx" -#ifdef BSPF_MACOS - #include -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifndef MAXPATHLEN // No MAXPATHLEN, as happens on Hurd - #define MAXPATHLEN 1024 -#endif - /* * Implementation of the Stella filesystem API for regular files, * based on the std::filesystem API in C++17.