1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3 4# Copyright (c) 2021 Huawei Device Co., Ltd. 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16import binascii 17import copy 18import os 19import subprocess 20import tempfile 21import time 22import collections as collect 23import enum 24import ctypes 25import zipfile 26 27from log_exception import UPDATE_LOGGER 28from script_generator import create_script 29from utils import sign_package 30from utils import HASH_CONTENT_LEN_DICT 31from utils import OPTIONS_MANAGER 32from utils import REGISTER_SCRIPT_FILE_NAME 33from utils import ON_SERVER 34from utils import SCRIPT_KEY_LIST 35from utils import EXTEND_OPTIONAL_COMPONENT_LIST 36from utils import COMPONENT_INFO_INNIT 37from utils import UPDATE_EXE_FILE_NAME 38from utils import TOTAL_SCRIPT_FILE_NAME 39from utils import EXTEND_PATH_EVENT 40from utils import LINUX_HASH_ALGORITHM_DICT 41from utils import UPDATE_BIN_FILE_NAME 42from utils import BUILD_TOOLS_FILE_NAME 43from utils import SIGN_PACKAGE_EVENT 44from utils import CHECK_BINARY_EVENT 45from utils import ZIP_EVENT 46from utils import GENERATE_SIGNED_DATA_EVENT 47from utils import DECOUPLED_EVENT 48from utils import get_extend_path_list 49from create_update_package import CreatePackage 50from create_update_package import SIGN_ALGO_RSA 51from create_update_package import SIGN_ALGO_PSS 52from create_signed_data import generate_signed_data_default 53 54IS_DEL = 0 55SIGNING_LENGTH_256 = 256 56DIGEST_LEN = 32 57HASH_VALUE_MAX_LEN = 128 58 59 60class SignMethod(enum.Enum): 61 RSA = 1 62 ECC = 2 63 64 65class PkgHeader(ctypes.Structure): 66 _fields_ = [("digest_method", ctypes.c_ubyte), 67 ("sign_method", ctypes.c_ubyte), 68 ("pkg_type", ctypes.c_ubyte), 69 ("pkg_flags", ctypes.c_ubyte), 70 ("entry_count", ctypes.c_int), 71 ("update_file_version", ctypes.c_int), 72 ("product_update_id", ctypes.c_char_p), 73 ("software_version", ctypes.c_char_p), 74 ("date", ctypes.c_char_p), 75 ("time", ctypes.c_char_p), 76 ("describe_package_id", ctypes.c_char_p)] 77 78 79class PkgComponent(ctypes.Structure): 80 _fields_ = [("digest", ctypes.c_ubyte * DIGEST_LEN), 81 ("file_path", ctypes.c_char_p), 82 ("component_addr", ctypes.c_char_p), 83 ("version", ctypes.c_char_p), 84 ("size", ctypes.c_int), 85 ("id", ctypes.c_int), 86 ("original_size", ctypes.c_int), 87 ("res_type", ctypes.c_ubyte), 88 ("type", ctypes.c_ubyte), 89 ("flags", ctypes.c_ubyte)] 90 91 92class SignInfo(ctypes.Structure): 93 _fields_ = [("sign_offset", ctypes.c_int), 94 ("hash_len", ctypes.c_int), 95 ("hash_code", ctypes.c_ubyte * (HASH_VALUE_MAX_LEN + 1))] 96 97 98def create_update_bin(): 99 """ 100 Call the interface to generate the update.bin file. 101 :return update_bin_obj: Update file object. 102 If exception occurs, return False. 103 """ 104 update_bin_obj = tempfile.NamedTemporaryFile(dir=OPTIONS_MANAGER.update_package, prefix="update_bin-") 105 106 head_value_list = OPTIONS_MANAGER.head_info_list 107 component_dict = OPTIONS_MANAGER.component_info_dict 108 full_image_file_obj_list = OPTIONS_MANAGER.full_image_file_obj_list 109 if OPTIONS_MANAGER.stream_update: 110 # List of chunks stored in full streaming update 111 full_img_list = OPTIONS_MANAGER.full_image_chunk_list 112 else: 113 full_img_list = OPTIONS_MANAGER.full_img_list 114 115 extend_component_list = get_extend_path_list() 116 if not OPTIONS_MANAGER.not_l2: 117 if OPTIONS_MANAGER.partition_file_obj is not None: 118 all_image_name = \ 119 extend_component_list + EXTEND_OPTIONAL_COMPONENT_LIST + full_img_list 120 else: 121 all_image_name = extend_component_list + full_img_list 122 else: 123 all_image_name = full_img_list 124 sort_component_dict = collect.OrderedDict() 125 for each_image_name in all_image_name: 126 sort_component_dict[each_image_name] = component_dict.get(each_image_name) 127 component_dict = copy.deepcopy(sort_component_dict) 128 head_list = get_head_list(len(component_dict), head_value_list) 129 130 component_list = get_component_list( 131 full_image_file_obj_list, component_dict) 132 133 save_patch = update_bin_obj.name.encode("utf-8") 134 135 if OPTIONS_MANAGER.private_key == ON_SERVER: 136 private_key = "./update_package.py" 137 else: 138 private_key = OPTIONS_MANAGER.private_key.encode("utf-8") 139 140 if OPTIONS_MANAGER.not_l2: 141 sign_algo = SIGN_ALGO_PSS 142 else: 143 sign_algo = SIGN_ALGO_RSA 144 145 # create bin 146 package = CreatePackage(head_list, component_list, save_patch, OPTIONS_MANAGER.private_key) 147 if not package.create_package(): 148 UPDATE_LOGGER.print_log("Create update package .bin failed!", UPDATE_LOGGER.ERROR_LOG) 149 return False 150 151 UPDATE_LOGGER.print_log("Create update package .bin complete! path: %s" % update_bin_obj.name) 152 return update_bin_obj 153 154 155def get_component_list(all_image_file_obj_list, component_dict): 156 """ 157 Get the list of component information according to 158 the component information structure. 159 :param all_image_file_obj_list: all image object file list 160 :param component_dict: Component information content dict 161 :return component_list: List of component information. 162 If exception occurs, return False. 163 """ 164 pkg_components = PkgComponent * len(component_dict) 165 component_list = pkg_components() 166 extend_list = get_extend_path_list() 167 if not OPTIONS_MANAGER.not_l2: 168 if OPTIONS_MANAGER.partition_file_obj is not None: 169 extend_component_list = extend_list + EXTEND_OPTIONAL_COMPONENT_LIST 170 extend_path_list = [OPTIONS_MANAGER.version_mbn_file_path, 171 OPTIONS_MANAGER.board_list_file_path, 172 OPTIONS_MANAGER.partition_file_obj.name] 173 else: 174 extend_component_list = extend_list 175 extend_path_list = [OPTIONS_MANAGER.version_mbn_file_path, 176 OPTIONS_MANAGER.board_list_file_path] 177 else: 178 extend_component_list = [] 179 extend_path_list = [] 180 get_path_list = OPTIONS_MANAGER.init.invoke_event(EXTEND_PATH_EVENT) 181 if get_path_list: 182 extend_path_list = get_path_list() 183 idx = 0 184 for key, component in component_dict.items(): 185 if idx < len(extend_component_list): 186 file_path = extend_path_list[idx] 187 else: 188 file_path = all_image_file_obj_list[idx - len(extend_component_list)].name 189 digest = get_hash_content(file_path, OPTIONS_MANAGER.hash_algorithm) 190 if not digest: 191 return 192 if component is None: 193 component = copy.copy(COMPONENT_INFO_INNIT) 194 component[0] = key 195 component_list[idx].digest = (ctypes.c_ubyte * 32).from_buffer_copy( 196 binascii.a2b_hex(digest.encode('utf-8'))) 197 component_list[idx].file_path = file_path.encode("utf-8") 198 if not OPTIONS_MANAGER.not_l2: 199 component_list[idx].component_addr = ('/%s' % component[0]).encode("utf-8") 200 else: 201 component_list[idx].component_addr = ('%s' % component[0]).encode("utf-8") 202 component_list[idx].version = component[4].encode("utf-8") 203 component_list[idx].size = os.path.getsize(file_path) 204 component_list[idx].id = int(component[1]) 205 if component[3] == 1: 206 component_list[idx].original_size = os.path.getsize(file_path) 207 else: 208 component_list[idx].original_size = 0 209 component_list[idx].res_type = int(component[2]) 210 component_list[idx].type = int(component[3]) 211 component_list[idx].flags = IS_DEL 212 213 idx += 1 214 return component_list 215 216 217def get_head_list(component_count, head_value_list): 218 """ 219 According to the header structure, get the list of HEAD headers. 220 :param component_count: number of components 221 :param head_value_list: list of header values 222 :return head_list: header list 223 """ 224 head_list = PkgHeader() 225 if OPTIONS_MANAGER.signing_length != SIGNING_LENGTH_256: 226 # PKG_DIGEST_TYPE_SHA384 3,use sha384 227 head_list.digest_method = 3 228 else: 229 # PKG_DIGEST_TYPE_SHA256 2,use sha256 230 head_list.digest_method = 2 231 if OPTIONS_MANAGER.private_key == ON_SERVER: 232 head_list.sign_method = 0 233 else: 234 if OPTIONS_MANAGER.signing_algorithm == "ECC": 235 # signing algorithm use ECC 236 head_list.sign_method = SignMethod.ECC.value 237 else: 238 # signing algorithm use RSA 239 head_list.sign_method = SignMethod.RSA.value 240 head_list.pkg_type = 1 241 if OPTIONS_MANAGER.not_l2: 242 head_list.pkg_flags = 1 243 else: 244 head_list.pkg_flags = 0 245 head_list.entry_count = component_count 246 head_list.update_file_version = int(head_value_list[0]) 247 head_list.product_update_id = head_value_list[1].encode("utf-8") 248 head_list.software_version = head_value_list[2].encode("utf-8") 249 head_list.date = head_value_list[3].encode("utf-8") 250 head_list.time = head_value_list[4].encode("utf-8") 251 head_list.describe_package_id = ctypes.c_char_p("update/info.bin".encode()) 252 return head_list 253 254 255def get_tools_component_list(count, opera_script_dict): 256 """ 257 Get the list of component information according to 258 the component information structure. 259 :param count: number of components 260 :param opera_script_dict: script file name and path dict 261 :return component_list: list of component information. 262 If exception occurs, return False. 263 """ 264 pkg_components = PkgComponent * count 265 component_list = pkg_components() 266 component_value_list = list(opera_script_dict.keys()) 267 component_num = 0 268 for i, component in enumerate(component_value_list): 269 component_list[i].file_path = component.encode("utf-8") 270 component_list[i].component_addr = \ 271 (opera_script_dict[component]).encode("utf-8") 272 component_num += 1 273 return component_list, component_num 274 275 276def get_tools_head_list(component_count): 277 """ 278 According to the header structure, get the list of HEAD headers. 279 :param component_count: number of components 280 :return head_list: header list 281 """ 282 head_list = PkgHeader() 283 head_list.digest_method = 0 284 head_list.sign_method = 0 285 head_list.pkg_type = 2 286 head_list.pkg_flags = 0 287 head_list.entry_count = component_count 288 return head_list 289 290 291def get_signing_from_server(package_path, hash_algorithm, hash_code=None): 292 """ 293 Server update package signature requires the vendor to 294 implement its own service signature interface, as shown below: 295 ip = "" 296 user_name = "" 297 pass_word = "" 298 signe_jar = "" 299 signing_config = [signe_jar, ip, user_name, pass_word, 300 hash_code, hash_algorithm] 301 cmd = ' '.join(signing_config) 302 subprocess.Popen( 303 cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 304 :param package_path: update package file path 305 :param hash_algorithm: hash algorithm 306 :param hash_code: hash code 307 :return: 308 """ 309 UPDATE_LOGGER.print_log("Signing %s, hash algorithm is: %s, " 310 "Signing hash code: %s" % 311 (package_path, hash_algorithm, hash_code)) 312 signing_content = "" 313 return signing_content.encode() 314 315 316def create_build_tools_zip(): 317 """ 318 Create the update package file. 319 :param lib: lib object 320 :return: 321 """ 322 opera_script_file_name_dict = OPTIONS_MANAGER.opera_script_file_name_dict 323 tmp_dict = {} 324 for each in SCRIPT_KEY_LIST: 325 tmp_dict[each] = [] 326 if opera_script_file_name_dict == tmp_dict: 327 UPDATE_LOGGER.print_log( 328 "Script dict is null!", 329 log_type=UPDATE_LOGGER.ERROR_LOG) 330 return False 331 count = 0 332 opera_script_dict = {} 333 for each_value in opera_script_file_name_dict.values(): 334 for each in each_value: 335 opera_script_dict[each[1].name] = each[0] 336 count += 1 337 # other_file_count --> 1(updater_binary) + 1(loadScript.us) 338 other_file_count = 2 339 count += other_file_count 340 if OPTIONS_MANAGER.register_script_file_obj is not None: 341 count += 1 342 head_list = get_tools_head_list(count) 343 component_list, num = get_tools_component_list(count, opera_script_dict) 344 total_script_file_obj = OPTIONS_MANAGER.total_script_file_obj 345 register_script_file_obj = OPTIONS_MANAGER.register_script_file_obj 346 update_exe_path = os.path.join(OPTIONS_MANAGER.target_package_dir, UPDATE_EXE_FILE_NAME) 347 348 file_obj = tempfile.NamedTemporaryFile(dir=OPTIONS_MANAGER.update_package, prefix="build_tools-") 349 files_to_sign = [] 350 zip_file = zipfile.ZipFile(file_obj.name, 'w', zipfile.ZIP_DEFLATED) 351 # file name will be prefixed by build_tools in hash signed data 352 name_format_str = "build_tools/{}" 353 # add opera_script to build_tools.zip 354 for key, value in opera_script_dict.items(): 355 zip_file.write(key, value) 356 files_to_sign += [(key, name_format_str.format(value))] 357 binary_check = OPTIONS_MANAGER.init.invoke_event(CHECK_BINARY_EVENT) 358 if callable(binary_check) is False or (callable(binary_check) and binary_check() is False): 359 if not os.path.exists(update_exe_path): 360 UPDATE_LOGGER.print_log("updater_binary file does not exist!path: %s" % update_exe_path, 361 log_type=UPDATE_LOGGER.ERROR_LOG) 362 return False 363 # add update_binary to build_tools.zip 364 zip_file.write(update_exe_path, UPDATE_EXE_FILE_NAME) 365 files_to_sign += [(update_exe_path, name_format_str.format(UPDATE_EXE_FILE_NAME))] 366 367 # add loadScript to build_tools.zip 368 zip_file.write(total_script_file_obj.name, TOTAL_SCRIPT_FILE_NAME) 369 files_to_sign += [(total_script_file_obj.name, name_format_str.format(TOTAL_SCRIPT_FILE_NAME))] 370 if OPTIONS_MANAGER.register_script_file_obj is not None: 371 zip_file.write(register_script_file_obj.name, REGISTER_SCRIPT_FILE_NAME) 372 files_to_sign += [(register_script_file_obj.name, name_format_str.format(REGISTER_SCRIPT_FILE_NAME))] 373 374 if create_hsd_for_build_tools(zip_file, files_to_sign) is False: 375 zip_file.close() 376 return False 377 zip_file.close() 378 return file_obj 379 380 381def do_sign_package(update_package, update_file_name): 382 signed_package = os.path.join( 383 update_package, "%s.zip" % update_file_name) 384 OPTIONS_MANAGER.signed_package = signed_package 385 if os.path.exists(signed_package): 386 os.remove(signed_package) 387 388 sign_ota_package = \ 389 OPTIONS_MANAGER.init.invoke_event(SIGN_PACKAGE_EVENT) 390 if sign_ota_package: 391 return sign_ota_package() 392 else: 393 return sign_package() 394 395 396def get_update_file_name(): 397 if OPTIONS_MANAGER.sd_card : 398 package_type = "sd" 399 elif OPTIONS_MANAGER.source_package : 400 package_type = "diff" 401 else : 402 package_type = "full" 403 if OPTIONS_MANAGER.not_l2: 404 update_file_name = ''.join( 405 ["updater_", OPTIONS_MANAGER.target_package_version.replace(" ", "_")]) 406 else : 407 update_file_name = ''.join( 408 ["updater_", package_type]) 409 return update_file_name 410 411 412def do_zip_update_package(): 413 zip_file = zipfile.ZipFile(OPTIONS_MANAGER.update_package_file_path, 414 'w', zipfile.ZIP_DEFLATED, allowZip64=True) 415 # add files to update package 416 do_add_files = OPTIONS_MANAGER.init.invoke_event(ZIP_EVENT) 417 if callable(do_add_files) and do_add_files(zip_file) is False: 418 UPDATE_LOGGER.print_log("add files fail", UPDATE_LOGGER.ERROR_LOG) 419 zip_file.close() 420 return False 421 # add update.bin to update package 422 if not OPTIONS_MANAGER.stream_update: 423 zip_file.write(OPTIONS_MANAGER.update_bin_obj.name, "update.bin") 424 # add build_tools.zip to update package 425 zip_file.write(OPTIONS_MANAGER.build_tools_zip_obj.name, BUILD_TOOLS_FILE_NAME) 426 427 zip_file.write(OPTIONS_MANAGER.board_list_file_path, "board_list") 428 decouple_res = OPTIONS_MANAGER.init.invoke_event(DECOUPLED_EVENT) 429 if decouple_res is False: 430 zip_file.write(OPTIONS_MANAGER.version_mbn_file_path, "version_list") 431 432 if OPTIONS_MANAGER.max_stash_size != 0: 433 max_stash_file_obj = tempfile.NamedTemporaryFile(mode="w+") 434 max_stash_file_obj.write(str(OPTIONS_MANAGER.max_stash_size)) 435 max_stash_file_obj.flush() 436 zip_file.write(max_stash_file_obj.name, "all_max_stash") 437 438 for package_patch_zip in OPTIONS_MANAGER.incremental_block_file_obj_dict.values(): 439 package_patch_zip.package_block_patch(zip_file) 440 441 for partition, patch_obj in OPTIONS_MANAGER.incremental_image_file_obj_dict.items(): 442 zip_file.write(patch_obj.name, "%s.patch.dat" % partition) 443 444 zip_file.close() 445 return True 446 447 448def do_zip_update_bin_package(): 449 zip_file = zipfile.ZipFile(OPTIONS_MANAGER.update_package_file_path, 450 'w', zipfile.ZIP_DEFLATED, allowZip64=True) 451 # add files to update package 452 do_add_files = OPTIONS_MANAGER.init.invoke_event(ZIP_EVENT) 453 if callable(do_add_files) and do_add_files(zip_file) is False: 454 UPDATE_LOGGER.print_log("add files fail", UPDATE_LOGGER.ERROR_LOG) 455 zip_file.close() 456 return False 457 # add update.bin to update package 458 zip_file.write(OPTIONS_MANAGER.update_bin_obj.name, "update.bin") 459 # add build_tools.zip to update package 460 zip_file.write(OPTIONS_MANAGER.build_tools_zip_obj.name, BUILD_TOOLS_FILE_NAME) 461 462 zip_file.write(OPTIONS_MANAGER.board_list_file_path, "board_list") 463 decouple_res = OPTIONS_MANAGER.init.invoke_event(DECOUPLED_EVENT) 464 if decouple_res is False: 465 zip_file.write(OPTIONS_MANAGER.version_mbn_file_path, "version_list") 466 467 if OPTIONS_MANAGER.max_stash_size != 0: 468 max_stash_file_obj = tempfile.NamedTemporaryFile(mode="w+") 469 max_stash_file_obj.write(str(OPTIONS_MANAGER.max_stash_size)) 470 max_stash_file_obj.flush() 471 zip_file.write(max_stash_file_obj.name, "all_max_stash") 472 473 for package_patch_zip in OPTIONS_MANAGER.incremental_block_file_obj_dict.values(): 474 package_patch_zip.package_block_patch(zip_file) 475 476 for partition, patch_obj in OPTIONS_MANAGER.incremental_image_file_obj_dict.items(): 477 zip_file.write(patch_obj.name, "%s.patch.dat" % partition) 478 479 zip_file.close() 480 return True 481 482 483def create_hsd_for_build_tools(zip_file, files_to_sign): 484 """ 485 generate hash signed data for build_tools.zip 486 """ 487 generate_signed_data_ext = OPTIONS_MANAGER.init.invoke_event(GENERATE_SIGNED_DATA_EVENT) 488 signed_data = "" 489 # add hash signed data to build_tools.zip 490 if generate_signed_data_ext is False: 491 signed_data = generate_signed_data_default(files_to_sign) 492 else: 493 signed_data = generate_signed_data_ext(files_to_sign) 494 if signed_data == "": 495 UPDATE_LOGGER.print_log("generate_signed_data failed", log_type=UPDATE_LOGGER.ERROR_LOG) 496 zip_file.close() 497 return False 498 zip_file.writestr("hash_signed_data", signed_data) 499 return True 500 501 502def build_update_package(no_zip, update_package, prelude_script, 503 verse_script, refrain_script, ending_script): 504 """ 505 Create the update package file. 506 :param no_zip: no zip 507 :param update_package: update package path 508 :param prelude_script: prelude object 509 :param verse_script: verse object 510 :param refrain_script: refrain object 511 :param ending_script: ending object 512 :return: If exception occurs, return False. 513 """ 514 if not OPTIONS_MANAGER.stream_update: 515 update_bin_obj = create_update_bin() 516 if update_bin_obj: 517 OPTIONS_MANAGER.update_bin_obj = update_bin_obj 518 else: 519 return False 520 521 update_file_name = get_update_file_name() 522 523 if not no_zip: 524 update_package_path = os.path.join( 525 update_package, '%s_unsigned.zip' % update_file_name) 526 OPTIONS_MANAGER.update_package_file_path = update_package_path 527 528 create_script(prelude_script, verse_script, 529 refrain_script, ending_script) 530 531 build_tools_zip_obj = create_build_tools_zip() 532 if build_tools_zip_obj is False: 533 UPDATE_LOGGER.print_log( 534 "Create build tools zip failed!", 535 log_type=UPDATE_LOGGER.ERROR_LOG) 536 return False 537 OPTIONS_MANAGER.build_tools_zip_obj = build_tools_zip_obj 538 539 if not do_zip_update_package(): 540 UPDATE_LOGGER.print_log("Zip update package fail", UPDATE_LOGGER.ERROR_LOG) 541 return False 542 543 sign_result = do_sign_package(update_package, update_file_name) 544 if not sign_result: 545 UPDATE_LOGGER.print_log("Sign ota package fail", UPDATE_LOGGER.ERROR_LOG) 546 return False 547 548 # 生成update_bin文件,流式本地升级 549 if OPTIONS_MANAGER.stream_update: 550 update_bin_obj = create_update_bin() 551 if update_bin_obj: 552 OPTIONS_MANAGER.update_bin_obj = update_bin_obj 553 else: 554 return False 555 556 if not do_zip_update_bin_package(): 557 UPDATE_LOGGER.print_log("Zip update package fail", UPDATE_LOGGER.ERROR_LOG) 558 return False 559 560 sign_result = do_sign_package(update_package, update_file_name) 561 if not sign_result: 562 UPDATE_LOGGER.print_log("Sign ota package fail", UPDATE_LOGGER.ERROR_LOG) 563 return False 564 UPDATE_LOGGER.print_log("create_update_bin successful %s" % update_package_path, UPDATE_LOGGER.INFO_LOG) 565 566 if os.path.exists(update_package_path): 567 os.remove(update_package_path) 568 569 else: 570 update_package_path = os.path.join( 571 update_package, '%s.bin' % update_file_name) 572 if os.path.exists(update_package_path): 573 os.remove(update_package_path) 574 OPTIONS_MANAGER.update_package_file_path = update_package_path 575 with open(OPTIONS_MANAGER.update_bin_obj.name, 'rb') as r_f: 576 content = r_f.read() 577 with open(update_package_path, 'wb') as w_f: 578 w_f.write(content) 579 return True 580 581 582def get_hash_content(file_path, hash_algorithm): 583 """ 584 Use SHA256SUM to get the hash value of the file. 585 :param file_path : file path 586 :param hash_algorithm: hash algorithm 587 :return hash_content: hash value 588 """ 589 try: 590 cmd = [LINUX_HASH_ALGORITHM_DICT[hash_algorithm], file_path] 591 except KeyError: 592 UPDATE_LOGGER.print_log( 593 "Unsupported hash algorithm! %s" % hash_algorithm, 594 log_type=UPDATE_LOGGER.ERROR_LOG) 595 return False 596 if not os.path.exists(file_path): 597 UPDATE_LOGGER.print_log( 598 "%s failed!" % LINUX_HASH_ALGORITHM_DICT[hash_algorithm], 599 UPDATE_LOGGER.ERROR_LOG) 600 raise RuntimeError 601 process_obj = subprocess.Popen( 602 cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 603 process_obj.wait() 604 hash_content = \ 605 process_obj.stdout.read().decode(encoding='gbk').split(' ')[0] 606 if len(hash_content) != HASH_CONTENT_LEN_DICT.get(hash_algorithm): 607 UPDATE_LOGGER.print_log( 608 "Get hash content failed! The length of the hash_content is 0!", 609 UPDATE_LOGGER.ERROR_LOG) 610 raise RuntimeError 611 if process_obj.returncode == 0: 612 UPDATE_LOGGER.print_log( 613 "Get hash content success! path: %s" % file_path) 614 return hash_content 615