Contribute
Register

pbzx Stream Parser

SJ_UnderWater

Moderator
Joined
Dec 3, 2010
Messages
652
Motherboard
Gigabyte GA-H55M-S2V
CPU
Intel i3-530
Graphics
HIS HD 6570
Mac
  1. iMac
Classic Mac
Mobile Phone
  1. 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

  • pbzx.zip
    41.4 KB · Views: 1,758
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
245
Motherboard
B85M-G
CPU
Core i7 4770
Graphics
nVidia 1050 Ti
Mac
  1. iMac
  2. 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
Motherboard
Asus Rampage ii gene
CPU
X5675
Graphics
GL216
Mac
  1. iMac
  2. MacBook
  3. MacBook Air
  4. MacBook Pro
  5. Mac mini
  6. Mac Pro
Mobile Phone
  1. iOS
This tool is great, helped me to recover legacy net commands, i.e. telnet, ftp, from Sierra install package. Thanks!
 
Top