3 """Dump archive contents, test extraction."""
8 from binascii
import crc32
, hexlify
9 from datetime
import datetime
16 return array
.array('B', v
)
18 rf
.UNICODE_COMMENTS
= 1
22 dumprar [switches] [ARC1 ARC2 ...] [@ARCLIST]
24 @file read archive names from file
26 -Ccharset set fallback charset
28 -t attempt to read all files
29 -x write read files out
30 -c show archive comment
32 -- stop switch parsing
35 os_list
= ['DOS', 'OS2', 'WIN', 'UNIX', 'MACOS', 'BEOS']
37 block_strs
= ['MARK', 'MAIN', 'FILE', 'OLD_COMMENT', 'OLD_EXTRA',
38 'OLD_SUB', 'OLD_RECOVERY', 'OLD_AUTH', 'SUB', 'ENDARC']
41 if type < rf
.RAR_BLOCK_MARK
or type > rf
.RAR_BLOCK_ENDARC
:
43 return block_strs
[type - rf
.RAR_BLOCK_MARK
]
46 (rf
.RAR_MAIN_VOLUME
, "VOL"),
47 (rf
.RAR_MAIN_COMMENT
, "COMMENT"),
48 (rf
.RAR_MAIN_LOCK
, "LOCK"),
49 (rf
.RAR_MAIN_SOLID
, "SOLID"),
50 (rf
.RAR_MAIN_NEWNUMBERING
, "NEWNR"),
51 (rf
.RAR_MAIN_AUTH
, "AUTH"),
52 (rf
.RAR_MAIN_RECOVERY
, "RECOVERY"),
53 (rf
.RAR_MAIN_PASSWORD
, "PASSWORD"),
54 (rf
.RAR_MAIN_FIRSTVOLUME
, "FIRSTVOL"),
55 (rf
.RAR_SKIP_IF_UNKNOWN
, "SKIP"),
56 (rf
.RAR_LONG_BLOCK
, "LONG"),
60 (rf
.RAR_ENDARC_NEXT_VOLUME
, "NEXTVOL"),
61 (rf
.RAR_ENDARC_DATACRC
, "DATACRC"),
62 (rf
.RAR_ENDARC_REVSPACE
, "REVSPACE"),
63 (rf
.RAR_ENDARC_VOLNR
, "VOLNR"),
64 (rf
.RAR_SKIP_IF_UNKNOWN
, "SKIP"),
65 (rf
.RAR_LONG_BLOCK
, "LONG"),
69 (rf
.RAR_FILE_SPLIT_BEFORE
, "SPLIT_BEFORE"),
70 (rf
.RAR_FILE_SPLIT_AFTER
, "SPLIT_AFTER"),
71 (rf
.RAR_FILE_PASSWORD
, "PASSWORD"),
72 (rf
.RAR_FILE_COMMENT
, "COMMENT"),
73 (rf
.RAR_FILE_SOLID
, "SOLID"),
74 (rf
.RAR_FILE_LARGE
, "LARGE"),
75 (rf
.RAR_FILE_UNICODE
, "UNICODE"),
76 (rf
.RAR_FILE_SALT
, "SALT"),
77 (rf
.RAR_FILE_VERSION
, "VERSION"),
78 (rf
.RAR_FILE_EXTTIME
, "EXTTIME"),
79 (rf
.RAR_FILE_EXTFLAGS
, "EXTFLAGS"),
80 (rf
.RAR_SKIP_IF_UNKNOWN
, "SKIP"),
81 (rf
.RAR_LONG_BLOCK
, "LONG"),
85 (rf
.RAR_SKIP_IF_UNKNOWN
, "SKIP"),
86 (rf
.RAR_LONG_BLOCK
, "LONG"),
89 file_parms
= ("D64", "D128", "D256", "D512",
90 "D1024", "D2048", "D4096", "DIR")
93 if sys
.hexversion
< 0x3000000:
97 if sys
.hexversion
< 0x3000000:
100 sys
.stdout
.write('\n')
102 def render_flags(flags
, bit_list
):
106 known
= known | bit
[0]
109 unknown
= flags
& ~known
113 res
.append("UNK_%04x" % (1 << n
))
114 unknown
= unknown
>> 1
119 def get_file_flags(flags
):
120 res
= render_flags(flags
& ~rf
.RAR_FILE_DICTMASK
, file_bits
)
122 xf
= (flags
& rf
.RAR_FILE_DICTMASK
) >> 5
123 res
+= "," + file_parms
[xf
]
126 def get_main_flags(flags
):
127 return render_flags(flags
, main_bits
)
129 def get_endarc_flags(flags
):
130 return render_flags(flags
, endarc_bits
)
132 def get_generic_flags(flags
):
133 return render_flags(flags
, generic_bits
)
136 if isinstance(t
, datetime
):
137 return t
.isoformat(' ')
138 return "%04d-%02d-%02d %02d:%02d:%02d" % t
142 unknown
= h
.header_size
- h
.header_base
143 xprint("%s: hdrlen=%d datlen=%d hdr_unknown=%d", st
, h
.header_size
,
145 if unknown
> 0 and cf_verbose
> 1:
146 dat
= h
.header_data
[h
.header_base
: ]
147 xprint(" unknown: %s", hexlify(dat
))
148 if h
.type in (rf
.RAR_BLOCK_FILE
, rf
.RAR_BLOCK_SUB
):
149 if h
.host_os
== rf
.RAR_OS_UNIX
:
150 s_mode
= "0%o" % h
.mode
152 s_mode
= "0x%x" % h
.mode
153 xprint(" flags=0x%04x:%s", h
.flags
, get_file_flags(h
.flags
))
154 if h
.host_os
>= 0 and h
.host_os
< len(os_list
):
155 s_os
= os_list
[h
.host_os
]
158 xprint(" os=%d:%s ver=%d mode=%s meth=%c cmp=%d dec=%d vol=%d",
160 h
.extract_version
, s_mode
, h
.compress_type
,
161 h
.compress_size
, h
.file_size
, h
.volume
)
162 ucrc
= (h
.CRC
+ (1 << 32)) & ((1 << 32) - 1)
163 xprint(" crc=0x%08x (%d) time=%s", ucrc
, h
.CRC
, fmt_time(h
.date_time
))
164 xprint(" name=%s", h
.filename
)
166 xprint(" mtime=%s", fmt_time(h
.mtime
))
168 xprint(" ctime=%s", fmt_time(h
.ctime
))
170 xprint(" atime=%s", fmt_time(h
.atime
))
172 xprint(" arctime=%s", fmt_time(h
.arctime
))
173 elif h
.type == rf
.RAR_BLOCK_MAIN
:
174 xprint(" flags=0x%04x:%s", h
.flags
, get_main_flags(h
.flags
))
175 elif h
.type == rf
.RAR_BLOCK_ENDARC
:
176 xprint(" flags=0x%04x:%s", h
.flags
, get_endarc_flags(h
.flags
))
177 elif h
.type == rf
.RAR_BLOCK_MARK
:
178 xprint(" flags=0x%04x:", h
.flags
)
180 xprint(" flags=0x%04x:%s", h
.flags
, get_generic_flags(h
.flags
))
182 if h
.comment
is not None:
186 xprint(" comment=%s", cm
)
196 def check_crc(f
, inf
):
199 ucrc
+= (long(1) << 32)
203 def test_read_long(r
, inf
):
204 f
= r
.open(inf
.filename
)
211 if total
!= inf
.file_size
:
212 xprint("\n *** %s has corrupt file: %s ***", r
.rarfile
, inf
.filename
)
213 xprint(" *** short read: got=%d, need=%d ***\n", total
, inf
.file_size
)
216 # test .seek() & .readinto()
220 # hack: re-enable crc calc
225 buf
= bytearray(rf
.ZERO
*4096)
227 res
= f
.readinto(buf
)
231 if inf
.file_size
!= total
:
232 xprint(" *** readinto failed: got=%d, need=%d ***\n", total
, inf
.file_size
)
236 def test_read(r
, inf
):
237 test_read_long(r
, inf
)
240 def test_real(fn
, psw
):
241 xprint("Archive: %s", fn
)
249 rfarg
= io
.BytesIO(open(fn
, 'rb').read())
252 if not rf
.is_rarfile(rfarg
):
253 xprint(" --- %s is not a RAR file ---", fn
)
257 r
= rf
.RarFile(rfarg
, charset
= cf_charset
, info_callback
= cb
)
259 if r
.needs_password():
263 xprint(" --- %s requires password ---", fn
)
267 if cf_show_comment
and r
.comment
:
268 for ln
in r
.comment
.split('\n'):
270 elif cf_verbose
== 1 and r
.comment
:
274 xprint(" comment=%s", cm
)
277 for n
in r
.namelist():
288 for inf
in r
.infolist():
297 except rf
.NeedFirstVolume
:
298 xprint(" --- %s is middle part of multi-vol archive ---", fn
)
300 exc
, msg
, tb
= sys
.exc_info()
301 xprint("\n *** %s: %s ***\n", exc
.__name
__, msg
)
304 exc
, msg
, tb
= sys
.exc_info()
305 xprint("\n *** %s: %s ***\n", exc
.__name
__, msg
)
309 global cf_verbose
, cf_show_comment
, cf_charset
310 global cf_extract
, cf_test_read
, cf_test_unrar
311 global cf_test_memory
317 for a
in sys
.argv
[1:]:
321 for ln
in open(a
[1:], 'r'):
348 raise Exception("unknown switch: "+a
)
356 if __name__
== '__main__':
359 except KeyboardInterrupt: