diff --git a/llvm-build/file_integrity_check/file_permission_check.py b/llvm-build/file_integrity_check/file_permission_check.py index 0a6727a889883bdc2037c590d5a38ec6c91fa762..fc31492bf6a409486d93e984527607bfef9cf2f4 100644 --- a/llvm-build/file_integrity_check/file_permission_check.py +++ b/llvm-build/file_integrity_check/file_permission_check.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python3 # Copyright (C) 2024 Huawei Device Co., Ltd. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,12 +18,13 @@ import stat import sys from datetime import datetime import logging +import argparse class FilePermissionCheck: SO_PERMISSION_CHECK_MIN_ARGS_NUMBER = 3 DEFAULT_CLANG_FILE_PERMISSION_CHECKLIST_PATH = "default_clang_file_permission.checklist" - DEFAULT_NDK_LIB_FILE_PERMISSION_CHECKLIST_PATH = "default_ndk_flie_permission.checklist" + DEFAULT_NDK_LIB_FILE_PERMISSION_CHECKLIST_PATH = "default_ndk_file_permission.checklist" TEMP_CLANG_FILE_PERMISSION_CHECKLIST_PATH = "temp_clang_file_permission.checklist" logger = None @@ -36,8 +37,8 @@ class FilePermissionCheck: ch.setFormatter(formatter) self.logger.addHandler(ch) - def get_file_size(file_path): - """返回文件的大小,以字节为单位""" + def get_file_size(self, file_path): + """ļĴСֽΪλ""" if os.path.exists(file_path): return os.path.getsize(file_path) return 0 @@ -72,54 +73,87 @@ class FilePermissionCheck: True(all permission check succeeded) or False(one or more check failed). ''' lack = 0 + extra = 0 total = 0 fail = 0 success = 0 timestamp = datetime.now().strftime("%Y_%m_%d_%H_%M_%S") - log_file_path = "file_permissions_check_log" + timestamp + ".txt" + log_file_path = "file_permissions_check_log" + timestamp + ".html" success_log = "" error_log = "" lack_log = "" + extra_log = "" + + # Read the checklist file into a dictionary + checklist = {} with open(checklist_file, 'r') as ff: for line in ff: - lib_file_path = os.path.join(directory, line.split(',')[0].split('lib/', 1)[1]).replace('\\', '/') - file_stat_expected = line.split(',')[1].replace('\n', '') - file_size_expected = line.split(',')[2].replace('\n', '') - file_stat_real = self.get_file_permissions(lib_file_path) - if file_stat_real is None: - lack += 1 - total += 1 - lack_log += f"{lib_file_path} check failed, the file is missed, missing file size is {file_size_expected} MB.\n" - elif file_stat_expected == stat.filemode(os.stat(lib_file_path).st_mode): - success += 1 - total += 1 - success_log += f"{lib_file_path} check succeeded.\n" + parts = line.strip().split(',') + checklist[parts[0]] = (parts[1], parts[2]) + + # Walk through the directory and compare with the checklist + for root, dirs, files in os.walk(directory): + for file in files: + total += 1 + file_path = os.path.join(root, file) + relative_path = 'lib' + file_path.replace(directory, '').replace('\\', '/') + file_stat_real = self.get_file_permissions(file_path) + + if relative_path not in checklist: + extra += 1 + extra_log += f"{relative_path}Extra file--\n" else: - fail += 1 - total += 1 - error_log += f"{lib_file_path} check failed, expected: {file_stat_expected}, real: {stat.filemode(os.stat(lib_file_path).st_mode)}\n" + file_stat_expected, file_size_expected = checklist[relative_path] + if file_stat_real is None: + lack += 1 + lack_log += f"{relative_path}Missing file{file_size_expected} MB-\n" + elif file_stat_expected == file_stat_real: + success += 1 + success_log += f"{relative_path}Check succeeded{file_size_expected} MB{file_stat_real}\n" + else: + fail += 1 + error_log += f"{relative_path}Check failedExpected: {file_stat_expected}, Real: {file_stat_real}{file_size_expected} MB\n" + + # Check for missing files in the directory + for relative_path, (file_stat_expected, file_size_expected) in checklist.items(): + if relative_path not in [os.path.join(root, file).replace(directory, '').replace('\\', '/') for root, dirs, files in os.walk(directory) for file in files]: + lack += 1 + lack_log += f"{relative_path}Missing file{file_size_expected} MB-\n" + # Write the HTML log file with open(log_file_path, 'w') as f: - f.write(f'llvm file permissions check complete, Success: {success}/{total}, Failed: {fail}/{total}, Lack: {lack}/{total}\n') - f.write(f'\n{fail}/{total} checks failed.\n') + f.write("\n") + f.write("\n") + f.write("\n") + f.write("File Permissions Check Log\n") + f.write("\n") + f.write("\n") + f.write("\n") + f.write(f"

