| #!/usr/bin/env python |
| # Copyright (C) 2018 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| # Takes output of |
| # adb shell 'find /data -print0 | xargs -0 ls -ldZ' | awk '{print $5 " " $9}' |
| # in standard input and generates list of directories we need to scan to cover |
| # the labels given on the command line. |
| |
| import sys |
| import argparse |
| |
| |
| class Node(object): |
| |
| def __init__(self, name, label=None): |
| self.name = name |
| self.label = label |
| self.marked = False |
| self.children = {} |
| |
| def Find(self, components): |
| if not components: |
| return self |
| |
| child = components[0] |
| if child in self.children: |
| return self.children[child].Find(components[1:]) |
| |
| n = Node(child) |
| self.children[child] = n |
| return n |
| |
| def __iter__(self): |
| for child in self.children.itervalues(): |
| yield self.name + '/' + child.name, child |
| for p, ch in child: |
| yield self.name + '/' + p, ch |
| |
| def Mark(self, labels): |
| # Either incorrect label or already marked, we do not need to scan |
| # this path. |
| if self.marked or self.label not in labels: |
| return False |
| |
| self.marked = True |
| |
| for child in self.children.itervalues(): |
| child.Mark(labels) |
| |
| return True |
| |
| |
| def BuildTree(stream=sys.stdin): |
| root = Node("") |
| |
| for line in stream: |
| line = line.strip() |
| if not line: |
| continue |
| |
| label, path = line.split(' ', 1) |
| # u:object_r:system_data_file:s0 -> system_data_file. |
| sanitized_label = label.split(':')[2] |
| # Strip leading slash. |
| components = path[1:].split('/') |
| |
| n = root.Find(components) |
| n.label = sanitized_label |
| return root |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser() |
| parser.add_argument( |
| 'labels', metavar='L', type=str, nargs='+', help='labels we want to find') |
| args = parser.parse_args() |
| root = BuildTree() |
| for fullpath, elem in root: |
| if elem.Mark(args.labels): |
| print fullpath |
| |
| |
| if __name__ == '__main__': |
| main() |