this repo has no description
1//
2// main.c
3// pbzx
4//
5// Created by PHPdev32 on 6/20/14.
6// Licensed under GPLv3, full text at http://www.gnu.org/licenses/gpl-3.0.txt
7//
8
9#include <stdio.h>
10#include <stdint.h>
11#include <string.h>
12#include <stdlib.h>
13#include <xar/xar.h>
14#include <lzma.h>
15#define min(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __a : __b; })
16#define err(c, m) if (c) { fprintf(stderr, m"\n"); exit(__COUNTER__ + 1); }
17#define XBSZ 4 * 1024
18#define ZBSZ 1024 * XBSZ
19
20static inline void xar_read(char *buffer, uint32_t size, xar_stream *stream) {
21 stream->next_out = buffer;
22 stream->avail_out = size;
23 while (stream->avail_out)
24 err(xar_extract_tostream(stream) != XAR_STREAM_OK, "XAR extraction failure");
25}
26
27static inline size_t cpio_out(char *buffer, size_t size) {
28 size_t c = 0;
29 while (c < size)
30 c+= fwrite(buffer + c, 1, size - c, stdout);
31 return c;
32}
33
34static inline uint64_t xar_read_64(xar_stream *stream) {
35 char t[8];
36 xar_read(t, 8, stream);
37 return __builtin_bswap64(*(uint64_t *)t);
38}
39
40int main(int argc, const char * argv[])
41{
42 char xbuf[XBSZ], *zbuf = malloc(ZBSZ);
43 xar_t x;
44 err(argc < 2, "No file specified");
45 err(!(x = xar_open(argv[1], READ)), "XAR open failure");
46 xar_iter_t i = xar_iter_new();
47 xar_file_t f = xar_file_first(x, i);
48 char *path;
49 while (strncmp((path = xar_get_path(f)), "Content", 7) && (f = xar_file_next(i)))
50 free(path);
51 free(path);
52 xar_iter_free(i);
53 err(!f, "No payload");
54 err(xar_verify(x, f) != XAR_STREAM_OK, "File verification failed");
55 xar_stream xs;
56 err(xar_extract_tostream_init(x, f, &xs) != XAR_STREAM_OK, "XAR init failed");
57 xar_read(xbuf, 4, &xs);
58 err(strncmp(xbuf, "pbzx", 4), "Not a pbzx stream");
59 uint64_t length = 0, flags = xar_read_64(&xs), last = 0;
60 lzma_stream zs = LZMA_STREAM_INIT;
61 err(lzma_stream_decoder(&zs, UINT64_MAX, LZMA_CONCATENATED) != LZMA_OK, "LZMA init failed");
62 while (flags & 1 << 24) {
63 flags = xar_read_64(&xs);
64 length = xar_read_64(&xs);
65 char plain = length == 0x1000000;
66 xar_read(xbuf, min(XBSZ, (uint32_t)length), &xs);
67 err(!plain && strncmp(xbuf, "\xfd""7zXZ\0", 6), "Header is not <FD>7zXZ<00>");
68 while (length) {
69 if (plain)
70 cpio_out(xbuf, min(XBSZ, length));
71 else {
72 zs.next_in = (typeof(zs.next_in))xbuf;
73 zs.avail_in = min(XBSZ, length);
74 while (zs.avail_in) {
75 zs.next_out = (typeof(zs.next_out))zbuf;
76 zs.avail_out = ZBSZ;
77 err(lzma_code(&zs, LZMA_RUN) != LZMA_OK, "LZMA failure");
78 cpio_out(zbuf, ZBSZ - zs.avail_out);
79 }
80 }
81 length -= last = min(XBSZ, length);
82 xar_read(xbuf, min(XBSZ, (uint32_t)length), &xs);
83 }
84 err(!plain && strncmp(xbuf + last - 2, "YZ", 2), "Footer is not YZ");
85 }
86 xar_extract_tostream_end(&xs);
87 free(zbuf);
88 lzma_end(&zs);
89 xar_close(x);
90 return 0;
91}