summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xlibsparse/simg_dump.py130
1 files changed, 91 insertions, 39 deletions
diff --git a/libsparse/simg_dump.py b/libsparse/simg_dump.py
index c70d45fe3..82a03ad95 100755
--- a/libsparse/simg_dump.py
+++ b/libsparse/simg_dump.py
@@ -15,43 +15,64 @@
15# limitations under the License. 15# limitations under the License.
16 16
17from __future__ import print_function 17from __future__ import print_function
18import getopt, posixpath, signal, struct, sys 18import csv
19import getopt
20import hashlib
21import posixpath
22import signal
23import struct
24import sys
25
19 26
20def usage(argv0): 27def usage(argv0):
21 print(""" 28 print("""
22Usage: %s [-v] sparse_image_file ... 29Usage: %s [-v] [-s] [-c <filename>] sparse_image_file ...
23 -v verbose output 30 -v verbose output
24""" % ( argv0 )) 31 -s show sha1sum of data blocks
32 -c <filename> save .csv file of blocks
33""" % (argv0))
25 sys.exit(2) 34 sys.exit(2)
26 35
27def main():
28 36
37def main():
29 signal.signal(signal.SIGPIPE, signal.SIG_DFL) 38 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
30 39
31 me = posixpath.basename(sys.argv[0]) 40 me = posixpath.basename(sys.argv[0])
32 41
33 # Parse the command line 42 # Parse the command line
34 verbose = 0 # -v 43 verbose = 0 # -v
44 showhash = 0 # -s
45 csvfilename = None # -c
35 try: 46 try:
36 opts, args = getopt.getopt(sys.argv[1:], 47 opts, args = getopt.getopt(sys.argv[1:],
37 "v", 48 "vsc:",
38 ["verbose"]) 49 ["verbose", "showhash", "csvfile"])
39 except getopt.GetoptError, e: 50 except getopt.GetoptError, e:
40 print(e) 51 print(e)
41 usage(me) 52 usage(me)
42 for o, a in opts: 53 for o, a in opts:
43 if o in ("-v", "--verbose"): 54 if o in ("-v", "--verbose"):
44 verbose += 1 55 verbose += 1
56 elif o in ("-s", "--showhash"):
57 showhash = True
58 elif o in ("-c", "--csvfile"):
59 csvfilename = a
45 else: 60 else:
46 print("Unrecognized option \"%s\"" % (o)) 61 print("Unrecognized option \"%s\"" % (o))
47 usage(me) 62 usage(me)
48 63
49 if len(args) == 0: 64 if not args:
50 print("No sparse_image_file specified") 65 print("No sparse_image_file specified")
51 usage(me) 66 usage(me)
52 67
68 if csvfilename:
69 csvfile = open(csvfilename, "wb")
70 csvwriter = csv.writer(csvfile)
71
72 output = verbose or csvfilename or showhash
73
53 for path in args: 74 for path in args:
54 FH = open(path, 'rb') 75 FH = open(path, "rb")
55 header_bin = FH.read(28) 76 header_bin = FH.read(28)
56 header = struct.unpack("<I4H4I", header_bin) 77 header = struct.unpack("<I4H4I", header_bin)
57 78
@@ -88,71 +109,99 @@ def main():
88 if image_checksum != 0: 109 if image_checksum != 0:
89 print("checksum=0x%08X" % (image_checksum)) 110 print("checksum=0x%08X" % (image_checksum))
90 111
91 if not verbose: 112 if not output:
92 continue 113 continue
93 print(" input_bytes output_blocks") 114
94 print("chunk offset number offset number") 115 if verbose > 0:
116 print(" input_bytes output_blocks")
117 print("chunk offset number offset number")
118
119 if csvfilename:
120 csvwriter.writerow(["chunk", "input offset", "input bytes",
121 "output offset", "output blocks", "type", "hash"])
122
95 offset = 0 123 offset = 0
96 for i in xrange(1,total_chunks+1): 124 for i in xrange(1, total_chunks + 1):
97 header_bin = FH.read(12) 125 header_bin = FH.read(12)
98 header = struct.unpack("<2H2I", header_bin) 126 header = struct.unpack("<2H2I", header_bin)
99 chunk_type = header[0] 127 chunk_type = header[0]
100 reserved1 = header[1]
101 chunk_sz = header[2] 128 chunk_sz = header[2]
102 total_sz = header[3] 129 total_sz = header[3]
103 data_sz = total_sz - 12 130 data_sz = total_sz - 12
131 curhash = ""
132 curtype = ""
133 curpos = FH.tell()
104 134
105 print("%4u %10u %10u %7u %7u" % (i, FH.tell(), data_sz, offset, chunk_sz), 135 if verbose > 0:
106 end=" ") 136 print("%4u %10u %10u %7u %7u" % (i, curpos, data_sz, offset, chunk_sz),
137 end=" ")
107 138
108 if chunk_type == 0xCAC1: 139 if chunk_type == 0xCAC1:
109 if data_sz != (chunk_sz * blk_sz): 140 if data_sz != (chunk_sz * blk_sz):
110 print("Raw chunk input size (%u) does not match output size (%u)" 141 print("Raw chunk input size (%u) does not match output size (%u)"
111 % (data_sz, chunk_sz * blk_sz)) 142 % (data_sz, chunk_sz * blk_sz))
112 break; 143 break
113 else: 144 else:
114 print("Raw data", end="") 145 curtype = "Raw data"
115 FH.read(data_sz) 146 data = FH.read(data_sz)
147 if showhash:
148 h = hashlib.sha1()
149 h.update(data)
150 curhash = h.hexdigest()
116 elif chunk_type == 0xCAC2: 151 elif chunk_type == 0xCAC2:
117 if data_sz != 4: 152 if data_sz != 4:
118 print("Fill chunk should have 4 bytes of fill, but this has %u" 153 print("Fill chunk should have 4 bytes of fill, but this has %u"
119 % (data_sz), end="") 154 % (data_sz))
120 break; 155 break
121 else: 156 else:
122 fill_bin = FH.read(4) 157 fill_bin = FH.read(4)
123 fill = struct.unpack("<I", fill_bin) 158 fill = struct.unpack("<I", fill_bin)
124 print("Fill with 0x%08X" % (fill)) 159 curtype = format("Fill with 0x%08X" % (fill))
160 if showhash:
161 h = hashlib.sha1()
162 data = fill_bin * (blk_sz / 4);
163 for block in xrange(chunk_sz):
164 h.update(data)
165 curhash = h.hexdigest()
125 elif chunk_type == 0xCAC3: 166 elif chunk_type == 0xCAC3:
126 if data_sz != 0: 167 if data_sz != 0:
127 print("Don't care chunk input size is non-zero (%u)" % (data_sz)) 168 print("Don't care chunk input size is non-zero (%u)" % (data_sz))
128 break; 169 break
129 else: 170 else:
130 print("Don't care", end="") 171 curtype = "Don't care"
131 elif chunk_type == 0xCAC4: 172 elif chunk_type == 0xCAC4:
132 if data_sz != 4: 173 if data_sz != 4:
133 print("CRC32 chunk should have 4 bytes of CRC, but this has %u" 174 print("CRC32 chunk should have 4 bytes of CRC, but this has %u"
134 % (data_sz), end="") 175 % (data_sz))
135 break; 176 break
136 else: 177 else:
137 crc_bin = FH.read(4) 178 crc_bin = FH.read(4)
138 crc = struct.unpack("<I", crc_bin) 179 crc = struct.unpack("<I", crc_bin)
139 print("Unverified CRC32 0x%08X" % (crc)) 180 curtype = format("Unverified CRC32 0x%08X" % (crc))
140 else:
141 print("Unknown chunk type 0x%04X" % (chunk_type), end="")
142 break;
143
144 if verbose > 1:
145 header = struct.unpack("<12B", header_bin)
146 print(" (%02X%02X %02X%02X %02X%02X%02X%02X %02X%02X%02X%02X)"
147 % (header[0], header[1], header[2], header[3],
148 header[4], header[5], header[6], header[7],
149 header[8], header[9], header[10], header[11]))
150 else: 181 else:
151 print() 182 print("Unknown chunk type 0x%04X" % (chunk_type))
183 break
184
185 if verbose > 0:
186 print("%-18s" % (curtype), end=" ")
187
188 if verbose > 1:
189 header = struct.unpack("<12B", header_bin)
190 print(" (%02X%02X %02X%02X %02X%02X%02X%02X %02X%02X%02X%02X)"
191 % (header[0], header[1], header[2], header[3],
192 header[4], header[5], header[6], header[7],
193 header[8], header[9], header[10], header[11]), end=" ")
194
195 print(curhash)
196
197 if csvfilename:
198 csvwriter.writerow([i, curpos, data_sz, offset, chunk_sz, curtype,
199 curhash])
152 200
153 offset += chunk_sz 201 offset += chunk_sz
154 202
155 print(" %10u %7u End" % (FH.tell(), offset)) 203 if verbose > 0:
204 print(" %10u %7u End" % (FH.tell(), offset))
156 205
157 if total_blks != offset: 206 if total_blks != offset:
158 print("The header said we should have %u output blocks, but we saw %u" 207 print("The header said we should have %u output blocks, but we saw %u"
@@ -163,6 +212,9 @@ def main():
163 print("There were %u bytes of extra data at the end of the file." 212 print("There were %u bytes of extra data at the end of the file."
164 % (junk_len)) 213 % (junk_len))
165 214
215 if csvfilename:
216 csvfile.close()
217
166 sys.exit(0) 218 sys.exit(0)
167 219
168if __name__ == "__main__": 220if __name__ == "__main__":