#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2021 Huawei Device Co., Ltd. # 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. import sys import os import hashlib import argparse class InterfaceMgr: __max_buf = 1024 * 1024 def get_file_sha256(self, filename: str): hash_value = None if os.path.isfile(filename): sha256obj = hashlib.sha256() try: with open(filename, 'rb') as f: while True: buf = f.read(self.__max_buf) if not buf: break sha256obj.update(buf) hash_value = sha256obj.hexdigest() except OSError as err: sys.stdout.write("read file failed. {}".format(err)) return "" return str(hash_value) def get_header_files(self, file_dir: str) -> list: h_files = [] for path, _, files in os.walk(file_dir): for file in files: if file.endswith('.h'): x_file = os.path.relpath(os.path.join(path, file), file_dir) h_files.append(x_file) return h_files def gen_sig_file_by_subsystem(self, subsystem_sdk_out_dir: str, sig_file_gen_dir: str): if not os.path.exists(subsystem_sdk_out_dir) or not os.path.isdir( subsystem_sdk_out_dir): raise Exception( "subsystem sdk out dir '{}' not exist or not dir".format( subsystem_sdk_out_dir)) module_list = os.listdir(subsystem_sdk_out_dir) for module_name in module_list: module_dir = os.path.join(subsystem_sdk_out_dir, module_name) if not os.path.exists(module_dir) or not os.path.isdir(module_dir): continue header_files = self.get_header_files(module_dir) if not header_files: continue check_content = [] for h_file in header_files: file_sha256 = self.get_file_sha256( os.path.join(module_dir, h_file)) check_content.append('{} {}'.format(h_file, file_sha256)) check_file = os.path.join(sig_file_gen_dir, module_name, 'check.txt') file_dir = os.path.dirname(os.path.abspath(check_file)) if not os.path.exists(file_dir): os.makedirs(file_dir, exist_ok=True) # sort check file content check_content.sort() with open(check_file, 'w') as output_file: output_file.write('\n'.join(check_content)) output_file.flush() def _gen_checkfile(self, check_file_dir: str, target_type_dir: str, target_type: str): subsystem_list = os.listdir(target_type_dir) for subsystem_name in subsystem_list: subsystem_dir = os.path.join(target_type_dir, subsystem_name) if not os.path.isdir(subsystem_dir) or target_type.startswith( '.'): continue self.gen_sig_file_by_subsystem(subsystem_name, check_file_dir) def gen_interface_checkfile(self, sdk_base_dir, check_file_dir): if not os.path.isdir(sdk_base_dir): raise Exception( 'sdk base dir [{}] does not exist.'.format(sdk_base_dir)) target_type_allowlist = ['ohos-arm64'] target_types = os.listdir(sdk_base_dir) for target_type in target_types: target_type_dir = os.path.join(sdk_base_dir, target_type) if not os.path.isdir(target_type_dir) or target_type.startswith( '.'): continue if target_type == 'java': continue if target_type not in target_type_allowlist: raise Exception('target type is incorrect.') self._gen_checkfile(check_file_dir, target_type_dir, target_type) def check(self, check_file_dir: str, subsystem_sdk_dir: str, subsystem_name: str, module_name: str): check_file = os.path.join(check_file_dir, subsystem_name, module_name, 'check.txt') if not os.path.isfile(check_file): raise Exception( '[{}:{}] interface check failed. file [{}] does not exist.'. format(subsystem_name, module_name, check_file)) check_value = {} with open(check_file, 'r') as f: for line in f.readlines(): values = line.rstrip('\n').split(' ') check_value[values[0]] = values[1] module_dir = os.path.join(subsystem_sdk_dir, module_name) header_files = self.get_header_files(module_dir) if len(check_value) != len(header_files): raise Exception(('[{}:{}] interface check failed. ' 'the number of files is different.').format( subsystem_name, module_name)) for h_file in header_files: file_sha256 = self.get_file_sha256(os.path.join( module_dir, h_file)) if check_value.get(h_file) != file_sha256: raise Exception( '[{}:{}] interface check failed. file [{}] has changed.'. format(subsystem_name, module_name, h_file)) def main(): parser = argparse.ArgumentParser() parser.add_argument('--generate', dest='generate', action='store_true') parser.set_defaults(generate=False) parser.add_argument('--sdk-base-dir', help='', required=True) parser.add_argument('--check_file_dir', help='', required=True) args = parser.parse_args() if args.generate: interface_mgr = InterfaceMgr() interface_mgr.gen_interface_checkfile(args.sdk_base_dir, args.check_file_dir) else: sys.stdout.write('Usage: interface_mgr.py --generate ' '--sdk-base-dir SDK_BASE_DIR ' '--check_file_dir CHECK_FILE_DIR') sys.stdout.flush() return 0 if __name__ == '__main__': sys.exit(main())