diff --git a/scripts/Android.bp b/scripts/Android.bp index 4c847a121..a694b953b 100644 --- a/scripts/Android.bp +++ b/scripts/Android.bp @@ -188,3 +188,11 @@ python_binary_host { "get_clang_version.py", ], } + +python_binary_host { + name: "list_image", + main: "list_image.py", + srcs: [ + "list_image.py", + ], +} diff --git a/scripts/list_image.py b/scripts/list_image.py new file mode 100644 index 000000000..7f76537f4 --- /dev/null +++ b/scripts/list_image.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +# +# Copyright (C) 2022 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. +"""list_image is a tool that prints out content of an .img file. + +To print content of an image to stdout: + list_image foo.img +""" +from __future__ import print_function + +import argparse +import os +import sys +import subprocess + +class ImageEntry(object): + + def __init__(self, name, base_dir, is_directory=False): + self._name = name + self._base_dir = base_dir + self._is_directory = is_directory + + @property + def name(self): + return self._name + + @property + def full_path(self): + return os.path.join(self._base_dir, self._name) + + @property + def is_directory(self): + return self._is_directory + + +class Image(object): + + def __init__(self, debugfs_path, img_path): + self._debugfs = debugfs_path + self._img_path = img_path + + def list(self, path): + print(path) + process = subprocess.Popen([self._debugfs, '-R', 'ls -l -p %s' % path, self._img_path], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + universal_newlines=True) + stdout, _ = process.communicate() + res = str(stdout) + entries = [] + for line in res.split('\n'): + if not line: + continue + parts = line.split('/') + if len(parts) != 8: + continue + name = parts[5] + if not name: + continue + bits = parts[2] + is_directory = bits[1] == '4' + entries.append(ImageEntry(name, path, is_directory)) + + for e in sorted(entries, key=lambda e: e.name): + yield e + if e.is_directory and e.name != '.' and e.name != '..': + yield from self.list(path + e.name + '/') + + +def main(argv): + parser = argparse.ArgumentParser() + + debugfs_default = None + if 'ANDROID_HOST_OUT' in os.environ: + debugfs_default = '%s/bin/debugfs_static' % os.environ['ANDROID_HOST_OUT'] + parser.add_argument('--debugfs_path', help='The path to debugfs binary', default=debugfs_default) + parser.add_argument('img_path', type=str, help='.img file') + args = parser.parse_args(argv) + + if not args.debugfs_path: + print('ANDROID_HOST_OUT environment variable is not defined, --debugfs_path must be set', + file=sys.stderr) + sys.exit(1) + + for e in Image(args.debugfs_path, args.img_path).list('./'): + if e.is_directory: + continue + print(e.full_path) + + +if __name__ == '__main__': + main(sys.argv[1:])