1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3# Copyright (c) 2021 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 sys 17import os 18import hashlib 19import argparse 20 21 22class InterfaceMgr: 23 __max_buf = 1024 * 1024 24 25 def get_file_sha256(self, filename: str): 26 hash_value = None 27 if os.path.isfile(filename): 28 sha256obj = hashlib.sha256() 29 try: 30 with open(filename, 'rb') as f: 31 while True: 32 buf = f.read(self.__max_buf) 33 if not buf: 34 break 35 sha256obj.update(buf) 36 hash_value = sha256obj.hexdigest() 37 except OSError as err: 38 sys.stdout.write("read file failed. {}".format(err)) 39 return "" 40 return str(hash_value) 41 42 def get_header_files(self, file_dir: str) -> list: 43 h_files = [] 44 for path, _, files in os.walk(file_dir): 45 for file in files: 46 if file.endswith('.h'): 47 x_file = os.path.relpath(os.path.join(path, file), 48 file_dir) 49 h_files.append(x_file) 50 return h_files 51 52 def gen_sig_file_by_subsystem(self, subsystem_sdk_out_dir: str, 53 sig_file_gen_dir: str): 54 if not os.path.exists(subsystem_sdk_out_dir) or not os.path.isdir( 55 subsystem_sdk_out_dir): 56 raise Exception( 57 "subsystem sdk out dir '{}' not exist or not dir".format( 58 subsystem_sdk_out_dir)) 59 60 module_list = os.listdir(subsystem_sdk_out_dir) 61 for module_name in module_list: 62 module_dir = os.path.join(subsystem_sdk_out_dir, module_name) 63 if not os.path.exists(module_dir) or not os.path.isdir(module_dir): 64 continue 65 header_files = self.get_header_files(module_dir) 66 if not header_files: 67 continue 68 check_content = [] 69 for h_file in header_files: 70 file_sha256 = self.get_file_sha256( 71 os.path.join(module_dir, h_file)) 72 check_content.append('{} {}'.format(h_file, file_sha256)) 73 74 check_file = os.path.join(sig_file_gen_dir, module_name, 75 'check.txt') 76 file_dir = os.path.dirname(os.path.abspath(check_file)) 77 if not os.path.exists(file_dir): 78 os.makedirs(file_dir, exist_ok=True) 79 80 # sort check file content 81 check_content.sort() 82 with open(check_file, 'w') as output_file: 83 output_file.write('\n'.join(check_content)) 84 output_file.flush() 85 86 def _gen_checkfile(self, check_file_dir: str, target_type_dir: str, target_type: str): 87 subsystem_list = os.listdir(target_type_dir) 88 for subsystem_name in subsystem_list: 89 subsystem_dir = os.path.join(target_type_dir, subsystem_name) 90 if not os.path.isdir(subsystem_dir) or target_type.startswith( 91 '.'): 92 continue 93 self.gen_sig_file_by_subsystem(subsystem_name, check_file_dir) 94 95 def gen_interface_checkfile(self, sdk_base_dir, check_file_dir): 96 if not os.path.isdir(sdk_base_dir): 97 raise Exception( 98 'sdk base dir [{}] does not exist.'.format(sdk_base_dir)) 99 100 target_type_allowlist = ['ohos-arm64'] 101 target_types = os.listdir(sdk_base_dir) 102 for target_type in target_types: 103 target_type_dir = os.path.join(sdk_base_dir, target_type) 104 if not os.path.isdir(target_type_dir) or target_type.startswith( 105 '.'): 106 continue 107 108 if target_type == 'java': 109 continue 110 111 if target_type not in target_type_allowlist: 112 raise Exception('target type is incorrect.') 113 114 self._gen_checkfile(check_file_dir, target_type_dir, target_type) 115 116 def check(self, check_file_dir: str, subsystem_sdk_dir: str, subsystem_name: str, 117 module_name: str): 118 check_file = os.path.join(check_file_dir, subsystem_name, module_name, 119 'check.txt') 120 if not os.path.isfile(check_file): 121 raise Exception( 122 '[{}:{}] interface check failed. file [{}] does not exist.'. 123 format(subsystem_name, module_name, check_file)) 124 125 check_value = {} 126 with open(check_file, 'r') as f: 127 for line in f.readlines(): 128 values = line.rstrip('\n').split(' ') 129 check_value[values[0]] = values[1] 130 131 module_dir = os.path.join(subsystem_sdk_dir, module_name) 132 header_files = self.get_header_files(module_dir) 133 if len(check_value) != len(header_files): 134 raise Exception(('[{}:{}] interface check failed. ' 135 'the number of files is different.').format( 136 subsystem_name, module_name)) 137 138 for h_file in header_files: 139 file_sha256 = self.get_file_sha256(os.path.join( 140 module_dir, h_file)) 141 if check_value.get(h_file) != file_sha256: 142 raise Exception( 143 '[{}:{}] interface check failed. file [{}] has changed.'. 144 format(subsystem_name, module_name, h_file)) 145 146 147def main(): 148 parser = argparse.ArgumentParser() 149 parser.add_argument('--generate', dest='generate', action='store_true') 150 parser.set_defaults(generate=False) 151 parser.add_argument('--sdk-base-dir', help='', required=True) 152 parser.add_argument('--check_file_dir', help='', required=True) 153 args = parser.parse_args() 154 155 if args.generate: 156 interface_mgr = InterfaceMgr() 157 interface_mgr.gen_interface_checkfile(args.sdk_base_dir, 158 args.check_file_dir) 159 else: 160 sys.stdout.write('Usage: interface_mgr.py --generate ' 161 '--sdk-base-dir SDK_BASE_DIR ' 162 '--check_file_dir CHECK_FILE_DIR') 163 sys.stdout.flush() 164 return 0 165 166 167if __name__ == '__main__': 168 sys.exit(main()) 169