aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Marshall <tdm.code@gmail.com>2018-02-16 21:44:03 +0100
committerTom Marshall <tdm.code@gmail.com>2018-02-26 20:08:24 +0100
commit570abd86c250686d2a125e654a36fe97ecd3b230 (patch)
treef8775211d212c7902650df9f79b53e50a5a030a6
parentba8fc2c1e62f40291501d2deb8be9ccdc40e14d7 (diff)
downloadandroid_build_kati-lineage-15.1.tar.gz
android_build_kati-lineage-15.1.tar.bz2
android_build_kati-lineage-15.1.zip
Fix findleaves emulator with symlink loopslineage-15.1
This updates the findleaves emulator to match the change "findleaves.py: prevent recursion into symlink loops" Also update findleaves.py to match build/make/tools/findleaves.py Change-Id: I20cf63c7b4e1a8a7b7fa8b4bde04ae821d5d98ea
-rw-r--r--find.cc15
-rw-r--r--find.h24
-rwxr-xr-xtestcase/tools/findleaves.py13
3 files changed, 51 insertions, 1 deletions
diff --git a/find.cc b/find.cc
index c36c468..33d9445 100644
--- a/find.cc
+++ b/find.cc
@@ -277,6 +277,18 @@ class DirentDirNode : public DirentNode {
return true;
}
+ if (fc.type == FindCommandType::FINDLEAVES) {
+ struct stat st;
+ if (stat(path->c_str(), &st)) {
+ PERROR("stat for %s", path->c_str());
+ }
+ devino di(st.st_dev, st.st_ino);
+ if (fc.read_inos->find(di) != fc.read_inos->end()) {
+ return true;
+ }
+ fc.read_inos->insert(di);
+ }
+
fc.read_dirs->insert(*path);
if (fc.prune_cond && fc.prune_cond->IsTrue(*path, DT_DIR)) {
@@ -1046,7 +1058,8 @@ FindCommand::FindCommand()
: follows_symlinks(false), depth(INT_MAX), mindepth(INT_MIN),
redirect_to_devnull(false),
found_files(new vector<string>()),
- read_dirs(new unordered_set<string>()) {
+ read_dirs(new unordered_set<string>()),
+ read_inos(new unordered_set<devino>()) {
}
FindCommand::~FindCommand() {
diff --git a/find.h b/find.h
index 9af261a..81c30b5 100644
--- a/find.h
+++ b/find.h
@@ -15,6 +15,8 @@
#ifndef FIND_H_
#define FIND_H_
+#include <sys/stat.h>
+
#include <memory>
#include <string>
#include <unordered_set>
@@ -33,6 +35,27 @@ enum struct FindCommandType {
LS,
};
+class devino {
+public:
+ devino(dev_t dev, ino_t ino) : dev_(dev), ino_(ino) {}
+ bool operator==(const devino& other) const {
+ return (dev_ == other.dev_ && ino_ == other.ino_);
+ }
+ dev_t dev() const { return dev_; }
+ ino_t ino() const { return ino_; }
+
+private:
+ dev_t dev_;
+ ino_t ino_;
+};
+
+namespace std {
+template<>
+struct hash<devino> {
+ std::size_t operator()(const devino& k) const { return (k.dev() ^ k.ino()); }
+};
+}
+
struct FindCommand {
FindCommand();
~FindCommand();
@@ -52,6 +75,7 @@ struct FindCommand {
unique_ptr<vector<string>> found_files;
unique_ptr<unordered_set<string>> read_dirs;
+ unique_ptr<unordered_set<devino>> read_inos;
private:
FindCommand(const FindCommand&) = delete;
diff --git a/testcase/tools/findleaves.py b/testcase/tools/findleaves.py
index 72cc024..f152a87 100755
--- a/testcase/tools/findleaves.py
+++ b/testcase/tools/findleaves.py
@@ -26,6 +26,7 @@ import sys
def perform_find(mindepth, prune, dirlist, filenames):
result = []
pruneleaves = set(map(lambda x: os.path.split(x)[1], prune))
+ seen = set()
for rootdir in dirlist:
rootdepth = rootdir.count("/")
for root, dirs, files in os.walk(rootdir, followlinks=True):
@@ -52,6 +53,18 @@ def perform_find(mindepth, prune, dirlist, filenames):
if filename in files:
result.append(os.path.join(root, filename))
del dirs[:]
+
+ # filter out inodes that have already been seen due to symlink loops
+ i = 0
+ while i < len(dirs):
+ st = os.stat(os.path.join(root, dirs[i]))
+ key = (st.st_dev, st.st_ino)
+ if key in seen:
+ del dirs[i]
+ else:
+ i += 1
+ seen.add(key)
+
return result
def usage():