xref: /aosp_15_r20/external/perfetto/tools/find_scan_roots.py (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker#!/usr/bin/env python
2*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2018 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker#
4*6dbdd20aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker#
8*6dbdd20aSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker#
10*6dbdd20aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker# limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker
16*6dbdd20aSAndroid Build Coastguard Worker# Takes output of
17*6dbdd20aSAndroid Build Coastguard Worker# adb shell 'find /data -print0 | xargs -0 ls -ldZ' | awk '{print $5 " " $9}'
18*6dbdd20aSAndroid Build Coastguard Worker# in standard input and generates list of directories we need to scan to cover
19*6dbdd20aSAndroid Build Coastguard Worker# the labels given on the command line.
20*6dbdd20aSAndroid Build Coastguard Worker
21*6dbdd20aSAndroid Build Coastguard Workerimport sys
22*6dbdd20aSAndroid Build Coastguard Workerimport argparse
23*6dbdd20aSAndroid Build Coastguard Worker
24*6dbdd20aSAndroid Build Coastguard Worker
25*6dbdd20aSAndroid Build Coastguard Workerclass Node(object):
26*6dbdd20aSAndroid Build Coastguard Worker
27*6dbdd20aSAndroid Build Coastguard Worker  def __init__(self, name, label=None):
28*6dbdd20aSAndroid Build Coastguard Worker    self.name = name
29*6dbdd20aSAndroid Build Coastguard Worker    self.label = label
30*6dbdd20aSAndroid Build Coastguard Worker    self.marked = False
31*6dbdd20aSAndroid Build Coastguard Worker    self.children = {}
32*6dbdd20aSAndroid Build Coastguard Worker
33*6dbdd20aSAndroid Build Coastguard Worker  def Find(self, components):
34*6dbdd20aSAndroid Build Coastguard Worker    if not components:
35*6dbdd20aSAndroid Build Coastguard Worker      return self
36*6dbdd20aSAndroid Build Coastguard Worker
37*6dbdd20aSAndroid Build Coastguard Worker    child = components[0]
38*6dbdd20aSAndroid Build Coastguard Worker    if child in self.children:
39*6dbdd20aSAndroid Build Coastguard Worker      return self.children[child].Find(components[1:])
40*6dbdd20aSAndroid Build Coastguard Worker
41*6dbdd20aSAndroid Build Coastguard Worker    n = Node(child)
42*6dbdd20aSAndroid Build Coastguard Worker    self.children[child] = n
43*6dbdd20aSAndroid Build Coastguard Worker    return n
44*6dbdd20aSAndroid Build Coastguard Worker
45*6dbdd20aSAndroid Build Coastguard Worker  def __iter__(self):
46*6dbdd20aSAndroid Build Coastguard Worker    for child in self.children.values():
47*6dbdd20aSAndroid Build Coastguard Worker      yield self.name + '/' + child.name, child
48*6dbdd20aSAndroid Build Coastguard Worker      for p, ch in child:
49*6dbdd20aSAndroid Build Coastguard Worker        yield self.name + '/' + p, ch
50*6dbdd20aSAndroid Build Coastguard Worker
51*6dbdd20aSAndroid Build Coastguard Worker  def Mark(self, labels):
52*6dbdd20aSAndroid Build Coastguard Worker    # Either incorrect label or already marked, we do not need to scan
53*6dbdd20aSAndroid Build Coastguard Worker    # this path.
54*6dbdd20aSAndroid Build Coastguard Worker    if self.marked or self.label not in labels:
55*6dbdd20aSAndroid Build Coastguard Worker      return False
56*6dbdd20aSAndroid Build Coastguard Worker
57*6dbdd20aSAndroid Build Coastguard Worker    self.marked = True
58*6dbdd20aSAndroid Build Coastguard Worker
59*6dbdd20aSAndroid Build Coastguard Worker    for child in self.children.values():
60*6dbdd20aSAndroid Build Coastguard Worker      child.Mark(labels)
61*6dbdd20aSAndroid Build Coastguard Worker
62*6dbdd20aSAndroid Build Coastguard Worker    return True
63*6dbdd20aSAndroid Build Coastguard Worker
64*6dbdd20aSAndroid Build Coastguard Worker
65*6dbdd20aSAndroid Build Coastguard Workerdef BuildTree(stream=sys.stdin):
66*6dbdd20aSAndroid Build Coastguard Worker  root = Node("")
67*6dbdd20aSAndroid Build Coastguard Worker
68*6dbdd20aSAndroid Build Coastguard Worker  for line in stream:
69*6dbdd20aSAndroid Build Coastguard Worker    line = line.strip()
70*6dbdd20aSAndroid Build Coastguard Worker    if not line:
71*6dbdd20aSAndroid Build Coastguard Worker      continue
72*6dbdd20aSAndroid Build Coastguard Worker
73*6dbdd20aSAndroid Build Coastguard Worker    label, path = line.split(' ', 1)
74*6dbdd20aSAndroid Build Coastguard Worker    #  u:object_r:system_data_file:s0  -> system_data_file.
75*6dbdd20aSAndroid Build Coastguard Worker    sanitized_label = label.split(':')[2]
76*6dbdd20aSAndroid Build Coastguard Worker    # Strip leading slash.
77*6dbdd20aSAndroid Build Coastguard Worker    components = path[1:].split('/')
78*6dbdd20aSAndroid Build Coastguard Worker
79*6dbdd20aSAndroid Build Coastguard Worker    n = root.Find(components)
80*6dbdd20aSAndroid Build Coastguard Worker    n.label = sanitized_label
81*6dbdd20aSAndroid Build Coastguard Worker  return root
82*6dbdd20aSAndroid Build Coastguard Worker
83*6dbdd20aSAndroid Build Coastguard Worker
84*6dbdd20aSAndroid Build Coastguard Workerdef main():
85*6dbdd20aSAndroid Build Coastguard Worker  parser = argparse.ArgumentParser()
86*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
87*6dbdd20aSAndroid Build Coastguard Worker      'labels', metavar='L', type=str, nargs='+', help='labels we want to find')
88*6dbdd20aSAndroid Build Coastguard Worker  args = parser.parse_args()
89*6dbdd20aSAndroid Build Coastguard Worker  root = BuildTree()
90*6dbdd20aSAndroid Build Coastguard Worker  for fullpath, elem in root:
91*6dbdd20aSAndroid Build Coastguard Worker    if elem.Mark(args.labels):
92*6dbdd20aSAndroid Build Coastguard Worker      print(fullpath)
93*6dbdd20aSAndroid Build Coastguard Worker
94*6dbdd20aSAndroid Build Coastguard Worker
95*6dbdd20aSAndroid Build Coastguard Workerif __name__ == '__main__':
96*6dbdd20aSAndroid Build Coastguard Worker  main()
97