| ... | ... |
@@ -56,6 +56,7 @@ |
| 56 | 56 |
#include "sf_base64decode.h" |
| 57 | 57 |
|
| 58 | 58 |
// #define DEBUG_DMG_PARSE |
| 59 |
+// #define DEBUG_DMG_BZIP |
|
| 59 | 60 |
|
| 60 | 61 |
#ifdef DEBUG_DMG_PARSE |
| 61 | 62 |
# define dmg_parsemsg(...) cli_dbgmsg( __VA_ARGS__) |
| ... | ... |
@@ -63,6 +64,12 @@ |
| 63 | 63 |
# define dmg_parsemsg(...) ; |
| 64 | 64 |
#endif |
| 65 | 65 |
|
| 66 |
+#ifdef DEBUG_DMG_BZIP |
|
| 67 |
+# define dmg_bzipmsg(...) cli_dbgmsg( __VA_ARGS__) |
|
| 68 |
+#else |
|
| 69 |
+# define dmg_bzipmsg(...) ; |
|
| 70 |
+#endif |
|
| 71 |
+ |
|
| 66 | 72 |
enum dmgReadState {
|
| 67 | 73 |
DMG_FIND_BASE_PLIST = 0, |
| 68 | 74 |
DMG_FIND_BASE_DICT = 1, |
| ... | ... |
@@ -127,6 +134,10 @@ int cli_scandmg(cli_ctx *ctx) |
| 127 | 127 |
return CL_EFORMAT; |
| 128 | 128 |
} |
| 129 | 129 |
|
| 130 |
+ hdr.dataForkOffset = be64_to_host(hdr.dataForkOffset); |
|
| 131 |
+ hdr.dataForkLength = be64_to_host(hdr.dataForkLength); |
|
| 132 |
+ cli_dbgmsg("cli_scandmg: data offset %lu len %d\n", (unsigned long)hdr.dataForkOffset, (int)hdr.dataForkLength);
|
|
| 133 |
+ |
|
| 130 | 134 |
hdr.xmlOffset = be64_to_host(hdr.xmlOffset); |
| 131 | 135 |
hdr.xmlLength = be64_to_host(hdr.xmlLength); |
| 132 | 136 |
if (hdr.xmlLength > (uint64_t)INT_MAX) {
|
| ... | ... |
@@ -710,7 +721,7 @@ static int dmg_stripe_inflate(cli_ctx *ctx, int fd, uint32_t index, struct dmg_m |
| 710 | 710 |
size_t off = mish_set->stripes[index].dataOffset; |
| 711 | 711 |
size_t len = mish_set->stripes[index].dataLength; |
| 712 | 712 |
off_t nbytes = 0; |
| 713 |
- char obuf[BUFSIZ]; |
|
| 713 |
+ uint8_t obuf[BUFSIZ]; |
|
| 714 | 714 |
|
| 715 | 715 |
cli_dbgmsg("dmg_stripe_inflate: stripe %lu\n", (unsigned long)index);
|
| 716 | 716 |
if (len == 0) |
| ... | ... |
@@ -790,10 +801,109 @@ static int dmg_stripe_inflate(cli_ctx *ctx, int fd, uint32_t index, struct dmg_m |
| 790 | 790 |
/* Stripe handling: bzip block (type 0x80000006) */ |
| 791 | 791 |
static int dmg_stripe_bzip(cli_ctx *ctx, int fd, uint32_t index, struct dmg_mish_with_stripes *mish_set) |
| 792 | 792 |
{
|
| 793 |
- /* Temporary stub */ |
|
| 794 |
- cli_dbgmsg("dmg_stripe_bzip: stripe %lu\n", (unsigned long)index);
|
|
| 793 |
+ int ret = CL_CLEAN; |
|
| 794 |
+ size_t len = mish_set->stripes[index].dataLength; |
|
| 795 |
+#if HAVE_BZLIB_H |
|
| 796 |
+ size_t off = mish_set->stripes[index].dataOffset; |
|
| 797 |
+ int rc; |
|
| 798 |
+ bz_stream strm; |
|
| 799 |
+ size_t size_so_far = 0; |
|
| 800 |
+ uint8_t obuf[BUFSIZ]; |
|
| 801 |
+#endif |
|
| 795 | 802 |
|
| 796 |
- return CL_CLEAN; |
|
| 803 |
+ cli_dbgmsg("dmg_stripe_bzip: stripe %lu initial len %lu expected len %lu\n", (unsigned long)index,
|
|
| 804 |
+ (unsigned long)len, (unsigned long)mish_set->stripes[index].sectorCount * DMG_SECTOR_SIZE); |
|
| 805 |
+ |
|
| 806 |
+#if HAVE_BZLIB_H |
|
| 807 |
+ memset(&strm, 0, sizeof(strm)); |
|
| 808 |
+ strm.next_out = obuf; |
|
| 809 |
+ strm.avail_out = sizeof(obuf); |
|
| 810 |
+ if (BZ2_bzDecompressInit(&strm, 0, 0) != BZ_OK) {
|
|
| 811 |
+ cli_dbgmsg("dmg_stripe_bzip: bzDecompressInit failed\n");
|
|
| 812 |
+ return CL_EOPEN; |
|
| 813 |
+ } |
|
| 814 |
+ |
|
| 815 |
+ do {
|
|
| 816 |
+ if (strm.avail_in == 0) {
|
|
| 817 |
+ size_t next_len = (len > sizeof(obuf)) ? sizeof(obuf) : len; |
|
| 818 |
+ dmg_bzipmsg("dmg_stripe_bzip: off %lu len %lu next_len %lu\n", off, len, next_len);
|
|
| 819 |
+ strm.next_in = (void*)fmap_need_off_once(*ctx->fmap, off, next_len); |
|
| 820 |
+ if (strm.next_in == NULL) {
|
|
| 821 |
+ cli_dbgmsg("dmg_stripe_bzip: expected more stream\n");
|
|
| 822 |
+ ret = CL_EMAP; |
|
| 823 |
+ break; |
|
| 824 |
+ } |
|
| 825 |
+ strm.avail_in = next_len; |
|
| 826 |
+ len -= next_len; |
|
| 827 |
+ off += next_len; |
|
| 828 |
+ } |
|
| 829 |
+ |
|
| 830 |
+ dmg_bzipmsg("dmg_stripe_bzip: before = strm.avail_in %lu strm.avail_out: %lu\n", strm.avail_in, strm.avail_out);
|
|
| 831 |
+ rc = BZ2_bzDecompress(&strm); |
|
| 832 |
+ if ((rc != BZ_OK) && (rc != BZ_STREAM_END)) {
|
|
| 833 |
+ cli_dbgmsg("dmg_stripe_bzip: decompress error: %d\n", rc);
|
|
| 834 |
+ ret = CL_EFORMAT; |
|
| 835 |
+ break; |
|
| 836 |
+ } |
|
| 837 |
+ |
|
| 838 |
+ dmg_bzipmsg("dmg_stripe_bzip: after = strm.avail_in %lu strm.avail_out: %lu rc: %d %d\n",
|
|
| 839 |
+ strm.avail_in, strm.avail_out, rc, BZ_STREAM_END); |
|
| 840 |
+ /* Drain output buffer */ |
|
| 841 |
+ if (!strm.avail_out) {
|
|
| 842 |
+ size_t next_write = sizeof(obuf); |
|
| 843 |
+ do {
|
|
| 844 |
+ size_so_far += next_write; |
|
| 845 |
+ dmg_bzipmsg("dmg_stripe_bzip: size_so_far: %lu next_write: %lu\n", size_so_far, next_write);
|
|
| 846 |
+ |
|
| 847 |
+ ret = cli_checklimits("dmg_stripe_bzip", ctx, (unsigned long)(size_so_far + sizeof(obuf)), 0, 0);
|
|
| 848 |
+ if (ret != CL_CLEAN) {
|
|
| 849 |
+ break; |
|
| 850 |
+ } |
|
| 851 |
+ |
|
| 852 |
+ if (cli_writen(fd, obuf, next_write) != next_write) {
|
|
| 853 |
+ cli_dbgmsg("dmg_stripe_bzip: error writing to tmpfile\n");
|
|
| 854 |
+ ret = CL_EWRITE; |
|
| 855 |
+ break; |
|
| 856 |
+ } |
|
| 857 |
+ |
|
| 858 |
+ strm.next_out = obuf; |
|
| 859 |
+ strm.avail_out = sizeof(obuf); |
|
| 860 |
+ |
|
| 861 |
+ if (rc == BZ_OK) |
|
| 862 |
+ rc = BZ2_bzDecompress(&strm); |
|
| 863 |
+ if ((rc != BZ_OK) && (rc != BZ_STREAM_END)) {
|
|
| 864 |
+ cli_dbgmsg("dmg_stripe_bzip: decompress error: %d\n", rc);
|
|
| 865 |
+ ret = CL_EFORMAT; |
|
| 866 |
+ break; |
|
| 867 |
+ } |
|
| 868 |
+ } while (!strm.avail_out); |
|
| 869 |
+ } |
|
| 870 |
+ /* Stream end, so write data if any remains in buffer */ |
|
| 871 |
+ if (rc == BZ_STREAM_END) {
|
|
| 872 |
+ size_t next_write = sizeof(obuf) - strm.avail_out; |
|
| 873 |
+ size_so_far += next_write; |
|
| 874 |
+ dmg_bzipmsg("dmg_stripe_bzip: size_so_far: %lu next_write: %lu\n", size_so_far, next_write);
|
|
| 875 |
+ |
|
| 876 |
+ ret = cli_checklimits("dmg_stripe_bzip", ctx, size_so_far + sizeof(obuf), 0, 0);
|
|
| 877 |
+ if (ret != CL_CLEAN) {
|
|
| 878 |
+ break; |
|
| 879 |
+ } |
|
| 880 |
+ |
|
| 881 |
+ if (cli_writen(fd, obuf, next_write) != next_write) {
|
|
| 882 |
+ cli_dbgmsg("dmg_stripe_bzip: error writing to tmpfile\n");
|
|
| 883 |
+ ret = CL_EWRITE; |
|
| 884 |
+ break; |
|
| 885 |
+ } |
|
| 886 |
+ |
|
| 887 |
+ strm.next_out = obuf; |
|
| 888 |
+ strm.avail_out = sizeof(obuf); |
|
| 889 |
+ } |
|
| 890 |
+ } while ((rc == BZ_OK) && (len > 0)); |
|
| 891 |
+ |
|
| 892 |
+ BZ2_bzDecompressEnd(&strm); |
|
| 893 |
+#endif |
|
| 894 |
+ |
|
| 895 |
+ return ret; |
|
| 797 | 896 |
} |
| 798 | 897 |
|
| 799 | 898 |
/* Given mish data, reconstruct the partition details */ |
| ... | ... |
@@ -816,7 +926,7 @@ static int dmg_handle_mish(cli_ctx *ctx, unsigned int mishblocknum, char *dir, |
| 816 | 816 |
blocklist[i].sectorCount = be64_to_host(blocklist[i].sectorCount); |
| 817 | 817 |
blocklist[i].dataOffset = be64_to_host(blocklist[i].dataOffset); |
| 818 | 818 |
blocklist[i].dataLength = be64_to_host(blocklist[i].dataLength); |
| 819 |
- cli_dbgmsg("mish %lu block %u type %lx start %lu count %lu source %lu length %lu\n", mishblocknum, i,
|
|
| 819 |
+ cli_dbgmsg("mish %lu stripe %u type %lx start %lu count %lu source %lu length %lu\n", mishblocknum, i,
|
|
| 820 | 820 |
blocklist[i].type, blocklist[i].startSector, blocklist[i].sectorCount, |
| 821 | 821 |
blocklist[i].dataOffset, blocklist[i].dataLength); |
| 822 | 822 |
if ((blocklist[i].dataOffset > xmlOffset) || |