summaryrefslogtreecommitdiff
path: root/src/fs/virtfs
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2017-04-24 17:04:47 +0300
committerAndrei Karas <akaras@inbox.ru>2017-04-24 17:04:47 +0300
commitd1b635ebf238fac5911fde8982d067ee4ffffe3a (patch)
tree788b6c6733550f5a54d5b3552a909a141af1223c /src/fs/virtfs
parent0835e09ee3a6c83ffa01454f2c05597e6195b07d (diff)
downloadmv-d1b635ebf238fac5911fde8982d067ee4ffffe3a.tar.gz
mv-d1b635ebf238fac5911fde8982d067ee4ffffe3a.tar.bz2
mv-d1b635ebf238fac5911fde8982d067ee4ffffe3a.tar.xz
mv-d1b635ebf238fac5911fde8982d067ee4ffffe3a.zip
Improve VirtFs::getDirs.
Diffstat (limited to 'src/fs/virtfs')
-rw-r--r--src/fs/virtfs/virtfs.cpp22
-rw-r--r--src/fs/virtfs/virtfs.h4
-rw-r--r--src/fs/virtfs/virtfs1_unittest.cc77
-rw-r--r--src/fs/virtfs/virtfsdir.cpp49
-rw-r--r--src/fs/virtfs/virtfsdir.h3
-rw-r--r--src/fs/virtfs/virtfsfuncs.h3
-rw-r--r--src/fs/virtfs/virtfstools.cpp11
-rw-r--r--src/fs/virtfs/virtfstools.h2
-rw-r--r--src/fs/virtfs/virtfszip.cpp93
-rw-r--r--src/fs/virtfs/virtfszip.h3
10 files changed, 252 insertions, 15 deletions
diff --git a/src/fs/virtfs/virtfs.cpp b/src/fs/virtfs/virtfs.cpp
index e61069301..b4807afe7 100644
--- a/src/fs/virtfs/virtfs.cpp
+++ b/src/fs/virtfs/virtfs.cpp
@@ -183,6 +183,28 @@ namespace VirtFs
}
}
+ void getDirs(std::string dirName,
+ StringVect &list)
+ {
+ prepareFsPath(dirName);
+ if (checkPath(dirName) == false)
+ {
+ reportAlways("VirtFs::enumerateFiles invalid path: %s",
+ dirName.c_str());
+ return;
+ }
+
+ std::string rootDir = dirName;
+ if (findLast(rootDir, std::string(dirSeparator)) == false)
+ rootDir += dirSeparator;
+
+ FOR_EACH (std::vector<VirtFsEntry*>::const_iterator, it, mEntries)
+ {
+ VirtFsEntry *const entry = *it;
+ entry->funcs->getDirs(entry, rootDir, list);
+ }
+ }
+
bool isDirectory(std::string name)
{
prepareFsPath(name);
diff --git a/src/fs/virtfs/virtfs.h b/src/fs/virtfs/virtfs.h
index 7f9600b88..5046f4675 100644
--- a/src/fs/virtfs/virtfs.h
+++ b/src/fs/virtfs/virtfs.h
@@ -94,8 +94,10 @@ namespace VirtFs
#endif // UNITTESTS
const char *loadFile(std::string filename,
int &restrict fileSize);
- void getFiles(std::string path,
+ void getFiles(std::string dirName,
StringVect &list);
+ void getDirs(std::string dirName,
+ StringVect &list);
} // namespace VirtFs
extern const char *dirSeparator;
diff --git a/src/fs/virtfs/virtfs1_unittest.cc b/src/fs/virtfs/virtfs1_unittest.cc
index a267f2b5a..23255e0c5 100644
--- a/src/fs/virtfs/virtfs1_unittest.cc
+++ b/src/fs/virtfs/virtfs1_unittest.cc
@@ -1935,13 +1935,88 @@ TEST_CASE("VirtFs1 getFiles zip")
list.clear();
VirtFs::getFiles("dir2", list);
+ REQUIRE(list.size() == 4);
REQUIRE(inList(list, "hide.png"));
REQUIRE(inList(list, "paths.xml"));
REQUIRE(inList(list, "test.txt"));
REQUIRE(inList(list, "units.xml"));
- REQUIRE(list.size() == 4);
VirtFs::unmountZip(prefix + "data/test/test2.zip");
VirtFs::deinit();
delete2(logger);
}
+
+TEST_CASE("VirtFs1 getDirs1")
+{
+ VirtFs::init(".");
+ logger = new Logger();
+ std::string name("data/test/test.zip");
+ std::string prefix;
+ if (Files::existsLocal(name) == false)
+ prefix = "../" + prefix;
+
+ VirtFs::mountZip(prefix + "data/test/test2.zip",
+ Append_false);
+
+ StringVect list;
+ VirtFs::getDirs("dir", list);
+ REQUIRE(list.size() == 2);
+ REQUIRE(inList(list, "1"));
+ REQUIRE(inList(list, "gpl"));
+ list.clear();
+
+ VirtFs::getDirs("dir2", list);
+ REQUIRE(list.size() == 0);
+
+ VirtFs::unmountZip(prefix + "data/test/test2.zip");
+ VirtFs::deinit();
+ delete2(logger);
+}
+
+TEST_CASE("VirtFs1 getDirs2")
+{
+ VirtFs::init(".");
+ logger = new Logger();
+ std::string name("data/test/test.zip");
+ std::string prefix;
+ if (Files::existsLocal(name) == false)
+ prefix = "../" + prefix;
+ StringVect list;
+
+ SECTION("dir1")
+ {
+ VirtFs::mountDir(prefix + "data/test",
+ Append_false);
+
+ VirtFs::getDirs("/", list);
+// REQUIRE(list.size() == 2);
+ REQUIRE(inList(list, "dir1"));
+ REQUIRE(inList(list, "dir2"));
+ list.clear();
+
+ VirtFs::getDirs("dir1", list);
+ REQUIRE(list.size() == 0);
+
+ VirtFs::unmountDir(prefix + "data/test");
+ }
+
+ SECTION("dir2")
+ {
+ VirtFs::mountDir(prefix + "data",
+ Append_false);
+
+ VirtFs::getDirs("sfx", list);
+ REQUIRE(inList(list, "system"));
+ list.clear();
+
+ VirtFs::getDirs("evol", list);
+ REQUIRE(list.size() == 2);
+ REQUIRE(inList(list, "icons"));
+ REQUIRE(inList(list, "images"));
+
+ VirtFs::unmountDir(prefix + "data");
+ }
+
+ VirtFs::deinit();
+ delete2(logger);
+}
diff --git a/src/fs/virtfs/virtfsdir.cpp b/src/fs/virtfs/virtfsdir.cpp
index 2d165195e..967c80610 100644
--- a/src/fs/virtfs/virtfsdir.cpp
+++ b/src/fs/virtfs/virtfsdir.cpp
@@ -138,6 +138,7 @@ namespace VirtFsDir
ptr->openAppend = &VirtFsDir::openAppend;
ptr->loadFile = &VirtFsDir::loadFile;
ptr->getFiles = &VirtFsDir::getFiles;
+ ptr->getDirs = &VirtFsDir::getDirs;
ptr->rwops_seek = &VirtFsDir::rwops_seek;
ptr->rwops_read = &VirtFsDir::rwops_read;
ptr->rwops_write = &VirtFsDir::rwops_write;
@@ -562,4 +563,52 @@ namespace VirtFsDir
}
}
+ void getDirs(VirtFsEntry *restrict const entry,
+ const std::string &dirName,
+ StringVect &names)
+ {
+ const std::string path = entry->root + dirName;
+ const struct dirent *next_file = nullptr;
+ DIR *const dir = opendir(path.c_str());
+ if (dir)
+ {
+ while ((next_file = readdir(dir)))
+ {
+ struct stat statbuf;
+ const std::string file = next_file->d_name;
+ if (file == "." || file == "..")
+ continue;
+#ifndef WIN32
+ if (mPermitLinks == false)
+ {
+ if (lstat(path.c_str(), &statbuf) == 0 &&
+ S_ISLNK(statbuf.st_mode) != 0)
+ {
+ continue;
+ }
+ }
+#endif // WIN32
+
+ const std::string filePath = pathJoin(path, file);
+ if (stat(filePath.c_str(), &statbuf) == 0)
+ {
+ if (S_ISDIR(statbuf.st_mode) == 0)
+ continue;
+ }
+
+ bool found(false);
+ FOR_EACH (StringVectCIter, itn, names)
+ {
+ if (*itn == file)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found == false)
+ names.push_back(file);
+ }
+ closedir(dir);
+ }
+ }
} // namespace VirtFs
diff --git a/src/fs/virtfs/virtfsdir.h b/src/fs/virtfs/virtfsdir.h
index 2a7829bb1..74bf569bf 100644
--- a/src/fs/virtfs/virtfsdir.h
+++ b/src/fs/virtfs/virtfsdir.h
@@ -58,6 +58,9 @@ namespace VirtFsDir
void getFiles(VirtFsEntry *restrict const entry,
const std::string &dirName,
StringVect &names);
+ void getDirs(VirtFsEntry *restrict const entry,
+ const std::string &dirName,
+ StringVect &names);
bool isDirectory(VirtFsEntry *restrict const entry,
const std::string &dirName,
bool &isDirFlag);
diff --git a/src/fs/virtfs/virtfsfuncs.h b/src/fs/virtfs/virtfsfuncs.h
index 47d765c5c..f8c69e125 100644
--- a/src/fs/virtfs/virtfsfuncs.h
+++ b/src/fs/virtfs/virtfsfuncs.h
@@ -88,6 +88,9 @@ struct VirtFsFuncs final
void (*getFiles) (VirtFsEntry *restrict const entry,
const std::string &dirName,
StringVect &names);
+ void (*getDirs) (VirtFsEntry *restrict const entry,
+ const std::string &dirName,
+ StringVect &names);
bool (*isDirectory) (VirtFsEntry *restrict const entry,
const std::string &dirName,
bool &isDirFlag);
diff --git a/src/fs/virtfs/virtfstools.cpp b/src/fs/virtfs/virtfstools.cpp
index 12b261320..be634b89c 100644
--- a/src/fs/virtfs/virtfstools.cpp
+++ b/src/fs/virtfs/virtfstools.cpp
@@ -104,17 +104,6 @@ namespace VirtFs
std::sort(list.begin(), list.end());
}
- void getDirs(const std::string &path, StringVect &list)
- {
- VirtList *const fonts = VirtFs::enumerateFiles(path);
- FOR_EACH (StringVectCIter, i, fonts->names)
- {
- if (VirtFs::isDirectory(pathJoin(path, *i)))
- list.push_back(*i);
- }
- VirtFs::freeList(fonts);
- }
-
std::string getPath(const std::string &file)
{
// get the real path to the file
diff --git a/src/fs/virtfs/virtfstools.h b/src/fs/virtfs/virtfstools.h
index fe9eb7ecf..8385920cc 100644
--- a/src/fs/virtfs/virtfstools.h
+++ b/src/fs/virtfs/virtfstools.h
@@ -39,8 +39,6 @@ namespace VirtFs
const std::string &ext);
void getFilesWithDir(const std::string &restrict path,
StringVect &restrict list);
- void getDirs(const std::string &path,
- StringVect &list);
std::string getPath(const std::string &file);
bool loadTextFile(const std::string &fileName,
StringVect &lines);
diff --git a/src/fs/virtfs/virtfszip.cpp b/src/fs/virtfs/virtfszip.cpp
index ae31f2606..bf7e8fba2 100644
--- a/src/fs/virtfs/virtfszip.cpp
+++ b/src/fs/virtfs/virtfszip.cpp
@@ -75,6 +75,7 @@ namespace VirtFsZip
ptr->openAppend = &VirtFsZip::openAppend;
ptr->loadFile = &VirtFsZip::loadFile;
ptr->getFiles = &VirtFsZip::getFiles;
+ ptr->getDirs = &VirtFsZip::getDirs;
ptr->rwops_seek = &VirtFsZip::rwops_seek;
ptr->rwops_read = &VirtFsZip::rwops_read;
ptr->rwops_write = &VirtFsZip::rwops_write;
@@ -287,6 +288,98 @@ namespace VirtFsZip
}
}
+ void getDirs(VirtFsEntry *restrict const entry,
+ const std::string &dirName,
+ StringVect &names)
+ {
+ VirtZipEntry *const zipEntry = static_cast<VirtZipEntry*>(entry);
+ if (dirName == dirSeparator)
+ {
+ FOR_EACH (std::vector<ZipLocalHeader*>::const_iterator,
+ it2,
+ zipEntry->mHeaders)
+ {
+ ZipLocalHeader *const header = *it2;
+ std::string fileName = header->fileName;
+ // skip subdirs from enumeration
+ const size_t idx = fileName.find(dirSeparator);
+ if (idx != std::string::npos)
+ fileName.erase(idx);
+ bool found(false);
+ FOR_EACH (StringVectCIter, itn, names)
+ {
+ if (*itn == fileName)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found == false)
+ {
+ std::string dirName2 = pathJoin(dirName, fileName);
+ if (findLast(dirName2, std::string(dirSeparator)) == false)
+ dirName2 += dirSeparator;
+ FOR_EACH (std::vector<std::string>::const_iterator,
+ it,
+ zipEntry->mDirs)
+ {
+ if (*it == dirName2)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found == true)
+ names.push_back(fileName);
+ }
+ }
+ }
+ else
+ {
+ FOR_EACH (std::vector<ZipLocalHeader*>::const_iterator,
+ it2,
+ zipEntry->mHeaders)
+ {
+ ZipLocalHeader *const header = *it2;
+ std::string fileName = header->fileName;
+ if (findCutFirst(fileName, dirName) == true)
+ {
+ // skip subdirs from enumeration
+ const size_t idx = fileName.find(dirSeparator);
+ if (idx != std::string::npos)
+ fileName.erase(idx);
+ bool found(false);
+ FOR_EACH (StringVectCIter, itn, names)
+ {
+ if (*itn == fileName)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found == false)
+ {
+ std::string dirName2 = pathJoin(dirName, fileName);
+ if (findLast(dirName2, std::string(dirSeparator)) == false)
+ dirName2 += dirSeparator;
+ FOR_EACH (std::vector<std::string>::const_iterator,
+ it,
+ zipEntry->mDirs)
+ {
+ if (*it == dirName2)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found == true)
+ names.push_back(fileName);
+ }
+ }
+ }
+ }
+ }
+
bool isDirectory(VirtFsEntry *restrict const entry,
const std::string &dirName,
bool &isDirFlag)
diff --git a/src/fs/virtfs/virtfszip.h b/src/fs/virtfs/virtfszip.h
index 8efa82a50..3ae74cc95 100644
--- a/src/fs/virtfs/virtfszip.h
+++ b/src/fs/virtfs/virtfszip.h
@@ -45,6 +45,9 @@ namespace VirtFsZip
void getFiles(VirtFsEntry *restrict const entry,
const std::string &dirName,
StringVect &names);
+ void getDirs(VirtFsEntry *restrict const entry,
+ const std::string &dirName,
+ StringVect &names);
bool isDirectory(VirtFsEntry *restrict const entry,
const std::string &dirName,
bool &isDirFlag);