diff --git a/dmg/Makefile b/dmg/Makefile index e0f96c1..0167cdf 100644 --- a/dmg/Makefile +++ b/dmg/Makefile @@ -1,27 +1,27 @@ -DMGOBJS=dmg.o base64.o resources.o checksum.o udif.o partition.o io.o filevault.o dmgfile.o dmglib.o zlib-1.2.3/libz.a openssl-0.9.8g/libcrypto.a -HFSOBJS=../hfs/volume.o ../hfs/btree.o ../hfs/extents.o ../hfs/rawfile.o ../hfs/catalog.o ../hfs/flatfile.o ../hfs/utility.o ../hfs/fastunicodecompare.o ../hfs/abstractfile.o -CFLAGS=-D_FILE_OFFSET_BITS=64 -DHAVE_CRYPT -LIBRARIES=`if $(CC) win32test.c -o /dev/null 2>/dev/null ; then echo ""; else echo "-lgdi32"; fi` - -all: dmg - -dmg: $(DMGOBJS) $(HFSOBJS) - $(CC) $(CFLAGS) $(DMGOBJS) $(HFSOBJS) $(LIBRARIES) -o dmg - -%.o: %.c dmg.h filevault.h dmgfile.h - $(CC) $(CFLAGS) -Izlib-1.2.3 -Iopenssl-0.9.8g/include -c $< -o $@ - -zlib-1.2.3/Makefile: - cd zlib-1.2.3; ./configure - -zlib-1.2.3/libz.a: zlib-1.2.3/Makefile - cd zlib-1.2.3; make - +DMGOBJS=dmg.o base64.o resources.o checksum.o udif.o partition.o io.o filevault.o dmgfile.o dmglib.o zlib-1.2.3/libz.a openssl-0.9.8g/libcrypto.a +HFSOBJS=../hfs/volume.o ../hfs/btree.o ../hfs/extents.o ../hfs/rawfile.o ../hfs/catalog.o ../hfs/flatfile.o ../hfs/utility.o ../hfs/fastunicodecompare.o ../hfs/abstractfile.o +CFLAGS=-D_FILE_OFFSET_BITS=64 -DHAVE_CRYPT +LIBRARIES=`if $(CC) win32test.c -o /dev/null 2>/dev/null ; then echo ""; else echo "-lgdi32"; fi` + +all: dmg + +dmg: $(DMGOBJS) $(HFSOBJS) + $(CC) $(CFLAGS) $(DMGOBJS) $(HFSOBJS) $(LIBRARIES) -o dmg + +%.o: %.c dmg.h filevault.h dmgfile.h + $(CC) $(CFLAGS) -Izlib-1.2.3 -Iopenssl-0.9.8g/include -c $< -o $@ + +zlib-1.2.3/Makefile: + cd zlib-1.2.3; ./configure + +zlib-1.2.3/libz.a: zlib-1.2.3/Makefile + cd zlib-1.2.3; make + openssl-0.9.8g/libcrypto.a: - touch openssl-0.9.8g/Makefile - cd openssl-0.9.8g/crypto; make - -clean: - -rm *.o - -rm dmg - -rm dmg.exe + touch openssl-0.9.8g/Makefile + cd openssl-0.9.8g/crypto; make + +clean: + -rm *.o + -rm dmg + -rm dmg.exe diff --git a/dmg/base64.c b/dmg/base64.c index 55d57fb..bad7709 100644 --- a/dmg/base64.c +++ b/dmg/base64.c @@ -1,183 +1,183 @@ -#include -#include -#include -#include - -#include "dmg.h" - -unsigned char* decodeBase64(char* toDecode, size_t* dataLength) { - uint8_t buffer[4]; - uint8_t charsInBuffer; - unsigned char* curChar; - unsigned char* decodeBuffer; - unsigned int decodeLoc; - unsigned int decodeBufferSize; - uint8_t bytesToDrop; - - curChar = (unsigned char*) toDecode; - charsInBuffer = 0; - - decodeBufferSize = 100; - decodeLoc = 0; - decodeBuffer = (unsigned char*) malloc(decodeBufferSize); - - bytesToDrop = 0; - - while((*curChar) != '\0') { - if((*curChar) >= 'A' && (*curChar) <= 'Z') { - buffer[charsInBuffer] = (*curChar) - 'A'; - charsInBuffer++; - } - - if((*curChar) >= 'a' && (*curChar) <= 'z') { - buffer[charsInBuffer] = ((*curChar) - 'a') + ('Z' - 'A' + 1); - charsInBuffer++; - } - - if((*curChar) >= '0' && (*curChar) <= '9') { - buffer[charsInBuffer] = ((*curChar) - '0') + ('Z' - 'A' + 1) + ('z' - 'a' + 1); - charsInBuffer++; - } - - if((*curChar) == '+') { - buffer[charsInBuffer] = ('Z' - 'A' + 1) + ('z' - 'a' + 1) + ('9' - '0' + 1); - charsInBuffer++; - } - - if((*curChar) == '/') { - buffer[charsInBuffer] = ('Z' - 'A' + 1) + ('z' - 'a' + 1) + ('9' - '0' + 1) + 1; - charsInBuffer++; - } - - if((*curChar) == '=') { - bytesToDrop++; - } - - if(charsInBuffer == 4) { - charsInBuffer = 0; - - if((decodeLoc + 3) >= decodeBufferSize) { - decodeBufferSize <<= 1; - decodeBuffer = (unsigned char*) realloc(decodeBuffer, decodeBufferSize); - } - decodeBuffer[decodeLoc] = ((buffer[0] << 2) & 0xFC) + ((buffer[1] >> 4) & 0x3F); - decodeBuffer[decodeLoc + 1] = ((buffer[1] << 4) & 0xF0) + ((buffer[2] >> 2) & 0x0F); - decodeBuffer[decodeLoc + 2] = ((buffer[2] << 6) & 0xC0) + (buffer[3] & 0x3F); - - decodeLoc += 3; - buffer[0] = 0; - buffer[1] = 0; - buffer[2] = 0; - buffer[3] = 0; - } - - curChar++; - } - - if(bytesToDrop != 0) { - if((decodeLoc + 3) >= decodeBufferSize) { - decodeBufferSize <<= 1; - decodeBuffer = (unsigned char*) realloc(decodeBuffer, decodeBufferSize); - } - - decodeBuffer[decodeLoc] = ((buffer[0] << 2) & 0xFC) | ((buffer[1] >> 4) & 0x3F); - - if(bytesToDrop <= 2) - decodeBuffer[decodeLoc + 1] = ((buffer[1] << 4) & 0xF0) | ((buffer[2] >> 2) & 0x0F); - - if(bytesToDrop <= 1) - decodeBuffer[decodeLoc + 2] = ((buffer[2] << 6) & 0xC0) | (buffer[3] & 0x3F); - - *dataLength = decodeLoc + 3 - bytesToDrop; - } else { - *dataLength = decodeLoc; - } - - return decodeBuffer; -} - -void writeBase64(AbstractFile* file, unsigned char* data, size_t dataLength, int tabLength, int width) { - char* buffer; - buffer = convertBase64(data, dataLength, tabLength, width); - file->write(file, buffer, strlen(buffer)); - free(buffer); -} - -#define CHECK_BUFFER_SIZE() \ - if(pos == bufferSize) { \ - bufferSize <<= 1; \ - buffer = (unsigned char*) realloc(buffer, bufferSize); \ - } - -#define CHECK_LINE_END_STRING() \ - CHECK_BUFFER_SIZE() \ - if(width == lineLength) { \ - buffer[pos++] = '\n'; \ - CHECK_BUFFER_SIZE() \ - for(j = 0; j < tabLength; j++) { \ - buffer[pos++] = '\t'; \ - CHECK_BUFFER_SIZE() \ - } \ - lineLength = 0; \ - } else { \ - lineLength++; \ - } - -char* convertBase64(unsigned char* data, size_t dataLength, int tabLength, int width) { - const char* dictionary = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - unsigned char* buffer; - size_t pos; - size_t bufferSize; - int i, j; - int lineLength; - - bufferSize = 100; - buffer = (unsigned char*) malloc(bufferSize); - pos = 0; - lineLength = 0; - - for(i = 0; i < tabLength; i++) { - CHECK_BUFFER_SIZE() - buffer[pos++] = '\t'; - } - i = 0; +#include +#include +#include +#include + +#include "dmg.h" + +unsigned char* decodeBase64(char* toDecode, size_t* dataLength) { + uint8_t buffer[4]; + uint8_t charsInBuffer; + unsigned char* curChar; + unsigned char* decodeBuffer; + unsigned int decodeLoc; + unsigned int decodeBufferSize; + uint8_t bytesToDrop; + + curChar = (unsigned char*) toDecode; + charsInBuffer = 0; + + decodeBufferSize = 100; + decodeLoc = 0; + decodeBuffer = (unsigned char*) malloc(decodeBufferSize); + + bytesToDrop = 0; + + while((*curChar) != '\0') { + if((*curChar) >= 'A' && (*curChar) <= 'Z') { + buffer[charsInBuffer] = (*curChar) - 'A'; + charsInBuffer++; + } + + if((*curChar) >= 'a' && (*curChar) <= 'z') { + buffer[charsInBuffer] = ((*curChar) - 'a') + ('Z' - 'A' + 1); + charsInBuffer++; + } + + if((*curChar) >= '0' && (*curChar) <= '9') { + buffer[charsInBuffer] = ((*curChar) - '0') + ('Z' - 'A' + 1) + ('z' - 'a' + 1); + charsInBuffer++; + } + + if((*curChar) == '+') { + buffer[charsInBuffer] = ('Z' - 'A' + 1) + ('z' - 'a' + 1) + ('9' - '0' + 1); + charsInBuffer++; + } + + if((*curChar) == '/') { + buffer[charsInBuffer] = ('Z' - 'A' + 1) + ('z' - 'a' + 1) + ('9' - '0' + 1) + 1; + charsInBuffer++; + } + + if((*curChar) == '=') { + bytesToDrop++; + } + + if(charsInBuffer == 4) { + charsInBuffer = 0; + + if((decodeLoc + 3) >= decodeBufferSize) { + decodeBufferSize <<= 1; + decodeBuffer = (unsigned char*) realloc(decodeBuffer, decodeBufferSize); + } + decodeBuffer[decodeLoc] = ((buffer[0] << 2) & 0xFC) + ((buffer[1] >> 4) & 0x3F); + decodeBuffer[decodeLoc + 1] = ((buffer[1] << 4) & 0xF0) + ((buffer[2] >> 2) & 0x0F); + decodeBuffer[decodeLoc + 2] = ((buffer[2] << 6) & 0xC0) + (buffer[3] & 0x3F); + + decodeLoc += 3; + buffer[0] = 0; + buffer[1] = 0; + buffer[2] = 0; + buffer[3] = 0; + } + + curChar++; + } + + if(bytesToDrop != 0) { + if((decodeLoc + 3) >= decodeBufferSize) { + decodeBufferSize <<= 1; + decodeBuffer = (unsigned char*) realloc(decodeBuffer, decodeBufferSize); + } + + decodeBuffer[decodeLoc] = ((buffer[0] << 2) & 0xFC) | ((buffer[1] >> 4) & 0x3F); + + if(bytesToDrop <= 2) + decodeBuffer[decodeLoc + 1] = ((buffer[1] << 4) & 0xF0) | ((buffer[2] >> 2) & 0x0F); + + if(bytesToDrop <= 1) + decodeBuffer[decodeLoc + 2] = ((buffer[2] << 6) & 0xC0) | (buffer[3] & 0x3F); + + *dataLength = decodeLoc + 3 - bytesToDrop; + } else { + *dataLength = decodeLoc; + } + + return decodeBuffer; +} + +void writeBase64(AbstractFile* file, unsigned char* data, size_t dataLength, int tabLength, int width) { + char* buffer; + buffer = convertBase64(data, dataLength, tabLength, width); + file->write(file, buffer, strlen(buffer)); + free(buffer); +} + +#define CHECK_BUFFER_SIZE() \ + if(pos == bufferSize) { \ + bufferSize <<= 1; \ + buffer = (unsigned char*) realloc(buffer, bufferSize); \ + } + +#define CHECK_LINE_END_STRING() \ + CHECK_BUFFER_SIZE() \ + if(width == lineLength) { \ + buffer[pos++] = '\n'; \ + CHECK_BUFFER_SIZE() \ + for(j = 0; j < tabLength; j++) { \ + buffer[pos++] = '\t'; \ + CHECK_BUFFER_SIZE() \ + } \ + lineLength = 0; \ + } else { \ + lineLength++; \ + } + +char* convertBase64(unsigned char* data, size_t dataLength, int tabLength, int width) { + const char* dictionary = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + unsigned char* buffer; + size_t pos; + size_t bufferSize; + int i, j; + int lineLength; + + bufferSize = 100; + buffer = (unsigned char*) malloc(bufferSize); + pos = 0; + lineLength = 0; + + for(i = 0; i < tabLength; i++) { + CHECK_BUFFER_SIZE() + buffer[pos++] = '\t'; + } + i = 0; while(dataLength >= 3) { - dataLength -= 3; - buffer[pos++] = dictionary[(data[i] >> 2) & 0x3F]; - CHECK_LINE_END_STRING(); - buffer[pos++] = dictionary[(((data[i] << 4) & 0x30) | ((data[i+1] >> 4) & 0x0F)) & 0x3F]; - CHECK_LINE_END_STRING(); - buffer[pos++] = dictionary[(((data[i+1] << 2) & 0x3C) | ((data[i+2] >> 6) & 0x03)) & 0x03F]; - CHECK_LINE_END_STRING(); - buffer[pos++] = dictionary[data[i+2] & 0x3F]; - CHECK_LINE_END_STRING(); - i += 3; - } - - if(dataLength == 2) { - buffer[pos++] = dictionary[(data[i] >> 2) & 0x3F]; - CHECK_LINE_END_STRING(); - buffer[pos++] = dictionary[(((data[i] << 4) & 0x30) | ((data[i+1] >> 4) & 0x0F)) & 0x3F]; - CHECK_LINE_END_STRING(); - buffer[pos++] = dictionary[(data[i+1] << 2) & 0x3C]; - CHECK_LINE_END_STRING(); - buffer[pos++] = '='; - } else if(dataLength == 1) { - buffer[pos++] = dictionary[(data[i] >> 2) & 0x3F]; - CHECK_LINE_END_STRING(); - buffer[pos++] = dictionary[(data[i] << 4) & 0x30]; - CHECK_LINE_END_STRING(); - buffer[pos++] = '='; - CHECK_LINE_END_STRING(); - buffer[pos++] = '='; - } - - CHECK_BUFFER_SIZE(); - buffer[pos++] = '\n'; - - CHECK_BUFFER_SIZE(); - buffer[pos++] = '\0'; - - return (char*) buffer; -} + dataLength -= 3; + buffer[pos++] = dictionary[(data[i] >> 2) & 0x3F]; + CHECK_LINE_END_STRING(); + buffer[pos++] = dictionary[(((data[i] << 4) & 0x30) | ((data[i+1] >> 4) & 0x0F)) & 0x3F]; + CHECK_LINE_END_STRING(); + buffer[pos++] = dictionary[(((data[i+1] << 2) & 0x3C) | ((data[i+2] >> 6) & 0x03)) & 0x03F]; + CHECK_LINE_END_STRING(); + buffer[pos++] = dictionary[data[i+2] & 0x3F]; + CHECK_LINE_END_STRING(); + i += 3; + } + + if(dataLength == 2) { + buffer[pos++] = dictionary[(data[i] >> 2) & 0x3F]; + CHECK_LINE_END_STRING(); + buffer[pos++] = dictionary[(((data[i] << 4) & 0x30) | ((data[i+1] >> 4) & 0x0F)) & 0x3F]; + CHECK_LINE_END_STRING(); + buffer[pos++] = dictionary[(data[i+1] << 2) & 0x3C]; + CHECK_LINE_END_STRING(); + buffer[pos++] = '='; + } else if(dataLength == 1) { + buffer[pos++] = dictionary[(data[i] >> 2) & 0x3F]; + CHECK_LINE_END_STRING(); + buffer[pos++] = dictionary[(data[i] << 4) & 0x30]; + CHECK_LINE_END_STRING(); + buffer[pos++] = '='; + CHECK_LINE_END_STRING(); + buffer[pos++] = '='; + } + + CHECK_BUFFER_SIZE(); + buffer[pos++] = '\n'; + + CHECK_BUFFER_SIZE(); + buffer[pos++] = '\0'; + + return (char*) buffer; +} diff --git a/dmg/checksum.c b/dmg/checksum.c index 2b4151d..b3c6a7c 100644 --- a/dmg/checksum.c +++ b/dmg/checksum.c @@ -1,313 +1,313 @@ -#include -#include -#include - -#include "dmg.h" - -void BlockSHA1CRC(void* token, const unsigned char* data, size_t len) { - ChecksumToken* ckSumToken; - ckSumToken = (ChecksumToken*) token; - MKBlockChecksum(&(ckSumToken->block), data, len); - CRC32Checksum(&(ckSumToken->crc), data, len); - SHA1Update(&(ckSumToken->sha1), data, len); -} - -void BlockCRC(void* token, const unsigned char* data, size_t len) { - ChecksumToken* ckSumToken; - ckSumToken = (ChecksumToken*) token; - MKBlockChecksum(&(ckSumToken->block), data, len); - CRC32Checksum(&(ckSumToken->crc), data, len); -} - - -void CRCProxy(void* token, const unsigned char* data, size_t len) { - ChecksumToken* ckSumToken; - ckSumToken = (ChecksumToken*) token; - CRC32Checksum(&(ckSumToken->crc), data, len); -} - -/* - * - * MediaKit block checksumming reverse-engineered from Leopard MediaKit framework - * - */ - -uint32_t MKBlockChecksum(uint32_t* ckSum, const unsigned char* data, size_t len) { - uint32_t* curDWordPtr; - uint32_t curDWord; - uint32_t myCkSum; - - myCkSum = *ckSum; - - if(data) { - curDWordPtr = (uint32_t*) data; - while(curDWordPtr < (uint32_t*)(&data[len & 0xFFFFFFFC])) { - curDWord = *curDWordPtr; - FLIPENDIAN(curDWord); - myCkSum = curDWord + ((myCkSum >> 31) | (myCkSum << 1)); - curDWordPtr++; - } - } - - *ckSum = myCkSum; - return myCkSum; -} - - -/* - * CRC32 code ripped off (and adapted) from the zlib-1.1.3 distribution by Jean-loup Gailly and Mark Adler. - * - * Copyright (C) 1995-1998 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - */ - -/* ======================================================================== - * Table of CRC-32's of all single-byte values (made by make_crc_table) - */ -static uint64_t crc_table[256] = { - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8l, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL -}; - -/* ========================================================================= */ -#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); -#define DO2(buf) DO1(buf); DO1(buf); -#define DO4(buf) DO2(buf); DO2(buf); -#define DO8(buf) DO4(buf); DO4(buf); - -/* ========================================================================= */ -uint32_t CRC32Checksum(uint32_t* ckSum, const unsigned char *buf, size_t len) -{ - uint32_t crc; - - crc = *ckSum; - - if (buf == NULL) return crc; - - crc = crc ^ 0xffffffffL; - while (len >= 8) - { - DO8(buf); - len -= 8; - } - if (len) - { - do { -DO1(buf); - } while (--len); - } - - crc = crc ^ 0xffffffffL; - - *ckSum = crc; - return crc; -} - -/* -SHA-1 in C -By Steve Reid -100% Public Domain - -Test Vectors (from FIPS PUB 180-1) -"abc" - A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D -"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 -A million repetitions of "a" - 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F -*/ - -#define SHA1HANDSOFF * Copies data before messing with it. - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -/* blk0() and blk() perform the initial expand. */ -/* I got the idea of expanding during the round function from SSLeay */ - -#define blk0(i) ((endianness == IS_LITTLE_ENDIAN) ? (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ - |(rol(block->l[i],8)&0x00FF00FF)) : block->l[i]) - -#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ - ^block->l[(i+2)&15]^block->l[i&15],1)) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); - - -/* Hash a single 512-bit block. This is the core of the algorithm. */ - -void SHA1Transform(unsigned long state[5], const unsigned char buffer[64]) -{ -unsigned long a, b, c, d, e; -typedef union { - unsigned char c[64]; - unsigned long l[16]; -} CHAR64LONG16; -CHAR64LONG16* block; -#ifdef SHA1HANDSOFF -static unsigned char workspace[64]; - block = (CHAR64LONG16*)workspace; - memcpy(block, buffer, 64); -#else - block = (CHAR64LONG16*)buffer; -#endif - /* Copy context->state[] to working vars */ - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - /* Wipe variables */ - a = b = c = d = e = 0; -} - - -/* SHA1Init - Initialize new context */ - -void SHA1Init(SHA1_CTX* context) -{ - /* SHA1 initialization constants */ - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - - -/* Run your data through this. */ - -void SHA1Update(SHA1_CTX* context, const unsigned char* data, unsigned int len) -{ -unsigned int i, j; - - j = (context->count[0] >> 3) & 63; - if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; - context->count[1] += (len >> 29); - if ((j + len) > 63) { - memcpy(&context->buffer[j], data, (i = 64-j)); - SHA1Transform(context->state, context->buffer); - for ( ; i + 63 < len; i += 64) { - SHA1Transform(context->state, &data[i]); - } - j = 0; - } - else i = 0; - memcpy(&context->buffer[j], &data[i], len - i); -} - - -/* Add padding and return the message digest. */ - -void SHA1Final(unsigned char digest[20], SHA1_CTX* context) -{ -unsigned long i, j; -unsigned char finalcount[8]; - - for (i = 0; i < 8; i++) { - finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] - >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ - } - SHA1Update(context, (unsigned char *)"\200", 1); - while ((context->count[0] & 504) != 448) { - SHA1Update(context, (unsigned char *)"\0", 1); - } - SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ - for (i = 0; i < 20; i++) { - digest[i] = (unsigned char) - ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); - } - /* Wipe variables */ - i = j = 0; - memset(context->buffer, 0, 64); - memset(context->state, 0, 20); - memset(context->count, 0, 8); - memset(&finalcount, 0, 8); -#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ - SHA1Transform(context->state, context->buffer); -#endif -} - +#include +#include +#include + +#include "dmg.h" + +void BlockSHA1CRC(void* token, const unsigned char* data, size_t len) { + ChecksumToken* ckSumToken; + ckSumToken = (ChecksumToken*) token; + MKBlockChecksum(&(ckSumToken->block), data, len); + CRC32Checksum(&(ckSumToken->crc), data, len); + SHA1Update(&(ckSumToken->sha1), data, len); +} + +void BlockCRC(void* token, const unsigned char* data, size_t len) { + ChecksumToken* ckSumToken; + ckSumToken = (ChecksumToken*) token; + MKBlockChecksum(&(ckSumToken->block), data, len); + CRC32Checksum(&(ckSumToken->crc), data, len); +} + + +void CRCProxy(void* token, const unsigned char* data, size_t len) { + ChecksumToken* ckSumToken; + ckSumToken = (ChecksumToken*) token; + CRC32Checksum(&(ckSumToken->crc), data, len); +} + +/* + * + * MediaKit block checksumming reverse-engineered from Leopard MediaKit framework + * + */ + +uint32_t MKBlockChecksum(uint32_t* ckSum, const unsigned char* data, size_t len) { + uint32_t* curDWordPtr; + uint32_t curDWord; + uint32_t myCkSum; + + myCkSum = *ckSum; + + if(data) { + curDWordPtr = (uint32_t*) data; + while(curDWordPtr < (uint32_t*)(&data[len & 0xFFFFFFFC])) { + curDWord = *curDWordPtr; + FLIPENDIAN(curDWord); + myCkSum = curDWord + ((myCkSum >> 31) | (myCkSum << 1)); + curDWordPtr++; + } + } + + *ckSum = myCkSum; + return myCkSum; +} + + +/* + * CRC32 code ripped off (and adapted) from the zlib-1.1.3 distribution by Jean-loup Gailly and Mark Adler. + * + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + */ + +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +static uint64_t crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8l, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; + +/* ========================================================================= */ +#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +/* ========================================================================= */ +uint32_t CRC32Checksum(uint32_t* ckSum, const unsigned char *buf, size_t len) +{ + uint32_t crc; + + crc = *ckSum; + + if (buf == NULL) return crc; + + crc = crc ^ 0xffffffffL; + while (len >= 8) + { + DO8(buf); + len -= 8; + } + if (len) + { + do { +DO1(buf); + } while (--len); + } + + crc = crc ^ 0xffffffffL; + + *ckSum = crc; + return crc; +} + +/* +SHA-1 in C +By Steve Reid +100% Public Domain + +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +#define SHA1HANDSOFF * Copies data before messing with it. + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ + +#define blk0(i) ((endianness == IS_LITTLE_ENDIAN) ? (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) : block->l[i]) + +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform(unsigned long state[5], const unsigned char buffer[64]) +{ +unsigned long a, b, c, d, e; +typedef union { + unsigned char c[64]; + unsigned long l[16]; +} CHAR64LONG16; +CHAR64LONG16* block; +#ifdef SHA1HANDSOFF +static unsigned char workspace[64]; + block = (CHAR64LONG16*)workspace; + memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16*)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init(SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update(SHA1_CTX* context, const unsigned char* data, unsigned int len) +{ +unsigned int i, j; + + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; + context->count[1] += (len >> 29); + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ + +void SHA1Final(unsigned char digest[20], SHA1_CTX* context) +{ +unsigned long i, j; +unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + SHA1Update(context, (unsigned char *)"\200", 1); + while ((context->count[0] & 504) != 448) { + SHA1Update(context, (unsigned char *)"\0", 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + /* Wipe variables */ + i = j = 0; + memset(context->buffer, 0, 64); + memset(context->state, 0, 20); + memset(context->count, 0, 8); + memset(&finalcount, 0, 8); +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ + SHA1Transform(context->state, context->buffer); +#endif +} + diff --git a/dmg/dmg.c b/dmg/dmg.c index e77bef8..e4858be 100644 --- a/dmg/dmg.c +++ b/dmg/dmg.c @@ -1,83 +1,83 @@ -#include -#include -#include -#include - -#include "dmg.h" -#include "filevault.h" - -char endianness; - -void TestByteOrder() -{ - short int word = 0x0001; - char *byte = (char *) &word; - endianness = byte[0] ? IS_LITTLE_ENDIAN : IS_BIG_ENDIAN; -} - -int buildInOut(const char* source, const char* dest, AbstractFile** in, AbstractFile** out) { - *in = createAbstractFileFromFile(fopen(source, "rb")); - if(!(*in)) { - printf("cannot open source: %s\n", source); - return FALSE; - } - - *out = createAbstractFileFromFile(fopen(dest, "wb")); - if(!(*out)) { - (*in)->close(*in); - printf("cannot open destination: %s\n", dest); - return FALSE; - } - - return TRUE; -} - -int main(int argc, char* argv[]) { - int partNum; - AbstractFile* in; - AbstractFile* out; - int hasKey; - - TestByteOrder(); - - if(argc < 4) { - printf("usage: %s [extract|build|iso|dmg] (-k ) (partition)\n", argv[0]); - return 0; - } - - if(!buildInOut(argv[2], argv[3], &in, &out)) { - return FALSE; - } - - hasKey = FALSE; - if(argc > 5) { - if(strcmp(argv[4], "-k") == 0) { - in = createAbstractFileFromFileVault(in, argv[5]); - hasKey = TRUE; - } - } - - - if(strcmp(argv[1], "extract") == 0) { - partNum = -1; - - if(hasKey) { - if(argc > 6) { - sscanf(argv[6], "%d", &partNum); - } - } else { - if(argc > 4) { - sscanf(argv[4], "%d", &partNum); - } - } - extractDmg(in, out, partNum); - } else if(strcmp(argv[1], "build") == 0) { - buildDmg(in, out); - } else if(strcmp(argv[1], "iso") == 0) { - convertToISO(in, out); - } else if(strcmp(argv[1], "dmg") == 0) { - convertToDMG(in, out); - } - - return 0; -} +#include +#include +#include +#include + +#include "dmg.h" +#include "filevault.h" + +char endianness; + +void TestByteOrder() +{ + short int word = 0x0001; + char *byte = (char *) &word; + endianness = byte[0] ? IS_LITTLE_ENDIAN : IS_BIG_ENDIAN; +} + +int buildInOut(const char* source, const char* dest, AbstractFile** in, AbstractFile** out) { + *in = createAbstractFileFromFile(fopen(source, "rb")); + if(!(*in)) { + printf("cannot open source: %s\n", source); + return FALSE; + } + + *out = createAbstractFileFromFile(fopen(dest, "wb")); + if(!(*out)) { + (*in)->close(*in); + printf("cannot open destination: %s\n", dest); + return FALSE; + } + + return TRUE; +} + +int main(int argc, char* argv[]) { + int partNum; + AbstractFile* in; + AbstractFile* out; + int hasKey; + + TestByteOrder(); + + if(argc < 4) { + printf("usage: %s [extract|build|iso|dmg] (-k ) (partition)\n", argv[0]); + return 0; + } + + if(!buildInOut(argv[2], argv[3], &in, &out)) { + return FALSE; + } + + hasKey = FALSE; + if(argc > 5) { + if(strcmp(argv[4], "-k") == 0) { + in = createAbstractFileFromFileVault(in, argv[5]); + hasKey = TRUE; + } + } + + + if(strcmp(argv[1], "extract") == 0) { + partNum = -1; + + if(hasKey) { + if(argc > 6) { + sscanf(argv[6], "%d", &partNum); + } + } else { + if(argc > 4) { + sscanf(argv[4], "%d", &partNum); + } + } + extractDmg(in, out, partNum); + } else if(strcmp(argv[1], "build") == 0) { + buildDmg(in, out); + } else if(strcmp(argv[1], "iso") == 0) { + convertToISO(in, out); + } else if(strcmp(argv[1], "dmg") == 0) { + convertToDMG(in, out); + } + + return 0; +} diff --git a/dmg/dmg.h b/dmg/dmg.h index 3db5cef..e28fe92 100644 --- a/dmg/dmg.h +++ b/dmg/dmg.h @@ -1,343 +1,343 @@ -#ifndef DMG_H -#define DMG_H - -#include -#include -#include - +#ifndef DMG_H +#define DMG_H + +#include +#include +#include + #include "../hfs/hfsplus.h" -#include "../hfs/abstractfile.h" - -#define CHECKSUM_CRC32 0x00000002 -#define CHECKSUM_MKBLOCK 0x0002 -#define CHECKSUM_NONE 0x0000 - -#define BLOCK_ZLIB 0x80000005 -#define BLOCK_RAW 0x00000001 -#define BLOCK_IGNORE 0x00000002 -#define BLOCK_COMMENT 0x7FFFFFFE -#define BLOCK_TERMINATOR 0xFFFFFFFF - -#define SECTOR_SIZE 512 - -#define DRIVER_DESCRIPTOR_SIGNATURE 0x4552 -#define APPLE_PARTITION_MAP_SIGNATURE 0x504D -#define UDIF_BLOCK_SIGNATURE 0x6D697368 -#define KOLY_SIGNATURE 0x6B6F6C79 -#define HFSX_SIGNATURE 0x4858 - -#define ATTRIBUTE_HDIUTIL 0x0050 - -#define HFSX_VOLUME_TYPE "Apple_HFSX" - -#define DDM_SIZE 0x1 -#define PARTITION_SIZE 0x3f -#define ATAPI_SIZE 0x8 -#define FREE_SIZE 0xa -#define EXTRA_SIZE (DDM_SIZE + PARTITION_SIZE + ATAPI_SIZE + FREE_SIZE) - -#define DDM_OFFSET 0x0 -#define PARTITION_OFFSET (DDM_SIZE) -#define ATAPI_OFFSET (DDM_SIZE + PARTITION_SIZE) -#define USER_OFFSET (DDM_SIZE + PARTITION_SIZE + ATAPI_SIZE) - -#define BOOTCODE_DMMY 0x444D4D59 -#define BOOTCODE_GOON 0x676F6F6E - -enum { - kUDIFFlagsFlattened = 1 -}; - -enum { - kUDIFDeviceImageType = 1, - kUDIFPartitionImageType = 2 -}; - -typedef struct { - uint32_t type; - uint32_t size; - uint32_t data[0x20]; -} __attribute__((__packed__)) UDIFChecksum; - -typedef struct { - uint32_t data1; /* smallest */ - uint32_t data2; - uint32_t data3; - uint32_t data4; /* largest */ -} __attribute__((__packed__)) UDIFID; - -typedef struct { - uint32_t fUDIFSignature; - uint32_t fUDIFVersion; - uint32_t fUDIFHeaderSize; - uint32_t fUDIFFlags; - - uint64_t fUDIFRunningDataForkOffset; - uint64_t fUDIFDataForkOffset; - uint64_t fUDIFDataForkLength; - uint64_t fUDIFRsrcForkOffset; - uint64_t fUDIFRsrcForkLength; - - uint32_t fUDIFSegmentNumber; - 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 */ - - UDIFChecksum fUDIFDataForkChecksum; - - uint64_t fUDIFXMLOffset; - 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 */ - - UDIFChecksum fUDIFMasterChecksum; - - uint32_t fUDIFImageVariant; - uint64_t fUDIFSectorCount; - - uint32_t reserved2; - uint32_t reserved3; - uint32_t reserved4; - -} __attribute__((__packed__)) UDIFResourceFile; - -typedef struct { - uint32_t type; - uint32_t reserved; - uint64_t sectorStart; - uint64_t sectorCount; - uint64_t compOffset; - uint64_t compLength; -} __attribute__((__packed__)) BLKXRun; - -typedef struct { - 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 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 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 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 unknown4; /* always seems to be 0 for UDIF */ - uint16_t volumeSignature; /* HX in our case */ - uint16_t sizePresent; /* always set to 1 */ -} __attribute__((__packed__)) SizeResource; - -typedef struct { - uint16_t version; /* set to 1 */ - uint32_t type; /* set to 0x2 for MKBlockChecksum */ - uint32_t checksum; -} __attribute__((__packed__)) CSumResource; - -typedef struct NSizResource { - char isVolume; - unsigned char* sha1Digest; - uint32_t blockChecksum2; - uint32_t bytes; - uint32_t modifyDate; - uint32_t partitionNumber; - uint32_t version; - uint32_t volumeSignature; - struct NSizResource* next; -} NSizResource; - -#define DDM_DESCRIPTOR 0xFFFFFFFF -#define ENTIRE_DEVICE_DESCRIPTOR 0xFFFFFFFE - -typedef struct { - uint32_t fUDIFBlocksSignature; - uint32_t infoVersion; - uint64_t firstSectorNumber; - uint64_t sectorCount; - - uint64_t dataStart; - uint32_t decompressBufferRequested; - uint32_t blocksDescriptor; - - uint32_t reserved1; - uint32_t reserved2; - uint32_t reserved3; - uint32_t reserved4; - uint32_t reserved5; - uint32_t reserved6; - - UDIFChecksum checksum; - - uint32_t blocksRunCount; - BLKXRun runs[0]; -} __attribute__((__packed__)) BLKXTable; - -typedef struct { - uint32_t ddBlock; - uint16_t ddSize; - uint16_t ddType; -} __attribute__((__packed__)) DriverDescriptor; - -typedef struct { - uint16_t pmSig; - uint16_t pmSigPad; - uint32_t pmMapBlkCnt; - uint32_t pmPyPartStart; - uint32_t pmPartBlkCnt; - unsigned char pmPartName[32]; - unsigned char pmParType[32]; - uint32_t pmLgDataStart; - uint32_t pmDataCnt; - uint32_t pmPartStatus; - uint32_t pmLgBootStart; - uint32_t pmBootSize; - uint32_t pmBootAddr; - uint32_t pmBootAddr2; - uint32_t pmBootEntry; - uint32_t pmBootEntry2; - uint32_t pmBootCksum; - unsigned char pmProcessor[16]; - uint32_t bootCode; - uint16_t pmPad[186]; -} __attribute__((__packed__)) Partition; - -typedef struct { - uint16_t sbSig; - uint16_t sbBlkSize; - uint32_t sbBlkCount; - uint16_t sbDevType; - uint16_t sbDevId; - uint32_t sbData; - uint16_t sbDrvrCount; - uint32_t ddBlock; - uint16_t ddSize; - uint16_t ddType; - DriverDescriptor ddPad[0]; -} __attribute__((__packed__)) DriverDescriptorRecord; - -typedef struct ResourceData { - uint32_t attributes; - unsigned char* data; - size_t dataLength; - int id; - unsigned char* name; - struct ResourceData* next; -} ResourceData; - -typedef void (*FlipDataFunc)(unsigned char* data, char out); -typedef void (*ChecksumFunc)(void* ckSum, const unsigned char* data, size_t len); - -typedef struct ResourceKey { - unsigned char* key; - ResourceData* data; - struct ResourceKey* next; - FlipDataFunc flipData; -} ResourceKey; - -typedef struct { - unsigned long state[5]; - unsigned long count[2]; - unsigned char buffer[64]; -} SHA1_CTX; - -typedef struct { - uint32_t block; - uint32_t crc; - SHA1_CTX sha1; -} ChecksumToken; - -static inline uint32_t readUInt32(AbstractFile* file) { - uint32_t data; - - ASSERT(file->read(file, &data, sizeof(data)) == sizeof(data), "fread"); - FLIPENDIAN(data); - - return data; -} - -static inline void writeUInt32(AbstractFile* file, uint32_t data) { - FLIPENDIAN(data); - ASSERT(file->write(file, &data, sizeof(data)) == sizeof(data), "fwrite"); -} - -static inline uint32_t readUInt64(AbstractFile* file) { - uint64_t data; - - ASSERT(file->read(file, &data, sizeof(data)) == sizeof(data), "fread"); - FLIPENDIAN(data); - - return data; -} - -static inline void writeUInt64(AbstractFile* file, uint64_t data) { - FLIPENDIAN(data); - ASSERT(file->write(file, &data, sizeof(data)) == sizeof(data), "fwrite"); -} +#include "../hfs/abstractfile.h" + +#define CHECKSUM_CRC32 0x00000002 +#define CHECKSUM_MKBLOCK 0x0002 +#define CHECKSUM_NONE 0x0000 + +#define BLOCK_ZLIB 0x80000005 +#define BLOCK_RAW 0x00000001 +#define BLOCK_IGNORE 0x00000002 +#define BLOCK_COMMENT 0x7FFFFFFE +#define BLOCK_TERMINATOR 0xFFFFFFFF + +#define SECTOR_SIZE 512 + +#define DRIVER_DESCRIPTOR_SIGNATURE 0x4552 +#define APPLE_PARTITION_MAP_SIGNATURE 0x504D +#define UDIF_BLOCK_SIGNATURE 0x6D697368 +#define KOLY_SIGNATURE 0x6B6F6C79 +#define HFSX_SIGNATURE 0x4858 + +#define ATTRIBUTE_HDIUTIL 0x0050 + +#define HFSX_VOLUME_TYPE "Apple_HFSX" + +#define DDM_SIZE 0x1 +#define PARTITION_SIZE 0x3f +#define ATAPI_SIZE 0x8 +#define FREE_SIZE 0xa +#define EXTRA_SIZE (DDM_SIZE + PARTITION_SIZE + ATAPI_SIZE + FREE_SIZE) + +#define DDM_OFFSET 0x0 +#define PARTITION_OFFSET (DDM_SIZE) +#define ATAPI_OFFSET (DDM_SIZE + PARTITION_SIZE) +#define USER_OFFSET (DDM_SIZE + PARTITION_SIZE + ATAPI_SIZE) + +#define BOOTCODE_DMMY 0x444D4D59 +#define BOOTCODE_GOON 0x676F6F6E + +enum { + kUDIFFlagsFlattened = 1 +}; + +enum { + kUDIFDeviceImageType = 1, + kUDIFPartitionImageType = 2 +}; + +typedef struct { + uint32_t type; + uint32_t size; + uint32_t data[0x20]; +} __attribute__((__packed__)) UDIFChecksum; + +typedef struct { + uint32_t data1; /* smallest */ + uint32_t data2; + uint32_t data3; + uint32_t data4; /* largest */ +} __attribute__((__packed__)) UDIFID; + +typedef struct { + uint32_t fUDIFSignature; + uint32_t fUDIFVersion; + uint32_t fUDIFHeaderSize; + uint32_t fUDIFFlags; + + uint64_t fUDIFRunningDataForkOffset; + uint64_t fUDIFDataForkOffset; + uint64_t fUDIFDataForkLength; + uint64_t fUDIFRsrcForkOffset; + uint64_t fUDIFRsrcForkLength; + + uint32_t fUDIFSegmentNumber; + 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 */ + + UDIFChecksum fUDIFDataForkChecksum; + + uint64_t fUDIFXMLOffset; + 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 */ + + UDIFChecksum fUDIFMasterChecksum; + + uint32_t fUDIFImageVariant; + uint64_t fUDIFSectorCount; + + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; + +} __attribute__((__packed__)) UDIFResourceFile; + +typedef struct { + uint32_t type; + uint32_t reserved; + uint64_t sectorStart; + uint64_t sectorCount; + uint64_t compOffset; + uint64_t compLength; +} __attribute__((__packed__)) BLKXRun; + +typedef struct { + 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 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 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 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 unknown4; /* always seems to be 0 for UDIF */ + uint16_t volumeSignature; /* HX in our case */ + uint16_t sizePresent; /* always set to 1 */ +} __attribute__((__packed__)) SizeResource; + +typedef struct { + uint16_t version; /* set to 1 */ + uint32_t type; /* set to 0x2 for MKBlockChecksum */ + uint32_t checksum; +} __attribute__((__packed__)) CSumResource; + +typedef struct NSizResource { + char isVolume; + unsigned char* sha1Digest; + uint32_t blockChecksum2; + uint32_t bytes; + uint32_t modifyDate; + uint32_t partitionNumber; + uint32_t version; + uint32_t volumeSignature; + struct NSizResource* next; +} NSizResource; + +#define DDM_DESCRIPTOR 0xFFFFFFFF +#define ENTIRE_DEVICE_DESCRIPTOR 0xFFFFFFFE + +typedef struct { + uint32_t fUDIFBlocksSignature; + uint32_t infoVersion; + uint64_t firstSectorNumber; + uint64_t sectorCount; + + uint64_t dataStart; + uint32_t decompressBufferRequested; + uint32_t blocksDescriptor; + + uint32_t reserved1; + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; + uint32_t reserved5; + uint32_t reserved6; + + UDIFChecksum checksum; + + uint32_t blocksRunCount; + BLKXRun runs[0]; +} __attribute__((__packed__)) BLKXTable; + +typedef struct { + uint32_t ddBlock; + uint16_t ddSize; + uint16_t ddType; +} __attribute__((__packed__)) DriverDescriptor; + +typedef struct { + uint16_t pmSig; + uint16_t pmSigPad; + uint32_t pmMapBlkCnt; + uint32_t pmPyPartStart; + uint32_t pmPartBlkCnt; + unsigned char pmPartName[32]; + unsigned char pmParType[32]; + uint32_t pmLgDataStart; + uint32_t pmDataCnt; + uint32_t pmPartStatus; + uint32_t pmLgBootStart; + uint32_t pmBootSize; + uint32_t pmBootAddr; + uint32_t pmBootAddr2; + uint32_t pmBootEntry; + uint32_t pmBootEntry2; + uint32_t pmBootCksum; + unsigned char pmProcessor[16]; + uint32_t bootCode; + uint16_t pmPad[186]; +} __attribute__((__packed__)) Partition; + +typedef struct { + uint16_t sbSig; + uint16_t sbBlkSize; + uint32_t sbBlkCount; + uint16_t sbDevType; + uint16_t sbDevId; + uint32_t sbData; + uint16_t sbDrvrCount; + uint32_t ddBlock; + uint16_t ddSize; + uint16_t ddType; + DriverDescriptor ddPad[0]; +} __attribute__((__packed__)) DriverDescriptorRecord; + +typedef struct ResourceData { + uint32_t attributes; + unsigned char* data; + size_t dataLength; + int id; + unsigned char* name; + struct ResourceData* next; +} ResourceData; + +typedef void (*FlipDataFunc)(unsigned char* data, char out); +typedef void (*ChecksumFunc)(void* ckSum, const unsigned char* data, size_t len); + +typedef struct ResourceKey { + unsigned char* key; + ResourceData* data; + struct ResourceKey* next; + FlipDataFunc flipData; +} ResourceKey; + +typedef struct { + unsigned long state[5]; + unsigned long count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +typedef struct { + uint32_t block; + uint32_t crc; + SHA1_CTX sha1; +} ChecksumToken; + +static inline uint32_t readUInt32(AbstractFile* file) { + uint32_t data; + + ASSERT(file->read(file, &data, sizeof(data)) == sizeof(data), "fread"); + FLIPENDIAN(data); + + return data; +} + +static inline void writeUInt32(AbstractFile* file, uint32_t data) { + FLIPENDIAN(data); + ASSERT(file->write(file, &data, sizeof(data)) == sizeof(data), "fwrite"); +} + +static inline uint32_t readUInt64(AbstractFile* file) { + uint64_t data; + + ASSERT(file->read(file, &data, sizeof(data)) == sizeof(data), "fread"); + FLIPENDIAN(data); + + return data; +} + +static inline void writeUInt64(AbstractFile* file, uint64_t data) { + FLIPENDIAN(data); + ASSERT(file->write(file, &data, sizeof(data)) == sizeof(data), "fwrite"); +} #ifdef __cplusplus extern "C" { -#endif - unsigned char* decodeBase64(char* toDecode, size_t* dataLength); - void writeBase64(AbstractFile* file, unsigned char* data, size_t dataLength, int tabLength, int width); - char* convertBase64(unsigned char* data, size_t dataLength, int tabLength, int width); - - uint32_t CRC32Checksum(uint32_t* crc, const unsigned char *buf, size_t len); - uint32_t MKBlockChecksum(uint32_t* ckSum, const unsigned char* data, size_t len); - - void BlockSHA1CRC(void* token, const unsigned char* data, size_t len); - void BlockCRC(void* token, const unsigned char* data, size_t len); - void CRCProxy(void* token, const unsigned char* data, size_t len); - - void SHA1Transform(unsigned long state[5], const unsigned char buffer[64]); - void SHA1Init(SHA1_CTX* context); - void SHA1Update(SHA1_CTX* context, const unsigned char* data, unsigned int len); - void SHA1Final(unsigned char digest[20], SHA1_CTX* context); - - void flipUDIFChecksum(UDIFChecksum* o, char out); - void readUDIFChecksum(AbstractFile* file, UDIFChecksum* o); - void writeUDIFChecksum(AbstractFile* file, UDIFChecksum* o); - void readUDIFID(AbstractFile* file, UDIFID* o); - void writeUDIFID(AbstractFile* file, UDIFID* o); - void readUDIFResourceFile(AbstractFile* file, UDIFResourceFile* o); - void writeUDIFResourceFile(AbstractFile* file, UDIFResourceFile* o); - - ResourceKey* readResources(AbstractFile* file, UDIFResourceFile* resourceFile); - void writeResources(AbstractFile* file, ResourceKey* resources); - void releaseResources(ResourceKey* resources); - - NSizResource* readNSiz(ResourceKey* resources); - ResourceKey* writeNSiz(NSizResource* nSiz); - void releaseNSiz(NSizResource* nSiz); - - extern const char* plistHeader; - extern const char* plistFooter; - - ResourceKey* getResourceByKey(ResourceKey* resources, const char* key); - ResourceData* getDataByID(ResourceKey* resource, int id); - ResourceKey* insertData(ResourceKey* resources, const char* key, int id, const char* name, const char* data, size_t dataLength, uint32_t attributes); - ResourceKey* makePlst(); - ResourceKey* makeSize(HFSPlusVolumeHeader* volumeHeader); - - void flipDriverDescriptorRecord(DriverDescriptorRecord* record, char out); - void flipPartition(Partition* partition, char out); - void flipPartitionMultiple(Partition* partition, char multiple, char out); - - void readDriverDescriptorMap(AbstractFile* file, ResourceKey* resources); - DriverDescriptorRecord* createDriverDescriptorMap(uint32_t numSectors); - void writeDriverDescriptorMap(AbstractFile* file, DriverDescriptorRecord* DDM, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources); - void readApplePartitionMap(AbstractFile* file, ResourceKey* resources); - Partition* createApplePartitionMap(uint32_t numSectors, const char* volumeType); - void writeApplePartitionMap(AbstractFile* file, Partition* partitions, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn); - void writeATAPI(AbstractFile* file, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn); - void writeFreePartition(AbstractFile* outFile, 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); - - - int extractDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, int partNum); - int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut); - int convertToISO(AbstractFile* abstractIn, AbstractFile* abstractOut); - int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut); +#endif + unsigned char* decodeBase64(char* toDecode, size_t* dataLength); + void writeBase64(AbstractFile* file, unsigned char* data, size_t dataLength, int tabLength, int width); + char* convertBase64(unsigned char* data, size_t dataLength, int tabLength, int width); + + uint32_t CRC32Checksum(uint32_t* crc, const unsigned char *buf, size_t len); + uint32_t MKBlockChecksum(uint32_t* ckSum, const unsigned char* data, size_t len); + + void BlockSHA1CRC(void* token, const unsigned char* data, size_t len); + void BlockCRC(void* token, const unsigned char* data, size_t len); + void CRCProxy(void* token, const unsigned char* data, size_t len); + + void SHA1Transform(unsigned long state[5], const unsigned char buffer[64]); + void SHA1Init(SHA1_CTX* context); + void SHA1Update(SHA1_CTX* context, const unsigned char* data, unsigned int len); + void SHA1Final(unsigned char digest[20], SHA1_CTX* context); + + void flipUDIFChecksum(UDIFChecksum* o, char out); + void readUDIFChecksum(AbstractFile* file, UDIFChecksum* o); + void writeUDIFChecksum(AbstractFile* file, UDIFChecksum* o); + void readUDIFID(AbstractFile* file, UDIFID* o); + void writeUDIFID(AbstractFile* file, UDIFID* o); + void readUDIFResourceFile(AbstractFile* file, UDIFResourceFile* o); + void writeUDIFResourceFile(AbstractFile* file, UDIFResourceFile* o); + + ResourceKey* readResources(AbstractFile* file, UDIFResourceFile* resourceFile); + void writeResources(AbstractFile* file, ResourceKey* resources); + void releaseResources(ResourceKey* resources); + + NSizResource* readNSiz(ResourceKey* resources); + ResourceKey* writeNSiz(NSizResource* nSiz); + void releaseNSiz(NSizResource* nSiz); + + extern const char* plistHeader; + extern const char* plistFooter; + + ResourceKey* getResourceByKey(ResourceKey* resources, const char* key); + ResourceData* getDataByID(ResourceKey* resource, int id); + ResourceKey* insertData(ResourceKey* resources, const char* key, int id, const char* name, const char* data, size_t dataLength, uint32_t attributes); + ResourceKey* makePlst(); + ResourceKey* makeSize(HFSPlusVolumeHeader* volumeHeader); + + void flipDriverDescriptorRecord(DriverDescriptorRecord* record, char out); + void flipPartition(Partition* partition, char out); + void flipPartitionMultiple(Partition* partition, char multiple, char out); + + void readDriverDescriptorMap(AbstractFile* file, ResourceKey* resources); + DriverDescriptorRecord* createDriverDescriptorMap(uint32_t numSectors); + void writeDriverDescriptorMap(AbstractFile* file, DriverDescriptorRecord* DDM, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources); + void readApplePartitionMap(AbstractFile* file, ResourceKey* resources); + Partition* createApplePartitionMap(uint32_t numSectors, const char* volumeType); + void writeApplePartitionMap(AbstractFile* file, Partition* partitions, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn); + void writeATAPI(AbstractFile* file, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn); + void writeFreePartition(AbstractFile* outFile, 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); + + + int extractDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, int partNum); + int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut); + int convertToISO(AbstractFile* abstractIn, AbstractFile* abstractOut); + int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut); #ifdef __cplusplus } #endif - -#endif + +#endif diff --git a/dmg/dmgfile.c b/dmg/dmgfile.c index e6d1adf..39ce76b 100644 --- a/dmg/dmgfile.c +++ b/dmg/dmgfile.c @@ -1,236 +1,236 @@ -/* - * dmgfile.c - * libdmg-hfsplus - */ - -#include -#include -#include - -#include "dmg.h" -#include "dmgfile.h" - -static void cacheRun(DMG* dmg, BLKXTable* blkx, int run) { - size_t bufferSize; - z_stream strm; - void* inBuffer; - int ret; - size_t have; - - if(dmg->runData) { - free(dmg->runData); - } - - bufferSize = SECTOR_SIZE * blkx->decompressBufferRequested; - - dmg->runData = (void*) malloc(bufferSize); - inBuffer = (void*) malloc(bufferSize); - memset(dmg->runData, 0, bufferSize); - - ASSERT(dmg->dmg->seek(dmg->dmg, blkx->dataStart + blkx->runs[run].compOffset) == 0, "fseeko"); - - switch(blkx->runs[run].type) { - case BLOCK_ZLIB: - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - - ASSERT(inflateInit(&strm) == Z_OK, "inflateInit"); - - ASSERT((strm.avail_in = dmg->dmg->read(dmg->dmg, inBuffer, blkx->runs[run].compLength)) == blkx->runs[run].compLength, "fread"); - strm.next_in = (unsigned char*) inBuffer; - - do { - strm.avail_out = bufferSize; - strm.next_out = (unsigned char*) dmg->runData; - ASSERT((ret = inflate(&strm, Z_NO_FLUSH)) != Z_STREAM_ERROR, "inflate/Z_STREAM_ERROR"); - if(ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_STREAM_END) { - ASSERT(FALSE, "inflate"); - } - have = bufferSize - strm.avail_out; - } while (strm.avail_out == 0); - - ASSERT(inflateEnd(&strm) == Z_OK, "inflateEnd"); - break; - case BLOCK_RAW: - ASSERT((have = dmg->dmg->read(dmg->dmg, dmg->runData, blkx->runs[run].compLength)) == blkx->runs[run].compLength, "fread"); - break; - case BLOCK_IGNORE: - break; - case BLOCK_COMMENT: - break; - case BLOCK_TERMINATOR: - break; - default: - break; - } - - dmg->runStart = (blkx->runs[run].sectorStart + blkx->firstSectorNumber) * SECTOR_SIZE; - dmg->runEnd = dmg->runStart + (blkx->runs[run].sectorCount * SECTOR_SIZE); -} - -static void cacheOffset(DMG* dmg, off_t location) { - int i; - int j; - uint64_t sector; - - sector = (uint64_t)(location / SECTOR_SIZE); - - for(i = 0; i < dmg->numBLKX; i++) { - if(sector >= dmg->blkx[i]->firstSectorNumber && sector < (dmg->blkx[i]->firstSectorNumber + dmg->blkx[i]->sectorCount)) { - for(j = 0; j < dmg->blkx[i]->blocksRunCount; j++) { - if(sector >= (dmg->blkx[i]->firstSectorNumber + dmg->blkx[i]->runs[j].sectorStart) && - sector < (dmg->blkx[i]->firstSectorNumber + dmg->blkx[i]->runs[j].sectorStart + dmg->blkx[i]->runs[j].sectorCount)) { - cacheRun(dmg, dmg->blkx[i], j); - } - } - } - } -} - -static int dmgFileRead(io_func* io, off_t location, size_t size, void *buffer) { - DMG* dmg; - size_t toRead; - - dmg = (DMG*) io->data; - - location += dmg->offset; - - if(size == 0) { - return TRUE; - } - - if(location < dmg->runStart || location >= dmg->runEnd) { - cacheOffset(dmg, location); - } - - if((location + size) > dmg->runEnd) { - toRead = dmg->runEnd - location; - } else { - toRead = size; - } - - memcpy(buffer, (void*)((uint8_t*)dmg->runData + (uint32_t)(location - dmg->runStart)), toRead); - size -= toRead; - location += toRead; - buffer = (void*)((uint8_t*)buffer + toRead); - - if(size > 0) { - return dmgFileRead(io, location, size, buffer); - } else { - return TRUE; - } -} - -static int dmgFileWrite(io_func* io, off_t location, size_t size, void *buffer) { - fprintf(stderr, "Error: writing to DMGs is not supported (impossible to achieve with compressed images and retain asr multicast ordering).\n"); - return FALSE; -} - - -static void closeDmgFile(io_func* io) { - DMG* dmg; - - dmg = (DMG*) io->data; - - if(dmg->runData) { - free(dmg->runData); - } - - free(dmg->blkx); - releaseResources(dmg->resources); - dmg->dmg->close(dmg->dmg); - free(dmg); - free(io); -} - -io_func* openDmgFile(AbstractFile* abstractIn) { - off_t fileLength; - UDIFResourceFile resourceFile; - DMG* dmg; - ResourceData* blkx; - ResourceData* curData; - int i; - - io_func* toReturn; - - if(abstractIn == NULL) { - return NULL; - } - - fileLength = abstractIn->getLength(abstractIn); - abstractIn->seek(abstractIn, fileLength - sizeof(UDIFResourceFile)); - readUDIFResourceFile(abstractIn, &resourceFile); - - dmg = (DMG*) malloc(sizeof(DMG)); - dmg->dmg = abstractIn; - dmg->resources = readResources(abstractIn, &resourceFile); - dmg->numBLKX = 0; - - blkx = (getResourceByKey(dmg->resources, "blkx"))->data; - - curData = blkx; - while(curData != NULL) { - dmg->numBLKX++; - curData = curData->next; - } - - dmg->blkx = (BLKXTable**) malloc(sizeof(BLKXTable*) * dmg->numBLKX); - - i = 0; - while(blkx != NULL) { - dmg->blkx[i] = (BLKXTable*)(blkx->data); - i++; - blkx = blkx->next; - } - - dmg->offset = 0; - - dmg->runData = NULL; - cacheOffset(dmg, 0); - - toReturn = (io_func*) malloc(sizeof(io_func)); - - toReturn->data = dmg; - toReturn->read = &dmgFileRead; - toReturn->write = &dmgFileWrite; - toReturn->close = &closeDmgFile; - - return toReturn; -} - -io_func* openDmgFilePartition(AbstractFile* abstractIn, int partition) { - io_func* toReturn; - Partition* partitions; - int numPartitions; - int i; - - toReturn = openDmgFile(abstractIn); - - if(toReturn == NULL) { - return NULL; - } - - partitions = (Partition*) malloc(sizeof(Partition)); - toReturn->read(toReturn, SECTOR_SIZE, SECTOR_SIZE, partitions); - flipPartitionMultiple(partitions, FALSE, FALSE); - numPartitions = partitions->pmMapBlkCnt; - partitions = (Partition*) realloc(partitions, numPartitions * SECTOR_SIZE); - toReturn->read(toReturn, SECTOR_SIZE, numPartitions * SECTOR_SIZE, partitions); - flipPartition(partitions, FALSE); - - if(partition >= 0) { - ((DMG*)toReturn->data)->offset = partitions[partition].pmPyPartStart * SECTOR_SIZE; - } else { - for(i = 0; i < numPartitions; i++) { - if(strcmp((char*)partitions[i].pmParType, "Apple_HFSX") == 0 || strcmp((char*)partitions[i].pmParType, "Apple_HFS") == 0) { - ((DMG*)toReturn->data)->offset = partitions[i].pmPyPartStart * SECTOR_SIZE; - break; - } - } - } - - return toReturn; -} +/* + * dmgfile.c + * libdmg-hfsplus + */ + +#include +#include +#include + +#include "dmg.h" +#include "dmgfile.h" + +static void cacheRun(DMG* dmg, BLKXTable* blkx, int run) { + size_t bufferSize; + z_stream strm; + void* inBuffer; + int ret; + size_t have; + + if(dmg->runData) { + free(dmg->runData); + } + + bufferSize = SECTOR_SIZE * blkx->decompressBufferRequested; + + dmg->runData = (void*) malloc(bufferSize); + inBuffer = (void*) malloc(bufferSize); + memset(dmg->runData, 0, bufferSize); + + ASSERT(dmg->dmg->seek(dmg->dmg, blkx->dataStart + blkx->runs[run].compOffset) == 0, "fseeko"); + + switch(blkx->runs[run].type) { + case BLOCK_ZLIB: + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + + ASSERT(inflateInit(&strm) == Z_OK, "inflateInit"); + + ASSERT((strm.avail_in = dmg->dmg->read(dmg->dmg, inBuffer, blkx->runs[run].compLength)) == blkx->runs[run].compLength, "fread"); + strm.next_in = (unsigned char*) inBuffer; + + do { + strm.avail_out = bufferSize; + strm.next_out = (unsigned char*) dmg->runData; + ASSERT((ret = inflate(&strm, Z_NO_FLUSH)) != Z_STREAM_ERROR, "inflate/Z_STREAM_ERROR"); + if(ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_STREAM_END) { + ASSERT(FALSE, "inflate"); + } + have = bufferSize - strm.avail_out; + } while (strm.avail_out == 0); + + ASSERT(inflateEnd(&strm) == Z_OK, "inflateEnd"); + break; + case BLOCK_RAW: + ASSERT((have = dmg->dmg->read(dmg->dmg, dmg->runData, blkx->runs[run].compLength)) == blkx->runs[run].compLength, "fread"); + break; + case BLOCK_IGNORE: + break; + case BLOCK_COMMENT: + break; + case BLOCK_TERMINATOR: + break; + default: + break; + } + + dmg->runStart = (blkx->runs[run].sectorStart + blkx->firstSectorNumber) * SECTOR_SIZE; + dmg->runEnd = dmg->runStart + (blkx->runs[run].sectorCount * SECTOR_SIZE); +} + +static void cacheOffset(DMG* dmg, off_t location) { + int i; + int j; + uint64_t sector; + + sector = (uint64_t)(location / SECTOR_SIZE); + + for(i = 0; i < dmg->numBLKX; i++) { + if(sector >= dmg->blkx[i]->firstSectorNumber && sector < (dmg->blkx[i]->firstSectorNumber + dmg->blkx[i]->sectorCount)) { + for(j = 0; j < dmg->blkx[i]->blocksRunCount; j++) { + if(sector >= (dmg->blkx[i]->firstSectorNumber + dmg->blkx[i]->runs[j].sectorStart) && + sector < (dmg->blkx[i]->firstSectorNumber + dmg->blkx[i]->runs[j].sectorStart + dmg->blkx[i]->runs[j].sectorCount)) { + cacheRun(dmg, dmg->blkx[i], j); + } + } + } + } +} + +static int dmgFileRead(io_func* io, off_t location, size_t size, void *buffer) { + DMG* dmg; + size_t toRead; + + dmg = (DMG*) io->data; + + location += dmg->offset; + + if(size == 0) { + return TRUE; + } + + if(location < dmg->runStart || location >= dmg->runEnd) { + cacheOffset(dmg, location); + } + + if((location + size) > dmg->runEnd) { + toRead = dmg->runEnd - location; + } else { + toRead = size; + } + + memcpy(buffer, (void*)((uint8_t*)dmg->runData + (uint32_t)(location - dmg->runStart)), toRead); + size -= toRead; + location += toRead; + buffer = (void*)((uint8_t*)buffer + toRead); + + if(size > 0) { + return dmgFileRead(io, location, size, buffer); + } else { + return TRUE; + } +} + +static int dmgFileWrite(io_func* io, off_t location, size_t size, void *buffer) { + fprintf(stderr, "Error: writing to DMGs is not supported (impossible to achieve with compressed images and retain asr multicast ordering).\n"); + return FALSE; +} + + +static void closeDmgFile(io_func* io) { + DMG* dmg; + + dmg = (DMG*) io->data; + + if(dmg->runData) { + free(dmg->runData); + } + + free(dmg->blkx); + releaseResources(dmg->resources); + dmg->dmg->close(dmg->dmg); + free(dmg); + free(io); +} + +io_func* openDmgFile(AbstractFile* abstractIn) { + off_t fileLength; + UDIFResourceFile resourceFile; + DMG* dmg; + ResourceData* blkx; + ResourceData* curData; + int i; + + io_func* toReturn; + + if(abstractIn == NULL) { + return NULL; + } + + fileLength = abstractIn->getLength(abstractIn); + abstractIn->seek(abstractIn, fileLength - sizeof(UDIFResourceFile)); + readUDIFResourceFile(abstractIn, &resourceFile); + + dmg = (DMG*) malloc(sizeof(DMG)); + dmg->dmg = abstractIn; + dmg->resources = readResources(abstractIn, &resourceFile); + dmg->numBLKX = 0; + + blkx = (getResourceByKey(dmg->resources, "blkx"))->data; + + curData = blkx; + while(curData != NULL) { + dmg->numBLKX++; + curData = curData->next; + } + + dmg->blkx = (BLKXTable**) malloc(sizeof(BLKXTable*) * dmg->numBLKX); + + i = 0; + while(blkx != NULL) { + dmg->blkx[i] = (BLKXTable*)(blkx->data); + i++; + blkx = blkx->next; + } + + dmg->offset = 0; + + dmg->runData = NULL; + cacheOffset(dmg, 0); + + toReturn = (io_func*) malloc(sizeof(io_func)); + + toReturn->data = dmg; + toReturn->read = &dmgFileRead; + toReturn->write = &dmgFileWrite; + toReturn->close = &closeDmgFile; + + return toReturn; +} + +io_func* openDmgFilePartition(AbstractFile* abstractIn, int partition) { + io_func* toReturn; + Partition* partitions; + int numPartitions; + int i; + + toReturn = openDmgFile(abstractIn); + + if(toReturn == NULL) { + return NULL; + } + + partitions = (Partition*) malloc(sizeof(Partition)); + toReturn->read(toReturn, SECTOR_SIZE, SECTOR_SIZE, partitions); + flipPartitionMultiple(partitions, FALSE, FALSE); + numPartitions = partitions->pmMapBlkCnt; + partitions = (Partition*) realloc(partitions, numPartitions * SECTOR_SIZE); + toReturn->read(toReturn, SECTOR_SIZE, numPartitions * SECTOR_SIZE, partitions); + flipPartition(partitions, FALSE); + + if(partition >= 0) { + ((DMG*)toReturn->data)->offset = partitions[partition].pmPyPartStart * SECTOR_SIZE; + } else { + for(i = 0; i < numPartitions; i++) { + if(strcmp((char*)partitions[i].pmParType, "Apple_HFSX") == 0 || strcmp((char*)partitions[i].pmParType, "Apple_HFS") == 0) { + ((DMG*)toReturn->data)->offset = partitions[i].pmPyPartStart * SECTOR_SIZE; + break; + } + } + } + + return toReturn; +} diff --git a/dmg/dmgfile.h b/dmg/dmgfile.h index 6af3d96..9f658b3 100644 --- a/dmg/dmgfile.h +++ b/dmg/dmgfile.h @@ -1,22 +1,22 @@ -/* - * dmgfile.h - * libdmg-hfsplus - * - */ - -#include "../hfs/common.h" -#include "dmg.h" - -io_func* openDmgFile(AbstractFile* dmg); -io_func* openDmgFilePartition(AbstractFile* dmg, int partition); - -typedef struct DMG { - AbstractFile* dmg; - ResourceKey* resources; - uint32_t numBLKX; - BLKXTable** blkx; - void* runData; - uint64_t runStart; - uint64_t runEnd; - uint64_t offset; -} DMG; +/* + * dmgfile.h + * libdmg-hfsplus + * + */ + +#include "../hfs/common.h" +#include "dmg.h" + +io_func* openDmgFile(AbstractFile* dmg); +io_func* openDmgFilePartition(AbstractFile* dmg, int partition); + +typedef struct DMG { + AbstractFile* dmg; + ResourceKey* resources; + uint32_t numBLKX; + BLKXTable** blkx; + void* runData; + uint64_t runStart; + uint64_t runEnd; + uint64_t offset; +} DMG; diff --git a/dmg/dmglib.c b/dmg/dmglib.c index 2726773..9f19eff 100644 --- a/dmg/dmglib.c +++ b/dmg/dmglib.c @@ -5,504 +5,504 @@ uint32_t calculateMasterChecksum(ResourceKey* resources); -int extractDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, int partNum) { - off_t fileLength; - UDIFResourceFile resourceFile; - ResourceKey* resources; - ResourceData* blkxData; - - fileLength = abstractIn->getLength(abstractIn); - abstractIn->seek(abstractIn, fileLength - sizeof(UDIFResourceFile)); - readUDIFResourceFile(abstractIn, &resourceFile); - resources = readResources(abstractIn, &resourceFile); - - printf("Writing out data..\n"); fflush(stdout); - - /* reasonable assumption that 2 is the main partition, given that that's usually the case in SPUD layouts */ - if(partNum < 0) { - blkxData = getResourceByKey(resources, "blkx")->data; - while(blkxData != NULL) { - if(strstr(blkxData->name, "Apple_HFS") != NULL) { - break; - } - blkxData = blkxData->next; - } - } else { - blkxData = getDataByID(getResourceByKey(resources, "blkx"), partNum); - } - - if(blkxData) { - extractBLKX(abstractIn, abstractOut, (BLKXTable*)(blkxData->data)); - } else { - printf("BLKX not found!\n"); fflush(stdout); - } - abstractOut->close(abstractOut); - - releaseResources(resources); - abstractIn->close(abstractIn); - - return TRUE; -} - -uint32_t calculateMasterChecksum(ResourceKey* resources) { - ResourceKey* blkxKeys; - ResourceData* data; - BLKXTable* blkx; - unsigned char* buffer; - int blkxNum; - uint32_t result; - - blkxKeys = getResourceByKey(resources, "blkx"); - - data = blkxKeys->data; - blkxNum = 0; - while(data != NULL) { - blkx = (BLKXTable*) data->data; - if(blkx->checksum.type == CHECKSUM_CRC32) { - blkxNum++; - } - data = data->next; - } - - buffer = (unsigned char*) malloc(4 * blkxNum) ; - data = blkxKeys->data; - blkxNum = 0; - while(data != NULL) { - blkx = (BLKXTable*) data->data; - if(blkx->checksum.type == CHECKSUM_CRC32) { - buffer[(blkxNum * 4) + 0] = (blkx->checksum.data[0] >> 24) & 0xff; - buffer[(blkxNum * 4) + 1] = (blkx->checksum.data[0] >> 16) & 0xff; - buffer[(blkxNum * 4) + 2] = (blkx->checksum.data[0] >> 8) & 0xff; - buffer[(blkxNum * 4) + 3] = (blkx->checksum.data[0] >> 0) & 0xff; - blkxNum++; - } - data = data->next; - } - - result = 0; - CRC32Checksum(&result, (const unsigned char*) buffer, 4 * blkxNum); - free(buffer); - return result; -} - -int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut) { - 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; - - off_t plistOffset; - uint32_t plistSize; - uint32_t dataForkChecksum; - - io = IOFuncFromAbstractFile(abstractIn); - volume = openVolume(io); - 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)); - - printf("Creating and writing DDM and partition map...\n"); fflush(stdout); - - DDM = createDriverDescriptorMap((volumeHeader->totalBlocks * volumeHeader->blockSize)/SECTOR_SIZE); - - partitions = createApplePartitionMap((volumeHeader->totalBlocks * volumeHeader->blockSize)/SECTOR_SIZE, HFSX_VOLUME_TYPE); - - writeDriverDescriptorMap(abstractOut, DDM, &CRCProxy, (void*) (&dataForkToken), &resources); - free(DDM); - writeApplePartitionMap(abstractOut, partitions, &CRCProxy, (void*) (&dataForkToken), &resources, &nsiz); - free(partitions); - writeATAPI(abstractOut, &CRCProxy, (void*) (&dataForkToken), &resources, &nsiz); - - memset(&uncompressedToken, 0, sizeof(uncompressedToken)); - SHA1Init(&(uncompressedToken.sha1)); - - printf("Writing main data blkx...\n"); fflush(stdout); - - abstractIn->seek(abstractIn, 0); - blkx = insertBLKX(abstractOut, abstractIn, USER_OFFSET, (volumeHeader->totalBlocks * volumeHeader->blockSize)/SECTOR_SIZE, - 2, CHECKSUM_CRC32, &BlockSHA1CRC, &uncompressedToken, &CRCProxy, &dataForkToken, volume); - - blkx->checksum.data[0] = uncompressedToken.crc; - printf("Inserting main blkx...\n"); fflush(stdout); - - resources = insertData(resources, "blkx", 2, "Mac_OS_X (Apple_HFSX : 3)", (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, "", (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 { - myNSiz->next = nsiz->next; - nsiz->next = myNSiz; - } - - printf("Writing free partition...\n"); fflush(stdout); - - writeFreePartition(abstractOut, (volumeHeader->totalBlocks * volumeHeader->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(); - curResource = curResource->next; - - curResource->next = makeSize(volumeHeader); - curResource = curResource->next; - - plistOffset = abstractOut->tell(abstractOut); - writeResources(abstractOut, resources); - 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_CRC32; - koly.fUDIFDataForkChecksum.size = 0x20; - koly.fUDIFDataForkChecksum.data[0] = dataForkChecksum; - koly.fUDIFXMLOffset = plistOffset; - koly.fUDIFXMLLength = plistSize; - memset(&(koly.reserved1), 0, 0x78); - - koly.fUDIFMasterChecksum.type = CHECKSUM_CRC32; - koly.fUDIFMasterChecksum.size = 0x20; - koly.fUDIFMasterChecksum.data[0] = calculateMasterChecksum(resources); - printf("Master checksum: %x\n", koly.fUDIFMasterChecksum.data[0]); fflush(stdout); - - koly.fUDIFImageVariant = kUDIFDeviceImageType; - koly.fUDIFSectorCount = EXTRA_SIZE + (volumeHeader->totalBlocks * volumeHeader->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; -} - -int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut) { - Partition* partitions; - DriverDescriptorRecord* DDM; - int i; - - BLKXTable* blkx; - ResourceKey* resources; - ResourceKey* curResource; - - ChecksumToken dataForkToken; - ChecksumToken uncompressedToken; - - NSizResource* nsiz; - NSizResource* myNSiz; - CSumResource csum; - - off_t plistOffset; - uint32_t plistSize; - uint32_t dataForkChecksum; - uint64_t numSectors; - - UDIFResourceFile koly; - - char partitionName[512]; - - off_t fileLength; - size_t partitionTableSize; - - - numSectors = 0; - - resources = NULL; - nsiz = NULL; - myNSiz = NULL; - memset(&dataForkToken, 0, sizeof(ChecksumToken)); - - partitions = (Partition*) malloc(SECTOR_SIZE); - - printf("Processing DDM...\n"); fflush(stdout); - DDM = (DriverDescriptorRecord*) malloc(SECTOR_SIZE); - abstractIn->seek(abstractIn, 0); - ASSERT(abstractIn->read(abstractIn, DDM, SECTOR_SIZE) == SECTOR_SIZE, "fread"); - flipDriverDescriptorRecord(DDM, FALSE); - - if(DDM->sbSig == DRIVER_DESCRIPTOR_SIGNATURE) { - writeDriverDescriptorMap(abstractOut, DDM, &CRCProxy, (void*) (&dataForkToken), &resources); - free(DDM); - - printf("Processing partition map...\n"); fflush(stdout); - - abstractIn->seek(abstractIn, SECTOR_SIZE); - ASSERT(abstractIn->read(abstractIn, partitions, SECTOR_SIZE) == SECTOR_SIZE, "fread"); - flipPartitionMultiple(partitions, FALSE, FALSE); - - partitionTableSize = SECTOR_SIZE * partitions->pmMapBlkCnt; - partitions = (Partition*) realloc(partitions, partitionTableSize); - - abstractIn->seek(abstractIn, SECTOR_SIZE); - ASSERT(abstractIn->read(abstractIn, partitions, partitionTableSize) == partitionTableSize, "fread"); - flipPartition(partitions, FALSE); - - printf("Writing blkx (%d)...\n", partitions->pmMapBlkCnt); fflush(stdout); - - for(i = 0; i < partitions->pmMapBlkCnt; i++) { - if(partitions[i].pmSig != APPLE_PARTITION_MAP_SIGNATURE) { - break; - } - - printf("Processing blkx %d, total %d...\n", i, partitions->pmMapBlkCnt); fflush(stdout); - - sprintf(partitionName, "%s (%s : %d)", partitions[i].pmPartName, partitions[i].pmParType, i + 1); - - memset(&uncompressedToken, 0, sizeof(uncompressedToken)); - - abstractIn->seek(abstractIn, partitions[i].pmPyPartStart * SECTOR_SIZE); - blkx = insertBLKX(abstractOut, abstractIn, partitions[i].pmPyPartStart, partitions[i].pmPartBlkCnt, i, CHECKSUM_CRC32, - &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; - } - } - - koly.fUDIFImageVariant = kUDIFDeviceImageType; - } else { - printf("No DDM! Just doing one huge blkx then...\n"); fflush(stdout); - - fileLength = abstractIn->getLength(abstractIn); - - memset(&uncompressedToken, 0, sizeof(uncompressedToken)); - - abstractIn->seek(abstractIn, 0); - blkx = insertBLKX(abstractOut, abstractIn, 0, fileLength/SECTOR_SIZE, ENTIRE_DEVICE_DESCRIPTOR, CHECKSUM_CRC32, - &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); - free(blkx); - - memset(&csum, 0, sizeof(CSumResource)); - csum.version = 1; - csum.type = CHECKSUM_MKBLOCK; - csum.checksum = uncompressedToken.block; - resources = insertData(resources, "cSum", 0, "", (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 = 0; - myNSiz->version = 6; - myNSiz->next = NULL; - - koly.fUDIFImageVariant = kUDIFPartitionImageType; - } - - 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(); - curResource = curResource->next; - - plistOffset = abstractOut->tell(abstractOut); - writeResources(abstractOut, resources); - 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_CRC32; - koly.fUDIFDataForkChecksum.size = 0x20; - koly.fUDIFDataForkChecksum.data[0] = dataForkChecksum; - koly.fUDIFXMLOffset = plistOffset; - koly.fUDIFXMLLength = plistSize; - memset(&(koly.reserved1), 0, 0x78); - - koly.fUDIFMasterChecksum.type = CHECKSUM_CRC32; - koly.fUDIFMasterChecksum.size = 0x20; - koly.fUDIFMasterChecksum.data[0] = calculateMasterChecksum(resources); - printf("Master checksum: %x\n", koly.fUDIFMasterChecksum.data[0]); fflush(stdout); - - koly.fUDIFSectorCount = numSectors; - 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); - - abstractIn->close(abstractIn); - free(partitions); - - printf("Done\n"); fflush(stdout); - - abstractOut->close(abstractOut); - - return TRUE; -} - -int convertToISO(AbstractFile* abstractIn, AbstractFile* abstractOut) { - off_t fileLength; - UDIFResourceFile resourceFile; - ResourceKey* resources; - ResourceData* blkx; - BLKXTable* blkxTable; - - fileLength = abstractIn->getLength(abstractIn); - abstractIn->seek(abstractIn, fileLength - sizeof(UDIFResourceFile)); - readUDIFResourceFile(abstractIn, &resourceFile); - resources = readResources(abstractIn, &resourceFile); - - blkx = (getResourceByKey(resources, "blkx"))->data; - - printf("Writing out data..\n"); fflush(stdout); - - while(blkx != NULL) { - blkxTable = (BLKXTable*)(blkx->data); - abstractOut->seek(abstractOut, blkxTable->firstSectorNumber * 512); - extractBLKX(abstractIn, abstractOut, blkxTable); - blkx = blkx->next; - } - - abstractOut->close(abstractOut); - - releaseResources(resources); - abstractIn->close(abstractIn); - - return TRUE; - +int extractDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, int partNum) { + off_t fileLength; + UDIFResourceFile resourceFile; + ResourceKey* resources; + ResourceData* blkxData; + + fileLength = abstractIn->getLength(abstractIn); + abstractIn->seek(abstractIn, fileLength - sizeof(UDIFResourceFile)); + readUDIFResourceFile(abstractIn, &resourceFile); + resources = readResources(abstractIn, &resourceFile); + + printf("Writing out data..\n"); fflush(stdout); + + /* reasonable assumption that 2 is the main partition, given that that's usually the case in SPUD layouts */ + if(partNum < 0) { + blkxData = getResourceByKey(resources, "blkx")->data; + while(blkxData != NULL) { + if(strstr(blkxData->name, "Apple_HFS") != NULL) { + break; + } + blkxData = blkxData->next; + } + } else { + blkxData = getDataByID(getResourceByKey(resources, "blkx"), partNum); + } + + if(blkxData) { + extractBLKX(abstractIn, abstractOut, (BLKXTable*)(blkxData->data)); + } else { + printf("BLKX not found!\n"); fflush(stdout); + } + abstractOut->close(abstractOut); + + releaseResources(resources); + abstractIn->close(abstractIn); + + return TRUE; +} + +uint32_t calculateMasterChecksum(ResourceKey* resources) { + ResourceKey* blkxKeys; + ResourceData* data; + BLKXTable* blkx; + unsigned char* buffer; + int blkxNum; + uint32_t result; + + blkxKeys = getResourceByKey(resources, "blkx"); + + data = blkxKeys->data; + blkxNum = 0; + while(data != NULL) { + blkx = (BLKXTable*) data->data; + if(blkx->checksum.type == CHECKSUM_CRC32) { + blkxNum++; + } + data = data->next; + } + + buffer = (unsigned char*) malloc(4 * blkxNum) ; + data = blkxKeys->data; + blkxNum = 0; + while(data != NULL) { + blkx = (BLKXTable*) data->data; + if(blkx->checksum.type == CHECKSUM_CRC32) { + buffer[(blkxNum * 4) + 0] = (blkx->checksum.data[0] >> 24) & 0xff; + buffer[(blkxNum * 4) + 1] = (blkx->checksum.data[0] >> 16) & 0xff; + buffer[(blkxNum * 4) + 2] = (blkx->checksum.data[0] >> 8) & 0xff; + buffer[(blkxNum * 4) + 3] = (blkx->checksum.data[0] >> 0) & 0xff; + blkxNum++; + } + data = data->next; + } + + result = 0; + CRC32Checksum(&result, (const unsigned char*) buffer, 4 * blkxNum); + free(buffer); + return result; +} + +int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut) { + 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; + + off_t plistOffset; + uint32_t plistSize; + uint32_t dataForkChecksum; + + io = IOFuncFromAbstractFile(abstractIn); + volume = openVolume(io); + 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)); + + printf("Creating and writing DDM and partition map...\n"); fflush(stdout); + + DDM = createDriverDescriptorMap((volumeHeader->totalBlocks * volumeHeader->blockSize)/SECTOR_SIZE); + + partitions = createApplePartitionMap((volumeHeader->totalBlocks * volumeHeader->blockSize)/SECTOR_SIZE, HFSX_VOLUME_TYPE); + + writeDriverDescriptorMap(abstractOut, DDM, &CRCProxy, (void*) (&dataForkToken), &resources); + free(DDM); + writeApplePartitionMap(abstractOut, partitions, &CRCProxy, (void*) (&dataForkToken), &resources, &nsiz); + free(partitions); + writeATAPI(abstractOut, &CRCProxy, (void*) (&dataForkToken), &resources, &nsiz); + + memset(&uncompressedToken, 0, sizeof(uncompressedToken)); + SHA1Init(&(uncompressedToken.sha1)); + + printf("Writing main data blkx...\n"); fflush(stdout); + + abstractIn->seek(abstractIn, 0); + blkx = insertBLKX(abstractOut, abstractIn, USER_OFFSET, (volumeHeader->totalBlocks * volumeHeader->blockSize)/SECTOR_SIZE, + 2, CHECKSUM_CRC32, &BlockSHA1CRC, &uncompressedToken, &CRCProxy, &dataForkToken, volume); + + blkx->checksum.data[0] = uncompressedToken.crc; + printf("Inserting main blkx...\n"); fflush(stdout); + + resources = insertData(resources, "blkx", 2, "Mac_OS_X (Apple_HFSX : 3)", (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, "", (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 { + myNSiz->next = nsiz->next; + nsiz->next = myNSiz; + } + + printf("Writing free partition...\n"); fflush(stdout); + + writeFreePartition(abstractOut, (volumeHeader->totalBlocks * volumeHeader->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(); + curResource = curResource->next; + + curResource->next = makeSize(volumeHeader); + curResource = curResource->next; + + plistOffset = abstractOut->tell(abstractOut); + writeResources(abstractOut, resources); + 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_CRC32; + koly.fUDIFDataForkChecksum.size = 0x20; + koly.fUDIFDataForkChecksum.data[0] = dataForkChecksum; + koly.fUDIFXMLOffset = plistOffset; + koly.fUDIFXMLLength = plistSize; + memset(&(koly.reserved1), 0, 0x78); + + koly.fUDIFMasterChecksum.type = CHECKSUM_CRC32; + koly.fUDIFMasterChecksum.size = 0x20; + koly.fUDIFMasterChecksum.data[0] = calculateMasterChecksum(resources); + printf("Master checksum: %x\n", koly.fUDIFMasterChecksum.data[0]); fflush(stdout); + + koly.fUDIFImageVariant = kUDIFDeviceImageType; + koly.fUDIFSectorCount = EXTRA_SIZE + (volumeHeader->totalBlocks * volumeHeader->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; +} + +int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut) { + Partition* partitions; + DriverDescriptorRecord* DDM; + int i; + + BLKXTable* blkx; + ResourceKey* resources; + ResourceKey* curResource; + + ChecksumToken dataForkToken; + ChecksumToken uncompressedToken; + + NSizResource* nsiz; + NSizResource* myNSiz; + CSumResource csum; + + off_t plistOffset; + uint32_t plistSize; + uint32_t dataForkChecksum; + uint64_t numSectors; + + UDIFResourceFile koly; + + char partitionName[512]; + + off_t fileLength; + size_t partitionTableSize; + + + numSectors = 0; + + resources = NULL; + nsiz = NULL; + myNSiz = NULL; + memset(&dataForkToken, 0, sizeof(ChecksumToken)); + + partitions = (Partition*) malloc(SECTOR_SIZE); + + printf("Processing DDM...\n"); fflush(stdout); + DDM = (DriverDescriptorRecord*) malloc(SECTOR_SIZE); + abstractIn->seek(abstractIn, 0); + ASSERT(abstractIn->read(abstractIn, DDM, SECTOR_SIZE) == SECTOR_SIZE, "fread"); + flipDriverDescriptorRecord(DDM, FALSE); + + if(DDM->sbSig == DRIVER_DESCRIPTOR_SIGNATURE) { + writeDriverDescriptorMap(abstractOut, DDM, &CRCProxy, (void*) (&dataForkToken), &resources); + free(DDM); + + printf("Processing partition map...\n"); fflush(stdout); + + abstractIn->seek(abstractIn, SECTOR_SIZE); + ASSERT(abstractIn->read(abstractIn, partitions, SECTOR_SIZE) == SECTOR_SIZE, "fread"); + flipPartitionMultiple(partitions, FALSE, FALSE); + + partitionTableSize = SECTOR_SIZE * partitions->pmMapBlkCnt; + partitions = (Partition*) realloc(partitions, partitionTableSize); + + abstractIn->seek(abstractIn, SECTOR_SIZE); + ASSERT(abstractIn->read(abstractIn, partitions, partitionTableSize) == partitionTableSize, "fread"); + flipPartition(partitions, FALSE); + + printf("Writing blkx (%d)...\n", partitions->pmMapBlkCnt); fflush(stdout); + + for(i = 0; i < partitions->pmMapBlkCnt; i++) { + if(partitions[i].pmSig != APPLE_PARTITION_MAP_SIGNATURE) { + break; + } + + printf("Processing blkx %d, total %d...\n", i, partitions->pmMapBlkCnt); fflush(stdout); + + sprintf(partitionName, "%s (%s : %d)", partitions[i].pmPartName, partitions[i].pmParType, i + 1); + + memset(&uncompressedToken, 0, sizeof(uncompressedToken)); + + abstractIn->seek(abstractIn, partitions[i].pmPyPartStart * SECTOR_SIZE); + blkx = insertBLKX(abstractOut, abstractIn, partitions[i].pmPyPartStart, partitions[i].pmPartBlkCnt, i, CHECKSUM_CRC32, + &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; + } + } + + koly.fUDIFImageVariant = kUDIFDeviceImageType; + } else { + printf("No DDM! Just doing one huge blkx then...\n"); fflush(stdout); + + fileLength = abstractIn->getLength(abstractIn); + + memset(&uncompressedToken, 0, sizeof(uncompressedToken)); + + abstractIn->seek(abstractIn, 0); + blkx = insertBLKX(abstractOut, abstractIn, 0, fileLength/SECTOR_SIZE, ENTIRE_DEVICE_DESCRIPTOR, CHECKSUM_CRC32, + &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); + free(blkx); + + memset(&csum, 0, sizeof(CSumResource)); + csum.version = 1; + csum.type = CHECKSUM_MKBLOCK; + csum.checksum = uncompressedToken.block; + resources = insertData(resources, "cSum", 0, "", (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 = 0; + myNSiz->version = 6; + myNSiz->next = NULL; + + koly.fUDIFImageVariant = kUDIFPartitionImageType; + } + + 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(); + curResource = curResource->next; + + plistOffset = abstractOut->tell(abstractOut); + writeResources(abstractOut, resources); + 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_CRC32; + koly.fUDIFDataForkChecksum.size = 0x20; + koly.fUDIFDataForkChecksum.data[0] = dataForkChecksum; + koly.fUDIFXMLOffset = plistOffset; + koly.fUDIFXMLLength = plistSize; + memset(&(koly.reserved1), 0, 0x78); + + koly.fUDIFMasterChecksum.type = CHECKSUM_CRC32; + koly.fUDIFMasterChecksum.size = 0x20; + koly.fUDIFMasterChecksum.data[0] = calculateMasterChecksum(resources); + printf("Master checksum: %x\n", koly.fUDIFMasterChecksum.data[0]); fflush(stdout); + + koly.fUDIFSectorCount = numSectors; + 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); + + abstractIn->close(abstractIn); + free(partitions); + + printf("Done\n"); fflush(stdout); + + abstractOut->close(abstractOut); + + return TRUE; +} + +int convertToISO(AbstractFile* abstractIn, AbstractFile* abstractOut) { + off_t fileLength; + UDIFResourceFile resourceFile; + ResourceKey* resources; + ResourceData* blkx; + BLKXTable* blkxTable; + + fileLength = abstractIn->getLength(abstractIn); + abstractIn->seek(abstractIn, fileLength - sizeof(UDIFResourceFile)); + readUDIFResourceFile(abstractIn, &resourceFile); + resources = readResources(abstractIn, &resourceFile); + + blkx = (getResourceByKey(resources, "blkx"))->data; + + printf("Writing out data..\n"); fflush(stdout); + + while(blkx != NULL) { + blkxTable = (BLKXTable*)(blkx->data); + abstractOut->seek(abstractOut, blkxTable->firstSectorNumber * 512); + extractBLKX(abstractIn, abstractOut, blkxTable); + blkx = blkx->next; + } + + abstractOut->close(abstractOut); + + releaseResources(resources); + abstractIn->close(abstractIn); + + return TRUE; + } diff --git a/dmg/dmglib.h b/dmg/dmglib.h index 49ba80c..39d265a 100644 --- a/dmg/dmglib.h +++ b/dmg/dmglib.h @@ -1,4 +1,4 @@ -#ifndef DMGLIB_H +#ifndef DMGLIB_H #define DMGLIB_H #include "dmg.h" @@ -6,7 +6,7 @@ #ifdef __cplusplus extern "C" { -#endif +#endif int extractDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, int partNum); int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut); @@ -15,5 +15,5 @@ extern "C" { #ifdef __cplusplus } #endif - -#endif + +#endif diff --git a/dmg/filevault.c b/dmg/filevault.c index 3db9401..37482df 100644 --- a/dmg/filevault.c +++ b/dmg/filevault.c @@ -1,263 +1,263 @@ -#include -#include -#include - -#include "dmg.h" -#include "filevault.h" - -#ifdef HAVE_CRYPT - -#include -#include -#include - -#define CHUNKNO(oft, info) ((uint32_t)((oft)/info->blockSize)) -#define CHUNKOFFSET(oft, info) ((size_t)((oft) - ((off_t)(CHUNKNO(oft, info)) * (off_t)info->blockSize))) - -static void flipFileVaultV2Header(FileVaultV2Header* header) { - FLIPENDIAN(header->signature); - FLIPENDIAN(header->version); - FLIPENDIAN(header->encIVSize); - FLIPENDIAN(header->unk1); - FLIPENDIAN(header->unk2); - FLIPENDIAN(header->unk3); - FLIPENDIAN(header->unk4); - FLIPENDIAN(header->unk5); - FLIPENDIAN(header->unk5); - - FLIPENDIAN(header->blockSize); - FLIPENDIAN(header->dataSize); - FLIPENDIAN(header->dataOffset); - FLIPENDIAN(header->kdfAlgorithm); - FLIPENDIAN(header->kdfPRNGAlgorithm); - FLIPENDIAN(header->kdfIterationCount); - FLIPENDIAN(header->kdfSaltLen); - FLIPENDIAN(header->blobEncIVSize); - FLIPENDIAN(header->blobEncKeyBits); - FLIPENDIAN(header->blobEncAlgorithm); - FLIPENDIAN(header->blobEncPadding); - FLIPENDIAN(header->blobEncMode); - FLIPENDIAN(header->encryptedKeyblobSize); -} - -static void writeChunk(FileVaultInfo* info) { - unsigned char buffer[info->blockSize]; - unsigned char buffer2[info->blockSize]; - unsigned char msgDigest[FILEVAULT_MSGDGST_LENGTH]; - uint32_t msgDigestLen; - uint32_t myChunk; - - myChunk = info->curChunk; - - FLIPENDIAN(myChunk); - HMAC_Init_ex(&(info->hmacCTX), NULL, 0, NULL, NULL); - HMAC_Update(&(info->hmacCTX), (unsigned char *) &myChunk, sizeof(uint32_t)); - HMAC_Final(&(info->hmacCTX), msgDigest, &msgDigestLen); - - AES_cbc_encrypt(info->chunk, buffer, info->blockSize, &(info->aesEncKey), msgDigest, AES_ENCRYPT); - - info->file->seek(info->file, (info->curChunk * info->blockSize) + info->dataOffset); - info->file->read(info->file, buffer2, info->blockSize); - - info->file->seek(info->file, (info->curChunk * info->blockSize) + info->dataOffset); - info->file->write(info->file, buffer, info->blockSize); - - info->dirty = FALSE; -} - -static void cacheChunk(FileVaultInfo* info, uint32_t chunk) { - unsigned char buffer[info->blockSize]; - unsigned char msgDigest[FILEVAULT_MSGDGST_LENGTH]; - uint32_t msgDigestLen; - - if(chunk == info->curChunk) { - return; - } - - if(info->dirty) { - writeChunk(info); - } - - info->file->seek(info->file, chunk * info->blockSize + info->dataOffset); - info->file->read(info->file, buffer, info->blockSize); - - info->curChunk = chunk; - - FLIPENDIAN(chunk); - HMAC_Init_ex(&(info->hmacCTX), NULL, 0, NULL, NULL); - HMAC_Update(&(info->hmacCTX), (unsigned char *) &chunk, sizeof(uint32_t)); - HMAC_Final(&(info->hmacCTX), msgDigest, &msgDigestLen); - - AES_cbc_encrypt(buffer, info->chunk, info->blockSize, &(info->aesKey), msgDigest, AES_DECRYPT); -} - -size_t fvRead(AbstractFile* file, void* data, size_t len) { - FileVaultInfo* info; - size_t toRead; - - info = (FileVaultInfo*) (file->data); - - if((CHUNKOFFSET(info->offset, info) + len) > info->blockSize) { - toRead = info->blockSize - CHUNKOFFSET(info->offset, info); - memcpy(data, (void *)((uint8_t*)(&(info->chunk)) + CHUNKOFFSET(info->offset, info)), toRead); - info->offset += toRead; - cacheChunk(info, CHUNKNO(info->offset, info)); - return toRead + fvRead(file, (void *)((uint8_t*)data + toRead), len - toRead); - } else { - toRead = len; - memcpy(data, (void *)((uint8_t*)(&(info->chunk)) + CHUNKOFFSET(info->offset, info)), toRead); - info->offset += toRead; - cacheChunk(info, CHUNKNO(info->offset, info)); - return toRead; - } -} - -size_t fvWrite(AbstractFile* file, const void* data, size_t len) { - FileVaultInfo* info; - size_t toRead; - int i; - - info = (FileVaultInfo*) (file->data); - - if(info->dataSize < (info->offset + len)) { - if(info->version == 2) { - info->header.v2.dataSize = info->offset + len; - } - info->headerDirty = TRUE; - } - - if((CHUNKOFFSET(info->offset, info) + len) > info->blockSize) { - toRead = info->blockSize - CHUNKOFFSET(info->offset, info); - for(i = 0; i < toRead; i++) { - ASSERT(*((char*)((uint8_t*)(&(info->chunk)) + (uint32_t)CHUNKOFFSET(info->offset, info) + i)) == ((char*)data)[i], "blah"); - } - memcpy((void *)((uint8_t*)(&(info->chunk)) + (uint32_t)CHUNKOFFSET(info->offset, info)), data, toRead); - info->dirty = TRUE; - info->offset += toRead; - cacheChunk(info, CHUNKNO(info->offset, info)); - return toRead + fvWrite(file, (void *)((uint8_t*)data + toRead), len - toRead); - } else { - toRead = len; - for(i = 0; i < toRead; i++) { - ASSERT(*((char*)((uint8_t*)(&(info->chunk)) + CHUNKOFFSET(info->offset, info) + i)) == ((char*)data)[i], "blah"); - } - memcpy((void *)((uint8_t*)(&(info->chunk)) + CHUNKOFFSET(info->offset, info)), data, toRead); - info->dirty = TRUE; - info->offset += toRead; - cacheChunk(info, CHUNKNO(info->offset, info)); - return toRead; - } -} - -int fvSeek(AbstractFile* file, off_t offset) { - FileVaultInfo* info = (FileVaultInfo*) (file->data); - info->offset = offset; - cacheChunk(info, CHUNKNO(offset, info)); - return 0; -} - -off_t fvTell(AbstractFile* file) { - FileVaultInfo* info = (FileVaultInfo*) (file->data); - return info->offset; -} - -off_t fvGetLength(AbstractFile* file) { - FileVaultInfo* info = (FileVaultInfo*) (file->data); - return info->dataSize; -} - -void fvClose(AbstractFile* file) { - FileVaultInfo* info = (FileVaultInfo*) (file->data); - - /* force a flush */ - if(info->curChunk == 0) { - cacheChunk(info, 1); - } else { - cacheChunk(info, 0); - } - - HMAC_CTX_cleanup(&(info->hmacCTX)); - - if(info->headerDirty) { - if(info->version == 2) { - file->seek(file, 0); - flipFileVaultV2Header(&(info->header.v2)); - file->write(file, &(info->header.v2), sizeof(FileVaultV2Header)); - } - } - - info->file->close(info->file); - free(info); - free(file); -} - -AbstractFile* createAbstractFileFromFileVault(AbstractFile* file, const char* key) { - FileVaultInfo* info; - AbstractFile* toReturn; - uint64_t signature; - uint8_t aesKey[16]; - uint8_t hmacKey[20]; - - int i; - - if(file == NULL) - return NULL; - - file->seek(file, 0); - file->read(file, &signature, sizeof(uint64_t)); - FLIPENDIAN(signature); - if(signature != FILEVAULT_V2_SIGNATURE) { - /* no FileVault v1 handling yet */ - return NULL; - } - - toReturn = (AbstractFile*) malloc(sizeof(AbstractFile)); - info = (FileVaultInfo*) malloc(sizeof(FileVaultInfo)); - - info->version = 2; - - file->seek(file, 0); - file->read(file, &(info->header.v2), sizeof(FileVaultV2Header)); - flipFileVaultV2Header(&(info->header.v2)); - - for(i = 0; i < 16; i++) { - sscanf(&(key[i * 2]), "%02hhx", &(aesKey[i])); - } - - for(i = 0; i < 20; i++) { - sscanf(&(key[(16 * 2) + i * 2]), "%02hhx", &(hmacKey[i])); - } - - HMAC_CTX_init(&(info->hmacCTX)); - HMAC_Init_ex(&(info->hmacCTX), hmacKey, sizeof(hmacKey), EVP_sha1(), NULL); - AES_set_decrypt_key(aesKey, FILEVAULT_CIPHER_KEY_LENGTH * 8, &(info->aesKey)); - AES_set_encrypt_key(aesKey, FILEVAULT_CIPHER_KEY_LENGTH * 8, &(info->aesEncKey)); - - info->dataOffset = info->header.v2.dataOffset; - info->dataSize = info->header.v2.dataSize; - info->blockSize = info->header.v2.blockSize; - info->offset = 0; - info->file = file; - - info->headerDirty = FALSE; - info->dirty = FALSE; - info->curChunk = 1; /* just to set it to a value not 0 */ - cacheChunk(info, 0); - - toReturn->data = info; - toReturn->read = fvRead; - toReturn->write = fvWrite; - toReturn->seek = fvSeek; - toReturn->tell = fvTell; - toReturn->getLength = fvGetLength; - toReturn->close = fvClose; - return toReturn; -} - -#else - -AbstractFile* createAbstractFileFromFileVault(AbstractFile* file, const char* key) { - return NULL; -} - -#endif +#include +#include +#include + +#include "dmg.h" +#include "filevault.h" + +#ifdef HAVE_CRYPT + +#include +#include +#include + +#define CHUNKNO(oft, info) ((uint32_t)((oft)/info->blockSize)) +#define CHUNKOFFSET(oft, info) ((size_t)((oft) - ((off_t)(CHUNKNO(oft, info)) * (off_t)info->blockSize))) + +static void flipFileVaultV2Header(FileVaultV2Header* header) { + FLIPENDIAN(header->signature); + FLIPENDIAN(header->version); + FLIPENDIAN(header->encIVSize); + FLIPENDIAN(header->unk1); + FLIPENDIAN(header->unk2); + FLIPENDIAN(header->unk3); + FLIPENDIAN(header->unk4); + FLIPENDIAN(header->unk5); + FLIPENDIAN(header->unk5); + + FLIPENDIAN(header->blockSize); + FLIPENDIAN(header->dataSize); + FLIPENDIAN(header->dataOffset); + FLIPENDIAN(header->kdfAlgorithm); + FLIPENDIAN(header->kdfPRNGAlgorithm); + FLIPENDIAN(header->kdfIterationCount); + FLIPENDIAN(header->kdfSaltLen); + FLIPENDIAN(header->blobEncIVSize); + FLIPENDIAN(header->blobEncKeyBits); + FLIPENDIAN(header->blobEncAlgorithm); + FLIPENDIAN(header->blobEncPadding); + FLIPENDIAN(header->blobEncMode); + FLIPENDIAN(header->encryptedKeyblobSize); +} + +static void writeChunk(FileVaultInfo* info) { + unsigned char buffer[info->blockSize]; + unsigned char buffer2[info->blockSize]; + unsigned char msgDigest[FILEVAULT_MSGDGST_LENGTH]; + uint32_t msgDigestLen; + uint32_t myChunk; + + myChunk = info->curChunk; + + FLIPENDIAN(myChunk); + HMAC_Init_ex(&(info->hmacCTX), NULL, 0, NULL, NULL); + HMAC_Update(&(info->hmacCTX), (unsigned char *) &myChunk, sizeof(uint32_t)); + HMAC_Final(&(info->hmacCTX), msgDigest, &msgDigestLen); + + AES_cbc_encrypt(info->chunk, buffer, info->blockSize, &(info->aesEncKey), msgDigest, AES_ENCRYPT); + + info->file->seek(info->file, (info->curChunk * info->blockSize) + info->dataOffset); + info->file->read(info->file, buffer2, info->blockSize); + + info->file->seek(info->file, (info->curChunk * info->blockSize) + info->dataOffset); + info->file->write(info->file, buffer, info->blockSize); + + info->dirty = FALSE; +} + +static void cacheChunk(FileVaultInfo* info, uint32_t chunk) { + unsigned char buffer[info->blockSize]; + unsigned char msgDigest[FILEVAULT_MSGDGST_LENGTH]; + uint32_t msgDigestLen; + + if(chunk == info->curChunk) { + return; + } + + if(info->dirty) { + writeChunk(info); + } + + info->file->seek(info->file, chunk * info->blockSize + info->dataOffset); + info->file->read(info->file, buffer, info->blockSize); + + info->curChunk = chunk; + + FLIPENDIAN(chunk); + HMAC_Init_ex(&(info->hmacCTX), NULL, 0, NULL, NULL); + HMAC_Update(&(info->hmacCTX), (unsigned char *) &chunk, sizeof(uint32_t)); + HMAC_Final(&(info->hmacCTX), msgDigest, &msgDigestLen); + + AES_cbc_encrypt(buffer, info->chunk, info->blockSize, &(info->aesKey), msgDigest, AES_DECRYPT); +} + +size_t fvRead(AbstractFile* file, void* data, size_t len) { + FileVaultInfo* info; + size_t toRead; + + info = (FileVaultInfo*) (file->data); + + if((CHUNKOFFSET(info->offset, info) + len) > info->blockSize) { + toRead = info->blockSize - CHUNKOFFSET(info->offset, info); + memcpy(data, (void *)((uint8_t*)(&(info->chunk)) + CHUNKOFFSET(info->offset, info)), toRead); + info->offset += toRead; + cacheChunk(info, CHUNKNO(info->offset, info)); + return toRead + fvRead(file, (void *)((uint8_t*)data + toRead), len - toRead); + } else { + toRead = len; + memcpy(data, (void *)((uint8_t*)(&(info->chunk)) + CHUNKOFFSET(info->offset, info)), toRead); + info->offset += toRead; + cacheChunk(info, CHUNKNO(info->offset, info)); + return toRead; + } +} + +size_t fvWrite(AbstractFile* file, const void* data, size_t len) { + FileVaultInfo* info; + size_t toRead; + int i; + + info = (FileVaultInfo*) (file->data); + + if(info->dataSize < (info->offset + len)) { + if(info->version == 2) { + info->header.v2.dataSize = info->offset + len; + } + info->headerDirty = TRUE; + } + + if((CHUNKOFFSET(info->offset, info) + len) > info->blockSize) { + toRead = info->blockSize - CHUNKOFFSET(info->offset, info); + for(i = 0; i < toRead; i++) { + ASSERT(*((char*)((uint8_t*)(&(info->chunk)) + (uint32_t)CHUNKOFFSET(info->offset, info) + i)) == ((char*)data)[i], "blah"); + } + memcpy((void *)((uint8_t*)(&(info->chunk)) + (uint32_t)CHUNKOFFSET(info->offset, info)), data, toRead); + info->dirty = TRUE; + info->offset += toRead; + cacheChunk(info, CHUNKNO(info->offset, info)); + return toRead + fvWrite(file, (void *)((uint8_t*)data + toRead), len - toRead); + } else { + toRead = len; + for(i = 0; i < toRead; i++) { + ASSERT(*((char*)((uint8_t*)(&(info->chunk)) + CHUNKOFFSET(info->offset, info) + i)) == ((char*)data)[i], "blah"); + } + memcpy((void *)((uint8_t*)(&(info->chunk)) + CHUNKOFFSET(info->offset, info)), data, toRead); + info->dirty = TRUE; + info->offset += toRead; + cacheChunk(info, CHUNKNO(info->offset, info)); + return toRead; + } +} + +int fvSeek(AbstractFile* file, off_t offset) { + FileVaultInfo* info = (FileVaultInfo*) (file->data); + info->offset = offset; + cacheChunk(info, CHUNKNO(offset, info)); + return 0; +} + +off_t fvTell(AbstractFile* file) { + FileVaultInfo* info = (FileVaultInfo*) (file->data); + return info->offset; +} + +off_t fvGetLength(AbstractFile* file) { + FileVaultInfo* info = (FileVaultInfo*) (file->data); + return info->dataSize; +} + +void fvClose(AbstractFile* file) { + FileVaultInfo* info = (FileVaultInfo*) (file->data); + + /* force a flush */ + if(info->curChunk == 0) { + cacheChunk(info, 1); + } else { + cacheChunk(info, 0); + } + + HMAC_CTX_cleanup(&(info->hmacCTX)); + + if(info->headerDirty) { + if(info->version == 2) { + file->seek(file, 0); + flipFileVaultV2Header(&(info->header.v2)); + file->write(file, &(info->header.v2), sizeof(FileVaultV2Header)); + } + } + + info->file->close(info->file); + free(info); + free(file); +} + +AbstractFile* createAbstractFileFromFileVault(AbstractFile* file, const char* key) { + FileVaultInfo* info; + AbstractFile* toReturn; + uint64_t signature; + uint8_t aesKey[16]; + uint8_t hmacKey[20]; + + int i; + + if(file == NULL) + return NULL; + + file->seek(file, 0); + file->read(file, &signature, sizeof(uint64_t)); + FLIPENDIAN(signature); + if(signature != FILEVAULT_V2_SIGNATURE) { + /* no FileVault v1 handling yet */ + return NULL; + } + + toReturn = (AbstractFile*) malloc(sizeof(AbstractFile)); + info = (FileVaultInfo*) malloc(sizeof(FileVaultInfo)); + + info->version = 2; + + file->seek(file, 0); + file->read(file, &(info->header.v2), sizeof(FileVaultV2Header)); + flipFileVaultV2Header(&(info->header.v2)); + + for(i = 0; i < 16; i++) { + sscanf(&(key[i * 2]), "%02hhx", &(aesKey[i])); + } + + for(i = 0; i < 20; i++) { + sscanf(&(key[(16 * 2) + i * 2]), "%02hhx", &(hmacKey[i])); + } + + HMAC_CTX_init(&(info->hmacCTX)); + HMAC_Init_ex(&(info->hmacCTX), hmacKey, sizeof(hmacKey), EVP_sha1(), NULL); + AES_set_decrypt_key(aesKey, FILEVAULT_CIPHER_KEY_LENGTH * 8, &(info->aesKey)); + AES_set_encrypt_key(aesKey, FILEVAULT_CIPHER_KEY_LENGTH * 8, &(info->aesEncKey)); + + info->dataOffset = info->header.v2.dataOffset; + info->dataSize = info->header.v2.dataSize; + info->blockSize = info->header.v2.blockSize; + info->offset = 0; + info->file = file; + + info->headerDirty = FALSE; + info->dirty = FALSE; + info->curChunk = 1; /* just to set it to a value not 0 */ + cacheChunk(info, 0); + + toReturn->data = info; + toReturn->read = fvRead; + toReturn->write = fvWrite; + toReturn->seek = fvSeek; + toReturn->tell = fvTell; + toReturn->getLength = fvGetLength; + toReturn->close = fvClose; + return toReturn; +} + +#else + +AbstractFile* createAbstractFileFromFileVault(AbstractFile* file, const char* key) { + return NULL; +} + +#endif diff --git a/dmg/filevault.h b/dmg/filevault.h index 9f58a78..42cd0f4 100644 --- a/dmg/filevault.h +++ b/dmg/filevault.h @@ -1,98 +1,98 @@ -#ifndef FILEVAULT_H -#define FILEVAULT_H - -#include -#include "dmg.h" - -#ifdef HAVE_CRYPT - -#include -#include - -#define FILEVAULT_CIPHER_KEY_LENGTH 16 -#define FILEVAULT_CIPHER_BLOCKSIZE 16 -#define FILEVAULT_CHUNK_SIZE 4096 -#define FILEVAULT_PBKDF2_ITER_COUNT 1000 -#define FILEVAULT_MSGDGST_LENGTH 20 - -/* - * Information about the FileVault format was yoinked from vfdecrypt, which was written by Ralf-Philipp Weinmann , - * Jacob Appelbaum , and Christian Fromme - */ - -#define FILEVAULT_V2_SIGNATURE 0x656e637263647361ULL - -typedef struct FileVaultV1Header { - uint8_t padding1[48]; - uint32_t kdfIterationCount; - uint32_t kdfSaltLen; - uint8_t kdfSalt[48]; - uint8_t unwrapIV[0x20]; - uint32_t wrappedAESKeyLen; - uint8_t wrappedAESKey[296]; - uint32_t wrappedHMACSHA1KeyLen; - uint8_t wrappedHMACSHA1Key[300]; - uint32_t integrityKeyLen; - uint8_t integrityKey[48]; - uint8_t padding2[484]; -} __attribute__((__packed__)) FileVaultV1Header; - -typedef struct FileVaultV2Header { - uint64_t signature; - uint32_t version; - uint32_t encIVSize; - uint32_t unk1; - uint32_t unk2; - uint32_t unk3; - uint32_t unk4; - uint32_t unk5; - UDIFID uuid; - uint32_t blockSize; - uint64_t dataSize; - uint64_t dataOffset; - uint8_t padding[0x260]; - uint32_t kdfAlgorithm; - uint32_t kdfPRNGAlgorithm; - uint32_t kdfIterationCount; - uint32_t kdfSaltLen; - uint8_t kdfSalt[0x20]; - uint32_t blobEncIVSize; - uint8_t blobEncIV[0x20]; - uint32_t blobEncKeyBits; - uint32_t blobEncAlgorithm; - uint32_t blobEncPadding; - uint32_t blobEncMode; - uint32_t encryptedKeyblobSize; - uint8_t encryptedKeyblob[0x30]; -} __attribute__((__packed__)) FileVaultV2Header; - -typedef struct FileVaultInfo { - union { - FileVaultV1Header v1; - FileVaultV2Header v2; - } header; - - uint8_t version; - uint64_t dataOffset; - uint64_t dataSize; - uint32_t blockSize; - - AbstractFile* file; - - HMAC_CTX hmacCTX; - AES_KEY aesKey; - AES_KEY aesEncKey; - - off_t offset; - - uint32_t curChunk; - unsigned char chunk[FILEVAULT_CHUNK_SIZE]; - - char dirty; - char headerDirty; -} FileVaultInfo; -#endif - -AbstractFile* createAbstractFileFromFileVault(AbstractFile* file, const char* key); - -#endif +#ifndef FILEVAULT_H +#define FILEVAULT_H + +#include +#include "dmg.h" + +#ifdef HAVE_CRYPT + +#include +#include + +#define FILEVAULT_CIPHER_KEY_LENGTH 16 +#define FILEVAULT_CIPHER_BLOCKSIZE 16 +#define FILEVAULT_CHUNK_SIZE 4096 +#define FILEVAULT_PBKDF2_ITER_COUNT 1000 +#define FILEVAULT_MSGDGST_LENGTH 20 + +/* + * Information about the FileVault format was yoinked from vfdecrypt, which was written by Ralf-Philipp Weinmann , + * Jacob Appelbaum , and Christian Fromme + */ + +#define FILEVAULT_V2_SIGNATURE 0x656e637263647361ULL + +typedef struct FileVaultV1Header { + uint8_t padding1[48]; + uint32_t kdfIterationCount; + uint32_t kdfSaltLen; + uint8_t kdfSalt[48]; + uint8_t unwrapIV[0x20]; + uint32_t wrappedAESKeyLen; + uint8_t wrappedAESKey[296]; + uint32_t wrappedHMACSHA1KeyLen; + uint8_t wrappedHMACSHA1Key[300]; + uint32_t integrityKeyLen; + uint8_t integrityKey[48]; + uint8_t padding2[484]; +} __attribute__((__packed__)) FileVaultV1Header; + +typedef struct FileVaultV2Header { + uint64_t signature; + uint32_t version; + uint32_t encIVSize; + uint32_t unk1; + uint32_t unk2; + uint32_t unk3; + uint32_t unk4; + uint32_t unk5; + UDIFID uuid; + uint32_t blockSize; + uint64_t dataSize; + uint64_t dataOffset; + uint8_t padding[0x260]; + uint32_t kdfAlgorithm; + uint32_t kdfPRNGAlgorithm; + uint32_t kdfIterationCount; + uint32_t kdfSaltLen; + uint8_t kdfSalt[0x20]; + uint32_t blobEncIVSize; + uint8_t blobEncIV[0x20]; + uint32_t blobEncKeyBits; + uint32_t blobEncAlgorithm; + uint32_t blobEncPadding; + uint32_t blobEncMode; + uint32_t encryptedKeyblobSize; + uint8_t encryptedKeyblob[0x30]; +} __attribute__((__packed__)) FileVaultV2Header; + +typedef struct FileVaultInfo { + union { + FileVaultV1Header v1; + FileVaultV2Header v2; + } header; + + uint8_t version; + uint64_t dataOffset; + uint64_t dataSize; + uint32_t blockSize; + + AbstractFile* file; + + HMAC_CTX hmacCTX; + AES_KEY aesKey; + AES_KEY aesEncKey; + + off_t offset; + + uint32_t curChunk; + unsigned char chunk[FILEVAULT_CHUNK_SIZE]; + + char dirty; + char headerDirty; +} FileVaultInfo; +#endif + +AbstractFile* createAbstractFileFromFileVault(AbstractFile* file, const char* key); + +#endif diff --git a/dmg/io.c b/dmg/io.c index 0a842c8..47aabe1 100644 --- a/dmg/io.c +++ b/dmg/io.c @@ -1,224 +1,224 @@ -#include -#include -#include -#include - -#include "dmg.h" - -#define SECTORS_AT_A_TIME 0x200 - -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) { - BLKXTable* blkx; - - uint32_t roomForRuns; - uint32_t curRun; - uint64_t curSector; - - unsigned char* inBuffer; - unsigned char* outBuffer; - size_t bufferSize; - size_t have; - int ret; - - z_stream strm; - - - blkx = (BLKXTable*) malloc(sizeof(BLKXTable) + (2 * sizeof(BLKXRun))); - roomForRuns = 2; - memset(blkx, 0, sizeof(BLKXTable) + (roomForRuns * sizeof(BLKXRun))); - - blkx->fUDIFBlocksSignature = UDIF_BLOCK_SIGNATURE; - blkx->infoVersion = 1; - blkx->firstSectorNumber = firstSectorNumber; - blkx->sectorCount = numSectors; - blkx->dataStart = 0; - blkx->decompressBufferRequested = 0x208; - blkx->blocksDescriptor = blocksDescriptor; - blkx->reserved1 = 0; - blkx->reserved2 = 0; - blkx->reserved3 = 0; - blkx->reserved4 = 0; - blkx->reserved5 = 0; - blkx->reserved6 = 0; - memset(&(blkx->checksum), 0, sizeof(blkx->checksum)); - blkx->checksum.type = checksumType; - blkx->checksum.size = 0x20; - blkx->blocksRunCount = 0; - - bufferSize = SECTOR_SIZE * blkx->decompressBufferRequested; - - ASSERT(inBuffer = (unsigned char*) malloc(bufferSize), "malloc"); - ASSERT(outBuffer = (unsigned char*) malloc(bufferSize), "malloc"); - - curRun = 0; - curSector = 0; - - while(numSectors > 0) { - if(curRun >= roomForRuns) { - roomForRuns <<= 1; - blkx = (BLKXTable*) realloc(blkx, sizeof(BLKXTable) + (roomForRuns * sizeof(BLKXRun))); - } - - blkx->runs[curRun].type = BLOCK_ZLIB; - blkx->runs[curRun].reserved = 0; - blkx->runs[curRun].sectorStart = curSector; - blkx->runs[curRun].sectorCount = (numSectors > SECTORS_AT_A_TIME) ? SECTORS_AT_A_TIME : numSectors; - - memset(&strm, 0, sizeof(strm)); - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - - printf("run %d: sectors=%lld, left=%d\n", curRun, blkx->runs[curRun].sectorCount, numSectors); - - ASSERT(deflateInit(&strm, Z_DEFAULT_COMPRESSION) == Z_OK, "deflateInit"); - - ASSERT((strm.avail_in = in->read(in, inBuffer, blkx->runs[curRun].sectorCount * SECTOR_SIZE)) == (blkx->runs[curRun].sectorCount * SECTOR_SIZE), "mRead"); - strm.next_in = inBuffer; - - if(uncompressedChk) - (*uncompressedChk)(uncompressedChkToken, inBuffer, blkx->runs[curRun].sectorCount * SECTOR_SIZE); - - blkx->runs[curRun].compOffset = out->tell(out) - blkx->dataStart; - blkx->runs[curRun].compLength = 0; - - strm.avail_out = bufferSize; - strm.next_out = outBuffer; - - ASSERT((ret = deflate(&strm, Z_FINISH)) != Z_STREAM_ERROR, "deflate/Z_STREAM_ERROR"); - if(ret != Z_STREAM_END) { - ASSERT(FALSE, "deflate"); - } - have = bufferSize - strm.avail_out; - - if((have / SECTOR_SIZE) > blkx->runs[curRun].sectorCount) { - blkx->runs[curRun].type = BLOCK_RAW; - ASSERT(out->write(out, inBuffer, blkx->runs[curRun].sectorCount * SECTOR_SIZE) == (blkx->runs[curRun].sectorCount * SECTOR_SIZE), "fwrite"); - blkx->runs[curRun].compLength += blkx->runs[curRun].sectorCount * SECTOR_SIZE; +#include +#include +#include +#include - if(compressedChk) +#include "dmg.h" + +#define SECTORS_AT_A_TIME 0x200 + +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) { + BLKXTable* blkx; + + uint32_t roomForRuns; + uint32_t curRun; + uint64_t curSector; + + unsigned char* inBuffer; + unsigned char* outBuffer; + size_t bufferSize; + size_t have; + int ret; + + z_stream strm; + + + blkx = (BLKXTable*) malloc(sizeof(BLKXTable) + (2 * sizeof(BLKXRun))); + roomForRuns = 2; + memset(blkx, 0, sizeof(BLKXTable) + (roomForRuns * sizeof(BLKXRun))); + + blkx->fUDIFBlocksSignature = UDIF_BLOCK_SIGNATURE; + blkx->infoVersion = 1; + blkx->firstSectorNumber = firstSectorNumber; + blkx->sectorCount = numSectors; + blkx->dataStart = 0; + blkx->decompressBufferRequested = 0x208; + blkx->blocksDescriptor = blocksDescriptor; + blkx->reserved1 = 0; + blkx->reserved2 = 0; + blkx->reserved3 = 0; + blkx->reserved4 = 0; + blkx->reserved5 = 0; + blkx->reserved6 = 0; + memset(&(blkx->checksum), 0, sizeof(blkx->checksum)); + blkx->checksum.type = checksumType; + blkx->checksum.size = 0x20; + blkx->blocksRunCount = 0; + + bufferSize = SECTOR_SIZE * blkx->decompressBufferRequested; + + ASSERT(inBuffer = (unsigned char*) malloc(bufferSize), "malloc"); + ASSERT(outBuffer = (unsigned char*) malloc(bufferSize), "malloc"); + + curRun = 0; + curSector = 0; + + while(numSectors > 0) { + if(curRun >= roomForRuns) { + roomForRuns <<= 1; + blkx = (BLKXTable*) realloc(blkx, sizeof(BLKXTable) + (roomForRuns * sizeof(BLKXRun))); + } + + blkx->runs[curRun].type = BLOCK_ZLIB; + blkx->runs[curRun].reserved = 0; + blkx->runs[curRun].sectorStart = curSector; + blkx->runs[curRun].sectorCount = (numSectors > SECTORS_AT_A_TIME) ? SECTORS_AT_A_TIME : numSectors; + + memset(&strm, 0, sizeof(strm)); + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + + printf("run %d: sectors=%lld, left=%d\n", curRun, blkx->runs[curRun].sectorCount, numSectors); + + ASSERT(deflateInit(&strm, Z_DEFAULT_COMPRESSION) == Z_OK, "deflateInit"); + + ASSERT((strm.avail_in = in->read(in, inBuffer, blkx->runs[curRun].sectorCount * SECTOR_SIZE)) == (blkx->runs[curRun].sectorCount * SECTOR_SIZE), "mRead"); + strm.next_in = inBuffer; + + if(uncompressedChk) + (*uncompressedChk)(uncompressedChkToken, inBuffer, blkx->runs[curRun].sectorCount * SECTOR_SIZE); + + blkx->runs[curRun].compOffset = out->tell(out) - blkx->dataStart; + blkx->runs[curRun].compLength = 0; + + strm.avail_out = bufferSize; + strm.next_out = outBuffer; + + ASSERT((ret = deflate(&strm, Z_FINISH)) != Z_STREAM_ERROR, "deflate/Z_STREAM_ERROR"); + if(ret != Z_STREAM_END) { + ASSERT(FALSE, "deflate"); + } + have = bufferSize - strm.avail_out; + + if((have / SECTOR_SIZE) > blkx->runs[curRun].sectorCount) { + blkx->runs[curRun].type = BLOCK_RAW; + ASSERT(out->write(out, inBuffer, blkx->runs[curRun].sectorCount * SECTOR_SIZE) == (blkx->runs[curRun].sectorCount * SECTOR_SIZE), "fwrite"); + blkx->runs[curRun].compLength += blkx->runs[curRun].sectorCount * SECTOR_SIZE; + + if(compressedChk) (*compressedChk)(compressedChkToken, inBuffer, blkx->runs[curRun].sectorCount * SECTOR_SIZE); - } else { + } else { ASSERT(out->write(out, outBuffer, have) == have, "fwrite"); - if(compressedChk) + if(compressedChk) (*compressedChk)(compressedChkToken, outBuffer, have); - - blkx->runs[curRun].compLength += have; - } - - deflateEnd(&strm); - - curSector += blkx->runs[curRun].sectorCount; - numSectors -= blkx->runs[curRun].sectorCount; - curRun++; - } - - if(curRun >= roomForRuns) { - roomForRuns <<= 1; - blkx = (BLKXTable*) realloc(blkx, sizeof(BLKXTable) + (roomForRuns * sizeof(BLKXRun))); - } - - blkx->runs[curRun].type = BLOCK_TERMINATOR; - blkx->runs[curRun].reserved = 0; - blkx->runs[curRun].sectorStart = curSector; - blkx->runs[curRun].sectorCount = 0; - blkx->runs[curRun].compOffset = out->tell(out) - blkx->dataStart; - blkx->runs[curRun].compLength = 0; - blkx->blocksRunCount = curRun + 1; - - free(inBuffer); - free(outBuffer); - - return blkx; -} - -void extractBLKX(AbstractFile* in, AbstractFile* out, BLKXTable* blkx) { - unsigned char* inBuffer; - unsigned char* outBuffer; - unsigned char zero; - size_t bufferSize; - size_t have; - off_t initialOffset; - int i; - int ret; - - z_stream strm; - - bufferSize = SECTOR_SIZE * blkx->decompressBufferRequested; - - ASSERT(inBuffer = (unsigned char*) malloc(bufferSize), "malloc"); - ASSERT(outBuffer = (unsigned char*) malloc(bufferSize), "malloc"); - - initialOffset = out->tell(out); - ASSERT(initialOffset != -1, "ftello"); - - zero = 0; - - for(i = 0; i < blkx->blocksRunCount; i++) { - ASSERT(in->seek(in, blkx->dataStart + blkx->runs[i].compOffset) == 0, "fseeko"); - ASSERT(out->seek(out, initialOffset + (blkx->runs[i].sectorStart * SECTOR_SIZE)) == 0, "mSeek"); - - if(blkx->runs[i].sectorCount > 0) { - ASSERT(out->seek(out, initialOffset + (blkx->runs[i].sectorStart + blkx->runs[i].sectorCount) * SECTOR_SIZE - 1) == 0, "mSeek"); - ASSERT(out->write(out, &zero, 1) == 1, "mWrite"); - ASSERT(out->seek(out, initialOffset + (blkx->runs[i].sectorStart * SECTOR_SIZE)) == 0, "mSeek"); - } - - if(blkx->runs[i].type == BLOCK_TERMINATOR) { - break; - } - - if( blkx->runs[i].compLength == 0) { - continue; - } - - printf("run %d: sectors=%lld, length=%lld, fileOffset=0x%llx\n", i, blkx->runs[i].sectorCount, blkx->runs[i].compLength, blkx->runs[i].compOffset); - - switch(blkx->runs[i].type) { - case BLOCK_ZLIB: - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - - ASSERT(inflateInit(&strm) == Z_OK, "inflateInit"); - - ASSERT((strm.avail_in = in->read(in, inBuffer, blkx->runs[i].compLength)) == blkx->runs[i].compLength, "fread"); - strm.next_in = inBuffer; - - do { - strm.avail_out = bufferSize; - strm.next_out = outBuffer; - ASSERT((ret = inflate(&strm, Z_NO_FLUSH)) != Z_STREAM_ERROR, "inflate/Z_STREAM_ERROR"); - if(ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_STREAM_END) { - ASSERT(FALSE, "inflate"); - } - have = bufferSize - strm.avail_out; - ASSERT(out->write(out, outBuffer, have) == have, "mWrite"); - } while (strm.avail_out == 0); - - ASSERT(inflateEnd(&strm) == Z_OK, "inflateEnd"); - break; - case BLOCK_RAW: - ASSERT((have = in->read(in, inBuffer, blkx->runs[i].compLength)) == blkx->runs[i].compLength, "fread"); - ASSERT(out->write(out, inBuffer, have) == have, "mWrite"); - break; - case BLOCK_IGNORE: - break; - case BLOCK_COMMENT: - break; - case BLOCK_TERMINATOR: - break; - default: - break; - } - } - - free(inBuffer); - free(outBuffer); -} + + blkx->runs[curRun].compLength += have; + } + + deflateEnd(&strm); + + curSector += blkx->runs[curRun].sectorCount; + numSectors -= blkx->runs[curRun].sectorCount; + curRun++; + } + + if(curRun >= roomForRuns) { + roomForRuns <<= 1; + blkx = (BLKXTable*) realloc(blkx, sizeof(BLKXTable) + (roomForRuns * sizeof(BLKXRun))); + } + + blkx->runs[curRun].type = BLOCK_TERMINATOR; + blkx->runs[curRun].reserved = 0; + blkx->runs[curRun].sectorStart = curSector; + blkx->runs[curRun].sectorCount = 0; + blkx->runs[curRun].compOffset = out->tell(out) - blkx->dataStart; + blkx->runs[curRun].compLength = 0; + blkx->blocksRunCount = curRun + 1; + + free(inBuffer); + free(outBuffer); + + return blkx; +} + +void extractBLKX(AbstractFile* in, AbstractFile* out, BLKXTable* blkx) { + unsigned char* inBuffer; + unsigned char* outBuffer; + unsigned char zero; + size_t bufferSize; + size_t have; + off_t initialOffset; + int i; + int ret; + + z_stream strm; + + bufferSize = SECTOR_SIZE * blkx->decompressBufferRequested; + + ASSERT(inBuffer = (unsigned char*) malloc(bufferSize), "malloc"); + ASSERT(outBuffer = (unsigned char*) malloc(bufferSize), "malloc"); + + initialOffset = out->tell(out); + ASSERT(initialOffset != -1, "ftello"); + + zero = 0; + + for(i = 0; i < blkx->blocksRunCount; i++) { + ASSERT(in->seek(in, blkx->dataStart + blkx->runs[i].compOffset) == 0, "fseeko"); + ASSERT(out->seek(out, initialOffset + (blkx->runs[i].sectorStart * SECTOR_SIZE)) == 0, "mSeek"); + + if(blkx->runs[i].sectorCount > 0) { + ASSERT(out->seek(out, initialOffset + (blkx->runs[i].sectorStart + blkx->runs[i].sectorCount) * SECTOR_SIZE - 1) == 0, "mSeek"); + ASSERT(out->write(out, &zero, 1) == 1, "mWrite"); + ASSERT(out->seek(out, initialOffset + (blkx->runs[i].sectorStart * SECTOR_SIZE)) == 0, "mSeek"); + } + + if(blkx->runs[i].type == BLOCK_TERMINATOR) { + break; + } + + if( blkx->runs[i].compLength == 0) { + continue; + } + + printf("run %d: sectors=%lld, length=%lld, fileOffset=0x%llx\n", i, blkx->runs[i].sectorCount, blkx->runs[i].compLength, blkx->runs[i].compOffset); + + switch(blkx->runs[i].type) { + case BLOCK_ZLIB: + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + + ASSERT(inflateInit(&strm) == Z_OK, "inflateInit"); + + ASSERT((strm.avail_in = in->read(in, inBuffer, blkx->runs[i].compLength)) == blkx->runs[i].compLength, "fread"); + strm.next_in = inBuffer; + + do { + strm.avail_out = bufferSize; + strm.next_out = outBuffer; + ASSERT((ret = inflate(&strm, Z_NO_FLUSH)) != Z_STREAM_ERROR, "inflate/Z_STREAM_ERROR"); + if(ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_STREAM_END) { + ASSERT(FALSE, "inflate"); + } + have = bufferSize - strm.avail_out; + ASSERT(out->write(out, outBuffer, have) == have, "mWrite"); + } while (strm.avail_out == 0); + + ASSERT(inflateEnd(&strm) == Z_OK, "inflateEnd"); + break; + case BLOCK_RAW: + ASSERT((have = in->read(in, inBuffer, blkx->runs[i].compLength)) == blkx->runs[i].compLength, "fread"); + ASSERT(out->write(out, inBuffer, have) == have, "mWrite"); + break; + case BLOCK_IGNORE: + break; + case BLOCK_COMMENT: + break; + case BLOCK_TERMINATOR: + break; + default: + break; + } + } + + free(inBuffer); + free(outBuffer); +} diff --git a/dmg/openssl-0.9.8g/demos/engines/ibmca/hw_ibmca.c b/dmg/openssl-0.9.8g/demos/engines/ibmca/hw_ibmca.c index 0c2c39b..d42cdba 100644 --- a/dmg/openssl-0.9.8g/demos/engines/ibmca/hw_ibmca.c +++ b/dmg/openssl-0.9.8g/demos/engines/ibmca/hw_ibmca.c @@ -1,920 +1,920 @@ -/* crypto/engine/hw_ibmca.c */ -/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL - * project 2000. - */ -/* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - -/* (C) COPYRIGHT International Business Machines Corp. 2001 */ - -#include -#include -#include -#include - -#ifndef OPENSSL_NO_HW -#ifndef OPENSSL_NO_HW_IBMCA - -#ifdef FLAT_INC -#include "ica_openssl_api.h" -#else -#include "vendor_defns/ica_openssl_api.h" -#endif - -#define IBMCA_LIB_NAME "ibmca engine" -#include "hw_ibmca_err.c" - -static int ibmca_destroy(ENGINE *e); -static int ibmca_init(ENGINE *e); -static int ibmca_finish(ENGINE *e); -static int ibmca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); - -static const char *IBMCA_F1 = "icaOpenAdapter"; -static const char *IBMCA_F2 = "icaCloseAdapter"; -static const char *IBMCA_F3 = "icaRsaModExpo"; -static const char *IBMCA_F4 = "icaRandomNumberGenerate"; -static const char *IBMCA_F5 = "icaRsaCrt"; - -ICA_ADAPTER_HANDLE handle=0; - -/* BIGNUM stuff */ -static int ibmca_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx); - -static int ibmca_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1, - const BIGNUM *iqmp, BN_CTX *ctx); - -#ifndef OPENSSL_NO_RSA -/* RSA stuff */ -static int ibmca_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa); -#endif - -/* This function is aliased to mod_exp (with the mont stuff dropped). */ -static int ibmca_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); - -#ifndef OPENSSL_NO_DSA -/* DSA stuff */ -static int ibmca_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, - BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, - BN_CTX *ctx, BN_MONT_CTX *in_mont); -static int ibmca_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, - const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, - BN_MONT_CTX *m_ctx); -#endif - -#ifndef OPENSSL_NO_DH -/* DH stuff */ -/* This function is alised to mod_exp (with the DH and mont dropped). */ -static int ibmca_mod_exp_dh(const DH *dh, BIGNUM *r, - const BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); -#endif - -/* RAND stuff */ -static int ibmca_rand_bytes(unsigned char *buf, int num); -static int ibmca_rand_status(void); - - -/* WJH - check for more commands, like in nuron */ - -/* The definitions for control commands specific to this engine */ -#define IBMCA_CMD_SO_PATH ENGINE_CMD_BASE -static const ENGINE_CMD_DEFN ibmca_cmd_defns[] = { - {IBMCA_CMD_SO_PATH, - "SO_PATH", - "Specifies the path to the 'atasi' shared library", - ENGINE_CMD_FLAG_STRING}, - {0, NULL, NULL, 0} - }; - -#ifndef OPENSSL_NO_RSA -/* Our internal RSA_METHOD that we provide pointers to */ -static RSA_METHOD ibmca_rsa = - { - "Ibmca RSA method", - NULL, - NULL, - NULL, - NULL, - ibmca_rsa_mod_exp, - ibmca_mod_exp_mont, - NULL, - NULL, - 0, - NULL, - NULL, - NULL - }; -#endif - -#ifndef OPENSSL_NO_DSA -/* Our internal DSA_METHOD that we provide pointers to */ -static DSA_METHOD ibmca_dsa = - { - "Ibmca DSA method", - NULL, /* dsa_do_sign */ - NULL, /* dsa_sign_setup */ - NULL, /* dsa_do_verify */ - ibmca_dsa_mod_exp, /* dsa_mod_exp */ - ibmca_mod_exp_dsa, /* bn_mod_exp */ - NULL, /* init */ - NULL, /* finish */ - 0, /* flags */ - NULL /* app_data */ - }; -#endif - -#ifndef OPENSSL_NO_DH -/* Our internal DH_METHOD that we provide pointers to */ -static DH_METHOD ibmca_dh = - { - "Ibmca DH method", - NULL, - NULL, - ibmca_mod_exp_dh, - NULL, - NULL, - 0, - NULL - }; -#endif - -static RAND_METHOD ibmca_rand = - { - /* "IBMCA RAND method", */ - NULL, - ibmca_rand_bytes, - NULL, - NULL, - ibmca_rand_bytes, - ibmca_rand_status, - }; - -/* Constants used when creating the ENGINE */ -static const char *engine_ibmca_id = "ibmca"; -static const char *engine_ibmca_name = "Ibmca hardware engine support"; - -/* This internal function is used by ENGINE_ibmca() and possibly by the - * "dynamic" ENGINE support too */ -static int bind_helper(ENGINE *e) - { -#ifndef OPENSSL_NO_RSA - const RSA_METHOD *meth1; -#endif -#ifndef OPENSSL_NO_DSA - const DSA_METHOD *meth2; -#endif -#ifndef OPENSSL_NO_DH - const DH_METHOD *meth3; -#endif - if(!ENGINE_set_id(e, engine_ibmca_id) || - !ENGINE_set_name(e, engine_ibmca_name) || -#ifndef OPENSSL_NO_RSA - !ENGINE_set_RSA(e, &ibmca_rsa) || -#endif -#ifndef OPENSSL_NO_DSA - !ENGINE_set_DSA(e, &ibmca_dsa) || -#endif -#ifndef OPENSSL_NO_DH - !ENGINE_set_DH(e, &ibmca_dh) || -#endif - !ENGINE_set_RAND(e, &ibmca_rand) || - !ENGINE_set_destroy_function(e, ibmca_destroy) || - !ENGINE_set_init_function(e, ibmca_init) || - !ENGINE_set_finish_function(e, ibmca_finish) || - !ENGINE_set_ctrl_function(e, ibmca_ctrl) || - !ENGINE_set_cmd_defns(e, ibmca_cmd_defns)) - return 0; - -#ifndef OPENSSL_NO_RSA - /* We know that the "PKCS1_SSLeay()" functions hook properly - * to the ibmca-specific mod_exp and mod_exp_crt so we use - * those functions. NB: We don't use ENGINE_openssl() or - * anything "more generic" because something like the RSAref - * code may not hook properly, and if you own one of these - * cards then you have the right to do RSA operations on it - * anyway! */ - meth1 = RSA_PKCS1_SSLeay(); - ibmca_rsa.rsa_pub_enc = meth1->rsa_pub_enc; - ibmca_rsa.rsa_pub_dec = meth1->rsa_pub_dec; - ibmca_rsa.rsa_priv_enc = meth1->rsa_priv_enc; - ibmca_rsa.rsa_priv_dec = meth1->rsa_priv_dec; -#endif - -#ifndef OPENSSL_NO_DSA - /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish - * bits. */ - meth2 = DSA_OpenSSL(); - ibmca_dsa.dsa_do_sign = meth2->dsa_do_sign; - ibmca_dsa.dsa_sign_setup = meth2->dsa_sign_setup; - ibmca_dsa.dsa_do_verify = meth2->dsa_do_verify; -#endif - -#ifndef OPENSSL_NO_DH - /* Much the same for Diffie-Hellman */ - meth3 = DH_OpenSSL(); - ibmca_dh.generate_key = meth3->generate_key; - ibmca_dh.compute_key = meth3->compute_key; -#endif - - /* Ensure the ibmca error handling is set up */ - ERR_load_IBMCA_strings(); - return 1; - } - -static ENGINE *engine_ibmca(void) - { - ENGINE *ret = ENGINE_new(); - if(!ret) - return NULL; - if(!bind_helper(ret)) - { - ENGINE_free(ret); - return NULL; - } - return ret; - } - -#ifdef ENGINE_DYNAMIC_SUPPORT -static -#endif -void ENGINE_load_ibmca(void) - { - /* Copied from eng_[openssl|dyn].c */ - ENGINE *toadd = engine_ibmca(); - if(!toadd) return; - ENGINE_add(toadd); - ENGINE_free(toadd); - ERR_clear_error(); - } - -/* Destructor (complements the "ENGINE_ibmca()" constructor) */ -static int ibmca_destroy(ENGINE *e) - { - /* Unload the ibmca error strings so any error state including our - * functs or reasons won't lead to a segfault (they simply get displayed - * without corresponding string data because none will be found). */ - ERR_unload_IBMCA_strings(); - return 1; - } - - -/* This is a process-global DSO handle used for loading and unloading - * the Ibmca library. NB: This is only set (or unset) during an - * init() or finish() call (reference counts permitting) and they're - * operating with global locks, so this should be thread-safe - * implicitly. */ - -static DSO *ibmca_dso = NULL; - -/* These are the function pointers that are (un)set when the library has - * successfully (un)loaded. */ - -static unsigned int (ICA_CALL *p_icaOpenAdapter)(); -static unsigned int (ICA_CALL *p_icaCloseAdapter)(); -static unsigned int (ICA_CALL *p_icaRsaModExpo)(); -static unsigned int (ICA_CALL *p_icaRandomNumberGenerate)(); -static unsigned int (ICA_CALL *p_icaRsaCrt)(); - -/* utility function to obtain a context */ -static int get_context(ICA_ADAPTER_HANDLE *p_handle) - { - unsigned int status=0; - - status = p_icaOpenAdapter(0, p_handle); - if(status != 0) - return 0; - return 1; - } - -/* similarly to release one. */ -static void release_context(ICA_ADAPTER_HANDLE handle) - { - p_icaCloseAdapter(handle); - } - -/* (de)initialisation functions. */ -static int ibmca_init(ENGINE *e) - { - - void (*p1)(); - void (*p2)(); - void (*p3)(); - void (*p4)(); - void (*p5)(); - - if(ibmca_dso != NULL) - { - IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_ALREADY_LOADED); - goto err; - } - /* Attempt to load libatasi.so/atasi.dll/whatever. Needs to be - * changed unfortunately because the Ibmca drivers don't have - * standard library names that can be platform-translated well. */ - /* TODO: Work out how to actually map to the names the Ibmca - * drivers really use - for now a symbollic link needs to be - * created on the host system from libatasi.so to atasi.so on - * unix variants. */ - - /* WJH XXX check name translation */ - - ibmca_dso = DSO_load(NULL, IBMCA_LIBNAME, NULL, - /* DSO_FLAG_NAME_TRANSLATION */ 0); - if(ibmca_dso == NULL) - { - IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_DSO_FAILURE); - goto err; - } - - if(!(p1 = DSO_bind_func( - ibmca_dso, IBMCA_F1)) || - !(p2 = DSO_bind_func( - ibmca_dso, IBMCA_F2)) || - !(p3 = DSO_bind_func( - ibmca_dso, IBMCA_F3)) || - !(p4 = DSO_bind_func( - ibmca_dso, IBMCA_F4)) || - !(p5 = DSO_bind_func( - ibmca_dso, IBMCA_F5))) - { - IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_DSO_FAILURE); - goto err; - } - - /* Copy the pointers */ - - p_icaOpenAdapter = (unsigned int (ICA_CALL *)())p1; - p_icaCloseAdapter = (unsigned int (ICA_CALL *)())p2; - p_icaRsaModExpo = (unsigned int (ICA_CALL *)())p3; - p_icaRandomNumberGenerate = (unsigned int (ICA_CALL *)())p4; - p_icaRsaCrt = (unsigned int (ICA_CALL *)())p5; - - if(!get_context(&handle)) - { - IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_UNIT_FAILURE); - goto err; - } - - return 1; - err: - if(ibmca_dso) - DSO_free(ibmca_dso); - - p_icaOpenAdapter = NULL; - p_icaCloseAdapter = NULL; - p_icaRsaModExpo = NULL; - p_icaRandomNumberGenerate = NULL; - - return 0; - } - -static int ibmca_finish(ENGINE *e) - { - if(ibmca_dso == NULL) - { - IBMCAerr(IBMCA_F_IBMCA_FINISH,IBMCA_R_NOT_LOADED); - return 0; - } - release_context(handle); - if(!DSO_free(ibmca_dso)) - { - IBMCAerr(IBMCA_F_IBMCA_FINISH,IBMCA_R_DSO_FAILURE); - return 0; - } - ibmca_dso = NULL; - - return 1; - } - -static int ibmca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) - { - int initialised = ((ibmca_dso == NULL) ? 0 : 1); - switch(cmd) - { - case IBMCA_CMD_SO_PATH: - if(p == NULL) - { - IBMCAerr(IBMCA_F_IBMCA_CTRL,ERR_R_PASSED_NULL_PARAMETER); - return 0; - } - if(initialised) - { - IBMCAerr(IBMCA_F_IBMCA_CTRL,IBMCA_R_ALREADY_LOADED); - return 0; - } - IBMCA_LIBNAME = (const char *)p; - return 1; - default: - break; - } - IBMCAerr(IBMCA_F_IBMCA_CTRL,IBMCA_R_CTRL_COMMAND_NOT_IMPLEMENTED); - return 0; - } - - -static int ibmca_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx) - { - /* I need somewhere to store temporary serialised values for - * use with the Ibmca API calls. A neat cheat - I'll use - * BIGNUMs from the BN_CTX but access their arrays directly as - * byte arrays . This way I don't have to clean anything - * up. */ - - BIGNUM *argument=NULL; - BIGNUM *result=NULL; - BIGNUM *key=NULL; - int to_return; - int inLen, outLen, tmpLen; - - - ICA_KEY_RSA_MODEXPO *publKey=NULL; - unsigned int rc; - - to_return = 0; /* expect failure */ - - if(!ibmca_dso) - { - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_NOT_LOADED); - goto err; - } - /* Prepare the params */ - BN_CTX_start(ctx); - argument = BN_CTX_get(ctx); - result = BN_CTX_get(ctx); - key = BN_CTX_get(ctx); - - if( !argument || !result || !key) - { - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_BN_CTX_FULL); - goto err; - } - - - if(!bn_wexpand(argument, m->top) || !bn_wexpand(result, m->top) || - !bn_wexpand(key, sizeof(*publKey)/BN_BYTES)) - - { - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_BN_EXPAND_FAIL); - goto err; - } - - publKey = (ICA_KEY_RSA_MODEXPO *)key->d; - - if (publKey == NULL) - { - goto err; - } - memset(publKey, 0, sizeof(ICA_KEY_RSA_MODEXPO)); - - publKey->keyType = CORRECT_ENDIANNESS(ME_KEY_TYPE); - publKey->keyLength = CORRECT_ENDIANNESS(sizeof(ICA_KEY_RSA_MODEXPO)); - publKey->expOffset = (char *) publKey->keyRecord - (char *) publKey; - - /* A quirk of the card: the exponent length has to be the same - as the modulus (key) length */ - - outLen = BN_num_bytes(m); - -/* check for modulus length SAB*/ - if (outLen > 256 ) { - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_MEXP_LENGTH_TO_LARGE); - goto err; - } -/* check for modulus length SAB*/ - - - publKey->expLength = publKey->nLength = outLen; -/* SAB Check for underflow condition - the size of the exponent is less than the size of the parameter - then we have a big problem and will underflow the keyRecord - buffer. Bad stuff could happen then -*/ -if (outLen < BN_num_bytes(p)){ - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_UNDERFLOW_KEYRECORD); - goto err; -} -/* SAB End check for underflow */ - - - BN_bn2bin(p, &publKey->keyRecord[publKey->expLength - - BN_num_bytes(p)]); - BN_bn2bin(m, &publKey->keyRecord[publKey->expLength]); - - - - publKey->modulusBitLength = CORRECT_ENDIANNESS(publKey->nLength * 8); - publKey->nOffset = CORRECT_ENDIANNESS(publKey->expOffset + - publKey->expLength); - - publKey->expOffset = CORRECT_ENDIANNESS((char *) publKey->keyRecord - - (char *) publKey); - - tmpLen = outLen; - publKey->expLength = publKey->nLength = CORRECT_ENDIANNESS(tmpLen); - - /* Prepare the argument */ - - memset(argument->d, 0, outLen); - BN_bn2bin(a, (unsigned char *)argument->d + outLen - - BN_num_bytes(a)); - - inLen = outLen; - - /* Perform the operation */ - - if( (rc = p_icaRsaModExpo(handle, inLen,(unsigned char *)argument->d, - publKey, &outLen, (unsigned char *)result->d)) - !=0 ) - - { - printf("rc = %d\n", rc); - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_REQUEST_FAILED); - goto err; - } - - - /* Convert the response */ - BN_bin2bn((unsigned char *)result->d, outLen, r); - to_return = 1; - err: - BN_CTX_end(ctx); - return to_return; - } - -#ifndef OPENSSL_NO_RSA -static int ibmca_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa) - { - BN_CTX *ctx; - int to_return = 0; - - if((ctx = BN_CTX_new()) == NULL) - goto err; - if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) - { - if(!rsa->d || !rsa->n) - { - IBMCAerr(IBMCA_F_IBMCA_RSA_MOD_EXP, - IBMCA_R_MISSING_KEY_COMPONENTS); - goto err; - } - to_return = ibmca_mod_exp(r0, I, rsa->d, rsa->n, ctx); - } - else - { - to_return = ibmca_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1, - rsa->dmq1, rsa->iqmp, ctx); - } - err: - if(ctx) - BN_CTX_free(ctx); - return to_return; - } -#endif - -/* Ein kleines chinesisches "Restessen" */ -static int ibmca_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *q, const BIGNUM *dmp1, - const BIGNUM *dmq1, const BIGNUM *iqmp, BN_CTX *ctx) - { - - BIGNUM *argument = NULL; - BIGNUM *result = NULL; - BIGNUM *key = NULL; - - int to_return = 0; /* expect failure */ - - char *pkey=NULL; - ICA_KEY_RSA_CRT *privKey=NULL; - int inLen, outLen; - - int rc; - unsigned int offset, pSize, qSize; -/* SAB New variables */ - unsigned int keyRecordSize; - unsigned int pbytes = BN_num_bytes(p); - unsigned int qbytes = BN_num_bytes(q); - unsigned int dmp1bytes = BN_num_bytes(dmp1); - unsigned int dmq1bytes = BN_num_bytes(dmq1); - unsigned int iqmpbytes = BN_num_bytes(iqmp); - - /* Prepare the params */ - - BN_CTX_start(ctx); - argument = BN_CTX_get(ctx); - result = BN_CTX_get(ctx); - key = BN_CTX_get(ctx); - - if(!argument || !result || !key) - { - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_BN_CTX_FULL); - goto err; - } - - if(!bn_wexpand(argument, p->top + q->top) || - !bn_wexpand(result, p->top + q->top) || - !bn_wexpand(key, sizeof(*privKey)/BN_BYTES )) - { - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_BN_EXPAND_FAIL); - goto err; - } - - - privKey = (ICA_KEY_RSA_CRT *)key->d; -/* SAB Add check for total size in bytes of the parms does not exceed - the buffer space we have - do this first -*/ - keyRecordSize = pbytes+qbytes+dmp1bytes+dmq1bytes+iqmpbytes; - if ( keyRecordSize > sizeof(privKey->keyRecord )) { - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE); - goto err; - } - - if ( (qbytes + dmq1bytes) > 256 ){ - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE); - goto err; - } - - if ( pbytes + dmp1bytes > 256 ) { - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE); - goto err; - } - -/* end SAB additions */ - - memset(privKey, 0, sizeof(ICA_KEY_RSA_CRT)); - privKey->keyType = CORRECT_ENDIANNESS(CRT_KEY_TYPE); - privKey->keyLength = CORRECT_ENDIANNESS(sizeof(ICA_KEY_RSA_CRT)); - privKey->modulusBitLength = - CORRECT_ENDIANNESS(BN_num_bytes(q) * 2 * 8); - - /* - * p,dp & qInv are 1 QWORD Larger - */ - privKey->pLength = CORRECT_ENDIANNESS(BN_num_bytes(p)+8); - privKey->qLength = CORRECT_ENDIANNESS(BN_num_bytes(q)); - privKey->dpLength = CORRECT_ENDIANNESS(BN_num_bytes(dmp1)+8); - privKey->dqLength = CORRECT_ENDIANNESS(BN_num_bytes(dmq1)); - privKey->qInvLength = CORRECT_ENDIANNESS(BN_num_bytes(iqmp)+8); - - offset = (char *) privKey->keyRecord - - (char *) privKey; - - qSize = BN_num_bytes(q); - pSize = qSize + 8; /* 1 QWORD larger */ - - -/* SAB probably aittle redundant, but we'll verify that each of the - components which make up a key record sent ot the card does not exceed - the space that is allocated for it. this handles the case where even if - the total length does not exceed keyrecord zied, if the operands are funny sized -they could cause potential side affects on either the card or the result */ - - if ( (pbytes > pSize) || (dmp1bytes > pSize) || - (iqmpbytes > pSize) || ( qbytes >qSize) || - (dmq1bytes > qSize) ) { - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT, IBMCA_R_OPERANDS_TO_LARGE); - goto err; - - } - - - privKey->dpOffset = CORRECT_ENDIANNESS(offset); - - offset += pSize; - privKey->dqOffset = CORRECT_ENDIANNESS(offset); - - offset += qSize; - privKey->pOffset = CORRECT_ENDIANNESS(offset); - - offset += pSize; - privKey->qOffset = CORRECT_ENDIANNESS(offset); - - offset += qSize; - privKey->qInvOffset = CORRECT_ENDIANNESS(offset); - - pkey = (char *) privKey->keyRecord; - - -/* SAB first check that we don;t under flow the buffer */ - if ( pSize < pbytes ) { - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT, IBMCA_R_UNDERFLOW_CONDITION); - goto err; - } - - /* pkey += pSize - BN_num_bytes(p); WROING this should be dmp1) */ - pkey += pSize - BN_num_bytes(dmp1); - BN_bn2bin(dmp1, pkey); - pkey += BN_num_bytes(dmp1); /* move the pointer */ - - BN_bn2bin(dmq1, pkey); /* Copy over dmq1 */ - - pkey += qSize; /* move pointer */ - pkey += pSize - BN_num_bytes(p); /* set up for zero padding of next field */ - - BN_bn2bin(p, pkey); - pkey += BN_num_bytes(p); /* increment pointer by number of bytes moved */ - - BN_bn2bin(q, pkey); - pkey += qSize ; /* move the pointer */ - pkey += pSize - BN_num_bytes(iqmp); /* Adjust for padding */ - BN_bn2bin(iqmp, pkey); - - /* Prepare the argument and response */ - - outLen = CORRECT_ENDIANNESS(privKey->qLength) * 2; /* Correct endianess is used - because the fields were converted above */ - - if (outLen > 256) { - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OUTLEN_TO_LARGE); - goto err; - } - - /* SAB check for underflow here on the argeument */ - if ( outLen < BN_num_bytes(a)) { - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_UNDERFLOW_CONDITION); - goto err; - } - - BN_bn2bin(a, (unsigned char *)argument->d + outLen - - BN_num_bytes(a)); - inLen = outLen; - - memset(result->d, 0, outLen); - - /* Perform the operation */ - - if ( (rc = p_icaRsaCrt(handle, inLen, (unsigned char *)argument->d, - privKey, &outLen, (unsigned char *)result->d)) != 0) - { - printf("rc = %d\n", rc); - IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_REQUEST_FAILED); - goto err; - } - - /* Convert the response */ - - BN_bin2bn((unsigned char *)result->d, outLen, r); - to_return = 1; - - err: - BN_CTX_end(ctx); - return to_return; - - } - -#ifndef OPENSSL_NO_DSA -/* This code was liberated and adapted from the commented-out code in - * dsa_ossl.c. Because of the unoptimised form of the Ibmca acceleration - * (it doesn't have a CRT form for RSA), this function means that an - * Ibmca system running with a DSA server certificate can handshake - * around 5 or 6 times faster/more than an equivalent system running with - * RSA. Just check out the "signs" statistics from the RSA and DSA parts - * of "openssl speed -engine ibmca dsa1024 rsa1024". */ -static int ibmca_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, - BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, - BN_CTX *ctx, BN_MONT_CTX *in_mont) - { - BIGNUM t; - int to_return = 0; - - BN_init(&t); - /* let rr = a1 ^ p1 mod m */ - if (!ibmca_mod_exp(rr,a1,p1,m,ctx)) goto end; - /* let t = a2 ^ p2 mod m */ - if (!ibmca_mod_exp(&t,a2,p2,m,ctx)) goto end; - /* let rr = rr * t mod m */ - if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end; - to_return = 1; - end: - BN_free(&t); - return to_return; - } - - -static int ibmca_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, - const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, - BN_MONT_CTX *m_ctx) - { - return ibmca_mod_exp(r, a, p, m, ctx); - } -#endif - -/* This function is aliased to mod_exp (with the mont stuff dropped). */ -static int ibmca_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) - { - return ibmca_mod_exp(r, a, p, m, ctx); - } - -#ifndef OPENSSL_NO_DH -/* This function is aliased to mod_exp (with the dh and mont dropped). */ -static int ibmca_mod_exp_dh(DH const *dh, BIGNUM *r, - const BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) - { - return ibmca_mod_exp(r, a, p, m, ctx); - } -#endif - -/* Random bytes are good */ -static int ibmca_rand_bytes(unsigned char *buf, int num) - { - int to_return = 0; /* assume failure */ - unsigned int ret; - - - if(handle == 0) - { - IBMCAerr(IBMCA_F_IBMCA_RAND_BYTES,IBMCA_R_NOT_INITIALISED); - goto err; - } - - ret = p_icaRandomNumberGenerate(handle, num, buf); - if (ret < 0) - { - IBMCAerr(IBMCA_F_IBMCA_RAND_BYTES,IBMCA_R_REQUEST_FAILED); - goto err; - } - to_return = 1; - err: - return to_return; - } - -static int ibmca_rand_status(void) - { - return 1; - } - -/* This stuff is needed if this ENGINE is being compiled into a self-contained - * shared-library. */ -#ifdef ENGINE_DYNAMIC_SUPPORT -static int bind_fn(ENGINE *e, const char *id) - { - if(id && (strcmp(id, engine_ibmca_id) != 0)) /* WJH XXX */ - return 0; - if(!bind_helper(e)) - return 0; - return 1; - } -IMPLEMENT_DYNAMIC_CHECK_FN() -IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) -#endif /* ENGINE_DYNAMIC_SUPPORT */ - - -#endif /* !OPENSSL_NO_HW_IBMCA */ -#endif /* !OPENSSL_NO_HW */ +/* crypto/engine/hw_ibmca.c */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* (C) COPYRIGHT International Business Machines Corp. 2001 */ + +#include +#include +#include +#include + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_IBMCA + +#ifdef FLAT_INC +#include "ica_openssl_api.h" +#else +#include "vendor_defns/ica_openssl_api.h" +#endif + +#define IBMCA_LIB_NAME "ibmca engine" +#include "hw_ibmca_err.c" + +static int ibmca_destroy(ENGINE *e); +static int ibmca_init(ENGINE *e); +static int ibmca_finish(ENGINE *e); +static int ibmca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); + +static const char *IBMCA_F1 = "icaOpenAdapter"; +static const char *IBMCA_F2 = "icaCloseAdapter"; +static const char *IBMCA_F3 = "icaRsaModExpo"; +static const char *IBMCA_F4 = "icaRandomNumberGenerate"; +static const char *IBMCA_F5 = "icaRsaCrt"; + +ICA_ADAPTER_HANDLE handle=0; + +/* BIGNUM stuff */ +static int ibmca_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); + +static int ibmca_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1, + const BIGNUM *iqmp, BN_CTX *ctx); + +#ifndef OPENSSL_NO_RSA +/* RSA stuff */ +static int ibmca_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa); +#endif + +/* This function is aliased to mod_exp (with the mont stuff dropped). */ +static int ibmca_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); + +#ifndef OPENSSL_NO_DSA +/* DSA stuff */ +static int ibmca_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, + BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, + BN_CTX *ctx, BN_MONT_CTX *in_mont); +static int ibmca_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); +#endif + +#ifndef OPENSSL_NO_DH +/* DH stuff */ +/* This function is alised to mod_exp (with the DH and mont dropped). */ +static int ibmca_mod_exp_dh(const DH *dh, BIGNUM *r, + const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +#endif + +/* RAND stuff */ +static int ibmca_rand_bytes(unsigned char *buf, int num); +static int ibmca_rand_status(void); + + +/* WJH - check for more commands, like in nuron */ + +/* The definitions for control commands specific to this engine */ +#define IBMCA_CMD_SO_PATH ENGINE_CMD_BASE +static const ENGINE_CMD_DEFN ibmca_cmd_defns[] = { + {IBMCA_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'atasi' shared library", + ENGINE_CMD_FLAG_STRING}, + {0, NULL, NULL, 0} + }; + +#ifndef OPENSSL_NO_RSA +/* Our internal RSA_METHOD that we provide pointers to */ +static RSA_METHOD ibmca_rsa = + { + "Ibmca RSA method", + NULL, + NULL, + NULL, + NULL, + ibmca_rsa_mod_exp, + ibmca_mod_exp_mont, + NULL, + NULL, + 0, + NULL, + NULL, + NULL + }; +#endif + +#ifndef OPENSSL_NO_DSA +/* Our internal DSA_METHOD that we provide pointers to */ +static DSA_METHOD ibmca_dsa = + { + "Ibmca DSA method", + NULL, /* dsa_do_sign */ + NULL, /* dsa_sign_setup */ + NULL, /* dsa_do_verify */ + ibmca_dsa_mod_exp, /* dsa_mod_exp */ + ibmca_mod_exp_dsa, /* bn_mod_exp */ + NULL, /* init */ + NULL, /* finish */ + 0, /* flags */ + NULL /* app_data */ + }; +#endif + +#ifndef OPENSSL_NO_DH +/* Our internal DH_METHOD that we provide pointers to */ +static DH_METHOD ibmca_dh = + { + "Ibmca DH method", + NULL, + NULL, + ibmca_mod_exp_dh, + NULL, + NULL, + 0, + NULL + }; +#endif + +static RAND_METHOD ibmca_rand = + { + /* "IBMCA RAND method", */ + NULL, + ibmca_rand_bytes, + NULL, + NULL, + ibmca_rand_bytes, + ibmca_rand_status, + }; + +/* Constants used when creating the ENGINE */ +static const char *engine_ibmca_id = "ibmca"; +static const char *engine_ibmca_name = "Ibmca hardware engine support"; + +/* This internal function is used by ENGINE_ibmca() and possibly by the + * "dynamic" ENGINE support too */ +static int bind_helper(ENGINE *e) + { +#ifndef OPENSSL_NO_RSA + const RSA_METHOD *meth1; +#endif +#ifndef OPENSSL_NO_DSA + const DSA_METHOD *meth2; +#endif +#ifndef OPENSSL_NO_DH + const DH_METHOD *meth3; +#endif + if(!ENGINE_set_id(e, engine_ibmca_id) || + !ENGINE_set_name(e, engine_ibmca_name) || +#ifndef OPENSSL_NO_RSA + !ENGINE_set_RSA(e, &ibmca_rsa) || +#endif +#ifndef OPENSSL_NO_DSA + !ENGINE_set_DSA(e, &ibmca_dsa) || +#endif +#ifndef OPENSSL_NO_DH + !ENGINE_set_DH(e, &ibmca_dh) || +#endif + !ENGINE_set_RAND(e, &ibmca_rand) || + !ENGINE_set_destroy_function(e, ibmca_destroy) || + !ENGINE_set_init_function(e, ibmca_init) || + !ENGINE_set_finish_function(e, ibmca_finish) || + !ENGINE_set_ctrl_function(e, ibmca_ctrl) || + !ENGINE_set_cmd_defns(e, ibmca_cmd_defns)) + return 0; + +#ifndef OPENSSL_NO_RSA + /* We know that the "PKCS1_SSLeay()" functions hook properly + * to the ibmca-specific mod_exp and mod_exp_crt so we use + * those functions. NB: We don't use ENGINE_openssl() or + * anything "more generic" because something like the RSAref + * code may not hook properly, and if you own one of these + * cards then you have the right to do RSA operations on it + * anyway! */ + meth1 = RSA_PKCS1_SSLeay(); + ibmca_rsa.rsa_pub_enc = meth1->rsa_pub_enc; + ibmca_rsa.rsa_pub_dec = meth1->rsa_pub_dec; + ibmca_rsa.rsa_priv_enc = meth1->rsa_priv_enc; + ibmca_rsa.rsa_priv_dec = meth1->rsa_priv_dec; +#endif + +#ifndef OPENSSL_NO_DSA + /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish + * bits. */ + meth2 = DSA_OpenSSL(); + ibmca_dsa.dsa_do_sign = meth2->dsa_do_sign; + ibmca_dsa.dsa_sign_setup = meth2->dsa_sign_setup; + ibmca_dsa.dsa_do_verify = meth2->dsa_do_verify; +#endif + +#ifndef OPENSSL_NO_DH + /* Much the same for Diffie-Hellman */ + meth3 = DH_OpenSSL(); + ibmca_dh.generate_key = meth3->generate_key; + ibmca_dh.compute_key = meth3->compute_key; +#endif + + /* Ensure the ibmca error handling is set up */ + ERR_load_IBMCA_strings(); + return 1; + } + +static ENGINE *engine_ibmca(void) + { + ENGINE *ret = ENGINE_new(); + if(!ret) + return NULL; + if(!bind_helper(ret)) + { + ENGINE_free(ret); + return NULL; + } + return ret; + } + +#ifdef ENGINE_DYNAMIC_SUPPORT +static +#endif +void ENGINE_load_ibmca(void) + { + /* Copied from eng_[openssl|dyn].c */ + ENGINE *toadd = engine_ibmca(); + if(!toadd) return; + ENGINE_add(toadd); + ENGINE_free(toadd); + ERR_clear_error(); + } + +/* Destructor (complements the "ENGINE_ibmca()" constructor) */ +static int ibmca_destroy(ENGINE *e) + { + /* Unload the ibmca error strings so any error state including our + * functs or reasons won't lead to a segfault (they simply get displayed + * without corresponding string data because none will be found). */ + ERR_unload_IBMCA_strings(); + return 1; + } + + +/* This is a process-global DSO handle used for loading and unloading + * the Ibmca library. NB: This is only set (or unset) during an + * init() or finish() call (reference counts permitting) and they're + * operating with global locks, so this should be thread-safe + * implicitly. */ + +static DSO *ibmca_dso = NULL; + +/* These are the function pointers that are (un)set when the library has + * successfully (un)loaded. */ + +static unsigned int (ICA_CALL *p_icaOpenAdapter)(); +static unsigned int (ICA_CALL *p_icaCloseAdapter)(); +static unsigned int (ICA_CALL *p_icaRsaModExpo)(); +static unsigned int (ICA_CALL *p_icaRandomNumberGenerate)(); +static unsigned int (ICA_CALL *p_icaRsaCrt)(); + +/* utility function to obtain a context */ +static int get_context(ICA_ADAPTER_HANDLE *p_handle) + { + unsigned int status=0; + + status = p_icaOpenAdapter(0, p_handle); + if(status != 0) + return 0; + return 1; + } + +/* similarly to release one. */ +static void release_context(ICA_ADAPTER_HANDLE handle) + { + p_icaCloseAdapter(handle); + } + +/* (de)initialisation functions. */ +static int ibmca_init(ENGINE *e) + { + + void (*p1)(); + void (*p2)(); + void (*p3)(); + void (*p4)(); + void (*p5)(); + + if(ibmca_dso != NULL) + { + IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_ALREADY_LOADED); + goto err; + } + /* Attempt to load libatasi.so/atasi.dll/whatever. Needs to be + * changed unfortunately because the Ibmca drivers don't have + * standard library names that can be platform-translated well. */ + /* TODO: Work out how to actually map to the names the Ibmca + * drivers really use - for now a symbollic link needs to be + * created on the host system from libatasi.so to atasi.so on + * unix variants. */ + + /* WJH XXX check name translation */ + + ibmca_dso = DSO_load(NULL, IBMCA_LIBNAME, NULL, + /* DSO_FLAG_NAME_TRANSLATION */ 0); + if(ibmca_dso == NULL) + { + IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_DSO_FAILURE); + goto err; + } + + if(!(p1 = DSO_bind_func( + ibmca_dso, IBMCA_F1)) || + !(p2 = DSO_bind_func( + ibmca_dso, IBMCA_F2)) || + !(p3 = DSO_bind_func( + ibmca_dso, IBMCA_F3)) || + !(p4 = DSO_bind_func( + ibmca_dso, IBMCA_F4)) || + !(p5 = DSO_bind_func( + ibmca_dso, IBMCA_F5))) + { + IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_DSO_FAILURE); + goto err; + } + + /* Copy the pointers */ + + p_icaOpenAdapter = (unsigned int (ICA_CALL *)())p1; + p_icaCloseAdapter = (unsigned int (ICA_CALL *)())p2; + p_icaRsaModExpo = (unsigned int (ICA_CALL *)())p3; + p_icaRandomNumberGenerate = (unsigned int (ICA_CALL *)())p4; + p_icaRsaCrt = (unsigned int (ICA_CALL *)())p5; + + if(!get_context(&handle)) + { + IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_UNIT_FAILURE); + goto err; + } + + return 1; + err: + if(ibmca_dso) + DSO_free(ibmca_dso); + + p_icaOpenAdapter = NULL; + p_icaCloseAdapter = NULL; + p_icaRsaModExpo = NULL; + p_icaRandomNumberGenerate = NULL; + + return 0; + } + +static int ibmca_finish(ENGINE *e) + { + if(ibmca_dso == NULL) + { + IBMCAerr(IBMCA_F_IBMCA_FINISH,IBMCA_R_NOT_LOADED); + return 0; + } + release_context(handle); + if(!DSO_free(ibmca_dso)) + { + IBMCAerr(IBMCA_F_IBMCA_FINISH,IBMCA_R_DSO_FAILURE); + return 0; + } + ibmca_dso = NULL; + + return 1; + } + +static int ibmca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) + { + int initialised = ((ibmca_dso == NULL) ? 0 : 1); + switch(cmd) + { + case IBMCA_CMD_SO_PATH: + if(p == NULL) + { + IBMCAerr(IBMCA_F_IBMCA_CTRL,ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if(initialised) + { + IBMCAerr(IBMCA_F_IBMCA_CTRL,IBMCA_R_ALREADY_LOADED); + return 0; + } + IBMCA_LIBNAME = (const char *)p; + return 1; + default: + break; + } + IBMCAerr(IBMCA_F_IBMCA_CTRL,IBMCA_R_CTRL_COMMAND_NOT_IMPLEMENTED); + return 0; + } + + +static int ibmca_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx) + { + /* I need somewhere to store temporary serialised values for + * use with the Ibmca API calls. A neat cheat - I'll use + * BIGNUMs from the BN_CTX but access their arrays directly as + * byte arrays . This way I don't have to clean anything + * up. */ + + BIGNUM *argument=NULL; + BIGNUM *result=NULL; + BIGNUM *key=NULL; + int to_return; + int inLen, outLen, tmpLen; + + + ICA_KEY_RSA_MODEXPO *publKey=NULL; + unsigned int rc; + + to_return = 0; /* expect failure */ + + if(!ibmca_dso) + { + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_NOT_LOADED); + goto err; + } + /* Prepare the params */ + BN_CTX_start(ctx); + argument = BN_CTX_get(ctx); + result = BN_CTX_get(ctx); + key = BN_CTX_get(ctx); + + if( !argument || !result || !key) + { + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_BN_CTX_FULL); + goto err; + } + + + if(!bn_wexpand(argument, m->top) || !bn_wexpand(result, m->top) || + !bn_wexpand(key, sizeof(*publKey)/BN_BYTES)) + + { + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_BN_EXPAND_FAIL); + goto err; + } + + publKey = (ICA_KEY_RSA_MODEXPO *)key->d; + + if (publKey == NULL) + { + goto err; + } + memset(publKey, 0, sizeof(ICA_KEY_RSA_MODEXPO)); + + publKey->keyType = CORRECT_ENDIANNESS(ME_KEY_TYPE); + publKey->keyLength = CORRECT_ENDIANNESS(sizeof(ICA_KEY_RSA_MODEXPO)); + publKey->expOffset = (char *) publKey->keyRecord - (char *) publKey; + + /* A quirk of the card: the exponent length has to be the same + as the modulus (key) length */ + + outLen = BN_num_bytes(m); + +/* check for modulus length SAB*/ + if (outLen > 256 ) { + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_MEXP_LENGTH_TO_LARGE); + goto err; + } +/* check for modulus length SAB*/ + + + publKey->expLength = publKey->nLength = outLen; +/* SAB Check for underflow condition + the size of the exponent is less than the size of the parameter + then we have a big problem and will underflow the keyRecord + buffer. Bad stuff could happen then +*/ +if (outLen < BN_num_bytes(p)){ + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_UNDERFLOW_KEYRECORD); + goto err; +} +/* SAB End check for underflow */ + + + BN_bn2bin(p, &publKey->keyRecord[publKey->expLength - + BN_num_bytes(p)]); + BN_bn2bin(m, &publKey->keyRecord[publKey->expLength]); + + + + publKey->modulusBitLength = CORRECT_ENDIANNESS(publKey->nLength * 8); + publKey->nOffset = CORRECT_ENDIANNESS(publKey->expOffset + + publKey->expLength); + + publKey->expOffset = CORRECT_ENDIANNESS((char *) publKey->keyRecord - + (char *) publKey); + + tmpLen = outLen; + publKey->expLength = publKey->nLength = CORRECT_ENDIANNESS(tmpLen); + + /* Prepare the argument */ + + memset(argument->d, 0, outLen); + BN_bn2bin(a, (unsigned char *)argument->d + outLen - + BN_num_bytes(a)); + + inLen = outLen; + + /* Perform the operation */ + + if( (rc = p_icaRsaModExpo(handle, inLen,(unsigned char *)argument->d, + publKey, &outLen, (unsigned char *)result->d)) + !=0 ) + + { + printf("rc = %d\n", rc); + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_REQUEST_FAILED); + goto err; + } + + + /* Convert the response */ + BN_bin2bn((unsigned char *)result->d, outLen, r); + to_return = 1; + err: + BN_CTX_end(ctx); + return to_return; + } + +#ifndef OPENSSL_NO_RSA +static int ibmca_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa) + { + BN_CTX *ctx; + int to_return = 0; + + if((ctx = BN_CTX_new()) == NULL) + goto err; + if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) + { + if(!rsa->d || !rsa->n) + { + IBMCAerr(IBMCA_F_IBMCA_RSA_MOD_EXP, + IBMCA_R_MISSING_KEY_COMPONENTS); + goto err; + } + to_return = ibmca_mod_exp(r0, I, rsa->d, rsa->n, ctx); + } + else + { + to_return = ibmca_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1, + rsa->dmq1, rsa->iqmp, ctx); + } + err: + if(ctx) + BN_CTX_free(ctx); + return to_return; + } +#endif + +/* Ein kleines chinesisches "Restessen" */ +static int ibmca_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *q, const BIGNUM *dmp1, + const BIGNUM *dmq1, const BIGNUM *iqmp, BN_CTX *ctx) + { + + BIGNUM *argument = NULL; + BIGNUM *result = NULL; + BIGNUM *key = NULL; + + int to_return = 0; /* expect failure */ + + char *pkey=NULL; + ICA_KEY_RSA_CRT *privKey=NULL; + int inLen, outLen; + + int rc; + unsigned int offset, pSize, qSize; +/* SAB New variables */ + unsigned int keyRecordSize; + unsigned int pbytes = BN_num_bytes(p); + unsigned int qbytes = BN_num_bytes(q); + unsigned int dmp1bytes = BN_num_bytes(dmp1); + unsigned int dmq1bytes = BN_num_bytes(dmq1); + unsigned int iqmpbytes = BN_num_bytes(iqmp); + + /* Prepare the params */ + + BN_CTX_start(ctx); + argument = BN_CTX_get(ctx); + result = BN_CTX_get(ctx); + key = BN_CTX_get(ctx); + + if(!argument || !result || !key) + { + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_BN_CTX_FULL); + goto err; + } + + if(!bn_wexpand(argument, p->top + q->top) || + !bn_wexpand(result, p->top + q->top) || + !bn_wexpand(key, sizeof(*privKey)/BN_BYTES )) + { + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_BN_EXPAND_FAIL); + goto err; + } + + + privKey = (ICA_KEY_RSA_CRT *)key->d; +/* SAB Add check for total size in bytes of the parms does not exceed + the buffer space we have + do this first +*/ + keyRecordSize = pbytes+qbytes+dmp1bytes+dmq1bytes+iqmpbytes; + if ( keyRecordSize > sizeof(privKey->keyRecord )) { + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE); + goto err; + } + + if ( (qbytes + dmq1bytes) > 256 ){ + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE); + goto err; + } + + if ( pbytes + dmp1bytes > 256 ) { + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE); + goto err; + } + +/* end SAB additions */ + + memset(privKey, 0, sizeof(ICA_KEY_RSA_CRT)); + privKey->keyType = CORRECT_ENDIANNESS(CRT_KEY_TYPE); + privKey->keyLength = CORRECT_ENDIANNESS(sizeof(ICA_KEY_RSA_CRT)); + privKey->modulusBitLength = + CORRECT_ENDIANNESS(BN_num_bytes(q) * 2 * 8); + + /* + * p,dp & qInv are 1 QWORD Larger + */ + privKey->pLength = CORRECT_ENDIANNESS(BN_num_bytes(p)+8); + privKey->qLength = CORRECT_ENDIANNESS(BN_num_bytes(q)); + privKey->dpLength = CORRECT_ENDIANNESS(BN_num_bytes(dmp1)+8); + privKey->dqLength = CORRECT_ENDIANNESS(BN_num_bytes(dmq1)); + privKey->qInvLength = CORRECT_ENDIANNESS(BN_num_bytes(iqmp)+8); + + offset = (char *) privKey->keyRecord + - (char *) privKey; + + qSize = BN_num_bytes(q); + pSize = qSize + 8; /* 1 QWORD larger */ + + +/* SAB probably aittle redundant, but we'll verify that each of the + components which make up a key record sent ot the card does not exceed + the space that is allocated for it. this handles the case where even if + the total length does not exceed keyrecord zied, if the operands are funny sized +they could cause potential side affects on either the card or the result */ + + if ( (pbytes > pSize) || (dmp1bytes > pSize) || + (iqmpbytes > pSize) || ( qbytes >qSize) || + (dmq1bytes > qSize) ) { + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT, IBMCA_R_OPERANDS_TO_LARGE); + goto err; + + } + + + privKey->dpOffset = CORRECT_ENDIANNESS(offset); + + offset += pSize; + privKey->dqOffset = CORRECT_ENDIANNESS(offset); + + offset += qSize; + privKey->pOffset = CORRECT_ENDIANNESS(offset); + + offset += pSize; + privKey->qOffset = CORRECT_ENDIANNESS(offset); + + offset += qSize; + privKey->qInvOffset = CORRECT_ENDIANNESS(offset); + + pkey = (char *) privKey->keyRecord; + + +/* SAB first check that we don;t under flow the buffer */ + if ( pSize < pbytes ) { + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT, IBMCA_R_UNDERFLOW_CONDITION); + goto err; + } + + /* pkey += pSize - BN_num_bytes(p); WROING this should be dmp1) */ + pkey += pSize - BN_num_bytes(dmp1); + BN_bn2bin(dmp1, pkey); + pkey += BN_num_bytes(dmp1); /* move the pointer */ + + BN_bn2bin(dmq1, pkey); /* Copy over dmq1 */ + + pkey += qSize; /* move pointer */ + pkey += pSize - BN_num_bytes(p); /* set up for zero padding of next field */ + + BN_bn2bin(p, pkey); + pkey += BN_num_bytes(p); /* increment pointer by number of bytes moved */ + + BN_bn2bin(q, pkey); + pkey += qSize ; /* move the pointer */ + pkey += pSize - BN_num_bytes(iqmp); /* Adjust for padding */ + BN_bn2bin(iqmp, pkey); + + /* Prepare the argument and response */ + + outLen = CORRECT_ENDIANNESS(privKey->qLength) * 2; /* Correct endianess is used + because the fields were converted above */ + + if (outLen > 256) { + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OUTLEN_TO_LARGE); + goto err; + } + + /* SAB check for underflow here on the argeument */ + if ( outLen < BN_num_bytes(a)) { + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_UNDERFLOW_CONDITION); + goto err; + } + + BN_bn2bin(a, (unsigned char *)argument->d + outLen - + BN_num_bytes(a)); + inLen = outLen; + + memset(result->d, 0, outLen); + + /* Perform the operation */ + + if ( (rc = p_icaRsaCrt(handle, inLen, (unsigned char *)argument->d, + privKey, &outLen, (unsigned char *)result->d)) != 0) + { + printf("rc = %d\n", rc); + IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_REQUEST_FAILED); + goto err; + } + + /* Convert the response */ + + BN_bin2bn((unsigned char *)result->d, outLen, r); + to_return = 1; + + err: + BN_CTX_end(ctx); + return to_return; + + } + +#ifndef OPENSSL_NO_DSA +/* This code was liberated and adapted from the commented-out code in + * dsa_ossl.c. Because of the unoptimised form of the Ibmca acceleration + * (it doesn't have a CRT form for RSA), this function means that an + * Ibmca system running with a DSA server certificate can handshake + * around 5 or 6 times faster/more than an equivalent system running with + * RSA. Just check out the "signs" statistics from the RSA and DSA parts + * of "openssl speed -engine ibmca dsa1024 rsa1024". */ +static int ibmca_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, + BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, + BN_CTX *ctx, BN_MONT_CTX *in_mont) + { + BIGNUM t; + int to_return = 0; + + BN_init(&t); + /* let rr = a1 ^ p1 mod m */ + if (!ibmca_mod_exp(rr,a1,p1,m,ctx)) goto end; + /* let t = a2 ^ p2 mod m */ + if (!ibmca_mod_exp(&t,a2,p2,m,ctx)) goto end; + /* let rr = rr * t mod m */ + if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end; + to_return = 1; + end: + BN_free(&t); + return to_return; + } + + +static int ibmca_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx) + { + return ibmca_mod_exp(r, a, p, m, ctx); + } +#endif + +/* This function is aliased to mod_exp (with the mont stuff dropped). */ +static int ibmca_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) + { + return ibmca_mod_exp(r, a, p, m, ctx); + } + +#ifndef OPENSSL_NO_DH +/* This function is aliased to mod_exp (with the dh and mont dropped). */ +static int ibmca_mod_exp_dh(DH const *dh, BIGNUM *r, + const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) + { + return ibmca_mod_exp(r, a, p, m, ctx); + } +#endif + +/* Random bytes are good */ +static int ibmca_rand_bytes(unsigned char *buf, int num) + { + int to_return = 0; /* assume failure */ + unsigned int ret; + + + if(handle == 0) + { + IBMCAerr(IBMCA_F_IBMCA_RAND_BYTES,IBMCA_R_NOT_INITIALISED); + goto err; + } + + ret = p_icaRandomNumberGenerate(handle, num, buf); + if (ret < 0) + { + IBMCAerr(IBMCA_F_IBMCA_RAND_BYTES,IBMCA_R_REQUEST_FAILED); + goto err; + } + to_return = 1; + err: + return to_return; + } + +static int ibmca_rand_status(void) + { + return 1; + } + +/* This stuff is needed if this ENGINE is being compiled into a self-contained + * shared-library. */ +#ifdef ENGINE_DYNAMIC_SUPPORT +static int bind_fn(ENGINE *e, const char *id) + { + if(id && (strcmp(id, engine_ibmca_id) != 0)) /* WJH XXX */ + return 0; + if(!bind_helper(e)) + return 0; + return 1; + } +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) +#endif /* ENGINE_DYNAMIC_SUPPORT */ + + +#endif /* !OPENSSL_NO_HW_IBMCA */ +#endif /* !OPENSSL_NO_HW */ diff --git a/dmg/partition.c b/dmg/partition.c index 81a62b4..7456f2c 100644 --- a/dmg/partition.c +++ b/dmg/partition.c @@ -1,788 +1,788 @@ -#include -#include - -#include "dmg.h" - -static unsigned char atapi_data [4096] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 -}; - -static void flipDriverDescriptor(DriverDescriptor* descriptor) { - FLIPENDIAN(descriptor->ddBlock); - FLIPENDIAN(descriptor->ddSize); - FLIPENDIAN(descriptor->ddType); -} - -void flipDriverDescriptorRecord(DriverDescriptorRecord* record, char out) { - int i; - - FLIPENDIAN(record->sbSig); - FLIPENDIAN(record->sbBlkSize); - FLIPENDIAN(record->sbBlkCount); - FLIPENDIAN(record->sbDevType); - FLIPENDIAN(record->sbDevId); - FLIPENDIAN(record->sbData); - FLIPENDIAN(record->ddBlock); - FLIPENDIAN(record->ddSize); - FLIPENDIAN(record->ddType); - - if(out) { - for(i = 0; i < record->sbDrvrCount; i++) { - flipDriverDescriptor(&(record->ddPad[i])); - } - FLIPENDIAN(record->sbDrvrCount); - } else { - if(record->sbSig != DRIVER_DESCRIPTOR_SIGNATURE) { - return; - } - - FLIPENDIAN(record->sbDrvrCount); - for(i = 0; i < record->sbDrvrCount; i++) { - flipDriverDescriptor(&(record->ddPad[i])); - } - } -} - -void flipPartitionMultiple(Partition* partition, char multiple, char out) { - int i; - int numPartitions; - - if(out) { - numPartitions = partition->pmMapBlkCnt; - } else { - numPartitions = partition->pmMapBlkCnt; - FLIPENDIAN(numPartitions); - } - - for(i = 0; i < numPartitions; i++) { - if(out) { - if(partition[i].pmSig != APPLE_PARTITION_MAP_SIGNATURE) { - break; - } - FLIPENDIAN(partition[i].pmSig); - } else { - FLIPENDIAN(partition[i].pmSig); - if(partition[i].pmSig != APPLE_PARTITION_MAP_SIGNATURE) { - break; - } - } - - FLIPENDIAN(partition[i].pmMapBlkCnt); - FLIPENDIAN(partition[i].pmPyPartStart); - FLIPENDIAN(partition[i].pmPartBlkCnt); - FLIPENDIAN(partition[i].pmLgDataStart); - FLIPENDIAN(partition[i].pmDataCnt); - FLIPENDIAN(partition[i].pmPartStatus); - FLIPENDIAN(partition[i].pmLgBootStart); - FLIPENDIAN(partition[i].pmBootSize); - FLIPENDIAN(partition[i].pmBootAddr); - FLIPENDIAN(partition[i].pmBootAddr2); - FLIPENDIAN(partition[i].pmBootEntry); - FLIPENDIAN(partition[i].pmBootEntry2); - FLIPENDIAN(partition[i].pmBootCksum); - FLIPENDIAN(partition[i].bootCode); - - if(!multiple) { - break; - } - } -} - -void flipPartition(Partition* partition, char out) { - flipPartitionMultiple(partition, TRUE, out); -} - - -void readDriverDescriptorMap(AbstractFile* file, ResourceKey* resources) { - BLKXTable* blkx; - unsigned char* buffer; - AbstractFile* bufferFile; - DriverDescriptorRecord* record; - int i; - - blkx = (BLKXTable*) (getDataByID(getResourceByKey(resources, "blkx"), -1)->data); - - buffer = (unsigned char*) malloc(512); - bufferFile = createAbstractFileFromMemory((void**)&(buffer), 512); - extractBLKX(file, bufferFile, blkx); - bufferFile->close(bufferFile); - - record = (DriverDescriptorRecord*)buffer; - flipDriverDescriptorRecord(record, FALSE); - printf("sbSig:\t\t0x%x\n", record->sbSig); - printf("sbBlkSize:\t0x%x\n", record->sbBlkSize); - printf("sbBlkCount:\t0x%x\n", record->sbBlkCount); - printf("sbDevType:\t0x%x\n", record->sbDevType); - printf("sbDevId:\t0x%x\n", record->sbDevId); - printf("sbData:\t\t0x%x\n", record->sbData); - printf("sbDrvrCount:\t0x%x\n", record->sbDrvrCount); - printf("ddBlock:\t0x%x\n", record->ddBlock); - printf("ddSize:\t\t0x%x\n", record->ddSize); - printf("ddType:\t\t0x%x\n", record->ddType); - - for(i = 0; i < (record->sbDrvrCount - 1); i++) { - printf("\tddBlock:\t0x%x\n", record->ddPad[i].ddBlock); - printf("\tddSize:\t\t0x%x\n", record->ddPad[i].ddSize); - printf("\tddType:\t\t0x%x\n", record->ddPad[i].ddType); - } - - free(buffer); -} - -DriverDescriptorRecord* createDriverDescriptorMap(uint32_t numSectors) { - DriverDescriptorRecord* toReturn; - - toReturn = (DriverDescriptorRecord*) malloc(SECTOR_SIZE); - memset(toReturn, 0, SECTOR_SIZE); - - toReturn->sbSig = DRIVER_DESCRIPTOR_SIGNATURE; - toReturn->sbBlkSize = SECTOR_SIZE; - toReturn->sbBlkCount = numSectors + EXTRA_SIZE; - toReturn->sbDevType = 0; - toReturn->sbDevId = 0; - toReturn->sbData = 0; - toReturn->sbDrvrCount = 1; - toReturn->ddBlock = ATAPI_OFFSET; - toReturn->ddSize = 0x4; - toReturn->ddType = 0x701; - - return toReturn; -} - -void writeDriverDescriptorMap(AbstractFile* file, DriverDescriptorRecord* DDM, ChecksumFunc dataForkChecksum, void* dataForkToken, - ResourceKey **resources) { - AbstractFile* bufferFile; - BLKXTable* blkx; - ChecksumToken uncompressedToken; - DriverDescriptorRecord* buffer; - - buffer = (DriverDescriptorRecord*) malloc(DDM_SIZE * SECTOR_SIZE); - memcpy(buffer, DDM, DDM_SIZE * SECTOR_SIZE); - memset(&uncompressedToken, 0, sizeof(uncompressedToken)); - - flipDriverDescriptorRecord(buffer, TRUE); - - bufferFile = createAbstractFileFromMemory((void**)&buffer, DDM_SIZE * SECTOR_SIZE); - - blkx = insertBLKX(file, bufferFile, DDM_OFFSET, DDM_SIZE, DDM_DESCRIPTOR, CHECKSUM_CRC32, &CRCProxy, &uncompressedToken, - dataForkChecksum, dataForkToken, NULL); - - blkx->checksum.data[0] = uncompressedToken.crc; - - *resources = insertData(*resources, "blkx", -1, "Driver Descriptor Map (DDM : 0)", (const char*) blkx, sizeof(BLKXTable) + (blkx->blocksRunCount * sizeof(BLKXRun)), ATTRIBUTE_HDIUTIL); - - free(buffer); - bufferFile->close(bufferFile); - free(blkx); -} - -void writeApplePartitionMap(AbstractFile* file, Partition* partitions, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn) { - AbstractFile* bufferFile; - BLKXTable* blkx; - ChecksumToken uncompressedToken; - Partition* buffer; - NSizResource* nsiz; - CSumResource csum; - - buffer = (Partition*) malloc(PARTITION_SIZE * SECTOR_SIZE); - memcpy(buffer, partitions, PARTITION_SIZE * SECTOR_SIZE); - memset(&uncompressedToken, 0, sizeof(uncompressedToken)); - - flipPartition(buffer, TRUE); - - bufferFile = createAbstractFileFromMemory((void**)&buffer, PARTITION_SIZE * SECTOR_SIZE); - - blkx = insertBLKX(file, bufferFile, PARTITION_OFFSET, PARTITION_SIZE, 0, CHECKSUM_CRC32, - &BlockCRC, &uncompressedToken, dataForkChecksum, dataForkToken, NULL); - - bufferFile->close(bufferFile); - - *((uint32_t*)blkx->checksum.data) = uncompressedToken.crc; - - csum.version = 1; - csum.type = CHECKSUM_MKBLOCK; - csum.checksum = uncompressedToken.block; - - *resources = insertData(*resources, "blkx", 0, "Apple (Apple_partition_map : 1)", (const char*) blkx, sizeof(BLKXTable) + (blkx->blocksRunCount * sizeof(BLKXRun)), ATTRIBUTE_HDIUTIL); - *resources = insertData(*resources, "cSum", 0, "", (const char*) (&csum), sizeof(csum), 0); - - nsiz = (NSizResource*) malloc(sizeof(NSizResource)); - memset(nsiz, 0, sizeof(NSizResource)); - nsiz->isVolume = FALSE; - nsiz->blockChecksum2 = uncompressedToken.block; - nsiz->partitionNumber = 0; - nsiz->version = 6; - nsiz->next = NULL; - - if((*nsizIn) == NULL) { - *nsizIn = nsiz; - } else { - nsiz->next = (*nsizIn)->next; - (*nsizIn)->next = nsiz; - } - - free(buffer); - free(blkx); -} - -void writeATAPI(AbstractFile* file, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn) { - AbstractFile* bufferFile; - BLKXTable* blkx; - ChecksumToken uncompressedToken; - NSizResource* nsiz; - CSumResource csum; - char* atapi; - - memset(&uncompressedToken, 0, sizeof(uncompressedToken)); +#include +#include + +#include "dmg.h" + +static unsigned char atapi_data [4096] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +static void flipDriverDescriptor(DriverDescriptor* descriptor) { + FLIPENDIAN(descriptor->ddBlock); + FLIPENDIAN(descriptor->ddSize); + FLIPENDIAN(descriptor->ddType); +} + +void flipDriverDescriptorRecord(DriverDescriptorRecord* record, char out) { + int i; + + FLIPENDIAN(record->sbSig); + FLIPENDIAN(record->sbBlkSize); + FLIPENDIAN(record->sbBlkCount); + FLIPENDIAN(record->sbDevType); + FLIPENDIAN(record->sbDevId); + FLIPENDIAN(record->sbData); + FLIPENDIAN(record->ddBlock); + FLIPENDIAN(record->ddSize); + FLIPENDIAN(record->ddType); + + if(out) { + for(i = 0; i < record->sbDrvrCount; i++) { + flipDriverDescriptor(&(record->ddPad[i])); + } + FLIPENDIAN(record->sbDrvrCount); + } else { + if(record->sbSig != DRIVER_DESCRIPTOR_SIGNATURE) { + return; + } + + FLIPENDIAN(record->sbDrvrCount); + for(i = 0; i < record->sbDrvrCount; i++) { + flipDriverDescriptor(&(record->ddPad[i])); + } + } +} + +void flipPartitionMultiple(Partition* partition, char multiple, char out) { + int i; + int numPartitions; + + if(out) { + numPartitions = partition->pmMapBlkCnt; + } else { + numPartitions = partition->pmMapBlkCnt; + FLIPENDIAN(numPartitions); + } + + for(i = 0; i < numPartitions; i++) { + if(out) { + if(partition[i].pmSig != APPLE_PARTITION_MAP_SIGNATURE) { + break; + } + FLIPENDIAN(partition[i].pmSig); + } else { + FLIPENDIAN(partition[i].pmSig); + if(partition[i].pmSig != APPLE_PARTITION_MAP_SIGNATURE) { + break; + } + } + + FLIPENDIAN(partition[i].pmMapBlkCnt); + FLIPENDIAN(partition[i].pmPyPartStart); + FLIPENDIAN(partition[i].pmPartBlkCnt); + FLIPENDIAN(partition[i].pmLgDataStart); + FLIPENDIAN(partition[i].pmDataCnt); + FLIPENDIAN(partition[i].pmPartStatus); + FLIPENDIAN(partition[i].pmLgBootStart); + FLIPENDIAN(partition[i].pmBootSize); + FLIPENDIAN(partition[i].pmBootAddr); + FLIPENDIAN(partition[i].pmBootAddr2); + FLIPENDIAN(partition[i].pmBootEntry); + FLIPENDIAN(partition[i].pmBootEntry2); + FLIPENDIAN(partition[i].pmBootCksum); + FLIPENDIAN(partition[i].bootCode); + + if(!multiple) { + break; + } + } +} + +void flipPartition(Partition* partition, char out) { + flipPartitionMultiple(partition, TRUE, out); +} + + +void readDriverDescriptorMap(AbstractFile* file, ResourceKey* resources) { + BLKXTable* blkx; + unsigned char* buffer; + AbstractFile* bufferFile; + DriverDescriptorRecord* record; + int i; + + blkx = (BLKXTable*) (getDataByID(getResourceByKey(resources, "blkx"), -1)->data); + + buffer = (unsigned char*) malloc(512); + bufferFile = createAbstractFileFromMemory((void**)&(buffer), 512); + extractBLKX(file, bufferFile, blkx); + bufferFile->close(bufferFile); + + record = (DriverDescriptorRecord*)buffer; + flipDriverDescriptorRecord(record, FALSE); + printf("sbSig:\t\t0x%x\n", record->sbSig); + printf("sbBlkSize:\t0x%x\n", record->sbBlkSize); + printf("sbBlkCount:\t0x%x\n", record->sbBlkCount); + printf("sbDevType:\t0x%x\n", record->sbDevType); + printf("sbDevId:\t0x%x\n", record->sbDevId); + printf("sbData:\t\t0x%x\n", record->sbData); + printf("sbDrvrCount:\t0x%x\n", record->sbDrvrCount); + printf("ddBlock:\t0x%x\n", record->ddBlock); + printf("ddSize:\t\t0x%x\n", record->ddSize); + printf("ddType:\t\t0x%x\n", record->ddType); + + for(i = 0; i < (record->sbDrvrCount - 1); i++) { + printf("\tddBlock:\t0x%x\n", record->ddPad[i].ddBlock); + printf("\tddSize:\t\t0x%x\n", record->ddPad[i].ddSize); + printf("\tddType:\t\t0x%x\n", record->ddPad[i].ddType); + } + + free(buffer); +} + +DriverDescriptorRecord* createDriverDescriptorMap(uint32_t numSectors) { + DriverDescriptorRecord* toReturn; + + toReturn = (DriverDescriptorRecord*) malloc(SECTOR_SIZE); + memset(toReturn, 0, SECTOR_SIZE); + + toReturn->sbSig = DRIVER_DESCRIPTOR_SIGNATURE; + toReturn->sbBlkSize = SECTOR_SIZE; + toReturn->sbBlkCount = numSectors + EXTRA_SIZE; + toReturn->sbDevType = 0; + toReturn->sbDevId = 0; + toReturn->sbData = 0; + toReturn->sbDrvrCount = 1; + toReturn->ddBlock = ATAPI_OFFSET; + toReturn->ddSize = 0x4; + toReturn->ddType = 0x701; + + return toReturn; +} + +void writeDriverDescriptorMap(AbstractFile* file, DriverDescriptorRecord* DDM, ChecksumFunc dataForkChecksum, void* dataForkToken, + ResourceKey **resources) { + AbstractFile* bufferFile; + BLKXTable* blkx; + ChecksumToken uncompressedToken; + DriverDescriptorRecord* buffer; + + buffer = (DriverDescriptorRecord*) malloc(DDM_SIZE * SECTOR_SIZE); + memcpy(buffer, DDM, DDM_SIZE * SECTOR_SIZE); + memset(&uncompressedToken, 0, sizeof(uncompressedToken)); + + flipDriverDescriptorRecord(buffer, TRUE); + + bufferFile = createAbstractFileFromMemory((void**)&buffer, DDM_SIZE * SECTOR_SIZE); + + blkx = insertBLKX(file, bufferFile, DDM_OFFSET, DDM_SIZE, DDM_DESCRIPTOR, CHECKSUM_CRC32, &CRCProxy, &uncompressedToken, + dataForkChecksum, dataForkToken, NULL); + + blkx->checksum.data[0] = uncompressedToken.crc; + + *resources = insertData(*resources, "blkx", -1, "Driver Descriptor Map (DDM : 0)", (const char*) blkx, sizeof(BLKXTable) + (blkx->blocksRunCount * sizeof(BLKXRun)), ATTRIBUTE_HDIUTIL); + + free(buffer); + bufferFile->close(bufferFile); + free(blkx); +} + +void writeApplePartitionMap(AbstractFile* file, Partition* partitions, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn) { + AbstractFile* bufferFile; + BLKXTable* blkx; + ChecksumToken uncompressedToken; + Partition* buffer; + NSizResource* nsiz; + CSumResource csum; + + buffer = (Partition*) malloc(PARTITION_SIZE * SECTOR_SIZE); + memcpy(buffer, partitions, PARTITION_SIZE * SECTOR_SIZE); + memset(&uncompressedToken, 0, sizeof(uncompressedToken)); + + flipPartition(buffer, TRUE); + + bufferFile = createAbstractFileFromMemory((void**)&buffer, PARTITION_SIZE * SECTOR_SIZE); + + blkx = insertBLKX(file, bufferFile, PARTITION_OFFSET, PARTITION_SIZE, 0, CHECKSUM_CRC32, + &BlockCRC, &uncompressedToken, dataForkChecksum, dataForkToken, NULL); + + bufferFile->close(bufferFile); + + *((uint32_t*)blkx->checksum.data) = uncompressedToken.crc; + + csum.version = 1; + csum.type = CHECKSUM_MKBLOCK; + csum.checksum = uncompressedToken.block; + + *resources = insertData(*resources, "blkx", 0, "Apple (Apple_partition_map : 1)", (const char*) blkx, sizeof(BLKXTable) + (blkx->blocksRunCount * sizeof(BLKXRun)), ATTRIBUTE_HDIUTIL); + *resources = insertData(*resources, "cSum", 0, "", (const char*) (&csum), sizeof(csum), 0); + + nsiz = (NSizResource*) malloc(sizeof(NSizResource)); + memset(nsiz, 0, sizeof(NSizResource)); + nsiz->isVolume = FALSE; + nsiz->blockChecksum2 = uncompressedToken.block; + nsiz->partitionNumber = 0; + nsiz->version = 6; + nsiz->next = NULL; + + if((*nsizIn) == NULL) { + *nsizIn = nsiz; + } else { + nsiz->next = (*nsizIn)->next; + (*nsizIn)->next = nsiz; + } + + free(buffer); + free(blkx); +} + +void writeATAPI(AbstractFile* file, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn) { + AbstractFile* bufferFile; + BLKXTable* blkx; + ChecksumToken uncompressedToken; + NSizResource* nsiz; + CSumResource csum; + char* atapi; + + memset(&uncompressedToken, 0, sizeof(uncompressedToken)); atapi = (char*) malloc(ATAPI_SIZE * SECTOR_SIZE); - printf("malloc: %x %d\n", atapi, ATAPI_SIZE * SECTOR_SIZE); fflush(stdout); - memcpy(atapi, atapi_data, ATAPI_SIZE * SECTOR_SIZE); - bufferFile = createAbstractFileFromMemory((void**)&atapi, ATAPI_SIZE * SECTOR_SIZE); - - blkx = insertBLKX(file, bufferFile, ATAPI_OFFSET, ATAPI_SIZE, 1, CHECKSUM_CRC32, - &BlockCRC, &uncompressedToken, dataForkChecksum, dataForkToken, NULL); + printf("malloc: %x %d\n", atapi, ATAPI_SIZE * SECTOR_SIZE); fflush(stdout); + memcpy(atapi, atapi_data, ATAPI_SIZE * SECTOR_SIZE); + bufferFile = createAbstractFileFromMemory((void**)&atapi, ATAPI_SIZE * SECTOR_SIZE); + + blkx = insertBLKX(file, bufferFile, ATAPI_OFFSET, ATAPI_SIZE, 1, CHECKSUM_CRC32, + &BlockCRC, &uncompressedToken, dataForkChecksum, dataForkToken, NULL); bufferFile->close(bufferFile); - free(atapi); - - blkx->checksum.data[0] = uncompressedToken.crc; - - csum.version = 1; - csum.type = CHECKSUM_MKBLOCK; - csum.checksum = uncompressedToken.block; - - *resources = insertData(*resources, "blkx", 1, "Macintosh (Apple_Driver_ATAPI : 2)", (const char*) blkx, sizeof(BLKXTable) + (blkx->blocksRunCount * sizeof(BLKXRun)), ATTRIBUTE_HDIUTIL); - *resources = insertData(*resources, "cSum", 1, "", (const char*) (&csum), sizeof(csum), 0); - - nsiz = (NSizResource*) malloc(sizeof(NSizResource)); - memset(nsiz, 0, sizeof(NSizResource)); - nsiz->isVolume = FALSE; - nsiz->blockChecksum2 = uncompressedToken.block; - nsiz->partitionNumber = 1; - nsiz->version = 6; - nsiz->next = NULL; - - if((*nsizIn) == NULL) { - *nsizIn = nsiz; - } else { - nsiz->next = (*nsizIn)->next; - (*nsizIn)->next = nsiz; - } - - free(blkx); -} - - -void readApplePartitionMap(AbstractFile* file, ResourceKey* resources) { - AbstractFile* bufferFile; - BLKXTable* blkx; - Partition* partition; - int i; - - blkx = (BLKXTable*) (getDataByID(getResourceByKey(resources, "blkx"), 0)->data); - - partition = (Partition*) malloc(512); - bufferFile = createAbstractFileFromMemory((void**)&partition, 512); - extractBLKX(file, bufferFile, blkx); - bufferFile->close(bufferFile); - - flipPartition(partition, FALSE); - - for(i = 0; i < partition->pmMapBlkCnt; i++) { - if(partition[i].pmSig != APPLE_PARTITION_MAP_SIGNATURE) { - break; - } - - printf("pmSig:\t\t\t0x%x\n", partition[i].pmSig); - printf("pmSigPad:\t\t0x%x\n", partition[i].pmSigPad); - printf("pmMapBlkCnt:\t\t0x%x\n", partition[i].pmMapBlkCnt); - printf("pmPartName:\t\t%s\n", partition[i].pmPartName); - printf("pmParType:\t\t%s\n", partition[i].pmParType); - printf("pmPyPartStart:\t\t0x%x\n", partition[i].pmPyPartStart); - printf("pmPartBlkCnt:\t\t0x%x\n", partition[i].pmPartBlkCnt); - printf("pmLgDataStart:\t\t0x%x\n", partition[i].pmLgDataStart); - printf("pmDataCnt:\t\t0x%x\n", partition[i].pmDataCnt); - printf("pmPartStatus:\t\t0x%x\n", partition[i].pmPartStatus); - printf("pmLgBootStart:\t\t0x%x\n", partition[i].pmLgBootStart); - printf("pmBootSize:\t\t0x%x\n", partition[i].pmBootSize); - printf("pmBootAddr:\t\t0x%x\n", partition[i].pmBootAddr); - printf("pmBootAddr2:\t\t0x%x\n", partition[i].pmBootAddr2); - printf("pmBootEntry:\t\t0x%x\n", partition[i].pmBootEntry); - printf("pmBootEntry2:\t\t0x%x\n", partition[i].pmBootEntry2); - printf("pmBootCksum:\t\t0x%x\n", partition[i].pmBootCksum); - printf("pmProcessor:\t\t\t%s\n\n", partition[i].pmProcessor); - } - - free(partition); -} - -Partition* createApplePartitionMap(uint32_t numSectors, const char* volumeType) { - Partition* partition; - - partition = (Partition*) malloc(SECTOR_SIZE * PARTITION_SIZE); - memset(partition, 0, SECTOR_SIZE * PARTITION_SIZE); - - partition[0].pmSig = APPLE_PARTITION_MAP_SIGNATURE; - partition[0].pmSigPad = 0; - partition[0].pmMapBlkCnt = 0x4; - strcpy((char*)partition[0].pmPartName, "Apple"); - strcpy((char*)partition[0].pmParType, "Apple_partition_map"); - partition[0].pmPyPartStart = PARTITION_OFFSET; - partition[0].pmPartBlkCnt = PARTITION_SIZE; - partition[0].pmLgDataStart = 0; - partition[0].pmDataCnt = PARTITION_SIZE; - partition[0].pmPartStatus = 0x3; - partition[0].pmLgBootStart = 0x0; - partition[0].pmBootSize = 0x0; - partition[0].pmBootAddr = 0x0; - partition[0].pmBootAddr2 = 0x0; - partition[0].pmBootEntry = 0x0; - partition[0].pmBootEntry2 = 0x0; - partition[0].pmBootCksum = 0x0; - partition[0].pmProcessor[0] = '\0'; - partition[0].bootCode = 0; - - partition[1].pmSig = APPLE_PARTITION_MAP_SIGNATURE; - partition[1].pmSigPad = 0; - partition[1].pmMapBlkCnt = 0x4; - strcpy((char*)partition[1].pmPartName, "Macintosh"); - strcpy((char*)partition[1].pmParType, "Apple_Driver_ATAPI"); - partition[1].pmPyPartStart = ATAPI_OFFSET; - partition[1].pmPartBlkCnt = ATAPI_SIZE; - partition[1].pmLgDataStart = 0; - partition[1].pmDataCnt = 0x04; - partition[1].pmPartStatus = 0x303; - partition[1].pmLgBootStart = 0x0; - partition[1].pmBootSize = 0x800; - partition[1].pmBootAddr = 0x0; - partition[1].pmBootAddr2 = 0x0; - partition[1].pmBootEntry = 0x0; - partition[1].pmBootEntry2 = 0x0; - partition[1].pmBootCksum = 0xffff; - partition[1].pmProcessor[0] = '\0'; - partition[1].bootCode = BOOTCODE_DMMY; - - partition[2].pmSig = APPLE_PARTITION_MAP_SIGNATURE; - partition[2].pmSigPad = 0; - partition[2].pmMapBlkCnt = 0x4; - strcpy((char*)partition[2].pmPartName, "Mac_OS_X"); - strcpy((char*)partition[2].pmParType, volumeType); - partition[2].pmPyPartStart = USER_OFFSET; - partition[2].pmPartBlkCnt = numSectors; - partition[2].pmLgDataStart = 0; - partition[2].pmDataCnt = numSectors; - partition[2].pmPartStatus = 0x40000033; - partition[2].pmLgBootStart = 0x0; - partition[2].pmBootSize = 0x0; - partition[2].pmBootAddr = 0x0; - partition[2].pmBootAddr2 = 0x0; - partition[2].pmBootEntry = 0x0; - partition[2].pmBootEntry2 = 0x0; - partition[2].pmBootCksum = 0x0; - partition[2].pmProcessor[0] = '\0'; - partition[2].bootCode = BOOTCODE_GOON; - - partition[3].pmSig = APPLE_PARTITION_MAP_SIGNATURE; - partition[3].pmSigPad = 0; - partition[3].pmMapBlkCnt = 0x4; - partition[3].pmPartName[0] = '\0'; - strcpy((char*)partition[3].pmParType, "Apple_Free"); - partition[3].pmPyPartStart = USER_OFFSET + numSectors; - partition[3].pmPartBlkCnt = FREE_SIZE; - partition[3].pmLgDataStart = 0; - partition[3].pmDataCnt = 0x0; - partition[3].pmPartStatus = 0x0; - partition[3].pmLgBootStart = 0x0; - partition[3].pmBootSize = 0x0; - partition[3].pmBootAddr = 0x0; - partition[3].pmBootAddr2 = 0x0; - partition[3].pmBootEntry = 0x0; - partition[3].pmBootEntry2 = 0x0; - partition[3].pmBootCksum = 0x0; - partition[3].pmProcessor[0] = '\0'; - partition[3].bootCode = 0; - - return partition; -} - -void writeFreePartition(AbstractFile* outFile, uint32_t numSectors, ResourceKey** resources) { - BLKXTable* blkx; - - blkx = (BLKXTable*) malloc(sizeof(BLKXTable) + (2 * sizeof(BLKXRun))); - - blkx->fUDIFBlocksSignature = UDIF_BLOCK_SIGNATURE; - blkx->infoVersion = 1; - blkx->firstSectorNumber = USER_OFFSET + numSectors; - blkx->sectorCount = FREE_SIZE; - blkx->dataStart = 0; - blkx->decompressBufferRequested = 0; - blkx->blocksDescriptor = 3; - blkx->reserved1 = 0; - blkx->reserved2 = 0; - blkx->reserved3 = 0; - blkx->reserved4 = 0; - blkx->reserved5 = 0; + free(atapi); + + blkx->checksum.data[0] = uncompressedToken.crc; + + csum.version = 1; + csum.type = CHECKSUM_MKBLOCK; + csum.checksum = uncompressedToken.block; + + *resources = insertData(*resources, "blkx", 1, "Macintosh (Apple_Driver_ATAPI : 2)", (const char*) blkx, sizeof(BLKXTable) + (blkx->blocksRunCount * sizeof(BLKXRun)), ATTRIBUTE_HDIUTIL); + *resources = insertData(*resources, "cSum", 1, "", (const char*) (&csum), sizeof(csum), 0); + + nsiz = (NSizResource*) malloc(sizeof(NSizResource)); + memset(nsiz, 0, sizeof(NSizResource)); + nsiz->isVolume = FALSE; + nsiz->blockChecksum2 = uncompressedToken.block; + nsiz->partitionNumber = 1; + nsiz->version = 6; + nsiz->next = NULL; + + if((*nsizIn) == NULL) { + *nsizIn = nsiz; + } else { + nsiz->next = (*nsizIn)->next; + (*nsizIn)->next = nsiz; + } + + free(blkx); +} + + +void readApplePartitionMap(AbstractFile* file, ResourceKey* resources) { + AbstractFile* bufferFile; + BLKXTable* blkx; + Partition* partition; + int i; + + blkx = (BLKXTable*) (getDataByID(getResourceByKey(resources, "blkx"), 0)->data); + + partition = (Partition*) malloc(512); + bufferFile = createAbstractFileFromMemory((void**)&partition, 512); + extractBLKX(file, bufferFile, blkx); + bufferFile->close(bufferFile); + + flipPartition(partition, FALSE); + + for(i = 0; i < partition->pmMapBlkCnt; i++) { + if(partition[i].pmSig != APPLE_PARTITION_MAP_SIGNATURE) { + break; + } + + printf("pmSig:\t\t\t0x%x\n", partition[i].pmSig); + printf("pmSigPad:\t\t0x%x\n", partition[i].pmSigPad); + printf("pmMapBlkCnt:\t\t0x%x\n", partition[i].pmMapBlkCnt); + printf("pmPartName:\t\t%s\n", partition[i].pmPartName); + printf("pmParType:\t\t%s\n", partition[i].pmParType); + printf("pmPyPartStart:\t\t0x%x\n", partition[i].pmPyPartStart); + printf("pmPartBlkCnt:\t\t0x%x\n", partition[i].pmPartBlkCnt); + printf("pmLgDataStart:\t\t0x%x\n", partition[i].pmLgDataStart); + printf("pmDataCnt:\t\t0x%x\n", partition[i].pmDataCnt); + printf("pmPartStatus:\t\t0x%x\n", partition[i].pmPartStatus); + printf("pmLgBootStart:\t\t0x%x\n", partition[i].pmLgBootStart); + printf("pmBootSize:\t\t0x%x\n", partition[i].pmBootSize); + printf("pmBootAddr:\t\t0x%x\n", partition[i].pmBootAddr); + printf("pmBootAddr2:\t\t0x%x\n", partition[i].pmBootAddr2); + printf("pmBootEntry:\t\t0x%x\n", partition[i].pmBootEntry); + printf("pmBootEntry2:\t\t0x%x\n", partition[i].pmBootEntry2); + printf("pmBootCksum:\t\t0x%x\n", partition[i].pmBootCksum); + printf("pmProcessor:\t\t\t%s\n\n", partition[i].pmProcessor); + } + + free(partition); +} + +Partition* createApplePartitionMap(uint32_t numSectors, const char* volumeType) { + Partition* partition; + + partition = (Partition*) malloc(SECTOR_SIZE * PARTITION_SIZE); + memset(partition, 0, SECTOR_SIZE * PARTITION_SIZE); + + partition[0].pmSig = APPLE_PARTITION_MAP_SIGNATURE; + partition[0].pmSigPad = 0; + partition[0].pmMapBlkCnt = 0x4; + strcpy((char*)partition[0].pmPartName, "Apple"); + strcpy((char*)partition[0].pmParType, "Apple_partition_map"); + partition[0].pmPyPartStart = PARTITION_OFFSET; + partition[0].pmPartBlkCnt = PARTITION_SIZE; + partition[0].pmLgDataStart = 0; + partition[0].pmDataCnt = PARTITION_SIZE; + partition[0].pmPartStatus = 0x3; + partition[0].pmLgBootStart = 0x0; + partition[0].pmBootSize = 0x0; + partition[0].pmBootAddr = 0x0; + partition[0].pmBootAddr2 = 0x0; + partition[0].pmBootEntry = 0x0; + partition[0].pmBootEntry2 = 0x0; + partition[0].pmBootCksum = 0x0; + partition[0].pmProcessor[0] = '\0'; + partition[0].bootCode = 0; + + partition[1].pmSig = APPLE_PARTITION_MAP_SIGNATURE; + partition[1].pmSigPad = 0; + partition[1].pmMapBlkCnt = 0x4; + strcpy((char*)partition[1].pmPartName, "Macintosh"); + strcpy((char*)partition[1].pmParType, "Apple_Driver_ATAPI"); + partition[1].pmPyPartStart = ATAPI_OFFSET; + partition[1].pmPartBlkCnt = ATAPI_SIZE; + partition[1].pmLgDataStart = 0; + partition[1].pmDataCnt = 0x04; + partition[1].pmPartStatus = 0x303; + partition[1].pmLgBootStart = 0x0; + partition[1].pmBootSize = 0x800; + partition[1].pmBootAddr = 0x0; + partition[1].pmBootAddr2 = 0x0; + partition[1].pmBootEntry = 0x0; + partition[1].pmBootEntry2 = 0x0; + partition[1].pmBootCksum = 0xffff; + partition[1].pmProcessor[0] = '\0'; + partition[1].bootCode = BOOTCODE_DMMY; + + partition[2].pmSig = APPLE_PARTITION_MAP_SIGNATURE; + partition[2].pmSigPad = 0; + partition[2].pmMapBlkCnt = 0x4; + strcpy((char*)partition[2].pmPartName, "Mac_OS_X"); + strcpy((char*)partition[2].pmParType, volumeType); + partition[2].pmPyPartStart = USER_OFFSET; + partition[2].pmPartBlkCnt = numSectors; + partition[2].pmLgDataStart = 0; + partition[2].pmDataCnt = numSectors; + partition[2].pmPartStatus = 0x40000033; + partition[2].pmLgBootStart = 0x0; + partition[2].pmBootSize = 0x0; + partition[2].pmBootAddr = 0x0; + partition[2].pmBootAddr2 = 0x0; + partition[2].pmBootEntry = 0x0; + partition[2].pmBootEntry2 = 0x0; + partition[2].pmBootCksum = 0x0; + partition[2].pmProcessor[0] = '\0'; + partition[2].bootCode = BOOTCODE_GOON; + + partition[3].pmSig = APPLE_PARTITION_MAP_SIGNATURE; + partition[3].pmSigPad = 0; + partition[3].pmMapBlkCnt = 0x4; + partition[3].pmPartName[0] = '\0'; + strcpy((char*)partition[3].pmParType, "Apple_Free"); + partition[3].pmPyPartStart = USER_OFFSET + numSectors; + partition[3].pmPartBlkCnt = FREE_SIZE; + partition[3].pmLgDataStart = 0; + partition[3].pmDataCnt = 0x0; + partition[3].pmPartStatus = 0x0; + partition[3].pmLgBootStart = 0x0; + partition[3].pmBootSize = 0x0; + partition[3].pmBootAddr = 0x0; + partition[3].pmBootAddr2 = 0x0; + partition[3].pmBootEntry = 0x0; + partition[3].pmBootEntry2 = 0x0; + partition[3].pmBootCksum = 0x0; + partition[3].pmProcessor[0] = '\0'; + partition[3].bootCode = 0; + + return partition; +} + +void writeFreePartition(AbstractFile* outFile, uint32_t numSectors, ResourceKey** resources) { + BLKXTable* blkx; + + blkx = (BLKXTable*) malloc(sizeof(BLKXTable) + (2 * sizeof(BLKXRun))); + + blkx->fUDIFBlocksSignature = UDIF_BLOCK_SIGNATURE; + blkx->infoVersion = 1; + blkx->firstSectorNumber = USER_OFFSET + numSectors; + blkx->sectorCount = FREE_SIZE; + blkx->dataStart = 0; + blkx->decompressBufferRequested = 0; + blkx->blocksDescriptor = 3; + blkx->reserved1 = 0; + blkx->reserved2 = 0; + blkx->reserved3 = 0; + blkx->reserved4 = 0; + blkx->reserved5 = 0; blkx->reserved6 = 0; - memset(&(blkx->checksum), 0, sizeof(blkx->checksum)); - blkx->checksum.type = CHECKSUM_CRC32; - blkx->checksum.size = 0x20; - blkx->blocksRunCount = 2; - blkx->runs[0].type = BLOCK_IGNORE; - blkx->runs[0].reserved = 0; - blkx->runs[0].sectorStart = 0; - blkx->runs[0].sectorCount = FREE_SIZE; - blkx->runs[0].compOffset = outFile->tell(outFile); - blkx->runs[0].compLength = 0; - blkx->runs[1].type = BLOCK_TERMINATOR; - blkx->runs[1].reserved = 0; - blkx->runs[1].sectorStart = FREE_SIZE; - blkx->runs[1].sectorCount = 0; - blkx->runs[1].compOffset = blkx->runs[0].compOffset; - blkx->runs[1].compLength = 0; - - *resources = insertData(*resources, "blkx", 3, " (Apple_Free : 4)", (const char*) blkx, sizeof(BLKXTable) + (blkx->blocksRunCount * sizeof(BLKXRun)), ATTRIBUTE_HDIUTIL); - - free(blkx); -} + memset(&(blkx->checksum), 0, sizeof(blkx->checksum)); + blkx->checksum.type = CHECKSUM_CRC32; + blkx->checksum.size = 0x20; + blkx->blocksRunCount = 2; + blkx->runs[0].type = BLOCK_IGNORE; + blkx->runs[0].reserved = 0; + blkx->runs[0].sectorStart = 0; + blkx->runs[0].sectorCount = FREE_SIZE; + blkx->runs[0].compOffset = outFile->tell(outFile); + blkx->runs[0].compLength = 0; + blkx->runs[1].type = BLOCK_TERMINATOR; + blkx->runs[1].reserved = 0; + blkx->runs[1].sectorStart = FREE_SIZE; + blkx->runs[1].sectorCount = 0; + blkx->runs[1].compOffset = blkx->runs[0].compOffset; + blkx->runs[1].compLength = 0; + + *resources = insertData(*resources, "blkx", 3, " (Apple_Free : 4)", (const char*) blkx, sizeof(BLKXTable) + (blkx->blocksRunCount * sizeof(BLKXRun)), ATTRIBUTE_HDIUTIL); + + free(blkx); +} diff --git a/dmg/resources.c b/dmg/resources.c index 2b45ae0..6169dd2 100644 --- a/dmg/resources.c +++ b/dmg/resources.c @@ -1,850 +1,850 @@ -#include -#include -#include -#include -#include - -#include "dmg.h" - -static char plstData[1032] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -const char* plistHeader = "\n\n\n\n"; -const char* plistFooter = "\n\n"; - -static void flipSizeResource(unsigned char* data, char out) { - SizeResource* size; - - size = (SizeResource*) data; - - FLIPENDIAN(size->version); - FLIPENDIAN(size->isHFS); - FLIPENDIAN(size->unknown2); - FLIPENDIAN(size->unknown3); - FLIPENDIAN(size->volumeModified); - FLIPENDIAN(size->unknown4); - FLIPENDIAN(size->volumeSignature); - FLIPENDIAN(size->sizePresent); -} - -static void flipCSumResource(unsigned char* data, char out) { - CSumResource* cSum; - - cSum = (CSumResource*) data; - - FLIPENDIAN(cSum->version); - FLIPENDIAN(cSum->type); - FLIPENDIAN(cSum->checksum); -} - - -static void flipBLKXRun(BLKXRun* data) { - BLKXRun* run; - - run = (BLKXRun*) data; - - FLIPENDIAN(run->type); - FLIPENDIAN(run->reserved); - FLIPENDIAN(run->sectorStart); - FLIPENDIAN(run->sectorCount); - FLIPENDIAN(run->compOffset); - FLIPENDIAN(run->compLength); -} - -static void flipBLKX(unsigned char* data, char out) { - BLKXTable* blkx; - uint32_t i; - - blkx = (BLKXTable*) data; - - FLIPENDIAN(blkx->fUDIFBlocksSignature); - FLIPENDIAN(blkx->infoVersion); - FLIPENDIAN(blkx->firstSectorNumber); - FLIPENDIAN(blkx->sectorCount); - - FLIPENDIAN(blkx->dataStart); - FLIPENDIAN(blkx->decompressBufferRequested); - FLIPENDIAN(blkx->blocksDescriptor); - - FLIPENDIAN(blkx->reserved1); - FLIPENDIAN(blkx->reserved2); - FLIPENDIAN(blkx->reserved3); - FLIPENDIAN(blkx->reserved4); - FLIPENDIAN(blkx->reserved5); - FLIPENDIAN(blkx->reserved6); - - flipUDIFChecksum(&(blkx->checksum), out); - - if(out) { - for(i = 0; i < blkx->blocksRunCount; i++) { - flipBLKXRun(&(blkx->runs[i])); - } - FLIPENDIAN(blkx->blocksRunCount); - } else { - FLIPENDIAN(blkx->blocksRunCount); - for(i = 0; i < blkx->blocksRunCount; i++) { - flipBLKXRun(&(blkx->runs[i])); - } - - /*printf("fUDIFBlocksSignature: 0x%x\n", blkx->fUDIFBlocksSignature); - printf("infoVersion: 0x%x\n", blkx->infoVersion); - printf("firstSectorNumber: 0x%llx\n", blkx->firstSectorNumber); - printf("sectorCount: 0x%llx\n", blkx->sectorCount); - printf("dataStart: 0x%llx\n", blkx->dataStart); - printf("decompressBufferRequested: 0x%x\n", blkx->decompressBufferRequested); - printf("blocksDescriptor: 0x%x\n", blkx->blocksDescriptor); - printf("blocksRunCount: 0x%x\n", blkx->blocksRunCount);*/ - } -} - -static char* getXMLString(char** location) { - char* curLoc; - char* tagEnd; - char* toReturn; - size_t strLen; - - curLoc = *location; - - curLoc = strstr(curLoc, ""); - if(!curLoc) - return NULL; - curLoc += sizeof("") - 1; - - tagEnd = strstr(curLoc, ""); - - strLen = (size_t)(tagEnd - curLoc); - toReturn = (char*) malloc(strLen + 1); - memcpy(toReturn, curLoc, strLen); - toReturn[strLen] = '\0'; - - curLoc = tagEnd + sizeof("") - 1; - - *location = curLoc; - - return toReturn; -} - -static uint32_t getXMLInteger(char** location) { - char* curLoc; - char* tagEnd; - char* buffer; - uint32_t toReturn; - size_t strLen; - - curLoc = *location; - - curLoc = strstr(curLoc, ""); - if(!curLoc) - return 0; - curLoc += sizeof("") - 1; - - tagEnd = strstr(curLoc, ""); - - strLen = (size_t)(tagEnd - curLoc); - buffer = (char*) malloc(strLen + 1); - memcpy(buffer, curLoc, strLen); - buffer[strLen] = '\0'; - - curLoc = tagEnd + sizeof("") - 1; - - sscanf(buffer, "%d", (int32_t*)(&toReturn)); - - free(buffer); - - *location = curLoc; - - return toReturn; -} - -static unsigned char* getXMLData(char** location, size_t *dataLength) { - char* curLoc; - char* tagEnd; - char* encodedData; - unsigned char* toReturn; - size_t strLen; - - curLoc = *location; - - curLoc = strstr(curLoc, ""); - if(!curLoc) - return NULL; - curLoc += sizeof("") - 1; - - tagEnd = strstr(curLoc, ""); - - - strLen = (size_t)(tagEnd - curLoc); - - encodedData = (char*) malloc(strLen + 1); - memcpy(encodedData, curLoc, strLen); - encodedData[strLen] = '\0'; - - curLoc = tagEnd + sizeof("") - 1; - - *location = curLoc; - - toReturn = decodeBase64(encodedData, dataLength); - - free(encodedData); - - return toReturn; -} - -static void readResourceData(ResourceData* data, char** location, FlipDataFunc flipData) { - char* curLoc; - char* tagBegin; - char* tagEnd; - char* dictEnd; - size_t strLen; - char* buffer; - - curLoc = *location; - - data->name = NULL; - data->attributes = 0; - data->id = 0; - data->data = NULL; - - curLoc = strstr(curLoc, ""); - dictEnd = strstr(curLoc, ""); /* hope there's not a dict type in this resource data! */ - while(curLoc != NULL && curLoc < dictEnd) { - curLoc = strstr(curLoc, ""); - if(!curLoc) - break; - curLoc += sizeof("") - 1; - - tagEnd = strstr(curLoc, ""); - - strLen = (size_t)(tagEnd - curLoc); - tagBegin = curLoc; - curLoc = tagEnd + sizeof("") - 1; - - if(strncmp(tagBegin, "Attributes", strLen) == 0) { - buffer = getXMLString(&curLoc); - sscanf(buffer, "0x%x", &(data->attributes)); - free(buffer); - } else if(strncmp(tagBegin, "Data", strLen) == 0) { - data->data = getXMLData(&curLoc, &(data->dataLength)); - if(flipData) { - (*flipData)(data->data, 0); - } - } else if(strncmp(tagBegin, "ID", strLen) == 0) { - buffer = getXMLString(&curLoc); - sscanf(buffer, "%d", &(data->id)); - free(buffer); - } else if(strncmp(tagBegin, "Name", strLen) == 0) { - data->name = (unsigned char*) getXMLString(&curLoc); - } - } - - curLoc = dictEnd + sizeof("") - 1; - - *location = curLoc; -} - -static void readNSizResource(NSizResource* data, char** location) { - char* curLoc; - char* tagBegin; - char* tagEnd; - char* dictEnd; - size_t strLen; - size_t dummy; - - curLoc = *location; - - data->isVolume = FALSE; - data->sha1Digest = NULL; - data->blockChecksum2 = 0; - data->bytes = 0; - data->modifyDate = 0; - data->partitionNumber = 0; - data->version = 0; - data->volumeSignature = 0; - - curLoc = strstr(curLoc, ""); - dictEnd = strstr(curLoc, ""); /* hope there's not a dict type in this resource data! */ - while(curLoc != NULL && curLoc < dictEnd) { - curLoc = strstr(curLoc, ""); - if(!curLoc) - break; - curLoc += sizeof("") - 1; - - tagEnd = strstr(curLoc, ""); - - strLen = (size_t)(tagEnd - curLoc); - tagBegin = curLoc; - curLoc = tagEnd + sizeof("") - 1; - - if(strncmp(tagBegin, "SHA-1-digest", strLen) == 0) { - data->sha1Digest = getXMLData(&curLoc, &dummy);; - /*flipEndian(data->sha1Digest, 4);*/ - } else if(strncmp(tagBegin, "block-checksum-2", strLen) == 0) { - data->blockChecksum2 = getXMLInteger(&curLoc); - } else if(strncmp(tagBegin, "bytes", strLen) == 0) { - data->bytes = getXMLInteger(&curLoc); - } else if(strncmp(tagBegin, "date", strLen) == 0) { - data->modifyDate = getXMLInteger(&curLoc); - } else if(strncmp(tagBegin, "part-num", strLen) == 0) { - data->partitionNumber = getXMLInteger(&curLoc); - } else if(strncmp(tagBegin, "version", strLen) == 0) { - data->version = getXMLInteger(&curLoc); - } else if(strncmp(tagBegin, "volume-signature", strLen) == 0) { - data->volumeSignature = getXMLInteger(&curLoc); - data->isVolume = TRUE; - } - } - - curLoc = dictEnd + sizeof("") - 1; - - *location = curLoc; -} - -static void writeNSizResource(NSizResource* data, char* buffer) { - char itemBuffer[1024]; - char* sha1Buffer; - - (*buffer) = '\0'; - itemBuffer[0] = '\0'; - - strcat(buffer, plistHeader); - if(data->sha1Digest != NULL) { - sha1Buffer = convertBase64(data->sha1Digest, 20, 1, 42); - sprintf(itemBuffer, "\tSHA-1-digest\n\t\n%s\t\n", sha1Buffer); - free(sha1Buffer); - strcat(buffer, itemBuffer); - } - sprintf(itemBuffer, "\tblock-checksum-2\n\t%d\n", (int32_t)(data->blockChecksum2)); - strcat(buffer, itemBuffer); - if(data->isVolume) { - sprintf(itemBuffer, "\tbytes\n\t%d\n", (int32_t)(data->bytes)); - strcat(buffer, itemBuffer); - sprintf(itemBuffer, "\tdate\n\t%d\n", (int32_t)(data->modifyDate)); - strcat(buffer, itemBuffer); - } - sprintf(itemBuffer, "\tpart-num\n\t%d\n", (int32_t)(data->partitionNumber)); - strcat(buffer, itemBuffer); - sprintf(itemBuffer, "\tversion\n\t%d\n", (int32_t)(data->version)); - strcat(buffer, itemBuffer); - if(data->isVolume) { - sprintf(itemBuffer, "\tbytes\n\t%d\n", (int32_t)(data->volumeSignature)); - strcat(buffer, itemBuffer); - } - strcat(buffer, plistFooter); -} - - -NSizResource* readNSiz(ResourceKey* resources) { - ResourceData* curData; - NSizResource* toReturn; - NSizResource* curNSiz; - char* curLoc; - uint32_t modifyDate; - - curData = getResourceByKey(resources, "nsiz")->data; - toReturn = NULL; - - while(curData != NULL) { - curLoc = (char*) curData->data; - - if(toReturn == NULL) { - toReturn = (NSizResource*) malloc(sizeof(NSizResource)); - curNSiz = toReturn; - } else { - curNSiz->next = (NSizResource*) malloc(sizeof(NSizResource)); - curNSiz = curNSiz->next; - } - - curNSiz->next = NULL; - - readNSizResource(curNSiz, &curLoc); - - - printf("block-checksum-2:\t0x%x\n", curNSiz->blockChecksum2); - printf("part-num:\t\t0x%x\n", curNSiz->partitionNumber); - printf("version:\t\t0x%x\n", curNSiz->version); - - if(curNSiz->isVolume) { - printf("has SHA1:\t\t%d\n", curNSiz->sha1Digest != NULL); - printf("bytes:\t\t\t0x%x\n", curNSiz->bytes); - modifyDate = APPLE_TO_UNIX_TIME(curNSiz->modifyDate); - printf("date:\t\t\t%s", ctime((time_t*)(&modifyDate))); - printf("volume-signature:\t0x%x\n", curNSiz->volumeSignature); - } - - printf("\n"); - - curData = curData->next; - } - - return toReturn; -} - -ResourceKey* writeNSiz(NSizResource* nSiz) { - NSizResource* curNSiz; - ResourceKey* key; - ResourceData* curData; - char buffer[1024]; - - curNSiz = nSiz; - - key = (ResourceKey*) malloc(sizeof(ResourceKey)); - key->key = (unsigned char*) malloc(sizeof("nsiz") + 1); - strcpy((char*) key->key, "nsiz"); - key->next = NULL; - key->flipData = NULL; - key->data = NULL; - - while(curNSiz != NULL) { - writeNSizResource(curNSiz, buffer); - if(key->data == NULL) { - key->data = (ResourceData*) malloc(sizeof(ResourceData)); - curData = key->data; - } else { - curData->next = (ResourceData*) malloc(sizeof(ResourceData)); - curData = curData->next; - } - - curData->attributes = 0; - curData->id = curNSiz->partitionNumber; - curData->name = (unsigned char*) malloc(sizeof(char)); - curData->name[0] = '\0'; - curData->next = NULL; - curData->dataLength = sizeof(char) * strlen(buffer); - curData->data = (unsigned char*) malloc(curData->dataLength); - memcpy(curData->data, buffer, curData->dataLength); - - curNSiz = curNSiz->next; - } - - return key; -} - -void releaseNSiz(NSizResource* nSiz) { - NSizResource* curNSiz; - NSizResource* toRemove; - - curNSiz = nSiz; - - while(curNSiz != NULL) { - if(curNSiz->sha1Digest != NULL) - free(curNSiz->sha1Digest); - - toRemove = curNSiz; - curNSiz = curNSiz->next; - free(toRemove); - } -} - -ResourceKey* readResources(AbstractFile* file, UDIFResourceFile* resourceFile) { - char* xml; - char* curLoc; - char* tagEnd; - size_t strLen; - - ResourceKey* toReturn; - ResourceKey* curResource; - ResourceData* curData; - - xml = (char*) malloc((size_t)resourceFile->fUDIFXMLLength + 1); /* we're not going to handle over 32-bit resource files, that'd be insane */ - xml[(size_t)resourceFile->fUDIFXMLLength] = '\0'; - - if(!xml) - return NULL; - - toReturn = NULL; - curResource = NULL; - curData = NULL; - - file->seek(file, (off_t)(resourceFile->fUDIFXMLOffset)); - ASSERT(file->read(file, xml, (size_t)resourceFile->fUDIFXMLLength) == (size_t)resourceFile->fUDIFXMLLength, "fread"); - - curLoc = strstr(xml, "resource-fork"); - if(!curLoc) - return NULL; - curLoc += sizeof("resource-fork") - 1; - - curLoc = strstr(curLoc, ""); - if(!curLoc) - return NULL; - curLoc += sizeof("") - 1; - - while(TRUE) { - curLoc = strstr(curLoc, ""); - if(!curLoc) - break; - curLoc += sizeof("") - 1; - - tagEnd = strstr(curLoc, ""); - if(!tagEnd) - break; - - if(toReturn == NULL) { - toReturn = (ResourceKey*) malloc(sizeof(ResourceKey)); - curResource = toReturn; - } else { - curResource->next = (ResourceKey*) malloc(sizeof(ResourceKey)); - curResource = curResource->next; - } - - curResource->data = NULL; - curResource->next = NULL; - curResource->flipData = NULL; - - strLen = (size_t)(tagEnd - curLoc); - curResource->key = (unsigned char*) malloc(strLen + 1); - memcpy(curResource->key, curLoc, strLen); - curResource->key[strLen] = '\0'; - - curLoc = tagEnd + sizeof("") - 1; - - curLoc = strstr(curLoc, ""); - if(!curLoc) - return NULL; - curLoc += sizeof("") - 1; - - tagEnd = strstr(curLoc, ""); - if(!tagEnd) - break; - - if(strcmp((char*) curResource->key, "blkx") == 0) { - curResource->flipData = &flipBLKX; - } else if(strcmp((char*) curResource->key, "size") == 0) { - curResource->flipData = &flipSizeResource; - } else if(strcmp((char*) curResource->key, "cSum") == 0) { - curResource->flipData = &flipCSumResource; - } - - curLoc = strstr(curLoc, ""); - while(curLoc != NULL && curLoc < tagEnd) { - if(curResource->data == NULL) { - curResource->data = (ResourceData*) malloc(sizeof(ResourceData)); - curData = curResource->data; - } else { - curData->next = (ResourceData*) malloc(sizeof(ResourceData)); - curData = curData->next; - } - - curData->next = NULL; - - readResourceData(curData, &curLoc, curResource->flipData); - curLoc = strstr(curLoc, ""); - } - - curLoc = tagEnd + sizeof("") - 1; - } - - free(xml); - - return toReturn; -} - -static void writeResourceData(AbstractFile* file, ResourceData* data, FlipDataFunc flipData, int tabLength) { - unsigned char* dataBuf; - char* tabs; - int i; - - tabs = (char*) malloc(sizeof(char) * (tabLength + 1)); - for(i = 0; i < tabLength; i++) { - tabs[i] = '\t'; - } - tabs[tabLength] = '\0'; - - abstractFilePrint(file, "%s\n", tabs); - abstractFilePrint(file, "%s\tAttributes\n%s\t0x%04x\n", tabs, tabs, data->attributes); - abstractFilePrint(file, "%s\tData\n%s\t\n", tabs, tabs); - - if(flipData) { - dataBuf = (unsigned char*) malloc(data->dataLength); - memcpy(dataBuf, data->data, data->dataLength); +#include +#include +#include +#include +#include + +#include "dmg.h" + +static char plstData[1032] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const char* plistHeader = "\n\n\n\n"; +const char* plistFooter = "\n\n"; + +static void flipSizeResource(unsigned char* data, char out) { + SizeResource* size; + + size = (SizeResource*) data; + + FLIPENDIAN(size->version); + FLIPENDIAN(size->isHFS); + FLIPENDIAN(size->unknown2); + FLIPENDIAN(size->unknown3); + FLIPENDIAN(size->volumeModified); + FLIPENDIAN(size->unknown4); + FLIPENDIAN(size->volumeSignature); + FLIPENDIAN(size->sizePresent); +} + +static void flipCSumResource(unsigned char* data, char out) { + CSumResource* cSum; + + cSum = (CSumResource*) data; + + FLIPENDIAN(cSum->version); + FLIPENDIAN(cSum->type); + FLIPENDIAN(cSum->checksum); +} + + +static void flipBLKXRun(BLKXRun* data) { + BLKXRun* run; + + run = (BLKXRun*) data; + + FLIPENDIAN(run->type); + FLIPENDIAN(run->reserved); + FLIPENDIAN(run->sectorStart); + FLIPENDIAN(run->sectorCount); + FLIPENDIAN(run->compOffset); + FLIPENDIAN(run->compLength); +} + +static void flipBLKX(unsigned char* data, char out) { + BLKXTable* blkx; + uint32_t i; + + blkx = (BLKXTable*) data; + + FLIPENDIAN(blkx->fUDIFBlocksSignature); + FLIPENDIAN(blkx->infoVersion); + FLIPENDIAN(blkx->firstSectorNumber); + FLIPENDIAN(blkx->sectorCount); + + FLIPENDIAN(blkx->dataStart); + FLIPENDIAN(blkx->decompressBufferRequested); + FLIPENDIAN(blkx->blocksDescriptor); + + FLIPENDIAN(blkx->reserved1); + FLIPENDIAN(blkx->reserved2); + FLIPENDIAN(blkx->reserved3); + FLIPENDIAN(blkx->reserved4); + FLIPENDIAN(blkx->reserved5); + FLIPENDIAN(blkx->reserved6); + + flipUDIFChecksum(&(blkx->checksum), out); + + if(out) { + for(i = 0; i < blkx->blocksRunCount; i++) { + flipBLKXRun(&(blkx->runs[i])); + } + FLIPENDIAN(blkx->blocksRunCount); + } else { + FLIPENDIAN(blkx->blocksRunCount); + for(i = 0; i < blkx->blocksRunCount; i++) { + flipBLKXRun(&(blkx->runs[i])); + } + + /*printf("fUDIFBlocksSignature: 0x%x\n", blkx->fUDIFBlocksSignature); + printf("infoVersion: 0x%x\n", blkx->infoVersion); + printf("firstSectorNumber: 0x%llx\n", blkx->firstSectorNumber); + printf("sectorCount: 0x%llx\n", blkx->sectorCount); + printf("dataStart: 0x%llx\n", blkx->dataStart); + printf("decompressBufferRequested: 0x%x\n", blkx->decompressBufferRequested); + printf("blocksDescriptor: 0x%x\n", blkx->blocksDescriptor); + printf("blocksRunCount: 0x%x\n", blkx->blocksRunCount);*/ + } +} + +static char* getXMLString(char** location) { + char* curLoc; + char* tagEnd; + char* toReturn; + size_t strLen; + + curLoc = *location; + + curLoc = strstr(curLoc, ""); + if(!curLoc) + return NULL; + curLoc += sizeof("") - 1; + + tagEnd = strstr(curLoc, ""); + + strLen = (size_t)(tagEnd - curLoc); + toReturn = (char*) malloc(strLen + 1); + memcpy(toReturn, curLoc, strLen); + toReturn[strLen] = '\0'; + + curLoc = tagEnd + sizeof("") - 1; + + *location = curLoc; + + return toReturn; +} + +static uint32_t getXMLInteger(char** location) { + char* curLoc; + char* tagEnd; + char* buffer; + uint32_t toReturn; + size_t strLen; + + curLoc = *location; + + curLoc = strstr(curLoc, ""); + if(!curLoc) + return 0; + curLoc += sizeof("") - 1; + + tagEnd = strstr(curLoc, ""); + + strLen = (size_t)(tagEnd - curLoc); + buffer = (char*) malloc(strLen + 1); + memcpy(buffer, curLoc, strLen); + buffer[strLen] = '\0'; + + curLoc = tagEnd + sizeof("") - 1; + + sscanf(buffer, "%d", (int32_t*)(&toReturn)); + + free(buffer); + + *location = curLoc; + + return toReturn; +} + +static unsigned char* getXMLData(char** location, size_t *dataLength) { + char* curLoc; + char* tagEnd; + char* encodedData; + unsigned char* toReturn; + size_t strLen; + + curLoc = *location; + + curLoc = strstr(curLoc, ""); + if(!curLoc) + return NULL; + curLoc += sizeof("") - 1; + + tagEnd = strstr(curLoc, ""); + + + strLen = (size_t)(tagEnd - curLoc); + + encodedData = (char*) malloc(strLen + 1); + memcpy(encodedData, curLoc, strLen); + encodedData[strLen] = '\0'; + + curLoc = tagEnd + sizeof("") - 1; + + *location = curLoc; + + toReturn = decodeBase64(encodedData, dataLength); + + free(encodedData); + + return toReturn; +} + +static void readResourceData(ResourceData* data, char** location, FlipDataFunc flipData) { + char* curLoc; + char* tagBegin; + char* tagEnd; + char* dictEnd; + size_t strLen; + char* buffer; + + curLoc = *location; + + data->name = NULL; + data->attributes = 0; + data->id = 0; + data->data = NULL; + + curLoc = strstr(curLoc, ""); + dictEnd = strstr(curLoc, ""); /* hope there's not a dict type in this resource data! */ + while(curLoc != NULL && curLoc < dictEnd) { + curLoc = strstr(curLoc, ""); + if(!curLoc) + break; + curLoc += sizeof("") - 1; + + tagEnd = strstr(curLoc, ""); + + strLen = (size_t)(tagEnd - curLoc); + tagBegin = curLoc; + curLoc = tagEnd + sizeof("") - 1; + + if(strncmp(tagBegin, "Attributes", strLen) == 0) { + buffer = getXMLString(&curLoc); + sscanf(buffer, "0x%x", &(data->attributes)); + free(buffer); + } else if(strncmp(tagBegin, "Data", strLen) == 0) { + data->data = getXMLData(&curLoc, &(data->dataLength)); + if(flipData) { + (*flipData)(data->data, 0); + } + } else if(strncmp(tagBegin, "ID", strLen) == 0) { + buffer = getXMLString(&curLoc); + sscanf(buffer, "%d", &(data->id)); + free(buffer); + } else if(strncmp(tagBegin, "Name", strLen) == 0) { + data->name = (unsigned char*) getXMLString(&curLoc); + } + } + + curLoc = dictEnd + sizeof("") - 1; + + *location = curLoc; +} + +static void readNSizResource(NSizResource* data, char** location) { + char* curLoc; + char* tagBegin; + char* tagEnd; + char* dictEnd; + size_t strLen; + size_t dummy; + + curLoc = *location; + + data->isVolume = FALSE; + data->sha1Digest = NULL; + data->blockChecksum2 = 0; + data->bytes = 0; + data->modifyDate = 0; + data->partitionNumber = 0; + data->version = 0; + data->volumeSignature = 0; + + curLoc = strstr(curLoc, ""); + dictEnd = strstr(curLoc, ""); /* hope there's not a dict type in this resource data! */ + while(curLoc != NULL && curLoc < dictEnd) { + curLoc = strstr(curLoc, ""); + if(!curLoc) + break; + curLoc += sizeof("") - 1; + + tagEnd = strstr(curLoc, ""); + + strLen = (size_t)(tagEnd - curLoc); + tagBegin = curLoc; + curLoc = tagEnd + sizeof("") - 1; + + if(strncmp(tagBegin, "SHA-1-digest", strLen) == 0) { + data->sha1Digest = getXMLData(&curLoc, &dummy);; + /*flipEndian(data->sha1Digest, 4);*/ + } else if(strncmp(tagBegin, "block-checksum-2", strLen) == 0) { + data->blockChecksum2 = getXMLInteger(&curLoc); + } else if(strncmp(tagBegin, "bytes", strLen) == 0) { + data->bytes = getXMLInteger(&curLoc); + } else if(strncmp(tagBegin, "date", strLen) == 0) { + data->modifyDate = getXMLInteger(&curLoc); + } else if(strncmp(tagBegin, "part-num", strLen) == 0) { + data->partitionNumber = getXMLInteger(&curLoc); + } else if(strncmp(tagBegin, "version", strLen) == 0) { + data->version = getXMLInteger(&curLoc); + } else if(strncmp(tagBegin, "volume-signature", strLen) == 0) { + data->volumeSignature = getXMLInteger(&curLoc); + data->isVolume = TRUE; + } + } + + curLoc = dictEnd + sizeof("") - 1; + + *location = curLoc; +} + +static void writeNSizResource(NSizResource* data, char* buffer) { + char itemBuffer[1024]; + char* sha1Buffer; + + (*buffer) = '\0'; + itemBuffer[0] = '\0'; + + strcat(buffer, plistHeader); + if(data->sha1Digest != NULL) { + sha1Buffer = convertBase64(data->sha1Digest, 20, 1, 42); + sprintf(itemBuffer, "\tSHA-1-digest\n\t\n%s\t\n", sha1Buffer); + free(sha1Buffer); + strcat(buffer, itemBuffer); + } + sprintf(itemBuffer, "\tblock-checksum-2\n\t%d\n", (int32_t)(data->blockChecksum2)); + strcat(buffer, itemBuffer); + if(data->isVolume) { + sprintf(itemBuffer, "\tbytes\n\t%d\n", (int32_t)(data->bytes)); + strcat(buffer, itemBuffer); + sprintf(itemBuffer, "\tdate\n\t%d\n", (int32_t)(data->modifyDate)); + strcat(buffer, itemBuffer); + } + sprintf(itemBuffer, "\tpart-num\n\t%d\n", (int32_t)(data->partitionNumber)); + strcat(buffer, itemBuffer); + sprintf(itemBuffer, "\tversion\n\t%d\n", (int32_t)(data->version)); + strcat(buffer, itemBuffer); + if(data->isVolume) { + sprintf(itemBuffer, "\tbytes\n\t%d\n", (int32_t)(data->volumeSignature)); + strcat(buffer, itemBuffer); + } + strcat(buffer, plistFooter); +} + + +NSizResource* readNSiz(ResourceKey* resources) { + ResourceData* curData; + NSizResource* toReturn; + NSizResource* curNSiz; + char* curLoc; + uint32_t modifyDate; + + curData = getResourceByKey(resources, "nsiz")->data; + toReturn = NULL; + + while(curData != NULL) { + curLoc = (char*) curData->data; + + if(toReturn == NULL) { + toReturn = (NSizResource*) malloc(sizeof(NSizResource)); + curNSiz = toReturn; + } else { + curNSiz->next = (NSizResource*) malloc(sizeof(NSizResource)); + curNSiz = curNSiz->next; + } + + curNSiz->next = NULL; + + readNSizResource(curNSiz, &curLoc); + + + printf("block-checksum-2:\t0x%x\n", curNSiz->blockChecksum2); + printf("part-num:\t\t0x%x\n", curNSiz->partitionNumber); + printf("version:\t\t0x%x\n", curNSiz->version); + + if(curNSiz->isVolume) { + printf("has SHA1:\t\t%d\n", curNSiz->sha1Digest != NULL); + printf("bytes:\t\t\t0x%x\n", curNSiz->bytes); + modifyDate = APPLE_TO_UNIX_TIME(curNSiz->modifyDate); + printf("date:\t\t\t%s", ctime((time_t*)(&modifyDate))); + printf("volume-signature:\t0x%x\n", curNSiz->volumeSignature); + } + + printf("\n"); + + curData = curData->next; + } + + return toReturn; +} + +ResourceKey* writeNSiz(NSizResource* nSiz) { + NSizResource* curNSiz; + ResourceKey* key; + ResourceData* curData; + char buffer[1024]; + + curNSiz = nSiz; + + key = (ResourceKey*) malloc(sizeof(ResourceKey)); + key->key = (unsigned char*) malloc(sizeof("nsiz") + 1); + strcpy((char*) key->key, "nsiz"); + key->next = NULL; + key->flipData = NULL; + key->data = NULL; + + while(curNSiz != NULL) { + writeNSizResource(curNSiz, buffer); + if(key->data == NULL) { + key->data = (ResourceData*) malloc(sizeof(ResourceData)); + curData = key->data; + } else { + curData->next = (ResourceData*) malloc(sizeof(ResourceData)); + curData = curData->next; + } + + curData->attributes = 0; + curData->id = curNSiz->partitionNumber; + curData->name = (unsigned char*) malloc(sizeof(char)); + curData->name[0] = '\0'; + curData->next = NULL; + curData->dataLength = sizeof(char) * strlen(buffer); + curData->data = (unsigned char*) malloc(curData->dataLength); + memcpy(curData->data, buffer, curData->dataLength); + + curNSiz = curNSiz->next; + } + + return key; +} + +void releaseNSiz(NSizResource* nSiz) { + NSizResource* curNSiz; + NSizResource* toRemove; + + curNSiz = nSiz; + + while(curNSiz != NULL) { + if(curNSiz->sha1Digest != NULL) + free(curNSiz->sha1Digest); + + toRemove = curNSiz; + curNSiz = curNSiz->next; + free(toRemove); + } +} + +ResourceKey* readResources(AbstractFile* file, UDIFResourceFile* resourceFile) { + char* xml; + char* curLoc; + char* tagEnd; + size_t strLen; + + ResourceKey* toReturn; + ResourceKey* curResource; + ResourceData* curData; + + xml = (char*) malloc((size_t)resourceFile->fUDIFXMLLength + 1); /* we're not going to handle over 32-bit resource files, that'd be insane */ + xml[(size_t)resourceFile->fUDIFXMLLength] = '\0'; + + if(!xml) + return NULL; + + toReturn = NULL; + curResource = NULL; + curData = NULL; + + file->seek(file, (off_t)(resourceFile->fUDIFXMLOffset)); + ASSERT(file->read(file, xml, (size_t)resourceFile->fUDIFXMLLength) == (size_t)resourceFile->fUDIFXMLLength, "fread"); + + curLoc = strstr(xml, "resource-fork"); + if(!curLoc) + return NULL; + curLoc += sizeof("resource-fork") - 1; + + curLoc = strstr(curLoc, ""); + if(!curLoc) + return NULL; + curLoc += sizeof("") - 1; + + while(TRUE) { + curLoc = strstr(curLoc, ""); + if(!curLoc) + break; + curLoc += sizeof("") - 1; + + tagEnd = strstr(curLoc, ""); + if(!tagEnd) + break; + + if(toReturn == NULL) { + toReturn = (ResourceKey*) malloc(sizeof(ResourceKey)); + curResource = toReturn; + } else { + curResource->next = (ResourceKey*) malloc(sizeof(ResourceKey)); + curResource = curResource->next; + } + + curResource->data = NULL; + curResource->next = NULL; + curResource->flipData = NULL; + + strLen = (size_t)(tagEnd - curLoc); + curResource->key = (unsigned char*) malloc(strLen + 1); + memcpy(curResource->key, curLoc, strLen); + curResource->key[strLen] = '\0'; + + curLoc = tagEnd + sizeof("") - 1; + + curLoc = strstr(curLoc, ""); + if(!curLoc) + return NULL; + curLoc += sizeof("") - 1; + + tagEnd = strstr(curLoc, ""); + if(!tagEnd) + break; + + if(strcmp((char*) curResource->key, "blkx") == 0) { + curResource->flipData = &flipBLKX; + } else if(strcmp((char*) curResource->key, "size") == 0) { + curResource->flipData = &flipSizeResource; + } else if(strcmp((char*) curResource->key, "cSum") == 0) { + curResource->flipData = &flipCSumResource; + } + + curLoc = strstr(curLoc, ""); + while(curLoc != NULL && curLoc < tagEnd) { + if(curResource->data == NULL) { + curResource->data = (ResourceData*) malloc(sizeof(ResourceData)); + curData = curResource->data; + } else { + curData->next = (ResourceData*) malloc(sizeof(ResourceData)); + curData = curData->next; + } + + curData->next = NULL; + + readResourceData(curData, &curLoc, curResource->flipData); + curLoc = strstr(curLoc, ""); + } + + curLoc = tagEnd + sizeof("") - 1; + } + + free(xml); + + return toReturn; +} + +static void writeResourceData(AbstractFile* file, ResourceData* data, FlipDataFunc flipData, int tabLength) { + unsigned char* dataBuf; + char* tabs; + int i; + + tabs = (char*) malloc(sizeof(char) * (tabLength + 1)); + for(i = 0; i < tabLength; i++) { + tabs[i] = '\t'; + } + tabs[tabLength] = '\0'; + + abstractFilePrint(file, "%s\n", tabs); + abstractFilePrint(file, "%s\tAttributes\n%s\t0x%04x\n", tabs, tabs, data->attributes); + abstractFilePrint(file, "%s\tData\n%s\t\n", tabs, tabs); + + if(flipData) { + dataBuf = (unsigned char*) malloc(data->dataLength); + memcpy(dataBuf, data->data, data->dataLength); (*flipData)(dataBuf, 1); - writeBase64(file, dataBuf, data->dataLength, tabLength + 1, 43); - free(dataBuf); - } else { - writeBase64(file, data->data, data->dataLength, tabLength + 1, 43); - } - - abstractFilePrint(file, "%s\t\n", tabs); - abstractFilePrint(file, "%s\tID\n%s\t%d\n", tabs, tabs, data->id); - abstractFilePrint(file, "%s\tName\n%s\t%s\n", tabs, tabs, data->name); - abstractFilePrint(file, "%s\n", tabs); - - free(tabs); -} - -void writeResources(AbstractFile* file, ResourceKey* resources) { - ResourceKey* curResource; - ResourceData* curData; - - abstractFilePrint(file, plistHeader); - abstractFilePrint(file, "\tresource-fork\n\t\n"); - - curResource = resources; - while(curResource != NULL) { - abstractFilePrint(file, "\t\t%s\n\t\t\n", curResource->key); - curData = curResource->data; - while(curData != NULL) { - writeResourceData(file, curData, curResource->flipData, 3); - curData = curData->next; - } - abstractFilePrint(file, "\t\t\n", curResource->key); - curResource = curResource->next; - } - - abstractFilePrint(file, "\t\n"); - abstractFilePrint(file, plistFooter); - -} - -static void releaseResourceData(ResourceData* data) { - ResourceData* curData; - ResourceData* nextData; - - nextData = data; - while(nextData != NULL) { - curData = nextData; - - if(curData->name) - free(curData->name); - - if(curData->data) - free(curData->data); - - nextData = nextData->next; - free(curData); - } -} - -void releaseResources(ResourceKey* resources) { - ResourceKey* curResource; - ResourceKey* nextResource; - - nextResource = resources; - while(nextResource != NULL) { - curResource = nextResource; - free(curResource->key); - releaseResourceData(curResource->data); - nextResource = nextResource->next; - free(curResource); - } -} - -ResourceKey* getResourceByKey(ResourceKey* resources, const char* key) { - ResourceKey* curResource; - - curResource = resources; - while(curResource != NULL) { - if(strcmp((char*) curResource->key, key) == 0) { - return curResource; - } - curResource = curResource->next; - } - - return NULL; -} - -ResourceData* getDataByID(ResourceKey* resource, int id) { - ResourceData* curData; - - curData = resource->data; - - while(curData != NULL) { - if(curData->id == id) { - return curData; - } - curData = curData->next; - } - - return NULL; -} - -ResourceKey* insertData(ResourceKey* resources, const char* key, int id, const char* name, const char* data, size_t dataLength, uint32_t attributes) { - ResourceKey* curResource; - ResourceKey* lastResource; - ResourceData* curData; - - lastResource = resources; - curResource = resources; - while(curResource != NULL) { - if(strcmp((char*) curResource->key, key) == 0) { - break; - } - lastResource = curResource; - curResource = curResource->next; - } - - if(curResource == NULL) { - if(lastResource == NULL) { - curResource = (ResourceKey*) malloc(sizeof(ResourceKey)); - } else { - lastResource->next = (ResourceKey*) malloc(sizeof(ResourceKey)); - curResource = lastResource->next; - } - - curResource->key = (unsigned char*) malloc(strlen(key) + 1); - strcpy((char*) curResource->key, key); - curResource->next = NULL; - - if(strcmp((char*) curResource->key, "blkx") == 0) { - curResource->flipData = &flipBLKX; - } else if(strcmp((char*) curResource->key, "size") == 0) { - printf("we know to flip this size resource\n"); - curResource->flipData = &flipSizeResource; - } else if(strcmp((char*) curResource->key, "cSum") == 0) { - curResource->flipData = &flipCSumResource; - } else { - curResource->flipData = NULL; - } - - curResource->data = NULL; - } - - if(curResource->data == NULL) { - curData = (ResourceData*) malloc(sizeof(ResourceData)); - curResource->data = curData; - curData->next = NULL; - } else { - curData = curResource->data; - while(curData->next != NULL) { - if(curData->id == id) { - break; - } - curData = curData->next; - } - - if(curData->id != id) { - curData->next = (ResourceData*) malloc(sizeof(ResourceData)); - curData = curData->next; - curData->next = NULL; - } else { - free(curData->data); - free(curData->name); - } - } - - curData->attributes = attributes; - curData->dataLength = dataLength; - curData->id = id; - curData->name = (unsigned char*) malloc(strlen(name) + 1); - strcpy((char*) curData->name, name); - curData->data = (unsigned char*) malloc(dataLength); - memcpy(curData->data, data, dataLength); - - int i = 0; - if(resources) { - curResource = resources; - while(curResource) { - curResource = curResource->next; - i++; - } - return resources; - } else { - return curResource; - } -} - -ResourceKey* makePlst() { - return insertData(NULL, "plst", 0, "", plstData, sizeof(plstData), ATTRIBUTE_HDIUTIL); -} - -ResourceKey* makeSize(HFSPlusVolumeHeader* volumeHeader) { - SizeResource size; - memset(&size, 0, sizeof(SizeResource)); - size.version = 5; - size.isHFS = 1; - size.unknown2 = 0; - size.unknown3 = 0; - size.volumeModified = volumeHeader->modifyDate; - size.unknown4 = 0; - size.volumeSignature = volumeHeader->signature; - size.sizePresent = 1; - - printf("making size data\n"); - return insertData(NULL, "size", 0, "", (const char*)(&size), sizeof(SizeResource), 0); -} - + writeBase64(file, dataBuf, data->dataLength, tabLength + 1, 43); + free(dataBuf); + } else { + writeBase64(file, data->data, data->dataLength, tabLength + 1, 43); + } + + abstractFilePrint(file, "%s\t\n", tabs); + abstractFilePrint(file, "%s\tID\n%s\t%d\n", tabs, tabs, data->id); + abstractFilePrint(file, "%s\tName\n%s\t%s\n", tabs, tabs, data->name); + abstractFilePrint(file, "%s\n", tabs); + + free(tabs); +} + +void writeResources(AbstractFile* file, ResourceKey* resources) { + ResourceKey* curResource; + ResourceData* curData; + + abstractFilePrint(file, plistHeader); + abstractFilePrint(file, "\tresource-fork\n\t\n"); + + curResource = resources; + while(curResource != NULL) { + abstractFilePrint(file, "\t\t%s\n\t\t\n", curResource->key); + curData = curResource->data; + while(curData != NULL) { + writeResourceData(file, curData, curResource->flipData, 3); + curData = curData->next; + } + abstractFilePrint(file, "\t\t\n", curResource->key); + curResource = curResource->next; + } + + abstractFilePrint(file, "\t\n"); + abstractFilePrint(file, plistFooter); + +} + +static void releaseResourceData(ResourceData* data) { + ResourceData* curData; + ResourceData* nextData; + + nextData = data; + while(nextData != NULL) { + curData = nextData; + + if(curData->name) + free(curData->name); + + if(curData->data) + free(curData->data); + + nextData = nextData->next; + free(curData); + } +} + +void releaseResources(ResourceKey* resources) { + ResourceKey* curResource; + ResourceKey* nextResource; + + nextResource = resources; + while(nextResource != NULL) { + curResource = nextResource; + free(curResource->key); + releaseResourceData(curResource->data); + nextResource = nextResource->next; + free(curResource); + } +} + +ResourceKey* getResourceByKey(ResourceKey* resources, const char* key) { + ResourceKey* curResource; + + curResource = resources; + while(curResource != NULL) { + if(strcmp((char*) curResource->key, key) == 0) { + return curResource; + } + curResource = curResource->next; + } + + return NULL; +} + +ResourceData* getDataByID(ResourceKey* resource, int id) { + ResourceData* curData; + + curData = resource->data; + + while(curData != NULL) { + if(curData->id == id) { + return curData; + } + curData = curData->next; + } + + return NULL; +} + +ResourceKey* insertData(ResourceKey* resources, const char* key, int id, const char* name, const char* data, size_t dataLength, uint32_t attributes) { + ResourceKey* curResource; + ResourceKey* lastResource; + ResourceData* curData; + + lastResource = resources; + curResource = resources; + while(curResource != NULL) { + if(strcmp((char*) curResource->key, key) == 0) { + break; + } + lastResource = curResource; + curResource = curResource->next; + } + + if(curResource == NULL) { + if(lastResource == NULL) { + curResource = (ResourceKey*) malloc(sizeof(ResourceKey)); + } else { + lastResource->next = (ResourceKey*) malloc(sizeof(ResourceKey)); + curResource = lastResource->next; + } + + curResource->key = (unsigned char*) malloc(strlen(key) + 1); + strcpy((char*) curResource->key, key); + curResource->next = NULL; + + if(strcmp((char*) curResource->key, "blkx") == 0) { + curResource->flipData = &flipBLKX; + } else if(strcmp((char*) curResource->key, "size") == 0) { + printf("we know to flip this size resource\n"); + curResource->flipData = &flipSizeResource; + } else if(strcmp((char*) curResource->key, "cSum") == 0) { + curResource->flipData = &flipCSumResource; + } else { + curResource->flipData = NULL; + } + + curResource->data = NULL; + } + + if(curResource->data == NULL) { + curData = (ResourceData*) malloc(sizeof(ResourceData)); + curResource->data = curData; + curData->next = NULL; + } else { + curData = curResource->data; + while(curData->next != NULL) { + if(curData->id == id) { + break; + } + curData = curData->next; + } + + if(curData->id != id) { + curData->next = (ResourceData*) malloc(sizeof(ResourceData)); + curData = curData->next; + curData->next = NULL; + } else { + free(curData->data); + free(curData->name); + } + } + + curData->attributes = attributes; + curData->dataLength = dataLength; + curData->id = id; + curData->name = (unsigned char*) malloc(strlen(name) + 1); + strcpy((char*) curData->name, name); + curData->data = (unsigned char*) malloc(dataLength); + memcpy(curData->data, data, dataLength); + + int i = 0; + if(resources) { + curResource = resources; + while(curResource) { + curResource = curResource->next; + i++; + } + return resources; + } else { + return curResource; + } +} + +ResourceKey* makePlst() { + return insertData(NULL, "plst", 0, "", plstData, sizeof(plstData), ATTRIBUTE_HDIUTIL); +} + +ResourceKey* makeSize(HFSPlusVolumeHeader* volumeHeader) { + SizeResource size; + memset(&size, 0, sizeof(SizeResource)); + size.version = 5; + size.isHFS = 1; + size.unknown2 = 0; + size.unknown3 = 0; + size.volumeModified = volumeHeader->modifyDate; + size.unknown4 = 0; + size.volumeSignature = volumeHeader->signature; + size.sizePresent = 1; + + printf("making size data\n"); + return insertData(NULL, "size", 0, "", (const char*)(&size), sizeof(SizeResource), 0); +} + diff --git a/dmg/udif.c b/dmg/udif.c index 41fea45..60a4835 100644 --- a/dmg/udif.c +++ b/dmg/udif.c @@ -1,129 +1,129 @@ -#include -#include -#include - -#include "dmg.h" - -void flipUDIFChecksum(UDIFChecksum* o, char out) { - int i; - - FLIPENDIAN(o->type); - - if(out) { - for(i = 0; i < o->size; i++) { - FLIPENDIAN(o->data[i]); - } - FLIPENDIAN(o->size); - } else { - FLIPENDIAN(o->size); - for(i = 0; i < o->size; i++) { - FLIPENDIAN(o->data[i]); - } - } -} - -void readUDIFChecksum(AbstractFile* file, UDIFChecksum* o) { - int i; - - o->type = readUInt32(file); - o->size = readUInt32(file); - - for(i = 0; i < 0x20; i++) { - o->data[i] = readUInt32(file); - } -} - -void writeUDIFChecksum(AbstractFile* file, UDIFChecksum* o) { - int i; - - writeUInt32(file, o->type); - writeUInt32(file, o->size); - - for(i = 0; i < o->size; i++) { - writeUInt32(file, o->data[i]); - } -} - -void readUDIFID(AbstractFile* file, UDIFID* o) { - o->data4 = readUInt32(file); FLIPENDIAN(o->data4); - o->data3 = readUInt32(file); FLIPENDIAN(o->data3); - o->data2 = readUInt32(file); FLIPENDIAN(o->data2); - o->data1 = readUInt32(file); FLIPENDIAN(o->data1); -} - -void writeUDIFID(AbstractFile* file, UDIFID* o) { - FLIPENDIAN(o->data4); writeUInt32(file, o->data4); FLIPENDIAN(o->data4); - FLIPENDIAN(o->data3); writeUInt32(file, o->data3); FLIPENDIAN(o->data3); - FLIPENDIAN(o->data2); writeUInt32(file, o->data2); FLIPENDIAN(o->data2); - FLIPENDIAN(o->data1); writeUInt32(file, o->data1); FLIPENDIAN(o->data1); -} - -void readUDIFResourceFile(AbstractFile* file, UDIFResourceFile* o) { - o->fUDIFSignature = readUInt32(file); - - ASSERT(o->fUDIFSignature == 0x6B6F6C79, "readUDIFResourceFile - signature incorrect"); - - o->fUDIFVersion = readUInt32(file); - o->fUDIFHeaderSize = readUInt32(file); - o->fUDIFFlags = readUInt32(file); - - o->fUDIFRunningDataForkOffset = readUInt64(file); - o->fUDIFDataForkOffset = readUInt64(file); - o->fUDIFDataForkLength = readUInt64(file); - o->fUDIFRsrcForkOffset = readUInt64(file); - o->fUDIFRsrcForkLength = readUInt64(file); - - o->fUDIFSegmentNumber = readUInt32(file); - o->fUDIFSegmentCount = readUInt32(file); - readUDIFID(file, &(o->fUDIFSegmentID)); - - readUDIFChecksum(file, &(o->fUDIFDataForkChecksum)); - - o->fUDIFXMLOffset = readUInt64(file); - o->fUDIFXMLLength = readUInt64(file); - - ASSERT(file->read(file, &(o->reserved1), 0x78) == 0x78, "fread"); - - readUDIFChecksum(file, &(o->fUDIFMasterChecksum)); - - o->fUDIFImageVariant = readUInt32(file); - o->fUDIFSectorCount = readUInt64(file); - - o->reserved2 = readUInt32(file); - o->reserved3 = readUInt32(file); - o->reserved4 = readUInt32(file); -} - -void writeUDIFResourceFile(AbstractFile* file, UDIFResourceFile* o) { - writeUInt32(file, o->fUDIFSignature); - writeUInt32(file, o->fUDIFVersion); - writeUInt32(file, o->fUDIFHeaderSize); - writeUInt32(file, o->fUDIFFlags); - - writeUInt64(file, o->fUDIFRunningDataForkOffset); - writeUInt64(file, o->fUDIFDataForkOffset); - writeUInt64(file, o->fUDIFDataForkLength); - writeUInt64(file, o->fUDIFRsrcForkOffset); - writeUInt64(file, o->fUDIFRsrcForkLength); - - writeUInt32(file, o->fUDIFSegmentNumber); - writeUInt32(file, o->fUDIFSegmentCount); - writeUDIFID(file, &(o->fUDIFSegmentID)); - - writeUDIFChecksum(file, &(o->fUDIFDataForkChecksum)); - - writeUInt64(file, o->fUDIFXMLOffset); - writeUInt64(file, o->fUDIFXMLLength); - - ASSERT(file->write(file, &(o->reserved1), 0x78) == 0x78, "fwrite"); - - writeUDIFChecksum(file, &(o->fUDIFMasterChecksum)); - - writeUInt32(file, o->fUDIFImageVariant); - writeUInt64(file, o->fUDIFSectorCount); - - writeUInt32(file, o->reserved2); - writeUInt32(file, o->reserved3); - writeUInt32(file, o->reserved4); -} - +#include +#include +#include + +#include "dmg.h" + +void flipUDIFChecksum(UDIFChecksum* o, char out) { + int i; + + FLIPENDIAN(o->type); + + if(out) { + for(i = 0; i < o->size; i++) { + FLIPENDIAN(o->data[i]); + } + FLIPENDIAN(o->size); + } else { + FLIPENDIAN(o->size); + for(i = 0; i < o->size; i++) { + FLIPENDIAN(o->data[i]); + } + } +} + +void readUDIFChecksum(AbstractFile* file, UDIFChecksum* o) { + int i; + + o->type = readUInt32(file); + o->size = readUInt32(file); + + for(i = 0; i < 0x20; i++) { + o->data[i] = readUInt32(file); + } +} + +void writeUDIFChecksum(AbstractFile* file, UDIFChecksum* o) { + int i; + + writeUInt32(file, o->type); + writeUInt32(file, o->size); + + for(i = 0; i < o->size; i++) { + writeUInt32(file, o->data[i]); + } +} + +void readUDIFID(AbstractFile* file, UDIFID* o) { + o->data4 = readUInt32(file); FLIPENDIAN(o->data4); + o->data3 = readUInt32(file); FLIPENDIAN(o->data3); + o->data2 = readUInt32(file); FLIPENDIAN(o->data2); + o->data1 = readUInt32(file); FLIPENDIAN(o->data1); +} + +void writeUDIFID(AbstractFile* file, UDIFID* o) { + FLIPENDIAN(o->data4); writeUInt32(file, o->data4); FLIPENDIAN(o->data4); + FLIPENDIAN(o->data3); writeUInt32(file, o->data3); FLIPENDIAN(o->data3); + FLIPENDIAN(o->data2); writeUInt32(file, o->data2); FLIPENDIAN(o->data2); + FLIPENDIAN(o->data1); writeUInt32(file, o->data1); FLIPENDIAN(o->data1); +} + +void readUDIFResourceFile(AbstractFile* file, UDIFResourceFile* o) { + o->fUDIFSignature = readUInt32(file); + + ASSERT(o->fUDIFSignature == 0x6B6F6C79, "readUDIFResourceFile - signature incorrect"); + + o->fUDIFVersion = readUInt32(file); + o->fUDIFHeaderSize = readUInt32(file); + o->fUDIFFlags = readUInt32(file); + + o->fUDIFRunningDataForkOffset = readUInt64(file); + o->fUDIFDataForkOffset = readUInt64(file); + o->fUDIFDataForkLength = readUInt64(file); + o->fUDIFRsrcForkOffset = readUInt64(file); + o->fUDIFRsrcForkLength = readUInt64(file); + + o->fUDIFSegmentNumber = readUInt32(file); + o->fUDIFSegmentCount = readUInt32(file); + readUDIFID(file, &(o->fUDIFSegmentID)); + + readUDIFChecksum(file, &(o->fUDIFDataForkChecksum)); + + o->fUDIFXMLOffset = readUInt64(file); + o->fUDIFXMLLength = readUInt64(file); + + ASSERT(file->read(file, &(o->reserved1), 0x78) == 0x78, "fread"); + + readUDIFChecksum(file, &(o->fUDIFMasterChecksum)); + + o->fUDIFImageVariant = readUInt32(file); + o->fUDIFSectorCount = readUInt64(file); + + o->reserved2 = readUInt32(file); + o->reserved3 = readUInt32(file); + o->reserved4 = readUInt32(file); +} + +void writeUDIFResourceFile(AbstractFile* file, UDIFResourceFile* o) { + writeUInt32(file, o->fUDIFSignature); + writeUInt32(file, o->fUDIFVersion); + writeUInt32(file, o->fUDIFHeaderSize); + writeUInt32(file, o->fUDIFFlags); + + writeUInt64(file, o->fUDIFRunningDataForkOffset); + writeUInt64(file, o->fUDIFDataForkOffset); + writeUInt64(file, o->fUDIFDataForkLength); + writeUInt64(file, o->fUDIFRsrcForkOffset); + writeUInt64(file, o->fUDIFRsrcForkLength); + + writeUInt32(file, o->fUDIFSegmentNumber); + writeUInt32(file, o->fUDIFSegmentCount); + writeUDIFID(file, &(o->fUDIFSegmentID)); + + writeUDIFChecksum(file, &(o->fUDIFDataForkChecksum)); + + writeUInt64(file, o->fUDIFXMLOffset); + writeUInt64(file, o->fUDIFXMLLength); + + ASSERT(file->write(file, &(o->reserved1), 0x78) == 0x78, "fwrite"); + + writeUDIFChecksum(file, &(o->fUDIFMasterChecksum)); + + writeUInt32(file, o->fUDIFImageVariant); + writeUInt64(file, o->fUDIFSectorCount); + + writeUInt32(file, o->reserved2); + writeUInt32(file, o->reserved3); + writeUInt32(file, o->reserved4); +} + diff --git a/dmg/win32test.c b/dmg/win32test.c index 85f2cba..cbc6106 100644 --- a/dmg/win32test.c +++ b/dmg/win32test.c @@ -1,9 +1,9 @@ -#include - -#ifdef WIN32 -blahfs-o_f-0-(){ {}A -#else -int main(int argc, char* argv[]) { - return 0; -} -#endif +#include + +#ifdef WIN32 +blahfs-o_f-0-(){ {}A +#else +int main(int argc, char* argv[]) { + return 0; +} +#endif diff --git a/dmg/zlib-1.2.3/contrib/masmx64/inffas8664.c b/dmg/zlib-1.2.3/contrib/masmx64/inffas8664.c index 3af764d..3b54555 100644 --- a/dmg/zlib-1.2.3/contrib/masmx64/inffas8664.c +++ b/dmg/zlib-1.2.3/contrib/masmx64/inffas8664.c @@ -1,186 +1,186 @@ -/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding - * version for AMD64 on Windows using Microsoft C compiler - * - * Copyright (C) 1995-2003 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Copyright (C) 2003 Chris Anderson - * Please use the copyright conditions above. - * - * 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant - * - * inffas8664.c call function inffas8664fnc in inffasx64.asm - * inffasx64.asm is automatically convert from AMD64 portion of inffas86.c - * - * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also - * slightly quicker on x86 systems because, instead of using rep movsb to copy - * data, it uses rep movsw, which moves data in 2-byte chunks instead of single - * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates - * from http://fedora.linux.duke.edu/fc1_x86_64 - * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with - * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, - * when decompressing mozilla-source-1.3.tar.gz. - * - * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from - * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at - * the moment. I have successfully compiled and tested this code with gcc2.96, - * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S - * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX - * enabled. I will attempt to merge the MMX code into this version. Newer - * versions of this and inffast.S can be found at - * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ - * - */ - -#include -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -/* Mark Adler's comments from inffast.c: */ - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ - - - - typedef struct inffast_ar { -/* 64 32 x86 x86_64 */ -/* ar offset register */ -/* 0 0 */ void *esp; /* esp save */ -/* 8 4 */ void *ebp; /* ebp save */ -/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ -/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ -/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ -/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ -/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ -/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ -/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ -/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ -/* 80 40 */ size_t /*unsigned long */hold; /* edx rdx local strm->hold */ -/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ -/* 92 48 */ unsigned wsize; /* window size */ -/* 96 52 */ unsigned write; /* window write index */ -/*100 56 */ unsigned lmask; /* r12 mask for lcode */ -/*104 60 */ unsigned dmask; /* r13 mask for dcode */ -/*108 64 */ unsigned len; /* r14 match length */ -/*112 68 */ unsigned dist; /* r15 match distance */ -/*116 72 */ unsigned status; /* set when state chng*/ - } type_ar; -#ifdef ASMINF - -void inflate_fast(strm, start) -z_streamp strm; -unsigned start; /* inflate()'s starting value for strm->avail_out */ -{ - struct inflate_state FAR *state; - type_ar ar; - void inffas8664fnc(struct inffast_ar * par); - - - -#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64)) -#define PAD_AVAIL_IN 6 -#define PAD_AVAIL_OUT 258 -#else -#define PAD_AVAIL_IN 5 -#define PAD_AVAIL_OUT 257 -#endif - - /* copy state to local variables */ - state = (struct inflate_state FAR *)strm->state; - - ar.in = strm->next_in; - ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); - ar.out = strm->next_out; - ar.beg = ar.out - (start - strm->avail_out); - ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); - ar.wsize = state->wsize; - ar.write = state->write; - ar.window = state->window; - ar.hold = state->hold; - ar.bits = state->bits; - ar.lcode = state->lencode; - ar.dcode = state->distcode; - ar.lmask = (1U << state->lenbits) - 1; - ar.dmask = (1U << state->distbits) - 1; - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - - /* align in on 1/2 hold size boundary */ - while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { - ar.hold += (unsigned long)*ar.in++ << ar.bits; - ar.bits += 8; - } - - inffas8664fnc(&ar); - - if (ar.status > 1) { - if (ar.status == 2) - strm->msg = "invalid literal/length code"; - else if (ar.status == 3) - strm->msg = "invalid distance code"; - else - strm->msg = "invalid distance too far back"; - state->mode = BAD; - } - else if ( ar.status == 1 ) { - state->mode = TYPE; - } - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - ar.len = ar.bits >> 3; - ar.in -= ar.len; - ar.bits -= ar.len << 3; - ar.hold &= (1U << ar.bits) - 1; - - /* update state and return */ - strm->next_in = ar.in; - strm->next_out = ar.out; - strm->avail_in = (unsigned)(ar.in < ar.last ? - PAD_AVAIL_IN + (ar.last - ar.in) : - PAD_AVAIL_IN - (ar.in - ar.last)); - strm->avail_out = (unsigned)(ar.out < ar.end ? - PAD_AVAIL_OUT + (ar.end - ar.out) : - PAD_AVAIL_OUT - (ar.out - ar.end)); - state->hold = (unsigned long)ar.hold; - state->bits = ar.bits; - return; -} - -#endif +/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding + * version for AMD64 on Windows using Microsoft C compiler + * + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Copyright (C) 2003 Chris Anderson + * Please use the copyright conditions above. + * + * 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant + * + * inffas8664.c call function inffas8664fnc in inffasx64.asm + * inffasx64.asm is automatically convert from AMD64 portion of inffas86.c + * + * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also + * slightly quicker on x86 systems because, instead of using rep movsb to copy + * data, it uses rep movsw, which moves data in 2-byte chunks instead of single + * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates + * from http://fedora.linux.duke.edu/fc1_x86_64 + * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with + * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, + * when decompressing mozilla-source-1.3.tar.gz. + * + * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from + * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at + * the moment. I have successfully compiled and tested this code with gcc2.96, + * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S + * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX + * enabled. I will attempt to merge the MMX code into this version. Newer + * versions of this and inffast.S can be found at + * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ + * + */ + +#include +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* Mark Adler's comments from inffast.c: */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ + + + + typedef struct inffast_ar { +/* 64 32 x86 x86_64 */ +/* ar offset register */ +/* 0 0 */ void *esp; /* esp save */ +/* 8 4 */ void *ebp; /* ebp save */ +/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ +/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ +/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ +/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ +/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ +/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ +/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ +/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ +/* 80 40 */ size_t /*unsigned long */hold; /* edx rdx local strm->hold */ +/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ +/* 92 48 */ unsigned wsize; /* window size */ +/* 96 52 */ unsigned write; /* window write index */ +/*100 56 */ unsigned lmask; /* r12 mask for lcode */ +/*104 60 */ unsigned dmask; /* r13 mask for dcode */ +/*108 64 */ unsigned len; /* r14 match length */ +/*112 68 */ unsigned dist; /* r15 match distance */ +/*116 72 */ unsigned status; /* set when state chng*/ + } type_ar; +#ifdef ASMINF + +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + type_ar ar; + void inffas8664fnc(struct inffast_ar * par); + + + +#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64)) +#define PAD_AVAIL_IN 6 +#define PAD_AVAIL_OUT 258 +#else +#define PAD_AVAIL_IN 5 +#define PAD_AVAIL_OUT 257 +#endif + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + + ar.in = strm->next_in; + ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); + ar.out = strm->next_out; + ar.beg = ar.out - (start - strm->avail_out); + ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); + ar.wsize = state->wsize; + ar.write = state->write; + ar.window = state->window; + ar.hold = state->hold; + ar.bits = state->bits; + ar.lcode = state->lencode; + ar.dcode = state->distcode; + ar.lmask = (1U << state->lenbits) - 1; + ar.dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + /* align in on 1/2 hold size boundary */ + while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { + ar.hold += (unsigned long)*ar.in++ << ar.bits; + ar.bits += 8; + } + + inffas8664fnc(&ar); + + if (ar.status > 1) { + if (ar.status == 2) + strm->msg = "invalid literal/length code"; + else if (ar.status == 3) + strm->msg = "invalid distance code"; + else + strm->msg = "invalid distance too far back"; + state->mode = BAD; + } + else if ( ar.status == 1 ) { + state->mode = TYPE; + } + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + ar.len = ar.bits >> 3; + ar.in -= ar.len; + ar.bits -= ar.len << 3; + ar.hold &= (1U << ar.bits) - 1; + + /* update state and return */ + strm->next_in = ar.in; + strm->next_out = ar.out; + strm->avail_in = (unsigned)(ar.in < ar.last ? + PAD_AVAIL_IN + (ar.last - ar.in) : + PAD_AVAIL_IN - (ar.in - ar.last)); + strm->avail_out = (unsigned)(ar.out < ar.end ? + PAD_AVAIL_OUT + (ar.end - ar.out) : + PAD_AVAIL_OUT - (ar.out - ar.end)); + state->hold = (unsigned long)ar.hold; + state->bits = ar.bits; + return; +} + +#endif diff --git a/dmg/zlib-1.2.3/contrib/masmx86/gvmat32c.c b/dmg/zlib-1.2.3/contrib/masmx86/gvmat32c.c index 7ad2b27..89f525c 100644 --- a/dmg/zlib-1.2.3/contrib/masmx86/gvmat32c.c +++ b/dmg/zlib-1.2.3/contrib/masmx86/gvmat32c.c @@ -1,62 +1,62 @@ -/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86 - * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant. - * File written by Gilles Vollant, by modifiying the longest_match - * from Jean-loup Gailly in deflate.c - * it prepare all parameters and call the assembly longest_match_gvasm - * longest_match execute standard C code is wmask != 0x7fff - * (assembly code is faster with a fixed wmask) - * - * Read comment at beginning of gvmat32.asm for more information - */ - -#if defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) -#include "deflate.h" - -/* if your C compiler don't add underline before function name, - define ADD_UNDERLINE_ASMFUNC */ -#ifdef ADD_UNDERLINE_ASMFUNC -#define longest_match_7fff _longest_match_7fff -#define longest_match_686 _longest_match_686 -#define cpudetect32 _cpudetect32 -#endif - - -unsigned long cpudetect32(); - -uInt longest_match_c( - deflate_state *s, - IPos cur_match); /* current match */ - - -uInt longest_match_7fff( - deflate_state *s, - IPos cur_match); /* current match */ - -uInt longest_match_686( - deflate_state *s, - IPos cur_match); /* current match */ - - -static uInt iIsPPro=2; - -void match_init () -{ - iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0; -} - -uInt longest_match( - deflate_state *s, - IPos cur_match) /* current match */ -{ - if (iIsPPro!=0) - return longest_match_686(s,cur_match); - - if (s->w_mask != 0x7fff) - return longest_match_686(s,cur_match); - - /* now ((s->w_mask == 0x7fff) && (iIsPPro==0)) */ - return longest_match_7fff(s,cur_match); -} - - -#endif /* defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) */ +/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86 + * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant. + * File written by Gilles Vollant, by modifiying the longest_match + * from Jean-loup Gailly in deflate.c + * it prepare all parameters and call the assembly longest_match_gvasm + * longest_match execute standard C code is wmask != 0x7fff + * (assembly code is faster with a fixed wmask) + * + * Read comment at beginning of gvmat32.asm for more information + */ + +#if defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) +#include "deflate.h" + +/* if your C compiler don't add underline before function name, + define ADD_UNDERLINE_ASMFUNC */ +#ifdef ADD_UNDERLINE_ASMFUNC +#define longest_match_7fff _longest_match_7fff +#define longest_match_686 _longest_match_686 +#define cpudetect32 _cpudetect32 +#endif + + +unsigned long cpudetect32(); + +uInt longest_match_c( + deflate_state *s, + IPos cur_match); /* current match */ + + +uInt longest_match_7fff( + deflate_state *s, + IPos cur_match); /* current match */ + +uInt longest_match_686( + deflate_state *s, + IPos cur_match); /* current match */ + + +static uInt iIsPPro=2; + +void match_init () +{ + iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0; +} + +uInt longest_match( + deflate_state *s, + IPos cur_match) /* current match */ +{ + if (iIsPPro!=0) + return longest_match_686(s,cur_match); + + if (s->w_mask != 0x7fff) + return longest_match_686(s,cur_match); + + /* now ((s->w_mask == 0x7fff) && (iIsPPro==0)) */ + return longest_match_7fff(s,cur_match); +} + + +#endif /* defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) */ diff --git a/dmg/zlib-1.2.3/contrib/testzlib/testzlib.c b/dmg/zlib-1.2.3/contrib/testzlib/testzlib.c index e5574f4..08a4b4b 100644 --- a/dmg/zlib-1.2.3/contrib/testzlib/testzlib.c +++ b/dmg/zlib-1.2.3/contrib/testzlib/testzlib.c @@ -1,275 +1,275 @@ -#include -#include -#include - -#include "zlib.h" - - -void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B) -{ - R->HighPart = A.HighPart - B.HighPart; - if (A.LowPart >= B.LowPart) - R->LowPart = A.LowPart - B.LowPart; - else - { - R->LowPart = A.LowPart - B.LowPart; - R->HighPart --; - } -} - -#ifdef _M_X64 -// see http://msdn2.microsoft.com/library/twchhe95(en-us,vs.80).aspx for __rdtsc -unsigned __int64 __rdtsc(void); -void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) -{ - // printf("rdtsc = %I64x\n",__rdtsc()); - pbeginTime64->QuadPart=__rdtsc(); -} - -LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER LIres; - unsigned _int64 res=__rdtsc()-((unsigned _int64)(beginTime64.QuadPart)); - LIres.QuadPart=res; - // printf("rdtsc = %I64x\n",__rdtsc()); - return LIres; -} -#else -#ifdef _M_IX86 -void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) -{ - DWORD dwEdx,dwEax; - _asm - { - rdtsc - mov dwEax,eax - mov dwEdx,edx - } - pbeginTime64->LowPart=dwEax; - pbeginTime64->HighPart=dwEdx; -} - -void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) -{ - myGetRDTSC32(pbeginTime64); -} - -LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER LIres,endTime64; - myGetRDTSC32(&endTime64); - - LIres.LowPart=LIres.HighPart=0; - MyDoMinus64(&LIres,endTime64,beginTime64); - return LIres; -} -#else -void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) -{ -} - -void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) -{ -} - -LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER lr; - lr.QuadPart=0; - return lr; -} -#endif -#endif - -void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf) -{ - if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64))) - { - pbeginTime64->LowPart = GetTickCount(); - pbeginTime64->HighPart = 0; - } -} - -DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) -{ - LARGE_INTEGER endTime64,ticksPerSecond,ticks; - DWORDLONG ticksShifted,tickSecShifted; - DWORD dwLog=16+0; - DWORD dwRet; - if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64))) - dwRet = (GetTickCount() - beginTime64.LowPart)*1; - else - { - MyDoMinus64(&ticks,endTime64,beginTime64); - QueryPerformanceFrequency(&ticksPerSecond); - - - { - ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog); - tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog); - - } - - dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted)); - dwRet *=1; - } - return dwRet; -} - -int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr) -{ - FILE* stream; - void* ptr; - int retVal=1; - stream=fopen(filename, "rb"); - if (stream==NULL) - return 0; - - fseek(stream,0,SEEK_END); - - *plFileSize=ftell(stream); - fseek(stream,0,SEEK_SET); - ptr=malloc((*plFileSize)+1); - if (ptr==NULL) - retVal=0; - else - { - if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize)) - retVal=0; - } - fclose(stream); - *pFilePtr=ptr; - return retVal; -} - -int main(int argc, char *argv[]) -{ - int BlockSizeCompress=0x8000; - int BlockSizeUncompress=0x8000; - int cprLevel=Z_DEFAULT_COMPRESSION ; - long lFileSize; - unsigned char* FilePtr; - long lBufferSizeCpr; - long lBufferSizeUncpr; - long lCompressedSize=0; - unsigned char* CprPtr; - unsigned char* UncprPtr; - long lSizeCpr,lSizeUncpr; - DWORD dwGetTick,dwMsecQP; - LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc; - - if (argc<=1) - { - printf("run TestZlib [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n"); - return 0; - } - - if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0) - { - printf("error reading %s\n",argv[1]); - return 1; - } - else printf("file %s read, %u bytes\n",argv[1],lFileSize); - - if (argc>=3) - BlockSizeCompress=atol(argv[2]); - - if (argc>=4) - BlockSizeUncompress=atol(argv[3]); - - if (argc>=5) - cprLevel=(int)atol(argv[4]); - - lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200; - lBufferSizeUncpr = lBufferSizeCpr; - - CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress); - - BeginCountPerfCounter(&li_qp,TRUE); - dwGetTick=GetTickCount(); - BeginCountRdtsc(&li_rdtsc); - { - z_stream zcpr; - int ret=Z_OK; - long lOrigToDo = lFileSize; - long lOrigDone = 0; - int step=0; - memset(&zcpr,0,sizeof(z_stream)); - deflateInit(&zcpr,cprLevel); - - zcpr.next_in = FilePtr; - zcpr.next_out = CprPtr; - - - do - { - long all_read_before = zcpr.total_in; - zcpr.avail_in = min(lOrigToDo,BlockSizeCompress); - zcpr.avail_out = BlockSizeCompress; - ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH); - lOrigDone += (zcpr.total_in-all_read_before); - lOrigToDo -= (zcpr.total_in-all_read_before); - step++; - } while (ret==Z_OK); - - lSizeCpr=zcpr.total_out; - deflateEnd(&zcpr); - dwGetTick=GetTickCount()-dwGetTick; - dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); - dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); - printf("total compress size = %u, in %u step\n",lSizeCpr,step); - printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); - printf("defcpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); - printf("defcpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); - } - - CprPtr=(unsigned char*)realloc(CprPtr,lSizeCpr); - UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress); - - BeginCountPerfCounter(&li_qp,TRUE); - dwGetTick=GetTickCount(); - BeginCountRdtsc(&li_rdtsc); - { - z_stream zcpr; - int ret=Z_OK; - long lOrigToDo = lSizeCpr; - long lOrigDone = 0; - int step=0; - memset(&zcpr,0,sizeof(z_stream)); - inflateInit(&zcpr); - - zcpr.next_in = CprPtr; - zcpr.next_out = UncprPtr; - - - do - { - long all_read_before = zcpr.total_in; - zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress); - zcpr.avail_out = BlockSizeUncompress; - ret=inflate(&zcpr,Z_SYNC_FLUSH); - lOrigDone += (zcpr.total_in-all_read_before); - lOrigToDo -= (zcpr.total_in-all_read_before); - step++; - } while (ret==Z_OK); - - lSizeUncpr=zcpr.total_out; - inflateEnd(&zcpr); - dwGetTick=GetTickCount()-dwGetTick; - dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); - dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); - printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step); - printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); - printf("uncpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); - printf("uncpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); - } - - if (lSizeUncpr==lFileSize) - { - if (memcmp(FilePtr,UncprPtr,lFileSize)==0) - printf("compare ok\n"); - - } - - return 0; -} +#include +#include +#include + +#include "zlib.h" + + +void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B) +{ + R->HighPart = A.HighPart - B.HighPart; + if (A.LowPart >= B.LowPart) + R->LowPart = A.LowPart - B.LowPart; + else + { + R->LowPart = A.LowPart - B.LowPart; + R->HighPart --; + } +} + +#ifdef _M_X64 +// see http://msdn2.microsoft.com/library/twchhe95(en-us,vs.80).aspx for __rdtsc +unsigned __int64 __rdtsc(void); +void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) +{ + // printf("rdtsc = %I64x\n",__rdtsc()); + pbeginTime64->QuadPart=__rdtsc(); +} + +LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER LIres; + unsigned _int64 res=__rdtsc()-((unsigned _int64)(beginTime64.QuadPart)); + LIres.QuadPart=res; + // printf("rdtsc = %I64x\n",__rdtsc()); + return LIres; +} +#else +#ifdef _M_IX86 +void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) +{ + DWORD dwEdx,dwEax; + _asm + { + rdtsc + mov dwEax,eax + mov dwEdx,edx + } + pbeginTime64->LowPart=dwEax; + pbeginTime64->HighPart=dwEdx; +} + +void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) +{ + myGetRDTSC32(pbeginTime64); +} + +LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER LIres,endTime64; + myGetRDTSC32(&endTime64); + + LIres.LowPart=LIres.HighPart=0; + MyDoMinus64(&LIres,endTime64,beginTime64); + return LIres; +} +#else +void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) +{ +} + +void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) +{ +} + +LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER lr; + lr.QuadPart=0; + return lr; +} +#endif +#endif + +void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf) +{ + if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64))) + { + pbeginTime64->LowPart = GetTickCount(); + pbeginTime64->HighPart = 0; + } +} + +DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER endTime64,ticksPerSecond,ticks; + DWORDLONG ticksShifted,tickSecShifted; + DWORD dwLog=16+0; + DWORD dwRet; + if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64))) + dwRet = (GetTickCount() - beginTime64.LowPart)*1; + else + { + MyDoMinus64(&ticks,endTime64,beginTime64); + QueryPerformanceFrequency(&ticksPerSecond); + + + { + ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog); + tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog); + + } + + dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted)); + dwRet *=1; + } + return dwRet; +} + +int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr) +{ + FILE* stream; + void* ptr; + int retVal=1; + stream=fopen(filename, "rb"); + if (stream==NULL) + return 0; + + fseek(stream,0,SEEK_END); + + *plFileSize=ftell(stream); + fseek(stream,0,SEEK_SET); + ptr=malloc((*plFileSize)+1); + if (ptr==NULL) + retVal=0; + else + { + if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize)) + retVal=0; + } + fclose(stream); + *pFilePtr=ptr; + return retVal; +} + +int main(int argc, char *argv[]) +{ + int BlockSizeCompress=0x8000; + int BlockSizeUncompress=0x8000; + int cprLevel=Z_DEFAULT_COMPRESSION ; + long lFileSize; + unsigned char* FilePtr; + long lBufferSizeCpr; + long lBufferSizeUncpr; + long lCompressedSize=0; + unsigned char* CprPtr; + unsigned char* UncprPtr; + long lSizeCpr,lSizeUncpr; + DWORD dwGetTick,dwMsecQP; + LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc; + + if (argc<=1) + { + printf("run TestZlib [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n"); + return 0; + } + + if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0) + { + printf("error reading %s\n",argv[1]); + return 1; + } + else printf("file %s read, %u bytes\n",argv[1],lFileSize); + + if (argc>=3) + BlockSizeCompress=atol(argv[2]); + + if (argc>=4) + BlockSizeUncompress=atol(argv[3]); + + if (argc>=5) + cprLevel=(int)atol(argv[4]); + + lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200; + lBufferSizeUncpr = lBufferSizeCpr; + + CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress); + + BeginCountPerfCounter(&li_qp,TRUE); + dwGetTick=GetTickCount(); + BeginCountRdtsc(&li_rdtsc); + { + z_stream zcpr; + int ret=Z_OK; + long lOrigToDo = lFileSize; + long lOrigDone = 0; + int step=0; + memset(&zcpr,0,sizeof(z_stream)); + deflateInit(&zcpr,cprLevel); + + zcpr.next_in = FilePtr; + zcpr.next_out = CprPtr; + + + do + { + long all_read_before = zcpr.total_in; + zcpr.avail_in = min(lOrigToDo,BlockSizeCompress); + zcpr.avail_out = BlockSizeCompress; + ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH); + lOrigDone += (zcpr.total_in-all_read_before); + lOrigToDo -= (zcpr.total_in-all_read_before); + step++; + } while (ret==Z_OK); + + lSizeCpr=zcpr.total_out; + deflateEnd(&zcpr); + dwGetTick=GetTickCount()-dwGetTick; + dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); + dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); + printf("total compress size = %u, in %u step\n",lSizeCpr,step); + printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); + printf("defcpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); + printf("defcpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); + } + + CprPtr=(unsigned char*)realloc(CprPtr,lSizeCpr); + UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress); + + BeginCountPerfCounter(&li_qp,TRUE); + dwGetTick=GetTickCount(); + BeginCountRdtsc(&li_rdtsc); + { + z_stream zcpr; + int ret=Z_OK; + long lOrigToDo = lSizeCpr; + long lOrigDone = 0; + int step=0; + memset(&zcpr,0,sizeof(z_stream)); + inflateInit(&zcpr); + + zcpr.next_in = CprPtr; + zcpr.next_out = UncprPtr; + + + do + { + long all_read_before = zcpr.total_in; + zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress); + zcpr.avail_out = BlockSizeUncompress; + ret=inflate(&zcpr,Z_SYNC_FLUSH); + lOrigDone += (zcpr.total_in-all_read_before); + lOrigToDo -= (zcpr.total_in-all_read_before); + step++; + } while (ret==Z_OK); + + lSizeUncpr=zcpr.total_out; + inflateEnd(&zcpr); + dwGetTick=GetTickCount()-dwGetTick; + dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); + dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); + printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step); + printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); + printf("uncpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); + printf("uncpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); + } + + if (lSizeUncpr==lFileSize) + { + if (memcmp(FilePtr,UncprPtr,lFileSize)==0) + printf("compare ok\n"); + + } + + return 0; +} diff --git a/dmg/zlib-1.2.3/projects/visualc6/README.txt b/dmg/zlib-1.2.3/projects/visualc6/README.txt index d0296c2..3d0aef0 100644 --- a/dmg/zlib-1.2.3/projects/visualc6/README.txt +++ b/dmg/zlib-1.2.3/projects/visualc6/README.txt @@ -1,73 +1,73 @@ -Microsoft Developer Studio Project Files, Format Version 6.00 for zlib. - -Copyright (C) 2000-2004 Simon-Pierre Cadieux. -Copyright (C) 2004 Cosmin Truta. -For conditions of distribution and use, see copyright notice in zlib.h. - - -This project builds the zlib binaries as follows: - -* Win32_DLL_Release\zlib1.dll DLL build -* Win32_DLL_Debug\zlib1d.dll DLL build (debug version) -* Win32_DLL_ASM_Release\zlib1.dll DLL build using ASM code -* Win32_DLL_ASM_Debug\zlib1d.dll DLL build using ASM code (debug version) -* Win32_LIB_Release\zlib.lib static build -* Win32_LIB_Debug\zlibd.lib static build (debug version) -* Win32_LIB_ASM_Release\zlib.lib static build using ASM code -* Win32_LIB_ASM_Debug\zlibd.lib static build using ASM code (debug version) - - -For more information regarding the DLL builds, please see the DLL FAQ -in ..\..\win32\DLL_FAQ.txt. - - -To build and test: - -1) On the main menu, select "File | Open Workspace". - Open "zlib.dsw". - -2) Select "Build | Set Active Configuration". - Choose the configuration you wish to build. - -3) Select "Build | Clean". - -4) Select "Build | Build ... (F7)". Ignore warning messages about - not being able to find certain include files (e.g. alloc.h). - -5) If you built one of the sample programs (example or minigzip), - select "Build | Execute ... (Ctrl+F5)". - - -To use: - -1) Select "Project | Settings (Alt+F7)". - Make note of the configuration names used in your project. - Usually, these names are "Win32 Release" and "Win32 Debug". - -2) In the Workspace window, select the "FileView" tab. - Right-click on the root item "Workspace '...'". - Select "Insert Project into Workspace". - Switch on the checkbox "Dependency of:", and select the name - of your project. Open "zlib.dsp". - -3) Select "Build | Configurations". - For each configuration of your project: - 3.1) Choose the zlib configuration you wish to use. - 3.2) Click on "Add". - 3.3) Set the new zlib configuration name to the name used by - the configuration from the current iteration. - -4) Select "Build | Set Active Configuration". - Choose the configuration you wish to build. - -5) Select "Build | Build ... (F7)". - -6) If you built an executable program, select - "Build | Execute ... (Ctrl+F5)". - - -Note: - -To build the ASM-enabled code, you need Microsoft Assembler -(ML.EXE). You can get it by downloading and installing the -latest Processor Pack for Visual C++ 6.0. +Microsoft Developer Studio Project Files, Format Version 6.00 for zlib. + +Copyright (C) 2000-2004 Simon-Pierre Cadieux. +Copyright (C) 2004 Cosmin Truta. +For conditions of distribution and use, see copyright notice in zlib.h. + + +This project builds the zlib binaries as follows: + +* Win32_DLL_Release\zlib1.dll DLL build +* Win32_DLL_Debug\zlib1d.dll DLL build (debug version) +* Win32_DLL_ASM_Release\zlib1.dll DLL build using ASM code +* Win32_DLL_ASM_Debug\zlib1d.dll DLL build using ASM code (debug version) +* Win32_LIB_Release\zlib.lib static build +* Win32_LIB_Debug\zlibd.lib static build (debug version) +* Win32_LIB_ASM_Release\zlib.lib static build using ASM code +* Win32_LIB_ASM_Debug\zlibd.lib static build using ASM code (debug version) + + +For more information regarding the DLL builds, please see the DLL FAQ +in ..\..\win32\DLL_FAQ.txt. + + +To build and test: + +1) On the main menu, select "File | Open Workspace". + Open "zlib.dsw". + +2) Select "Build | Set Active Configuration". + Choose the configuration you wish to build. + +3) Select "Build | Clean". + +4) Select "Build | Build ... (F7)". Ignore warning messages about + not being able to find certain include files (e.g. alloc.h). + +5) If you built one of the sample programs (example or minigzip), + select "Build | Execute ... (Ctrl+F5)". + + +To use: + +1) Select "Project | Settings (Alt+F7)". + Make note of the configuration names used in your project. + Usually, these names are "Win32 Release" and "Win32 Debug". + +2) In the Workspace window, select the "FileView" tab. + Right-click on the root item "Workspace '...'". + Select "Insert Project into Workspace". + Switch on the checkbox "Dependency of:", and select the name + of your project. Open "zlib.dsp". + +3) Select "Build | Configurations". + For each configuration of your project: + 3.1) Choose the zlib configuration you wish to use. + 3.2) Click on "Add". + 3.3) Set the new zlib configuration name to the name used by + the configuration from the current iteration. + +4) Select "Build | Set Active Configuration". + Choose the configuration you wish to build. + +5) Select "Build | Build ... (F7)". + +6) If you built an executable program, select + "Build | Execute ... (Ctrl+F5)". + + +Note: + +To build the ASM-enabled code, you need Microsoft Assembler +(ML.EXE). You can get it by downloading and installing the +latest Processor Pack for Visual C++ 6.0. diff --git a/hfs/Makefile b/hfs/Makefile index 9d07629..78afe22 100644 --- a/hfs/Makefile +++ b/hfs/Makefile @@ -1,16 +1,16 @@ -HFSPLUSOBJS=btree.o catalog.o extents.o flatfile.o rawfile.o volume.o utility.o hfs.o fastunicodecompare.o abstractfile.o hfslib.o -CFLAGS=-D_FILE_OFFSET_BITS=64 -O3 - -all: hfsplus - -hfsplus: $(HFSPLUSOBJS) - $(CC) $(CFLAGS) $(HFSPLUSOBJS) -o hfsplus - -%.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ - -clean: - -rm *.o - -rm hfsplus - -rm hfsplus.exe - +HFSPLUSOBJS=btree.o catalog.o extents.o flatfile.o rawfile.o volume.o utility.o hfs.o fastunicodecompare.o abstractfile.o hfslib.o +CFLAGS=-D_FILE_OFFSET_BITS=64 -O3 + +all: hfsplus + +hfsplus: $(HFSPLUSOBJS) + $(CC) $(CFLAGS) $(HFSPLUSOBJS) -o hfsplus + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + -rm *.o + -rm hfsplus + -rm hfsplus.exe + diff --git a/hfs/abstractfile.c b/hfs/abstractfile.c index 5c90e43..c7b4121 100644 --- a/hfs/abstractfile.c +++ b/hfs/abstractfile.c @@ -1,302 +1,302 @@ -#include -#include -#include +#include +#include +#include #include #include #include "abstractfile.h" -#include "common.h" - -size_t freadWrapper(AbstractFile* file, void* data, size_t len) { - return fread(data, 1, len, (FILE*) (file->data)); -} - -size_t fwriteWrapper(AbstractFile* file, const void* data, size_t len) { - return fwrite(data, 1, len, (FILE*) (file->data)); -} - -int fseekWrapper(AbstractFile* file, off_t offset) { - return fseeko((FILE*) (file->data), offset, SEEK_SET); -} - -off_t ftellWrapper(AbstractFile* file) { - return ftello((FILE*) (file->data)); -} - -void fcloseWrapper(AbstractFile* file) { - fclose((FILE*) (file->data)); - free(file); -} - -off_t fileGetLength(AbstractFile* file) { - off_t length; - off_t pos; - - pos = ftello((FILE*) (file->data)); - - fseeko((FILE*) (file->data), 0, SEEK_END); - length = ftello((FILE*) (file->data)); - - fseeko((FILE*) (file->data), pos, SEEK_SET); - - return length; -} - -AbstractFile* createAbstractFileFromFile(FILE* file) { - AbstractFile* toReturn; - - if(file == NULL) { - return NULL; - } - - toReturn = (AbstractFile*) malloc(sizeof(AbstractFile)); - toReturn->data = file; - toReturn->read = freadWrapper; - toReturn->write = fwriteWrapper; - toReturn->seek = fseekWrapper; - toReturn->tell = ftellWrapper; - toReturn->getLength = fileGetLength; - toReturn->close = fcloseWrapper; - return toReturn; -} - -size_t dummyRead(AbstractFile* file, void* data, size_t len) { - return 0; -} - -size_t dummyWrite(AbstractFile* file, const void* data, size_t len) { - *((off_t*) (file->data)) += len; - return len; -} - -int dummySeek(AbstractFile* file, off_t offset) { - *((off_t*) (file->data)) = offset; - return 0; -} - -off_t dummyTell(AbstractFile* file) { - return *((off_t*) (file->data)); -} - -void dummyClose(AbstractFile* file) { - free(file); -} - -AbstractFile* createAbstractFileFromDummy() { - AbstractFile* toReturn; - toReturn = (AbstractFile*) malloc(sizeof(AbstractFile)); - toReturn->data = NULL; - toReturn->read = dummyRead; - toReturn->write = dummyWrite; - toReturn->seek = dummySeek; - toReturn->tell = dummyTell; - toReturn->getLength = NULL; - toReturn->close = dummyClose; - return toReturn; -} - -size_t memRead(AbstractFile* file, void* data, size_t len) { - MemWrapperInfo* info = (MemWrapperInfo*) (file->data); - memcpy(data, (void*)((uint8_t*)(*(info->buffer)) + (uint32_t)info->offset), len); - info->offset += (size_t)len; - return len; -} - -size_t memWrite(AbstractFile* file, const void* data, size_t len) { - MemWrapperInfo* info = (MemWrapperInfo*) (file->data); - - while((info->offset + (size_t)len) > info->bufferSize) { - info->bufferSize <<= 1; - *(info->buffer) = realloc(*(info->buffer), info->bufferSize); - } - - memcpy((void*)((uint8_t*)(*(info->buffer)) + (uint32_t)info->offset), data, len); - info->offset += (size_t)len; - return len; -} - -int memSeek(AbstractFile* file, off_t offset) { - MemWrapperInfo* info = (MemWrapperInfo*) (file->data); - info->offset = (size_t)offset; - return 0; -} - -off_t memTell(AbstractFile* file) { - MemWrapperInfo* info = (MemWrapperInfo*) (file->data); - return (off_t)info->offset; -} - -off_t memGetLength(AbstractFile* file) { - MemWrapperInfo* info = (MemWrapperInfo*) (file->data); - return info->bufferSize; -} - -void memClose(AbstractFile* file) { - free(file->data); - free(file); -} - -AbstractFile* createAbstractFileFromMemory(void** buffer, size_t size) { - MemWrapperInfo* info; - AbstractFile* toReturn; - toReturn = (AbstractFile*) malloc(sizeof(AbstractFile)); - - info = (MemWrapperInfo*) malloc(sizeof(MemWrapperInfo)); - info->offset = 0; - info->buffer = buffer; - info->bufferSize = size; - - toReturn->data = info; - toReturn->read = memRead; - toReturn->write = memWrite; - toReturn->seek = memSeek; - toReturn->tell = memTell; - toReturn->getLength = memGetLength; - toReturn->close = memClose; - return toReturn; -} - -void abstractFilePrint(AbstractFile* file, const char* format, ...) { - va_list args; - char buffer[1024]; - size_t length; - - buffer[0] = '\0'; - va_start(args, format); - length = vsprintf(buffer, format, args); - va_end(args); - ASSERT(file->write(file, buffer, length) == length, "fwrite"); -} - -int absFileRead(io_func* io, off_t location, size_t size, void *buffer) { - AbstractFile* file; - file = (AbstractFile*) io->data; - file->seek(file, location); - if(file->read(file, buffer, size) == size) { - return TRUE; - } else { - return FALSE; - } -} - -int absFileWrite(io_func* io, off_t location, size_t size, void *buffer) { - AbstractFile* file; - file = (AbstractFile*) io->data; - file->seek(file, location); - if(file->write(file, buffer, size) == size) { - return TRUE; - } else { - return FALSE; - } -} - -void closeAbsFile(io_func* io) { - AbstractFile* file; - file = (AbstractFile*) io->data; - file->close(file); - free(io); -} - - -io_func* IOFuncFromAbstractFile(AbstractFile* file) { - io_func* io; - - io = (io_func*) malloc(sizeof(io_func)); - io->data = file; - io->read = &absFileRead; - io->write = &absFileWrite; - io->close = &closeAbsFile; - - return io; -} - -size_t memFileRead(AbstractFile* file, void* data, size_t len) { - MemFileWrapperInfo* info = (MemFileWrapperInfo*) (file->data); - memcpy(data, (void*)((uint8_t*)(*(info->buffer)) + (uint32_t)info->offset), len); - info->offset += (size_t)len; - return len; -} - -size_t memFileWrite(AbstractFile* file, const void* data, size_t len) { - MemFileWrapperInfo* info = (MemFileWrapperInfo*) (file->data); - - while((info->offset + (size_t)len) > info->actualBufferSize) { - info->actualBufferSize <<= 1; - *(info->buffer) = realloc(*(info->buffer), info->actualBufferSize); - } - - if((info->offset + (size_t)len) > (*(info->bufferSize))) { - *(info->bufferSize) = info->offset + (size_t)len; - } - - memcpy((void*)((uint8_t*)(*(info->buffer)) + (uint32_t)info->offset), data, len); - info->offset += (size_t)len; - return len; -} - -int memFileSeek(AbstractFile* file, off_t offset) { - MemFileWrapperInfo* info = (MemFileWrapperInfo*) (file->data); - info->offset = (size_t)offset; - return 0; -} - -off_t memFileTell(AbstractFile* file) { - MemFileWrapperInfo* info = (MemFileWrapperInfo*) (file->data); - return (off_t)info->offset; -} - -off_t memFileGetLength(AbstractFile* file) { - MemFileWrapperInfo* info = (MemFileWrapperInfo*) (file->data); - return *(info->bufferSize); -} - -void memFileClose(AbstractFile* file) { - free(file->data); - free(file); -} - -AbstractFile* createAbstractFileFromMemoryFile(void** buffer, size_t* size) { - MemFileWrapperInfo* info; - AbstractFile* toReturn; - toReturn = (AbstractFile*) malloc(sizeof(AbstractFile)); - - info = (MemFileWrapperInfo*) malloc(sizeof(MemFileWrapperInfo)); - info->offset = 0; - info->buffer = buffer; - info->bufferSize = size; +#include "common.h" + +size_t freadWrapper(AbstractFile* file, void* data, size_t len) { + return fread(data, 1, len, (FILE*) (file->data)); +} + +size_t fwriteWrapper(AbstractFile* file, const void* data, size_t len) { + return fwrite(data, 1, len, (FILE*) (file->data)); +} + +int fseekWrapper(AbstractFile* file, off_t offset) { + return fseeko((FILE*) (file->data), offset, SEEK_SET); +} + +off_t ftellWrapper(AbstractFile* file) { + return ftello((FILE*) (file->data)); +} + +void fcloseWrapper(AbstractFile* file) { + fclose((FILE*) (file->data)); + free(file); +} + +off_t fileGetLength(AbstractFile* file) { + off_t length; + off_t pos; + + pos = ftello((FILE*) (file->data)); + + fseeko((FILE*) (file->data), 0, SEEK_END); + length = ftello((FILE*) (file->data)); + + fseeko((FILE*) (file->data), pos, SEEK_SET); + + return length; +} + +AbstractFile* createAbstractFileFromFile(FILE* file) { + AbstractFile* toReturn; + + if(file == NULL) { + return NULL; + } + + toReturn = (AbstractFile*) malloc(sizeof(AbstractFile)); + toReturn->data = file; + toReturn->read = freadWrapper; + toReturn->write = fwriteWrapper; + toReturn->seek = fseekWrapper; + toReturn->tell = ftellWrapper; + toReturn->getLength = fileGetLength; + toReturn->close = fcloseWrapper; + return toReturn; +} + +size_t dummyRead(AbstractFile* file, void* data, size_t len) { + return 0; +} + +size_t dummyWrite(AbstractFile* file, const void* data, size_t len) { + *((off_t*) (file->data)) += len; + return len; +} + +int dummySeek(AbstractFile* file, off_t offset) { + *((off_t*) (file->data)) = offset; + return 0; +} + +off_t dummyTell(AbstractFile* file) { + return *((off_t*) (file->data)); +} + +void dummyClose(AbstractFile* file) { + free(file); +} + +AbstractFile* createAbstractFileFromDummy() { + AbstractFile* toReturn; + toReturn = (AbstractFile*) malloc(sizeof(AbstractFile)); + toReturn->data = NULL; + toReturn->read = dummyRead; + toReturn->write = dummyWrite; + toReturn->seek = dummySeek; + toReturn->tell = dummyTell; + toReturn->getLength = NULL; + toReturn->close = dummyClose; + return toReturn; +} + +size_t memRead(AbstractFile* file, void* data, size_t len) { + MemWrapperInfo* info = (MemWrapperInfo*) (file->data); + memcpy(data, (void*)((uint8_t*)(*(info->buffer)) + (uint32_t)info->offset), len); + info->offset += (size_t)len; + return len; +} + +size_t memWrite(AbstractFile* file, const void* data, size_t len) { + MemWrapperInfo* info = (MemWrapperInfo*) (file->data); + + while((info->offset + (size_t)len) > info->bufferSize) { + info->bufferSize <<= 1; + *(info->buffer) = realloc(*(info->buffer), info->bufferSize); + } + + memcpy((void*)((uint8_t*)(*(info->buffer)) + (uint32_t)info->offset), data, len); + info->offset += (size_t)len; + return len; +} + +int memSeek(AbstractFile* file, off_t offset) { + MemWrapperInfo* info = (MemWrapperInfo*) (file->data); + info->offset = (size_t)offset; + return 0; +} + +off_t memTell(AbstractFile* file) { + MemWrapperInfo* info = (MemWrapperInfo*) (file->data); + return (off_t)info->offset; +} + +off_t memGetLength(AbstractFile* file) { + MemWrapperInfo* info = (MemWrapperInfo*) (file->data); + return info->bufferSize; +} + +void memClose(AbstractFile* file) { + free(file->data); + free(file); +} + +AbstractFile* createAbstractFileFromMemory(void** buffer, size_t size) { + MemWrapperInfo* info; + AbstractFile* toReturn; + toReturn = (AbstractFile*) malloc(sizeof(AbstractFile)); + + info = (MemWrapperInfo*) malloc(sizeof(MemWrapperInfo)); + info->offset = 0; + info->buffer = buffer; + info->bufferSize = size; + + toReturn->data = info; + toReturn->read = memRead; + toReturn->write = memWrite; + toReturn->seek = memSeek; + toReturn->tell = memTell; + toReturn->getLength = memGetLength; + toReturn->close = memClose; + return toReturn; +} + +void abstractFilePrint(AbstractFile* file, const char* format, ...) { + va_list args; + char buffer[1024]; + size_t length; + + buffer[0] = '\0'; + va_start(args, format); + length = vsprintf(buffer, format, args); + va_end(args); + ASSERT(file->write(file, buffer, length) == length, "fwrite"); +} + +int absFileRead(io_func* io, off_t location, size_t size, void *buffer) { + AbstractFile* file; + file = (AbstractFile*) io->data; + file->seek(file, location); + if(file->read(file, buffer, size) == size) { + return TRUE; + } else { + return FALSE; + } +} + +int absFileWrite(io_func* io, off_t location, size_t size, void *buffer) { + AbstractFile* file; + file = (AbstractFile*) io->data; + file->seek(file, location); + if(file->write(file, buffer, size) == size) { + return TRUE; + } else { + return FALSE; + } +} + +void closeAbsFile(io_func* io) { + AbstractFile* file; + file = (AbstractFile*) io->data; + file->close(file); + free(io); +} + + +io_func* IOFuncFromAbstractFile(AbstractFile* file) { + io_func* io; + + io = (io_func*) malloc(sizeof(io_func)); + io->data = file; + io->read = &absFileRead; + io->write = &absFileWrite; + io->close = &closeAbsFile; + + return io; +} + +size_t memFileRead(AbstractFile* file, void* data, size_t len) { + MemFileWrapperInfo* info = (MemFileWrapperInfo*) (file->data); + memcpy(data, (void*)((uint8_t*)(*(info->buffer)) + (uint32_t)info->offset), len); + info->offset += (size_t)len; + return len; +} + +size_t memFileWrite(AbstractFile* file, const void* data, size_t len) { + MemFileWrapperInfo* info = (MemFileWrapperInfo*) (file->data); + + while((info->offset + (size_t)len) > info->actualBufferSize) { + info->actualBufferSize <<= 1; + *(info->buffer) = realloc(*(info->buffer), info->actualBufferSize); + } + + if((info->offset + (size_t)len) > (*(info->bufferSize))) { + *(info->bufferSize) = info->offset + (size_t)len; + } + + memcpy((void*)((uint8_t*)(*(info->buffer)) + (uint32_t)info->offset), data, len); + info->offset += (size_t)len; + return len; +} + +int memFileSeek(AbstractFile* file, off_t offset) { + MemFileWrapperInfo* info = (MemFileWrapperInfo*) (file->data); + info->offset = (size_t)offset; + return 0; +} + +off_t memFileTell(AbstractFile* file) { + MemFileWrapperInfo* info = (MemFileWrapperInfo*) (file->data); + return (off_t)info->offset; +} + +off_t memFileGetLength(AbstractFile* file) { + MemFileWrapperInfo* info = (MemFileWrapperInfo*) (file->data); + return *(info->bufferSize); +} + +void memFileClose(AbstractFile* file) { + free(file->data); + free(file); +} + +AbstractFile* createAbstractFileFromMemoryFile(void** buffer, size_t* size) { + MemFileWrapperInfo* info; + AbstractFile* toReturn; + toReturn = (AbstractFile*) malloc(sizeof(AbstractFile)); + + info = (MemFileWrapperInfo*) malloc(sizeof(MemFileWrapperInfo)); + info->offset = 0; + info->buffer = buffer; + info->bufferSize = size; info->actualBufferSize = (1024 < (*size)) ? (*size) : 1024; - if(info->actualBufferSize != *(info->bufferSize)) { + if(info->actualBufferSize != *(info->bufferSize)) { *(info->buffer) = realloc(*(info->buffer), info->actualBufferSize); - } - - toReturn->data = info; - toReturn->read = memFileRead; - toReturn->write = memFileWrite; - toReturn->seek = memFileSeek; - toReturn->tell = memFileTell; - toReturn->getLength = memFileGetLength; - toReturn->close = memFileClose; - return toReturn; -} - -AbstractFile* createAbstractFileFromMemoryFileBuffer(void** buffer, size_t* size, size_t actualBufferSize) { - MemFileWrapperInfo* info; - AbstractFile* toReturn; - toReturn = (AbstractFile*) malloc(sizeof(AbstractFile)); - - info = (MemFileWrapperInfo*) malloc(sizeof(MemFileWrapperInfo)); - info->offset = 0; - info->buffer = buffer; - info->bufferSize = size; - info->actualBufferSize = actualBufferSize; - - toReturn->data = info; - toReturn->read = memFileRead; - toReturn->write = memFileWrite; - toReturn->seek = memFileSeek; - toReturn->tell = memFileTell; - toReturn->getLength = memFileGetLength; - toReturn->close = memFileClose; - return toReturn; -} - + } + + toReturn->data = info; + toReturn->read = memFileRead; + toReturn->write = memFileWrite; + toReturn->seek = memFileSeek; + toReturn->tell = memFileTell; + toReturn->getLength = memFileGetLength; + toReturn->close = memFileClose; + return toReturn; +} + +AbstractFile* createAbstractFileFromMemoryFileBuffer(void** buffer, size_t* size, size_t actualBufferSize) { + MemFileWrapperInfo* info; + AbstractFile* toReturn; + toReturn = (AbstractFile*) malloc(sizeof(AbstractFile)); + + info = (MemFileWrapperInfo*) malloc(sizeof(MemFileWrapperInfo)); + info->offset = 0; + info->buffer = buffer; + info->bufferSize = size; + info->actualBufferSize = actualBufferSize; + + toReturn->data = info; + toReturn->read = memFileRead; + toReturn->write = memFileWrite; + toReturn->seek = memFileSeek; + toReturn->tell = memFileTell; + toReturn->getLength = memFileGetLength; + toReturn->close = memFileClose; + return toReturn; +} + diff --git a/hfs/abstractfile.h b/hfs/abstractfile.h index 9266265..af3b1fa 100644 --- a/hfs/abstractfile.h +++ b/hfs/abstractfile.h @@ -3,47 +3,47 @@ #include "common.h" -typedef struct AbstractFile AbstractFile; - -typedef size_t (*WriteFunc)(AbstractFile* file, const void* data, size_t len); -typedef size_t (*ReadFunc)(AbstractFile* file, void* data, size_t len); -typedef int (*SeekFunc)(AbstractFile* file, off_t offset); -typedef off_t (*TellFunc)(AbstractFile* file); -typedef void (*CloseFunc)(AbstractFile* file); -typedef off_t (*GetLengthFunc)(AbstractFile* file); - -struct AbstractFile { - void* data; - WriteFunc write; - ReadFunc read; - SeekFunc seek; - TellFunc tell; - GetLengthFunc getLength; - CloseFunc close; +typedef struct AbstractFile AbstractFile; + +typedef size_t (*WriteFunc)(AbstractFile* file, const void* data, size_t len); +typedef size_t (*ReadFunc)(AbstractFile* file, void* data, size_t len); +typedef int (*SeekFunc)(AbstractFile* file, off_t offset); +typedef off_t (*TellFunc)(AbstractFile* file); +typedef void (*CloseFunc)(AbstractFile* file); +typedef off_t (*GetLengthFunc)(AbstractFile* file); + +struct AbstractFile { + void* data; + WriteFunc write; + ReadFunc read; + SeekFunc seek; + TellFunc tell; + GetLengthFunc getLength; + CloseFunc close; }; -typedef struct { - size_t offset; - void** buffer; - size_t bufferSize; -} MemWrapperInfo; - -typedef struct { - size_t offset; - void** buffer; - size_t* bufferSize; - size_t actualBufferSize; -} MemFileWrapperInfo; +typedef struct { + size_t offset; + void** buffer; + size_t bufferSize; +} MemWrapperInfo; + +typedef struct { + size_t offset; + void** buffer; + size_t* bufferSize; + size_t actualBufferSize; +} MemFileWrapperInfo; #ifdef __cplusplus extern "C" { #endif - AbstractFile* createAbstractFileFromFile(FILE* file); - AbstractFile* createAbstractFileFromDummy(); - AbstractFile* createAbstractFileFromMemory(void** buffer, size_t size); - AbstractFile* createAbstractFileFromMemoryFile(void** buffer, size_t* size); - AbstractFile* createAbstractFileFromMemoryFileBuffer(void** buffer, size_t* size, size_t actualBufferSize); - void abstractFilePrint(AbstractFile* file, const char* format, ...); + AbstractFile* createAbstractFileFromFile(FILE* file); + AbstractFile* createAbstractFileFromDummy(); + AbstractFile* createAbstractFileFromMemory(void** buffer, size_t size); + AbstractFile* createAbstractFileFromMemoryFile(void** buffer, size_t* size); + AbstractFile* createAbstractFileFromMemoryFileBuffer(void** buffer, size_t* size, size_t actualBufferSize); + void abstractFilePrint(AbstractFile* file, const char* format, ...); io_func* IOFuncFromAbstractFile(AbstractFile* file); #ifdef __cplusplus } diff --git a/hfs/catalog.c b/hfs/catalog.c index 212b9c2..8f01ef2 100644 --- a/hfs/catalog.c +++ b/hfs/catalog.c @@ -1,444 +1,444 @@ -#include -#include -#include -#include "hfsplus.h" - -static inline void flipBSDInfo(HFSPlusBSDInfo* info) { - FLIPENDIAN(info->ownerID); - FLIPENDIAN(info->groupID); - FLIPENDIAN(info->fileMode); - FLIPENDIAN(info->special); -} - -static inline void flipPoint(Point* point) { - FLIPENDIAN(point->v); - FLIPENDIAN(point->h); -} - -static inline void flipRect(Rect* rect) { - FLIPENDIAN(rect->top); - FLIPENDIAN(rect->left); - FLIPENDIAN(rect->bottom); - FLIPENDIAN(rect->right); -} - -static inline void flipFolderInfo(FolderInfo* info) { - flipRect(&info->windowBounds); - FLIPENDIAN(info->finderFlags); - flipPoint(&info->location); -} - -static inline void flipExtendedFolderInfo(ExtendedFolderInfo* info) { - flipPoint(&info->scrollPosition); - FLIPENDIAN(info->extendedFinderFlags); - FLIPENDIAN(info->putAwayFolderID); -} - -static inline void flipFileInfo(FileInfo* info) { - FLIPENDIAN(info->fileType); - FLIPENDIAN(info->fileCreator); - FLIPENDIAN(info->finderFlags); - flipPoint(&info->location); -} - -static inline void flipExtendedFileInfo(ExtendedFileInfo* info) { - FLIPENDIAN(info->extendedFinderFlags); - FLIPENDIAN(info->putAwayFolderID); -} - -void flipCatalogFolder(HFSPlusCatalogFolder* record) { - FLIPENDIAN(record->recordType); - FLIPENDIAN(record->flags); - FLIPENDIAN(record->valence); - FLIPENDIAN(record->folderID); - FLIPENDIAN(record->createDate); - FLIPENDIAN(record->contentModDate); - FLIPENDIAN(record->attributeModDate); - FLIPENDIAN(record->accessDate); - FLIPENDIAN(record->backupDate); - - flipBSDInfo(&record->permissions); - flipFolderInfo(&record->userInfo); - flipExtendedFolderInfo(&record->finderInfo); - - FLIPENDIAN(record->textEncoding); - FLIPENDIAN(record->folderCount); -} - -void flipCatalogFile(HFSPlusCatalogFile* record) { - FLIPENDIAN(record->recordType); - FLIPENDIAN(record->flags); - FLIPENDIAN(record->fileID); - FLIPENDIAN(record->createDate); - FLIPENDIAN(record->contentModDate); - FLIPENDIAN(record->attributeModDate); - FLIPENDIAN(record->accessDate); - FLIPENDIAN(record->backupDate); - - flipBSDInfo(&record->permissions); - flipFileInfo(&record->userInfo); - flipExtendedFileInfo(&record->finderInfo); - - FLIPENDIAN(record->textEncoding); - - flipForkData(&record->dataFork); - flipForkData(&record->resourceFork); -} - -void flipCatalogThread(HFSPlusCatalogThread* record, int out) { - int i; - int nameLength; - - FLIPENDIAN(record->recordType); - FLIPENDIAN(record->parentID); - if(out) { - nameLength = record->nodeName.length; - FLIPENDIAN(record->nodeName.length); - } else { - FLIPENDIAN(record->nodeName.length); - nameLength = record->nodeName.length; - } - - for(i = 0; i < nameLength; i++) { - if(out) { - if(record->nodeName.unicode[i] == ':') { - record->nodeName.unicode[i] = '/'; - } - FLIPENDIAN(record->nodeName.unicode[i]); - } else { - FLIPENDIAN(record->nodeName.unicode[i]); - if(record->nodeName.unicode[i] == '/') { - record->nodeName.unicode[i] = ':'; - } - } - } -} - -#define UNICODE_START (sizeof(uint16_t) + sizeof(HFSCatalogNodeID) + sizeof(uint16_t)) - -static void catalogKeyPrint(BTKey* toPrint) { - HFSPlusCatalogKey* key; - - key = (HFSPlusCatalogKey*) toPrint; - - printf("%d:", key->parentID); - printUnicode(&key->nodeName); -} - -static int catalogCompare(BTKey* vLeft, BTKey* vRight) { - HFSPlusCatalogKey* left; - HFSPlusCatalogKey* right; - uint16_t i; - - uint16_t cLeft; - uint16_t cRight; - - left = (HFSPlusCatalogKey*) vLeft; - right =(HFSPlusCatalogKey*) vRight; - - if(left->parentID < right->parentID) { - return -1; - } else if(left->parentID > right->parentID) { - return 1; - } else { - for(i = 0; i < left->nodeName.length; i++) { - if(i >= right->nodeName.length) { - return 1; - } else { - /* ugly hack to support weird : to / conversion on iPhone */ - if(left->nodeName.unicode[i] == ':') { - cLeft = '/'; - } else { - cLeft = left->nodeName.unicode[i] ; - } - - if(right->nodeName.unicode[i] == ':') { - cRight = '/'; - } else { - cRight = right->nodeName.unicode[i]; - } - - if(cLeft < cRight) - return -1; - else if(cLeft > cRight) - return 1; - } - } - - if(i < right->nodeName.length) { - return -1; - } else { - /* do a safety check on key length. Otherwise, bad things may happen later on when we try to add or remove with this key */ - /*if(left->keyLength == right->keyLength) { - return 0; - } else if(left->keyLength < right->keyLength) { - return -1; - } else { - return 1; - }*/ - return 0; - } - } -} - -static int catalogCompareCS(BTKey* vLeft, BTKey* vRight) { - HFSPlusCatalogKey* left; - HFSPlusCatalogKey* right; - uint16_t i; - - uint16_t cLeft; - uint16_t cRight; - - left = (HFSPlusCatalogKey*) vLeft; - right =(HFSPlusCatalogKey*) vRight; - - if(left->parentID < right->parentID) { - return -1; - } else if(left->parentID > right->parentID) { - return 1; - } else { - return FastUnicodeCompare(left->nodeName.unicode, left->nodeName.length, right->nodeName.unicode, right->nodeName.length); - } -} - -static BTKey* catalogKeyRead(off_t offset, io_func* io) { - HFSPlusCatalogKey* key; - uint16_t i; - - key = (HFSPlusCatalogKey*) malloc(sizeof(HFSPlusCatalogKey)); - - if(!READ(io, offset, UNICODE_START, key)) - return NULL; - - FLIPENDIAN(key->keyLength); - FLIPENDIAN(key->parentID); - FLIPENDIAN(key->nodeName.length); - - if(!READ(io, offset + UNICODE_START, key->nodeName.length * sizeof(uint16_t), ((unsigned char *)key) + UNICODE_START)) - return NULL; - - for(i = 0; i < key->nodeName.length; i++) { - FLIPENDIAN(key->nodeName.unicode[i]); - if(key->nodeName.unicode[i] == '/') /* ugly hack that iPhone seems to do */ - key->nodeName.unicode[i] = ':'; - } - - return (BTKey*)key; -} - -static int catalogKeyWrite(off_t offset, BTKey* toWrite, io_func* io) { - HFSPlusCatalogKey* key; - uint16_t i; - uint16_t keyLength; - uint16_t nodeNameLength; - - keyLength = toWrite->keyLength + sizeof(uint16_t); - key = (HFSPlusCatalogKey*) malloc(keyLength); - memcpy(key, toWrite, keyLength); - - nodeNameLength = key->nodeName.length; - - FLIPENDIAN(key->keyLength); - FLIPENDIAN(key->parentID); - FLIPENDIAN(key->nodeName.length); - - for(i = 0; i < nodeNameLength; i++) { - if(key->nodeName.unicode[i] == ':') /* ugly hack that iPhone seems to do */ - key->nodeName.unicode[i] = '/'; - - FLIPENDIAN(key->nodeName.unicode[i]); - } - - if(!WRITE(io, offset, keyLength, key)) - return FALSE; - - free(key); - - return TRUE; -} - -static BTKey* catalogDataRead(off_t offset, io_func* io) { - int16_t recordType; - HFSPlusCatalogRecord* record; - uint16_t nameLength; - - if(!READ(io, offset, sizeof(int16_t), &recordType)) - return NULL; - - FLIPENDIAN(recordType); fflush(stdout); - - switch(recordType) { - case kHFSPlusFolderRecord: - record = (HFSPlusCatalogRecord*) malloc(sizeof(HFSPlusCatalogFolder)); - if(!READ(io, offset, sizeof(HFSPlusCatalogFolder), record)) - return NULL; - flipCatalogFolder((HFSPlusCatalogFolder*)record); - break; - - case kHFSPlusFileRecord: - record = (HFSPlusCatalogRecord*) malloc(sizeof(HFSPlusCatalogFile)); - if(!READ(io, offset, sizeof(HFSPlusCatalogFile), record)) - return NULL; - flipCatalogFile((HFSPlusCatalogFile*)record); - break; - - case kHFSPlusFolderThreadRecord: - case kHFSPlusFileThreadRecord: - record = (HFSPlusCatalogRecord*) malloc(sizeof(HFSPlusCatalogThread)); - - if(!READ(io, offset + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t), sizeof(uint16_t), &nameLength)) - return NULL; - - FLIPENDIAN(nameLength); - - if(!READ(io, offset, sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t) + (sizeof(uint16_t) * nameLength), record)) - return NULL; - - flipCatalogThread((HFSPlusCatalogThread*)record, FALSE); - break; - } - - return (BTKey*)record; -} - -void ASCIIToUnicode(const char* ascii, HFSUniStr255* unistr) { - int count; - - count = 0; - while(ascii[count] != '\0') { - unistr->unicode[count] = ascii[count]; - count++; - } - - unistr->length = count; -} - -HFSPlusCatalogRecord* getRecordByCNID(HFSCatalogNodeID CNID, Volume* volume) { - HFSPlusCatalogKey key; - HFSPlusCatalogThread* thread; - HFSPlusCatalogRecord* record; - int exact; - - key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); - key.parentID = CNID; - key.nodeName.length = 0; - - thread = (HFSPlusCatalogThread*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); - - if(thread == NULL) { - return NULL; - } - - if(exact == FALSE) { - free(thread); - return NULL; - } - - key.parentID = thread->parentID; - key.nodeName = thread->nodeName; - - free(thread); - - record = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); - - if(record == NULL || exact == FALSE) - return NULL; - else - return record; -} - -CatalogRecordList* getFolderContents(HFSCatalogNodeID CNID, Volume* volume) { - BTree* tree; - HFSPlusCatalogThread* record; - HFSPlusCatalogKey key; - uint32_t nodeNumber; - int recordNumber; - - BTNodeDescriptor* descriptor; - off_t recordOffset; - off_t recordDataOffset; - HFSPlusCatalogKey* currentKey; - - CatalogRecordList* list; - CatalogRecordList* lastItem; - CatalogRecordList* item; - - tree = volume->catalogTree; - - key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); - key.parentID = CNID; - key.nodeName.length = 0; - - list = NULL; - - record = (HFSPlusCatalogThread*) search(tree, (BTKey*)(&key), NULL, &nodeNumber, &recordNumber); - - if(record == NULL) - return NULL; - - free(record); - - ++recordNumber; - - while(nodeNumber != 0) { - descriptor = readBTNodeDescriptor(nodeNumber, tree); - - while(recordNumber < descriptor->numRecords) { - recordOffset = getRecordOffset(recordNumber, nodeNumber, tree); - currentKey = (HFSPlusCatalogKey*) READ_KEY(tree, recordOffset, tree->io); - recordDataOffset = recordOffset + currentKey->keyLength + sizeof(currentKey->keyLength); - - if(currentKey->parentID == CNID) { - item = (CatalogRecordList*) malloc(sizeof(CatalogRecordList)); - item->name = currentKey->nodeName; - item->record = (HFSPlusCatalogRecord*) READ_DATA(tree, recordDataOffset, tree->io); - item->next = NULL; - - if(list == NULL) { - list = item; - } else { - lastItem->next = item; - } - - lastItem = item; - free(currentKey); - } else { - free(currentKey); - free(descriptor); - return list; - } - - recordNumber++; - } - - nodeNumber = descriptor->fLink; - recordNumber = 0; - - free(descriptor); - } - - return list; -} - -void releaseCatalogRecordList(CatalogRecordList* list) { - CatalogRecordList* next; - while(list) { - next = list->next; - free(list->record); - free(list); - list = next; - } -} +#include +#include +#include +#include "hfsplus.h" + +static inline void flipBSDInfo(HFSPlusBSDInfo* info) { + FLIPENDIAN(info->ownerID); + FLIPENDIAN(info->groupID); + FLIPENDIAN(info->fileMode); + FLIPENDIAN(info->special); +} + +static inline void flipPoint(Point* point) { + FLIPENDIAN(point->v); + FLIPENDIAN(point->h); +} + +static inline void flipRect(Rect* rect) { + FLIPENDIAN(rect->top); + FLIPENDIAN(rect->left); + FLIPENDIAN(rect->bottom); + FLIPENDIAN(rect->right); +} + +static inline void flipFolderInfo(FolderInfo* info) { + flipRect(&info->windowBounds); + FLIPENDIAN(info->finderFlags); + flipPoint(&info->location); +} + +static inline void flipExtendedFolderInfo(ExtendedFolderInfo* info) { + flipPoint(&info->scrollPosition); + FLIPENDIAN(info->extendedFinderFlags); + FLIPENDIAN(info->putAwayFolderID); +} + +static inline void flipFileInfo(FileInfo* info) { + FLIPENDIAN(info->fileType); + FLIPENDIAN(info->fileCreator); + FLIPENDIAN(info->finderFlags); + flipPoint(&info->location); +} + +static inline void flipExtendedFileInfo(ExtendedFileInfo* info) { + FLIPENDIAN(info->extendedFinderFlags); + FLIPENDIAN(info->putAwayFolderID); +} + +void flipCatalogFolder(HFSPlusCatalogFolder* record) { + FLIPENDIAN(record->recordType); + FLIPENDIAN(record->flags); + FLIPENDIAN(record->valence); + FLIPENDIAN(record->folderID); + FLIPENDIAN(record->createDate); + FLIPENDIAN(record->contentModDate); + FLIPENDIAN(record->attributeModDate); + FLIPENDIAN(record->accessDate); + FLIPENDIAN(record->backupDate); + + flipBSDInfo(&record->permissions); + flipFolderInfo(&record->userInfo); + flipExtendedFolderInfo(&record->finderInfo); + + FLIPENDIAN(record->textEncoding); + FLIPENDIAN(record->folderCount); +} + +void flipCatalogFile(HFSPlusCatalogFile* record) { + FLIPENDIAN(record->recordType); + FLIPENDIAN(record->flags); + FLIPENDIAN(record->fileID); + FLIPENDIAN(record->createDate); + FLIPENDIAN(record->contentModDate); + FLIPENDIAN(record->attributeModDate); + FLIPENDIAN(record->accessDate); + FLIPENDIAN(record->backupDate); + + flipBSDInfo(&record->permissions); + flipFileInfo(&record->userInfo); + flipExtendedFileInfo(&record->finderInfo); + + FLIPENDIAN(record->textEncoding); + + flipForkData(&record->dataFork); + flipForkData(&record->resourceFork); +} + +void flipCatalogThread(HFSPlusCatalogThread* record, int out) { + int i; + int nameLength; + + FLIPENDIAN(record->recordType); + FLIPENDIAN(record->parentID); + if(out) { + nameLength = record->nodeName.length; + FLIPENDIAN(record->nodeName.length); + } else { + FLIPENDIAN(record->nodeName.length); + nameLength = record->nodeName.length; + } + + for(i = 0; i < nameLength; i++) { + if(out) { + if(record->nodeName.unicode[i] == ':') { + record->nodeName.unicode[i] = '/'; + } + FLIPENDIAN(record->nodeName.unicode[i]); + } else { + FLIPENDIAN(record->nodeName.unicode[i]); + if(record->nodeName.unicode[i] == '/') { + record->nodeName.unicode[i] = ':'; + } + } + } +} + +#define UNICODE_START (sizeof(uint16_t) + sizeof(HFSCatalogNodeID) + sizeof(uint16_t)) + +static void catalogKeyPrint(BTKey* toPrint) { + HFSPlusCatalogKey* key; + + key = (HFSPlusCatalogKey*) toPrint; + + printf("%d:", key->parentID); + printUnicode(&key->nodeName); +} + +static int catalogCompare(BTKey* vLeft, BTKey* vRight) { + HFSPlusCatalogKey* left; + HFSPlusCatalogKey* right; + uint16_t i; + + uint16_t cLeft; + uint16_t cRight; + + left = (HFSPlusCatalogKey*) vLeft; + right =(HFSPlusCatalogKey*) vRight; + + if(left->parentID < right->parentID) { + return -1; + } else if(left->parentID > right->parentID) { + return 1; + } else { + for(i = 0; i < left->nodeName.length; i++) { + if(i >= right->nodeName.length) { + return 1; + } else { + /* ugly hack to support weird : to / conversion on iPhone */ + if(left->nodeName.unicode[i] == ':') { + cLeft = '/'; + } else { + cLeft = left->nodeName.unicode[i] ; + } + + if(right->nodeName.unicode[i] == ':') { + cRight = '/'; + } else { + cRight = right->nodeName.unicode[i]; + } + + if(cLeft < cRight) + return -1; + else if(cLeft > cRight) + return 1; + } + } + + if(i < right->nodeName.length) { + return -1; + } else { + /* do a safety check on key length. Otherwise, bad things may happen later on when we try to add or remove with this key */ + /*if(left->keyLength == right->keyLength) { + return 0; + } else if(left->keyLength < right->keyLength) { + return -1; + } else { + return 1; + }*/ + return 0; + } + } +} + +static int catalogCompareCS(BTKey* vLeft, BTKey* vRight) { + HFSPlusCatalogKey* left; + HFSPlusCatalogKey* right; + uint16_t i; + + uint16_t cLeft; + uint16_t cRight; + + left = (HFSPlusCatalogKey*) vLeft; + right =(HFSPlusCatalogKey*) vRight; + + if(left->parentID < right->parentID) { + return -1; + } else if(left->parentID > right->parentID) { + return 1; + } else { + return FastUnicodeCompare(left->nodeName.unicode, left->nodeName.length, right->nodeName.unicode, right->nodeName.length); + } +} + +static BTKey* catalogKeyRead(off_t offset, io_func* io) { + HFSPlusCatalogKey* key; + uint16_t i; + + key = (HFSPlusCatalogKey*) malloc(sizeof(HFSPlusCatalogKey)); + + if(!READ(io, offset, UNICODE_START, key)) + return NULL; + + FLIPENDIAN(key->keyLength); + FLIPENDIAN(key->parentID); + FLIPENDIAN(key->nodeName.length); + + if(!READ(io, offset + UNICODE_START, key->nodeName.length * sizeof(uint16_t), ((unsigned char *)key) + UNICODE_START)) + return NULL; + + for(i = 0; i < key->nodeName.length; i++) { + FLIPENDIAN(key->nodeName.unicode[i]); + if(key->nodeName.unicode[i] == '/') /* ugly hack that iPhone seems to do */ + key->nodeName.unicode[i] = ':'; + } + + return (BTKey*)key; +} + +static int catalogKeyWrite(off_t offset, BTKey* toWrite, io_func* io) { + HFSPlusCatalogKey* key; + uint16_t i; + uint16_t keyLength; + uint16_t nodeNameLength; + + keyLength = toWrite->keyLength + sizeof(uint16_t); + key = (HFSPlusCatalogKey*) malloc(keyLength); + memcpy(key, toWrite, keyLength); + + nodeNameLength = key->nodeName.length; + + FLIPENDIAN(key->keyLength); + FLIPENDIAN(key->parentID); + FLIPENDIAN(key->nodeName.length); + + for(i = 0; i < nodeNameLength; i++) { + if(key->nodeName.unicode[i] == ':') /* ugly hack that iPhone seems to do */ + key->nodeName.unicode[i] = '/'; + + FLIPENDIAN(key->nodeName.unicode[i]); + } + + if(!WRITE(io, offset, keyLength, key)) + return FALSE; + + free(key); + + return TRUE; +} + +static BTKey* catalogDataRead(off_t offset, io_func* io) { + int16_t recordType; + HFSPlusCatalogRecord* record; + uint16_t nameLength; + + if(!READ(io, offset, sizeof(int16_t), &recordType)) + return NULL; + + FLIPENDIAN(recordType); fflush(stdout); + + switch(recordType) { + case kHFSPlusFolderRecord: + record = (HFSPlusCatalogRecord*) malloc(sizeof(HFSPlusCatalogFolder)); + if(!READ(io, offset, sizeof(HFSPlusCatalogFolder), record)) + return NULL; + flipCatalogFolder((HFSPlusCatalogFolder*)record); + break; + + case kHFSPlusFileRecord: + record = (HFSPlusCatalogRecord*) malloc(sizeof(HFSPlusCatalogFile)); + if(!READ(io, offset, sizeof(HFSPlusCatalogFile), record)) + return NULL; + flipCatalogFile((HFSPlusCatalogFile*)record); + break; + + case kHFSPlusFolderThreadRecord: + case kHFSPlusFileThreadRecord: + record = (HFSPlusCatalogRecord*) malloc(sizeof(HFSPlusCatalogThread)); + + if(!READ(io, offset + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t), sizeof(uint16_t), &nameLength)) + return NULL; + + FLIPENDIAN(nameLength); + + if(!READ(io, offset, sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t) + (sizeof(uint16_t) * nameLength), record)) + return NULL; + + flipCatalogThread((HFSPlusCatalogThread*)record, FALSE); + break; + } + + return (BTKey*)record; +} + +void ASCIIToUnicode(const char* ascii, HFSUniStr255* unistr) { + int count; + + count = 0; + while(ascii[count] != '\0') { + unistr->unicode[count] = ascii[count]; + count++; + } + + unistr->length = count; +} + +HFSPlusCatalogRecord* getRecordByCNID(HFSCatalogNodeID CNID, Volume* volume) { + HFSPlusCatalogKey key; + HFSPlusCatalogThread* thread; + HFSPlusCatalogRecord* record; + int exact; + + key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); + key.parentID = CNID; + key.nodeName.length = 0; + + thread = (HFSPlusCatalogThread*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); + + if(thread == NULL) { + return NULL; + } + + if(exact == FALSE) { + free(thread); + return NULL; + } + + key.parentID = thread->parentID; + key.nodeName = thread->nodeName; + + free(thread); + + record = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); + + if(record == NULL || exact == FALSE) + return NULL; + else + return record; +} + +CatalogRecordList* getFolderContents(HFSCatalogNodeID CNID, Volume* volume) { + BTree* tree; + HFSPlusCatalogThread* record; + HFSPlusCatalogKey key; + uint32_t nodeNumber; + int recordNumber; + + BTNodeDescriptor* descriptor; + off_t recordOffset; + off_t recordDataOffset; + HFSPlusCatalogKey* currentKey; + + CatalogRecordList* list; + CatalogRecordList* lastItem; + CatalogRecordList* item; + + tree = volume->catalogTree; + + key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); + key.parentID = CNID; + key.nodeName.length = 0; + + list = NULL; + + record = (HFSPlusCatalogThread*) search(tree, (BTKey*)(&key), NULL, &nodeNumber, &recordNumber); + + if(record == NULL) + return NULL; + + free(record); + + ++recordNumber; + + while(nodeNumber != 0) { + descriptor = readBTNodeDescriptor(nodeNumber, tree); + + while(recordNumber < descriptor->numRecords) { + recordOffset = getRecordOffset(recordNumber, nodeNumber, tree); + currentKey = (HFSPlusCatalogKey*) READ_KEY(tree, recordOffset, tree->io); + recordDataOffset = recordOffset + currentKey->keyLength + sizeof(currentKey->keyLength); + + if(currentKey->parentID == CNID) { + item = (CatalogRecordList*) malloc(sizeof(CatalogRecordList)); + item->name = currentKey->nodeName; + item->record = (HFSPlusCatalogRecord*) READ_DATA(tree, recordDataOffset, tree->io); + item->next = NULL; + + if(list == NULL) { + list = item; + } else { + lastItem->next = item; + } + + lastItem = item; + free(currentKey); + } else { + free(currentKey); + free(descriptor); + return list; + } + + recordNumber++; + } + + nodeNumber = descriptor->fLink; + recordNumber = 0; + + free(descriptor); + } + + return list; +} + +void releaseCatalogRecordList(CatalogRecordList* list) { + CatalogRecordList* next; + while(list) { + next = list->next; + free(list->record); + free(list); + list = next; + } +} HFSPlusCatalogRecord* getLinkTarget(HFSPlusCatalogRecord* record, HFSCatalogNodeID parentID, HFSPlusCatalogKey *key, Volume* volume) { - io_func* io; + io_func* io; char pathBuffer[1024]; HFSPlusCatalogRecord* toReturn; - if(record->recordType == kHFSPlusFileRecord && (((HFSPlusCatalogFile*)record)->permissions.fileMode & S_IFLNK) == S_IFLNK) { - io = openRawFile(((HFSPlusCatalogFile*)record)->fileID, &(((HFSPlusCatalogFile*)record)->dataFork), record, volume); - READ(io, 0, (((HFSPlusCatalogFile*)record)->dataFork).logicalSize, pathBuffer); - CLOSE(io); + if(record->recordType == kHFSPlusFileRecord && (((HFSPlusCatalogFile*)record)->permissions.fileMode & S_IFLNK) == S_IFLNK) { + io = openRawFile(((HFSPlusCatalogFile*)record)->fileID, &(((HFSPlusCatalogFile*)record)->dataFork), record, volume); + READ(io, 0, (((HFSPlusCatalogFile*)record)->dataFork).logicalSize, pathBuffer); + CLOSE(io); pathBuffer[(((HFSPlusCatalogFile*)record)->dataFork).logicalSize] = '\0'; toReturn = getRecordFromPath3(pathBuffer, volume, NULL, key, TRUE, TRUE, parentID); free(record); @@ -455,355 +455,355 @@ HFSPlusCatalogRecord* getRecordFromPath(const char* path, Volume* volume, char * HFSPlusCatalogRecord* getRecordFromPath2(const char* path, Volume* volume, char **name, HFSPlusCatalogKey* retKey, char traverse) { return getRecordFromPath3(path, volume, name, retKey, TRUE, TRUE, kHFSRootFolderID); } - -HFSPlusCatalogRecord* getRecordFromPath3(const char* path, Volume* volume, char **name, HFSPlusCatalogKey* retKey, char traverse, char returnLink, HFSCatalogNodeID parentID) { - HFSPlusCatalogKey key; - HFSPlusCatalogRecord* record; - - char* origPath; - char* myPath; - char* word; - char* pathLimit; - - uint32_t realParent; - char* lastWordDetectSlash; - int exact; - - if(path[0] == '\0' || (path[0] == '/' && path[1] == '\0')) { - if(name != NULL) - *name = (char*)path; - - key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); - key.parentID = kHFSRootFolderID; - key.nodeName.length = 0; - - record = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); - key.parentID = ((HFSPlusCatalogThread*)record)->parentID; - key.nodeName = ((HFSPlusCatalogThread*)record)->nodeName; - - free(record); - - record = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); - return record; - } - - myPath = strdup(path); - origPath = myPath; - - record = NULL; - if(path[0] == '/') { +HFSPlusCatalogRecord* getRecordFromPath3(const char* path, Volume* volume, char **name, HFSPlusCatalogKey* retKey, char traverse, char returnLink, HFSCatalogNodeID parentID) { + HFSPlusCatalogKey key; + HFSPlusCatalogRecord* record; + + char* origPath; + char* myPath; + char* word; + char* pathLimit; + + uint32_t realParent; + char* lastWordDetectSlash; + int exact; + + if(path[0] == '\0' || (path[0] == '/' && path[1] == '\0')) { + if(name != NULL) + *name = (char*)path; + + key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); + key.parentID = kHFSRootFolderID; + key.nodeName.length = 0; + + record = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); + key.parentID = ((HFSPlusCatalogThread*)record)->parentID; + key.nodeName = ((HFSPlusCatalogThread*)record)->nodeName; + + free(record); + + record = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); + return record; + } + + myPath = strdup(path); + origPath = myPath; + + record = NULL; + + if(path[0] == '/') { key.parentID = kHFSRootFolderID; } else { key.parentID = parentID; } - - pathLimit = myPath + strlen(myPath); - - for(word = (char*)strtok(myPath, "/"); word && (word < pathLimit); + + pathLimit = myPath + strlen(myPath); + + for(word = (char*)strtok(myPath, "/"); word && (word < pathLimit); word = ((word + strlen(word) + 1) < pathLimit) ? (char*)strtok(word + strlen(word) + 1, "/") : NULL) { - if(name != NULL) - *name = (char*)(path + (word - origPath)); - - if(record != NULL) { - free(record); - record = NULL; - } - - if(word[0] == '\0') { - continue; - } - + if(name != NULL) + *name = (char*)(path + (word - origPath)); + + if(record != NULL) { + free(record); + record = NULL; + } + + if(word[0] == '\0') { + continue; + } + ASCIIToUnicode(word, &key.nodeName); - - key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length) + (sizeof(uint16_t) * key.nodeName.length); - record = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); - - if(record == NULL || exact == FALSE) { - free(origPath); - return NULL; + + key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length) + (sizeof(uint16_t) * key.nodeName.length); + record = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); + + if(record == NULL || exact == FALSE) { + free(origPath); + return NULL; } if(traverse) { lastWordDetectSlash = strchr(word, '/'); if((lastWordDetectSlash && *(lastWordDetectSlash + 1) != '\0') || returnLink) { record = getLinkTarget(record, key.parentID, &key, volume); - if(record == NULL || exact == FALSE) { - free(origPath); - return NULL; + if(record == NULL || exact == FALSE) { + free(origPath); + return NULL; } } } - - if(record->recordType == kHFSPlusFileRecord) { - free(origPath); - - if(retKey != NULL) { - memcpy(retKey, &key, sizeof(HFSPlusCatalogKey)); - } - - return record; - } - - if(record->recordType != kHFSPlusFolderRecord) - panic("inconsistent catalog tree!"); - - realParent = key.parentID; - key.parentID = ((HFSPlusCatalogFolder*)record)->folderID; - } - - if(retKey != NULL) { - memcpy(retKey, &key, sizeof(HFSPlusCatalogKey)); - retKey->parentID = realParent; - } - - free(origPath); - return record; -} - -int updateCatalog(Volume* volume, HFSPlusCatalogRecord* catalogRecord) { - HFSPlusCatalogKey key; - HFSPlusCatalogRecord* record; - HFSPlusCatalogFile file; - HFSPlusCatalogFolder folder; - int exact; - - key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); - if(catalogRecord->recordType == kHFSPlusFolderRecord) { - key.parentID = ((HFSPlusCatalogFolder*)catalogRecord)->folderID; - } else if(catalogRecord->recordType == kHFSPlusFileRecord) { - key.parentID = ((HFSPlusCatalogFile*)catalogRecord)->fileID; - } else { - /* unexpected */ - return FALSE; - } - key.nodeName.length = 0; - - record = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); - - key.parentID = ((HFSPlusCatalogThread*)record)->parentID; - key.nodeName = ((HFSPlusCatalogThread*)record)->nodeName; - key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length) + (sizeof(uint16_t) * key.nodeName.length); - - free(record); - - record = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); - - removeFromBTree(volume->catalogTree, (BTKey*)(&key)); - - switch(record->recordType) { - case kHFSPlusFolderRecord: - memcpy(&folder, catalogRecord, sizeof(HFSPlusCatalogFolder)); - flipCatalogFolder(&folder); - free(record); - return addToBTree(volume->catalogTree, (BTKey*)(&key), sizeof(HFSPlusCatalogFolder), (unsigned char *)(&folder)); - break; - - case kHFSPlusFileRecord: - memcpy(&file, catalogRecord, sizeof(HFSPlusCatalogFile)); - flipCatalogFile(&file); - free(record); - return addToBTree(volume->catalogTree, (BTKey*)(&key), sizeof(HFSPlusCatalogFile), (unsigned char *)(&file)); - break; - } - - return TRUE; -} - -int move(const char* source, const char* dest, Volume* volume) { - HFSPlusCatalogRecord* srcRec; - HFSPlusCatalogFolder* srcFolderRec; - HFSPlusCatalogFolder* destRec; - char* destPath; - char* destName; - char* curChar; - char* lastSeparator; - - int i; - int threadLength; - - HFSPlusCatalogKey srcKey; - HFSPlusCatalogKey destKey; - HFSPlusCatalogThread* thread; - - srcRec = getRecordFromPath3(source, volume, NULL, &srcKey, TRUE, FALSE, kHFSRootFolderID); - if(srcRec == NULL) { - free(srcRec); - return FALSE; - } - - srcFolderRec = (HFSPlusCatalogFolder*) getRecordByCNID(srcKey.parentID, volume); - - if(srcFolderRec == NULL || srcFolderRec->recordType != kHFSPlusFolderRecord) { - free(srcRec); - free(srcFolderRec); - return FALSE; - } - - destPath = strdup(dest); - - curChar = destPath; - lastSeparator = NULL; - - while((*curChar) != '\0') { - if((*curChar) == '/') - lastSeparator = curChar; - curChar++; - } - - if(lastSeparator == NULL) { - destRec = (HFSPlusCatalogFolder*) getRecordFromPath("/", volume, NULL, NULL); - destName = destPath; - } else { - destName = lastSeparator + 1; - *lastSeparator = '\0'; - destRec = (HFSPlusCatalogFolder*) getRecordFromPath(destPath, volume, NULL, NULL); - - if(destRec == NULL || destRec->recordType != kHFSPlusFolderRecord) { - free(destPath); - free(srcRec); - free(destRec); - free(srcFolderRec); - return FALSE; - } - } - - removeFromBTree(volume->catalogTree, (BTKey*)(&srcKey)); - - srcKey.nodeName.length = 0; - if(srcRec->recordType == kHFSPlusFolderRecord) { - srcKey.parentID = ((HFSPlusCatalogFolder*)srcRec)->folderID; - } else if(srcRec->recordType == kHFSPlusFileRecord) { - srcKey.parentID = ((HFSPlusCatalogFile*)srcRec)->fileID; - } else { - /* unexpected */ - return FALSE; - } - srcKey.keyLength = sizeof(srcKey.parentID) + sizeof(srcKey.nodeName.length); - - removeFromBTree(volume->catalogTree, (BTKey*)(&srcKey)); - - - destKey.nodeName.length = strlen(destName); - - threadLength = sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t) + (sizeof(uint16_t) * destKey.nodeName.length); - thread = (HFSPlusCatalogThread*) malloc(threadLength); - thread->reserved = 0; - destKey.parentID = destRec->folderID; - thread->parentID = destKey.parentID; - thread->nodeName.length = destKey.nodeName.length; - for(i = 0; i < destKey.nodeName.length; i++) { - destKey.nodeName.unicode[i] = destName[i]; - thread->nodeName.unicode[i] = destName[i]; - } - - destKey.keyLength = sizeof(uint32_t) + sizeof(uint16_t) + (sizeof(uint16_t) * destKey.nodeName.length); - - switch(srcRec->recordType) { - case kHFSPlusFolderRecord: - thread->recordType = kHFSPlusFolderThreadRecord; - flipCatalogFolder((HFSPlusCatalogFolder*)srcRec); - addToBTree(volume->catalogTree, (BTKey*)(&destKey), sizeof(HFSPlusCatalogFolder), (unsigned char *)(srcRec)); - break; - - case kHFSPlusFileRecord: - thread->recordType = kHFSPlusFileThreadRecord; - flipCatalogFile((HFSPlusCatalogFile*)srcRec); - addToBTree(volume->catalogTree, (BTKey*)(&destKey), sizeof(HFSPlusCatalogFile), (unsigned char *)(srcRec)); - break; - } - - destKey.nodeName.length = 0; - destKey.parentID = srcKey.parentID; - destKey.keyLength = sizeof(destKey.parentID) + sizeof(destKey.nodeName.length); - - flipCatalogThread(thread, TRUE); - addToBTree(volume->catalogTree, (BTKey*)(&destKey), threadLength, (unsigned char *)(thread)); - - /* adjust valence */ - srcFolderRec->valence--; - updateCatalog(volume, (HFSPlusCatalogRecord*) srcFolderRec); - destRec->valence++; - updateCatalog(volume, (HFSPlusCatalogRecord*) destRec); - - free(thread); - free(destPath); - free(srcRec); - free(destRec); - free(srcFolderRec); - - return TRUE; -} - -int removeFile(const char* fileName, Volume* volume) { - HFSPlusCatalogRecord* record; - HFSPlusCatalogRecord* parentRecord; + + if(record->recordType == kHFSPlusFileRecord) { + free(origPath); + + if(retKey != NULL) { + memcpy(retKey, &key, sizeof(HFSPlusCatalogKey)); + } + + return record; + } + + if(record->recordType != kHFSPlusFolderRecord) + panic("inconsistent catalog tree!"); + + realParent = key.parentID; + key.parentID = ((HFSPlusCatalogFolder*)record)->folderID; + } + + if(retKey != NULL) { + memcpy(retKey, &key, sizeof(HFSPlusCatalogKey)); + retKey->parentID = realParent; + } + + free(origPath); + return record; +} + +int updateCatalog(Volume* volume, HFSPlusCatalogRecord* catalogRecord) { HFSPlusCatalogKey key; - HFSPlusCatalogKey parentKey; - io_func* io; + HFSPlusCatalogRecord* record; + HFSPlusCatalogFile file; + HFSPlusCatalogFolder folder; + int exact; + + key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); + if(catalogRecord->recordType == kHFSPlusFolderRecord) { + key.parentID = ((HFSPlusCatalogFolder*)catalogRecord)->folderID; + } else if(catalogRecord->recordType == kHFSPlusFileRecord) { + key.parentID = ((HFSPlusCatalogFile*)catalogRecord)->fileID; + } else { + /* unexpected */ + return FALSE; + } + key.nodeName.length = 0; + + record = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); + + key.parentID = ((HFSPlusCatalogThread*)record)->parentID; + key.nodeName = ((HFSPlusCatalogThread*)record)->nodeName; + key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length) + (sizeof(uint16_t) * key.nodeName.length); + + free(record); + + record = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&key), &exact, NULL, NULL); + + removeFromBTree(volume->catalogTree, (BTKey*)(&key)); + + switch(record->recordType) { + case kHFSPlusFolderRecord: + memcpy(&folder, catalogRecord, sizeof(HFSPlusCatalogFolder)); + flipCatalogFolder(&folder); + free(record); + return addToBTree(volume->catalogTree, (BTKey*)(&key), sizeof(HFSPlusCatalogFolder), (unsigned char *)(&folder)); + break; + + case kHFSPlusFileRecord: + memcpy(&file, catalogRecord, sizeof(HFSPlusCatalogFile)); + flipCatalogFile(&file); + free(record); + return addToBTree(volume->catalogTree, (BTKey*)(&key), sizeof(HFSPlusCatalogFile), (unsigned char *)(&file)); + break; + } + + return TRUE; +} + +int move(const char* source, const char* dest, Volume* volume) { + HFSPlusCatalogRecord* srcRec; + HFSPlusCatalogFolder* srcFolderRec; + HFSPlusCatalogFolder* destRec; + char* destPath; + char* destName; + char* curChar; + char* lastSeparator; + + int i; + int threadLength; + + HFSPlusCatalogKey srcKey; + HFSPlusCatalogKey destKey; + HFSPlusCatalogThread* thread; + + srcRec = getRecordFromPath3(source, volume, NULL, &srcKey, TRUE, FALSE, kHFSRootFolderID); + if(srcRec == NULL) { + free(srcRec); + return FALSE; + } + + srcFolderRec = (HFSPlusCatalogFolder*) getRecordByCNID(srcKey.parentID, volume); + + if(srcFolderRec == NULL || srcFolderRec->recordType != kHFSPlusFolderRecord) { + free(srcRec); + free(srcFolderRec); + return FALSE; + } + + destPath = strdup(dest); + + curChar = destPath; + lastSeparator = NULL; + + while((*curChar) != '\0') { + if((*curChar) == '/') + lastSeparator = curChar; + curChar++; + } + + if(lastSeparator == NULL) { + destRec = (HFSPlusCatalogFolder*) getRecordFromPath("/", volume, NULL, NULL); + destName = destPath; + } else { + destName = lastSeparator + 1; + *lastSeparator = '\0'; + destRec = (HFSPlusCatalogFolder*) getRecordFromPath(destPath, volume, NULL, NULL); + + if(destRec == NULL || destRec->recordType != kHFSPlusFolderRecord) { + free(destPath); + free(srcRec); + free(destRec); + free(srcFolderRec); + return FALSE; + } + } + + removeFromBTree(volume->catalogTree, (BTKey*)(&srcKey)); + + srcKey.nodeName.length = 0; + if(srcRec->recordType == kHFSPlusFolderRecord) { + srcKey.parentID = ((HFSPlusCatalogFolder*)srcRec)->folderID; + } else if(srcRec->recordType == kHFSPlusFileRecord) { + srcKey.parentID = ((HFSPlusCatalogFile*)srcRec)->fileID; + } else { + /* unexpected */ + return FALSE; + } + srcKey.keyLength = sizeof(srcKey.parentID) + sizeof(srcKey.nodeName.length); + + removeFromBTree(volume->catalogTree, (BTKey*)(&srcKey)); + + + destKey.nodeName.length = strlen(destName); + + threadLength = sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t) + (sizeof(uint16_t) * destKey.nodeName.length); + thread = (HFSPlusCatalogThread*) malloc(threadLength); + thread->reserved = 0; + destKey.parentID = destRec->folderID; + thread->parentID = destKey.parentID; + thread->nodeName.length = destKey.nodeName.length; + for(i = 0; i < destKey.nodeName.length; i++) { + destKey.nodeName.unicode[i] = destName[i]; + thread->nodeName.unicode[i] = destName[i]; + } + + destKey.keyLength = sizeof(uint32_t) + sizeof(uint16_t) + (sizeof(uint16_t) * destKey.nodeName.length); + + switch(srcRec->recordType) { + case kHFSPlusFolderRecord: + thread->recordType = kHFSPlusFolderThreadRecord; + flipCatalogFolder((HFSPlusCatalogFolder*)srcRec); + addToBTree(volume->catalogTree, (BTKey*)(&destKey), sizeof(HFSPlusCatalogFolder), (unsigned char *)(srcRec)); + break; + + case kHFSPlusFileRecord: + thread->recordType = kHFSPlusFileThreadRecord; + flipCatalogFile((HFSPlusCatalogFile*)srcRec); + addToBTree(volume->catalogTree, (BTKey*)(&destKey), sizeof(HFSPlusCatalogFile), (unsigned char *)(srcRec)); + break; + } + + destKey.nodeName.length = 0; + destKey.parentID = srcKey.parentID; + destKey.keyLength = sizeof(destKey.parentID) + sizeof(destKey.nodeName.length); + + flipCatalogThread(thread, TRUE); + addToBTree(volume->catalogTree, (BTKey*)(&destKey), threadLength, (unsigned char *)(thread)); + + /* adjust valence */ + srcFolderRec->valence--; + updateCatalog(volume, (HFSPlusCatalogRecord*) srcFolderRec); + destRec->valence++; + updateCatalog(volume, (HFSPlusCatalogRecord*) destRec); + + free(thread); + free(destPath); + free(srcRec); + free(destRec); + free(srcFolderRec); + + return TRUE; +} + +int removeFile(const char* fileName, Volume* volume) { + HFSPlusCatalogRecord* record; + HFSPlusCatalogRecord* parentRecord; + HFSPlusCatalogKey key; + HFSPlusCatalogKey parentKey; + io_func* io; HFSPlusCatalogFolder* parentFolder; - int exact; + int exact; record = getRecordFromPath3(fileName, volume, NULL, &key, TRUE, FALSE, kHFSRootFolderID); if(record != NULL) { - parentFolder = (HFSPlusCatalogFolder*) getRecordByCNID(key.parentID, volume); - if(parentFolder != NULL) { - if(parentFolder->recordType != kHFSPlusFolderRecord) { - ASSERT(FALSE, "parent not folder"); - free(parentFolder); - return FALSE; - } - } else { - ASSERT(FALSE, "can't find parent"); - return FALSE; - } - - if(record->recordType == kHFSPlusFileRecord) { - io = openRawFile(((HFSPlusCatalogFile*)record)->fileID, &((HFSPlusCatalogFile*)record)->dataFork, record, volume); - allocate((RawFile*)io->data, 0); - CLOSE(io); - - removeFromBTree(volume->catalogTree, (BTKey*)(&key)); - - key.nodeName.length = 0; - key.parentID = ((HFSPlusCatalogFile*)record)->fileID; - key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); - removeFromBTree(volume->catalogTree, (BTKey*)(&key)); - - volume->volumeHeader->fileCount--; - } else { - if(((HFSPlusCatalogFolder*)record)->valence > 0) { - free(record); - free(parentFolder); - ASSERT(FALSE, "folder not empty"); - return FALSE; - } else { - removeFromBTree(volume->catalogTree, (BTKey*)(&key)); - - key.nodeName.length = 0; - key.parentID = ((HFSPlusCatalogFolder*)record)->folderID; - key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); - removeFromBTree(volume->catalogTree, (BTKey*)(&key)); - } - - parentFolder->folderCount--; - volume->volumeHeader->folderCount--; - } - parentFolder->valence--; - updateCatalog(volume, (HFSPlusCatalogRecord*) parentFolder); - updateVolume(volume); - - free(record); - free(parentFolder); - - return TRUE; - } else { - free(parentFolder); - ASSERT(FALSE, "cannot find record"); - return FALSE; - } -} + parentFolder = (HFSPlusCatalogFolder*) getRecordByCNID(key.parentID, volume); + if(parentFolder != NULL) { + if(parentFolder->recordType != kHFSPlusFolderRecord) { + ASSERT(FALSE, "parent not folder"); + free(parentFolder); + return FALSE; + } + } else { + ASSERT(FALSE, "can't find parent"); + return FALSE; + } + + if(record->recordType == kHFSPlusFileRecord) { + io = openRawFile(((HFSPlusCatalogFile*)record)->fileID, &((HFSPlusCatalogFile*)record)->dataFork, record, volume); + allocate((RawFile*)io->data, 0); + CLOSE(io); + + removeFromBTree(volume->catalogTree, (BTKey*)(&key)); + + key.nodeName.length = 0; + key.parentID = ((HFSPlusCatalogFile*)record)->fileID; + key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); + removeFromBTree(volume->catalogTree, (BTKey*)(&key)); + + volume->volumeHeader->fileCount--; + } else { + if(((HFSPlusCatalogFolder*)record)->valence > 0) { + free(record); + free(parentFolder); + ASSERT(FALSE, "folder not empty"); + return FALSE; + } else { + removeFromBTree(volume->catalogTree, (BTKey*)(&key)); + + key.nodeName.length = 0; + key.parentID = ((HFSPlusCatalogFolder*)record)->folderID; + key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); + removeFromBTree(volume->catalogTree, (BTKey*)(&key)); + } + + parentFolder->folderCount--; + volume->volumeHeader->folderCount--; + } + parentFolder->valence--; + updateCatalog(volume, (HFSPlusCatalogRecord*) parentFolder); + updateVolume(volume); + + free(record); + free(parentFolder); + + return TRUE; + } else { + free(parentFolder); + ASSERT(FALSE, "cannot find record"); + return FALSE; + } +} int makeSymlink(const char* pathName, const char* target, Volume* volume) { io_func* io; @@ -828,262 +828,262 @@ int makeSymlink(const char* pathName, const char* target, Volume* volume) { } } - io = openRawFile(record->fileID, &record->dataFork, (HFSPlusCatalogRecord*) record, volume); - WRITE(io, 0, strlen(target), (void*) target); + io = openRawFile(record->fileID, &record->dataFork, (HFSPlusCatalogRecord*) record, volume); + WRITE(io, 0, strlen(target), (void*) target); CLOSE(io); return TRUE; } - -HFSCatalogNodeID newFolder(const char* pathName, Volume* volume) { - HFSPlusCatalogFolder* parentFolder; - HFSPlusCatalogFolder folder; - HFSPlusCatalogKey key; - HFSPlusCatalogThread thread; - - uint32_t newFolderID; - - int threadLength; - - char* path; - char* name; - char* curChar; - char* lastSeparator; - - path = strdup(pathName); - - curChar = path; - lastSeparator = NULL; - - while((*curChar) != '\0') { - if((*curChar) == '/') - lastSeparator = curChar; - curChar++; - } - - if(lastSeparator == NULL) { - parentFolder = (HFSPlusCatalogFolder*) getRecordFromPath("/", volume, NULL, NULL); - name = path; - } else { - name = lastSeparator + 1; - *lastSeparator = '\0'; - parentFolder = (HFSPlusCatalogFolder*) getRecordFromPath(path, volume, NULL, NULL); - - if(parentFolder == NULL || parentFolder->recordType != kHFSPlusFolderRecord) { - free(path); - free(parentFolder); - return FALSE; - } - } - - newFolderID = volume->volumeHeader->nextCatalogID++; - volume->volumeHeader->folderCount++; - - folder.recordType = kHFSPlusFolderRecord; - folder.flags = kHFSHasFolderCountMask; - folder.valence = 0; - folder.folderID = newFolderID; - folder.createDate = UNIX_TO_APPLE_TIME(time(NULL)); - folder.contentModDate = folder.createDate; - folder.attributeModDate = folder.createDate; - folder.accessDate = folder.createDate; - folder.backupDate = folder.createDate; - folder.permissions.ownerID = parentFolder->permissions.ownerID; - folder.permissions.groupID = parentFolder->permissions.groupID; - folder.permissions.adminFlags = 0; - folder.permissions.ownerFlags = 0; - folder.permissions.fileMode = S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; - folder.permissions.special.iNodeNum = 0; - memset(&folder.userInfo, 0, sizeof(folder.userInfo)); - memset(&folder.finderInfo, 0, sizeof(folder.finderInfo)); - folder.textEncoding = 0; - folder.folderCount = 0; - - key.parentID = parentFolder->folderID; - ASCIIToUnicode(name, &key.nodeName); - key.keyLength = sizeof(key.parentID) + STR_SIZE(key.nodeName); - - thread.recordType = kHFSPlusFolderThreadRecord; - thread.reserved = 0; - thread.parentID = parentFolder->folderID; - ASCIIToUnicode(name, &thread.nodeName); - threadLength = sizeof(thread.recordType) + sizeof(thread.reserved) + sizeof(thread.parentID) + STR_SIZE(thread.nodeName); - flipCatalogThread(&thread, TRUE); - flipCatalogFolder(&folder); - - ASSERT(addToBTree(volume->catalogTree, (BTKey*)(&key), sizeof(HFSPlusCatalogFolder), (unsigned char *)(&folder)), "addToBTree"); - key.nodeName.length = 0; - key.parentID = newFolderID; - key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); - ASSERT(addToBTree(volume->catalogTree, (BTKey*)(&key), threadLength, (unsigned char *)(&thread)), "addToBTree"); - - parentFolder->folderCount++; - parentFolder->valence++; - updateCatalog(volume, (HFSPlusCatalogRecord*) parentFolder); - - updateVolume(volume); - - free(parentFolder); - free(path); - - return newFolderID; -} - -HFSCatalogNodeID newFile(const char* pathName, Volume* volume) { - HFSPlusCatalogFolder* parentFolder; - HFSPlusCatalogFile file; - HFSPlusCatalogKey key; - HFSPlusCatalogThread thread; - - uint32_t newFileID; - - int threadLength; - - char* path; - char* name; - char* curChar; - char* lastSeparator; - - path = strdup(pathName); - - curChar = path; - lastSeparator = NULL; - - while((*curChar) != '\0') { - if((*curChar) == '/') - lastSeparator = curChar; - curChar++; - } - - if(lastSeparator == NULL) { - parentFolder = (HFSPlusCatalogFolder*) getRecordFromPath("/", volume, NULL, NULL); - name = path; - } else { - name = lastSeparator + 1; - *lastSeparator = '\0'; - parentFolder = (HFSPlusCatalogFolder*) getRecordFromPath(path, volume, NULL, NULL); - - if(parentFolder == NULL || parentFolder->recordType != kHFSPlusFolderRecord) { - free(path); - free(parentFolder); - return FALSE; - } - } - - newFileID = volume->volumeHeader->nextCatalogID++; - volume->volumeHeader->fileCount++; - - file.recordType = kHFSPlusFileRecord; - file.flags = kHFSThreadExistsMask; - file.reserved1 = 0; - file.fileID = newFileID; - file.createDate = UNIX_TO_APPLE_TIME(time(NULL)); - file.contentModDate = file.createDate; - file.attributeModDate = file.createDate; - file.accessDate = file.createDate; - file.backupDate = file.createDate; - file.permissions.ownerID = parentFolder->permissions.ownerID; - file.permissions.groupID = parentFolder->permissions.groupID; - file.permissions.adminFlags = 0; - file.permissions.ownerFlags = 0; - file.permissions.fileMode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - file.permissions.special.iNodeNum = 0; - memset(&file.userInfo, 0, sizeof(file.userInfo)); - memset(&file.finderInfo, 0, sizeof(file.finderInfo)); - file.textEncoding = 0; - file.reserved2 = 0; - memset(&file.dataFork, 0, sizeof(file.dataFork)); - memset(&file.resourceFork, 0, sizeof(file.resourceFork)); - - key.parentID = parentFolder->folderID; - ASCIIToUnicode(name, &key.nodeName); - key.keyLength = sizeof(key.parentID) + STR_SIZE(key.nodeName); - - thread.recordType = kHFSPlusFileThreadRecord; - thread.reserved = 0; - thread.parentID = parentFolder->folderID; - ASCIIToUnicode(name, &thread.nodeName); - threadLength = sizeof(thread.recordType) + sizeof(thread.reserved) + sizeof(thread.parentID) + STR_SIZE(thread.nodeName); - flipCatalogThread(&thread, TRUE); - flipCatalogFile(&file); - - ASSERT(addToBTree(volume->catalogTree, (BTKey*)(&key), sizeof(HFSPlusCatalogFile), (unsigned char *)(&file)), "addToBTree"); - key.nodeName.length = 0; - key.parentID = newFileID; - key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); - ASSERT(addToBTree(volume->catalogTree, (BTKey*)(&key), threadLength, (unsigned char *)(&thread)), "addToBTree"); - - parentFolder->valence++; - updateCatalog(volume, (HFSPlusCatalogRecord*) parentFolder); - - updateVolume(volume); - - free(parentFolder); - free(path); - - return newFileID; -} - -int chmodFile(const char* pathName, int mode, Volume* volume) { - HFSPlusCatalogRecord* record; - - record = getRecordFromPath(pathName, volume, NULL, NULL); - - if(record == NULL) { - return FALSE; - } - - if(record->recordType == kHFSPlusFolderRecord) { - ((HFSPlusCatalogFolder*)record)->permissions.fileMode = (((HFSPlusCatalogFolder*)record)->permissions.fileMode & 0770000) | mode; - } else if(record->recordType == kHFSPlusFileRecord) { - ((HFSPlusCatalogFile*)record)->permissions.fileMode = (((HFSPlusCatalogFolder*)record)->permissions.fileMode & 0770000) | mode; - } else { - return FALSE; - } - - updateCatalog(volume, record); - - free(record); - - return TRUE; -} - -int chownFile(const char* pathName, uint32_t owner, uint32_t group, Volume* volume) { - HFSPlusCatalogRecord* record; - - record = getRecordFromPath(pathName, volume, NULL, NULL); - - if(record == NULL) { - return FALSE; - } - - if(record->recordType == kHFSPlusFolderRecord) { - ((HFSPlusCatalogFolder*)record)->permissions.ownerID = owner; - ((HFSPlusCatalogFolder*)record)->permissions.groupID = group; - } else if(record->recordType == kHFSPlusFileRecord) { - ((HFSPlusCatalogFile*)record)->permissions.ownerID = owner; - ((HFSPlusCatalogFile*)record)->permissions.groupID = group; - } else { - return FALSE; - } - - updateCatalog(volume, record); - - free(record); - - return TRUE; -} - - -BTree* openCatalogTree(io_func* file) { - BTree* btree; - - btree = openBTree(file, &catalogCompare, &catalogKeyRead, &catalogKeyWrite, &catalogKeyPrint, &catalogDataRead); - - if(btree->headerRec->keyCompareType == kHFSCaseFolding) { - btree->compare = &catalogCompareCS; - } - - return btree; + +HFSCatalogNodeID newFolder(const char* pathName, Volume* volume) { + HFSPlusCatalogFolder* parentFolder; + HFSPlusCatalogFolder folder; + HFSPlusCatalogKey key; + HFSPlusCatalogThread thread; + + uint32_t newFolderID; + + int threadLength; + + char* path; + char* name; + char* curChar; + char* lastSeparator; + + path = strdup(pathName); + + curChar = path; + lastSeparator = NULL; + + while((*curChar) != '\0') { + if((*curChar) == '/') + lastSeparator = curChar; + curChar++; + } + + if(lastSeparator == NULL) { + parentFolder = (HFSPlusCatalogFolder*) getRecordFromPath("/", volume, NULL, NULL); + name = path; + } else { + name = lastSeparator + 1; + *lastSeparator = '\0'; + parentFolder = (HFSPlusCatalogFolder*) getRecordFromPath(path, volume, NULL, NULL); + + if(parentFolder == NULL || parentFolder->recordType != kHFSPlusFolderRecord) { + free(path); + free(parentFolder); + return FALSE; + } + } + + newFolderID = volume->volumeHeader->nextCatalogID++; + volume->volumeHeader->folderCount++; + + folder.recordType = kHFSPlusFolderRecord; + folder.flags = kHFSHasFolderCountMask; + folder.valence = 0; + folder.folderID = newFolderID; + folder.createDate = UNIX_TO_APPLE_TIME(time(NULL)); + folder.contentModDate = folder.createDate; + folder.attributeModDate = folder.createDate; + folder.accessDate = folder.createDate; + folder.backupDate = folder.createDate; + folder.permissions.ownerID = parentFolder->permissions.ownerID; + folder.permissions.groupID = parentFolder->permissions.groupID; + folder.permissions.adminFlags = 0; + folder.permissions.ownerFlags = 0; + folder.permissions.fileMode = S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + folder.permissions.special.iNodeNum = 0; + memset(&folder.userInfo, 0, sizeof(folder.userInfo)); + memset(&folder.finderInfo, 0, sizeof(folder.finderInfo)); + folder.textEncoding = 0; + folder.folderCount = 0; + + key.parentID = parentFolder->folderID; + ASCIIToUnicode(name, &key.nodeName); + key.keyLength = sizeof(key.parentID) + STR_SIZE(key.nodeName); + + thread.recordType = kHFSPlusFolderThreadRecord; + thread.reserved = 0; + thread.parentID = parentFolder->folderID; + ASCIIToUnicode(name, &thread.nodeName); + threadLength = sizeof(thread.recordType) + sizeof(thread.reserved) + sizeof(thread.parentID) + STR_SIZE(thread.nodeName); + flipCatalogThread(&thread, TRUE); + flipCatalogFolder(&folder); + + ASSERT(addToBTree(volume->catalogTree, (BTKey*)(&key), sizeof(HFSPlusCatalogFolder), (unsigned char *)(&folder)), "addToBTree"); + key.nodeName.length = 0; + key.parentID = newFolderID; + key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); + ASSERT(addToBTree(volume->catalogTree, (BTKey*)(&key), threadLength, (unsigned char *)(&thread)), "addToBTree"); + + parentFolder->folderCount++; + parentFolder->valence++; + updateCatalog(volume, (HFSPlusCatalogRecord*) parentFolder); + + updateVolume(volume); + + free(parentFolder); + free(path); + + return newFolderID; +} + +HFSCatalogNodeID newFile(const char* pathName, Volume* volume) { + HFSPlusCatalogFolder* parentFolder; + HFSPlusCatalogFile file; + HFSPlusCatalogKey key; + HFSPlusCatalogThread thread; + + uint32_t newFileID; + + int threadLength; + + char* path; + char* name; + char* curChar; + char* lastSeparator; + + path = strdup(pathName); + + curChar = path; + lastSeparator = NULL; + + while((*curChar) != '\0') { + if((*curChar) == '/') + lastSeparator = curChar; + curChar++; + } + + if(lastSeparator == NULL) { + parentFolder = (HFSPlusCatalogFolder*) getRecordFromPath("/", volume, NULL, NULL); + name = path; + } else { + name = lastSeparator + 1; + *lastSeparator = '\0'; + parentFolder = (HFSPlusCatalogFolder*) getRecordFromPath(path, volume, NULL, NULL); + + if(parentFolder == NULL || parentFolder->recordType != kHFSPlusFolderRecord) { + free(path); + free(parentFolder); + return FALSE; + } + } + + newFileID = volume->volumeHeader->nextCatalogID++; + volume->volumeHeader->fileCount++; + + file.recordType = kHFSPlusFileRecord; + file.flags = kHFSThreadExistsMask; + file.reserved1 = 0; + file.fileID = newFileID; + file.createDate = UNIX_TO_APPLE_TIME(time(NULL)); + file.contentModDate = file.createDate; + file.attributeModDate = file.createDate; + file.accessDate = file.createDate; + file.backupDate = file.createDate; + file.permissions.ownerID = parentFolder->permissions.ownerID; + file.permissions.groupID = parentFolder->permissions.groupID; + file.permissions.adminFlags = 0; + file.permissions.ownerFlags = 0; + file.permissions.fileMode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + file.permissions.special.iNodeNum = 0; + memset(&file.userInfo, 0, sizeof(file.userInfo)); + memset(&file.finderInfo, 0, sizeof(file.finderInfo)); + file.textEncoding = 0; + file.reserved2 = 0; + memset(&file.dataFork, 0, sizeof(file.dataFork)); + memset(&file.resourceFork, 0, sizeof(file.resourceFork)); + + key.parentID = parentFolder->folderID; + ASCIIToUnicode(name, &key.nodeName); + key.keyLength = sizeof(key.parentID) + STR_SIZE(key.nodeName); + + thread.recordType = kHFSPlusFileThreadRecord; + thread.reserved = 0; + thread.parentID = parentFolder->folderID; + ASCIIToUnicode(name, &thread.nodeName); + threadLength = sizeof(thread.recordType) + sizeof(thread.reserved) + sizeof(thread.parentID) + STR_SIZE(thread.nodeName); + flipCatalogThread(&thread, TRUE); + flipCatalogFile(&file); + + ASSERT(addToBTree(volume->catalogTree, (BTKey*)(&key), sizeof(HFSPlusCatalogFile), (unsigned char *)(&file)), "addToBTree"); + key.nodeName.length = 0; + key.parentID = newFileID; + key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length); + ASSERT(addToBTree(volume->catalogTree, (BTKey*)(&key), threadLength, (unsigned char *)(&thread)), "addToBTree"); + + parentFolder->valence++; + updateCatalog(volume, (HFSPlusCatalogRecord*) parentFolder); + + updateVolume(volume); + + free(parentFolder); + free(path); + + return newFileID; +} + +int chmodFile(const char* pathName, int mode, Volume* volume) { + HFSPlusCatalogRecord* record; + + record = getRecordFromPath(pathName, volume, NULL, NULL); + + if(record == NULL) { + return FALSE; + } + + if(record->recordType == kHFSPlusFolderRecord) { + ((HFSPlusCatalogFolder*)record)->permissions.fileMode = (((HFSPlusCatalogFolder*)record)->permissions.fileMode & 0770000) | mode; + } else if(record->recordType == kHFSPlusFileRecord) { + ((HFSPlusCatalogFile*)record)->permissions.fileMode = (((HFSPlusCatalogFolder*)record)->permissions.fileMode & 0770000) | mode; + } else { + return FALSE; + } + + updateCatalog(volume, record); + + free(record); + + return TRUE; +} + +int chownFile(const char* pathName, uint32_t owner, uint32_t group, Volume* volume) { + HFSPlusCatalogRecord* record; + + record = getRecordFromPath(pathName, volume, NULL, NULL); + + if(record == NULL) { + return FALSE; + } + + if(record->recordType == kHFSPlusFolderRecord) { + ((HFSPlusCatalogFolder*)record)->permissions.ownerID = owner; + ((HFSPlusCatalogFolder*)record)->permissions.groupID = group; + } else if(record->recordType == kHFSPlusFileRecord) { + ((HFSPlusCatalogFile*)record)->permissions.ownerID = owner; + ((HFSPlusCatalogFile*)record)->permissions.groupID = group; + } else { + return FALSE; + } + + updateCatalog(volume, record); + + free(record); + + return TRUE; +} + + +BTree* openCatalogTree(io_func* file) { + BTree* btree; + + btree = openBTree(file, &catalogCompare, &catalogKeyRead, &catalogKeyWrite, &catalogKeyPrint, &catalogDataRead); + + if(btree->headerRec->keyCompareType == kHFSCaseFolding) { + btree->compare = &catalogCompareCS; + } + + return btree; } diff --git a/hfs/common.h b/hfs/common.h index bb5c2dc..779f6e9 100644 --- a/hfs/common.h +++ b/hfs/common.h @@ -1,75 +1,75 @@ -#ifndef COMMON_H -#define COMMON_H - -#include -#include -#include - -#ifdef WIN32 -#define fseeko fseeko64 -#define ftello ftello64 -#define off_t off64_t -#define mkdir(x, y) mkdir(x) -#endif - -#define TRUE 1 -#define FALSE 0 - -#define FLIPENDIAN(x) flipEndian((unsigned char *)(&(x)), sizeof(x)) -#define FLIPENDIANLE(x) flipEndianLE((unsigned char *)(&(x)), sizeof(x)) - -#define IS_BIG_ENDIAN 0 -#define IS_LITTLE_ENDIAN 1 - -#define TIME_OFFSET_FROM_UNIX 2082844800L -#define APPLE_TO_UNIX_TIME(x) ((x) - TIME_OFFSET_FROM_UNIX) -#define UNIX_TO_APPLE_TIME(x) ((x) + TIME_OFFSET_FROM_UNIX) - -#define ASSERT(x, m) if(!(x)) { fflush(stdout); fprintf(stderr, "error: %s\n", m); perror("error"); fflush(stderr); exit(1); } - -extern char endianness; - -static inline void flipEndian(unsigned char* x, int length) { - int i; - unsigned char tmp; - - if(endianness == IS_BIG_ENDIAN) { - return; - } else { - for(i = 0; i < (length / 2); i++) { - tmp = x[i]; - x[i] = x[length - i - 1]; - x[length - i - 1] = tmp; - } - } -} - -static inline void flipEndianLE(unsigned char* x, int length) { - int i; - unsigned char tmp; - - if(endianness == IS_LITTLE_ENDIAN) { - return; - } else { - for(i = 0; i < (length / 2); i++) { - tmp = x[i]; - x[i] = x[length - i - 1]; - x[length - i - 1] = tmp; - } - } -} - -struct io_func_struct; - -typedef int (*readFunc)(struct io_func_struct* io, off_t location, size_t size, void *buffer); -typedef int (*writeFunc)(struct io_func_struct* io, off_t location, size_t size, void *buffer); -typedef void (*closeFunc)(struct io_func_struct* io); - -typedef struct io_func_struct { - void* data; - readFunc read; - writeFunc write; - closeFunc close; -} io_func; - -#endif +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include + +#ifdef WIN32 +#define fseeko fseeko64 +#define ftello ftello64 +#define off_t off64_t +#define mkdir(x, y) mkdir(x) +#endif + +#define TRUE 1 +#define FALSE 0 + +#define FLIPENDIAN(x) flipEndian((unsigned char *)(&(x)), sizeof(x)) +#define FLIPENDIANLE(x) flipEndianLE((unsigned char *)(&(x)), sizeof(x)) + +#define IS_BIG_ENDIAN 0 +#define IS_LITTLE_ENDIAN 1 + +#define TIME_OFFSET_FROM_UNIX 2082844800L +#define APPLE_TO_UNIX_TIME(x) ((x) - TIME_OFFSET_FROM_UNIX) +#define UNIX_TO_APPLE_TIME(x) ((x) + TIME_OFFSET_FROM_UNIX) + +#define ASSERT(x, m) if(!(x)) { fflush(stdout); fprintf(stderr, "error: %s\n", m); perror("error"); fflush(stderr); exit(1); } + +extern char endianness; + +static inline void flipEndian(unsigned char* x, int length) { + int i; + unsigned char tmp; + + if(endianness == IS_BIG_ENDIAN) { + return; + } else { + for(i = 0; i < (length / 2); i++) { + tmp = x[i]; + x[i] = x[length - i - 1]; + x[length - i - 1] = tmp; + } + } +} + +static inline void flipEndianLE(unsigned char* x, int length) { + int i; + unsigned char tmp; + + if(endianness == IS_LITTLE_ENDIAN) { + return; + } else { + for(i = 0; i < (length / 2); i++) { + tmp = x[i]; + x[i] = x[length - i - 1]; + x[length - i - 1] = tmp; + } + } +} + +struct io_func_struct; + +typedef int (*readFunc)(struct io_func_struct* io, off_t location, size_t size, void *buffer); +typedef int (*writeFunc)(struct io_func_struct* io, off_t location, size_t size, void *buffer); +typedef void (*closeFunc)(struct io_func_struct* io); + +typedef struct io_func_struct { + void* data; + readFunc read; + writeFunc write; + closeFunc close; +} io_func; + +#endif diff --git a/hfs/extents.c b/hfs/extents.c index e0bc20d..c87bfd9 100644 --- a/hfs/extents.c +++ b/hfs/extents.c @@ -1,119 +1,119 @@ #include -#include -#include "hfsplus.h" - -static inline void flipExtentDescriptor(HFSPlusExtentDescriptor* extentDescriptor) { - FLIPENDIAN(extentDescriptor->startBlock); - FLIPENDIAN(extentDescriptor->blockCount); -} - -void flipExtentRecord(HFSPlusExtentRecord* extentRecord) { - HFSPlusExtentDescriptor *extentDescriptor; - extentDescriptor = (HFSPlusExtentDescriptor*)extentRecord; - - flipExtentDescriptor(&extentDescriptor[0]); - flipExtentDescriptor(&extentDescriptor[1]); - flipExtentDescriptor(&extentDescriptor[2]); - flipExtentDescriptor(&extentDescriptor[3]); - flipExtentDescriptor(&extentDescriptor[4]); - flipExtentDescriptor(&extentDescriptor[5]); - flipExtentDescriptor(&extentDescriptor[6]); - flipExtentDescriptor(&extentDescriptor[7]); -} - -static int extentCompare(BTKey* vLeft, BTKey* vRight) { - HFSPlusExtentKey* left; - HFSPlusExtentKey* right; - - left = (HFSPlusExtentKey*) vLeft; - right =(HFSPlusExtentKey*) vRight; - - if(left->forkType < right->forkType) { - return -1; - } else if(left->forkType > right->forkType) { - return 1; - } else { - if(left->fileID < right->fileID) { - return -1; - } else if(left->fileID > right->fileID) { - return 1; - } else { - if(left->startBlock < right->startBlock) { - return -1; - } else if(left->startBlock > right->startBlock) { - return 1; - } else { - /* do a safety check on key length. Otherwise, bad things may happen later on when we try to add or remove with this key */ - if(left->keyLength == right->keyLength) { - return 0; - } else if(left->keyLength < right->keyLength) { - return -1; - } else { - return 1; - } - return 0; - } - } - } -} - -static BTKey* extentKeyRead(off_t offset, io_func* io) { - HFSPlusExtentKey* key; - - key = (HFSPlusExtentKey*) malloc(sizeof(HFSPlusExtentKey)); - - if(!READ(io, offset, sizeof(HFSPlusExtentKey), key)) - return NULL; - - FLIPENDIAN(key->keyLength); - FLIPENDIAN(key->forkType); - FLIPENDIAN(key->fileID); - FLIPENDIAN(key->startBlock); - - return (BTKey*)key; -} - -static int extentKeyWrite(off_t offset, BTKey* toWrite, io_func* io) { - HFSPlusExtentKey* key; - - key = (HFSPlusExtentKey*) malloc(sizeof(HFSPlusExtentKey)); - - memcpy(key, toWrite, sizeof(HFSPlusExtentKey)); - - FLIPENDIAN(key->keyLength); - FLIPENDIAN(key->forkType); - FLIPENDIAN(key->fileID); - FLIPENDIAN(key->startBlock); - - if(!WRITE(io, offset, sizeof(HFSPlusExtentKey), key)) - return FALSE; - - free(key); - - return TRUE; -} - -static void extentKeyPrint(BTKey* toPrint) { - HFSPlusExtentKey* key; - - key = (HFSPlusExtentKey*)toPrint; - - printf("extent%d:%d:%d", key->forkType, key->fileID, key->startBlock); -} - -static BTKey* extentDataRead(off_t offset, io_func* io) { - HFSPlusExtentRecord* record; - - record = (HFSPlusExtentRecord*) malloc(sizeof(HFSPlusExtentRecord)); - - if(!READ(io, offset, sizeof(HFSPlusExtentRecord), record)) - return NULL; - - flipExtentRecord(record); - - return (BTKey*)record; -} - -BTree* openExtentsTree(io_func* file) { - return openBTree(file, &extentCompare, &extentKeyRead, &extentKeyWrite, &extentKeyPrint, &extentDataRead); -} +#include +#include "hfsplus.h" + +static inline void flipExtentDescriptor(HFSPlusExtentDescriptor* extentDescriptor) { + FLIPENDIAN(extentDescriptor->startBlock); + FLIPENDIAN(extentDescriptor->blockCount); +} + +void flipExtentRecord(HFSPlusExtentRecord* extentRecord) { + HFSPlusExtentDescriptor *extentDescriptor; + extentDescriptor = (HFSPlusExtentDescriptor*)extentRecord; + + flipExtentDescriptor(&extentDescriptor[0]); + flipExtentDescriptor(&extentDescriptor[1]); + flipExtentDescriptor(&extentDescriptor[2]); + flipExtentDescriptor(&extentDescriptor[3]); + flipExtentDescriptor(&extentDescriptor[4]); + flipExtentDescriptor(&extentDescriptor[5]); + flipExtentDescriptor(&extentDescriptor[6]); + flipExtentDescriptor(&extentDescriptor[7]); +} + +static int extentCompare(BTKey* vLeft, BTKey* vRight) { + HFSPlusExtentKey* left; + HFSPlusExtentKey* right; + + left = (HFSPlusExtentKey*) vLeft; + right =(HFSPlusExtentKey*) vRight; + + if(left->forkType < right->forkType) { + return -1; + } else if(left->forkType > right->forkType) { + return 1; + } else { + if(left->fileID < right->fileID) { + return -1; + } else if(left->fileID > right->fileID) { + return 1; + } else { + if(left->startBlock < right->startBlock) { + return -1; + } else if(left->startBlock > right->startBlock) { + return 1; + } else { + /* do a safety check on key length. Otherwise, bad things may happen later on when we try to add or remove with this key */ + if(left->keyLength == right->keyLength) { + return 0; + } else if(left->keyLength < right->keyLength) { + return -1; + } else { + return 1; + } + return 0; + } + } + } +} + +static BTKey* extentKeyRead(off_t offset, io_func* io) { + HFSPlusExtentKey* key; + + key = (HFSPlusExtentKey*) malloc(sizeof(HFSPlusExtentKey)); + + if(!READ(io, offset, sizeof(HFSPlusExtentKey), key)) + return NULL; + + FLIPENDIAN(key->keyLength); + FLIPENDIAN(key->forkType); + FLIPENDIAN(key->fileID); + FLIPENDIAN(key->startBlock); + + return (BTKey*)key; +} + +static int extentKeyWrite(off_t offset, BTKey* toWrite, io_func* io) { + HFSPlusExtentKey* key; + + key = (HFSPlusExtentKey*) malloc(sizeof(HFSPlusExtentKey)); + + memcpy(key, toWrite, sizeof(HFSPlusExtentKey)); + + FLIPENDIAN(key->keyLength); + FLIPENDIAN(key->forkType); + FLIPENDIAN(key->fileID); + FLIPENDIAN(key->startBlock); + + if(!WRITE(io, offset, sizeof(HFSPlusExtentKey), key)) + return FALSE; + + free(key); + + return TRUE; +} + +static void extentKeyPrint(BTKey* toPrint) { + HFSPlusExtentKey* key; + + key = (HFSPlusExtentKey*)toPrint; + + printf("extent%d:%d:%d", key->forkType, key->fileID, key->startBlock); +} + +static BTKey* extentDataRead(off_t offset, io_func* io) { + HFSPlusExtentRecord* record; + + record = (HFSPlusExtentRecord*) malloc(sizeof(HFSPlusExtentRecord)); + + if(!READ(io, offset, sizeof(HFSPlusExtentRecord), record)) + return NULL; + + flipExtentRecord(record); + + return (BTKey*)record; +} + +BTree* openExtentsTree(io_func* file) { + return openBTree(file, &extentCompare, &extentKeyRead, &extentKeyWrite, &extentKeyPrint, &extentDataRead); +} diff --git a/hfs/fastunicodecompare.c b/hfs/fastunicodecompare.c index bbea700..ea0a01f 100644 --- a/hfs/fastunicodecompare.c +++ b/hfs/fastunicodecompare.c @@ -1,418 +1,418 @@ -#include -#include "hfsplus.h" - -/* This routine is taken from Apple's TN 1150, with adaptations for C */ - -/* The lower case table consists of a 256-entry high-byte table followed by - some number of 256-entry subtables. The high-byte table contains either an - offset to the subtable for characters with that high byte or zero, which - means that there are no case mappings or ignored characters in that block. - Ignored characters are mapped to zero. - */ - -uint16_t gLowerCaseTable[] = { - - /* 0 */ 0x0100, 0x0200, 0x0000, 0x0300, 0x0400, 0x0500, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* 1 */ 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* 2 */ 0x0700, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* 3 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* 4 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* 5 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* 6 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* 7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* 8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* 9 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* A */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* B */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* C */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* D */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* E */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* F */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0900, 0x0A00, - - /* 0 */ 0xFFFF, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, - /* 1 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, - /* 2 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, - /* 3 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, - /* 4 */ 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, - /* 5 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, - /* 6 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, - /* 7 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, - /* 8 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, - 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, - /* 9 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, - 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, - /* A */ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, - 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, - /* B */ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, - 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, - /* C */ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00E6, 0x00C7, - 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, - /* D */ 0x00F0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00F8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00FE, 0x00DF, - /* E */ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, - 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, - /* F */ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, - 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, - - /* 0 */ 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, - 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F, - /* 1 */ 0x0111, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117, - 0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F, - /* 2 */ 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0127, 0x0127, - 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F, - /* 3 */ 0x0130, 0x0131, 0x0133, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137, - 0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x0140, - /* 4 */ 0x0140, 0x0142, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147, - 0x0148, 0x0149, 0x014B, 0x014B, 0x014C, 0x014D, 0x014E, 0x014F, - /* 5 */ 0x0150, 0x0151, 0x0153, 0x0153, 0x0154, 0x0155, 0x0156, 0x0157, - 0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F, - /* 6 */ 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0167, 0x0167, - 0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F, - /* 7 */ 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175, 0x0176, 0x0177, - 0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x017F, - /* 8 */ 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188, - 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259, - /* 9 */ 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268, - 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275, - /* A */ 0x01A0, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8, - 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01AF, - /* B */ 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292, - 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF, - /* C */ 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9, - 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CD, 0x01CE, 0x01CF, - /* D */ 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7, - 0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF, - /* E */ 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E5, 0x01E5, 0x01E6, 0x01E7, - 0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, 0x01ED, 0x01EE, 0x01EF, - /* F */ 0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7, - 0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, - - /* 0 */ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, - 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F, - /* 1 */ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, - 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, - /* 2 */ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, - 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, - /* 3 */ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, - 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F, - /* 4 */ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347, - 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F, - /* 5 */ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, - 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, - /* 6 */ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, - 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F, - /* 7 */ 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, - 0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F, - /* 8 */ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387, - 0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F, - /* 9 */ 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - /* A */ 0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, - 0x03C8, 0x03C9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, - /* B */ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - /* C */ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, - 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF, - /* D */ 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7, - 0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF, - /* E */ 0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7, - 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF, - /* F */ 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7, - 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, - - /* 0 */ 0x0400, 0x0401, 0x0452, 0x0403, 0x0454, 0x0455, 0x0456, 0x0407, - 0x0458, 0x0459, 0x045A, 0x045B, 0x040C, 0x040D, 0x040E, 0x045F, - /* 1 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0419, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - /* 2 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, - /* 3 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, - /* 4 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, - /* 5 */ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, - 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F, - /* 6 */ 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467, - 0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F, - /* 7 */ 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0476, 0x0477, - 0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F, - /* 8 */ 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, - 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F, - /* 9 */ 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497, - 0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F, - /* A */ 0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7, - 0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF, - /* B */ 0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7, - 0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF, - /* C */ 0x04C0, 0x04C1, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8, - 0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF, - /* D */ 0x04D0, 0x04D1, 0x04D2, 0x04D3, 0x04D4, 0x04D5, 0x04D6, 0x04D7, - 0x04D8, 0x04D9, 0x04DA, 0x04DB, 0x04DC, 0x04DD, 0x04DE, 0x04DF, - /* E */ 0x04E0, 0x04E1, 0x04E2, 0x04E3, 0x04E4, 0x04E5, 0x04E6, 0x04E7, - 0x04E8, 0x04E9, 0x04EA, 0x04EB, 0x04EC, 0x04ED, 0x04EE, 0x04EF, - /* F */ 0x04F0, 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, 0x04F7, - 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF, - - /* 0 */ 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, - 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F, - /* 1 */ 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517, - 0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F, - /* 2 */ 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, - 0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F, - /* 3 */ 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, - 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, - /* 4 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, - 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F, - /* 5 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557, - 0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F, - /* 6 */ 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, - 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, - /* 7 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, - 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F, - /* 8 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587, - 0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F, - /* 9 */ 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, - 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F, - /* A */ 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7, - 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF, - /* B */ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, - 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, - /* C */ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7, - 0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF, - /* D */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, - 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, - /* E */ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, - 0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF, - /* F */ 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7, - 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, - - /* 0 */ 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, - 0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F, - /* 1 */ 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017, - 0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F, - /* 2 */ 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027, - 0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F, - /* 3 */ 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037, - 0x1038, 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F, - /* 4 */ 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047, - 0x1048, 0x1049, 0x104A, 0x104B, 0x104C, 0x104D, 0x104E, 0x104F, - /* 5 */ 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057, - 0x1058, 0x1059, 0x105A, 0x105B, 0x105C, 0x105D, 0x105E, 0x105F, - /* 6 */ 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067, - 0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, 0x106F, - /* 7 */ 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077, - 0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F, - /* 8 */ 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, - 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F, - /* 9 */ 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, - 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x109F, - /* A */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7, - 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF, - /* B */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, - 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF, - /* C */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10C6, 0x10C7, - 0x10C8, 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF, - /* D */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7, - 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF, - /* E */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, - 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF, - /* F */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7, - 0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, 0x10FF, - - /* 0 */ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, - 0x2008, 0x2009, 0x200A, 0x200B, 0x0000, 0x0000, 0x0000, 0x0000, - /* 1 */ 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, - 0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E, 0x201F, - /* 2 */ 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, - 0x2028, 0x2029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x202F, - /* 3 */ 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, - 0x2038, 0x2039, 0x203A, 0x203B, 0x203C, 0x203D, 0x203E, 0x203F, - /* 4 */ 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047, - 0x2048, 0x2049, 0x204A, 0x204B, 0x204C, 0x204D, 0x204E, 0x204F, - /* 5 */ 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, - 0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, 0x205E, 0x205F, - /* 6 */ 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067, - 0x2068, 0x2069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - /* 7 */ 0x2070, 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077, - 0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F, - /* 8 */ 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087, - 0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x208F, - /* 9 */ 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x2095, 0x2096, 0x2097, - 0x2098, 0x2099, 0x209A, 0x209B, 0x209C, 0x209D, 0x209E, 0x209F, - /* A */ 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, 0x20A6, 0x20A7, - 0x20A8, 0x20A9, 0x20AA, 0x20AB, 0x20AC, 0x20AD, 0x20AE, 0x20AF, - /* B */ 0x20B0, 0x20B1, 0x20B2, 0x20B3, 0x20B4, 0x20B5, 0x20B6, 0x20B7, - 0x20B8, 0x20B9, 0x20BA, 0x20BB, 0x20BC, 0x20BD, 0x20BE, 0x20BF, - /* C */ 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7, - 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF, - /* D */ 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7, - 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF, - /* E */ 0x20E0, 0x20E1, 0x20E2, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7, - 0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF, - /* F */ 0x20F0, 0x20F1, 0x20F2, 0x20F3, 0x20F4, 0x20F5, 0x20F6, 0x20F7, - 0x20F8, 0x20F9, 0x20FA, 0x20FB, 0x20FC, 0x20FD, 0x20FE, 0x20FF, - - /* 0 */ 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107, - 0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F, - /* 1 */ 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117, - 0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F, - /* 2 */ 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127, - 0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F, - /* 3 */ 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137, - 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F, - /* 4 */ 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, - 0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F, - /* 5 */ 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, - 0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F, - /* 6 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, - 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, - /* 7 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, - 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, - /* 8 */ 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187, - 0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F, - /* 9 */ 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197, - 0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F, - /* A */ 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7, - 0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF, - /* B */ 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7, - 0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF, - /* C */ 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7, - 0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF, - /* D */ 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7, - 0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF, - /* E */ 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7, - 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF, - /* F */ 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7, - 0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF, - - /* 0 */ 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, - 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, - /* 1 */ 0xFE10, 0xFE11, 0xFE12, 0xFE13, 0xFE14, 0xFE15, 0xFE16, 0xFE17, - 0xFE18, 0xFE19, 0xFE1A, 0xFE1B, 0xFE1C, 0xFE1D, 0xFE1E, 0xFE1F, - /* 2 */ 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27, - 0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F, - /* 3 */ 0xFE30, 0xFE31, 0xFE32, 0xFE33, 0xFE34, 0xFE35, 0xFE36, 0xFE37, - 0xFE38, 0xFE39, 0xFE3A, 0xFE3B, 0xFE3C, 0xFE3D, 0xFE3E, 0xFE3F, - /* 4 */ 0xFE40, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE45, 0xFE46, 0xFE47, - 0xFE48, 0xFE49, 0xFE4A, 0xFE4B, 0xFE4C, 0xFE4D, 0xFE4E, 0xFE4F, - /* 5 */ 0xFE50, 0xFE51, 0xFE52, 0xFE53, 0xFE54, 0xFE55, 0xFE56, 0xFE57, - 0xFE58, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, 0xFE5E, 0xFE5F, - /* 6 */ 0xFE60, 0xFE61, 0xFE62, 0xFE63, 0xFE64, 0xFE65, 0xFE66, 0xFE67, - 0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0xFE6C, 0xFE6D, 0xFE6E, 0xFE6F, - /* 7 */ 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, 0xFE76, 0xFE77, - 0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F, - /* 8 */ 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, 0xFE86, 0xFE87, - 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, 0xFE8E, 0xFE8F, - /* 9 */ 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95, 0xFE96, 0xFE97, - 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0xFE9F, - /* A */ 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7, - 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF, - /* B */ 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7, - 0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF, - /* C */ 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7, - 0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF, - /* D */ 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, 0xFED6, 0xFED7, - 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, 0xFEDE, 0xFEDF, - /* E */ 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6, 0xFEE7, - 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF, - /* F */ 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, - 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0x0000, - - /* 0 */ 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07, - 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F, - /* 1 */ 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, - 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F, - /* 2 */ 0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, - 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, - /* 3 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, - 0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F, - /* 4 */ 0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, - 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, - /* 5 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, - 0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F, - /* 6 */ 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, - 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, - /* 7 */ 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, - 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, - /* 8 */ 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, - 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, - /* 9 */ 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, - 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, - /* A */ 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7, - 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF, - /* B */ 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7, - 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF, - /* C */ 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7, - 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF, - /* D */ 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7, - 0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF, - /* E */ 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7, - 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF, - /* F */ 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, - 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF, -}; - -int32_t FastUnicodeCompare ( register uint16_t str1[], register uint16_t length1, - register uint16_t str2[], register uint16_t length2) -{ - register uint16_t c1,c2; - register uint16_t temp; - register uint16_t* lowerCaseTable; - - lowerCaseTable = gLowerCaseTable; - - while (1) { - c1 = 0; - c2 = 0; - while (length1 && c1 == 0) { - c1 = *(str1++); - --length1; - if ((temp = lowerCaseTable[c1>>8]) != 0) - c1 = lowerCaseTable[temp + (c1 & 0x00FF)]; - } - while (length2 && c2 == 0) { - c2 = *(str2++); - --length2; - if ((temp = lowerCaseTable[c2>>8]) != 0) - c2 = lowerCaseTable[temp + (c2 & 0x00FF)]; - } - if (c1 == ':') { - c1 = '/'; - } - if (c2 == ':') { - c2 = '/'; - } - if (c1 != c2) - break; - if (c1 == 0) - return 0; - } - if (c1 < c2) - return -1; - else - return 1; -} +#include +#include "hfsplus.h" + +/* This routine is taken from Apple's TN 1150, with adaptations for C */ + +/* The lower case table consists of a 256-entry high-byte table followed by + some number of 256-entry subtables. The high-byte table contains either an + offset to the subtable for characters with that high byte or zero, which + means that there are no case mappings or ignored characters in that block. + Ignored characters are mapped to zero. + */ + +uint16_t gLowerCaseTable[] = { + + /* 0 */ 0x0100, 0x0200, 0x0000, 0x0300, 0x0400, 0x0500, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 1 */ 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 2 */ 0x0700, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 3 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 4 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 5 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 6 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 9 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* A */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* B */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* C */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* D */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* E */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* F */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0900, 0x0A00, + + /* 0 */ 0xFFFF, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + /* 1 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, + /* 2 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + /* 3 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, + /* 4 */ 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + /* 5 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, + /* 6 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + /* 7 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, + /* 8 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + /* 9 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + /* A */ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + /* B */ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + /* C */ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00E6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + /* D */ 0x00F0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00F8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00FE, 0x00DF, + /* E */ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + /* F */ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, + + /* 0 */ 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, + 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F, + /* 1 */ 0x0111, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117, + 0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F, + /* 2 */ 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0127, 0x0127, + 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F, + /* 3 */ 0x0130, 0x0131, 0x0133, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137, + 0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x0140, + /* 4 */ 0x0140, 0x0142, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147, + 0x0148, 0x0149, 0x014B, 0x014B, 0x014C, 0x014D, 0x014E, 0x014F, + /* 5 */ 0x0150, 0x0151, 0x0153, 0x0153, 0x0154, 0x0155, 0x0156, 0x0157, + 0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F, + /* 6 */ 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0167, 0x0167, + 0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F, + /* 7 */ 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175, 0x0176, 0x0177, + 0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x017F, + /* 8 */ 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188, + 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259, + /* 9 */ 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268, + 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275, + /* A */ 0x01A0, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8, + 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01AF, + /* B */ 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292, + 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF, + /* C */ 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9, + 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CD, 0x01CE, 0x01CF, + /* D */ 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7, + 0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF, + /* E */ 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E5, 0x01E5, 0x01E6, 0x01E7, + 0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, 0x01ED, 0x01EE, 0x01EF, + /* F */ 0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7, + 0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, + + /* 0 */ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, + 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F, + /* 1 */ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, + 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, + /* 2 */ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, + 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, + /* 3 */ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, + 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F, + /* 4 */ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347, + 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F, + /* 5 */ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, + 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, + /* 6 */ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, + 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F, + /* 7 */ 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, + 0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F, + /* 8 */ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387, + 0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F, + /* 9 */ 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + /* A */ 0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + /* B */ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + /* C */ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF, + /* D */ 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7, + 0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF, + /* E */ 0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7, + 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF, + /* F */ 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7, + 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, + + /* 0 */ 0x0400, 0x0401, 0x0452, 0x0403, 0x0454, 0x0455, 0x0456, 0x0407, + 0x0458, 0x0459, 0x045A, 0x045B, 0x040C, 0x040D, 0x040E, 0x045F, + /* 1 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0419, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + /* 2 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + /* 3 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + /* 4 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + /* 5 */ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, + 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F, + /* 6 */ 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467, + 0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F, + /* 7 */ 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0476, 0x0477, + 0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F, + /* 8 */ 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, + 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F, + /* 9 */ 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497, + 0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F, + /* A */ 0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7, + 0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF, + /* B */ 0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7, + 0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF, + /* C */ 0x04C0, 0x04C1, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8, + 0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF, + /* D */ 0x04D0, 0x04D1, 0x04D2, 0x04D3, 0x04D4, 0x04D5, 0x04D6, 0x04D7, + 0x04D8, 0x04D9, 0x04DA, 0x04DB, 0x04DC, 0x04DD, 0x04DE, 0x04DF, + /* E */ 0x04E0, 0x04E1, 0x04E2, 0x04E3, 0x04E4, 0x04E5, 0x04E6, 0x04E7, + 0x04E8, 0x04E9, 0x04EA, 0x04EB, 0x04EC, 0x04ED, 0x04EE, 0x04EF, + /* F */ 0x04F0, 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, 0x04F7, + 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF, + + /* 0 */ 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, + 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F, + /* 1 */ 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517, + 0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F, + /* 2 */ 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, + 0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F, + /* 3 */ 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, + 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, + /* 4 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, + 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F, + /* 5 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557, + 0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F, + /* 6 */ 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, + 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, + /* 7 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, + 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F, + /* 8 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587, + 0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F, + /* 9 */ 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, + 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F, + /* A */ 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7, + 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF, + /* B */ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, + 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, + /* C */ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7, + 0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF, + /* D */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, + 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + /* E */ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, + 0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF, + /* F */ 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7, + 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, + + /* 0 */ 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, + 0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F, + /* 1 */ 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017, + 0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F, + /* 2 */ 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027, + 0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F, + /* 3 */ 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037, + 0x1038, 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F, + /* 4 */ 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047, + 0x1048, 0x1049, 0x104A, 0x104B, 0x104C, 0x104D, 0x104E, 0x104F, + /* 5 */ 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057, + 0x1058, 0x1059, 0x105A, 0x105B, 0x105C, 0x105D, 0x105E, 0x105F, + /* 6 */ 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067, + 0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, 0x106F, + /* 7 */ 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077, + 0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F, + /* 8 */ 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, + 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F, + /* 9 */ 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, + 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x109F, + /* A */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7, + 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF, + /* B */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, + 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF, + /* C */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10C6, 0x10C7, + 0x10C8, 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF, + /* D */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7, + 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF, + /* E */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, + 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF, + /* F */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7, + 0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, 0x10FF, + + /* 0 */ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, + 0x2008, 0x2009, 0x200A, 0x200B, 0x0000, 0x0000, 0x0000, 0x0000, + /* 1 */ 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, + 0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E, 0x201F, + /* 2 */ 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, + 0x2028, 0x2029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x202F, + /* 3 */ 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, + 0x2038, 0x2039, 0x203A, 0x203B, 0x203C, 0x203D, 0x203E, 0x203F, + /* 4 */ 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047, + 0x2048, 0x2049, 0x204A, 0x204B, 0x204C, 0x204D, 0x204E, 0x204F, + /* 5 */ 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, + 0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, 0x205E, 0x205F, + /* 6 */ 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067, + 0x2068, 0x2069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 7 */ 0x2070, 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077, + 0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F, + /* 8 */ 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087, + 0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x208F, + /* 9 */ 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x2095, 0x2096, 0x2097, + 0x2098, 0x2099, 0x209A, 0x209B, 0x209C, 0x209D, 0x209E, 0x209F, + /* A */ 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, 0x20A6, 0x20A7, + 0x20A8, 0x20A9, 0x20AA, 0x20AB, 0x20AC, 0x20AD, 0x20AE, 0x20AF, + /* B */ 0x20B0, 0x20B1, 0x20B2, 0x20B3, 0x20B4, 0x20B5, 0x20B6, 0x20B7, + 0x20B8, 0x20B9, 0x20BA, 0x20BB, 0x20BC, 0x20BD, 0x20BE, 0x20BF, + /* C */ 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7, + 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF, + /* D */ 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7, + 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF, + /* E */ 0x20E0, 0x20E1, 0x20E2, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7, + 0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF, + /* F */ 0x20F0, 0x20F1, 0x20F2, 0x20F3, 0x20F4, 0x20F5, 0x20F6, 0x20F7, + 0x20F8, 0x20F9, 0x20FA, 0x20FB, 0x20FC, 0x20FD, 0x20FE, 0x20FF, + + /* 0 */ 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107, + 0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F, + /* 1 */ 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117, + 0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F, + /* 2 */ 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127, + 0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F, + /* 3 */ 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137, + 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F, + /* 4 */ 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, + 0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F, + /* 5 */ 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, + 0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F, + /* 6 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, + 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, + /* 7 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, + 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, + /* 8 */ 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187, + 0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F, + /* 9 */ 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197, + 0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F, + /* A */ 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7, + 0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF, + /* B */ 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7, + 0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF, + /* C */ 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7, + 0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF, + /* D */ 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7, + 0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF, + /* E */ 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7, + 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF, + /* F */ 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7, + 0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF, + + /* 0 */ 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, + 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, + /* 1 */ 0xFE10, 0xFE11, 0xFE12, 0xFE13, 0xFE14, 0xFE15, 0xFE16, 0xFE17, + 0xFE18, 0xFE19, 0xFE1A, 0xFE1B, 0xFE1C, 0xFE1D, 0xFE1E, 0xFE1F, + /* 2 */ 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27, + 0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F, + /* 3 */ 0xFE30, 0xFE31, 0xFE32, 0xFE33, 0xFE34, 0xFE35, 0xFE36, 0xFE37, + 0xFE38, 0xFE39, 0xFE3A, 0xFE3B, 0xFE3C, 0xFE3D, 0xFE3E, 0xFE3F, + /* 4 */ 0xFE40, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE45, 0xFE46, 0xFE47, + 0xFE48, 0xFE49, 0xFE4A, 0xFE4B, 0xFE4C, 0xFE4D, 0xFE4E, 0xFE4F, + /* 5 */ 0xFE50, 0xFE51, 0xFE52, 0xFE53, 0xFE54, 0xFE55, 0xFE56, 0xFE57, + 0xFE58, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, 0xFE5E, 0xFE5F, + /* 6 */ 0xFE60, 0xFE61, 0xFE62, 0xFE63, 0xFE64, 0xFE65, 0xFE66, 0xFE67, + 0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0xFE6C, 0xFE6D, 0xFE6E, 0xFE6F, + /* 7 */ 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, 0xFE76, 0xFE77, + 0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F, + /* 8 */ 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, 0xFE86, 0xFE87, + 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, 0xFE8E, 0xFE8F, + /* 9 */ 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95, 0xFE96, 0xFE97, + 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0xFE9F, + /* A */ 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7, + 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF, + /* B */ 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7, + 0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF, + /* C */ 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7, + 0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF, + /* D */ 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, 0xFED6, 0xFED7, + 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, 0xFEDE, 0xFEDF, + /* E */ 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6, 0xFEE7, + 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF, + /* F */ 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, + 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0x0000, + + /* 0 */ 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07, + 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F, + /* 1 */ 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, + 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F, + /* 2 */ 0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, + 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, + /* 3 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, + 0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F, + /* 4 */ 0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, + 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, + /* 5 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, + 0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F, + /* 6 */ 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, + 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, + /* 7 */ 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, + 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, + /* 8 */ 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, + 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, + /* 9 */ 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, + 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, + /* A */ 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7, + 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF, + /* B */ 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7, + 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF, + /* C */ 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7, + 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF, + /* D */ 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7, + 0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF, + /* E */ 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7, + 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF, + /* F */ 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, + 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF, +}; + +int32_t FastUnicodeCompare ( register uint16_t str1[], register uint16_t length1, + register uint16_t str2[], register uint16_t length2) +{ + register uint16_t c1,c2; + register uint16_t temp; + register uint16_t* lowerCaseTable; + + lowerCaseTable = gLowerCaseTable; + + while (1) { + c1 = 0; + c2 = 0; + while (length1 && c1 == 0) { + c1 = *(str1++); + --length1; + if ((temp = lowerCaseTable[c1>>8]) != 0) + c1 = lowerCaseTable[temp + (c1 & 0x00FF)]; + } + while (length2 && c2 == 0) { + c2 = *(str2++); + --length2; + if ((temp = lowerCaseTable[c2>>8]) != 0) + c2 = lowerCaseTable[temp + (c2 & 0x00FF)]; + } + if (c1 == ':') { + c1 = '/'; + } + if (c2 == ':') { + c2 = '/'; + } + if (c1 != c2) + break; + if (c1 == 0) + return 0; + } + if (c1 < c2) + return -1; + else + return 1; +} diff --git a/hfs/flatfile.c b/hfs/flatfile.c index 35c2dce..c479f19 100644 --- a/hfs/flatfile.c +++ b/hfs/flatfile.c @@ -1,104 +1,104 @@ -#include -#include "hfsplus.h" - -static int flatFileRead(io_func* io, off_t location, size_t size, void *buffer) { - FILE* file; - file = (FILE*) io->data; - - if(size == 0) { - return TRUE; - } - - //printf("%d %d\n", location, size); fflush(stdout); - - if(fseeko(file, location, SEEK_SET) != 0) { - perror("fseek"); - return FALSE; - } - - if(fread(buffer, size, 1, file) != 1) { - perror("fread"); - return FALSE; - } else { - return TRUE; - } -} - -static int flatFileWrite(io_func* io, off_t location, size_t size, void *buffer) { - FILE* file; - - /*int i; - - printf("write: %lld %d - ", location, size); fflush(stdout); - - for(i = 0; i < size; i++) { - printf("%x ", ((unsigned char*)buffer)[i]); - fflush(stdout); - } - printf("\n"); fflush(stdout);*/ - - if(size == 0) { - return TRUE; - } - - file = (FILE*) io->data; - - if(fseeko(file, location, SEEK_SET) != 0) { - perror("fseek"); - return FALSE; - } - - if(fwrite(buffer, size, 1, file) != 1) { - perror("fwrite"); - return FALSE; - } else { - return TRUE; +#include +#include "hfsplus.h" + +static int flatFileRead(io_func* io, off_t location, size_t size, void *buffer) { + FILE* file; + file = (FILE*) io->data; + + if(size == 0) { + return TRUE; } - - return TRUE; -} - -static void closeFlatFile(io_func* io) { - FILE* file; - - file = (FILE*) io->data; - - fclose(file); - free(io); -} - -io_func* openFlatFile(const char* fileName) { - io_func* io; - - io = (io_func*) malloc(sizeof(io_func)); - io->data = fopen(fileName, "rb+"); - - if(io->data == NULL) { - perror("fopen"); - return NULL; - } - - io->read = &flatFileRead; - io->write = &flatFileWrite; - io->close = &closeFlatFile; - - return io; -} - -io_func* openFlatFileRO(const char* fileName) { - io_func* io; - - io = (io_func*) malloc(sizeof(io_func)); - io->data = fopen(fileName, "rb"); - - if(io->data == NULL) { - perror("fopen"); - return NULL; - } - - io->read = &flatFileRead; - io->write = &flatFileWrite; - io->close = &closeFlatFile; - - return io; -} + + //printf("%d %d\n", location, size); fflush(stdout); + + if(fseeko(file, location, SEEK_SET) != 0) { + perror("fseek"); + return FALSE; + } + + if(fread(buffer, size, 1, file) != 1) { + perror("fread"); + return FALSE; + } else { + return TRUE; + } +} + +static int flatFileWrite(io_func* io, off_t location, size_t size, void *buffer) { + FILE* file; + + /*int i; + + printf("write: %lld %d - ", location, size); fflush(stdout); + + for(i = 0; i < size; i++) { + printf("%x ", ((unsigned char*)buffer)[i]); + fflush(stdout); + } + printf("\n"); fflush(stdout);*/ + + if(size == 0) { + return TRUE; + } + + file = (FILE*) io->data; + + if(fseeko(file, location, SEEK_SET) != 0) { + perror("fseek"); + return FALSE; + } + + if(fwrite(buffer, size, 1, file) != 1) { + perror("fwrite"); + return FALSE; + } else { + return TRUE; + } + + return TRUE; +} + +static void closeFlatFile(io_func* io) { + FILE* file; + + file = (FILE*) io->data; + + fclose(file); + free(io); +} + +io_func* openFlatFile(const char* fileName) { + io_func* io; + + io = (io_func*) malloc(sizeof(io_func)); + io->data = fopen(fileName, "rb+"); + + if(io->data == NULL) { + perror("fopen"); + return NULL; + } + + io->read = &flatFileRead; + io->write = &flatFileWrite; + io->close = &closeFlatFile; + + return io; +} + +io_func* openFlatFileRO(const char* fileName) { + io_func* io; + + io = (io_func*) malloc(sizeof(io_func)); + io->data = fopen(fileName, "rb"); + + if(io->data == NULL) { + perror("fopen"); + return NULL; + } + + io->read = &flatFileRead; + io->write = &flatFileWrite; + io->close = &closeFlatFile; + + return io; +} diff --git a/hfs/hfs.c b/hfs/hfs.c index 6f24aa6..c05af72 100644 --- a/hfs/hfs.c +++ b/hfs/hfs.c @@ -1,298 +1,298 @@ -#include -#include -#include +#include +#include +#include #include -#include -#include "hfsplus.h" +#include +#include "hfsplus.h" #include #include "hfslib.h" -#include "abstractfile.h" - -char endianness; - - -void cmd_ls(Volume* volume, int argc, const char *argv[]) { - HFSPlusCatalogRecord* record; - char* name; - - if(argc > 1) - hfs_ls(volume, argv[1]); - else - hfs_ls(volume, "/"); } - -void cmd_cat(Volume* volume, int argc, const char *argv[]) { - HFSPlusCatalogRecord* record; +#include "abstractfile.h" + +char endianness; + + +void cmd_ls(Volume* volume, int argc, const char *argv[]) { + HFSPlusCatalogRecord* record; + char* name; + + if(argc > 1) + hfs_ls(volume, argv[1]); + else + hfs_ls(volume, "/"); } + +void cmd_cat(Volume* volume, int argc, const char *argv[]) { + HFSPlusCatalogRecord* record; AbstractFile* stdoutFile; - - record = getRecordFromPath(argv[1], volume, NULL, NULL); + + record = getRecordFromPath(argv[1], volume, NULL, NULL); stdoutFile = createAbstractFileFromFile(stdout); - - if(record != NULL) { - if(record->recordType == kHFSPlusFileRecord) - writeToFile((HFSPlusCatalogFile*)record, stdoutFile, volume); - else - printf("Not a file\n"); - } else { - printf("No such file or directory\n"); - } - + + if(record != NULL) { + if(record->recordType == kHFSPlusFileRecord) + writeToFile((HFSPlusCatalogFile*)record, stdoutFile, volume); + else + printf("Not a file\n"); + } else { + printf("No such file or directory\n"); + } + free(record); - free(stdoutFile); -} - -void cmd_extract(Volume* volume, int argc, const char *argv[]) { - HFSPlusCatalogRecord* record; - AbstractFile *outFile; - - if(argc < 3) { - printf("Not enough arguments"); - return; - } - - outFile = createAbstractFileFromFile(fopen(argv[2], "wb")); - - if(outFile == NULL) { - printf("cannot create file"); - } - - record = getRecordFromPath(argv[1], volume, NULL, NULL); - - if(record != NULL) { - if(record->recordType == kHFSPlusFileRecord) - writeToFile((HFSPlusCatalogFile*)record, outFile, volume); - else - printf("Not a file\n"); - } else { - printf("No such file or directory\n"); - } - - outFile->close(outFile); - free(record); -} - -void cmd_mv(Volume* volume, int argc, const char *argv[]) { - if(argc > 2) { - move(argv[1], argv[2], volume); - } else { - printf("Not enough arguments"); - } + free(stdoutFile); } -void cmd_symlink(Volume* volume, int argc, const char *argv[]) { - if(argc > 2) { - makeSymlink(argv[1], argv[2], volume); - } else { - printf("Not enough arguments"); - } -} - -void cmd_mkdir(Volume* volume, int argc, const char *argv[]) { - if(argc > 1) { - newFolder(argv[1], volume); - } else { - printf("Not enough arguments"); - } -} - -void cmd_add(Volume* volume, int argc, const char *argv[]) { - AbstractFile *inFile; - - if(argc < 3) { - printf("Not enough arguments"); - return; - } - - inFile = createAbstractFileFromFile(fopen(argv[1], "rb")); - - if(inFile == NULL) { - printf("file to add not found"); +void cmd_extract(Volume* volume, int argc, const char *argv[]) { + HFSPlusCatalogRecord* record; + AbstractFile *outFile; + + if(argc < 3) { + printf("Not enough arguments"); + return; + } + + outFile = createAbstractFileFromFile(fopen(argv[2], "wb")); + + if(outFile == NULL) { + printf("cannot create file"); + } + + record = getRecordFromPath(argv[1], volume, NULL, NULL); + + if(record != NULL) { + if(record->recordType == kHFSPlusFileRecord) + writeToFile((HFSPlusCatalogFile*)record, outFile, volume); + else + printf("Not a file\n"); + } else { + printf("No such file or directory\n"); + } + + outFile->close(outFile); + free(record); +} + +void cmd_mv(Volume* volume, int argc, const char *argv[]) { + if(argc > 2) { + move(argv[1], argv[2], volume); + } else { + printf("Not enough arguments"); + } +} + +void cmd_symlink(Volume* volume, int argc, const char *argv[]) { + if(argc > 2) { + makeSymlink(argv[1], argv[2], volume); + } else { + printf("Not enough arguments"); + } +} + +void cmd_mkdir(Volume* volume, int argc, const char *argv[]) { + if(argc > 1) { + newFolder(argv[1], volume); + } else { + printf("Not enough arguments"); + } +} + +void cmd_add(Volume* volume, int argc, const char *argv[]) { + AbstractFile *inFile; + + if(argc < 3) { + printf("Not enough arguments"); + return; + } + + inFile = createAbstractFileFromFile(fopen(argv[1], "rb")); + + if(inFile == NULL) { + printf("file to add not found"); } - add_hfs(volume, inFile, argv[2]); -} - -void cmd_rm(Volume* volume, int argc, const char *argv[]) { - if(argc > 1) { - removeFile(argv[1], volume); - } else { - printf("Not enough arguments"); - } -} - -void cmd_chmod(Volume* volume, int argc, const char *argv[]) { - int mode; - - if(argc > 2) { - sscanf(argv[1], "%o", &mode); - chmodFile(argv[2], mode, volume); - } else { - printf("Not enough arguments"); - } -} - -void cmd_extractall(Volume* volume, int argc, const char *argv[]) { - HFSPlusCatalogRecord* record; - char cwd[1024]; - char* name; - - ASSERT(getcwd(cwd, 1024) != NULL, "cannot get current working directory"); - - if(argc > 1) - record = getRecordFromPath(argv[1], volume, &name, NULL); - else - record = getRecordFromPath("/", volume, &name, NULL); - - if(argc > 2) { - ASSERT(chdir(argv[2]) == 0, "chdir"); - } - - if(record != NULL) { - if(record->recordType == kHFSPlusFolderRecord) - extractAllInFolder(((HFSPlusCatalogFolder*)record)->folderID, volume); - else - printf("Not a folder\n"); - } else { - printf("No such file or directory\n"); - } - free(record); - - ASSERT(chdir(cwd) == 0, "chdir"); -} - - -void cmd_rmall(Volume* volume, int argc, const char *argv[]) { - HFSPlusCatalogRecord* record; - char* name; - char initPath[1024]; - int lastCharOfPath; - - if(argc > 1) { - record = getRecordFromPath(argv[1], volume, &name, NULL); - strcpy(initPath, argv[1]); - lastCharOfPath = strlen(argv[1]) - 1; - if(argv[1][lastCharOfPath] != '/') { - initPath[lastCharOfPath + 1] = '/'; - initPath[lastCharOfPath + 2] = '\0'; - } - } else { - record = getRecordFromPath("/", volume, &name, NULL); - initPath[0] = '/'; - initPath[1] = '\0'; - } - - if(record != NULL) { - if(record->recordType == kHFSPlusFolderRecord) { - removeAllInFolder(((HFSPlusCatalogFolder*)record)->folderID, volume, initPath); - } else { - printf("Not a folder\n"); - } - } else { - printf("No such file or directory\n"); - } - free(record); -} - -void cmd_addall(Volume* volume, int argc, const char *argv[]) { - if(argc < 2) { - printf("Not enough arguments"); - return; + add_hfs(volume, inFile, argv[2]); +} + +void cmd_rm(Volume* volume, int argc, const char *argv[]) { + if(argc > 1) { + removeFile(argv[1], volume); + } else { + printf("Not enough arguments"); + } +} + +void cmd_chmod(Volume* volume, int argc, const char *argv[]) { + int mode; + + if(argc > 2) { + sscanf(argv[1], "%o", &mode); + chmodFile(argv[2], mode, volume); + } else { + printf("Not enough arguments"); + } +} + +void cmd_extractall(Volume* volume, int argc, const char *argv[]) { + HFSPlusCatalogRecord* record; + char cwd[1024]; + char* name; + + ASSERT(getcwd(cwd, 1024) != NULL, "cannot get current working directory"); + + if(argc > 1) + record = getRecordFromPath(argv[1], volume, &name, NULL); + else + record = getRecordFromPath("/", volume, &name, NULL); + + if(argc > 2) { + ASSERT(chdir(argv[2]) == 0, "chdir"); } - if(argc > 2) { - addall_hfs(volume, argv[1], argv[2]); - } else { - addall_hfs(volume, argv[1], "/"); - } -} - -void cmd_grow(Volume* volume, int argc, const char *argv[]) { - uint64_t newSize; - - if(argc < 2) { - printf("Not enough arguments\n"); - return; - } - - newSize = 0; + if(record != NULL) { + if(record->recordType == kHFSPlusFolderRecord) + extractAllInFolder(((HFSPlusCatalogFolder*)record)->folderID, volume); + else + printf("Not a folder\n"); + } else { + printf("No such file or directory\n"); + } + free(record); + + ASSERT(chdir(cwd) == 0, "chdir"); +} + + +void cmd_rmall(Volume* volume, int argc, const char *argv[]) { + HFSPlusCatalogRecord* record; + char* name; + char initPath[1024]; + int lastCharOfPath; + + if(argc > 1) { + record = getRecordFromPath(argv[1], volume, &name, NULL); + strcpy(initPath, argv[1]); + lastCharOfPath = strlen(argv[1]) - 1; + if(argv[1][lastCharOfPath] != '/') { + initPath[lastCharOfPath + 1] = '/'; + initPath[lastCharOfPath + 2] = '\0'; + } + } else { + record = getRecordFromPath("/", volume, &name, NULL); + initPath[0] = '/'; + initPath[1] = '\0'; + } + + if(record != NULL) { + if(record->recordType == kHFSPlusFolderRecord) { + removeAllInFolder(((HFSPlusCatalogFolder*)record)->folderID, volume, initPath); + } else { + printf("Not a folder\n"); + } + } else { + printf("No such file or directory\n"); + } + free(record); +} + +void cmd_addall(Volume* volume, int argc, const char *argv[]) { + if(argc < 2) { + printf("Not enough arguments"); + return; + } + + if(argc > 2) { + addall_hfs(volume, argv[1], argv[2]); + } else { + addall_hfs(volume, argv[1], "/"); + } +} + +void cmd_grow(Volume* volume, int argc, const char *argv[]) { + uint64_t newSize; + + if(argc < 2) { + printf("Not enough arguments\n"); + return; + } + + newSize = 0; sscanf(argv[1], "%lld", &newSize); grow_hfs(volume, newSize); - printf("grew volume: %lld\n", newSize); + printf("grew volume: %lld\n", newSize); } -void TestByteOrder() -{ - short int word = 0x0001; - char *byte = (char *) &word; - endianness = byte[0] ? IS_LITTLE_ENDIAN : IS_BIG_ENDIAN; -} - - -int main(int argc, const char *argv[]) { - io_func* io; - Volume* volume; - - TestByteOrder(); - - if(argc < 3) { - printf("usage: %s \n", argv[0]); - return 0; - } - - io = openFlatFile(argv[1]); - if(io == NULL) { - fprintf(stderr, "error: Cannot open image-file.\n"); - return 1; - } - - volume = openVolume(io); - if(volume == NULL) { - fprintf(stderr, "error: Cannot open volume.\n"); - CLOSE(io); - return 1; - } - - if(argc > 1) { - if(strcmp(argv[2], "ls") == 0) { - cmd_ls(volume, argc - 2, argv + 2); - } else if(strcmp(argv[2], "cat") == 0) { - cmd_cat(volume, argc - 2, argv + 2); - } else if(strcmp(argv[2], "mv") == 0) { - cmd_mv(volume, argc - 2, argv + 2); - } else if(strcmp(argv[2], "symlink") == 0) { - cmd_symlink(volume, argc - 2, argv + 2); - } else if(strcmp(argv[2], "mkdir") == 0) { - cmd_mkdir(volume, argc - 2, argv + 2); - } else if(strcmp(argv[2], "add") == 0) { - cmd_add(volume, argc - 2, argv + 2); - } else if(strcmp(argv[2], "rm") == 0) { - cmd_rm(volume, argc - 2, argv + 2); - } else if(strcmp(argv[2], "chmod") == 0) { - cmd_chmod(volume, argc - 2, argv + 2); - } else if(strcmp(argv[2], "extract") == 0) { - cmd_extract(volume, argc - 2, argv + 2); - } else if(strcmp(argv[2], "extractall") == 0) { - cmd_extractall(volume, argc - 2, argv + 2); - } else if(strcmp(argv[2], "rmall") == 0) { - cmd_rmall(volume, argc - 2, argv + 2); - } else if(strcmp(argv[2], "addall") == 0) { - cmd_addall(volume, argc - 2, argv + 2); - } else if(strcmp(argv[2], "grow") == 0) { - cmd_grow(volume, argc - 2, argv + 2); +void TestByteOrder() +{ + short int word = 0x0001; + char *byte = (char *) &word; + endianness = byte[0] ? IS_LITTLE_ENDIAN : IS_BIG_ENDIAN; +} + + +int main(int argc, const char *argv[]) { + io_func* io; + Volume* volume; + + TestByteOrder(); + + if(argc < 3) { + printf("usage: %s \n", argv[0]); + return 0; + } + + io = openFlatFile(argv[1]); + if(io == NULL) { + fprintf(stderr, "error: Cannot open image-file.\n"); + return 1; + } + + volume = openVolume(io); + if(volume == NULL) { + fprintf(stderr, "error: Cannot open volume.\n"); + CLOSE(io); + return 1; + } + + if(argc > 1) { + if(strcmp(argv[2], "ls") == 0) { + cmd_ls(volume, argc - 2, argv + 2); + } else if(strcmp(argv[2], "cat") == 0) { + cmd_cat(volume, argc - 2, argv + 2); + } else if(strcmp(argv[2], "mv") == 0) { + cmd_mv(volume, argc - 2, argv + 2); + } else if(strcmp(argv[2], "symlink") == 0) { + cmd_symlink(volume, argc - 2, argv + 2); + } else if(strcmp(argv[2], "mkdir") == 0) { + cmd_mkdir(volume, argc - 2, argv + 2); + } else if(strcmp(argv[2], "add") == 0) { + cmd_add(volume, argc - 2, argv + 2); + } else if(strcmp(argv[2], "rm") == 0) { + cmd_rm(volume, argc - 2, argv + 2); + } else if(strcmp(argv[2], "chmod") == 0) { + cmd_chmod(volume, argc - 2, argv + 2); + } else if(strcmp(argv[2], "extract") == 0) { + cmd_extract(volume, argc - 2, argv + 2); + } else if(strcmp(argv[2], "extractall") == 0) { + cmd_extractall(volume, argc - 2, argv + 2); + } else if(strcmp(argv[2], "rmall") == 0) { + cmd_rmall(volume, argc - 2, argv + 2); + } else if(strcmp(argv[2], "addall") == 0) { + cmd_addall(volume, argc - 2, argv + 2); + } else if(strcmp(argv[2], "grow") == 0) { + cmd_grow(volume, argc - 2, argv + 2); } else if(strcmp(argv[2], "debug") == 0) { if(argc > 3 && argv[3] == "verbose") { debugBTree(volume->catalogTree, TRUE); } else { debugBTree(volume->catalogTree, FALSE); } - } - } - - closeVolume(volume); - CLOSE(io); - - return 0; -} + } + } + + closeVolume(volume); + CLOSE(io); + + return 0; +} diff --git a/hfs/hfslib.c b/hfs/hfslib.c index 0fd002b..d2b72bb 100644 --- a/hfs/hfslib.c +++ b/hfs/hfslib.c @@ -8,551 +8,551 @@ #include "abstractfile.h" #include -#define BUFSIZE 1024*1024 - -void writeToFile(HFSPlusCatalogFile* file, AbstractFile* output, Volume* volume) { - unsigned char buffer[BUFSIZE]; - io_func* io; - off_t curPosition; - size_t bytesLeft; - - io = openRawFile(file->fileID, &file->dataFork, (HFSPlusCatalogRecord*)file, volume); - if(io == NULL) { - panic("error opening file"); - return; - } - - curPosition = 0; - bytesLeft = file->dataFork.logicalSize; - - while(bytesLeft > 0) { - if(bytesLeft > BUFSIZE) { - if(!READ(io, curPosition, BUFSIZE, buffer)) { - panic("error reading"); - } - if(output->write(output, buffer, BUFSIZE) != BUFSIZE) { - panic("error writing"); - } - curPosition += BUFSIZE; - bytesLeft -= BUFSIZE; - } else { - if(!READ(io, curPosition, bytesLeft, buffer)) { - panic("error reading"); - } - if(output->write(output, buffer, bytesLeft) != bytesLeft) { - panic("error writing"); - } - curPosition += bytesLeft; - bytesLeft -= bytesLeft; - } - } - CLOSE(io); -} - -void writeToHFSFile(HFSPlusCatalogFile* file, AbstractFile* input, Volume* volume) { - unsigned char buffer[BUFSIZE]; - io_func* io; - off_t curPosition; - off_t bytesLeft; - - bytesLeft = input->getLength(input); - - io = openRawFile(file->fileID, &file->dataFork, (HFSPlusCatalogRecord*)file, volume); - if(io == NULL) { - panic("error opening file"); - return; - } - - curPosition = 0; - - allocate((RawFile*)io->data, bytesLeft); - - while(bytesLeft > 0) { - if(bytesLeft > BUFSIZE) { - if(input->read(input, buffer, BUFSIZE) != BUFSIZE) { - panic("error reading"); - } - if(!WRITE(io, curPosition, BUFSIZE, buffer)) { - panic("error writing"); - } - curPosition += BUFSIZE; - bytesLeft -= BUFSIZE; - } else { - if(input->read(input, buffer, (size_t)bytesLeft) != (size_t)bytesLeft) { - panic("error reading"); - } - if(!WRITE(io, curPosition, (size_t)bytesLeft, buffer)) { - panic("error reading"); - } - curPosition += bytesLeft; - bytesLeft -= bytesLeft; - } - } - - CLOSE(io); -} - -void get_hfs(Volume* volume, const char* inFileName, AbstractFile* output) { - HFSPlusCatalogRecord* record; - - record = getRecordFromPath(inFileName, volume, NULL, NULL); - - if(record != NULL) { - if(record->recordType == kHFSPlusFileRecord) - writeToFile((HFSPlusCatalogFile*)record, output, volume); - else { - printf("Not a file\n"); - exit(0); - } - } else { - printf("No such file or directory\n"); - exit(0); - } - - free(record); -} - -int add_hfs(Volume* volume, AbstractFile* inFile, const char* outFileName) { - HFSPlusCatalogRecord* record; - int ret; - - record = getRecordFromPath(outFileName, volume, NULL, NULL); - - if(record != NULL) { - if(record->recordType == kHFSPlusFileRecord) { - writeToHFSFile((HFSPlusCatalogFile*)record, inFile, volume); - ret = TRUE; - } else { - printf("Not a file\n"); - exit(0); - } - } else { - if(newFile(outFileName, volume)) { - record = getRecordFromPath(outFileName, volume, NULL, NULL); - writeToHFSFile((HFSPlusCatalogFile*)record, inFile, volume); - ret = TRUE; - } else { - inFile->close(inFile); - ret = FALSE; - } - } - - inFile->close(inFile); - if(record != NULL) { - free(record); - } - - return ret; -} - -void grow_hfs(Volume* volume, uint64_t newSize) { - uint32_t newBlocks; - uint32_t blocksToGrow; - uint64_t newMapSize; - uint64_t i; - unsigned char zero; - - zero = 0; - - newBlocks = newSize / volume->volumeHeader->blockSize; +#define BUFSIZE 1024*1024 + +void writeToFile(HFSPlusCatalogFile* file, AbstractFile* output, Volume* volume) { + unsigned char buffer[BUFSIZE]; + io_func* io; + off_t curPosition; + size_t bytesLeft; + + io = openRawFile(file->fileID, &file->dataFork, (HFSPlusCatalogRecord*)file, volume); + if(io == NULL) { + panic("error opening file"); + return; + } + + curPosition = 0; + bytesLeft = file->dataFork.logicalSize; + + while(bytesLeft > 0) { + if(bytesLeft > BUFSIZE) { + if(!READ(io, curPosition, BUFSIZE, buffer)) { + panic("error reading"); + } + if(output->write(output, buffer, BUFSIZE) != BUFSIZE) { + panic("error writing"); + } + curPosition += BUFSIZE; + bytesLeft -= BUFSIZE; + } else { + if(!READ(io, curPosition, bytesLeft, buffer)) { + panic("error reading"); + } + if(output->write(output, buffer, bytesLeft) != bytesLeft) { + panic("error writing"); + } + curPosition += bytesLeft; + bytesLeft -= bytesLeft; + } + } + CLOSE(io); +} + +void writeToHFSFile(HFSPlusCatalogFile* file, AbstractFile* input, Volume* volume) { + unsigned char buffer[BUFSIZE]; + io_func* io; + off_t curPosition; + off_t bytesLeft; + + bytesLeft = input->getLength(input); + + io = openRawFile(file->fileID, &file->dataFork, (HFSPlusCatalogRecord*)file, volume); + if(io == NULL) { + panic("error opening file"); + return; + } + + curPosition = 0; + + allocate((RawFile*)io->data, bytesLeft); + + while(bytesLeft > 0) { + if(bytesLeft > BUFSIZE) { + if(input->read(input, buffer, BUFSIZE) != BUFSIZE) { + panic("error reading"); + } + if(!WRITE(io, curPosition, BUFSIZE, buffer)) { + panic("error writing"); + } + curPosition += BUFSIZE; + bytesLeft -= BUFSIZE; + } else { + if(input->read(input, buffer, (size_t)bytesLeft) != (size_t)bytesLeft) { + panic("error reading"); + } + if(!WRITE(io, curPosition, (size_t)bytesLeft, buffer)) { + panic("error reading"); + } + curPosition += bytesLeft; + bytesLeft -= bytesLeft; + } + } + + CLOSE(io); +} + +void get_hfs(Volume* volume, const char* inFileName, AbstractFile* output) { + HFSPlusCatalogRecord* record; + + record = getRecordFromPath(inFileName, volume, NULL, NULL); + + if(record != NULL) { + if(record->recordType == kHFSPlusFileRecord) + writeToFile((HFSPlusCatalogFile*)record, output, volume); + else { + printf("Not a file\n"); + exit(0); + } + } else { + printf("No such file or directory\n"); + exit(0); + } + + free(record); +} + +int add_hfs(Volume* volume, AbstractFile* inFile, const char* outFileName) { + HFSPlusCatalogRecord* record; + int ret; + + record = getRecordFromPath(outFileName, volume, NULL, NULL); + + if(record != NULL) { + if(record->recordType == kHFSPlusFileRecord) { + writeToHFSFile((HFSPlusCatalogFile*)record, inFile, volume); + ret = TRUE; + } else { + printf("Not a file\n"); + exit(0); + } + } else { + if(newFile(outFileName, volume)) { + record = getRecordFromPath(outFileName, volume, NULL, NULL); + writeToHFSFile((HFSPlusCatalogFile*)record, inFile, volume); + ret = TRUE; + } else { + inFile->close(inFile); + ret = FALSE; + } + } + + inFile->close(inFile); + if(record != NULL) { + free(record); + } + + return ret; +} + +void grow_hfs(Volume* volume, uint64_t newSize) { + uint32_t newBlocks; + uint32_t blocksToGrow; + uint64_t newMapSize; + uint64_t i; + unsigned char zero; + + zero = 0; + + newBlocks = newSize / volume->volumeHeader->blockSize; + + if(newBlocks <= volume->volumeHeader->totalBlocks) { + printf("Cannot shrink volume\n"); + return; + } + + blocksToGrow = newBlocks - volume->volumeHeader->totalBlocks; + newMapSize = newBlocks / 8; + + if(volume->volumeHeader->allocationFile.logicalSize < newMapSize) { + if(volume->volumeHeader->freeBlocks + < ((newMapSize - volume->volumeHeader->allocationFile.logicalSize) / volume->volumeHeader->blockSize)) { + printf("Not enough room to allocate new allocation map blocks\n"); + exit(0); + } + + allocate((RawFile*) (volume->allocationFile->data), newMapSize); + } + + /* unreserve last block */ + setBlockUsed(volume, volume->volumeHeader->totalBlocks - 1, 0); + /* don't need to increment freeBlocks because we will allocate another alternate volume header later on */ + + /* "unallocate" the new blocks */ + for(i = ((volume->volumeHeader->totalBlocks / 8) + 1); i < newMapSize; i++) { + ASSERT(WRITE(volume->allocationFile, i, 1, &zero), "WRITE"); + } + + /* grow backing store size */ + ASSERT(WRITE(volume->image, newSize - 1, 1, &zero), "WRITE"); + + /* write new volume information */ + volume->volumeHeader->totalBlocks = newBlocks; + volume->volumeHeader->freeBlocks += blocksToGrow; + + /* reserve last block */ + setBlockUsed(volume, volume->volumeHeader->totalBlocks - 1, 1); - if(newBlocks <= volume->volumeHeader->totalBlocks) { - printf("Cannot shrink volume\n"); - return; - } - - blocksToGrow = newBlocks - volume->volumeHeader->totalBlocks; - newMapSize = newBlocks / 8; - - if(volume->volumeHeader->allocationFile.logicalSize < newMapSize) { - if(volume->volumeHeader->freeBlocks - < ((newMapSize - volume->volumeHeader->allocationFile.logicalSize) / volume->volumeHeader->blockSize)) { - printf("Not enough room to allocate new allocation map blocks\n"); - exit(0); - } - - allocate((RawFile*) (volume->allocationFile->data), newMapSize); - } - - /* unreserve last block */ - setBlockUsed(volume, volume->volumeHeader->totalBlocks - 1, 0); - /* don't need to increment freeBlocks because we will allocate another alternate volume header later on */ - - /* "unallocate" the new blocks */ - for(i = ((volume->volumeHeader->totalBlocks / 8) + 1); i < newMapSize; i++) { - ASSERT(WRITE(volume->allocationFile, i, 1, &zero), "WRITE"); - } - - /* grow backing store size */ - ASSERT(WRITE(volume->image, newSize - 1, 1, &zero), "WRITE"); - - /* write new volume information */ - volume->volumeHeader->totalBlocks = newBlocks; - volume->volumeHeader->freeBlocks += blocksToGrow; - - /* reserve last block */ - setBlockUsed(volume, volume->volumeHeader->totalBlocks - 1, 1); - updateVolume(volume); } -void removeAllInFolder(HFSCatalogNodeID folderID, Volume* volume, const char* parentName) { - CatalogRecordList* list; - CatalogRecordList* theList; - char fullName[1024]; - char* name; - char* pathComponent; - int pathLen; - char isRoot; - - HFSPlusCatalogFolder* folder; - theList = list = getFolderContents(folderID, volume); - - strcpy(fullName, parentName); - pathComponent = fullName + strlen(fullName); - - isRoot = FALSE; - if(strcmp(fullName, "/") == 0) { - isRoot = TRUE; - } - - while(list != NULL) { - name = unicodeToAscii(&list->name); - if(isRoot && (name[0] == '\0' || strncmp(name, ".HFS+ Private Directory Data", sizeof(".HFS+ Private Directory Data") - 1) == 0)) { - free(name); - list = list->next; - continue; - } - - strcpy(pathComponent, name); - pathLen = strlen(fullName); - - if(list->record->recordType == kHFSPlusFolderRecord) { - folder = (HFSPlusCatalogFolder*)list->record; - fullName[pathLen] = '/'; - fullName[pathLen + 1] = '\0'; - removeAllInFolder(folder->folderID, volume, fullName); - } else { - printf("%s\n", fullName); - removeFile(fullName, volume); - } - - free(name); - list = list->next; - } - - releaseCatalogRecordList(theList); - - if(!isRoot) { - *(pathComponent - 1) = '\0'; - printf("%s\n", fullName); - removeFile(fullName, volume); - } -} - +void removeAllInFolder(HFSCatalogNodeID folderID, Volume* volume, const char* parentName) { + CatalogRecordList* list; + CatalogRecordList* theList; + char fullName[1024]; + char* name; + char* pathComponent; + int pathLen; + char isRoot; + + HFSPlusCatalogFolder* folder; + theList = list = getFolderContents(folderID, volume); + + strcpy(fullName, parentName); + pathComponent = fullName + strlen(fullName); + + isRoot = FALSE; + if(strcmp(fullName, "/") == 0) { + isRoot = TRUE; + } + + while(list != NULL) { + name = unicodeToAscii(&list->name); + if(isRoot && (name[0] == '\0' || strncmp(name, ".HFS+ Private Directory Data", sizeof(".HFS+ Private Directory Data") - 1) == 0)) { + free(name); + list = list->next; + continue; + } + + strcpy(pathComponent, name); + pathLen = strlen(fullName); + + if(list->record->recordType == kHFSPlusFolderRecord) { + folder = (HFSPlusCatalogFolder*)list->record; + fullName[pathLen] = '/'; + fullName[pathLen + 1] = '\0'; + removeAllInFolder(folder->folderID, volume, fullName); + } else { + printf("%s\n", fullName); + removeFile(fullName, volume); + } + + free(name); + list = list->next; + } + + releaseCatalogRecordList(theList); + + if(!isRoot) { + *(pathComponent - 1) = '\0'; + printf("%s\n", fullName); + removeFile(fullName, volume); + } +} -void addAllInFolder(HFSCatalogNodeID folderID, Volume* volume, const char* parentName) { - CatalogRecordList* list; - CatalogRecordList* theList; - char cwd[1024]; - char fullName[1024]; - char testBuffer[1024]; - char* pathComponent; - int pathLen; - - char* name; - - DIR* dir; - DIR* tmp; - - HFSCatalogNodeID cnid; - - struct dirent* ent; - - AbstractFile* file; - HFSPlusCatalogFile* outFile; - - strcpy(fullName, parentName); - pathComponent = fullName + strlen(fullName); - - ASSERT(getcwd(cwd, 1024) != NULL, "cannot get current working directory"); - - theList = list = getFolderContents(folderID, volume); - - ASSERT((dir = opendir(cwd)) != NULL, "opendir"); - - while((ent = readdir(dir)) != NULL) { - if(ent->d_name[0] == '.' && (ent->d_name[1] == '\0' || (ent->d_name[1] == '.' && ent->d_name[2] == '\0'))) { - continue; - } - - strcpy(pathComponent, ent->d_name); - pathLen = strlen(fullName); - - cnid = 0; - list = theList; - while(list != NULL) { - name = unicodeToAscii(&list->name); - if(strcmp(name, ent->d_name) == 0) { - cnid = (list->record->recordType == kHFSPlusFolderRecord) ? (((HFSPlusCatalogFolder*)list->record)->folderID) - : (((HFSPlusCatalogFile*)list->record)->fileID); - free(name); - break; - } - free(name); - list = list->next; - } - - if((tmp = opendir(ent->d_name)) != NULL) { - closedir(tmp); - printf("folder: %s\n", fullName); fflush(stdout); - - if(cnid == 0) { - cnid = newFolder(fullName, volume); - } - - fullName[pathLen] = '/'; - fullName[pathLen + 1] = '\0'; - ASSERT(chdir(ent->d_name) == 0, "chdir"); - addAllInFolder(cnid, volume, fullName); - ASSERT(chdir(cwd) == 0, "chdir"); - } else { - printf("file: %s\n", fullName); fflush(stdout); - if(cnid == 0) { - cnid = newFile(fullName, volume); - } - file = createAbstractFileFromFile(fopen(ent->d_name, "rb")); - ASSERT(file != NULL, "fopen"); - outFile = (HFSPlusCatalogFile*)getRecordByCNID(cnid, volume); - writeToHFSFile(outFile, file, volume); - file->close(file); - free(outFile); - - if(strncmp(fullName, "/Applications/", sizeof("/Applications/") - 1) == 0) { - testBuffer[0] = '\0'; - strcpy(testBuffer, "/Applications/"); - strcat(testBuffer, ent->d_name); - strcat(testBuffer, ".app/"); - strcat(testBuffer, ent->d_name); - if(strcmp(testBuffer, fullName) == 0) { + +void addAllInFolder(HFSCatalogNodeID folderID, Volume* volume, const char* parentName) { + CatalogRecordList* list; + CatalogRecordList* theList; + char cwd[1024]; + char fullName[1024]; + char testBuffer[1024]; + char* pathComponent; + int pathLen; + + char* name; + + DIR* dir; + DIR* tmp; + + HFSCatalogNodeID cnid; + + struct dirent* ent; + + AbstractFile* file; + HFSPlusCatalogFile* outFile; + + strcpy(fullName, parentName); + pathComponent = fullName + strlen(fullName); + + ASSERT(getcwd(cwd, 1024) != NULL, "cannot get current working directory"); + + theList = list = getFolderContents(folderID, volume); + + ASSERT((dir = opendir(cwd)) != NULL, "opendir"); + + while((ent = readdir(dir)) != NULL) { + if(ent->d_name[0] == '.' && (ent->d_name[1] == '\0' || (ent->d_name[1] == '.' && ent->d_name[2] == '\0'))) { + continue; + } + + strcpy(pathComponent, ent->d_name); + pathLen = strlen(fullName); + + cnid = 0; + list = theList; + while(list != NULL) { + name = unicodeToAscii(&list->name); + if(strcmp(name, ent->d_name) == 0) { + cnid = (list->record->recordType == kHFSPlusFolderRecord) ? (((HFSPlusCatalogFolder*)list->record)->folderID) + : (((HFSPlusCatalogFile*)list->record)->fileID); + free(name); + break; + } + free(name); + list = list->next; + } + + if((tmp = opendir(ent->d_name)) != NULL) { + closedir(tmp); + printf("folder: %s\n", fullName); fflush(stdout); + + if(cnid == 0) { + cnid = newFolder(fullName, volume); + } + + fullName[pathLen] = '/'; + fullName[pathLen + 1] = '\0'; + ASSERT(chdir(ent->d_name) == 0, "chdir"); + addAllInFolder(cnid, volume, fullName); + ASSERT(chdir(cwd) == 0, "chdir"); + } else { + printf("file: %s\n", fullName); fflush(stdout); + if(cnid == 0) { + cnid = newFile(fullName, volume); + } + file = createAbstractFileFromFile(fopen(ent->d_name, "rb")); + ASSERT(file != NULL, "fopen"); + outFile = (HFSPlusCatalogFile*)getRecordByCNID(cnid, volume); + writeToHFSFile(outFile, file, volume); + file->close(file); + free(outFile); + + if(strncmp(fullName, "/Applications/", sizeof("/Applications/") - 1) == 0) { + testBuffer[0] = '\0'; + strcpy(testBuffer, "/Applications/"); + strcat(testBuffer, ent->d_name); + strcat(testBuffer, ".app/"); + strcat(testBuffer, ent->d_name); + if(strcmp(testBuffer, fullName) == 0) { if(strcmp(ent->d_name, "Installer") == 0 || strcmp(ent->d_name, "BootNeuter") == 0 - ) { - printf("Giving setuid permissions to %s...\n", fullName); fflush(stdout); - chmodFile(fullName, 04755, volume); - } else { - printf("Giving permissions to %s\n", fullName); fflush(stdout); - chmodFile(fullName, 0755, volume); - } - } + ) { + printf("Giving setuid permissions to %s...\n", fullName); fflush(stdout); + chmodFile(fullName, 04755, volume); + } else { + printf("Giving permissions to %s\n", fullName); fflush(stdout); + chmodFile(fullName, 0755, volume); + } + } } else if(strncmp(fullName, "/bin/", sizeof("/bin/") - 1) == 0 - || strncmp(fullName, "/Applications/BootNeuter.app/bin/", sizeof("/Applications/BootNeuter.app/bin/") - 1) == 0 - || strncmp(fullName, "/sbin/", sizeof("/sbin/") - 1) == 0 - || strncmp(fullName, "/usr/sbin/", sizeof("/usr/sbin/") - 1) == 0 - || strncmp(fullName, "/usr/bin/", sizeof("/usr/bin/") - 1) == 0 - || strncmp(fullName, "/usr/libexec/", sizeof("/usr/libexec/") - 1) == 0 - || strncmp(fullName, "/usr/local/bin/", sizeof("/usr/local/bin/") - 1) == 0 - || strncmp(fullName, "/usr/local/sbin/", sizeof("/usr/local/sbin/") - 1) == 0 - || strncmp(fullName, "/usr/local/libexec/", sizeof("/usr/local/libexec/") - 1) == 0 - ) { - chmodFile(fullName, 0755, volume); - printf("Giving permissions to %s\n", fullName); fflush(stdout); - } - } - } - - closedir(dir); - - releaseCatalogRecordList(theList); + || strncmp(fullName, "/Applications/BootNeuter.app/bin/", sizeof("/Applications/BootNeuter.app/bin/") - 1) == 0 + || strncmp(fullName, "/sbin/", sizeof("/sbin/") - 1) == 0 + || strncmp(fullName, "/usr/sbin/", sizeof("/usr/sbin/") - 1) == 0 + || strncmp(fullName, "/usr/bin/", sizeof("/usr/bin/") - 1) == 0 + || strncmp(fullName, "/usr/libexec/", sizeof("/usr/libexec/") - 1) == 0 + || strncmp(fullName, "/usr/local/bin/", sizeof("/usr/local/bin/") - 1) == 0 + || strncmp(fullName, "/usr/local/sbin/", sizeof("/usr/local/sbin/") - 1) == 0 + || strncmp(fullName, "/usr/local/libexec/", sizeof("/usr/local/libexec/") - 1) == 0 + ) { + chmodFile(fullName, 0755, volume); + printf("Giving permissions to %s\n", fullName); fflush(stdout); + } + } + } + + closedir(dir); + + releaseCatalogRecordList(theList); } -void extractAllInFolder(HFSCatalogNodeID folderID, Volume* volume) { - CatalogRecordList* list; - CatalogRecordList* theList; - char cwd[1024]; - char* name; - HFSPlusCatalogFolder* folder; - HFSPlusCatalogFile* file; - AbstractFile* outFile; - struct stat status; - - ASSERT(getcwd(cwd, 1024) != NULL, "cannot get current working directory"); - - theList = list = getFolderContents(folderID, volume); - - while(list != NULL) { - name = unicodeToAscii(&list->name); - if(strncmp(name, ".HFS+ Private Directory Data", sizeof(".HFS+ Private Directory Data") - 1) == 0 || name[0] == '\0') { - free(name); - list = list->next; - continue; - } - - if(list->record->recordType == kHFSPlusFolderRecord) { - folder = (HFSPlusCatalogFolder*)list->record; - printf("folder: %s\n", name); - if(stat(name, &status) != 0) { - ASSERT(mkdir(name, 0755) == 0, "mkdir"); - } - ASSERT(chdir(name) == 0, "chdir"); - extractAllInFolder(folder->folderID, volume); - ASSERT(chdir(cwd) == 0, "chdir"); - } else if(list->record->recordType == kHFSPlusFileRecord) { - printf("file: %s\n", name); - file = (HFSPlusCatalogFile*)list->record; - outFile = createAbstractFileFromFile(fopen(name, "wb")); - if(outFile != NULL) { - writeToFile(file, outFile, volume); - outFile->close(outFile); - } else { - printf("WARNING: cannot fopen %s\n", name); - } - } - - free(name); - list = list->next; - } - releaseCatalogRecordList(theList); -} - - -void addall_hfs(Volume* volume, const char* dirToMerge, const char* dest) { - HFSPlusCatalogRecord* record; - char* name; - char cwd[1024]; - char initPath[1024]; - int lastCharOfPath; - - ASSERT(getcwd(cwd, 1024) != NULL, "cannot get current working directory"); - - if(chdir(dirToMerge) != 0) { - printf("Cannot open that directory: %s\n", dirToMerge); - exit(0); - } - - record = getRecordFromPath(dest, volume, &name, NULL); - strcpy(initPath, dest); - lastCharOfPath = strlen(dest) - 1; - if(dest[lastCharOfPath] != '/') { - initPath[lastCharOfPath + 1] = '/'; - initPath[lastCharOfPath + 2] = '\0'; - } - - if(record != NULL) { - if(record->recordType == kHFSPlusFolderRecord) - addAllInFolder(((HFSPlusCatalogFolder*)record)->folderID, volume, initPath); - else { - printf("Not a folder\n"); - exit(0); - } - } else { - printf("No such file or directory\n"); - exit(0); - } - - ASSERT(chdir(cwd) == 0, "chdir"); - free(record); - -} -int copyAcrossVolumes(Volume* volume1, Volume* volume2, char* path1, char* path2) { - void* buffer; - size_t bufferSize; - AbstractFile* tmpFile; - int ret; - - buffer = malloc(1); - bufferSize = 0; - tmpFile = createAbstractFileFromMemoryFile((void**)&buffer, &bufferSize); - - printf("retrieving... "); fflush(stdout); - get_hfs(volume1, path1, tmpFile); - tmpFile->seek(tmpFile, 0); - printf("writing (%lld)... ", tmpFile->getLength(tmpFile)); fflush(stdout); - ret = add_hfs(volume2, tmpFile, path2); - printf("done\n"); - - free(buffer); - - return ret; -} +void extractAllInFolder(HFSCatalogNodeID folderID, Volume* volume) { + CatalogRecordList* list; + CatalogRecordList* theList; + char cwd[1024]; + char* name; + HFSPlusCatalogFolder* folder; + HFSPlusCatalogFile* file; + AbstractFile* outFile; + struct stat status; + + ASSERT(getcwd(cwd, 1024) != NULL, "cannot get current working directory"); + + theList = list = getFolderContents(folderID, volume); + + while(list != NULL) { + name = unicodeToAscii(&list->name); + if(strncmp(name, ".HFS+ Private Directory Data", sizeof(".HFS+ Private Directory Data") - 1) == 0 || name[0] == '\0') { + free(name); + list = list->next; + continue; + } + + if(list->record->recordType == kHFSPlusFolderRecord) { + folder = (HFSPlusCatalogFolder*)list->record; + printf("folder: %s\n", name); + if(stat(name, &status) != 0) { + ASSERT(mkdir(name, 0755) == 0, "mkdir"); + } + ASSERT(chdir(name) == 0, "chdir"); + extractAllInFolder(folder->folderID, volume); + ASSERT(chdir(cwd) == 0, "chdir"); + } else if(list->record->recordType == kHFSPlusFileRecord) { + printf("file: %s\n", name); + file = (HFSPlusCatalogFile*)list->record; + outFile = createAbstractFileFromFile(fopen(name, "wb")); + if(outFile != NULL) { + writeToFile(file, outFile, volume); + outFile->close(outFile); + } else { + printf("WARNING: cannot fopen %s\n", name); + } + } + + free(name); + list = list->next; + } + releaseCatalogRecordList(theList); +} -void displayFolder(HFSCatalogNodeID folderID, Volume* volume) { - CatalogRecordList* list; - CatalogRecordList* theList; - HFSPlusCatalogFolder* folder; - HFSPlusCatalogFile* file; - time_t fileTime; - struct tm *date; - - theList = list = getFolderContents(folderID, volume); - - while(list != NULL) { - if(list->record->recordType == kHFSPlusFolderRecord) { - folder = (HFSPlusCatalogFolder*)list->record; - printf("%06o ", folder->permissions.fileMode); - printf("%3d ", folder->permissions.ownerID); - printf("%3d ", folder->permissions.groupID); - printf("%12d ", folder->valence); - fileTime = APPLE_TO_UNIX_TIME(folder->contentModDate); - } else if(list->record->recordType == kHFSPlusFileRecord) { - file = (HFSPlusCatalogFile*)list->record; - printf("%06o ", file->permissions.fileMode); - printf("%3d ", file->permissions.ownerID); - printf("%3d ", file->permissions.groupID); - printf("%12lld ", file->dataFork.logicalSize); - fileTime = APPLE_TO_UNIX_TIME(file->contentModDate); - } - - date = localtime(&fileTime); - if(date != NULL) { - printf("%2d/%2d/%4d %02d:%02d ", date->tm_mon, date->tm_mday, date->tm_year + 1900, date->tm_hour, date->tm_min); - } else { - printf(" "); - } - - printUnicode(&list->name); - printf("\n"); - - list = list->next; - } - - releaseCatalogRecordList(theList); -} - -void displayFileLSLine(HFSPlusCatalogFile* file, const char* name) { - time_t fileTime; - struct tm *date; - - printf("%06o ", file->permissions.fileMode); - printf("%3d ", file->permissions.ownerID); - printf("%3d ", file->permissions.groupID); - printf("%12d ", file->dataFork.logicalSize); - fileTime = APPLE_TO_UNIX_TIME(file->contentModDate); - date = localtime(&fileTime); - if(date != NULL) { - printf("%2d/%2d/%4d %2d:%02d ", date->tm_mon, date->tm_mday, date->tm_year + 1900, date->tm_hour, date->tm_min); - } else { - printf(" "); - } - printf("%s\n", name); + +void addall_hfs(Volume* volume, const char* dirToMerge, const char* dest) { + HFSPlusCatalogRecord* record; + char* name; + char cwd[1024]; + char initPath[1024]; + int lastCharOfPath; + + ASSERT(getcwd(cwd, 1024) != NULL, "cannot get current working directory"); + + if(chdir(dirToMerge) != 0) { + printf("Cannot open that directory: %s\n", dirToMerge); + exit(0); + } + + record = getRecordFromPath(dest, volume, &name, NULL); + strcpy(initPath, dest); + lastCharOfPath = strlen(dest) - 1; + if(dest[lastCharOfPath] != '/') { + initPath[lastCharOfPath + 1] = '/'; + initPath[lastCharOfPath + 2] = '\0'; + } + + if(record != NULL) { + if(record->recordType == kHFSPlusFolderRecord) + addAllInFolder(((HFSPlusCatalogFolder*)record)->folderID, volume, initPath); + else { + printf("Not a folder\n"); + exit(0); + } + } else { + printf("No such file or directory\n"); + exit(0); + } + + ASSERT(chdir(cwd) == 0, "chdir"); + free(record); + } +int copyAcrossVolumes(Volume* volume1, Volume* volume2, char* path1, char* path2) { + void* buffer; + size_t bufferSize; + AbstractFile* tmpFile; + int ret; + + buffer = malloc(1); + bufferSize = 0; + tmpFile = createAbstractFileFromMemoryFile((void**)&buffer, &bufferSize); + + printf("retrieving... "); fflush(stdout); + get_hfs(volume1, path1, tmpFile); + tmpFile->seek(tmpFile, 0); + printf("writing (%lld)... ", tmpFile->getLength(tmpFile)); fflush(stdout); + ret = add_hfs(volume2, tmpFile, path2); + printf("done\n"); + + free(buffer); + + return ret; +} + +void displayFolder(HFSCatalogNodeID folderID, Volume* volume) { + CatalogRecordList* list; + CatalogRecordList* theList; + HFSPlusCatalogFolder* folder; + HFSPlusCatalogFile* file; + time_t fileTime; + struct tm *date; + + theList = list = getFolderContents(folderID, volume); + + while(list != NULL) { + if(list->record->recordType == kHFSPlusFolderRecord) { + folder = (HFSPlusCatalogFolder*)list->record; + printf("%06o ", folder->permissions.fileMode); + printf("%3d ", folder->permissions.ownerID); + printf("%3d ", folder->permissions.groupID); + printf("%12d ", folder->valence); + fileTime = APPLE_TO_UNIX_TIME(folder->contentModDate); + } else if(list->record->recordType == kHFSPlusFileRecord) { + file = (HFSPlusCatalogFile*)list->record; + printf("%06o ", file->permissions.fileMode); + printf("%3d ", file->permissions.ownerID); + printf("%3d ", file->permissions.groupID); + printf("%12lld ", file->dataFork.logicalSize); + fileTime = APPLE_TO_UNIX_TIME(file->contentModDate); + } + + date = localtime(&fileTime); + if(date != NULL) { + printf("%2d/%2d/%4d %02d:%02d ", date->tm_mon, date->tm_mday, date->tm_year + 1900, date->tm_hour, date->tm_min); + } else { + printf(" "); + } + + printUnicode(&list->name); + printf("\n"); + + list = list->next; + } + + releaseCatalogRecordList(theList); +} + +void displayFileLSLine(HFSPlusCatalogFile* file, const char* name) { + time_t fileTime; + struct tm *date; + + printf("%06o ", file->permissions.fileMode); + printf("%3d ", file->permissions.ownerID); + printf("%3d ", file->permissions.groupID); + printf("%12d ", file->dataFork.logicalSize); + fileTime = APPLE_TO_UNIX_TIME(file->contentModDate); + date = localtime(&fileTime); + if(date != NULL) { + printf("%2d/%2d/%4d %2d:%02d ", date->tm_mon, date->tm_mday, date->tm_year + 1900, date->tm_hour, date->tm_min); + } else { + printf(" "); + } + printf("%s\n", name); +} void hfs_ls(Volume* volume, const char* path) { - HFSPlusCatalogRecord* record; + HFSPlusCatalogRecord* record; char* name; - record = getRecordFromPath(path, volume, &name, NULL); - - if(record != NULL) { - if(record->recordType == kHFSPlusFolderRecord) - displayFolder(((HFSPlusCatalogFolder*)record)->folderID, volume); - else - displayFileLSLine((HFSPlusCatalogFile*)record, name); - } else { - printf("No such file or directory\n"); + record = getRecordFromPath(path, volume, &name, NULL); + + if(record != NULL) { + if(record->recordType == kHFSPlusFolderRecord) + displayFolder(((HFSPlusCatalogFolder*)record)->folderID, volume); + else + displayFileLSLine((HFSPlusCatalogFile*)record, name); + } else { + printf("No such file or directory\n"); } - printf("Total filesystem size: %d, free: %d\n", (volume->volumeHeader->totalBlocks - volume->volumeHeader->freeBlocks) * volume->volumeHeader->blockSize, volume->volumeHeader->freeBlocks * volume->volumeHeader->blockSize); - - free(record); + printf("Total filesystem size: %d, free: %d\n", (volume->volumeHeader->totalBlocks - volume->volumeHeader->freeBlocks) * volume->volumeHeader->blockSize, volume->volumeHeader->freeBlocks * volume->volumeHeader->blockSize); + + free(record); } diff --git a/hfs/hfsplus.h b/hfs/hfsplus.h index 018aefc..45720e0 100644 --- a/hfs/hfsplus.h +++ b/hfs/hfsplus.h @@ -1,508 +1,508 @@ -#ifndef HFSPLUS_H -#define HFSPLUS_H - -#include -#include -#include - - -#include "common.h" - -#define READ(a, b, c, d) ((*((a)->read))(a, b, c, d)) -#define WRITE(a, b, c, d) ((*((a)->write))(a, b, c, d)) -#define CLOSE(a) ((*((a)->close))(a)) -#define COMPARE(a, b, c) ((*((a)->compare))(b, c)) -#define READ_KEY(a, b, c) ((*((a)->keyRead))(b, c)) -#define WRITE_KEY(a, b, c, d) ((*((a)->keyWrite))(b, c, d)) -#define READ_DATA(a, b, c) ((*((a)->dataRead))(b, c)) - -struct BTKey { - uint16_t keyLength; - unsigned char data[0]; -} __attribute__((__packed__)); - -typedef struct BTKey BTKey; - -typedef BTKey* (*dataReadFunc)(off_t offset, struct io_func_struct* io); -typedef void (*keyPrintFunc)(BTKey* toPrint); -typedef int (*keyWriteFunc)(off_t offset, BTKey* toWrite, struct io_func_struct* io); -typedef int (*compareFunc)(BTKey* left, BTKey* right); - -typedef uint32_t HFSCatalogNodeID; - -enum { - kHFSRootParentID = 1, - kHFSRootFolderID = 2, - kHFSExtentsFileID = 3, - kHFSCatalogFileID = 4, - kHFSBadBlockFileID = 5, - kHFSAllocationFileID = 6, - kHFSStartupFileID = 7, - kHFSAttributesFileID = 8, - kHFSRepairCatalogFileID = 14, - kHFSBogusExtentFileID = 15, - kHFSFirstUserCatalogNodeID = 16 -}; - -#define STR_SIZE(str) (sizeof(uint16_t) + (sizeof(uint16_t) * (str).length)) - -struct HFSUniStr255 { - uint16_t length; - uint16_t unicode[255]; -} __attribute__((__packed__)); -typedef struct HFSUniStr255 HFSUniStr255; -typedef const HFSUniStr255 *ConstHFSUniStr255Param; - -struct HFSPlusExtentDescriptor { - uint32_t startBlock; - uint32_t blockCount; -} __attribute__((__packed__)); -typedef struct HFSPlusExtentDescriptor HFSPlusExtentDescriptor; - -typedef HFSPlusExtentDescriptor HFSPlusExtentRecord[8]; - -struct HFSPlusForkData { - uint64_t logicalSize; - uint32_t clumpSize; - uint32_t totalBlocks; - HFSPlusExtentRecord extents; -} __attribute__((__packed__)); -typedef struct HFSPlusForkData HFSPlusForkData; - -struct HFSPlusVolumeHeader { - uint16_t signature; - uint16_t version; - uint32_t attributes; - uint32_t lastMountedVersion; - uint32_t journalInfoBlock; - - uint32_t createDate; - uint32_t modifyDate; - uint32_t backupDate; - uint32_t checkedDate; - - uint32_t fileCount; - uint32_t folderCount; - - uint32_t blockSize; - uint32_t totalBlocks; - uint32_t freeBlocks; - - uint32_t nextAllocation; - uint32_t rsrcClumpSize; - uint32_t dataClumpSize; - HFSCatalogNodeID nextCatalogID; - - uint32_t writeCount; - uint64_t encodingsBitmap; - - uint32_t finderInfo[8]; - - HFSPlusForkData allocationFile; - HFSPlusForkData extentsFile; - HFSPlusForkData catalogFile; - HFSPlusForkData attributesFile; - HFSPlusForkData startupFile; -} __attribute__((__packed__)); -typedef struct HFSPlusVolumeHeader HFSPlusVolumeHeader; - -enum { - kBTLeafNode = -1, - kBTIndexNode = 0, - kBTHeaderNode = 1, - kBTMapNode = 2 -}; - -struct BTNodeDescriptor { - uint32_t fLink; - uint32_t bLink; - int8_t kind; - uint8_t height; - uint16_t numRecords; - uint16_t reserved; -} __attribute__((__packed__)); -typedef struct BTNodeDescriptor BTNodeDescriptor; - -#define kHFSCaseFolding 0xCF -#define kHFSBinaryCompare 0xBC - -struct BTHeaderRec { - uint16_t treeDepth; - uint32_t rootNode; - uint32_t leafRecords; - uint32_t firstLeafNode; - uint32_t lastLeafNode; - uint16_t nodeSize; - uint16_t maxKeyLength; - uint32_t totalNodes; - uint32_t freeNodes; - uint16_t reserved1; - uint32_t clumpSize; // misaligned - uint8_t btreeType; - uint8_t keyCompareType; - uint32_t attributes; // long aligned again - uint32_t reserved3[16]; -} __attribute__((__packed__)); -typedef struct BTHeaderRec BTHeaderRec; - -struct HFSPlusExtentKey { - uint16_t keyLength; - uint8_t forkType; - uint8_t pad; - HFSCatalogNodeID fileID; - uint32_t startBlock; -} __attribute__((__packed__)); -typedef struct HFSPlusExtentKey HFSPlusExtentKey; - -struct HFSPlusCatalogKey { - uint16_t keyLength; - HFSCatalogNodeID parentID; - HFSUniStr255 nodeName; -} __attribute__((__packed__)); -typedef struct HFSPlusCatalogKey HFSPlusCatalogKey; - -struct Point { - int16_t v; - int16_t h; -} __attribute__((__packed__)); -typedef struct Point Point; - -struct Rect { - int16_t top; - int16_t left; - int16_t bottom; - int16_t right; -} __attribute__((__packed__)); -typedef struct Rect Rect; - -/* OSType is a 32-bit value made by packing four 1-byte characters - together. */ -typedef uint32_t FourCharCode; -typedef FourCharCode OSType; - -/* Finder flags (finderFlags, fdFlags and frFlags) */ -enum { - kIsOnDesk = 0x0001, /* Files and folders (System 6) */ - kColor = 0x000E, /* Files and folders */ - kIsShared = 0x0040, /* Files only (Applications only) If */ - /* clear, the application needs */ - /* to write to its resource fork, */ - /* and therefore cannot be shared */ - /* on a server */ - kHasNoINITs = 0x0080, /* Files only (Extensions/Control */ - /* Panels only) */ - /* This file contains no INIT resource */ - kHasBeenInited = 0x0100, /* Files only. Clear if the file */ - /* contains desktop database resources */ - /* ('BNDL', 'FREF', 'open', 'kind'...) */ - /* that have not been added yet. Set */ - /* only by the Finder. */ - /* Reserved for folders */ - kHasCustomIcon = 0x0400, /* Files and folders */ - kIsStationery = 0x0800, /* Files only */ - kNameLocked = 0x1000, /* Files and folders */ - kHasBundle = 0x2000, /* Files only */ - kIsInvisible = 0x4000, /* Files and folders */ - kIsAlias = 0x8000 /* Files only */ -}; - -/* Extended flags (extendedFinderFlags, fdXFlags and frXFlags) */ -enum { - kExtendedFlagsAreInvalid = 0x8000, /* The other extended flags */ - /* should be ignored */ - kExtendedFlagHasCustomBadge = 0x0100, /* The file or folder has a */ - /* badge resource */ - kExtendedFlagHasRoutingInfo = 0x0004 /* The file contains routing */ - /* info resource */ -}; +#ifndef HFSPLUS_H +#define HFSPLUS_H + +#include +#include +#include + + +#include "common.h" + +#define READ(a, b, c, d) ((*((a)->read))(a, b, c, d)) +#define WRITE(a, b, c, d) ((*((a)->write))(a, b, c, d)) +#define CLOSE(a) ((*((a)->close))(a)) +#define COMPARE(a, b, c) ((*((a)->compare))(b, c)) +#define READ_KEY(a, b, c) ((*((a)->keyRead))(b, c)) +#define WRITE_KEY(a, b, c, d) ((*((a)->keyWrite))(b, c, d)) +#define READ_DATA(a, b, c) ((*((a)->dataRead))(b, c)) + +struct BTKey { + uint16_t keyLength; + unsigned char data[0]; +} __attribute__((__packed__)); + +typedef struct BTKey BTKey; + +typedef BTKey* (*dataReadFunc)(off_t offset, struct io_func_struct* io); +typedef void (*keyPrintFunc)(BTKey* toPrint); +typedef int (*keyWriteFunc)(off_t offset, BTKey* toWrite, struct io_func_struct* io); +typedef int (*compareFunc)(BTKey* left, BTKey* right); + +typedef uint32_t HFSCatalogNodeID; + +enum { + kHFSRootParentID = 1, + kHFSRootFolderID = 2, + kHFSExtentsFileID = 3, + kHFSCatalogFileID = 4, + kHFSBadBlockFileID = 5, + kHFSAllocationFileID = 6, + kHFSStartupFileID = 7, + kHFSAttributesFileID = 8, + kHFSRepairCatalogFileID = 14, + kHFSBogusExtentFileID = 15, + kHFSFirstUserCatalogNodeID = 16 +}; + +#define STR_SIZE(str) (sizeof(uint16_t) + (sizeof(uint16_t) * (str).length)) + +struct HFSUniStr255 { + uint16_t length; + uint16_t unicode[255]; +} __attribute__((__packed__)); +typedef struct HFSUniStr255 HFSUniStr255; +typedef const HFSUniStr255 *ConstHFSUniStr255Param; + +struct HFSPlusExtentDescriptor { + uint32_t startBlock; + uint32_t blockCount; +} __attribute__((__packed__)); +typedef struct HFSPlusExtentDescriptor HFSPlusExtentDescriptor; + +typedef HFSPlusExtentDescriptor HFSPlusExtentRecord[8]; + +struct HFSPlusForkData { + uint64_t logicalSize; + uint32_t clumpSize; + uint32_t totalBlocks; + HFSPlusExtentRecord extents; +} __attribute__((__packed__)); +typedef struct HFSPlusForkData HFSPlusForkData; + +struct HFSPlusVolumeHeader { + uint16_t signature; + uint16_t version; + uint32_t attributes; + uint32_t lastMountedVersion; + uint32_t journalInfoBlock; + + uint32_t createDate; + uint32_t modifyDate; + uint32_t backupDate; + uint32_t checkedDate; + + uint32_t fileCount; + uint32_t folderCount; + + uint32_t blockSize; + uint32_t totalBlocks; + uint32_t freeBlocks; + + uint32_t nextAllocation; + uint32_t rsrcClumpSize; + uint32_t dataClumpSize; + HFSCatalogNodeID nextCatalogID; + + uint32_t writeCount; + uint64_t encodingsBitmap; + + uint32_t finderInfo[8]; + + HFSPlusForkData allocationFile; + HFSPlusForkData extentsFile; + HFSPlusForkData catalogFile; + HFSPlusForkData attributesFile; + HFSPlusForkData startupFile; +} __attribute__((__packed__)); +typedef struct HFSPlusVolumeHeader HFSPlusVolumeHeader; + +enum { + kBTLeafNode = -1, + kBTIndexNode = 0, + kBTHeaderNode = 1, + kBTMapNode = 2 +}; + +struct BTNodeDescriptor { + uint32_t fLink; + uint32_t bLink; + int8_t kind; + uint8_t height; + uint16_t numRecords; + uint16_t reserved; +} __attribute__((__packed__)); +typedef struct BTNodeDescriptor BTNodeDescriptor; + +#define kHFSCaseFolding 0xCF +#define kHFSBinaryCompare 0xBC + +struct BTHeaderRec { + uint16_t treeDepth; + uint32_t rootNode; + uint32_t leafRecords; + uint32_t firstLeafNode; + uint32_t lastLeafNode; + uint16_t nodeSize; + uint16_t maxKeyLength; + uint32_t totalNodes; + uint32_t freeNodes; + uint16_t reserved1; + uint32_t clumpSize; // misaligned + uint8_t btreeType; + uint8_t keyCompareType; + uint32_t attributes; // long aligned again + uint32_t reserved3[16]; +} __attribute__((__packed__)); +typedef struct BTHeaderRec BTHeaderRec; + +struct HFSPlusExtentKey { + uint16_t keyLength; + uint8_t forkType; + uint8_t pad; + HFSCatalogNodeID fileID; + uint32_t startBlock; +} __attribute__((__packed__)); +typedef struct HFSPlusExtentKey HFSPlusExtentKey; + +struct HFSPlusCatalogKey { + uint16_t keyLength; + HFSCatalogNodeID parentID; + HFSUniStr255 nodeName; +} __attribute__((__packed__)); +typedef struct HFSPlusCatalogKey HFSPlusCatalogKey; + +struct Point { + int16_t v; + int16_t h; +} __attribute__((__packed__)); +typedef struct Point Point; + +struct Rect { + int16_t top; + int16_t left; + int16_t bottom; + int16_t right; +} __attribute__((__packed__)); +typedef struct Rect Rect; + +/* OSType is a 32-bit value made by packing four 1-byte characters + together. */ +typedef uint32_t FourCharCode; +typedef FourCharCode OSType; + +/* Finder flags (finderFlags, fdFlags and frFlags) */ +enum { + kIsOnDesk = 0x0001, /* Files and folders (System 6) */ + kColor = 0x000E, /* Files and folders */ + kIsShared = 0x0040, /* Files only (Applications only) If */ + /* clear, the application needs */ + /* to write to its resource fork, */ + /* and therefore cannot be shared */ + /* on a server */ + kHasNoINITs = 0x0080, /* Files only (Extensions/Control */ + /* Panels only) */ + /* This file contains no INIT resource */ + kHasBeenInited = 0x0100, /* Files only. Clear if the file */ + /* contains desktop database resources */ + /* ('BNDL', 'FREF', 'open', 'kind'...) */ + /* that have not been added yet. Set */ + /* only by the Finder. */ + /* Reserved for folders */ + kHasCustomIcon = 0x0400, /* Files and folders */ + kIsStationery = 0x0800, /* Files only */ + kNameLocked = 0x1000, /* Files and folders */ + kHasBundle = 0x2000, /* Files only */ + kIsInvisible = 0x4000, /* Files and folders */ + kIsAlias = 0x8000 /* Files only */ +}; + +/* Extended flags (extendedFinderFlags, fdXFlags and frXFlags) */ +enum { + kExtendedFlagsAreInvalid = 0x8000, /* The other extended flags */ + /* should be ignored */ + kExtendedFlagHasCustomBadge = 0x0100, /* The file or folder has a */ + /* badge resource */ + kExtendedFlagHasRoutingInfo = 0x0004 /* The file contains routing */ + /* info resource */ +}; enum { kSymLinkFileType = 0x736C6E6B, /* 'slnk' */ kSymLinkCreator = 0x72686170 /* 'rhap' */ }; - -struct FileInfo { - OSType fileType; /* The type of the file */ - OSType fileCreator; /* The file's creator */ - uint16_t finderFlags; - Point location; /* File's location in the folder. */ - uint16_t reservedField; -} __attribute__((__packed__)); -typedef struct FileInfo FileInfo; - -struct ExtendedFileInfo { - int16_t reserved1[4]; - uint16_t extendedFinderFlags; - int16_t reserved2; - int32_t putAwayFolderID; -} __attribute__((__packed__)); -typedef struct ExtendedFileInfo ExtendedFileInfo; - -struct FolderInfo { - Rect windowBounds; /* The position and dimension of the */ - /* folder's window */ - uint16_t finderFlags; - Point location; /* Folder's location in the parent */ - /* folder. If set to {0, 0}, the Finder */ - /* will place the item automatically */ - uint16_t reservedField; -} __attribute__((__packed__)); -typedef struct FolderInfo FolderInfo; - -struct ExtendedFolderInfo { - Point scrollPosition; /* Scroll position (for icon views) */ - int32_t reserved1; - uint16_t extendedFinderFlags; - int16_t reserved2; - int32_t putAwayFolderID; -} __attribute__((__packed__)); -typedef struct ExtendedFolderInfo ExtendedFolderInfo; - -#define S_ISUID 0004000 /* set user id on execution */ -#define S_ISGID 0002000 /* set group id on execution */ -#define S_ISTXT 0001000 /* sticky bit */ - -#define S_IRWXU 0000700 /* RWX mask for owner */ -#define S_IRUSR 0000400 /* R for owner */ -#define S_IWUSR 0000200 /* W for owner */ -#define S_IXUSR 0000100 /* X for owner */ - -#define S_IRWXG 0000070 /* RWX mask for group */ -#define S_IRGRP 0000040 /* R for group */ -#define S_IWGRP 0000020 /* W for group */ -#define S_IXGRP 0000010 /* X for group */ - -#define S_IRWXO 0000007 /* RWX mask for other */ -#define S_IROTH 0000004 /* R for other */ -#define S_IWOTH 0000002 /* W for other */ -#define S_IXOTH 0000001 /* X for other */ - -#define S_IFMT 0170000 /* type of file mask */ -#define S_IFIFO 0010000 /* named pipe (fifo) */ -#define S_IFCHR 0020000 /* character special */ -#define S_IFDIR 0040000 /* directory */ -#define S_IFBLK 0060000 /* block special */ -#define S_IFREG 0100000 /* regular */ -#define S_IFLNK 0120000 /* symbolic link */ -#define S_IFSOCK 0140000 /* socket */ -#define S_IFWHT 0160000 /* whiteout */ - -struct HFSPlusBSDInfo { - uint32_t ownerID; - uint32_t groupID; - uint8_t adminFlags; - uint8_t ownerFlags; - uint16_t fileMode; - union { - uint32_t iNodeNum; - uint32_t linkCount; - uint32_t rawDevice; - } special; -} __attribute__((__packed__)); -typedef struct HFSPlusBSDInfo HFSPlusBSDInfo; - -enum { - kHFSPlusFolderRecord = 0x0001, - kHFSPlusFileRecord = 0x0002, - kHFSPlusFolderThreadRecord = 0x0003, - kHFSPlusFileThreadRecord = 0x0004 -}; - -enum { - kHFSFileLockedBit = 0x0000, /* file is locked and cannot be written to */ - kHFSFileLockedMask = 0x0001, - - kHFSThreadExistsBit = 0x0001, /* a file thread record exists for this file */ - kHFSThreadExistsMask = 0x0002, - - kHFSHasAttributesBit = 0x0002, /* object has extended attributes */ - kHFSHasAttributesMask = 0x0004, - - kHFSHasSecurityBit = 0x0003, /* object has security data (ACLs) */ - kHFSHasSecurityMask = 0x0008, - - kHFSHasFolderCountBit = 0x0004, /* only for HFSX, folder maintains a separate sub-folder count */ - kHFSHasFolderCountMask = 0x0010, /* (sum of folder records and directory hard links) */ - - kHFSHasLinkChainBit = 0x0005, /* has hardlink chain (inode or link) */ - kHFSHasLinkChainMask = 0x0020, - - kHFSHasChildLinkBit = 0x0006, /* folder has a child that's a dir link */ - kHFSHasChildLinkMask = 0x0040 -}; - -struct HFSPlusCatalogFolder { - int16_t recordType; - uint16_t flags; - uint32_t valence; - HFSCatalogNodeID folderID; - uint32_t createDate; - uint32_t contentModDate; - uint32_t attributeModDate; - uint32_t accessDate; - uint32_t backupDate; - HFSPlusBSDInfo permissions; - FolderInfo userInfo; - ExtendedFolderInfo finderInfo; - uint32_t textEncoding; - uint32_t folderCount; -} __attribute__((__packed__)); -typedef struct HFSPlusCatalogFolder HFSPlusCatalogFolder; - -struct HFSPlusCatalogFile { - int16_t recordType; - uint16_t flags; - uint32_t reserved1; - HFSCatalogNodeID fileID; - uint32_t createDate; - uint32_t contentModDate; - uint32_t attributeModDate; - uint32_t accessDate; - uint32_t backupDate; - HFSPlusBSDInfo permissions; - FileInfo userInfo; - ExtendedFileInfo finderInfo; - uint32_t textEncoding; - uint32_t reserved2; - - HFSPlusForkData dataFork; - HFSPlusForkData resourceFork; -} __attribute__((__packed__)); -typedef struct HFSPlusCatalogFile HFSPlusCatalogFile; - -struct HFSPlusCatalogThread { - int16_t recordType; - int16_t reserved; - HFSCatalogNodeID parentID; - HFSUniStr255 nodeName; -} __attribute__((__packed__)); -typedef struct HFSPlusCatalogThread HFSPlusCatalogThread; - -struct HFSPlusCatalogRecord { - int16_t recordType; - unsigned char data[0]; -} __attribute__((__packed__)); -typedef struct HFSPlusCatalogRecord HFSPlusCatalogRecord; - -struct CatalogRecordList { - HFSUniStr255 name; - HFSPlusCatalogRecord* record; - struct CatalogRecordList* next; -}; -typedef struct CatalogRecordList CatalogRecordList; - -struct Extent { - uint32_t startBlock; - uint32_t blockCount; - struct Extent* next; -}; - -typedef struct Extent Extent; - -typedef struct { - io_func* io; - BTHeaderRec *headerRec; - compareFunc compare; - dataReadFunc keyRead; - keyWriteFunc keyWrite; - keyPrintFunc keyPrint; - dataReadFunc dataRead; -} BTree; - -typedef struct { - io_func* image; - HFSPlusVolumeHeader* volumeHeader; - - BTree* extentsTree; - BTree* catalogTree; - io_func* allocationFile; -} Volume; - - -typedef struct { - HFSCatalogNodeID id; - HFSPlusCatalogRecord* catalogRecord; - Volume* volume; - HFSPlusForkData* forkData; - Extent* extents; -} RawFile; + +struct FileInfo { + OSType fileType; /* The type of the file */ + OSType fileCreator; /* The file's creator */ + uint16_t finderFlags; + Point location; /* File's location in the folder. */ + uint16_t reservedField; +} __attribute__((__packed__)); +typedef struct FileInfo FileInfo; + +struct ExtendedFileInfo { + int16_t reserved1[4]; + uint16_t extendedFinderFlags; + int16_t reserved2; + int32_t putAwayFolderID; +} __attribute__((__packed__)); +typedef struct ExtendedFileInfo ExtendedFileInfo; + +struct FolderInfo { + Rect windowBounds; /* The position and dimension of the */ + /* folder's window */ + uint16_t finderFlags; + Point location; /* Folder's location in the parent */ + /* folder. If set to {0, 0}, the Finder */ + /* will place the item automatically */ + uint16_t reservedField; +} __attribute__((__packed__)); +typedef struct FolderInfo FolderInfo; + +struct ExtendedFolderInfo { + Point scrollPosition; /* Scroll position (for icon views) */ + int32_t reserved1; + uint16_t extendedFinderFlags; + int16_t reserved2; + int32_t putAwayFolderID; +} __attribute__((__packed__)); +typedef struct ExtendedFolderInfo ExtendedFolderInfo; + +#define S_ISUID 0004000 /* set user id on execution */ +#define S_ISGID 0002000 /* set group id on execution */ +#define S_ISTXT 0001000 /* sticky bit */ + +#define S_IRWXU 0000700 /* RWX mask for owner */ +#define S_IRUSR 0000400 /* R for owner */ +#define S_IWUSR 0000200 /* W for owner */ +#define S_IXUSR 0000100 /* X for owner */ + +#define S_IRWXG 0000070 /* RWX mask for group */ +#define S_IRGRP 0000040 /* R for group */ +#define S_IWGRP 0000020 /* W for group */ +#define S_IXGRP 0000010 /* X for group */ + +#define S_IRWXO 0000007 /* RWX mask for other */ +#define S_IROTH 0000004 /* R for other */ +#define S_IWOTH 0000002 /* W for other */ +#define S_IXOTH 0000001 /* X for other */ + +#define S_IFMT 0170000 /* type of file mask */ +#define S_IFIFO 0010000 /* named pipe (fifo) */ +#define S_IFCHR 0020000 /* character special */ +#define S_IFDIR 0040000 /* directory */ +#define S_IFBLK 0060000 /* block special */ +#define S_IFREG 0100000 /* regular */ +#define S_IFLNK 0120000 /* symbolic link */ +#define S_IFSOCK 0140000 /* socket */ +#define S_IFWHT 0160000 /* whiteout */ + +struct HFSPlusBSDInfo { + uint32_t ownerID; + uint32_t groupID; + uint8_t adminFlags; + uint8_t ownerFlags; + uint16_t fileMode; + union { + uint32_t iNodeNum; + uint32_t linkCount; + uint32_t rawDevice; + } special; +} __attribute__((__packed__)); +typedef struct HFSPlusBSDInfo HFSPlusBSDInfo; + +enum { + kHFSPlusFolderRecord = 0x0001, + kHFSPlusFileRecord = 0x0002, + kHFSPlusFolderThreadRecord = 0x0003, + kHFSPlusFileThreadRecord = 0x0004 +}; + +enum { + kHFSFileLockedBit = 0x0000, /* file is locked and cannot be written to */ + kHFSFileLockedMask = 0x0001, + + kHFSThreadExistsBit = 0x0001, /* a file thread record exists for this file */ + kHFSThreadExistsMask = 0x0002, + + kHFSHasAttributesBit = 0x0002, /* object has extended attributes */ + kHFSHasAttributesMask = 0x0004, + + kHFSHasSecurityBit = 0x0003, /* object has security data (ACLs) */ + kHFSHasSecurityMask = 0x0008, + + kHFSHasFolderCountBit = 0x0004, /* only for HFSX, folder maintains a separate sub-folder count */ + kHFSHasFolderCountMask = 0x0010, /* (sum of folder records and directory hard links) */ + + kHFSHasLinkChainBit = 0x0005, /* has hardlink chain (inode or link) */ + kHFSHasLinkChainMask = 0x0020, + + kHFSHasChildLinkBit = 0x0006, /* folder has a child that's a dir link */ + kHFSHasChildLinkMask = 0x0040 +}; + +struct HFSPlusCatalogFolder { + int16_t recordType; + uint16_t flags; + uint32_t valence; + HFSCatalogNodeID folderID; + uint32_t createDate; + uint32_t contentModDate; + uint32_t attributeModDate; + uint32_t accessDate; + uint32_t backupDate; + HFSPlusBSDInfo permissions; + FolderInfo userInfo; + ExtendedFolderInfo finderInfo; + uint32_t textEncoding; + uint32_t folderCount; +} __attribute__((__packed__)); +typedef struct HFSPlusCatalogFolder HFSPlusCatalogFolder; + +struct HFSPlusCatalogFile { + int16_t recordType; + uint16_t flags; + uint32_t reserved1; + HFSCatalogNodeID fileID; + uint32_t createDate; + uint32_t contentModDate; + uint32_t attributeModDate; + uint32_t accessDate; + uint32_t backupDate; + HFSPlusBSDInfo permissions; + FileInfo userInfo; + ExtendedFileInfo finderInfo; + uint32_t textEncoding; + uint32_t reserved2; + + HFSPlusForkData dataFork; + HFSPlusForkData resourceFork; +} __attribute__((__packed__)); +typedef struct HFSPlusCatalogFile HFSPlusCatalogFile; + +struct HFSPlusCatalogThread { + int16_t recordType; + int16_t reserved; + HFSCatalogNodeID parentID; + HFSUniStr255 nodeName; +} __attribute__((__packed__)); +typedef struct HFSPlusCatalogThread HFSPlusCatalogThread; + +struct HFSPlusCatalogRecord { + int16_t recordType; + unsigned char data[0]; +} __attribute__((__packed__)); +typedef struct HFSPlusCatalogRecord HFSPlusCatalogRecord; + +struct CatalogRecordList { + HFSUniStr255 name; + HFSPlusCatalogRecord* record; + struct CatalogRecordList* next; +}; +typedef struct CatalogRecordList CatalogRecordList; + +struct Extent { + uint32_t startBlock; + uint32_t blockCount; + struct Extent* next; +}; + +typedef struct Extent Extent; + +typedef struct { + io_func* io; + BTHeaderRec *headerRec; + compareFunc compare; + dataReadFunc keyRead; + keyWriteFunc keyWrite; + keyPrintFunc keyPrint; + dataReadFunc dataRead; +} BTree; + +typedef struct { + io_func* image; + HFSPlusVolumeHeader* volumeHeader; + + BTree* extentsTree; + BTree* catalogTree; + io_func* allocationFile; +} Volume; + + +typedef struct { + HFSCatalogNodeID id; + HFSPlusCatalogRecord* catalogRecord; + Volume* volume; + HFSPlusForkData* forkData; + Extent* extents; +} RawFile; #ifdef __cplusplus extern "C" { -#endif - void panic(const char* panicString); - - void printUnicode(HFSUniStr255* str); - char* unicodeToAscii(HFSUniStr255* str); - - BTNodeDescriptor* readBTNodeDescriptor(uint32_t num, BTree* tree); - - BTHeaderRec* readBTHeaderRec(io_func* io); - - BTree* openBTree(io_func* io, compareFunc compare, dataReadFunc keyRead, keyWriteFunc keyWrite, keyPrintFunc keyPrint, dataReadFunc dataRead); - - void closeBTree(BTree* tree); - - off_t getRecordOffset(int num, uint32_t nodeNum, BTree* tree); - - off_t getNodeNumberFromPointerRecord(off_t offset, io_func* io); - - void* search(BTree* tree, BTKey* searchKey, int *exact, uint32_t *nodeNumber, int *recordNumber); - - io_func* openFlatFile(const char* fileName); - io_func* openFlatFileRO(const char* fileName); - - io_func* openRawFile(HFSCatalogNodeID id, HFSPlusForkData* forkData, HFSPlusCatalogRecord* catalogRecord, Volume* volume); - - void flipExtentRecord(HFSPlusExtentRecord* extentRecord); - - BTree* openExtentsTree(io_func* file); - - void ASCIIToUnicode(const char* ascii, HFSUniStr255* unistr); - - void flipCatalogFolder(HFSPlusCatalogFolder* record); - void flipCatalogFile(HFSPlusCatalogFile* record); - void flipCatalogThread(HFSPlusCatalogThread* record, int out); - - BTree* openCatalogTree(io_func* file); - int updateCatalog(Volume* volume, HFSPlusCatalogRecord* catalogRecord); - int move(const char* source, const char* dest, Volume* volume); - int removeFile(const char* fileName, Volume* volume); - HFSCatalogNodeID newFolder(const char* pathName, Volume* volume); - HFSCatalogNodeID newFile(const char* pathName, Volume* volume); - int chmodFile(const char* pathName, int mode, Volume* volume); +#endif + void panic(const char* panicString); + + void printUnicode(HFSUniStr255* str); + char* unicodeToAscii(HFSUniStr255* str); + + BTNodeDescriptor* readBTNodeDescriptor(uint32_t num, BTree* tree); + + BTHeaderRec* readBTHeaderRec(io_func* io); + + BTree* openBTree(io_func* io, compareFunc compare, dataReadFunc keyRead, keyWriteFunc keyWrite, keyPrintFunc keyPrint, dataReadFunc dataRead); + + void closeBTree(BTree* tree); + + off_t getRecordOffset(int num, uint32_t nodeNum, BTree* tree); + + off_t getNodeNumberFromPointerRecord(off_t offset, io_func* io); + + void* search(BTree* tree, BTKey* searchKey, int *exact, uint32_t *nodeNumber, int *recordNumber); + + io_func* openFlatFile(const char* fileName); + io_func* openFlatFileRO(const char* fileName); + + io_func* openRawFile(HFSCatalogNodeID id, HFSPlusForkData* forkData, HFSPlusCatalogRecord* catalogRecord, Volume* volume); + + void flipExtentRecord(HFSPlusExtentRecord* extentRecord); + + BTree* openExtentsTree(io_func* file); + + void ASCIIToUnicode(const char* ascii, HFSUniStr255* unistr); + + void flipCatalogFolder(HFSPlusCatalogFolder* record); + void flipCatalogFile(HFSPlusCatalogFile* record); + void flipCatalogThread(HFSPlusCatalogThread* record, int out); + + BTree* openCatalogTree(io_func* file); + int updateCatalog(Volume* volume, HFSPlusCatalogRecord* catalogRecord); + int move(const char* source, const char* dest, Volume* volume); + int removeFile(const char* fileName, Volume* volume); + HFSCatalogNodeID newFolder(const char* pathName, Volume* volume); + HFSCatalogNodeID newFile(const char* pathName, Volume* volume); + int chmodFile(const char* pathName, int mode, Volume* volume); int chownFile(const char* pathName, uint32_t owner, uint32_t group, Volume* volume); - int makeSymlink(const char* pathName, const char* target, Volume* volume); - + int makeSymlink(const char* pathName, const char* target, Volume* volume); + HFSPlusCatalogRecord* getRecordByCNID(HFSCatalogNodeID CNID, Volume* volume); - HFSPlusCatalogRecord* getLinkTarget(HFSPlusCatalogRecord* record, HFSCatalogNodeID parentID, HFSPlusCatalogKey *key, Volume* volume); - CatalogRecordList* getFolderContents(HFSCatalogNodeID CNID, Volume* volume); + HFSPlusCatalogRecord* getLinkTarget(HFSPlusCatalogRecord* record, HFSCatalogNodeID parentID, HFSPlusCatalogKey *key, Volume* volume); + CatalogRecordList* getFolderContents(HFSCatalogNodeID CNID, Volume* volume); HFSPlusCatalogRecord* getRecordFromPath(const char* path, Volume* volume, char **name, HFSPlusCatalogKey* retKey); - HFSPlusCatalogRecord* getRecordFromPath2(const char* path, Volume* volume, char **name, HFSPlusCatalogKey* retKey, char traverse); - HFSPlusCatalogRecord* getRecordFromPath3(const char* path, Volume* volume, char **name, HFSPlusCatalogKey* retKey, char traverse, char returnLink, HFSCatalogNodeID parentID); - void releaseCatalogRecordList(CatalogRecordList* list); - - int isBlockUsed(Volume* volume, uint32_t block); - int setBlockUsed(Volume* volume, uint32_t block, int used); - int allocate(RawFile* rawFile, off_t size); - - void flipForkData(HFSPlusForkData* forkData); - - Volume* openVolume(io_func* io); - void closeVolume(Volume *volume); - int updateVolume(Volume* volume); - - int debugBTree(BTree* tree, int displayTree); - - int addToBTree(BTree* tree, BTKey* searchKey, size_t length, unsigned char* content); - - int removeFromBTree(BTree* tree, BTKey* searchKey); - - int32_t FastUnicodeCompare ( register uint16_t str1[], register uint16_t length1, - register uint16_t str2[], register uint16_t length2); + HFSPlusCatalogRecord* getRecordFromPath2(const char* path, Volume* volume, char **name, HFSPlusCatalogKey* retKey, char traverse); + HFSPlusCatalogRecord* getRecordFromPath3(const char* path, Volume* volume, char **name, HFSPlusCatalogKey* retKey, char traverse, char returnLink, HFSCatalogNodeID parentID); + void releaseCatalogRecordList(CatalogRecordList* list); + + int isBlockUsed(Volume* volume, uint32_t block); + int setBlockUsed(Volume* volume, uint32_t block, int used); + int allocate(RawFile* rawFile, off_t size); + + void flipForkData(HFSPlusForkData* forkData); + + Volume* openVolume(io_func* io); + void closeVolume(Volume *volume); + int updateVolume(Volume* volume); + + int debugBTree(BTree* tree, int displayTree); + + int addToBTree(BTree* tree, BTKey* searchKey, size_t length, unsigned char* content); + + int removeFromBTree(BTree* tree, BTKey* searchKey); + + int32_t FastUnicodeCompare ( register uint16_t str1[], register uint16_t length1, + register uint16_t str2[], register uint16_t length2); #ifdef __cplusplus } #endif - -#endif - + +#endif +