15f9996aaSopenharmony_ci#!/usr/bin/env python 25f9996aaSopenharmony_ci# coding: utf-8 35f9996aaSopenharmony_ci# Copyright (c) 2022 Huawei Device Co., Ltd. 45f9996aaSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 55f9996aaSopenharmony_ci# you may not use this file except in compliance with the License. 65f9996aaSopenharmony_ci# You may obtain a copy of the License at 75f9996aaSopenharmony_ci# 85f9996aaSopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 95f9996aaSopenharmony_ci# 105f9996aaSopenharmony_ci# Unless required by applicable law or agreed to in writing, software 115f9996aaSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 125f9996aaSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135f9996aaSopenharmony_ci# See the License for the specific language governing permissions and 145f9996aaSopenharmony_ci# limitations under the License. 155f9996aaSopenharmony_ci 165f9996aaSopenharmony_ciimport sys 175f9996aaSopenharmony_ciimport os 185f9996aaSopenharmony_ciimport hashlib 195f9996aaSopenharmony_ciimport errno 205f9996aaSopenharmony_ciimport stat 215f9996aaSopenharmony_ciimport datetime 225f9996aaSopenharmony_ci 235f9996aaSopenharmony_ci 245f9996aaSopenharmony_cidef usage(): 255f9996aaSopenharmony_ci print('\n Usage: imgcovert.py <cmd> <input> <output>') 265f9996aaSopenharmony_ci print(' <cmd>: sparse or unsparse') 275f9996aaSopenharmony_ci print(' <input>: input image file') 285f9996aaSopenharmony_ci print(' <output>: ouput image file\n') 295f9996aaSopenharmony_ci return 305f9996aaSopenharmony_ci 315f9996aaSopenharmony_ci 325f9996aaSopenharmony_cidef get_fill_cnt(inputfile: str, blocksize: int) -> int: 335f9996aaSopenharmony_ci flags = os.O_WRONLY 345f9996aaSopenharmony_ci modes = stat.S_IWUSR | stat.S_IRUSR 355f9996aaSopenharmony_ci size = os.path.getsize(inputfile) 365f9996aaSopenharmony_ci fill_cnt = 0 375f9996aaSopenharmony_ci if size % blocksize != 0: 385f9996aaSopenharmony_ci fill_cnt = blocksize - size % blocksize 395f9996aaSopenharmony_ci indata = os.fdopen(os.open(inputfile, flags, modes), 'a') 405f9996aaSopenharmony_ci for _ in range(fill_cnt): 415f9996aaSopenharmony_ci indata.write("\0") 425f9996aaSopenharmony_ci indata.close() 435f9996aaSopenharmony_ci return fill_cnt 445f9996aaSopenharmony_ci 455f9996aaSopenharmony_ci 465f9996aaSopenharmony_cidef get_gap_blocksize(length: int, size: int) -> int: 475f9996aaSopenharmony_ci if length < size: 485f9996aaSopenharmony_ci cnt = 2 495f9996aaSopenharmony_ci elif length < (size * 2): 505f9996aaSopenharmony_ci cnt = 3 515f9996aaSopenharmony_ci else: 525f9996aaSopenharmony_ci cnt = 4 535f9996aaSopenharmony_ci return cnt 545f9996aaSopenharmony_ci 555f9996aaSopenharmony_ci 565f9996aaSopenharmony_cidef get_block_cnt(inputfile: str, blocksize: int) -> int: 575f9996aaSopenharmony_ci size = os.path.getsize(inputfile) 585f9996aaSopenharmony_ci if blocksize != 0: 595f9996aaSopenharmony_ci totalblocks = size / blocksize 605f9996aaSopenharmony_ci else: 615f9996aaSopenharmony_ci sys.exit(1) 625f9996aaSopenharmony_ci if (size % blocksize) != 0: 635f9996aaSopenharmony_ci print("len is not eq n * blocksize: ", size, totalblocks) 645f9996aaSopenharmony_ci return totalblocks 655f9996aaSopenharmony_ci 665f9996aaSopenharmony_ci 675f9996aaSopenharmony_cidef get_crc_value(inputfile: str, blocksize: int): 685f9996aaSopenharmony_ci totalblocks = get_block_cnt(inputfile, blocksize) 695f9996aaSopenharmony_ci with open(inputfile, 'rb') as indata: 705f9996aaSopenharmony_ci ind = 0 715f9996aaSopenharmony_ci md5 = hashlib.md5() 725f9996aaSopenharmony_ci while (ind < totalblocks): 735f9996aaSopenharmony_ci md5.update(indata.read(blocksize)) 745f9996aaSopenharmony_ci ind += 1 755f9996aaSopenharmony_ci return md5.hexdigest() 765f9996aaSopenharmony_ci 775f9996aaSopenharmony_ci 785f9996aaSopenharmony_cidef unsparse(sparseimagefile: str, imagefile: str): 795f9996aaSopenharmony_ci with open(sparseimagefile, 'r') as header: 805f9996aaSopenharmony_ci magic_mumber = header.readline() 815f9996aaSopenharmony_ci version = header.readline() 825f9996aaSopenharmony_ci blocksize = int(header.readline()) 835f9996aaSopenharmony_ci total_blocks = int(header.readline()) 845f9996aaSopenharmony_ci crc_value = header.readline() 855f9996aaSopenharmony_ci input_crc_value = header.readline() 865f9996aaSopenharmony_ci table_numbers = int(header.readline()) 875f9996aaSopenharmony_ci table = [] 885f9996aaSopenharmony_ci flags = os.O_CREAT | os.O_RDWR 895f9996aaSopenharmony_ci modes = stat.S_IWUSR | stat.S_IRUSR 905f9996aaSopenharmony_ci i = 0 915f9996aaSopenharmony_ci while (i < table_numbers): 925f9996aaSopenharmony_ci start = int(header.readline()) 935f9996aaSopenharmony_ci end = int(header.readline()) 945f9996aaSopenharmony_ci table.append([start, end]) 955f9996aaSopenharmony_ci i += 1 965f9996aaSopenharmony_ci fill_cnt = int(header.readline()) 975f9996aaSopenharmony_ci length = header.tell() 985f9996aaSopenharmony_ci with open(sparseimagefile, 'rb') as inputrow: 995f9996aaSopenharmony_ci inputrow.seek(get_gap_blocksize(length, blocksize) * blocksize) 1005f9996aaSopenharmony_ci output = os.fdopen(os.open(imagefile, flags, modes), 'wb') 1015f9996aaSopenharmony_ci output.truncate(total_blocks * blocksize) 1025f9996aaSopenharmony_ci md5 = hashlib.md5() 1035f9996aaSopenharmony_ci for block in table: 1045f9996aaSopenharmony_ci cnt = block[1] - block[0] 1055f9996aaSopenharmony_ci output.seek(block[0] * blocksize) 1065f9996aaSopenharmony_ci indata = inputrow.read(cnt * blocksize) 1075f9996aaSopenharmony_ci md5.update(indata) 1085f9996aaSopenharmony_ci output.write(indata) 1095f9996aaSopenharmony_ci output.close() 1105f9996aaSopenharmony_ci print("RawFileCRC: ", get_crc_value(imagefile, blocksize), crc_value) 1115f9996aaSopenharmony_ci print("SparseCRC: ", md5.hexdigest(), input_crc_value) 1125f9996aaSopenharmony_ci with open(imagefile, 'r+') as output: 1135f9996aaSopenharmony_ci output.truncate(total_blocks * blocksize - fill_cnt) 1145f9996aaSopenharmony_ci return 1155f9996aaSopenharmony_ci 1165f9996aaSopenharmony_ci 1175f9996aaSopenharmony_cidef is_empty_block(buff: list, size: int) -> bool: 1185f9996aaSopenharmony_ci ind = 0 1195f9996aaSopenharmony_ci while (ind < size): 1205f9996aaSopenharmony_ci if buff[ind] != 0: 1215f9996aaSopenharmony_ci return False 1225f9996aaSopenharmony_ci ind += 1 1235f9996aaSopenharmony_ci return True 1245f9996aaSopenharmony_ci 1255f9996aaSopenharmony_ci 1265f9996aaSopenharmony_cidef process_block(inputrow, blocksize, outputtemp, blockid, total_blocks) -> int: 1275f9996aaSopenharmony_ci ind = 0 1285f9996aaSopenharmony_ci start = -1 1295f9996aaSopenharmony_ci table_numbers = 0 1305f9996aaSopenharmony_ci while (ind < total_blocks): 1315f9996aaSopenharmony_ci indata = inputrow.read(blocksize) 1325f9996aaSopenharmony_ci if len(indata) != blocksize: 1335f9996aaSopenharmony_ci print("error Block", ind, len(indata)) 1345f9996aaSopenharmony_ci if is_empty_block(indata, blocksize): 1355f9996aaSopenharmony_ci if start != -1: 1365f9996aaSopenharmony_ci blockid.append([start, ind]) 1375f9996aaSopenharmony_ci table_numbers += 1 1385f9996aaSopenharmony_ci start = -1 1395f9996aaSopenharmony_ci else: 1405f9996aaSopenharmony_ci outputtemp.write(indata) 1415f9996aaSopenharmony_ci if start == -1: 1425f9996aaSopenharmony_ci start = ind 1435f9996aaSopenharmony_ci ind += 1 1445f9996aaSopenharmony_ci if start != -1: 1455f9996aaSopenharmony_ci blockid.append([start, ind]) 1465f9996aaSopenharmony_ci table_numbers += 1 1475f9996aaSopenharmony_ci start = -1 1485f9996aaSopenharmony_ci return table_numbers 1495f9996aaSopenharmony_ci 1505f9996aaSopenharmony_ci 1515f9996aaSopenharmony_cidef get_raw_datafile(imagefile: str, blockid, total_blocks: int, blocksize: int) -> int: 1525f9996aaSopenharmony_ci temp_file = imagefile + ".tempfile" 1535f9996aaSopenharmony_ci flags = os.O_CREAT | os.O_RDWR 1545f9996aaSopenharmony_ci modes = stat.S_IWUSR | stat.S_IRUSR 1555f9996aaSopenharmony_ci table_numbers = 0 1565f9996aaSopenharmony_ci with open(imagefile, 'rb') as inputrow, os.fdopen(os.open(temp_file, flags, modes), 'wb') as outputtemp: 1575f9996aaSopenharmony_ci table_numbers = process_block(inputrow, blocksize, outputtemp, blockid, total_blocks) 1585f9996aaSopenharmony_ci return table_numbers 1595f9996aaSopenharmony_ci 1605f9996aaSopenharmony_ci 1615f9996aaSopenharmony_cidef sparse(imagefile: str, sparseimagefile: str): 1625f9996aaSopenharmony_ci temp_file = imagefile + ".tempfile" 1635f9996aaSopenharmony_ci magic_number = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") 1645f9996aaSopenharmony_ci version = 1.0 1655f9996aaSopenharmony_ci blocksize = 4096 1665f9996aaSopenharmony_ci table_numbers = 0 1675f9996aaSopenharmony_ci blockid = [] 1685f9996aaSopenharmony_ci flags = os.O_CREAT | os.O_RDWR 1695f9996aaSopenharmony_ci modes = stat.S_IWUSR | stat.S_IRUSR 1705f9996aaSopenharmony_ci 1715f9996aaSopenharmony_ci fill_cnt = get_fill_cnt(imagefile, blocksize) 1725f9996aaSopenharmony_ci total_blocks = get_block_cnt(imagefile, blocksize) 1735f9996aaSopenharmony_ci table_numbers = get_raw_datafile(imagefile, blockid, total_blocks, blocksize) 1745f9996aaSopenharmony_ci 1755f9996aaSopenharmony_ci# save the header 1765f9996aaSopenharmony_ci outputrow = os.fdopen(os.open(sparseimagefile, flags, modes), 'w') 1775f9996aaSopenharmony_ci outputrow.write("%s\n" % (magic_number)) 1785f9996aaSopenharmony_ci outputrow.write("%s\n" % (version)) 1795f9996aaSopenharmony_ci outputrow.write("%s\n" % (blocksize)) 1805f9996aaSopenharmony_ci outputrow.write("%s\n" % (int(total_blocks))) 1815f9996aaSopenharmony_ci outputrow.write("%s\n" % (get_crc_value(imagefile, blocksize))) 1825f9996aaSopenharmony_ci outputrow.write("%s\n" % (get_crc_value(temp_file, blocksize))) 1835f9996aaSopenharmony_ci outputrow.write("%s\n" % (table_numbers)) 1845f9996aaSopenharmony_ci for block in blockid: 1855f9996aaSopenharmony_ci outputrow.write("%s\n" % (block[0])) 1865f9996aaSopenharmony_ci outputrow.write("%s\n" % (block[1])) 1875f9996aaSopenharmony_ci outputrow.write("%s\n" % (int(fill_cnt))) 1885f9996aaSopenharmony_ci outputrow.truncate(get_gap_blocksize(outputrow.tell(), blocksize) * blocksize) 1895f9996aaSopenharmony_ci outputrow.close() 1905f9996aaSopenharmony_ci 1915f9996aaSopenharmony_ci# append the raw data 1925f9996aaSopenharmony_ci outputrow = os.fdopen(os.open(sparseimagefile, flags, modes), 'ab') 1935f9996aaSopenharmony_ci outputtemp = os.fdopen(os.open(temp_file, flags, modes), 'rb') 1945f9996aaSopenharmony_ci blocknum = get_block_cnt(temp_file, blocksize) 1955f9996aaSopenharmony_ci i = 0 1965f9996aaSopenharmony_ci while (i < blocknum): 1975f9996aaSopenharmony_ci outputrow.write(outputtemp.read(blocksize)) 1985f9996aaSopenharmony_ci i += 1 1995f9996aaSopenharmony_ci outputtemp.close() 2005f9996aaSopenharmony_ci outputrow.close() 2015f9996aaSopenharmony_ci os.remove(temp_file) 2025f9996aaSopenharmony_ci with open(imagefile, 'r+') as output: 2035f9996aaSopenharmony_ci output.truncate(int(total_blocks) * int(blocksize) - int(fill_cnt)) 2045f9996aaSopenharmony_ci 2055f9996aaSopenharmony_ci 2065f9996aaSopenharmony_ciif __name__ == '__main__': 2075f9996aaSopenharmony_ci if len(sys.argv) != 4: 2085f9996aaSopenharmony_ci usage() 2095f9996aaSopenharmony_ci sys.exit() 2105f9996aaSopenharmony_ci CMD = str(sys.argv[1]) 2115f9996aaSopenharmony_ci INPUT_FILE = str(sys.argv[2]) 2125f9996aaSopenharmony_ci OUTPUT_FILE = str(sys.argv[3]) 2135f9996aaSopenharmony_ci if CMD == 'unsparse': 2145f9996aaSopenharmony_ci unsparse(INPUT_FILE, OUTPUT_FILE) 2155f9996aaSopenharmony_ci elif CMD == 'sparse': 2165f9996aaSopenharmony_ci sparse(INPUT_FILE, OUTPUT_FILE) 2175f9996aaSopenharmony_ci else: 2185f9996aaSopenharmony_ci usage()