Permalink
Browse files

ADC support for libdmg-hfsplus

adds decompression support only. code is from dmg2img
(http://vu1tur.eu.org/tools/) and is available under the GPL
  • Loading branch information...
1 parent 761fdc3 commit d4a253cae40fb4b38377273eb1f89f21c4cb224a Derrick Brashear committed Mar 7, 2010
Showing with 149 additions and 1 deletion.
  1. +1 −1 dmg/CMakeLists.txt
  2. +116 −0 dmg/adc.c
  3. +8 −0 dmg/dmgfile.c
  4. +8 −0 dmg/io.c
  5. +15 −0 includes/dmg/adc.h
  6. +1 −0 includes/dmg/dmg.h
View
@@ -16,7 +16,7 @@ link_directories(${ZLIB_LIBRARIES})
link_directories(${PROJECT_BINARY_DIR}/common ${PROJECT_BINARY_DIR}/hfs)
-add_library(dmg base64.c checksum.c dmgfile.c dmglib.c filevault.c io.c partition.c resources.c udif.c)
+add_library(dmg adc.c base64.c checksum.c dmgfile.c dmglib.c filevault.c io.c partition.c resources.c udif.c)
IF(OPENSSL_FOUND)
add_definitions(-DHAVE_CRYPT)
View
@@ -0,0 +1,116 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <dmg/dmg.h>
+#include <dmg/adc.h>
+
+int adc_decompress(int in_size, unsigned char *input, int avail_size, unsigned char *output, int *bytes_written)
+{
+ if (in_size == 0)
+ return 0;
+ bool output_full = false;
+ unsigned char *inp = input;
+ unsigned char *outp = output;
+ int chunk_type;
+ int chunk_size;
+ int offset;
+ int i;
+
+ while (inp - input < in_size) {
+ chunk_type = adc_chunk_type(*inp);
+ switch (chunk_type) {
+ case ADC_PLAIN:
+ chunk_size = adc_chunk_size(*inp);
+ if (outp + chunk_size - output > avail_size) {
+ output_full = true;
+ break;
+ }
+ memcpy(outp, inp + 1, chunk_size);
+ inp += chunk_size + 1;
+ outp += chunk_size;
+ break;
+
+ case ADC_2BYTE:
+ chunk_size = adc_chunk_size(*inp);
+ offset = adc_chunk_offset(inp);
+ if (outp + chunk_size - output > avail_size) {
+ output_full = true;
+ break;
+ }
+ if (offset == 0) {
+ memset(outp, *(outp - offset - 1), chunk_size);
+ outp += chunk_size;
+ inp += 2;
+ } else {
+ for (i = 0; i < chunk_size; i++) {
+ memcpy(outp, outp - offset - 1, 1);
+ outp++;
+ }
+ inp += 2;
+ }
+ break;
+
+ case ADC_3BYTE:
+ chunk_size = adc_chunk_size(*inp);
+ offset = adc_chunk_offset(inp);
+ if (outp + chunk_size - output > avail_size) {
+ output_full = true;
+ break;
+ }
+ if (offset == 0) {
+ memset(outp, *(outp - offset - 1), chunk_size);
+ outp += chunk_size;
+ inp += 3;
+ } else {
+ for (i = 0; i < chunk_size; i++) {
+ memcpy(outp, outp - offset - 1, 1);
+ outp++;
+ }
+ inp += 3;
+ }
+ break;
+ }
+ if (output_full)
+ break;
+ }
+ *bytes_written = outp - output;
+ return inp - input;
+}
+
+int adc_chunk_type(char _byte)
+{
+ if (_byte & 0x80)
+ return ADC_PLAIN;
+ if (_byte & 0x40)
+ return ADC_3BYTE;
+ return ADC_2BYTE;
+}
+
+int adc_chunk_size(char _byte)
+{
+ switch (adc_chunk_type(_byte)) {
+ case ADC_PLAIN:
+ return (_byte & 0x7F) + 1;
+ case ADC_2BYTE:
+ return ((_byte & 0x3F) >> 2) + 3;
+ case ADC_3BYTE:
+ return (_byte & 0x3F) + 4;
+ }
+ return -1;
+}
+
+int adc_chunk_offset(unsigned char *chunk_start)
+{
+ unsigned char *c = chunk_start;
+ switch (adc_chunk_type(*c)) {
+ case ADC_PLAIN:
+ return 0;
+ case ADC_2BYTE:
+ return ((((unsigned char)*c & 0x03)) << 8) + (unsigned char)*(c + 1);
+ case ADC_3BYTE:
+ return (((unsigned char)*(c + 1)) << 8) + (unsigned char)*(c + 2);
+ }
+ return -1;
+}
View
@@ -30,6 +30,14 @@ static void cacheRun(DMG* dmg, BLKXTable* blkx, int run) {
ASSERT(dmg->dmg->seek(dmg->dmg, blkx->dataStart + blkx->runs[run].compOffset) == 0, "fseeko");
switch(blkx->runs[run].type) {
+ case BLOCK_ADC:
+ bufferRead = 0;
+ do {
+ strm.avail_in = dmg->dmg->read(dmg->dmg, inBuffer, blkx->runs[run].compLength);
+ strm.avail_out = adc_decompress(strm.avail_in, inBuffer, bufferSize, dmg->runData, &have);
+ bufferRead+=strm.avail_out;
+ } while (bufferRead < blkx->runs[run].compLength);
+ break;
case BLOCK_ZLIB:
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
View
@@ -182,6 +182,14 @@ void extractBLKX(AbstractFile* in, AbstractFile* out, BLKXTable* blkx) {
printf("run %d: start=%" PRId64 " sectors=%" PRId64 ", length=%" PRId64 ", fileOffset=0x%" PRIx64 "\n", i, initialOffset + (blkx->runs[i].sectorStart * SECTOR_SIZE), blkx->runs[i].sectorCount, blkx->runs[i].compLength, blkx->runs[i].compOffset);
switch(blkx->runs[i].type) {
+ case BLOCK_ADC:
+ do {
+ ASSERT((strm.avail_in = in->read(in, inBuffer, blkx->runs[i].compLength)) == blkx->runs[i].compLength, "fread");
+ strm.avail_out = adc_decompress(strm.avail_in, inBuffer, bufferSize, outBuffer, &have);
+ ASSERT(out->write(out, outBuffer, have) == have, "mWrite");
+ bufferRead+=strm.avail_out;
+ } while (bufferRead < blkx->runs[i].compLength);
+ break;
case BLOCK_ZLIB:
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
View
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <unistd.h>
+
+#define ADC_PLAIN 0x01
+#define ADC_2BYTE 0x02
+#define ADC_3BYTE 0x03
+
+#define bool short
+#define true 1
+#define false 0
+
+int adc_decompress(int in_size, unsigned char *input, int avail_size, unsigned char *output, int *bytes_written);
+int adc_chunk_type(char _byte);
+int adc_chunk_size(char _byte);
+int adc_chunk_offset(unsigned char *chunk_start);
View
@@ -13,6 +13,7 @@
#define CHECKSUM_NONE 0x0000
#define BLOCK_ZLIB 0x80000005
+#define BLOCK_ADC 0x80000004
#define BLOCK_RAW 0x00000001
#define BLOCK_IGNORE 0x00000002
#define BLOCK_COMMENT 0x7FFFFFFE

0 comments on commit d4a253c

Please sign in to comment.