Allow specifying sectors per run
This commit is contained in:
Родитель
a928dd4daa
Коммит
d1d652c56d
|
@ -5,10 +5,6 @@
|
|||
#include <bzlib.h>
|
||||
#include "dmg/adc.h"
|
||||
|
||||
// LZMA and LZFSE seem to need a larger decompression buffer for macOS to be happy. This value is empirically taken from
|
||||
// an LZMA dmg created on macOS 14 with hdiutil.
|
||||
#define MODERN_DECOMPRESS_BUFFER_REQUESTED 0x82F
|
||||
|
||||
#ifdef HAVE_LIBLZMA
|
||||
#include <lzma.h>
|
||||
|
||||
|
@ -75,28 +71,45 @@ static int zlibCompress(unsigned char *inBuffer, size_t inSize,
|
|||
return (compress2(outBuffer, compSize, inBuffer, inSize, level) != Z_OK);
|
||||
}
|
||||
|
||||
size_t oldDecompressBuffer(size_t runSectors)
|
||||
{
|
||||
// A reasonable heuristic
|
||||
// Bzip2 at level 1 usually needs the largest extra space, compared to other compressors.
|
||||
// Happens to equal 0x208 for 0x200 sectors, same as before.
|
||||
return runSectors + 4 + (runSectors >> 7);
|
||||
}
|
||||
|
||||
size_t modernDecompressBuffer(size_t runSectors)
|
||||
{
|
||||
// Modern algorithms need more space for some reason, about double the size of a run.
|
||||
// Sometimes it's a bit more, so add a generous amount of padding.
|
||||
// It's unclear why so much is needed, lzma/lzfse shouldn't need this much in normal usage!
|
||||
return runSectors * 2 + 64;
|
||||
}
|
||||
|
||||
int getCompressor(Compressor* comp, char *name)
|
||||
{
|
||||
if (name == NULL) {
|
||||
comp->level = -1;
|
||||
comp->minDecompressBufferRequested = 0;
|
||||
}
|
||||
|
||||
if (name == NULL || strcasecmp(name, "bzip2") == 0) {
|
||||
comp->block_type = BLOCK_BZIP2;
|
||||
comp->compress = bz2Compress;
|
||||
comp->decompressBuffer = oldDecompressBuffer;
|
||||
return 0;
|
||||
}
|
||||
if (strcasecmp(name, "zlib") == 0) {
|
||||
comp->block_type = BLOCK_ZLIB;
|
||||
comp->compress = zlibCompress;
|
||||
comp->decompressBuffer = oldDecompressBuffer;
|
||||
return 0;
|
||||
}
|
||||
#ifdef HAVE_LIBLZMA
|
||||
if (strcasecmp(name, "lzma") == 0) {
|
||||
comp->block_type = BLOCK_LZMA;
|
||||
comp->compress = lzmaCompress;
|
||||
comp->minDecompressBufferRequested = MODERN_DECOMPRESS_BUFFER_REQUESTED;
|
||||
comp->decompressBuffer = modernDecompressBuffer;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -104,7 +117,7 @@ int getCompressor(Compressor* comp, char *name)
|
|||
if (strcasecmp(name, "lzfse") == 0) {
|
||||
comp->block_type = BLOCK_LZFSE;
|
||||
comp->compress = lzfseCompress;
|
||||
comp->minDecompressBufferRequested = MODERN_DECOMPRESS_BUFFER_REQUESTED;
|
||||
comp->decompressBuffer = modernDecompressBuffer;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -158,3 +171,4 @@ int decompressRun(uint32_t type,
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
17
dmg/dmg.c
17
dmg/dmg.c
|
@ -38,6 +38,7 @@ void usage(const char *name) {
|
|||
printf("\t-k\tkey\n");
|
||||
printf("\t-J\tcompressor name (%s)\n", compressionNames());
|
||||
printf("\t-L\tcompression level\n");
|
||||
printf("\t-r\trun size (in sectors)\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
@ -93,11 +94,12 @@ int main(int argc, char* argv[]) {
|
|||
char *key = NULL;
|
||||
Compressor comp;
|
||||
int ret;
|
||||
int runSectors = DEFAULT_SECTORS_AT_A_TIME;
|
||||
|
||||
TestByteOrder();
|
||||
getCompressor(&comp, NULL);
|
||||
|
||||
while ((opt = mgetopt(argc, argv, "kJL")) != -1) {
|
||||
while ((opt = mgetopt(argc, argv, "kJLr")) != -1) {
|
||||
switch (opt) {
|
||||
case 'k':
|
||||
key = moptarg;
|
||||
|
@ -112,6 +114,13 @@ int main(int argc, char* argv[]) {
|
|||
case 'L':
|
||||
sscanf(moptarg, "%d", &comp.level);
|
||||
break;
|
||||
case 'r':
|
||||
sscanf(moptarg, "%d", &runSectors);
|
||||
if (runSectors < DEFAULT_SECTORS_AT_A_TIME) {
|
||||
fprintf(stderr, "Run size must be at least %d sectors\n", DEFAULT_SECTORS_AT_A_TIME);
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,15 +149,15 @@ int main(int argc, char* argv[]) {
|
|||
if (moptind < argc) {
|
||||
anchor = argv[moptind++];
|
||||
}
|
||||
buildDmg(in, out, SECTOR_SIZE, anchor, &comp);
|
||||
buildDmg(in, out, SECTOR_SIZE, anchor, &comp, runSectors);
|
||||
} else if(strcmp(cmd, "build2048") == 0) {
|
||||
buildDmg(in, out, 2048, NULL, &comp);
|
||||
buildDmg(in, out, 2048, NULL, &comp, runSectors);
|
||||
} else if(strcmp(cmd, "res") == 0) {
|
||||
outResources(in, out);
|
||||
} else if(strcmp(cmd, "iso") == 0) {
|
||||
convertToISO(in, out);
|
||||
} else if(strcmp(cmd, "dmg") == 0) {
|
||||
convertToDMG(in, out, &comp);
|
||||
convertToDMG(in, out, &comp, runSectors);
|
||||
} else if(strcmp(cmd, "attribute") == 0) {
|
||||
char *anchor, *data;
|
||||
if(argc < moptind + 2) {
|
||||
|
|
18
dmg/dmglib.c
18
dmg/dmglib.c
|
@ -88,7 +88,7 @@ uint32_t calculateMasterChecksum(ResourceKey* resources) {
|
|||
return result;
|
||||
}
|
||||
|
||||
int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, unsigned int BlockSize, const char* sentinel, Compressor *comp) {
|
||||
int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, unsigned int BlockSize, const char* sentinel, Compressor *comp, size_t runSectors) {
|
||||
io_func* io;
|
||||
Volume* volume;
|
||||
|
||||
|
@ -136,11 +136,11 @@ int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, unsigned int B
|
|||
|
||||
partitions = createApplePartitionMap((volumeHeader->totalBlocks * volumeHeader->blockSize)/SECTOR_SIZE, HFSX_VOLUME_TYPE, BlockSize);
|
||||
|
||||
int pNum = writeDriverDescriptorMap(-1, abstractOut, DDM, BlockSize, &CRCProxy, (void*) (&dataForkToken), &resources, comp);
|
||||
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);
|
||||
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);
|
||||
pNum = writeATAPI(pNum, abstractOut, BlockSize, &CRCProxy, (void*) (&dataForkToken), &resources, &nsiz, comp, runSectors);
|
||||
|
||||
memset(&uncompressedToken, 0, sizeof(uncompressedToken));
|
||||
SHA1Init(&(uncompressedToken.sha1));
|
||||
|
@ -159,7 +159,7 @@ int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, unsigned int B
|
|||
}
|
||||
|
||||
blkx = insertBLKX(abstractOut, abstractIn, USER_OFFSET, (volumeHeader->totalBlocks * volumeHeader->blockSize)/SECTOR_SIZE,
|
||||
pNum, CHECKSUM_UDIF_CRC32, &BlockSHA1CRC, &uncompressedToken, &CRCProxy, &dataForkToken, volume, attribution, comp);
|
||||
pNum, CHECKSUM_UDIF_CRC32, &BlockSHA1CRC, &uncompressedToken, &CRCProxy, &dataForkToken, volume, attribution, comp, runSectors);
|
||||
|
||||
AttributionResource attributionResource;
|
||||
memset(&attributionResource, 0, sizeof(AttributionResource));
|
||||
|
@ -291,7 +291,7 @@ int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, unsigned int B
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut, Compressor *comp) {
|
||||
int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut, Compressor *comp, size_t runSectors) {
|
||||
Partition* partitions;
|
||||
DriverDescriptorRecord* DDM;
|
||||
int i;
|
||||
|
@ -340,7 +340,7 @@ int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut, Compressor
|
|||
|
||||
if(DDM->sbSig == DRIVER_DESCRIPTOR_SIGNATURE) {
|
||||
BlockSize = DDM->sbBlkSize;
|
||||
int pNum = writeDriverDescriptorMap(-1, abstractOut, DDM, BlockSize, &CRCProxy, (void*) (&dataForkToken), &resources, comp);
|
||||
int pNum = writeDriverDescriptorMap(-1, abstractOut, DDM, BlockSize, &CRCProxy, (void*) (&dataForkToken), &resources, comp, runSectors);
|
||||
free(DDM);
|
||||
|
||||
printf("Processing partition map...\n"); fflush(stdout);
|
||||
|
@ -371,7 +371,7 @@ int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut, Compressor
|
|||
|
||||
abstractIn->seek(abstractIn, partitions[i].pmPyPartStart * BlockSize);
|
||||
blkx = insertBLKX(abstractOut, abstractIn, partitions[i].pmPyPartStart, partitions[i].pmPartBlkCnt, i, CHECKSUM_UDIF_CRC32,
|
||||
&BlockCRC, &uncompressedToken, &CRCProxy, &dataForkToken, NULL, NULL, comp);
|
||||
&BlockCRC, &uncompressedToken, &CRCProxy, &dataForkToken, NULL, NULL, comp, runSectors);
|
||||
|
||||
blkx->checksum.data[0] = uncompressedToken.crc;
|
||||
resources = insertData(resources, "blkx", i, partitionName, 0, false, (const char*) blkx, sizeof(BLKXTable) + (blkx->blocksRunCount * sizeof(BLKXRun)), ATTRIBUTE_HDIUTIL);
|
||||
|
@ -412,7 +412,7 @@ int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut, Compressor
|
|||
|
||||
abstractIn->seek(abstractIn, 0);
|
||||
blkx = insertBLKX(abstractOut, abstractIn, 0, fileLength/SECTOR_SIZE, ENTIRE_DEVICE_DESCRIPTOR, CHECKSUM_UDIF_CRC32,
|
||||
&BlockCRC, &uncompressedToken, &CRCProxy, &dataForkToken, NULL, NULL, comp);
|
||||
&BlockCRC, &uncompressedToken, &CRCProxy, &dataForkToken, NULL, NULL, comp, runSectors);
|
||||
blkx->checksum.data[0] = uncompressedToken.crc;
|
||||
resources = insertData(resources, "blkx", 0, "whole disk (unknown partition : 0)", 0, false, (const char*) blkx, sizeof(BLKXTable) + (blkx->blocksRunCount * sizeof(BLKXRun)), ATTRIBUTE_HDIUTIL);
|
||||
free(blkx);
|
||||
|
|
31
dmg/io.c
31
dmg/io.c
|
@ -9,23 +9,6 @@
|
|||
#include <dmg/attribution.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
// Okay, this value sucks. You shouldn't touch it because it affects how many ignore sections get added to the blkx list
|
||||
// If the blkx list gets too fragmented with ignore sections, then the copy list in certain versions of the iPhone's
|
||||
// asr becomes too big. Due to Apple's BUGGY CODE, this causes asr to segfault! This is because the copy list becomes
|
||||
// too large for the initial buffer allocated, and realloc is called by asr. Unfortunately, after the realloc, the initial
|
||||
// pointer is still used by asr for a little while! Frakking noob mistake.
|
||||
|
||||
// The only reason why it works at all is their really idiotic algorithm to determine where to put ignore blocks. It's
|
||||
// certainly nothing reasonable like "put in an ignore block if you encounter more than X blank sectors" (like mine)
|
||||
// There's always a large-ish one at the end, and a tiny 2 sector one at the end too, to take care of the space after
|
||||
// the backup volume header. No frakking clue how they go about determining how to do that.
|
||||
|
||||
#define SECTORS_AT_A_TIME 0x200
|
||||
|
||||
// The base decompression buffer requested, if nothing else is specified.
|
||||
|
||||
#define DECOMPRESS_BUFFER_REQUESTED 0x208
|
||||
|
||||
typedef struct block {
|
||||
size_t bufferSize;
|
||||
|
||||
|
@ -43,6 +26,7 @@ typedef struct block {
|
|||
} block;
|
||||
|
||||
typedef struct {
|
||||
size_t runSectors;
|
||||
size_t bufferSize;
|
||||
AbstractAttribution* attribution;
|
||||
|
||||
|
@ -103,7 +87,7 @@ static block* blockRead(threadData* d) {
|
|||
block* b = blockAlloc(d->bufferSize, d->curRun);
|
||||
|
||||
b->run.sectorStart = d->curSector;
|
||||
b->run.sectorCount = (d->numSectors > SECTORS_AT_A_TIME) ? SECTORS_AT_A_TIME : d->numSectors;
|
||||
b->run.sectorCount = (d->numSectors > d->runSectors) ? d->runSectors : d->numSectors;
|
||||
size_t readSize = b->run.sectorCount * SECTOR_SIZE;
|
||||
|
||||
if (b->idx == 0) {
|
||||
|
@ -229,10 +213,11 @@ static void *threadWorker(void* arg) {
|
|||
|
||||
BLKXTable* insertBLKX(AbstractFile* out_, AbstractFile* in_, uint32_t firstSectorNumber, uint32_t numSectors_, uint32_t blocksDescriptor,
|
||||
uint32_t checksumType, ChecksumFunc uncompressedChk_, void* uncompressedChkToken_, ChecksumFunc compressedChk_,
|
||||
void* compressedChkToken_, Volume* volume, AbstractAttribution* attribution_, Compressor* comp) {
|
||||
void* compressedChkToken_, Volume* volume, AbstractAttribution* attribution_, Compressor* comp, size_t runSectors) {
|
||||
threadData td = {
|
||||
.out = out_,
|
||||
.in = in_,
|
||||
.runSectors = runSectors,
|
||||
.numSectors = numSectors_,
|
||||
.uncompressedChk = uncompressedChk_,
|
||||
.uncompressedChkToken = uncompressedChkToken_,
|
||||
|
@ -256,10 +241,12 @@ BLKXTable* insertBLKX(AbstractFile* out_, AbstractFile* in_, uint32_t firstSecto
|
|||
td.blkx->firstSectorNumber = firstSectorNumber;
|
||||
td.blkx->sectorCount = td.numSectors;
|
||||
td.blkx->dataStart = 0;
|
||||
td.blkx->decompressBufferRequested = DECOMPRESS_BUFFER_REQUESTED;
|
||||
if (comp->minDecompressBufferRequested > td.blkx->decompressBufferRequested) {
|
||||
td.blkx->decompressBufferRequested = comp->minDecompressBufferRequested;
|
||||
|
||||
td.blkx->decompressBufferRequested = comp->decompressBuffer(runSectors);
|
||||
if (MIN_DECOMPRESS_BUFFER_SECTORS > td.blkx->decompressBufferRequested) {
|
||||
td.blkx->decompressBufferRequested = MIN_DECOMPRESS_BUFFER_SECTORS;
|
||||
}
|
||||
|
||||
td.blkx->blocksDescriptor = blocksDescriptor;
|
||||
td.blkx->reserved1 = 0;
|
||||
td.blkx->reserved2 = 0;
|
||||
|
|
|
@ -499,7 +499,7 @@ DriverDescriptorRecord* createDriverDescriptorMap(uint32_t numSectors, unsigned
|
|||
}
|
||||
|
||||
int writeDriverDescriptorMap(int pNum, AbstractFile* file, DriverDescriptorRecord* DDM, unsigned int BlockSize, ChecksumFunc dataForkChecksum, void* dataForkToken,
|
||||
ResourceKey **resources, Compressor *comp) {
|
||||
ResourceKey **resources, Compressor *comp, size_t runSectors) {
|
||||
AbstractFile* bufferFile;
|
||||
BLKXTable* blkx;
|
||||
ChecksumToken uncompressedToken;
|
||||
|
@ -514,7 +514,7 @@ int writeDriverDescriptorMap(int pNum, AbstractFile* file, DriverDescriptorRecor
|
|||
bufferFile = createAbstractFileFromMemory((void**)&buffer, DDM_SIZE * BlockSize);
|
||||
|
||||
blkx = insertBLKX(file, bufferFile, DDM_OFFSET, DDM_SIZE, DDM_DESCRIPTOR, CHECKSUM_UDIF_CRC32, &CRCProxy, &uncompressedToken,
|
||||
dataForkChecksum, dataForkToken, NULL, NULL, comp);
|
||||
dataForkChecksum, dataForkToken, NULL, NULL, comp, runSectors);
|
||||
|
||||
blkx->checksum.data[0] = uncompressedToken.crc;
|
||||
|
||||
|
@ -534,7 +534,8 @@ int writeDriverDescriptorMap(int pNum, AbstractFile* file, DriverDescriptorRecor
|
|||
return pNum;
|
||||
}
|
||||
|
||||
int writeApplePartitionMap(int pNum, AbstractFile* file, Partition* partitions, unsigned int BlockSize, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn, Compressor *comp) {
|
||||
int writeApplePartitionMap(int pNum, AbstractFile* file, Partition* partitions, unsigned int BlockSize, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn,
|
||||
Compressor *comp, size_t runSectors) {
|
||||
AbstractFile* bufferFile;
|
||||
BLKXTable* blkx;
|
||||
ChecksumToken uncompressedToken;
|
||||
|
@ -552,7 +553,7 @@ int writeApplePartitionMap(int pNum, AbstractFile* file, Partition* partitions,
|
|||
bufferFile = createAbstractFileFromMemory((void**)&buffer, realPartitionSize);
|
||||
|
||||
blkx = insertBLKX(file, bufferFile, PARTITION_OFFSET * BlockSize / SECTOR_SIZE, realPartitionSize / SECTOR_SIZE, pNum, CHECKSUM_UDIF_CRC32,
|
||||
&BlockCRC, &uncompressedToken, dataForkChecksum, dataForkToken, NULL, NULL, comp);
|
||||
&BlockCRC, &uncompressedToken, dataForkChecksum, dataForkToken, NULL, NULL, comp, runSectors);
|
||||
|
||||
bufferFile->close(bufferFile);
|
||||
|
||||
|
@ -588,7 +589,8 @@ int writeApplePartitionMap(int pNum, AbstractFile* file, Partition* partitions,
|
|||
return pNum + 1;
|
||||
}
|
||||
|
||||
int writeATAPI(int pNum, AbstractFile* file, unsigned int BlockSize, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn, Compressor *comp) {
|
||||
int writeATAPI(int pNum, AbstractFile* file, unsigned int BlockSize, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn,
|
||||
Compressor *comp, size_t runSectors) {
|
||||
AbstractFile* bufferFile;
|
||||
BLKXTable* blkx;
|
||||
ChecksumToken uncompressedToken;
|
||||
|
@ -606,12 +608,12 @@ int writeATAPI(int pNum, AbstractFile* file, unsigned int BlockSize, ChecksumFun
|
|||
if(BlockSize != SECTOR_SIZE)
|
||||
{
|
||||
blkx = insertBLKX(file, bufferFile, ATAPI_OFFSET, BlockSize / SECTOR_SIZE, pNum, CHECKSUM_UDIF_CRC32,
|
||||
&BlockCRC, &uncompressedToken, dataForkChecksum, dataForkToken, NULL, NULL, comp);
|
||||
&BlockCRC, &uncompressedToken, dataForkChecksum, dataForkToken, NULL, NULL, comp, runSectors);
|
||||
}
|
||||
else
|
||||
{
|
||||
blkx = insertBLKX(file, bufferFile, ATAPI_OFFSET, ATAPI_SIZE, pNum, CHECKSUM_UDIF_CRC32,
|
||||
&BlockCRC, &uncompressedToken, dataForkChecksum, dataForkToken, NULL, NULL, comp);
|
||||
&BlockCRC, &uncompressedToken, dataForkChecksum, dataForkToken, NULL, NULL, comp, runSectors);
|
||||
}
|
||||
|
||||
bufferFile->close(bufferFile);
|
||||
|
|
|
@ -7,16 +7,20 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MIN_DECOMPRESS_BUFFER_SECTORS 0x208
|
||||
|
||||
// Return zero on success
|
||||
typedef int (*CompressFunc)(unsigned char *inBuffer, size_t inSize,
|
||||
unsigned char *outBuffer, size_t outBufSize, size_t *compSize,
|
||||
int level);
|
||||
|
||||
typedef size_t (*DecompressBufferFunc)(size_t runSectors);
|
||||
|
||||
typedef struct {
|
||||
CompressFunc compress;
|
||||
DecompressBufferFunc decompressBuffer;
|
||||
int level;
|
||||
uint32_t block_type;
|
||||
uint32_t minDecompressBufferRequested;
|
||||
} Compressor;
|
||||
|
||||
// Pass NULL name to get the default. Return zero on success
|
||||
|
|
|
@ -11,6 +11,19 @@
|
|||
#include "common.h"
|
||||
#include "compress.h"
|
||||
|
||||
// Okay, this value sucks. You shouldn't touch it because it affects how many ignore sections get added to the blkx list
|
||||
// If the blkx list gets too fragmented with ignore sections, then the copy list in certain versions of the iPhone's
|
||||
// asr becomes too big. Due to Apple's BUGGY CODE, this causes asr to segfault! This is because the copy list becomes
|
||||
// too large for the initial buffer allocated, and realloc is called by asr. Unfortunately, after the realloc, the initial
|
||||
// pointer is still used by asr for a little while! Frakking noob mistake.
|
||||
|
||||
// The only reason why it works at all is their really idiotic algorithm to determine where to put ignore blocks. It's
|
||||
// certainly nothing reasonable like "put in an ignore block if you encounter more than X blank sectors" (like mine)
|
||||
// There's always a large-ish one at the end, and a tiny 2 sector one at the end too, to take care of the space after
|
||||
// the backup volume header. No frakking clue how they go about determining how to do that.
|
||||
|
||||
#define DEFAULT_SECTORS_AT_A_TIME 0x200
|
||||
|
||||
#define CHECKSUM_UDIF_CRC32 0x00000002
|
||||
#define CHECKSUM_MD5 0x00000004
|
||||
#define CHECKSUM_MKBLOCK 0x0002
|
||||
|
@ -321,23 +334,26 @@ extern "C" {
|
|||
|
||||
void readDriverDescriptorMap(AbstractFile* file, ResourceKey* resources);
|
||||
DriverDescriptorRecord* createDriverDescriptorMap(uint32_t numSectors, unsigned int BlockSize);
|
||||
int writeDriverDescriptorMap(int pNum, AbstractFile* file, DriverDescriptorRecord* DDM, unsigned int BlockSize, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, Compressor *comp);
|
||||
int writeDriverDescriptorMap(int pNum, AbstractFile* file, DriverDescriptorRecord* DDM, unsigned int BlockSize, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources,
|
||||
Compressor *comp, size_t runSectors);
|
||||
void readApplePartitionMap(AbstractFile* file, ResourceKey* resources, unsigned int BlockSize);
|
||||
Partition* createApplePartitionMap(uint32_t numSectors, const char* volumeType, unsigned int BlockSize);
|
||||
int writeApplePartitionMap(int pNum, AbstractFile* file, Partition* partitions, unsigned int BlockSize, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn, Compressor *comp);
|
||||
int writeATAPI(int pNum, AbstractFile* file, unsigned int BlockSize, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn, Compressor *comp);
|
||||
int writeApplePartitionMap(int pNum, AbstractFile* file, Partition* partitions, unsigned int BlockSize, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn,
|
||||
Compressor *comp, size_t runSectors);
|
||||
int writeATAPI(int pNum, AbstractFile* file, unsigned int BlockSize, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn,
|
||||
Compressor *comp, size_t runSectors);
|
||||
int writeFreePartition(int pNum, AbstractFile* outFile, uint32_t offset, uint32_t numSectors, ResourceKey** resources);
|
||||
|
||||
void extractBLKX(AbstractFile* in, AbstractFile* out, BLKXTable* blkx);
|
||||
BLKXTable* insertBLKX(AbstractFile* out, AbstractFile* in, uint32_t firstSectorNumber, uint32_t numSectors, uint32_t blocksDescriptor,
|
||||
uint32_t checksumType, ChecksumFunc uncompressedChk, void* uncompressedChkToken, ChecksumFunc compressedChk,
|
||||
void* compressedChkToken, Volume* volume, AbstractAttribution* attribution, Compressor* comp);
|
||||
void* compressedChkToken, Volume* volume, AbstractAttribution* attribution, Compressor* comp, size_t runSectors);
|
||||
|
||||
|
||||
int extractDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, int partNum);
|
||||
int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, unsigned int BlockSize, const char* sentinel, Compressor *comp);
|
||||
int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, unsigned int BlockSize, const char* sentinel, Compressor *comp, size_t runSectors);
|
||||
int convertToISO(AbstractFile* abstractIn, AbstractFile* abstractOut);
|
||||
int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut, Compressor* comp);
|
||||
int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut, Compressor* comp, size_t runSectors);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -3,14 +3,15 @@
|
|||
|
||||
#include <dmg/dmg.h>
|
||||
#include "abstractfile.h"
|
||||
#include "compress.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int extractDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, int partNum);
|
||||
int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, unsigned int BlockSize);
|
||||
int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, unsigned int BlockSize, Compressor *comp, size_t runSectors);
|
||||
|
||||
int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut);
|
||||
int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut, Compressor *comp, size_t runSectors);
|
||||
int convertToISO(AbstractFile* abstractIn, AbstractFile* abstractOut);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче