• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# coding: utf-8
3# Copyright (c) 2022 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import sys
17import os
18import hashlib
19import errno
20import stat
21import datetime
22
23
24def usage():
25    print('\n Usage: imgcovert.py <cmd> <input> <output>')
26    print('         <cmd>: sparse or unsparse')
27    print('         <input>: input image file')
28    print('         <output>: ouput image file\n')
29    return
30
31
32def get_fill_cnt(inputfile, blocksize):
33    flags = os.O_WRONLY
34    modes = stat.S_IWUSR | stat.S_IRUSR
35    size = os.path.getsize(inputfile)
36    fill_cnt = 0
37    if size % blocksize != 0:
38        fill_cnt = blocksize - size % blocksize
39    indata = os.fdopen(os.open(inputfile, flags, modes), 'a')
40    for _ in range(fill_cnt):
41        indata.write("\0")
42    indata.close()
43    return fill_cnt
44
45
46def get_gap_blocksize(length, size):
47    if length < size:
48        cnt = 2
49    elif length < (size * 2):
50        cnt = 3
51    else:
52        cnt = 4
53    return cnt
54
55
56def get_block_cnt(inputfile, blocksize):
57    size = os.path.getsize(inputfile)
58    if blocksize != 0:
59        totalblocks = size / blocksize
60    else:
61        sys.exit(1)
62    if (size % blocksize) != 0:
63        print("len is not eq n * blocksize: ", size, totalblocks)
64    return totalblocks
65
66
67def get_crc_value(inputfile, blocksize):
68    totalblocks = get_block_cnt(inputfile, blocksize)
69    with open(inputfile, 'rb') as indata:
70        ind = 0
71        md5 = hashlib.md5()
72        while (ind < totalblocks):
73            md5.update(indata.read(blocksize))
74            ind += 1
75    return md5.hexdigest()
76
77
78def unsparse(sparseimagefile, imagefile):
79    with open(sparseimagefile, 'r') as header:
80        magic_mumber = header.readline()
81        version = header.readline()
82        blocksize = int(header.readline())
83        total_blocks = int(header.readline())
84        crc_value = header.readline()
85        input_crc_value = header.readline()
86        table_numbers = int(header.readline())
87        table = []
88        flags = os.O_CREAT | os.O_RDWR
89        modes = stat.S_IWUSR | stat.S_IRUSR
90        i = 0
91        while (i < table_numbers):
92            start = int(header.readline())
93            end = int(header.readline())
94            table.append([start, end])
95            i += 1
96        fill_cnt = int(header.readline())
97        length = header.tell()
98    with open(sparseimagefile, 'rb') as inputrow:
99        inputrow.seek(get_gap_blocksize(length, blocksize) * blocksize)
100        output = os.fdopen(os.open(imagefile, flags, modes), 'wb')
101        output.truncate(total_blocks * blocksize)
102        md5 = hashlib.md5()
103        for block in table:
104            cnt = block[1] - block[0]
105            output.seek(block[0] * blocksize)
106            indata = inputrow.read(cnt * blocksize)
107            md5.update(indata)
108            output.write(indata)
109        output.close()
110    print("RawFileCRC: ", get_crc_value(imagefile, blocksize), crc_value)
111    print("SparseCRC: ", md5.hexdigest(), input_crc_value)
112    with open(imagefile, 'r+') as output:
113        output.truncate(total_blocks * blocksize - fill_cnt)
114    return
115
116
117def is_empty_block(buff, size):
118    ind = 0
119    while (ind < size):
120        if buff[ind] != 0:
121            return False
122        ind += 1
123    return True
124
125
126def get_raw_datafile(imagefile, blockid, total_blocks, blocksize):
127    temp_file = imagefile + ".tempfile"
128    ind = 0
129    start = -1
130    table_numbers = 0
131    flags = os.O_CREAT | os.O_RDWR
132    modes = stat.S_IWUSR | stat.S_IRUSR
133
134    inputrow = open(imagefile, 'rb')
135    outputtemp = os.fdopen(os.open(temp_file, flags, modes), 'wb')
136    while (ind < total_blocks):
137        indata = inputrow.read(blocksize)
138        if len(indata) != blocksize:
139            print("error Block", ind, len(indata))
140        if is_empty_block(indata, blocksize) == True:
141            if start != -1:
142                blockid.append([start, ind])
143                table_numbers += 1
144                start = -1
145        else:
146            outputtemp.write(indata)
147            if start == -1:
148                start = ind
149        ind += 1
150    if start != -1:
151        blockid.append([start, ind])
152        table_numbers += 1
153        start = -1
154    inputrow.close()
155    outputtemp.close()
156    return table_numbers
157
158
159def sparse(imagefile, sparseimagefile):
160    temp_file = imagefile + ".tempfile"
161    magic_number = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
162    version = 1.0
163    blocksize = 4096
164    table_numbers = 0
165    blockid = []
166    flags = os.O_CREAT | os.O_RDWR
167    modes = stat.S_IWUSR | stat.S_IRUSR
168
169    fill_cnt = get_fill_cnt(imagefile, blocksize)
170    total_blocks = get_block_cnt(imagefile, blocksize)
171    table_numbers = get_raw_datafile(imagefile, blockid, total_blocks, blocksize)
172
173#   save the header
174    outputrow = os.fdopen(os.open(sparseimagefile, flags, modes), 'w')
175    outputrow.write("%s\n" % (magic_number))
176    outputrow.write("%s\n" % (version))
177    outputrow.write("%s\n" % (blocksize))
178    outputrow.write("%s\n" % (int(total_blocks)))
179    outputrow.write("%s\n" % (get_crc_value(imagefile, blocksize)))
180    outputrow.write("%s\n" % (get_crc_value(temp_file, blocksize)))
181    outputrow.write("%s\n" % (table_numbers))
182    for block in blockid:
183        outputrow.write("%s\n" % (block[0]))
184        outputrow.write("%s\n" % (block[1]))
185    outputrow.write("%s\n" % (int(fill_cnt)))
186    outputrow.truncate(get_gap_blocksize(outputrow.tell(), blocksize) * blocksize)
187    outputrow.close()
188
189#   append the raw data
190    outputrow = os.fdopen(os.open(sparseimagefile, flags, modes), 'ab')
191    outputtemp = os.fdopen(os.open(temp_file, flags, modes), 'rb')
192    blocknum = get_block_cnt(temp_file, blocksize)
193    i = 0
194    while (i < blocknum):
195        outputrow.write(outputtemp.read(blocksize))
196        i += 1
197    outputtemp.close()
198    outputrow.close()
199    os.remove(temp_file)
200    with open(imagefile, 'r+') as output:
201        output.truncate(int(total_blocks) * int(blocksize) - int(fill_cnt))
202
203
204if __name__ == '__main__':
205    if len(sys.argv) != 4:
206        usage()
207        sys.exit()
208    CMD = str(sys.argv[1])
209    INPUT_FILE = str(sys.argv[2])
210    OUTPUT_FILE = str(sys.argv[3])
211    if CMD == 'unsparse':
212        unsparse(INPUT_FILE, OUTPUT_FILE)
213    elif CMD == 'sparse':
214        sparse(INPUT_FILE, OUTPUT_FILE)
215    else:
216        usage()