mirror of https://github.com/stella-emu/stella.git
getChildren now works correctly.
This commit is contained in:
parent
686a5e289d
commit
d3285646ab
|
@ -128,16 +128,16 @@ class FSNode
|
|||
bool exists() const;
|
||||
|
||||
/**
|
||||
* Return a list of child nodes of this and all sub-directories. If called on a node
|
||||
* that does not represent a directory, false is returned.
|
||||
* Return a list of child nodes of this and all sub-directories. If called
|
||||
* on a node that does not represent a directory, false is returned.
|
||||
*
|
||||
* @return true if successful, false otherwise (e.g. when the directory
|
||||
* does not exist).
|
||||
*/
|
||||
bool getAllChildren(FSList& fslist, ListMode mode = ListMode::DirectoriesOnly,
|
||||
const NameFilter& filter = [](const FSNode&) { return true; },
|
||||
bool includeParentDirectory = true,
|
||||
const CancelCheck& isCancelled = []() { return false; }) const;
|
||||
const NameFilter& filter = [](const FSNode&) { return true; },
|
||||
bool includeParentDirectory = true,
|
||||
const CancelCheck& isCancelled = []() { return false; }) const;
|
||||
|
||||
/**
|
||||
* Return a list of child nodes of this directory node. If called on a node
|
||||
|
@ -147,10 +147,10 @@ class FSNode
|
|||
* does not exist).
|
||||
*/
|
||||
bool getChildren(FSList& fslist, ListMode mode = ListMode::DirectoriesOnly,
|
||||
const NameFilter& filter = [](const FSNode&){ return true; },
|
||||
bool includeChildDirectories = false,
|
||||
bool includeParentDirectory = true,
|
||||
const CancelCheck& isCancelled = []() { return false; }) const;
|
||||
const NameFilter& filter = [](const FSNode&){ return true; },
|
||||
bool includeChildDirectories = false,
|
||||
bool includeParentDirectory = true,
|
||||
const CancelCheck& isCancelled = []() { return false; }) const;
|
||||
|
||||
/**
|
||||
* Set/get a string representation of the name of the file. This is can be
|
||||
|
@ -452,7 +452,7 @@ class AbstractFSNode
|
|||
*
|
||||
* @return Size (in bytes) of the current node path.
|
||||
*/
|
||||
virtual size_t getSize() const { return 0; }
|
||||
virtual size_t getSize() const = 0;
|
||||
|
||||
/**
|
||||
* Read data (binary format) into the given buffer.
|
||||
|
|
|
@ -64,7 +64,6 @@ FSNodePOSIX::FSNodePOSIX(const string& path, bool verify)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FSNodePOSIX::setFlags()
|
||||
{
|
||||
#if 1
|
||||
// cerr << "_fspath: " << _fspath << endl;
|
||||
std::error_code ec;
|
||||
const auto s = fs::status(_fspath, ec);
|
||||
|
@ -72,7 +71,6 @@ void FSNodePOSIX::setFlags()
|
|||
{
|
||||
const auto p = s.permissions();
|
||||
|
||||
_isValid = true;
|
||||
_isFile = fs::is_regular_file(s);
|
||||
_isDirectory = fs::is_directory(s);
|
||||
_isReadable = (p & (fs::perms::owner_read |
|
||||
|
@ -81,32 +79,20 @@ void FSNodePOSIX::setFlags()
|
|||
_isWriteable = (p & (fs::perms::owner_write |
|
||||
fs::perms::group_write |
|
||||
fs::perms::others_write)) != fs::perms::none;
|
||||
// cerr << "_isValid: " << _isValid << endl
|
||||
// << "_isFile: " << _isFile << endl
|
||||
_size = _isFile ? fs::file_size(_fspath) : 0;
|
||||
|
||||
// cerr << "_isFile: " << _isFile << endl
|
||||
// << "_isDirectory: " << _isDirectory << endl
|
||||
// << "_isReadable: " << _isReadable << endl
|
||||
// << "_isWriteable: " << _isWriteable << endl
|
||||
// << "_size: " << _size << endl
|
||||
// << endl;
|
||||
}
|
||||
else
|
||||
_isValid = _isFile = _isDirectory = _isReadable = _isWriteable = false;
|
||||
|
||||
#else
|
||||
struct stat st;
|
||||
|
||||
_isValid = (0 == stat(_path.c_str(), &st));
|
||||
if(_isValid)
|
||||
{
|
||||
_isDirectory = S_ISDIR(st.st_mode);
|
||||
_isFile = S_ISREG(st.st_mode);
|
||||
|
||||
// Add a trailing slash, if necessary
|
||||
if (_isDirectory && _path.length() > 0 && _path[_path.length()-1] != '/')
|
||||
_path += '/';
|
||||
_isFile = _isDirectory = _isReadable = _isWriteable = false;
|
||||
_size = 0;
|
||||
}
|
||||
else
|
||||
_isDirectory = _isFile = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -140,93 +126,48 @@ bool FSNodePOSIX::hasParent() const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FSNodePOSIX::getChildren(AbstractFSList& myList, ListMode mode) const
|
||||
{
|
||||
cerr << "getChildren: " << _path << endl;
|
||||
assert(_isDirectory);
|
||||
|
||||
DIR* dirp = opendir(_path.c_str());
|
||||
if (dirp == nullptr)
|
||||
return false;
|
||||
|
||||
// Loop over dir entries using readdir
|
||||
struct dirent* dp = nullptr;
|
||||
while ((dp = readdir(dirp)) != nullptr)
|
||||
// cerr << "getChildren: " << _path << endl;
|
||||
std::error_code ec;
|
||||
for (const auto& entry: fs::directory_iterator{_fspath,
|
||||
fs::directory_options::follow_directory_symlink |
|
||||
fs::directory_options::skip_permission_denied,
|
||||
ec
|
||||
})
|
||||
{
|
||||
// Ignore all hidden files
|
||||
if (dp->d_name[0] == '.')
|
||||
continue;
|
||||
const auto& path = entry.path();
|
||||
|
||||
string newPath(_path);
|
||||
if (newPath.length() > 0 && newPath[newPath.length()-1] != '/')
|
||||
newPath += '/';
|
||||
newPath += dp->d_name;
|
||||
|
||||
FSNodePOSIX entry(newPath, false);
|
||||
|
||||
#if defined(SYSTEM_NOT_SUPPORTING_D_TYPE)
|
||||
/* TODO: d_type is not part of POSIX, so it might not be supported
|
||||
* on some of our targets. For those systems where it isn't supported,
|
||||
* add this #elif case, which tries to use stat() instead.
|
||||
*
|
||||
* The d_type method is used to avoid costly recurrent stat() calls in big
|
||||
* directories.
|
||||
*/
|
||||
entry.setFlags();
|
||||
#else
|
||||
if (dp->d_type == DT_UNKNOWN)
|
||||
{
|
||||
// Fall back to stat()
|
||||
entry.setFlags();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dp->d_type == DT_LNK)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(entry._path.c_str(), &st) == 0)
|
||||
{
|
||||
entry._isDirectory = S_ISDIR(st.st_mode);
|
||||
entry._isFile = S_ISREG(st.st_mode);
|
||||
}
|
||||
else
|
||||
entry._isDirectory = entry._isFile = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry._isDirectory = (dp->d_type == DT_DIR);
|
||||
entry._isFile = (dp->d_type == DT_REG);
|
||||
}
|
||||
|
||||
if (entry._isDirectory)
|
||||
entry._path += "/";
|
||||
|
||||
entry._isValid = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Skip files that are invalid for some reason (e.g. because we couldn't
|
||||
// properly stat them).
|
||||
if (!entry._isValid)
|
||||
// Ignore files with errors, or any that start with '.'
|
||||
if (ec || path.filename().string()[0] == '.')
|
||||
continue;
|
||||
|
||||
// Honor the chosen mode
|
||||
if ((mode == FSNode::ListMode::FilesOnly && !entry._isFile) ||
|
||||
(mode == FSNode::ListMode::DirectoriesOnly && !entry._isDirectory))
|
||||
const bool isFile = entry.is_regular_file(),
|
||||
isDir = entry.is_directory();
|
||||
if ((mode == FSNode::ListMode::FilesOnly && !isFile) ||
|
||||
(mode == FSNode::ListMode::DirectoriesOnly && !isDir))
|
||||
continue;
|
||||
|
||||
myList.emplace_back(make_shared<FSNodePOSIX>(entry));
|
||||
// Only create the object and add it to the list when absolutely
|
||||
// necessary
|
||||
FSNodePOSIX node(path.string(), false);
|
||||
node._isFile = isFile;
|
||||
node._isDirectory = isDir;
|
||||
node._size = isFile ? entry.file_size() : 0;
|
||||
|
||||
const auto p = entry.status().permissions();
|
||||
node._isReadable = (p & (fs::perms::owner_read |
|
||||
fs::perms::group_read |
|
||||
fs::perms::others_read)) != fs::perms::none;
|
||||
node._isWriteable = (p & (fs::perms::owner_write |
|
||||
fs::perms::group_write |
|
||||
fs::perms::others_write)) != fs::perms::none;
|
||||
|
||||
myList.emplace_back(make_shared<FSNodePOSIX>(node));
|
||||
}
|
||||
closedir(dirp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
size_t FSNodePOSIX::getSize() const
|
||||
{
|
||||
struct stat st;
|
||||
return (stat(_path.c_str(), &st) == 0) ? st.st_size : 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
size_t FSNodePOSIX::read(ByteBuffer& buffer, size_t size) const
|
||||
{
|
||||
|
|
|
@ -75,7 +75,7 @@ class FSNodePOSIX : public AbstractFSNode
|
|||
bool makeDir() override;
|
||||
bool rename(const string& newfile) override;
|
||||
|
||||
size_t getSize() const override;
|
||||
size_t getSize() const override { return _size; }
|
||||
size_t read(ByteBuffer& buffer, size_t size) const override;
|
||||
size_t read(stringstream& buffer) const override;
|
||||
size_t write(const ByteBuffer& buffer, size_t size) const override;
|
||||
|
@ -87,13 +87,13 @@ class FSNodePOSIX : public AbstractFSNode
|
|||
protected:
|
||||
fs::path _fspath;
|
||||
string _path, _displayName;
|
||||
bool _isValid{false}, _isFile{false}, _isDirectory{false},
|
||||
bool _isFile{false}, _isDirectory{false},
|
||||
_isReadable{false}, _isWriteable{false};
|
||||
size_t _size{0};
|
||||
|
||||
private:
|
||||
/**
|
||||
* Tests and sets the _isValid and _isDirectory/_isFile flags,
|
||||
* using the stat() function.
|
||||
* Tests and sets the various flags for a file/directory.
|
||||
*/
|
||||
void setFlags();
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue