Contribute
Register

pbzx Stream Parser

SJ_UnderWater

Moderator
Joined
Dec 3, 2010
Messages
707
Motherboard
Gigabyte GA-H55M-S2V
CPU
Intel i3-530
Graphics
HIS HD 6570
Mac
iMac
Classic Mac
Mobile Phone
Android
For anyone interested in pbzx streams, the following command line tool can unpack the xz frames from stdin, then echo to stdio for piping to `cpio` for unarchiving. Implemented in simple C:

--edit
On the eve of the (likely) release, I have updated the parser. When compiled with liblzma, example usage to expand to the current directory is `pbzx <pkg> | cpio -idmu`. The library requires autopoint to build (gettext, automake, autoconf, libtool), and its archive can be linked in directly for a single executable (attached).
Finally, to those who would build on early work done by others, then turn around and bundle it in shareware, without publishing a specification of the format or example code, shame.

Code:
//
//  main.c
//  pbzx
//
//  Created by PHPdev32 on 6/20/14.
//  Licensed under GPLv3, full text at http://www.gnu.org/licenses/gpl-3.0.txt
//

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <xar/xar.h>
#include <lzma.h>
#define min(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __a : __b; })
#define err(c, m) if (c) { fprintf(stderr, m"\n"); exit(__COUNTER__ + 1); }
#define XBSZ 4 * 1024
#define ZBSZ 1024 * XBSZ

static inline void xar_read(char *buffer, uint32_t size, xar_stream *stream) {
    stream->next_out = buffer;
    stream->avail_out = size;
    while (stream->avail_out)
        err(xar_extract_tostream(stream) != XAR_STREAM_OK, "XAR extraction failure");
}

static inline size_t cpio_out(char *buffer, size_t size) {
    size_t c = 0;
    while (c < size)
        c+= fwrite(buffer + c, 1, size - c, stdout);
    return c;
}

static inline uint64_t xar_read_64(xar_stream *stream) {
    char t[8];
    xar_read(t, 8, stream);
    return __builtin_bswap64(*(uint64_t *)t);
}

int main(int argc, const char * argv[])
{

    // insert code here...
    char xbuf[XBSZ], *zbuf = malloc(ZBSZ);
    xar_t x;
    err(argc < 2, "No file specified");
    err(!(x = xar_open(argv[1], READ)), "XAR open failure");
    xar_iter_t i = xar_iter_new();
    xar_file_t f = xar_file_first(x, i);
    char *path;
    while (strncmp((path = xar_get_path(f)), "Payload", 7) && (f = xar_file_next(i)))
        free(path);
    free(path);
    xar_iter_free(i);
    err(!f, "No payload");
    err(xar_verify(x, f) != XAR_STREAM_OK, "File verification failed");
    xar_stream xs;
    err(xar_extract_tostream_init(x, f, &xs) != XAR_STREAM_OK, "XAR init failed");
    xar_read(xbuf, 4, &xs);
    err(strncmp(xbuf, "pbzx", 4), "Not a pbzx stream");
    uint64_t length = 0, flags = xar_read_64(&xs), last = 0;
    lzma_stream zs = LZMA_STREAM_INIT;
    err(lzma_stream_decoder(&zs, UINT64_MAX, LZMA_CONCATENATED) != LZMA_OK, "LZMA init failed");
    while (flags & 1 << 24) {
        flags = xar_read_64(&xs);
        length = xar_read_64(&xs);
        char plain = length == 0x1000000;
        xar_read(xbuf, min(XBSZ, (uint32_t)length), &xs);
        err(!plain && strncmp(xbuf, "\xfd""7zXZ\0", 6), "Header is not <FD>7zXZ<00>");
        while (length) {
            if (plain)
                cpio_out(xbuf, min(XBSZ, length));
            else {
                zs.next_in = (typeof(zs.next_in))xbuf;
                zs.avail_in = min(XBSZ, length);
                while (zs.avail_in) {
                    zs.next_out = (typeof(zs.next_out))zbuf;
                    zs.avail_out = ZBSZ;
                    err(lzma_code(&zs, LZMA_RUN) != LZMA_OK, "LZMA failure");
                    cpio_out(zbuf, ZBSZ - zs.avail_out);
                }
            }
            length -= last = min(XBSZ, length);
            xar_read(xbuf, min(XBSZ, (uint32_t)length), &xs);
        }
        err(!plain && strncmp(xbuf + last - 2, "YZ", 2), "Footer is not YZ");
    }
    xar_extract_tostream_end(&xs);
    free(zbuf);
    lzma_end(&zs);
    xar_close(x);
    return 0;
}
 

Attachments

Joined
Oct 26, 2014
Messages
9
Motherboard
H61md2h
CPU
I5-2500k
Graphics
Gt210
Mac
iMac
Mobile Phone
Android, iOS
How to use it to extract file ???
 
Joined
Apr 14, 2016
Messages
1
Mac
Classic Mac
Mobile Phone
Hi how to do if i want to Revert the xz compressed file back to the PAYLOAD pbxz original format
 
Joined
Jan 18, 2011
Messages
239
Motherboard
B85M-G
CPU
Core i7 4770
Graphics
nVidia 1050 Ti
Mac
iMac, MacBook Pro
Tried this on Sierra 10.12.1 combo updates' payload file. Throws an error:
XAR open failure
 

rlc

Joined
Mar 18, 2014
Messages
1
Mac
Classic Mac
Mobile Phone
This tool is great, helped me to recover legacy net commands, i.e. telnet, ftp, from Sierra install package. Thanks!
 
Top