Skip to content

Instantly share code, notes, and snippets.

@wodim
Created January 4, 2016 16:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wodim/cb0642fcc56422ed275b to your computer and use it in GitHub Desktop.
Save wodim/cb0642fcc56422ed275b to your computer and use it in GitHub Desktop.
Extracts files inside BFZ archives (Cryo BigFile)
# 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