diff options
author | Tom Marshall <tdm.code@gmail.com> | 2018-02-16 21:44:03 +0100 |
---|---|---|
committer | Tom Marshall <tdm.code@gmail.com> | 2018-02-26 20:08:24 +0100 |
commit | 570abd86c250686d2a125e654a36fe97ecd3b230 (patch) | |
tree | f8775211d212c7902650df9f79b53e50a5a030a6 | |
parent | ba8fc2c1e62f40291501d2deb8be9ccdc40e14d7 (diff) | |
download | android_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.cc | 15 | ||||
-rw-r--r-- | find.h | 24 | ||||
-rwxr-xr-x | testcase/tools/findleaves.py | 13 |
3 files changed, 51 insertions, 1 deletions
@@ -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() { @@ -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(): |