ADC support for libdmg-hfsplus

adds decompression support only. code is from dmg2img
(http://vu1tur.eu.org/tools/) and is available under the GPL
This commit is contained in:
Derrick Brashear 2010-03-07 08:47:13 -05:00
Родитель 761fdc3b83
Коммит d4a253cae4
6 изменённых файлов: 149 добавлений и 1 удалений

Просмотреть файл

@ -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)

116
dmg/adc.c Normal file
Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

15
includes/dmg/adc.h Normal file
Просмотреть файл

@ -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);

Просмотреть файл

@ -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