• 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    indata = open(inputfile, 'rb')
70    ind = 0
71    md5 = hashlib.md5()
72    while (ind < totalblocks):
73        md5.update(indata.read(blocksize))
74        ind += 1
75    indata.close()
76    return md5.hexdigest()
77
78
79def unsparse(sparseimagefile, imagefile):
80    header = open(sparseimagefile, 'r')
81    magic_mumber = header.readline()
82    version = header.readline()
83    blocksize = int(header.readline())
84    total_blocks = int(header.readline())
85    crc_value = header.readline()
86    input_crc_value = header.readline()
87    table_numbers = int(header.readline())
88    table = []
89    flags = os.O_CREAT | os.O_RDWR
90    modes = stat.S_IWUSR | stat.S_IRUSR
91    i = 0
92    while (i < table_numbers):
93        start = int(header.readline())
94        end = int(header.readline())
95        table.append([start, end])
96        i += 1
97    fill_cnt = int(header.readline())
98    length = header.tell()
99    header.close()
100    inputrow = open(sparseimagefile, 'rb')
101    inputrow.seek(get_gap_blocksize(length, blocksize) * blocksize)
102    output = os.fdopen(os.open(imagefile, flags, modes), 'wb')
103    output.truncate(total_blocks * blocksize)
104    md5 = hashlib.md5()
105    for block in table:
106        cnt = block[1] - block[0]
107        output.seek(block[0] * blocksize)
108        indata = inputrow.read(cnt * blocksize)
109        md5.update(indata)
110        output.write(indata)
111    output.close()
112    inputrow.close()
113    print("RawFileCRC: ", get_crc_value(imagefile, blocksize), crc_value)
114    print("SparseCRC: ", md5.hexdigest(), input_crc_value)
115    output = open(imagefile, 'r+')
116    output.truncate(total_blocks * blocksize - fill_cnt)
117    output.close()
118    return
119
120
121def is_empty_block(buff, size):
122    ind = 0
123    while (ind < size):
124        if buff[ind] != 0:
125            return False
126        ind += 1
127    return True
128
129
130def get_raw_datafile(imagefile, blockid, total_blocks, blocksize):
131    temp_file = imagefile + ".tempfile"
132    ind = 0
133    start = -1
134    table_numbers = 0
135    flags = os.O_CREAT | os.O_RDWR
136    modes = stat.S_IWUSR | stat.S_IRUSR
137
138    inputrow = open(imagefile, 'rb')
139    outputtemp = os.fdopen(os.open(temp_file, flags, modes), 'wb')
140    while (ind < total_blocks):
141        indata = inputrow.read(blocksize)
142        if len(indata) != blocksize:
143            print("error Block", ind, len(indata))
144        if is_empty_block(indata, blocksize) == True:
145            if start != -1:
146                blockid.append([start, ind])
147                table_numbers += 1
148                start = -1
149        else:
150            outputtemp.write(indata)
151            if start == -1:
152                start = ind
153        ind += 1
154    if start != -1:
155        blockid.append([start, ind])
156        table_numbers += 1
157        start = -1
158    inputrow.close()
159    outputtemp.close()
160    return table_numbers
161
162
163def sparse(imagefile, sparseimagefile):
164    temp_file = imagefile + ".tempfile"
165    magic_number = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
166    version = 1.0
167    blocksize = 4096
168    table_numbers = 0
169    blockid = []
170    flags = os.O_CREAT | os.O_RDWR
171    modes = stat.S_IWUSR | stat.S_IRUSR
172
173    fill_cnt = get_fill_cnt(imagefile, blocksize)
174    total_blocks = get_block_cnt(imagefile, blocksize)
175    table_numbers = get_raw_datafile(imagefile, blockid, total_blocks, blocksize)
176
177#   save the header
178    outputrow = os.fdopen(os.open(sparseimagefile, flags, modes), 'w')
179    outputrow.write("%s\n" % (magic_number))
180    outputrow.write("%s\n" % (version))
181    outputrow.write("%s\n" % (blocksize))
182    outputrow.write("%s\n" % (int(total_blocks)))
183    outputrow.write("%s\n" % (get_crc_value(imagefile, blocksize)))
184    outputrow.write("%s\n" % (get_crc_value(temp_file, blocksize)))
185    outputrow.write("%s\n" % (table_numbers))
186    for block in blockid:
187        outputrow.write("%s\n" % (block[0]))
188        outputrow.write("%s\n" % (block[1]))
189    outputrow.write("%s\n" % (int(fill_cnt)))
190    outputrow.truncate(get_gap_blocksize(outputrow.tell(), blocksize) * blocksize)
191    outputrow.close()
192
193#   append the raw data
194    outputrow = os.fdopen(os.open(sparseimagefile, flags, modes), 'ab')
195    outputtemp = os.fdopen(os.open(temp_file, flags, modes), 'rb')
196    blocknum = get_block_cnt(temp_file, blocksize)
197    i = 0
198    while (i < blocknum):
199        outputrow.write(outputtemp.read(blocksize))
200        i += 1
201    outputtemp.close()
202    outputrow.close()
203    os.remove(temp_file)
204    output = open(imagefile, 'r+')
205    output.truncate(int(total_blocks) * int(blocksize) - int(fill_cnt))
206    output.close()
207
208
209if __name__ == '__main__':
210    if len(sys.argv) != 4:
211        usage()
212        sys.exit()
213    CMD = str(sys.argv[1])
214    INPUT_FILE = str(sys.argv[2])
215    OUTPUT_FILE = str(sys.argv[3])
216    if CMD == 'unsparse':
217        unsparse(INPUT_FILE, OUTPUT_FILE)
218    elif CMD == 'sparse':
219        sparse(INPUT_FILE, OUTPUT_FILE)
220    else:
221        usage()