Fixed bugs and implemented iso to dmg conversion

This commit is contained in:
planetbeing 2008-04-24 11:15:11 -04:00
Родитель 780984d5dd
Коммит a5a0490222
2 изменённых файлов: 236 добавлений и 194 удалений

115
dmg/dmg.c
Просмотреть файл

@ -262,6 +262,9 @@ int convertToDMG(const char* source, const char* dest) {
char partitionName[512]; char partitionName[512];
off_t fileLength;
numSectors = 0; numSectors = 0;
resources = NULL; resources = NULL;
@ -274,54 +277,95 @@ int convertToDMG(const char* source, const char* dest) {
ASSERT(file = fopen(source, "rb"), "fopen"); ASSERT(file = fopen(source, "rb"), "fopen");
ASSERT(outFile = fopen(dest, "wb"), "fopen"); ASSERT(outFile = fopen(dest, "wb"), "fopen");
printf("Writing DDM...\n"); fflush(stdout); printf("Processing DDM...\n"); fflush(stdout);
DDM = (DriverDescriptorRecord*) malloc(SECTOR_SIZE); DDM = (DriverDescriptorRecord*) malloc(SECTOR_SIZE);
fseeko(file, 0, SEEK_SET); fseeko(file, 0, SEEK_SET);
ASSERT(fread(DDM, SECTOR_SIZE, 1, file) == 1, "fread"); ASSERT(fread(DDM, SECTOR_SIZE, 1, file) == 1, "fread");
flipDriverDescriptorRecord(DDM, FALSE); flipDriverDescriptorRecord(DDM, FALSE);
writeDriverDescriptorMap(outFile, DDM, &CRCProxy, (void*) (&dataForkToken), &resources); if(DDM->sbSig == 0x4552) {
free(DDM); writeDriverDescriptorMap(outFile, DDM, &CRCProxy, (void*) (&dataForkToken), &resources);
free(DDM);
printf("Reading partition map...\n"); fflush(stdout);
printf("Processing partition map...\n"); fflush(stdout);
fseeko(file, SECTOR_SIZE, SEEK_SET);
ASSERT(fread(partitions, SECTOR_SIZE, 1, file) == 1, "fread"); fseeko(file, SECTOR_SIZE, SEEK_SET);
flipPartition(partitions, FALSE); ASSERT(fread(partitions, SECTOR_SIZE, 1, file) == 1, "fread");
flipPartition(partitions, FALSE);
partitions = (Partition*) realloc(partitions, SECTOR_SIZE * partitions->pmMapBlkCnt);
partitions = (Partition*) realloc(partitions, SECTOR_SIZE * partitions->pmMapBlkCnt);
fseeko(file, SECTOR_SIZE, SEEK_SET);
ASSERT(fread(partitions, SECTOR_SIZE * partitions->pmMapBlkCnt, 1, file) == 1, "fread"); fseeko(file, SECTOR_SIZE, SEEK_SET);
flipPartition(partitions, FALSE); ASSERT(fread(partitions, SECTOR_SIZE * partitions->pmMapBlkCnt, 1, file) == 1, "fread");
flipPartition(partitions, FALSE);
printf("Writing blkx...\n"); fflush(stdout);
printf("Writing blkx...\n"); fflush(stdout);
for(i = 0; i < partitions->pmPartBlkCnt; i++) {
if(partitions[i].pmSig != APPLE_PARTITION_MAP_SIGNATURE) { for(i = 0; i < partitions->pmPartBlkCnt; i++) {
break; if(partitions[i].pmSig != APPLE_PARTITION_MAP_SIGNATURE) {
break;
}
printf("Processing blkx %d...\n", i); fflush(stdout);
sprintf(partitionName, "%s (%s : %d)", partitions[i].pmPartName, partitions[i].pmParType, i + 1);
memset(&uncompressedToken, 0, sizeof(uncompressedToken));
fseeko(file, partitions[i].pmPyPartStart * SECTOR_SIZE, SEEK_SET);
blkx = insertBLKX(outFile, (void*) file, partitions[i].pmPyPartStart, partitions[i].pmPartBlkCnt, i, CHECKSUM_CRC32, &freadWrapper, &fseekWrapper, &ftellWrapper,
&BlockCRC, &uncompressedToken, &CRCProxy, &dataForkToken, NULL);
blkx->checksum.data[0] = uncompressedToken.crc;
resources = insertData(resources, "blkx", i, partitionName, (const char*) blkx, sizeof(BLKXTable) + (blkx->blocksRunCount * sizeof(BLKXRun)), ATTRIBUTE_HDIUTIL);
free(blkx);
memset(&csum, 0, sizeof(CSumResource));
csum.version = 1;
csum.type = CHECKSUM_MKBLOCK;
csum.checksum = uncompressedToken.block;
resources = insertData(resources, "cSum", i, "", (const char*) (&csum), sizeof(csum), 0);
if(nsiz == NULL) {
nsiz = myNSiz = (NSizResource*) malloc(sizeof(NSizResource));
} else {
myNSiz->next = (NSizResource*) malloc(sizeof(NSizResource));
myNSiz = myNSiz->next;
}
memset(myNSiz, 0, sizeof(NSizResource));
myNSiz->isVolume = FALSE;
myNSiz->blockChecksum2 = uncompressedToken.block;
myNSiz->partitionNumber = i;
myNSiz->version = 6;
myNSiz->next = NULL;
if((partitions[i].pmPyPartStart + partitions[i].pmPartBlkCnt) > numSectors) {
numSectors = partitions[i].pmPyPartStart + partitions[i].pmPartBlkCnt;
}
} }
printf("Processing blkx %d...\n", i); fflush(stdout); koly.fUDIFImageVariant = kUDIFDeviceImageType;
} else {
printf("No DDM! Just doing one huge blkx then...\n"); fflush(stdout);
sprintf(partitionName, "%s (%s : %d)", partitions[i].pmPartName, partitions[i].pmParType, i + 1); fseeko(file, 0, SEEK_END);
fileLength = ftello(file);
memset(&uncompressedToken, 0, sizeof(uncompressedToken)); memset(&uncompressedToken, 0, sizeof(uncompressedToken));
fseeko(file, partitions[i].pmPyPartStart * SECTOR_SIZE, SEEK_SET); fseeko(file, 0, SEEK_SET);
blkx = insertBLKX(outFile, (void*) file, partitions[i].pmPyPartStart * SECTOR_SIZE, partitions[i].pmPartBlkCnt, i, CHECKSUM_CRC32, &freadWrapper, &fseekWrapper, &ftellWrapper, blkx = insertBLKX(outFile, (void*) file, 0, fileLength/SECTOR_SIZE, ENTIRE_DEVICE_DESCRIPTOR, CHECKSUM_CRC32, &freadWrapper, &fseekWrapper, &ftellWrapper,
&BlockCRC, &uncompressedToken, &CRCProxy, &dataForkToken, NULL); &BlockCRC, &uncompressedToken, &CRCProxy, &dataForkToken, NULL);
resources = insertData(resources, "blkx", 0, "whole disk (unknown partition : 0)", (const char*) blkx, sizeof(BLKXTable) + (blkx->blocksRunCount * sizeof(BLKXRun)), ATTRIBUTE_HDIUTIL);
blkx->checksum.data[0] = uncompressedToken.crc;
resources = insertData(resources, "blkx", i, partitionName, (const char*) blkx, sizeof(BLKXTable) + (blkx->blocksRunCount * sizeof(BLKXRun)), ATTRIBUTE_HDIUTIL);
free(blkx); free(blkx);
memset(&csum, 0, sizeof(CSumResource)); memset(&csum, 0, sizeof(CSumResource));
csum.version = 1; csum.version = 1;
csum.type = CHECKSUM_MKBLOCK; csum.type = CHECKSUM_MKBLOCK;
csum.checksum = uncompressedToken.block; csum.checksum = uncompressedToken.block;
resources = insertData(resources, "cSum", i, "", (const char*) (&csum), sizeof(csum), 0); resources = insertData(resources, "cSum", 0, "", (const char*) (&csum), sizeof(csum), 0);
if(nsiz == NULL) { if(nsiz == NULL) {
nsiz = myNSiz = (NSizResource*) malloc(sizeof(NSizResource)); nsiz = myNSiz = (NSizResource*) malloc(sizeof(NSizResource));
} else { } else {
@ -332,13 +376,11 @@ int convertToDMG(const char* source, const char* dest) {
memset(myNSiz, 0, sizeof(NSizResource)); memset(myNSiz, 0, sizeof(NSizResource));
myNSiz->isVolume = FALSE; myNSiz->isVolume = FALSE;
myNSiz->blockChecksum2 = uncompressedToken.block; myNSiz->blockChecksum2 = uncompressedToken.block;
myNSiz->partitionNumber = i; myNSiz->partitionNumber = 0;
myNSiz->version = 6; myNSiz->version = 6;
myNSiz->next = NULL; myNSiz->next = NULL;
if((partitions[i].pmPyPartStart + partitions[i].pmPartBlkCnt) > numSectors) { koly.fUDIFImageVariant = kUDIFPartitionImageType;
numSectors = partitions[i].pmPyPartStart + partitions[i].pmPartBlkCnt;
}
} }
dataForkChecksum = dataForkToken.crc; dataForkChecksum = dataForkToken.crc;
@ -389,7 +431,6 @@ int convertToDMG(const char* source, const char* dest) {
koly.fUDIFMasterChecksum.data[0] = calculateMasterChecksum(resources); koly.fUDIFMasterChecksum.data[0] = calculateMasterChecksum(resources);
printf("Master checksum: %x\n", koly.fUDIFMasterChecksum.data[0]); fflush(stdout); printf("Master checksum: %x\n", koly.fUDIFMasterChecksum.data[0]); fflush(stdout);
koly.fUDIFImageVariant = kUDIFDeviceImageType;
koly.fUDIFSectorCount = numSectors; koly.fUDIFSectorCount = numSectors;
koly.reserved2 = 0; koly.reserved2 = 0;
koly.reserved3 = 0; koly.reserved3 = 0;
@ -402,7 +443,7 @@ int convertToDMG(const char* source, const char* dest) {
printf("Cleaning up...\n"); fflush(stdout); printf("Cleaning up...\n"); fflush(stdout);
releaseResources(resources); releaseResources(resources);
fclose(file); fclose(file);
free(partitions); free(partitions);

315
dmg/dmg.h
Просмотреть файл

@ -40,177 +40,178 @@
#define BOOTCODE_GOON 0x676F6F6E #define BOOTCODE_GOON 0x676F6F6E
enum { enum {
kUDIFFlagsFlattened = 1 kUDIFFlagsFlattened = 1
}; };
enum { enum {
kUDIFDeviceImageType = 1 kUDIFDeviceImageType = 1,
kUDIFPartitionImageType = 2
}; };
typedef struct { typedef struct {
uint32_t type; uint32_t type;
uint32_t size; uint32_t size;
uint32_t data[0x20]; uint32_t data[0x20];
} __attribute__((__packed__)) UDIFChecksum; } __attribute__((__packed__)) UDIFChecksum;
typedef struct { typedef struct {
uint32_t data1; /* smallest */ uint32_t data1; /* smallest */
uint32_t data2; uint32_t data2;
uint32_t data3; uint32_t data3;
uint32_t data4; /* largest */ uint32_t data4; /* largest */
} __attribute__((__packed__)) UDIFID; } __attribute__((__packed__)) UDIFID;
typedef struct { typedef struct {
uint32_t fUDIFSignature; uint32_t fUDIFSignature;
uint32_t fUDIFVersion; uint32_t fUDIFVersion;
uint32_t fUDIFHeaderSize; uint32_t fUDIFHeaderSize;
uint32_t fUDIFFlags; uint32_t fUDIFFlags;
uint64_t fUDIFRunningDataForkOffset; uint64_t fUDIFRunningDataForkOffset;
uint64_t fUDIFDataForkOffset; uint64_t fUDIFDataForkOffset;
uint64_t fUDIFDataForkLength; uint64_t fUDIFDataForkLength;
uint64_t fUDIFRsrcForkOffset; uint64_t fUDIFRsrcForkOffset;
uint64_t fUDIFRsrcForkLength; uint64_t fUDIFRsrcForkLength;
uint32_t fUDIFSegmentNumber; uint32_t fUDIFSegmentNumber;
uint32_t fUDIFSegmentCount; uint32_t fUDIFSegmentCount;
UDIFID fUDIFSegmentID; /* a 128-bit number like a GUID, but does not seem to be a OSF GUID, since it doesn't have the proper versioning byte */ UDIFID fUDIFSegmentID; /* a 128-bit number like a GUID, but does not seem to be a OSF GUID, since it doesn't have the proper versioning byte */
UDIFChecksum fUDIFDataForkChecksum; UDIFChecksum fUDIFDataForkChecksum;
uint64_t fUDIFXMLOffset; uint64_t fUDIFXMLOffset;
uint64_t fUDIFXMLLength; uint64_t fUDIFXMLLength;
uint8_t reserved1[0x78]; /* this is actually the perfect amount of space to store every thing in this struct until the checksum */ uint8_t reserved1[0x78]; /* this is actually the perfect amount of space to store every thing in this struct until the checksum */
UDIFChecksum fUDIFMasterChecksum; UDIFChecksum fUDIFMasterChecksum;
uint32_t fUDIFImageVariant; uint32_t fUDIFImageVariant;
uint64_t fUDIFSectorCount; uint64_t fUDIFSectorCount;
uint32_t reserved2; uint32_t reserved2;
uint32_t reserved3; uint32_t reserved3;
uint32_t reserved4; uint32_t reserved4;
} __attribute__((__packed__)) UDIFResourceFile; } __attribute__((__packed__)) UDIFResourceFile;
typedef struct { typedef struct {
uint32_t type; uint32_t type;
uint32_t reserved; uint32_t reserved;
uint64_t sectorStart; uint64_t sectorStart;
uint64_t sectorCount; uint64_t sectorCount;
uint64_t compOffset; uint64_t compOffset;
uint64_t compLength; uint64_t compLength;
} __attribute__((__packed__)) BLKXRun; } __attribute__((__packed__)) BLKXRun;
typedef struct { typedef struct {
uint16_t version; /* set to 5 */ uint16_t version; /* set to 5 */
uint32_t isHFS; /* first dword of v53(ImageInfoRec): Set to 1 if it's a HFS or HFS+ partition -- duh. */ uint32_t isHFS; /* first dword of v53(ImageInfoRec): Set to 1 if it's a HFS or HFS+ partition -- duh. */
uint32_t unknown1; /* second dword of v53: seems to be garbage if it's HFS+, stuff related to HFS embedded if it's that*/ uint32_t unknown1; /* second dword of v53: seems to be garbage if it's HFS+, stuff related to HFS embedded if it's that*/
uint8_t dataLen; /* length of data that proceeds, comes right before the data in ImageInfoRec. Always set to 0 for HFS, HFS+ */ uint8_t dataLen; /* length of data that proceeds, comes right before the data in ImageInfoRec. Always set to 0 for HFS, HFS+ */
uint8_t data[255]; /* other data from v53, dataLen + 1 bytes, the rest NULL filled... a string? Not set for HFS, HFS+ */ uint8_t data[255]; /* other data from v53, dataLen + 1 bytes, the rest NULL filled... a string? Not set for HFS, HFS+ */
uint32_t unknown2; /* 8 bytes before volumeModified in v53, seems to be always set to 0 for HFS, HFS+ */ uint32_t unknown2; /* 8 bytes before volumeModified in v53, seems to be always set to 0 for HFS, HFS+ */
uint32_t unknown3; /* 4 bytes before volumeModified in v53, seems to be always set to 0 for HFS, HFS+ */ uint32_t unknown3; /* 4 bytes before volumeModified in v53, seems to be always set to 0 for HFS, HFS+ */
uint32_t volumeModified; /* offset 272 in v53 */ uint32_t volumeModified; /* offset 272 in v53 */
uint32_t unknown4; /* always seems to be 0 for UDIF */ uint32_t unknown4; /* always seems to be 0 for UDIF */
uint16_t volumeSignature; /* HX in our case */ uint16_t volumeSignature; /* HX in our case */
uint16_t sizePresent; /* always set to 1 */ uint16_t sizePresent; /* always set to 1 */
} __attribute__((__packed__)) SizeResource; } __attribute__((__packed__)) SizeResource;
typedef struct { typedef struct {
uint16_t version; /* set to 1 */ uint16_t version; /* set to 1 */
uint32_t type; /* set to 0x2 for MKBlockChecksum */ uint32_t type; /* set to 0x2 for MKBlockChecksum */
uint32_t checksum; uint32_t checksum;
} __attribute__((__packed__)) CSumResource; } __attribute__((__packed__)) CSumResource;
typedef struct NSizResource { typedef struct NSizResource {
char isVolume; char isVolume;
unsigned char* sha1Digest; unsigned char* sha1Digest;
uint32_t blockChecksum2; uint32_t blockChecksum2;
uint32_t bytes; uint32_t bytes;
uint32_t modifyDate; uint32_t modifyDate;
uint32_t partitionNumber; uint32_t partitionNumber;
uint32_t version; uint32_t version;
uint32_t volumeSignature; uint32_t volumeSignature;
struct NSizResource* next; struct NSizResource* next;
} NSizResource; } NSizResource;
#define DDM_DESCRIPTOR 0xFFFFFFFF #define DDM_DESCRIPTOR 0xFFFFFFFF
#define ENTIRE_DEVICE_DESCRIPTOR 0xFFFFFFFE #define ENTIRE_DEVICE_DESCRIPTOR 0xFFFFFFFE
typedef struct { typedef struct {
uint32_t fUDIFBlocksSignature; uint32_t fUDIFBlocksSignature;
uint32_t infoVersion; uint32_t infoVersion;
uint64_t firstSectorNumber; uint64_t firstSectorNumber;
uint64_t sectorCount; uint64_t sectorCount;
uint64_t dataStart; uint64_t dataStart;
uint32_t decompressBufferRequested; uint32_t decompressBufferRequested;
uint32_t blocksDescriptor; uint32_t blocksDescriptor;
uint32_t reserved1; uint32_t reserved1;
uint32_t reserved2; uint32_t reserved2;
uint32_t reserved3; uint32_t reserved3;
uint32_t reserved4; uint32_t reserved4;
uint32_t reserved5; uint32_t reserved5;
uint32_t reserved6; uint32_t reserved6;
UDIFChecksum checksum; UDIFChecksum checksum;
uint32_t blocksRunCount; uint32_t blocksRunCount;
BLKXRun runs[0]; BLKXRun runs[0];
} __attribute__((__packed__)) BLKXTable; } __attribute__((__packed__)) BLKXTable;
typedef struct { typedef struct {
uint32_t ddBlock; uint32_t ddBlock;
uint16_t ddSize; uint16_t ddSize;
uint16_t ddType; uint16_t ddType;
} __attribute__((__packed__)) DriverDescriptor; } __attribute__((__packed__)) DriverDescriptor;
typedef struct { typedef struct {
uint16_t pmSig; uint16_t pmSig;
uint16_t pmSigPad; uint16_t pmSigPad;
uint32_t pmMapBlkCnt; uint32_t pmMapBlkCnt;
uint32_t pmPyPartStart; uint32_t pmPyPartStart;
uint32_t pmPartBlkCnt; uint32_t pmPartBlkCnt;
unsigned char pmPartName[32]; unsigned char pmPartName[32];
unsigned char pmParType[32]; unsigned char pmParType[32];
uint32_t pmLgDataStart; uint32_t pmLgDataStart;
uint32_t pmDataCnt; uint32_t pmDataCnt;
uint32_t pmPartStatus; uint32_t pmPartStatus;
uint32_t pmLgBootStart; uint32_t pmLgBootStart;
uint32_t pmBootSize; uint32_t pmBootSize;
uint32_t pmBootAddr; uint32_t pmBootAddr;
uint32_t pmBootAddr2; uint32_t pmBootAddr2;
uint32_t pmBootEntry; uint32_t pmBootEntry;
uint32_t pmBootEntry2; uint32_t pmBootEntry2;
uint32_t pmBootCksum; uint32_t pmBootCksum;
unsigned char pmProcessor[16]; unsigned char pmProcessor[16];
uint32_t bootCode; uint32_t bootCode;
uint16_t pmPad[186]; uint16_t pmPad[186];
} __attribute__((__packed__)) Partition; } __attribute__((__packed__)) Partition;
typedef struct { typedef struct {
uint16_t sbSig; uint16_t sbSig;
uint16_t sbBlkSize; uint16_t sbBlkSize;
uint32_t sbBlkCount; uint32_t sbBlkCount;
uint16_t sbDevType; uint16_t sbDevType;
uint16_t sbDevId; uint16_t sbDevId;
uint32_t sbData; uint32_t sbData;
uint16_t sbDrvrCount; uint16_t sbDrvrCount;
uint32_t ddBlock; uint32_t ddBlock;
uint16_t ddSize; uint16_t ddSize;
uint16_t ddType; uint16_t ddType;
DriverDescriptor ddPad[0]; DriverDescriptor ddPad[0];
} __attribute__((__packed__)) DriverDescriptorRecord; } __attribute__((__packed__)) DriverDescriptorRecord;
typedef struct ResourceData { typedef struct ResourceData {
uint32_t attributes; uint32_t attributes;
unsigned char* data; unsigned char* data;
size_t dataLength; size_t dataLength;
int id; int id;
unsigned char* name; unsigned char* name;
struct ResourceData* next; struct ResourceData* next;
} ResourceData; } ResourceData;
typedef void (*FlipDataFunc)(unsigned char* data, char out); typedef void (*FlipDataFunc)(unsigned char* data, char out);
@ -222,16 +223,16 @@ typedef int (*SeekFunc)(void* token, off_t offset);
typedef off_t (*TellFunc)(void* token); typedef off_t (*TellFunc)(void* token);
typedef struct ResourceKey { typedef struct ResourceKey {
unsigned char* key; unsigned char* key;
ResourceData* data; ResourceData* data;
struct ResourceKey* next; struct ResourceKey* next;
FlipDataFunc flipData; FlipDataFunc flipData;
} ResourceKey; } ResourceKey;
typedef struct { typedef struct {
size_t offset; size_t offset;
unsigned char* buffer; unsigned char* buffer;
size_t bufferSize; size_t bufferSize;
} MemWrapperInfo; } MemWrapperInfo;
typedef struct { typedef struct {
@ -241,37 +242,37 @@ typedef struct {
} SHA1_CTX; } SHA1_CTX;
typedef struct { typedef struct {
uint32_t block; uint32_t block;
uint32_t crc; uint32_t crc;
SHA1_CTX sha1; SHA1_CTX sha1;
} ChecksumToken; } ChecksumToken;
static inline uint32_t readUInt32(FILE* file) { static inline uint32_t readUInt32(FILE* file) {
uint32_t data; uint32_t data;
ASSERT(fread(&data, sizeof(data), 1, file) == 1, "fread"); ASSERT(fread(&data, sizeof(data), 1, file) == 1, "fread");
FLIPENDIAN(data); FLIPENDIAN(data);
return data; return data;
} }
static inline void writeUInt32(FILE* file, uint32_t data) { static inline void writeUInt32(FILE* file, uint32_t data) {
FLIPENDIAN(data); FLIPENDIAN(data);
ASSERT(fwrite(&data, sizeof(data), 1, file) == 1, "fwrite"); ASSERT(fwrite(&data, sizeof(data), 1, file) == 1, "fwrite");
} }
static inline uint32_t readUInt64(FILE* file) { static inline uint32_t readUInt64(FILE* file) {
uint64_t data; uint64_t data;
ASSERT(fread(&data, sizeof(data), 1, file) == 1, "fread"); ASSERT(fread(&data, sizeof(data), 1, file) == 1, "fread");
FLIPENDIAN(data); FLIPENDIAN(data);
return data; return data;
} }
static inline void writeUInt64(FILE* file, uint64_t data) { static inline void writeUInt64(FILE* file, uint64_t data) {
FLIPENDIAN(data); FLIPENDIAN(data);
ASSERT(fwrite(&data, sizeof(data), 1, file) == 1, "fwrite"); ASSERT(fwrite(&data, sizeof(data), 1, file) == 1, "fwrite");
} }
unsigned char* decodeBase64(char* toDecode, size_t* dataLength); unsigned char* decodeBase64(char* toDecode, size_t* dataLength);
@ -343,8 +344,8 @@ off_t memTell(void* token);
void extractBLKX(FILE* in, void* out, BLKXTable* blkx, WriteFunc mWrite, SeekFunc mSeek, TellFunc mTell); void extractBLKX(FILE* in, void* out, BLKXTable* blkx, WriteFunc mWrite, SeekFunc mSeek, TellFunc mTell);
BLKXTable* insertBLKX(FILE* out, void* in, uint32_t firstSectorNumber, uint32_t numSectors, uint32_t blocksDescriptor, uint32_t checksumType, BLKXTable* insertBLKX(FILE* out, void* in, uint32_t firstSectorNumber, uint32_t numSectors, uint32_t blocksDescriptor, uint32_t checksumType,
ReadFunc mRead, SeekFunc mSeek, TellFunc mTell, ReadFunc mRead, SeekFunc mSeek, TellFunc mTell,
ChecksumFunc uncompressedChk, void* uncompressedChkToken, ChecksumFunc compressedChk, void* compressedChkToken, Volume* volume); ChecksumFunc uncompressedChk, void* uncompressedChkToken, ChecksumFunc compressedChk, void* compressedChkToken, Volume* volume);
int extractDmg(const char* source, const char* dest, int partNum); int extractDmg(const char* source, const char* dest, int partNum);
int buildDmg(const char* source, const char* dest); int buildDmg(const char* source, const char* dest);