1 | #!/usr/bin/python2.6 |
---|
2 | |
---|
3 | """ |
---|
4 | Read a compressed file as created by 'lzop' from stdin and write a table to |
---|
5 | stdout containing the blocksize and the start offset (in bytes) of each |
---|
6 | compressed block. |
---|
7 | |
---|
8 | usage: %prog < FILENAME.lzo > FILENAME.lzot |
---|
9 | """ |
---|
10 | |
---|
11 | import struct, sys |
---|
12 | |
---|
13 | MAGIC="\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a" |
---|
14 | |
---|
15 | F_ADLER32_D = 0x00000001L |
---|
16 | F_ADLER32_C = 0x00000002L |
---|
17 | F_H_EXTRA_FIELD = 0x00000040L |
---|
18 | F_H_GMTDIFF = 0x00000080L |
---|
19 | F_CRC32_D = 0x00000100L |
---|
20 | F_CRC32_C = 0x00000200L |
---|
21 | F_MULTIPART = 0x00000400L |
---|
22 | F_H_FILTER = 0x00000800L |
---|
23 | F_H_CRC32 = 0x00001000L |
---|
24 | |
---|
25 | assert struct.calcsize( "!H" ) == 2 |
---|
26 | assert struct.calcsize( "!I" ) == 4 |
---|
27 | |
---|
28 | class UnpackWrapper( object ): |
---|
29 | def __init__( self, file ): |
---|
30 | self.file = file |
---|
31 | def read( self, amt ): |
---|
32 | return self.file.read( amt ) |
---|
33 | def get( self, fmt ): |
---|
34 | t = struct.unpack( fmt, self.file.read( struct.calcsize( fmt ) ) ) |
---|
35 | return t[0] |
---|
36 | |
---|
37 | def main(): |
---|
38 | f = UnpackWrapper( sys.stdin ) |
---|
39 | # Read header |
---|
40 | magic = f.read(9) |
---|
41 | assert magic == MAGIC, "Not LZOP file" |
---|
42 | version = f.get( "!H" ) |
---|
43 | lib_version = f.get( "!H" ) |
---|
44 | if version >= 0x0940: |
---|
45 | extract_version = f.get( "!H" ) |
---|
46 | method = f.get( "!B" ) |
---|
47 | assert 1 <= method <= 3, "Only LZO compression is currently supported" |
---|
48 | level = f.get( "!B" ) |
---|
49 | flags = f.get( "!I" ) |
---|
50 | assert not( flags & F_H_FILTER ), "LZOP filters not supported" |
---|
51 | has_compressed_crc = ( flags & F_CRC32_C or flags & F_ADLER32_C ) |
---|
52 | has_uncompressed_crc = ( flags & F_CRC32_D or flags & F_ADLER32_D ) |
---|
53 | mode = f.get( "!I" ) |
---|
54 | time = f.get( "!I" ) |
---|
55 | time_offset = f.get( "!I" ) |
---|
56 | fname_len = f.get( "!B" ) |
---|
57 | fname = f.read( fname_len ) |
---|
58 | assert len( fname ) == fname_len, "EOF reading filename" |
---|
59 | header_crc = f.get( "!I" ) |
---|
60 | if ( flags & F_H_EXTRA_FIELD ): |
---|
61 | extra_len = f.get( "!I" ) |
---|
62 | extra = f.read( extra_len ) |
---|
63 | assert len( extra ) == extra_len, "EOF reading extra field" |
---|
64 | # Done with header |
---|
65 | block_size = None |
---|
66 | expect_no_more = False |
---|
67 | # Read blocks |
---|
68 | while 1: |
---|
69 | size = f.get( "!I" ) |
---|
70 | if size == 0: break |
---|
71 | assert not( expect_no_more ), \ |
---|
72 | "Encountered an undersized block that was not the last block" |
---|
73 | if block_size is None: |
---|
74 | print "s", size |
---|
75 | block_size = size |
---|
76 | else: |
---|
77 | if size < block_size: |
---|
78 | expect_no_more = True |
---|
79 | compressed_size = f.get( "!I" ) |
---|
80 | if has_uncompressed_crc: |
---|
81 | crc = f.get( "!I" ) |
---|
82 | if has_compressed_crc: |
---|
83 | compressed_crc = f.get( "!I" ) |
---|
84 | print "o", f.file.tell(), compressed_size, size |
---|
85 | compressed_data = f.read( compressed_size ) |
---|
86 | assert len( compressed_data ) == compressed_size, \ |
---|
87 | "EOF reading compressed data" |
---|
88 | |
---|
89 | if __name__ == "__main__": |
---|
90 | main() |
---|