Browse code

bb #1570: process bzip stripes

David Raynor authored on 2013/09/17 02:31:06
Showing 1 changed files
... ...
@@ -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) ||