in dmg/dmglib.c [91:292]
int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, unsigned int BlockSize, const char* sentinel, Compressor *comp, size_t runSectors) {
io_func* io;
Volume* volume;
HFSPlusVolumeHeader* volumeHeader;
DriverDescriptorRecord* DDM;
Partition* partitions;
ResourceKey* resources;
ResourceKey* curResource;
NSizResource* nsiz;
NSizResource* myNSiz;
CSumResource csum;
BLKXTable* blkx;
ChecksumToken uncompressedToken;
ChecksumToken dataForkToken;
UDIFResourceFile koly = {0};
off_t plistOffset;
uint32_t plistSize;
uint32_t dataForkChecksum;
io = IOFuncFromAbstractFile(abstractIn);
ASSERT(volume = openVolume(io), "parse HFS volume");
volumeHeader = volume->volumeHeader;
if(volumeHeader->signature != HFSX_SIGNATURE) {
printf("Warning: ASR data only reverse engineered for case-sensitive HFS+ volumes\n");fflush(stdout);
}
resources = NULL;
nsiz = NULL;
memset(&dataForkToken, 0, sizeof(ChecksumToken));
memset(koly.fUDIFMasterChecksum.data, 0, sizeof(koly.fUDIFMasterChecksum.data));
memset(koly.fUDIFDataForkChecksum.data, 0, sizeof(koly.fUDIFDataForkChecksum.data));
printf("Creating and writing DDM and partition map...\n"); fflush(stdout);
DDM = createDriverDescriptorMap((volumeHeader->totalBlocks * volumeHeader->blockSize)/SECTOR_SIZE, BlockSize);
partitions = createApplePartitionMap((volumeHeader->totalBlocks * volumeHeader->blockSize)/SECTOR_SIZE, HFSX_VOLUME_TYPE, BlockSize);
int pNum = writeDriverDescriptorMap(-1, abstractOut, DDM, BlockSize, &CRCProxy, (void*) (&dataForkToken), &resources, comp, runSectors);
free(DDM);
pNum = writeApplePartitionMap(pNum, abstractOut, partitions, BlockSize, &CRCProxy, (void*) (&dataForkToken), &resources, &nsiz, comp, runSectors);
free(partitions);
pNum = writeATAPI(pNum, abstractOut, BlockSize, &CRCProxy, (void*) (&dataForkToken), &resources, &nsiz, comp, runSectors);
memset(&uncompressedToken, 0, sizeof(uncompressedToken));
SHA1Init(&(uncompressedToken.sha1));
printf("Writing main data blkx...\n"); fflush(stdout);
abstractIn->seek(abstractIn, 0);
AbstractAttribution* attribution = NULL;
if (sentinel) {
attribution = createAbstractAttributionPreservingSentinel(sentinel);
}
if (attribution) {
attribution->beforeMainBlkx(attribution, abstractOut, &dataForkToken);
}
blkx = insertBLKX(abstractOut, abstractIn, USER_OFFSET, (volumeHeader->totalBlocks * volumeHeader->blockSize)/SECTOR_SIZE,
pNum, CHECKSUM_UDIF_CRC32, &BlockSHA1CRC, &uncompressedToken, &CRCProxy, &dataForkToken, volume, attribution, comp, runSectors);
AttributionResource attributionResource;
memset(&attributionResource, 0, sizeof(AttributionResource));
if (attribution) {
attribution->afterMainBlkx(attribution, abstractOut, &dataForkToken, &attributionResource);
}
blkx->checksum.data[0] = uncompressedToken.crc;
printf("Inserting main blkx...\n"); fflush(stdout);
char pName[100];
sprintf(pName, "Mac_OS_X (Apple_HFSX : %d)", pNum + 1);
resources = insertData(resources, "blkx", pNum, pName, 0, false, (const char*) blkx, sizeof(BLKXTable) + (blkx->blocksRunCount * sizeof(BLKXRun)), ATTRIBUTE_HDIUTIL);
free(blkx);
printf("Inserting cSum data...\n"); fflush(stdout);
csum.version = 1;
csum.type = CHECKSUM_MKBLOCK;
csum.checksum = uncompressedToken.block;
resources = insertData(resources, "cSum", 2, "", 0, false, (const char*) (&csum), sizeof(csum), 0);
printf("Inserting nsiz data\n"); fflush(stdout);
myNSiz = (NSizResource*) malloc(sizeof(NSizResource));
memset(myNSiz, 0, sizeof(NSizResource));
myNSiz->isVolume = TRUE;
myNSiz->blockChecksum2 = uncompressedToken.block;
myNSiz->partitionNumber = 2;
myNSiz->version = 6;
myNSiz->bytes = (volumeHeader->totalBlocks - volumeHeader->freeBlocks) * volumeHeader->blockSize;
myNSiz->modifyDate = volumeHeader->modifyDate;
myNSiz->volumeSignature = volumeHeader->signature;
myNSiz->sha1Digest = (unsigned char *)malloc(20);
SHA1Final(myNSiz->sha1Digest, &(uncompressedToken.sha1));
myNSiz->next = NULL;
if(nsiz == NULL) {
nsiz = myNSiz;
} else {
NSizResource* curNsiz = nsiz;
while(curNsiz->next != NULL)
{
curNsiz = curNsiz->next;
}
curNsiz->next = myNSiz;
}
pNum++;
printf("Writing free partition...\n"); fflush(stdout);
pNum = writeFreePartition(pNum, abstractOut, USER_OFFSET + (volumeHeader->totalBlocks * volumeHeader->blockSize)/SECTOR_SIZE,
(FREE_SIZE + (BlockSize / SECTOR_SIZE / 2)) / (BlockSize / SECTOR_SIZE) * (BlockSize / SECTOR_SIZE), &resources);
dataForkChecksum = dataForkToken.crc;
printf("Writing XML data...\n"); fflush(stdout);
curResource = resources;
while(curResource->next != NULL)
curResource = curResource->next;
curResource->next = writeNSiz(nsiz);
curResource = curResource->next;
releaseNSiz(nsiz);
curResource->next = makePlst((const char*) (&attributionResource), sizeof(attributionResource), true);
curResource = curResource->next;
curResource->next = makeSize(volumeHeader);
curResource = curResource->next;
plistOffset = abstractOut->tell(abstractOut);
writeResources(abstractOut, resources, true);
plistSize = abstractOut->tell(abstractOut) - plistOffset;
printf("Generating UDIF metadata...\n"); fflush(stdout);
koly.fUDIFSignature = KOLY_SIGNATURE;
koly.fUDIFVersion = 4;
koly.fUDIFHeaderSize = sizeof(koly);
koly.fUDIFFlags = kUDIFFlagsFlattened;
koly.fUDIFRunningDataForkOffset = 0;
koly.fUDIFDataForkOffset = 0;
koly.fUDIFDataForkLength = plistOffset;
koly.fUDIFRsrcForkOffset = 0;
koly.fUDIFRsrcForkLength = 0;
koly.fUDIFSegmentNumber = 1;
koly.fUDIFSegmentCount = 1;
koly.fUDIFSegmentID.data1 = rand();
koly.fUDIFSegmentID.data2 = rand();
koly.fUDIFSegmentID.data3 = rand();
koly.fUDIFSegmentID.data4 = rand();
koly.fUDIFDataForkChecksum.type = CHECKSUM_UDIF_CRC32;
koly.fUDIFDataForkChecksum.bitness = checksumBitness(CHECKSUM_UDIF_CRC32);
koly.fUDIFDataForkChecksum.data[0] = dataForkChecksum;
koly.fUDIFXMLOffset = plistOffset;
koly.fUDIFXMLLength = plistSize;
memset(&(koly.reserved1), 0, 0x78);
koly.fUDIFMasterChecksum.type = CHECKSUM_UDIF_CRC32;
koly.fUDIFMasterChecksum.bitness = checksumBitness(CHECKSUM_UDIF_CRC32);
koly.fUDIFMasterChecksum.data[0] = calculateMasterChecksum(resources);
printf("Master checksum: %x\n", koly.fUDIFMasterChecksum.data[0]); fflush(stdout);
koly.fUDIFImageVariant = kUDIFDeviceImageType;
koly.fUDIFSectorCount = (volumeHeader->totalBlocks * volumeHeader->blockSize)/SECTOR_SIZE
+ ((EXTRA_SIZE + (BlockSize / SECTOR_SIZE / 2)) / (BlockSize / SECTOR_SIZE) * (BlockSize / SECTOR_SIZE));
koly.reserved2 = 0;
koly.reserved3 = 0;
koly.reserved4 = 0;
printf("Writing out UDIF resource file...\n"); fflush(stdout);
writeUDIFResourceFile(abstractOut, &koly);
printf("Cleaning up...\n"); fflush(stdout);
releaseResources(resources);
abstractOut->close(abstractOut);
closeVolume(volume);
CLOSE(io);
printf("Done.\n"); fflush(stdout);
return TRUE;
}