File Permissions Check Log - Total Files: {total}, Differences: {lack + extra}

\n") + f.write("\n") + f.write("\n") + f.write(success_log) f.write(error_log) - f.write(f'\n{lack}/{total} file missed.\n') f.write(lack_log) - f.write(f'\n{success}/{total} checks succeed.\n') - f.write(success_log) - - if success == total: + f.write(extra_log) + f.write("
File PathStatusExpected SizeReal Permissions
\n") + f.write("\n") + f.write("\n") + + if success == total - (lack + extra): self.logger.info(f"{directory} files permissions check passed.") return True else: self.logger.error(f"{directory} files permissions check failed.") - self.logger.error(f"{fail}/{total} checks failed.\n") - self.logger.error(error_log) - self.logger.error(f"{lack}/{total} file missed.\n") - self.logger.error(lack_log) - self.logger.error(f"{fail + lack}/{total} checks failed, check logs are in {os.path.join(os.getcwd(), log_file_path)}") + self.logger.error(f"{fail}/{total} checks failed.") + self.logger.error(f"{lack}/{total} file(s) missed.") + self.logger.error(f"{extra}/{total} extra file(s) found.") + self.logger.error(f"Check logs are in {os.path.join(os.getcwd(), log_file_path)}") return False def get_file_permissions(self, file_path: str) -> str: @@ -129,11 +163,11 @@ class FilePermissionCheck: permissions = stat.filemode(file_stat.st_mode) return permissions except FileNotFoundError: - self.logger.error(f"file '{file_path}' not found.") + self.logger.error(f"File '{file_path}' not found.") except PermissionError: - self.logger.error(f"no read permission for '{file_path}'.") + self.logger.error(f"No read permission for '{file_path}'.") except Exception as e: - self.logger.error(f"unknown error - {e}") + self.logger.error(f"Unknown error - {e}") return None def check(self, clang_lib_path: str, ndk_lib_path: str) -> bool: @@ -142,35 +176,80 @@ class FilePermissionCheck: Check the so file permissions in clang and ndk lib directories based on the default check list. ''' return self.file_list_check(clang_lib_path, self.DEFAULT_CLANG_FILE_PERMISSION_CHECKLIST_PATH) \ - & self.file_list_check(ndk_lib_path, self.DEFAULT_NDK_LIB_FILE_PERMISSION_CHECKLIST_PATH) + and self.file_list_check(ndk_lib_path, self.DEFAULT_NDK_LIB_FILE_PERMISSION_CHECKLIST_PATH) def cmd_handler(self) -> None: '''Perform parameter recognition and execute corresponding tasks.''' - args = sys.argv - if len(args) < self.SO_PERMISSION_CHECK_MIN_ARGS_NUMBER: - self.logger.info("Missing arguments. Correct eg: python file_permission_check.py --generate-default-list clang/lib") + if len(sys.argv) < self.SO_PERMISSION_CHECK_MIN_ARGS_NUMBER: + self.logger.info("Missing arguments. Correct example: python filepermissioncheck.py --generate-default-list clang/lib") return - if len(args) > 1: - if args[1] == '--generate-list': - self.file_list_generate(args[2], args[3]) - elif args[1] == '--generate-default-list': - self.file_list_generate(args[2], self.DEFAULT_CLANG_FILE_PERMISSION_CHECKLIST_PATH) - elif args[1] == '--generate-ndk-list': - self.file_list_generate(args[2], self.DEFAULT_NDK_LIB_FILE_PERMISSION_CHECKLIST_PATH) - elif args[1] == '--file-check': - self.file_list_check(args[2], args[3]) - elif args[1] == '--check-default-clang': - self.file_list_check(args[2], self.DEFAULT_CLANG_FILE_PERMISSION_CHECKLIST_PATH) - elif args[1] == '--check-default-ndk': - self.file_list_check(args[2], self.DEFAULT_NDK_LIB_FILE_PERMISSION_CHECKLIST_PATH) - elif args[1] == '--compare-between-path': - self.file_list_generate(args[2], self.TEMP_CLANG_FILE_PERMISSION_CHECKLIST_PATH) - self.file_list_check(args[3], self.TEMP_CLANG_FILE_PERMISSION_CHECKLIST_PATH) + parser = argparse.ArgumentParser(description='File permission check tool.') + parser.add_argument( + '--generate-list', + nargs=2, + metavar=('DIRECTORY', 'OUTPUT_FILE'), + help='Generate a file permission checklist for the given directory and save to the output file.') + + parser.add_argument( + '--generate-default-list', + nargs=1, + metavar='DIRECTORY', + help='Generate a default file permission checklist for the given directory.') + + parser.add_argument( + '--generate-ndk-list', + nargs=1, + metavar='DIRECTORY', + help='Generate a default NDK library file permission checklist for the given directory.') + + parser.add_argument( + '--file-check', + nargs=2, + metavar=('DIRECTORY', 'CHECKLIST_FILE'), + help='Check file permissions in the given directory based on the provided checklist file.') + + parser.add_argument( + '--check-default-clang', + nargs=1, + metavar='DIRECTORY', + help='Check file permissions in the given Clang directory based on the default checklist.') + parser.add_argument( + '--check-default-ndk', + nargs=1, + metavar='DIRECTORY', + help='Check file permissions in the given NDK directory based on the default checklist.') + + parser.add_argument( + '--compare-between-path', + nargs=2, + metavar=('SOURCE_DIRECTORY', 'TARGET_DIRECTORY'), + help='Generate a checklist for the source directory and check the target directory against it.') + + args = parser.parse_args() + + if len(vars(args)) > 1: + if args.generate_list: + self.file_list_generate(args.generate_list[0], args.generate_list[1]) + elif args.generate_default_list: + self.file_list_generate(args.generate_default_list[0], self.DEFAULT_CLANG_FILE_PERMISSION_CHECKLIST_PATH) + elif args.generate_ndk_list: + self.file_list_generate(args.generate_ndk_list[0], self.DEFAULT_NDK_LIB_FILE_PERMISSION_CHECKLIST_PATH) + elif args.file_check: + self.file_list_check(args.file_check[0], args.file_check[1]) + elif args.check_default_clang: + self.file_list_check(args.check_default_clang[0], self.DEFAULT_CLANG_FILE_PERMISSION_CHECKLIST_PATH) + elif args.check_default_ndk: + self.file_list_check(args.check_default_ndk[0], self.DEFAULT_NDK_LIB_FILE_PERMISSION_CHECKLIST_PATH) + elif args.compare_between_path: + self.file_list_generate(args.compare_between_path[0], self.TEMP_CLANG_FILE_PERMISSION_CHECKLIST_PATH) + self.file_list_check(args.compare_between_path[1], self.TEMP_CLANG_FILE_PERMISSION_CHECKLIST_PATH) else: self.logger.info("The input arguments are incorrect. Check the input arguments by reading the README document.") + def main(): file_permission_check = FilePermissionCheck() file_permission_check.cmd_handler() + if __name__ == '__main__': main()