diff --git a/Dockerfile.xcode b/Dockerfile.xcode index 322c465..380016e 100644 --- a/Dockerfile.xcode +++ b/Dockerfile.xcode @@ -2,11 +2,7 @@ ARG img_version FROM godot-fedora:${img_version} RUN dnf -y install --setopt=install_weak_deps=False \ - clang xar xar-devel xz-devel cpio && \ - git clone --progress https://github.com/nrosenstein-stuff/pbzx && \ - cd pbzx && \ - git checkout bf536e167f2e514866f91d7baa0df1dff5a13711 && \ - clang -O3 -llzma -lxar -I /usr/local/include pbzx.c -o pbzx + cpio python ENV XCODE_SDKV= ENV OSX_SDKV= @@ -14,8 +10,7 @@ ENV IOS_SDKV= CMD mkdir -p /root/xcode && \ cd /root/xcode && \ - xar -xf /root/files/Xcode_${XCODE_SDKV}.xip && \ - /root/pbzx/pbzx -n Content | cpio -i && \ + /root/files/extract_xcode.py -f /root/files/Xcode_${XCODE_SDKV}.xip | cpio -i && \ export OSX_SDK=MacOSX${OSX_SDKV}.sdk && \ cp -r Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk /tmp/${OSX_SDK} && \ cd /tmp && \ diff --git a/files/extract_xcode.py b/files/extract_xcode.py new file mode 100644 index 0000000..6156b8c --- /dev/null +++ b/files/extract_xcode.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +# Copyright (c) 2020 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +"""XCode extractor +""" + +import argparse +import sys +import struct +import zlib +import xml.etree.ElementTree as ET +import lzma + +XAR_MAGIC = b'\x78\x61\x72\x21' +PBZX_MAGIC = b'\x70\x62\x7a\x78' +LZMA_MAGIC = b'\xfd\x37\x7a\x58\x5a\x00' + +class io_wrapper(object): + """Helper for stdin/stdout binary weirdness""" + def __init__(self, filename, mode): + self.filename = filename + self.mode = mode + def __enter__(self): + if self.filename == '-': + if self.mode is None or self.mode == '' or 'r' in self.mode: + self.fh = sys.stdin + else: + self.fh = sys.stdout + else: + self.fh = open(self.filename, self.mode) + return self + def __exit__(self, exc_type, exc_val, exc_tb): + if self.filename != '-': + self.fh.close() + def write(self, bytes): + if self.filename != '-': + return self.fh.write(bytes) + return self.fh.buffer.write(bytes) + def read(self, size): + if self.filename != '-': + return self.fh.read(size) + return self.fh.buffer.read(size) + def seek(self, size): + return self.fh.seek(size) + +def run(): + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawTextHelpFormatter) + + parser.add_argument("-f", '--file', nargs='?', default="-") + parser.add_argument('outfile', nargs='?', default="-") + + args = parser.parse_args() + + with io_wrapper(args.file, "rb") as infile, io_wrapper(args.outfile, "wb") as outfile: + + start_offset = 0 + magic = infile.read(4) + if magic != XAR_MAGIC: + print("bad xar magic", file=sys.stderr) + sys.exit(1) + + bytes = infile.read(24) + header_size, xar_version, toc_compressed, toc_uncompressed, checksum_type = struct.unpack('>HHQQI', bytes) + start_offset += header_size + start_offset += toc_compressed + bytes = infile.read(toc_compressed) + + xml_toc = zlib.decompress(bytes).decode("utf-8") + + root = ET.fromstring(xml_toc) + + content_offset = 0 + content_length = 0 + content_encoding = "" + + toc = root.find("toc") + for elem in toc.findall("file"): + name = elem.find("name").text + if name == "Content": + data = elem.find("data") + content_offset = int(data.find("offset").text) + content_length = int(data.find("length").text) + content_encoding = data.find("encoding").get("style") + content_uncompressed_length = int(data.find("size").text) + found_content = True + break + + if (content_length == 0): + print("No \"Content\" file to extract.", file=sys.stderr) + sys.exit(1) + + infile.seek(content_offset + start_offset) + + content_read_size = 0 + + magic = infile.read(4) + content_read_size += 4 + if magic != PBZX_MAGIC: + print("bad pbzx magic", file=sys.stderr) + sys.exit(2) + + bytes = infile.read(8) + content_read_size += 8 + flags, = struct.unpack('>Q', bytes) + bytes = infile.read(16) + content_read_size += 16 + while (flags & 1 << 24): + flags, size = struct.unpack('>QQ', bytes) + bytes = infile.read(size) + content_read_size += size + compressed = size != 1 << 24 + if compressed: + if bytes[0:6] != LZMA_MAGIC: + print("bad lzma magic: ", file=sys.stderr) + sys.exit(3) + outfile.write(lzma.decompress(bytes)) + else: + outfile.write(bytes) + + if content_read_size == content_length: + break + + bytes = infile.read(16) + content_read_size += 16 + +if __name__ == '__main__': + run()