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:
Родитель
761fdc3b83
Коммит
d4a253cae4
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
8
dmg/io.c
8
dmg/io.c
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче