aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/fs/posix/posix-fs.cpp7
-rw-r--r--common/fs.cpp82
-rw-r--r--common/fs.h37
3 files changed, 125 insertions, 1 deletions
diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp
index c976830402..385bab833c 100644
--- a/backends/fs/posix/posix-fs.cpp
+++ b/backends/fs/posix/posix-fs.cpp
@@ -174,8 +174,13 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo
// loop over dir entries using readdir
while ((dp = readdir(dirp)) != NULL) {
// Skip 'invisible' files if necessary
- if (dp->d_name[0] == '.' && !hidden)
+ if (dp->d_name[0] == '.' && !hidden) {
continue;
+ }
+ // Skip '.' and '..' to avoid cycles
+ if((dp->d_name[0] == '.' && dp->d_name[1] == 0) || (dp->d_name[0] == '.' && dp->d_name[1] == '.')) {
+ continue;
+ }
String newPath(_path);
if (newPath.lastChar() != '/')
diff --git a/common/fs.cpp b/common/fs.cpp
index 6eaa35e67f..28f3e11f0b 100644
--- a/common/fs.cpp
+++ b/common/fs.cpp
@@ -27,6 +27,43 @@
#include "backends/fs/abstract-fs.h"
#include "backends/fs/fs-factory-maker.cpp"
+/*
+ * Simple DOS-style pattern matching function (understands * and ? like used in DOS).
+ * Taken from exult/files/listfiles.cc
+ */
+static bool matchString(const char *str, const char *pat) {
+ const char *p = 0;
+ const char *q = 0;
+
+ for (;;) {
+ switch (*pat) {
+ case '*':
+ p = ++pat;
+ q = str;
+ break;
+
+ default:
+ if (*pat != *str) {
+ if (p) {
+ pat = p;
+ str = ++q;
+ if(!*str)
+ return !*pat;
+ break;
+ }
+ else
+ return false;
+ }
+ // fallthrough
+ case '?':
+ if(!*str)
+ return !*pat;
+ pat++;
+ str++;
+ }
+ }
+}
+
FilesystemNode::FilesystemNode() {
_realNode = 0;
_refCount = 0;
@@ -166,3 +203,48 @@ bool FilesystemNode::isWritable() const {
return false;
return _realNode->isWritable();
}
+
+bool FilesystemNode::lookupFile(FSList &results, FSList &fslist, Common::String &filename, bool hidden, bool exhaustive) const
+{
+ for(FSList::iterator entry = fslist.begin(); entry != fslist.end(); ++entry)
+ {
+ if(entry->isDirectory()) {
+ lookupFileRec(results, *entry, filename, hidden, exhaustive);
+ }
+ }
+
+ //TODO: we would return true even if no matches were found, if the initial results list isn't empty
+ return ((results.size() > 0) ? true : false);
+}
+
+bool FilesystemNode::lookupFile(FSList &results, FilesystemNode &dir, Common::String &filename, bool hidden, bool exhaustive) const
+{
+ lookupFileRec(results, dir, filename, hidden, exhaustive);
+
+ //TODO: we would return true even if no matches were found, if the initial results list isn't empty
+ return ((results.size() > 0) ? true : false);
+}
+
+void FilesystemNode::lookupFileRec(FSList &results, FilesystemNode &dir, Common::String &filename, bool hidden, bool exhaustive) const
+{
+ FSList entries;
+ dir.getChildren(entries, FilesystemNode::kListAll, hidden);
+
+ for(FSList::iterator entry = entries.begin(); entry != entries.end(); ++entry)
+ {
+ if(entry->isDirectory()) {
+ lookupFileRec(results, *entry, filename, hidden, exhaustive);
+ } else {
+ //TODO: here we assume all backends implement the lastPathComponent method. It is currently static,
+ // so it might be a good idea to include it inside the backend class. This would enforce its
+ // implementation by all ports.
+ if(matchString(lastPathComponent(entry->getPath()), filename.c_str())) {
+ results.push_back(*entry);
+
+ if(!exhaustive) {
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/common/fs.h b/common/fs.h
index 7291fb75fc..6a2f049be1 100644
--- a/common/fs.h
+++ b/common/fs.h
@@ -196,6 +196,32 @@ public:
* Indicates whether this path can be written to or not.
*/
virtual bool isWritable() const;
+
+ /**
+ * Searches recursively for a filename inside the given directories.
+ *
+ * @param results List to put the matches in.
+ * @param fslist List of directories to search within.
+ * @param filename Name of the file to look for.
+ * @param hidden Whether to search hidden files or not. Default: false
+ * @param exhaustive Whether to continue searching after one match has been found. Default: false
+ *
+ * @return true if matches could be found, false otherwise.
+ */
+ virtual bool lookupFile(FSList &results, FSList &fslist, Common::String &filename, bool hidden, bool exhaustive) const;
+
+ /**
+ * Searches recursively for a filename inside the given directory.
+ *
+ * @param results List to put the matches in.
+ * @param FilesystemNode Directory to search within.
+ * @param filename Name of the file to look for.
+ * @param hidden Whether to search hidden files or not. Default: false
+ * @param exhaustive Whether to continue searching after one match has been found. Default: false
+ *
+ * @return true if matches could be found, false otherwise.
+ */
+ virtual bool lookupFile(FSList &results, FilesystemNode &dir, Common::String &filename, bool hidden, bool exhaustive) const;
protected:
/**
@@ -203,6 +229,17 @@ protected:
* deletes the corresponding underlying references.
*/
void decRefCount();
+
+ /**
+ * Searches recursively for a filename inside the given directory.
+ *
+ * @param results List to put the matches in.
+ * @param FilesystemNode Directory to search within.
+ * @param filename Name of the file to look for.
+ * @param hidden Whether to search hidden files or not.
+ * @param exhaustive Whether to continue searching after one match has been found.
+ */
+ void lookupFileRec(FSList &results, FilesystemNode &dir, Common::String &filename, bool hidden, bool exhaustive) const;
};
//} // End of namespace Common