summaryrefslogtreecommitdiff
path: root/src/fs/virtfs/virtfs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/virtfs/virtfs.cpp')
-rw-r--r--src/fs/virtfs/virtfs.cpp386
1 files changed, 331 insertions, 55 deletions
diff --git a/src/fs/virtfs/virtfs.cpp b/src/fs/virtfs/virtfs.cpp
index aa2f4d57c..2bd59a0a2 100644
--- a/src/fs/virtfs/virtfs.cpp
+++ b/src/fs/virtfs/virtfs.cpp
@@ -22,17 +22,22 @@
#include "fs/virtfs.h"
+#include "fs/files.h"
#include "fs/paths.h"
#include "fs/virtfile.h"
#include "fs/virtfsfuncs.h"
#include "fs/virtlist.h"
#include "fs/virtfs/virtdirentry.h"
-#include "fs/virtfs/virtfsentry.h"
+#include "fs/virtfs/virtfs.h"
#include "fs/virtfs/virtfsdir.h"
#include "fs/virtfs/virtfszip.h"
+#include "fs/virtfs/virtzipentry.h"
+#include "fs/virtfs/zip.h"
#include "utils/checkutils.h"
+#include "utils/dtor.h"
+#include "utils/stringutils.h"
#include "debug.h"
@@ -43,6 +48,12 @@ namespace
std::vector<VirtFsEntry*> mEntries;
} // namespace
+#ifdef UNITTESTS
+#define reportNonTests logger->log
+#else // UNITTESTS
+#define reportNonTests reportAlways
+#endif // UNITTESTS
+
namespace VirtFs
{
void init(const std::string &restrict name)
@@ -76,9 +87,57 @@ namespace VirtFs
return VirtFsDir::getUserDir();
}
- bool exists(const std::string &restrict name)
+ std::vector<VirtFsEntry*> &getEntries()
+ {
+ return mEntries;
+ }
+
+ VirtFsEntry *searchEntryByRootInternal(const std::string &restrict root)
+ {
+ FOR_EACH (std::vector<VirtFsEntry*>::const_iterator, it, mEntries)
+ {
+ if ((*it)->root == root)
+ return *it;
+ }
+ return nullptr;
+ }
+
+ VirtFsEntry *searchEntryInternal(const std::string &restrict root,
+ const FsEntryType type)
+ {
+ FOR_EACH (std::vector<VirtFsEntry*>::const_iterator, it, mEntries)
+ {
+ VirtFsEntry *const entry = *it;
+ if (entry->root == root &&
+ entry->type == type)
+ {
+ return *it;
+ }
+ }
+ return nullptr;
+ }
+
+ bool exists(std::string name)
{
- return VirtFsDir::exists(name) || VirtFsZip::exists(name);
+ prepareFsPath(name);
+ if (checkPath(name) == false)
+ {
+ reportAlways("VirtFsDir::exists invalid path: %s",
+ name.c_str());
+ return false;
+ }
+
+ std::string rootDir = name;
+ if (findLast(rootDir, std::string(dirSeparator)) == false)
+ rootDir += dirSeparator;
+
+ FOR_EACH (std::vector<VirtFsEntry*>::const_iterator, it, mEntries)
+ {
+ VirtFsEntry *const entry = *it;
+ if (entry->funcs->exists(entry, name, rootDir) == true)
+ return true;
+ }
+ return false;
}
VirtList *enumerateFiles(std::string dirName)
@@ -92,8 +151,17 @@ namespace VirtFs
return list;
}
- VirtFsDir::enumerateFiles(dirName, list);
- VirtFsZip::enumerateFiles(dirName, list);
+ std::string rootDir = dirName;
+ if (findLast(rootDir, std::string(dirSeparator)) == false)
+ rootDir += dirSeparator;
+ StringVect &names = list->names;
+
+ FOR_EACH (std::vector<VirtFsEntry*>::const_iterator, it, mEntries)
+ {
+ VirtFsEntry *const entry = *it;
+ entry->funcs->enumerate(entry, rootDir, names);
+ }
+
return list;
}
@@ -106,8 +174,20 @@ namespace VirtFs
name.c_str());
return false;
}
- return VirtFsDir::isDirectoryInternal(name) ||
- VirtFsZip::isDirectoryInternal(name);
+ std::string dirName = name;
+ if (findLast(dirName, std::string(dirSeparator)) == false)
+ dirName += dirSeparator;
+
+ FOR_EACH (std::vector<VirtFsEntry*>::const_iterator, it, mEntries)
+ {
+ VirtFsEntry *const entry = *it;
+ bool isDirFlag(false);
+ if (entry->funcs->isDirectory(entry, dirName, isDirFlag) == true)
+ {
+ return isDirFlag;
+ }
+ }
+ return false;
}
bool isSymbolicLink(const std::string &restrict name)
@@ -129,20 +209,52 @@ namespace VirtFs
filename.c_str());
return nullptr;
}
- VirtDirEntry *const entry = VirtFsDir::searchEntryByPath(filename);
- if (entry == nullptr)
- return VirtFsZip::openReadInternal(filename);
- return VirtFsDir::openReadDirEntry(entry, filename);
+ FOR_EACH (std::vector<VirtFsEntry*>::const_iterator, it, mEntries)
+ {
+ VirtFsEntry *const entry = *it;
+ VirtFile *const file = entry->funcs->openRead(entry, filename);
+ if (file != nullptr)
+ return file;
+ }
+ return nullptr;
}
- VirtFile *openWrite(const std::string &restrict filename)
+ VirtFile *openWrite(std::string filename)
{
- return VirtFsDir::openWrite(filename);
+ prepareFsPath(filename);
+ if (checkPath(filename) == false)
+ {
+ reportAlways("VirtFs::openWrite invalid path: %s",
+ filename.c_str());
+ return nullptr;
+ }
+ FOR_EACH (std::vector<VirtFsEntry*>::const_iterator, it, mEntries)
+ {
+ VirtFsEntry *const entry = *it;
+ VirtFile *const file = entry->funcs->openWrite(entry, filename);
+ if (file != nullptr)
+ return file;
+ }
+ return nullptr;
}
- VirtFile *openAppend(const std::string &restrict filename)
+ VirtFile *openAppend(std::string filename)
{
- return VirtFsDir::openAppend(filename);
+ prepareFsPath(filename);
+ if (checkPath(filename) == false)
+ {
+ reportAlways("VirtFs::openAppend invalid path: %s",
+ filename.c_str());
+ return nullptr;
+ }
+ FOR_EACH (std::vector<VirtFsEntry*>::const_iterator, it, mEntries)
+ {
+ VirtFsEntry *const entry = *it;
+ VirtFile *const file = entry->funcs->openAppend(entry, filename);
+ if (file != nullptr)
+ return file;
+ }
+ return nullptr;
}
bool setWriteDir(const std::string &restrict newDir)
@@ -150,72 +262,224 @@ namespace VirtFs
return VirtFsDir::setWriteDir(newDir);
}
- bool addDirToSearchPath(const std::string &restrict newDir,
+ void addEntry(VirtFsEntry *const entry,
+ const Append append)
+ {
+ if (append == Append_true)
+ mEntries.push_back(entry);
+ else
+ mEntries.insert(mEntries.begin(), entry);
+ }
+
+ bool addDirToSearchPathInternal(const std::string &restrict newDir,
+ const Append append)
+ {
+ if (newDir.find(".zip") != std::string::npos)
+ {
+ reportAlways("Called VirtFsDir::addToSearchPath with zip archive");
+ return false;
+ }
+ std::string rootDir = newDir;
+ if (findLast(rootDir, std::string(dirSeparator)) == false)
+ rootDir += dirSeparator;
+ VirtFsEntry *const entry = searchEntryByRootInternal(rootDir);
+ if (entry != nullptr)
+ {
+ reportAlways("VirtFs::addToSearchPath already exists: %s",
+ newDir.c_str());
+ return false;
+ }
+ logger->log("Add virtual directory: " + newDir);
+ addEntry(new VirtDirEntry(newDir, rootDir, VirtFsDir::getFuncs()),
+ append);
+ return true;
+ }
+
+ bool addDirToSearchPath(std::string newDir,
const Append append)
{
-#ifdef UNITTESTS
- return VirtFsDir::addToSearchPathSilent(newDir,
- append,
- SkipError_false);
-#else // UNITTESTS
- return VirtFsDir::addToSearchPath(newDir, append);
-#endif // UNITTESTS
+ prepareFsPath(newDir);
+ if (Files::existsLocal(newDir) == false)
+ {
+ reportNonTests("VirtFs::addToSearchPath directory not exists: %s",
+ newDir.c_str());
+ return false;
+ }
+ return addDirToSearchPathInternal(newDir, append);
}
- bool addDirToSearchPathSilent(const std::string &restrict newDir,
+ bool addDirToSearchPathSilent(std::string newDir,
const Append append)
{
- return VirtFsDir::addToSearchPathSilent(newDir,
- append,
- SkipError_false);
+ prepareFsPath(newDir);
+ if (Files::existsLocal(newDir) == false)
+ {
+ logger->log("VirtFs::addToSearchPath directory not exists: %s",
+ newDir.c_str());
+ return false;
+ }
+ return addDirToSearchPathInternal(newDir, append);
}
- bool removeDirFromSearchPath(const std::string &restrict oldDir)
- {
#ifdef UNITTESTS
- return VirtFsDir::removeFromSearchPathSilent(oldDir);
-#else // UNITTESTS
- return VirtFsDir::removeFromSearchPath(oldDir);
+ bool addDirToSearchPathSilent2(std::string newDir,
+ const Append append)
+ {
+ prepareFsPath(newDir);
+ if (Files::existsLocal(newDir) == false)
+ {
+ logger->log("VirtFs::addToSearchPath directory not exists: %s",
+ newDir.c_str());
+ }
+ return addDirToSearchPathInternal(newDir, append);
+ }
#endif // UNITTESTS
+
+ bool removeDirFromSearchPathInternal(std::string oldDir)
+ {
+ if (findLast(oldDir, std::string(dirSeparator)) == false)
+ oldDir += dirSeparator;
+ FOR_EACH (std::vector<VirtFsEntry*>::iterator, it, mEntries)
+ {
+ VirtFsEntry *const entry = *it;
+ if (entry->root == oldDir &&
+ entry->type == FsEntryType::Dir)
+ {
+ VirtDirEntry *const dirEntry = static_cast<VirtDirEntry*>(
+ entry);
+ logger->log("Remove virtual directory: " + oldDir);
+ mEntries.erase(it);
+ delete dirEntry;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool removeDirFromSearchPath(std::string oldDir)
+ {
+ prepareFsPath(oldDir);
+ if (oldDir.find(".zip") != std::string::npos)
+ {
+ reportAlways("Called removeFromSearchPath with zip archive");
+ return false;
+ }
+ if (removeDirFromSearchPathInternal(oldDir) == false)
+ {
+ reportAlways("VirtFs::removeDirFromSearchPath not exists: %s",
+ oldDir.c_str());
+ return false;
+ }
+ return true;
}
- bool removeDirFromSearchPathSilent(const std::string &restrict oldDir)
+ bool removeDirFromSearchPathSilent(std::string oldDir)
{
- return VirtFsDir::removeFromSearchPathSilent(oldDir);
+ prepareFsPath(oldDir);
+ if (oldDir.find(".zip") != std::string::npos)
+ {
+ reportAlways("Called removeFromSearchPath with zip archive");
+ return false;
+ }
+ if (removeDirFromSearchPathInternal(oldDir) == false)
+ {
+ logger->log("VirtFs::removeDirFromSearchPath not exists: %s",
+ oldDir.c_str());
+ return false;
+ }
+ return true;
}
- bool addZipToSearchPath(const std::string &restrict newDir,
+ bool addZipToSearchPath(std::string newDir,
const Append append)
{
-#ifdef UNITTESTS
- return VirtFsZip::addToSearchPathSilent(newDir, append);
-#else // UNITTESTS
- return VirtFsZip::addToSearchPath(newDir, append);
-#endif // UNITTESTS
+ prepareFsPath(newDir);
+ if (Files::existsLocal(newDir) == false)
+ {
+ reportNonTests("VirtFsZip::addToSearchPath file not exists: %s",
+ newDir.c_str());
+ return false;
+ }
+ if (findLast(newDir, ".zip") == false)
+ {
+ reportAlways("Called VirtFs::addToSearchPath without "
+ "zip archive");
+ return false;
+ }
+ if (searchEntryByRootInternal(newDir) != nullptr)
+ {
+ reportAlways("VirtFsZip::addToSearchPath already exists: %s",
+ newDir.c_str());
+ return false;
+ }
+ VirtZipEntry *const entry = new VirtZipEntry(newDir,
+ VirtFsZip::getFuncs());
+ if (Zip::readArchiveInfo(entry) == false)
+ {
+ delete entry;
+ return false;
+ }
+
+ logger->log("Add virtual zip: " + newDir);
+ addEntry(entry, append);
+ return true;
}
- bool removeZipFromSearchPath(const std::string &restrict oldDir)
+ bool removeZipFromSearchPath(std::string oldDir)
{
-#ifdef UNITTESTS
- return VirtFsZip::removeFromSearchPathSilent(oldDir);
-#else // UNITTESTS
- return VirtFsZip::removeFromSearchPath(oldDir);
-#endif // UNITTESTS
+ prepareFsPath(oldDir);
+ if (findLast(oldDir, ".zip") == false)
+ {
+ reportAlways("Called removeFromSearchPath without zip archive");
+ return false;
+ }
+ FOR_EACH (std::vector<VirtFsEntry*>::iterator, it, mEntries)
+ {
+ VirtFsEntry *const entry = *it;
+ if (entry->root == oldDir &&
+ entry->type == FsEntryType::Zip)
+ {
+ VirtZipEntry *const zipEntry = static_cast<VirtZipEntry*>(
+ entry);
+ logger->log("Remove virtual zip: " + oldDir);
+ mEntries.erase(it);
+ delete zipEntry;
+ return true;
+ }
+ }
+
+ reportAlways("VirtFs::removeZipFromSearchPath not exists: %s",
+ oldDir.c_str());
+ return false;
}
- std::string getRealDir(std::string filename)
+ std::string getRealDir(std::string fileName)
{
- prepareFsPath(filename);
- if (checkPath(filename) == false)
+ prepareFsPath(fileName);
+ if (checkPath(fileName) == false)
{
- reportAlways("VirtFs::getRealDir invalid path: %s",
- filename.c_str());
+ reportAlways("VirtFsDir::getRealDir invalid path: %s",
+ fileName.c_str());
return std::string();
}
- VirtDirEntry *const entry = VirtFsDir::searchEntryByPath(filename);
- if (entry == nullptr)
- return VirtFsZip::getRealDirInternal(filename);
- return entry->mUserDir;
+
+ std::string rootDir = fileName;
+ if (findLast(rootDir, std::string(dirSeparator)) == false)
+ rootDir += dirSeparator;
+
+ FOR_EACH (std::vector<VirtFsEntry*>::const_iterator, it, mEntries)
+ {
+ VirtFsEntry *const entry = *it;
+ std::string realDir;
+ if (entry->funcs->getRealDir(entry,
+ fileName,
+ rootDir,
+ realDir) == true)
+ {
+ return realDir;
+ }
+ }
+ return std::string();
}
bool mkdir(const std::string &restrict dirname)
@@ -232,6 +496,18 @@ namespace VirtFs
{
VirtFsDir::deinit();
VirtFsZip::deinit();
+ FOR_EACH (std::vector<VirtFsEntry*>::iterator, it, mEntries)
+ {
+ VirtFsEntry *const entry = *it;
+ if (entry->type == FsEntryType::Dir)
+ delete static_cast<VirtDirEntry*>(entry);
+ else if (entry->type == FsEntryType::Zip)
+ delete static_cast<VirtZipEntry*>(entry);
+ else
+ delete entry;
+ }
+// delete_all(mEntries);
+ mEntries.clear();
return true;
}