summaryrefslogtreecommitdiffstats
path: root/find_file.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'find_file.cpp')
-rw-r--r--find_file.cpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/find_file.cpp b/find_file.cpp
new file mode 100644
index 000000000..8ae0a51b4
--- /dev/null
+++ b/find_file.cpp
@@ -0,0 +1,90 @@
+/*
+ Copyright 2014 TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string>
+#include <vector>
+#include <dirent.h>
+#include "find_file.hpp"
+#include "twrp-functions.hpp"
+#include "twcommon.h"
+
+using namespace std;
+
+string Find_File::Find(const string& file_name, const string& start_path) {
+ return Find_File().Find_Internal(file_name, start_path);
+}
+
+Find_File::Find_File() {
+}
+
+string Find_File::Find_Internal(const string& filename, const string& starting_path) {
+ DIR *d;
+ string new_path, return_path;
+ vector<string> dirs;
+ vector<string> symlinks;
+ unsigned index;
+
+ // Check to see if we have already searched this directory to prevent infinite loops
+ if (std::find(searched_dirs.begin(), searched_dirs.end(), starting_path) != searched_dirs.end()) {
+ return "";
+ }
+ searched_dirs.push_back(starting_path);
+
+ d = opendir(starting_path.c_str());
+ if (d == NULL) {
+ LOGERR("Find_File: Error opening '%s'\n", starting_path.c_str());
+ return "";
+ }
+
+ struct dirent *p;
+ while ((p = readdir(d))) {
+ if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, ".."))
+ continue;
+ new_path = starting_path + "/";
+ new_path.append(p->d_name);
+ if (p->d_type == DT_DIR) {
+ // Add dir to search list for later
+ dirs.push_back(new_path);
+ } else if (p->d_type == DT_LNK) {
+ // Add symlink to search list for later
+ symlinks.push_back(new_path);
+ } else if (p->d_type == DT_REG && filename == p->d_name) {
+ // We found a match!
+ closedir(d);
+ return new_path;
+ }
+ }
+ closedir(d);
+
+ // Scan real directories first if no match found in this path
+ for (index = 0; index < dirs.size(); index++) {
+ return_path = Find_Internal(filename, dirs.at(index));
+ if (!return_path.empty()) return return_path;
+ }
+ // Scan symlinks after scanning real directories
+ for (index = 0; index < symlinks.size(); index++) {
+ char buf[PATH_MAX];
+ // Resolve symlink to a real path
+ char* ret = realpath(symlinks.at(index).c_str(), buf);
+ if (ret) {
+ return_path = Find_Internal(filename, buf);
+ if (!return_path.empty()) return return_path;
+ }
+ }
+ return "";
+}