Skip to content

Instantly share code, notes, and snippets.

@Jeremy-D-Miller
Forked from pudquick/parse_pbzx.py
Created October 28, 2015 06:42
Show Gist options
  • Save Jeremy-D-Miller/e12cdcf594cccabb1c75 to your computer and use it in GitHub Desktop.
Save Jeremy-D-Miller/e12cdcf594cccabb1c75 to your computer and use it in GitHub Desktop.
Pure python reimplementation of .cpio.xz content extraction from pbzx file payload for OS X packages
# Pure python reimplementation of .cpio.xz content extraction from pbzx file payload originally here:
# http://www.tonymacx86.com/general-help/135458-pbzx-stream-parser.html
#
# Cleaned up C version (as the basis for my code) here, thanks to Pepijn Bruienne / @bruienne
# https://gist.github.com/bruienne/029494bbcfb358098b41
# Example usage:
# parse_pbzx('PayloadJava', 'PayloadJava.cpio.xz')
import struct
def parse_pbzx(pbzx_path, xar_out_path):
f = open(pbzx_path, 'rb')
pbzx = f.read()
f.close()
magic, pbzx = pbzx[:4],pbzx[4:]
if magic != 'pbzx':
raise "Error: Not a pbzx file"
# Read 8 bytes for initial flags
flags, pbzx = pbzx[:8],pbzx[8:]
# Interpret the flags as a 64-bit big-endian unsigned int
flags = struct.unpack('>Q', flags)[0]
xar_f = open(xar_out_path, 'wb')
while (flags & (1 << 24)):
# Read in more flags
flags, pbzx = pbzx[:8],pbzx[8:]
flags = struct.unpack('>Q', flags)[0]
# Read in length
f_length, pbzx = pbzx[:8],pbzx[8:]
f_length = struct.unpack('>Q', f_length)[0]
xzmagic, pbzx = pbzx[:6],pbzx[6:]
if xzmagic != '\xfd7zXZ\x00':
xar_f.close()
raise "Error: Header is not xar file header"
f_length -= 6
f_content, pbzx = pbzx[:f_length],pbzx[f_length:]
if f_content[-2:] != 'YZ':
xar_f.close()
raise "Error: Footer is not xar file footer"
xar_f.write(xzmagic)
xar_f.write(f_content)
try:
xar_f.close()
except:
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment