1#!/usr/bin/env python 2# coding: utf-8 3 4""" 5Copyright (c) 2024 Huawei Device Co., Ltd. 6Licensed under the Apache License, Version 2.0 (the "License"); 7you may not use this file except in compliance with the License. 8You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12Unless required by applicable law or agreed to in writing, software 13distributed under the License is distributed on an "AS IS" BASIS, 14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15See the License for the specific language governing permissions and 16limitations under the License. 17 18""" 19 20import os 21import argparse 22 23 24def parse_args(): 25 parser = argparse.ArgumentParser() 26 parser.add_argument("--dst-dir", help="the output dest path", required=True) 27 parser.add_argument("--source-root-dir", help="project root path", required=True) 28 parser.add_argument( 29 "--policy-dir-list", help="policy dirs need to be included", required=True 30 ) 31 parser.add_argument( 32 "--components", help="system or vendor or default", required=True 33 ) 34 return parser.parse_args() 35 36 37def prepare_build_path(dir_list, root_dir, build_dir_list): 38 build_ignore_cfg_list = [ 39 "base/security/selinux_adapter/sepolicy/base", 40 "base/security/selinux_adapter/sepolicy/ohos_policy", 41 ] 42 build_ignore_cfg_list += dir_list.split(":") 43 44 for i in build_ignore_cfg_list: 45 if not i or i == "default": 46 continue 47 path = os.path.join(root_dir, i) 48 if os.path.exists(path): 49 build_dir_list.append(path) 50 else: 51 raise Exception(f"following path not exists!! {path}") 52 53 54def check_ignore_file(ignore_file, err_msg): 55 """ 56 Check the format of ignore_cfg file. 57 :param ignore_file: ignore_file 58 :return: 59 """ 60 err = "" 61 lines = [] 62 with open(ignore_file, "rb") as fp: 63 lines = fp.readlines() 64 if len(lines) == 0: 65 return 66 last_line = lines[-1] 67 if b"\n" not in last_line: 68 err = "".join((ignore_file, " : need an empty line at end ")) 69 for line in lines: 70 strip_line = line.strip() 71 if not strip_line: 72 continue 73 if line.endswith(b"\r\n") or line.endswith(b"\r"): 74 err = "".join((ignore_file, " : must be unix format")) 75 break 76 if strip_line in [b"/", b"/*"]: 77 err = "".join((ignore_file, " : line must not be only / or /*")) 78 break 79 if not (strip_line.endswith(b"/") or strip_line.endswith(b"/*")): 80 err = "".join((ignore_file, " : line must end with / or /*")) 81 break 82 if err: 83 err_msg.append(err) 84 85 86def traverse_folder_in_type(search_dir_list, file_suffix): 87 """ 88 for special folder search_dir, find all files endwith file_suffix. 89 :param search_dir: path to search 90 :param file_suffix: postfix of file name 91 :return: file list 92 """ 93 err_msg = [] 94 ignore_cfg_file_list = [] 95 for item in search_dir_list: 96 for root, _, files in sorted(os.walk(item)): 97 filtered_files = [f for f in files if f == file_suffix] 98 for each_file in filtered_files: 99 file_list_path = os.path.join(root, each_file) 100 check_ignore_file(file_list_path, err_msg) 101 ignore_cfg_file_list.append(file_list_path) 102 if err_msg: 103 err_str = "\n{}".format("\n".join(err_msg)) 104 raise Exception(err_str) 105 ignore_cfg_file_list.sort() 106 return ignore_cfg_file_list 107 108 109def check_and_add_line(lines, line): 110 line = line.strip() 111 if not line: 112 return 113 for existing_line in lines[:]: 114 if len(line) >= len(existing_line) and line.startswith(existing_line): 115 return 116 elif len(line) < len(existing_line) and existing_line.startswith(line): 117 lines.remove(existing_line) 118 lines.append(line) 119 return 120 lines.append(line) 121 122 123def get_path_lines(ignore_cfg_list): 124 lines = [] 125 for ignore_cfg in ignore_cfg_list: 126 with open(ignore_cfg, "r") as src_file: 127 for line in src_file: 128 check_and_add_line(lines, line) 129 return lines 130 131 132def filter_and_write_to_dst(lines, dst_file): 133 fd = os.open(dst_file, os.O_WRONLY | os.O_CREAT, 0o664) 134 with os.fdopen(fd, "w") as dst_f: 135 dst_f.truncate(0) 136 for line in lines: 137 if line and not line.startswith("#"): 138 line = "".join([line, "\n"]) 139 dst_f.write(line) 140 141 142def combine_ignore_cfg(ignore_cfg_list, combined_ignore_cfg): 143 lines = get_path_lines(ignore_cfg_list) 144 filter_and_write_to_dst(lines, combined_ignore_cfg) 145 146 147def traverse_folder_in_dir_name(search_dir, folder_suffix): 148 folder_list = [] 149 for root, dirs, _ in sorted(os.walk(search_dir)): 150 for dir_i in dirs: 151 if dir_i == folder_suffix: 152 folder_list.append(os.path.join(root, dir_i)) 153 return folder_list 154 155 156def build_ignore_cfg(output_path, folder_list): 157 combined_ignore_cfg = os.path.join(output_path, "ignore_cfg") 158 ignore_cfg_list = traverse_folder_in_type(folder_list, "ignore_cfg") 159 combine_ignore_cfg(ignore_cfg_list, combined_ignore_cfg) 160 161 162def main(args): 163 output_path = args.dst_dir 164 print("output_path: ", output_path) 165 policy_path = [] 166 prepare_build_path(args.policy_dir_list, args.source_root_dir, policy_path) 167 print("policy_path: ", policy_path) 168 169 folder_list = [] 170 for item in policy_path: 171 public_ = traverse_folder_in_dir_name(item, "public") 172 if args.components == "system": 173 system_policy = traverse_folder_in_dir_name(item, "system") 174 folder_list += public_ + system_policy 175 elif args.components == "vendor": 176 vendor_policy = traverse_folder_in_dir_name(item, "vendor") 177 folder_list += public_ + vendor_policy 178 else: 179 system_policy = traverse_folder_in_dir_name(item, "system") 180 vendor_policy = traverse_folder_in_dir_name(item, "vendor") 181 folder_list += public_ + system_policy + vendor_policy 182 183 build_ignore_cfg(output_path, folder_list) 184 print("build_ignore_cfg done") 185 186 187if __name__ == "__main__": 188 input_args = parse_args() 189 main(input_args) 190