Created
January 4, 2016 16:08
-
-
Save wodim/cb0642fcc56422ed275b to your computer and use it in GitHub Desktop.
Extracts files inside BFZ archives (Cryo BigFile)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# wodim, 04/01/2016 -- public domain | |
import mimetypes | |
import os | |
import sys | |
import zlib | |
import magic | |
WORD_SIZE = 4 | |
if len(sys.argv) < 2 or len(sys.argv) > 3: | |
print("Usage: %s <raw file> [output folder]" % (sys.argv[0])) | |
sys.exit(1) | |
bigfile = open(sys.argv[1], "rb") | |
if len(sys.argv) == 3: | |
extracted_dir = sys.argv[2] | |
if not os.path.isdir(extracted_dir): | |
os.mkdir(extracted_dir) | |
else: | |
extracted_dir = None | |
entries_count = int.from_bytes(bigfile.read(WORD_SIZE), byteorder="little") | |
for i in range(entries_count): | |
dir_offset = bigfile.tell() | |
entry = bigfile.read(WORD_SIZE * 5) | |
file_name = "file%04x" % (i,) | |
offset = int.from_bytes(entry[0:WORD_SIZE], byteorder="little") | |
size = int.from_bytes(entry[WORD_SIZE:WORD_SIZE * 2], byteorder="little") | |
real_size = int.from_bytes(entry[WORD_SIZE * 2:WORD_SIZE * 3], byteorder="little") | |
checksum = int.from_bytes(entry[WORD_SIZE * 3:WORD_SIZE * 4], byteorder="little") | |
# last field is just a word of padding | |
print("File:\t\t%s" % (file_name,)) | |
print("Offset:\t\t%04x" % (offset,)) | |
print("Dir offset:\t%04x" % (dir_offset,)) | |
print("Size:\t\t%04x" % (size,)) | |
print("Real size:\t%04x" % (real_size,)) | |
print("Checksum:\t%04x" % (checksum,)) | |
print("==================================") | |
if extracted_dir: # i.e. if the user wants to extract the file | |
file_path = os.path.join(extracted_dir, "%s" % (file_name,)) | |
# remove existing file | |
if os.path.isfile(file_path): | |
os.remove(file_path) | |
bigfile.seek(offset, 0) | |
contents = bigfile.read(size) | |
if size != real_size: | |
file_path = file_path + "_" | |
contents = zlib.decompress(contents) | |
mimetype = magic.from_buffer(contents, mime=True).decode("utf-8") | |
extension = mimetypes.guess_extension(mimetype) | |
if extension: | |
file_path = file_path + extension | |
with open(file_path, "wb") as output_file: | |
output_file.write(contents) | |
bigfile.seek(dir_offset + WORD_SIZE * 5) | |
bigfile.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment