140681896Sopenharmony_ci#!/usr/bin/env python3 240681896Sopenharmony_ci# -*- coding: utf-8 -*- 340681896Sopenharmony_ci 440681896Sopenharmony_ci# Copyright (c) 2021 Huawei Device Co., Ltd. 540681896Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 640681896Sopenharmony_ci# you may not use this file except in compliance with the License. 740681896Sopenharmony_ci# You may obtain a copy of the License at 840681896Sopenharmony_ci# 940681896Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 1040681896Sopenharmony_ci# 1140681896Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 1240681896Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 1340681896Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1440681896Sopenharmony_ci# See the License for the specific language governing permissions and 1540681896Sopenharmony_ci# limitations under the License. 1640681896Sopenharmony_ciimport bisect 1740681896Sopenharmony_ciimport copy 1840681896Sopenharmony_ciimport os 1940681896Sopenharmony_ciimport struct 2040681896Sopenharmony_ciimport tempfile 2140681896Sopenharmony_cifrom hashlib import sha256 2240681896Sopenharmony_ci 2340681896Sopenharmony_cifrom log_exception import UPDATE_LOGGER 2440681896Sopenharmony_cifrom blocks_manager import BlocksManager 2540681896Sopenharmony_cifrom utils import OPTIONS_MANAGER 2640681896Sopenharmony_cifrom utils import EXTEND_VALUE 2740681896Sopenharmony_cifrom utils import FILE_MAP_ZERO_KEY 2840681896Sopenharmony_cifrom utils import FILE_MAP_NONZERO_KEY 2940681896Sopenharmony_cifrom utils import FILE_MAP_COPY_KEY 3040681896Sopenharmony_cifrom utils import MAX_BLOCKS_PER_GROUP 3140681896Sopenharmony_cifrom utils import UPDATE_BIN_FILE_NAME 3240681896Sopenharmony_cifrom utils import FORBIDEN_UPDATE_IMAGE_SET 3340681896Sopenharmony_ci 3440681896Sopenharmony_ci 3540681896Sopenharmony_ciclass FullUpdateImage: 3640681896Sopenharmony_ci """ 3740681896Sopenharmony_ci Full image processing class 3840681896Sopenharmony_ci """ 3940681896Sopenharmony_ci 4040681896Sopenharmony_ci def __init__(self, target_package_images_dir, 4140681896Sopenharmony_ci full_img_list, full_img_name_list, 4240681896Sopenharmony_ci verse_script, full_image_path_list, 4340681896Sopenharmony_ci no_zip=False): 4440681896Sopenharmony_ci self.target_package_images_dir = target_package_images_dir 4540681896Sopenharmony_ci self.full_img_list = full_img_list 4640681896Sopenharmony_ci self.full_img_name_list = full_img_name_list 4740681896Sopenharmony_ci self.verse_script = verse_script 4840681896Sopenharmony_ci self.full_image_path_list = full_image_path_list 4940681896Sopenharmony_ci self.no_zip = no_zip 5040681896Sopenharmony_ci 5140681896Sopenharmony_ci def update_full_image(self): 5240681896Sopenharmony_ci """ 5340681896Sopenharmony_ci Processing of the full image 5440681896Sopenharmony_ci :return full_image_content_len_list: full image content length list 5540681896Sopenharmony_ci :return full_image_file_obj_list: full image temporary file list 5640681896Sopenharmony_ci """ 5740681896Sopenharmony_ci full_image_file_obj_list = [] 5840681896Sopenharmony_ci full_image_content_len_list = [] 5940681896Sopenharmony_ci for idx, each_name in enumerate(self.full_img_list): 6040681896Sopenharmony_ci full_image_content = self.get_full_image_content( 6140681896Sopenharmony_ci self.full_image_path_list[idx]) 6240681896Sopenharmony_ci img_name = self.full_img_name_list[idx][:-4] 6340681896Sopenharmony_ci if full_image_content is False: 6440681896Sopenharmony_ci UPDATE_LOGGER.print_log( 6540681896Sopenharmony_ci "Get full image content failed!", 6640681896Sopenharmony_ci log_type=UPDATE_LOGGER.ERROR_LOG) 6740681896Sopenharmony_ci return False, False 6840681896Sopenharmony_ci each_img = tempfile.NamedTemporaryFile( 6940681896Sopenharmony_ci dir=self.target_package_images_dir, 7040681896Sopenharmony_ci prefix="full_image%s" % img_name, mode='wb') 7140681896Sopenharmony_ci each_img.write(full_image_content) 7240681896Sopenharmony_ci each_img.seek(0) 7340681896Sopenharmony_ci full_image_content_len_list.append(len(full_image_content)) 7440681896Sopenharmony_ci full_image_file_obj_list.append(each_img) 7540681896Sopenharmony_ci UPDATE_LOGGER.print_log( 7640681896Sopenharmony_ci "Image %s full processing completed" % img_name) 7740681896Sopenharmony_ci update_image_set = set(self.full_img_list) - FORBIDEN_UPDATE_IMAGE_SET 7840681896Sopenharmony_ci if not self.no_zip and len(update_image_set) != 0: 7940681896Sopenharmony_ci # No zip mode (no script command) 8040681896Sopenharmony_ci image_write_cmd = self.verse_script.full_image_update(UPDATE_BIN_FILE_NAME) 8140681896Sopenharmony_ci cmd = '%s_WRITE_FLAG%s' % (UPDATE_BIN_FILE_NAME, image_write_cmd) 8240681896Sopenharmony_ci if each_name not in FORBIDEN_UPDATE_IMAGE_SET: 8340681896Sopenharmony_ci self.verse_script.add_command(cmd=cmd) 8440681896Sopenharmony_ci 8540681896Sopenharmony_ci UPDATE_LOGGER.print_log( 8640681896Sopenharmony_ci "All full image processing completed! image count: %d" % 8740681896Sopenharmony_ci len(self.full_img_list)) 8840681896Sopenharmony_ci return full_image_content_len_list, full_image_file_obj_list 8940681896Sopenharmony_ci 9040681896Sopenharmony_ci @staticmethod 9140681896Sopenharmony_ci def get_full_image_content(each_name): 9240681896Sopenharmony_ci """ 9340681896Sopenharmony_ci Obtain the full image content. 9440681896Sopenharmony_ci :param each_name: image name 9540681896Sopenharmony_ci :return content: full image content if available; false otherwise 9640681896Sopenharmony_ci """ 9740681896Sopenharmony_ci each_image_path = each_name 9840681896Sopenharmony_ci if not os.path.exists(each_image_path): 9940681896Sopenharmony_ci UPDATE_LOGGER.print_log( 10040681896Sopenharmony_ci "The file is missing " 10140681896Sopenharmony_ci "from the target package, " 10240681896Sopenharmony_ci "the component: %s cannot be full update processed. " % 10340681896Sopenharmony_ci each_image_path) 10440681896Sopenharmony_ci return False 10540681896Sopenharmony_ci with open(each_image_path, 'rb') as f_r: 10640681896Sopenharmony_ci content = f_r.read() 10740681896Sopenharmony_ci return content 10840681896Sopenharmony_ci 10940681896Sopenharmony_ci 11040681896Sopenharmony_ciclass IncUpdateImage: 11140681896Sopenharmony_ci """ 11240681896Sopenharmony_ci Increment update image class 11340681896Sopenharmony_ci """ 11440681896Sopenharmony_ci 11540681896Sopenharmony_ci def __init__(self, image_path, map_path): 11640681896Sopenharmony_ci """ 11740681896Sopenharmony_ci Initialize the inc image. 11840681896Sopenharmony_ci :param image_path: img file path 11940681896Sopenharmony_ci :param map_path: map file path 12040681896Sopenharmony_ci """ 12140681896Sopenharmony_ci self.image_path = image_path 12240681896Sopenharmony_ci self.map_path = map_path 12340681896Sopenharmony_ci self.offset_value_list = [] 12440681896Sopenharmony_ci self.care_block_range = None 12540681896Sopenharmony_ci self.extended_range = None 12640681896Sopenharmony_ci self.reserved_blocks = BlocksManager("0") 12740681896Sopenharmony_ci self.file_map = [] 12840681896Sopenharmony_ci self.offset_index = [] 12940681896Sopenharmony_ci self.block_size = None 13040681896Sopenharmony_ci self.total_blocks = None 13140681896Sopenharmony_ci self.parse_raw_image_file(image_path, map_path) 13240681896Sopenharmony_ci 13340681896Sopenharmony_ci def parse_raw_image_file(self, image_path, map_path): 13440681896Sopenharmony_ci """ 13540681896Sopenharmony_ci Parse the .img file. 13640681896Sopenharmony_ci :param image_path: img file path 13740681896Sopenharmony_ci :param map_path: map file path 13840681896Sopenharmony_ci """ 13940681896Sopenharmony_ci self.block_size = block_size = 4096 14040681896Sopenharmony_ci self.total_blocks = total_blocks = \ 14140681896Sopenharmony_ci os.path.getsize(self.image_path) // self.block_size 14240681896Sopenharmony_ci reference = b'\0' * self.block_size 14340681896Sopenharmony_ci with open(image_path, 'rb') as f_r: 14440681896Sopenharmony_ci care_value_list, offset_value_list = [], [] 14540681896Sopenharmony_ci nonzero_blocks = [] 14640681896Sopenharmony_ci for i in range(self.total_blocks): 14740681896Sopenharmony_ci blocks_data = f_r.read(self.block_size) 14840681896Sopenharmony_ci if blocks_data != reference: 14940681896Sopenharmony_ci nonzero_blocks.append(i) 15040681896Sopenharmony_ci nonzero_blocks.append(i + 1) 15140681896Sopenharmony_ci self.care_block_range = BlocksManager(nonzero_blocks) 15240681896Sopenharmony_ci care_value_list = list(self.care_block_range.range_data) 15340681896Sopenharmony_ci for idx, value in enumerate(care_value_list): 15440681896Sopenharmony_ci if idx != 0 and (idx + 1) % 2 == 0: 15540681896Sopenharmony_ci be_value = int(care_value_list[idx - 1]) 15640681896Sopenharmony_ci af_value = int(care_value_list[idx]) 15740681896Sopenharmony_ci file_tell = be_value * block_size 15840681896Sopenharmony_ci offset_value_list.append( 15940681896Sopenharmony_ci (be_value, af_value - be_value, 16040681896Sopenharmony_ci file_tell, None)) 16140681896Sopenharmony_ci 16240681896Sopenharmony_ci self.offset_index = [i[0] for i in offset_value_list] 16340681896Sopenharmony_ci self.offset_value_list = offset_value_list 16440681896Sopenharmony_ci extended_range = \ 16540681896Sopenharmony_ci self.care_block_range.extend_value_to_blocks(EXTEND_VALUE) 16640681896Sopenharmony_ci all_blocks = BlocksManager(range_data=(0, total_blocks)) 16740681896Sopenharmony_ci self.extended_range = \ 16840681896Sopenharmony_ci extended_range.get_intersect_with_other(all_blocks). \ 16940681896Sopenharmony_ci get_subtract_with_other(self.care_block_range) 17040681896Sopenharmony_ci self.parse_block_map_file(map_path, f_r) 17140681896Sopenharmony_ci 17240681896Sopenharmony_ci def parse_block_map_file(self, map_path, image_file_r): 17340681896Sopenharmony_ci """ 17440681896Sopenharmony_ci Parses the map file for blocks where files are contained in the image. 17540681896Sopenharmony_ci :param map_path: map file path 17640681896Sopenharmony_ci :param image_file_r: file reading object 17740681896Sopenharmony_ci :return: 17840681896Sopenharmony_ci """ 17940681896Sopenharmony_ci remain_range = self.care_block_range 18040681896Sopenharmony_ci temp_file_map = {} 18140681896Sopenharmony_ci 18240681896Sopenharmony_ci with open(map_path, 'r') as f_r: 18340681896Sopenharmony_ci # Read the .map file and process each line. 18440681896Sopenharmony_ci for each_line in f_r.readlines(): 18540681896Sopenharmony_ci each_map_path, ranges_value = each_line.split(None, 1) 18640681896Sopenharmony_ci each_range = BlocksManager(ranges_value) 18740681896Sopenharmony_ci each_range = each_range.get_subtract_with_other(BlocksManager("0")) 18840681896Sopenharmony_ci # each_range may not contained in the remain range. 18940681896Sopenharmony_ci intersect_range = each_range.get_intersect_with_other(remain_range) 19040681896Sopenharmony_ci if each_range.size() != intersect_range.size(): 19140681896Sopenharmony_ci each_range = intersect_range 19240681896Sopenharmony_ci temp_file_map[each_map_path] = each_range 19340681896Sopenharmony_ci # After the processing is complete, 19440681896Sopenharmony_ci # remove each_range from remain_range. 19540681896Sopenharmony_ci remain_range = remain_range.get_subtract_with_other(each_range) 19640681896Sopenharmony_ci reserved_blocks = self.reserved_blocks 19740681896Sopenharmony_ci # Remove reserved blocks from all blocks. 19840681896Sopenharmony_ci remain_range = remain_range.get_subtract_with_other(reserved_blocks) 19940681896Sopenharmony_ci 20040681896Sopenharmony_ci # Divide all blocks into zero_blocks 20140681896Sopenharmony_ci # (if there are many) and nonzero_blocks. 20240681896Sopenharmony_ci zero_blocks_list = [] 20340681896Sopenharmony_ci nonzero_blocks_list = [] 20440681896Sopenharmony_ci nonzero_groups_list = [] 20540681896Sopenharmony_ci default_zero_block = ('\0' * self.block_size).encode() 20640681896Sopenharmony_ci 20740681896Sopenharmony_ci nonzero_blocks_list, nonzero_groups_list, zero_blocks_list = \ 20840681896Sopenharmony_ci self.apply_remain_range( 20940681896Sopenharmony_ci default_zero_block, image_file_r, nonzero_blocks_list, 21040681896Sopenharmony_ci nonzero_groups_list, remain_range, zero_blocks_list) 21140681896Sopenharmony_ci 21240681896Sopenharmony_ci temp_file_map = self.get_file_map( 21340681896Sopenharmony_ci nonzero_blocks_list, nonzero_groups_list, 21440681896Sopenharmony_ci reserved_blocks, temp_file_map, zero_blocks_list) 21540681896Sopenharmony_ci self.file_map = temp_file_map 21640681896Sopenharmony_ci 21740681896Sopenharmony_ci def apply_remain_range(self, *args): 21840681896Sopenharmony_ci """ 21940681896Sopenharmony_ci Implement traversal processing of remain_range. 22040681896Sopenharmony_ci """ 22140681896Sopenharmony_ci default_zero_block, image_file_r, \ 22240681896Sopenharmony_ci nonzero_blocks_list, nonzero_groups_list, \ 22340681896Sopenharmony_ci remain_range, zero_blocks_list = args 22440681896Sopenharmony_ci for start_value, end_value in remain_range: 22540681896Sopenharmony_ci for each_value in range(start_value, end_value): 22640681896Sopenharmony_ci # bisect 二分查找,b在self.offset_index中的位置 22740681896Sopenharmony_ci idx = bisect.bisect_right(self.offset_index, each_value) - 1 22840681896Sopenharmony_ci chunk_start, _, file_pos, fill_data = \ 22940681896Sopenharmony_ci self.offset_value_list[idx] 23040681896Sopenharmony_ci data = self.get_file_data(self.block_size, chunk_start, 23140681896Sopenharmony_ci default_zero_block, each_value, 23240681896Sopenharmony_ci file_pos, fill_data, image_file_r) 23340681896Sopenharmony_ci 23440681896Sopenharmony_ci zero_blocks_list, nonzero_blocks_list, nonzero_groups_list = \ 23540681896Sopenharmony_ci self.get_zero_nonzero_blocks_list( 23640681896Sopenharmony_ci data, default_zero_block, each_value, 23740681896Sopenharmony_ci nonzero_blocks_list, nonzero_groups_list, 23840681896Sopenharmony_ci zero_blocks_list) 23940681896Sopenharmony_ci return nonzero_blocks_list, nonzero_groups_list, zero_blocks_list 24040681896Sopenharmony_ci 24140681896Sopenharmony_ci @staticmethod 24240681896Sopenharmony_ci def get_file_map(*args): 24340681896Sopenharmony_ci """ 24440681896Sopenharmony_ci Obtain the file map. 24540681896Sopenharmony_ci nonzero_blocks_list nonzero blocks list, 24640681896Sopenharmony_ci nonzero_groups_list nonzero groups list, 24740681896Sopenharmony_ci reserved_blocks reserved blocks , 24840681896Sopenharmony_ci temp_file_map temporary file map, 24940681896Sopenharmony_ci zero_blocks_list zero block list 25040681896Sopenharmony_ci :return temp_file_map file map 25140681896Sopenharmony_ci """ 25240681896Sopenharmony_ci nonzero_blocks_list, nonzero_groups_list, \ 25340681896Sopenharmony_ci reserved_blocks, temp_file_map, zero_blocks_list = args 25440681896Sopenharmony_ci if nonzero_blocks_list: 25540681896Sopenharmony_ci nonzero_groups_list.append(nonzero_blocks_list) 25640681896Sopenharmony_ci if zero_blocks_list: 25740681896Sopenharmony_ci temp_file_map[FILE_MAP_ZERO_KEY] = \ 25840681896Sopenharmony_ci BlocksManager(range_data=zero_blocks_list) 25940681896Sopenharmony_ci if nonzero_groups_list: 26040681896Sopenharmony_ci for i, blocks in enumerate(nonzero_groups_list): 26140681896Sopenharmony_ci temp_file_map["%s-%d" % (FILE_MAP_NONZERO_KEY, i)] = \ 26240681896Sopenharmony_ci BlocksManager(range_data=blocks) 26340681896Sopenharmony_ci if reserved_blocks: 26440681896Sopenharmony_ci temp_file_map[FILE_MAP_COPY_KEY] = reserved_blocks 26540681896Sopenharmony_ci return temp_file_map 26640681896Sopenharmony_ci 26740681896Sopenharmony_ci @staticmethod 26840681896Sopenharmony_ci def get_zero_nonzero_blocks_list(*args): 26940681896Sopenharmony_ci """ 27040681896Sopenharmony_ci Get zero_blocks_list, nonzero_blocks_list, and nonzero_groups_list. 27140681896Sopenharmony_ci data: block data, 27240681896Sopenharmony_ci default_zero_block: default to zero block, 27340681896Sopenharmony_ci each_value: each value, 27440681896Sopenharmony_ci nonzero_blocks_list: nonzero_blocks_list, 27540681896Sopenharmony_ci nonzero_groups_list: nonzero_groups_list, 27640681896Sopenharmony_ci zero_blocks_list: zero_blocks_list, 27740681896Sopenharmony_ci :return new_zero_blocks_list: new zero blocks list, 27840681896Sopenharmony_ci :return new_nonzero_blocks_list: new nonzero blocks list, 27940681896Sopenharmony_ci :return new_nonzero_groups_list: new nonzero groups list. 28040681896Sopenharmony_ci """ 28140681896Sopenharmony_ci data, default_zero_block, each_value, \ 28240681896Sopenharmony_ci nonzero_blocks_list, nonzero_groups_list, \ 28340681896Sopenharmony_ci zero_blocks_list = args 28440681896Sopenharmony_ci # Check whether the data block is equal to the default zero_blocks. 28540681896Sopenharmony_ci if data == default_zero_block: 28640681896Sopenharmony_ci zero_blocks_list.append(each_value) 28740681896Sopenharmony_ci zero_blocks_list.append(each_value + 1) 28840681896Sopenharmony_ci else: 28940681896Sopenharmony_ci nonzero_blocks_list.append(each_value) 29040681896Sopenharmony_ci nonzero_blocks_list.append(each_value + 1) 29140681896Sopenharmony_ci # The number of nonzero_blocks is greater than 29240681896Sopenharmony_ci # or equal to the upper limit. 29340681896Sopenharmony_ci if len(nonzero_blocks_list) >= MAX_BLOCKS_PER_GROUP: 29440681896Sopenharmony_ci nonzero_groups_list.append(nonzero_blocks_list) 29540681896Sopenharmony_ci nonzero_blocks_list = [] 29640681896Sopenharmony_ci new_zero_blocks_list, new_nonzero_blocks_list, \ 29740681896Sopenharmony_ci new_nonzero_groups_list = \ 29840681896Sopenharmony_ci copy.copy(zero_blocks_list), \ 29940681896Sopenharmony_ci copy.copy(nonzero_blocks_list),\ 30040681896Sopenharmony_ci copy.copy(nonzero_groups_list) 30140681896Sopenharmony_ci return new_zero_blocks_list, new_nonzero_blocks_list, \ 30240681896Sopenharmony_ci new_nonzero_groups_list 30340681896Sopenharmony_ci 30440681896Sopenharmony_ci @staticmethod 30540681896Sopenharmony_ci def get_file_data(*args): 30640681896Sopenharmony_ci """ 30740681896Sopenharmony_ci Get the file data. 30840681896Sopenharmony_ci block_size: blocksize, 30940681896Sopenharmony_ci chunk_start: the start position of chunk, 31040681896Sopenharmony_ci default_zero_block: default to zero blocks, 31140681896Sopenharmony_ci each_value: each_value, 31240681896Sopenharmony_ci file_pos: file position, 31340681896Sopenharmony_ci fill_data: data, 31440681896Sopenharmony_ci image_file_r: read file object, 31540681896Sopenharmony_ci :return data: Get the file data. 31640681896Sopenharmony_ci """ 31740681896Sopenharmony_ci block_size, chunk_start, default_zero_block, each_value, \ 31840681896Sopenharmony_ci file_pos, fill_data, image_file_r = args 31940681896Sopenharmony_ci if file_pos is not None: 32040681896Sopenharmony_ci file_pos += (each_value - chunk_start) * block_size 32140681896Sopenharmony_ci image_file_r.seek(file_pos, os.SEEK_SET) 32240681896Sopenharmony_ci data = image_file_r.read(block_size) 32340681896Sopenharmony_ci else: 32440681896Sopenharmony_ci if fill_data == default_zero_block[:4]: 32540681896Sopenharmony_ci data = default_zero_block 32640681896Sopenharmony_ci else: 32740681896Sopenharmony_ci data = None 32840681896Sopenharmony_ci return data 32940681896Sopenharmony_ci 33040681896Sopenharmony_ci def range_sha256(self, ranges): 33140681896Sopenharmony_ci """ 33240681896Sopenharmony_ci range sha256 hash content 33340681896Sopenharmony_ci :param ranges: ranges value 33440681896Sopenharmony_ci :return: 33540681896Sopenharmony_ci """ 33640681896Sopenharmony_ci hash_obj = sha256() 33740681896Sopenharmony_ci for data in self.__get_blocks_set_data(ranges): 33840681896Sopenharmony_ci hash_obj.update(data) 33940681896Sopenharmony_ci return hash_obj.hexdigest() 34040681896Sopenharmony_ci 34140681896Sopenharmony_ci def write_range_data_2_fd(self, ranges, file_obj): 34240681896Sopenharmony_ci """ 34340681896Sopenharmony_ci write range data to fd 34440681896Sopenharmony_ci :param ranges: ranges obj 34540681896Sopenharmony_ci :param file_obj: file obj 34640681896Sopenharmony_ci :return: 34740681896Sopenharmony_ci """ 34840681896Sopenharmony_ci for data in self.__get_blocks_set_data(ranges): 34940681896Sopenharmony_ci file_obj.write(data) 35040681896Sopenharmony_ci 35140681896Sopenharmony_ci def get_ranges(self, ranges): 35240681896Sopenharmony_ci """ 35340681896Sopenharmony_ci get ranges value 35440681896Sopenharmony_ci :param ranges: ranges 35540681896Sopenharmony_ci :return: ranges value 35640681896Sopenharmony_ci """ 35740681896Sopenharmony_ci return [each_data for each_data in self.__get_blocks_set_data(ranges)] 35840681896Sopenharmony_ci 35940681896Sopenharmony_ci def __get_blocks_set_data(self, blocks_set_data): 36040681896Sopenharmony_ci """ 36140681896Sopenharmony_ci Get the range data. 36240681896Sopenharmony_ci """ 36340681896Sopenharmony_ci with open(self.image_path, 'rb') as f_r: 36440681896Sopenharmony_ci for start, end in blocks_set_data: 36540681896Sopenharmony_ci diff_value = end - start 36640681896Sopenharmony_ci idx = bisect.bisect_right(self.offset_index, start) - 1 36740681896Sopenharmony_ci chunk_start, chunk_len, file_pos, fill_data = \ 36840681896Sopenharmony_ci self.offset_value_list[idx] 36940681896Sopenharmony_ci 37040681896Sopenharmony_ci remain = chunk_len - (start - chunk_start) 37140681896Sopenharmony_ci this_read = min(remain, diff_value) 37240681896Sopenharmony_ci if file_pos is not None: 37340681896Sopenharmony_ci pos = file_pos + ((start - chunk_start) * self.block_size) 37440681896Sopenharmony_ci f_r.seek(pos, os.SEEK_SET) 37540681896Sopenharmony_ci yield f_r.read(this_read * self.block_size) 37640681896Sopenharmony_ci else: 37740681896Sopenharmony_ci yield fill_data * (this_read * (self.block_size >> 2)) 37840681896Sopenharmony_ci diff_value -= this_read 37940681896Sopenharmony_ci 38040681896Sopenharmony_ci while diff_value > 0: 38140681896Sopenharmony_ci idx += 1 38240681896Sopenharmony_ci chunk_start, chunk_len, file_pos, fill_data = \ 38340681896Sopenharmony_ci self.offset_value_list[idx] 38440681896Sopenharmony_ci this_read = min(chunk_len, diff_value) 38540681896Sopenharmony_ci if file_pos is not None: 38640681896Sopenharmony_ci f_r.seek(file_pos, os.SEEK_SET) 38740681896Sopenharmony_ci yield f_r.read(this_read * self.block_size) 38840681896Sopenharmony_ci else: 38940681896Sopenharmony_ci yield fill_data * (this_read * (self.block_size >> 2)) 39040681896Sopenharmony_ci diff_value -= this_read