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_lib_available(lib_name: str, lib_chain: list, available_libs: list, lib_to_path: dict) -> bool: 46 if lib_name in available_libs: 47 return True 48 lib_path = lib_to_path.get(lib_name) 49 if lib_path is None: 50 return False 51 for next_lib in get_needed_lib(lib_path): 52 if next_lib not in lib_chain: 53 lib_chain.append(next_lib) 54 if not judge_lib_available(next_lib, lib_chain, available_libs, lib_to_path): 55 return False 56 lib_chain.remove(next_lib) 57 available_libs.add(lib_name) 58 return True 59 60 61def judge_updater_available(updater_root_path: str) -> bool: 62 lib_to_path = dict() 63 for path in [os.path.join(updater_root_path, "lib64"), os.path.join(updater_root_path, "lib")]: 64 for root, dirs, files in os.walk(path): 65 for file in files: 66 lib_to_path[file] = os.path.join(root, file) 67 lib_to_path["updater"] = os.path.join(updater_root_path, "bin", "updater") 68 lib_chain = ["updater"] 69 available_libs = set() 70 if not judge_lib_available("updater", lib_chain, available_libs, lib_to_path): 71 print("Reason: not allow updater to depend dynamic library which not exist in updater.img. {}"\ 72 .format("->".join(lib_chain))) 73 print("Solution: add updater in install_images field when compiling {}".format(lib_chain[-1])) 74 return False 75 return True 76 77 78def judge_updater_img_available(updater_root_path: str) -> bool: 79 return judge_updater_available(updater_root_path) 80