BACKENDS: Add possibility to specify virtual drive in ChRootFilesystemFactory

It allows to get access to additional directories outside of the sandbox root.
This is used on iOS to access files in the app bundle.
This commit is contained in:
Thierry Crozat 2023-03-19 23:30:11 +00:00 committed by Eugene Sandulenko
parent 9bf4f3609a
commit 148892f102
No known key found for this signature in database
GPG key ID: 014D387312D34F08
5 changed files with 47 additions and 14 deletions

View file

@ -47,16 +47,31 @@ AbstractFSNode *ChRootFilesystemFactory::makeCurrentDirectoryFileNode() const {
return NULL;
}
if (Common::String(buf).hasPrefix(_root + Common::String("/"))) {
Common::String curPath(buf);
if (curPath.hasPrefix(_root + Common::String("/"))) {
return new ChRootFilesystemNode(_root, buf + _root.size());
}
for (auto it = _virtualDrives.begin() ; it != _virtualDrives.end() ; ++it) {
if (curPath.hasPrefix(it->_value + Common::String("/")))
return new ChRootFilesystemNode(it->_value, buf + it->_value.size(), it->_key);
}
return new ChRootFilesystemNode(_root, "/");
}
AbstractFSNode *ChRootFilesystemFactory::makeFileNodePath(const Common::String &path) const {
assert(!path.empty());
size_t driveEnd = path.findFirstOf('/');
if (driveEnd != Common::String::npos && driveEnd > 0) {
auto it = _virtualDrives.find(path.substr(0, driveEnd));
if (it != _virtualDrives.end())
return new ChRootFilesystemNode(it->_value, path.substr(driveEnd), it->_key);
}
return new ChRootFilesystemNode(_root, path);
}
void ChRootFilesystemFactory::addVirtualDrive(const Common::String &name, const Common::String &path) {
_virtualDrives[name] = path;
}
#endif

View file

@ -37,9 +37,12 @@ public:
AbstractFSNode *makeRootFileNode() const override;
AbstractFSNode *makeCurrentDirectoryFileNode() const override;
AbstractFSNode *makeFileNodePath(const Common::String &path) const override;
void addVirtualDrive(const Common::String &name, const Common::String &path);
private:
const Common::String _root;
Common::StringMap _virtualDrives;
};
#endif /* BACKENDS_FS_CHROOT_CHROOT_FS_FACTORY_H */

View file

@ -23,13 +23,15 @@
#include "backends/fs/chroot/chroot-fs.h"
ChRootFilesystemNode::ChRootFilesystemNode(const Common::String &root, POSIXFilesystemNode *node) {
ChRootFilesystemNode::ChRootFilesystemNode(const Common::String &root, POSIXFilesystemNode *node, const Common::String &drive) {
_root = Common::normalizePath(root, '/');
_drive = drive;
_realNode = node;
}
ChRootFilesystemNode::ChRootFilesystemNode(const Common::String &root, const Common::String &path) {
ChRootFilesystemNode::ChRootFilesystemNode(const Common::String &root, const Common::String &path, const Common::String &drive) {
_root = Common::normalizePath(root, '/');
_drive = drive;
_realNode = new POSIXFilesystemNode(addPathComponent(root, path));
}
@ -51,10 +53,9 @@ Common::String ChRootFilesystemNode::getName() const {
Common::String ChRootFilesystemNode::getPath() const {
Common::String path = _realNode->getPath();
if (path.size() > _root.size()) {
return Common::String(path.c_str() + _root.size());
}
return Common::String("/");
if (path.size() > _root.size())
return _drive + Common::String(path.c_str() + _root.size());
return _drive + "/";
}
bool ChRootFilesystemNode::isDirectory() const {
@ -66,11 +67,14 @@ bool ChRootFilesystemNode::isReadable() const {
}
bool ChRootFilesystemNode::isWritable() const {
// Assume virtual drives are not writable
if (!_drive.empty())
return false;
return _realNode->isWritable();
}
AbstractFSNode *ChRootFilesystemNode::getChild(const Common::String &n) const {
return new ChRootFilesystemNode(_root, (POSIXFilesystemNode *)_realNode->getChild(n));
return new ChRootFilesystemNode(_root, (POSIXFilesystemNode *)_realNode->getChild(n), _drive);
}
bool ChRootFilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool hidden) const {
@ -80,15 +84,16 @@ bool ChRootFilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool
}
for (AbstractFSList::iterator i=tmp.begin(); i!=tmp.end(); ++i) {
list.push_back(new ChRootFilesystemNode(_root, (POSIXFilesystemNode *) *i));
list.push_back(new ChRootFilesystemNode(_root, (POSIXFilesystemNode *) *i, _drive));
}
return true;
}
AbstractFSNode *ChRootFilesystemNode::getParent() const {
if (getPath() == "/") return 0;
return new ChRootFilesystemNode(_root, (POSIXFilesystemNode *)_realNode->getParent());
if (getPath() == _drive + "/")
return nullptr;
return new ChRootFilesystemNode(_root, (POSIXFilesystemNode *)_realNode->getParent(), _drive);
}
Common::SeekableReadStream *ChRootFilesystemNode::createReadStream() {

View file

@ -26,12 +26,13 @@
class ChRootFilesystemNode final : public AbstractFSNode {
Common::String _root;
Common::String _drive;
POSIXFilesystemNode *_realNode;
ChRootFilesystemNode(const Common::String &root, POSIXFilesystemNode *);
ChRootFilesystemNode(const Common::String &root, POSIXFilesystemNode *, const Common::String &drive);
public:
ChRootFilesystemNode(const Common::String &root, const Common::String &path);
ChRootFilesystemNode(const Common::String &root, const Common::String &path, const Common::String &drive = Common::String());
~ChRootFilesystemNode() override;
bool exists() const override;

View file

@ -97,7 +97,16 @@ OSystem_iOS7::OSystem_iOS7() :
_touchpadModeEnabled = !iOS7_isBigDevice();
#ifdef IPHONE_SANDBOXED
_chrootBasePath = iOS7_getDocumentsDir();
_fsFactory = new ChRootFilesystemFactory(_chrootBasePath);
ChRootFilesystemFactory *chFsFactory = new ChRootFilesystemFactory(_chrootBasePath);
_fsFactory = chFsFactory;
// Add virtual drive for bundle path
CFURLRef fileUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
if (fileUrl) {
UInt8 buf[MAXPATHLEN];
if (CFURLGetFileSystemRepresentation(fileUrl, true, buf, sizeof(buf)))
chFsFactory->addVirtualDrive("appbundle:", Common::String((const char *)buf));
CFRelease(fileUrl);
}
#else
_fsFactory = new POSIXFilesystemFactory();
#endif