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:
parent
9bf4f3609a
commit
148892f102
5 changed files with 47 additions and 14 deletions
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue