• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# coding: utf-8
3# Copyright (c) 2023 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import os
17import subprocess
18
19
20def run_cmd(cmd: str):
21    res = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE,
22                           stderr=subprocess.PIPE)
23    sout, serr = res.communicate(timeout=60)
24
25    return res.pid, res.returncode, sout, serr
26
27
28def get_needed_lib(file_path: str) -> list:
29    cmd = " ".join(["readelf", "-d", file_path])
30    res = run_cmd(cmd)
31    if res[1] != 0:
32        print("error run readelf -d {}".format(file_path))
33        print(" ".join(["pid ", str(res[0]), " ret ", str(res[1]), "\n",
34                        res[2].decode(), res[3].decode()]))
35        return []
36    needed_lib_name = []
37    lib_info = res[2].decode().split()
38    for i, val in enumerate(lib_info):
39        # lib_info : ... (NEEDED) Shared library: [libc++.so] ...
40        if val == "(NEEDED)" and lib_info[i + 3].startswith("[") and lib_info[i + 3].endswith("]"):
41            needed_lib_name.append(lib_info[i + 3][1 : -1])
42    return needed_lib_name
43
44
45def judge_updater_binary_available(updater_root_path: str) -> bool:
46    updater_binary_path = os.path.join(updater_root_path, "bin", "updater_binary")
47    updater_binary_needed_lib = get_needed_lib(updater_binary_path)
48    # The ASAN version does not set restriction
49    for lib_name in updater_binary_needed_lib:
50        if lib_name.endswith('asan.so'):
51            return True
52    updater_binary_lib_scope = {'libc.so', 'libc++.so', 'libselinux.z.so', 'librestorecon.z.so', 'libssl_openssl.z.so',
53                                'libbegetutil.z.so', 'libcjson.z.so', 'libpartition_slot_manager.z.so'}
54    extra_lib = set(updater_binary_needed_lib) - updater_binary_lib_scope
55    if len(extra_lib) != 0:
56        print("Reason:  not allow updater_binary to depend dynamic library: {}".format(" ".join(extra_lib)))
57        return False
58    return True
59
60
61def judge_lib_available(lib_name: str, lib_chain: list, available_libs: list, lib_to_path: dict) -> bool:
62    if lib_name in available_libs:
63        return True
64    lib_path = lib_to_path.get(lib_name)
65    if lib_path is None:
66        return False
67    for next_lib in get_needed_lib(lib_path):
68        if next_lib not in lib_chain:
69            lib_chain.append(next_lib)
70            if not judge_lib_available(next_lib, lib_chain, available_libs, lib_to_path):
71                return False
72            lib_chain.remove(next_lib)
73    available_libs.add(lib_name)
74    return True
75
76
77def judge_updater_available(updater_root_path: str) -> bool:
78    lib_to_path = dict()
79    for path in [os.path.join(updater_root_path, "lib64"), os.path.join(updater_root_path, "lib")]:
80        for root, dirs, files in os.walk(path):
81            for file in files:
82                lib_to_path[file] = os.path.join(root, file)
83    lib_to_path["updater"] = os.path.join(updater_root_path, "bin", "updater")
84    lib_chain = ["updater"]
85    available_libs = set()
86    if not judge_lib_available("updater", lib_chain, available_libs, lib_to_path):
87        print("Reason:  not allow updater to depend dynamic library which not exist in updater.img. {}"\
88              .format("->".join(lib_chain)))
89        print("Solution:  add updater in install_images field when compiling {}".format(lib_chain[-1]))
90        return False
91    return True
92
93
94def judge_updater_img_available(updater_root_path: str) -> bool:
95    return judge_updater_binary_available(updater_root_path) and\
96           judge_updater_available(updater_root_path)