initial code for dumping imessages in a reasonable format
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
#ifndef ABSTRACTFILE_H
|
||||
#define ABSTRACTFILE_H
|
||||
|
||||
#include "common.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct AbstractFile AbstractFile;
|
||||
typedef struct AbstractFile2 AbstractFile2;
|
||||
|
||||
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);
|
||||
typedef void (*SetKeyFunc)(AbstractFile2* file, const unsigned int* key, const unsigned int* iv);
|
||||
|
||||
typedef enum AbstractFileType {
|
||||
AbstractFileTypeFile,
|
||||
AbstractFileType8900,
|
||||
AbstractFileTypeImg2,
|
||||
AbstractFileTypeImg3,
|
||||
AbstractFileTypeLZSS,
|
||||
AbstractFileTypeIBootIM,
|
||||
AbstractFileTypeMem,
|
||||
AbstractFileTypeMemFile,
|
||||
AbstractFileTypeDummy
|
||||
} AbstractFileType;
|
||||
|
||||
struct AbstractFile {
|
||||
void* data;
|
||||
WriteFunc write;
|
||||
ReadFunc read;
|
||||
SeekFunc seek;
|
||||
TellFunc tell;
|
||||
GetLengthFunc getLength;
|
||||
CloseFunc close;
|
||||
AbstractFileType type;
|
||||
};
|
||||
|
||||
struct AbstractFile2 {
|
||||
AbstractFile super;
|
||||
SetKeyFunc setKey;
|
||||
};
|
||||
|
||||
|
||||
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, ...);
|
||||
io_func* IOFuncFromAbstractFile(AbstractFile* file);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#define fseeko fseeko64
|
||||
#define ftello ftello64
|
||||
#define off_t off64_t
|
||||
#define mkdir(x, y) mkdir(x)
|
||||
#define PATH_SEPARATOR "\\"
|
||||
#else
|
||||
#define PATH_SEPARATOR "/"
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void hexToBytes(const char* hex, uint8_t** buffer, size_t* bytes) {
|
||||
*bytes = strlen(hex) / 2;
|
||||
*buffer = (uint8_t*) malloc(*bytes);
|
||||
size_t i;
|
||||
for(i = 0; i < *bytes; i++) {
|
||||
uint32_t byte;
|
||||
sscanf(hex, "%2x", &byte);
|
||||
(*buffer)[i] = byte;
|
||||
hex += 2;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void hexToInts(const char* hex, unsigned int** buffer, size_t* bytes) {
|
||||
*bytes = strlen(hex) / 2;
|
||||
*buffer = (unsigned int*) malloc((*bytes) * sizeof(int));
|
||||
size_t i;
|
||||
for(i = 0; i < *bytes; i++) {
|
||||
sscanf(hex, "%2x", &((*buffer)[i]));
|
||||
hex += 2;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
struct AbstractFile;
|
||||
|
||||
unsigned char* decodeBase64(char* toDecode, size_t* dataLength);
|
||||
void writeBase64(struct AbstractFile* file, unsigned char* data, size_t dataLength, int tabLength, int width);
|
||||
char* convertBase64(unsigned char* data, size_t dataLength, int tabLength, int width);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,342 @@
|
||||
#ifndef DMG_H
|
||||
#define DMG_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <hfs/hfsplus.h>
|
||||
#include "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 (ATAPI_OFFSET + ATAPI_SIZE + FREE_SIZE)
|
||||
|
||||
#define DDM_OFFSET 0x0
|
||||
#define PARTITION_OFFSET (DDM_SIZE)
|
||||
#define ATAPI_OFFSET 64
|
||||
#define USER_OFFSET (ATAPI_OFFSET + 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;
|
||||
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;
|
||||
|
||||
#define SHA1_DIGEST_SIZE 20
|
||||
|
||||
typedef struct {
|
||||
uint32_t state[5];
|
||||
uint32_t count[2];
|
||||
uint8_t 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
|
||||
void outResources(AbstractFile* file, AbstractFile* out);
|
||||
|
||||
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 SHA1Init(SHA1_CTX* context);
|
||||
void SHA1Update(SHA1_CTX* context, const uint8_t* data, const size_t len);
|
||||
void SHA1Final(uint8_t digest[SHA1_DIGEST_SIZE], 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, unsigned int BlockSize);
|
||||
void flipPartitionMultiple(Partition* partition, char multiple, char out, unsigned int BlockSize);
|
||||
|
||||
void readDriverDescriptorMap(AbstractFile* file, ResourceKey* resources);
|
||||
DriverDescriptorRecord* createDriverDescriptorMap(uint32_t numSectors, unsigned int BlockSize);
|
||||
int writeDriverDescriptorMap(int pNum, AbstractFile* file, DriverDescriptorRecord* DDM, unsigned int BlockSize, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources);
|
||||
void readApplePartitionMap(AbstractFile* file, ResourceKey* resources, unsigned int BlockSize);
|
||||
Partition* createApplePartitionMap(uint32_t numSectors, const char* volumeType, unsigned int BlockSize);
|
||||
int writeApplePartitionMap(int pNum, AbstractFile* file, Partition* partitions, unsigned int BlockSize, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn);
|
||||
int writeATAPI(int pNum, AbstractFile* file, unsigned int BlockSize, ChecksumFunc dataForkChecksum, void* dataForkToken, ResourceKey **resources, NSizResource** nsizIn);
|
||||
int writeFreePartition(int pNum, AbstractFile* outFile, uint32_t offset, uint32_t numSectors, ResourceKey** resources);
|
||||
|
||||
void extractBLKX(AbstractFile* in, AbstractFile* out, BLKXTable* blkx);
|
||||
BLKXTable* insertBLKX(AbstractFile* out, AbstractFile* in, uint32_t firstSectorNumber, uint32_t numSectors, uint32_t blocksDescriptor,
|
||||
uint32_t checksumType, ChecksumFunc uncompressedChk, void* uncompressedChkToken, ChecksumFunc compressedChk,
|
||||
void* compressedChkToken, Volume* volume, int addComment);
|
||||
|
||||
|
||||
int extractDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, int partNum);
|
||||
int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, unsigned int BlockSize);
|
||||
int convertToISO(AbstractFile* abstractIn, AbstractFile* abstractOut);
|
||||
int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* dmgfile.h
|
||||
* libdmg-hfsplus
|
||||
*
|
||||
*/
|
||||
|
||||
#include <dmg/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;
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef DMGLIB_H
|
||||
#define DMGLIB_H
|
||||
|
||||
#include <dmg/dmg.h>
|
||||
#include "abstractfile.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int extractDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, int partNum);
|
||||
int buildDmg(AbstractFile* abstractIn, AbstractFile* abstractOut, unsigned int BlockSize);
|
||||
|
||||
int convertToDMG(AbstractFile* abstractIn, AbstractFile* abstractOut);
|
||||
int convertToISO(AbstractFile* abstractIn, AbstractFile* abstractOut);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
#ifndef FILEVAULT_H
|
||||
#define FILEVAULT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "dmg.h"
|
||||
|
||||
#ifdef HAVE_CRYPT
|
||||
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/aes.h>
|
||||
|
||||
#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 <ralf@coderpunks.org>,
|
||||
* Jacob Appelbaum <jacob@appelbaum.net>, and Christian Fromme <kaner@strace.org>
|
||||
*/
|
||||
|
||||
#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
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef HFSCOMPRESS_H
|
||||
#define HFSCOMPRESS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common.h"
|
||||
|
||||
#define CMPFS_MAGIC 0x636D7066
|
||||
|
||||
typedef struct HFSPlusDecmpfs {
|
||||
uint32_t magic;
|
||||
uint32_t flags;
|
||||
uint64_t size;
|
||||
uint8_t data[0];
|
||||
} __attribute__ ((packed)) HFSPlusDecmpfs;
|
||||
|
||||
typedef struct HFSPlusCmpfRsrcHead {
|
||||
uint32_t headerSize;
|
||||
uint32_t totalSize;
|
||||
uint32_t dataSize;
|
||||
uint32_t flags;
|
||||
} __attribute__ ((packed)) HFSPlusCmpfRsrcHead;
|
||||
|
||||
typedef struct HFSPlusCmpfRsrcBlock {
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
} __attribute__ ((packed)) HFSPlusCmpfRsrcBlock;
|
||||
|
||||
typedef struct HFSPlusCmpfRsrcBlockHead {
|
||||
uint32_t dataSize;
|
||||
uint32_t numBlocks;
|
||||
HFSPlusCmpfRsrcBlock blocks[0];
|
||||
} __attribute__ ((packed)) HFSPlusCmpfRsrcBlockHead;
|
||||
|
||||
typedef struct HFSPlusCmpfEnd {
|
||||
uint32_t pad[6];
|
||||
uint16_t unk1;
|
||||
uint16_t unk2;
|
||||
uint16_t unk3;
|
||||
uint32_t magic;
|
||||
uint32_t flags;
|
||||
uint64_t size;
|
||||
uint32_t unk4;
|
||||
} __attribute__ ((packed)) HFSPlusCmpfEnd;
|
||||
|
||||
typedef struct HFSPlusCompressed {
|
||||
Volume* volume;
|
||||
HFSPlusCatalogFile* file;
|
||||
io_func* io;
|
||||
size_t decmpfsSize;
|
||||
HFSPlusDecmpfs* decmpfs;
|
||||
|
||||
HFSPlusCmpfRsrcHead rsrcHead;
|
||||
HFSPlusCmpfRsrcBlockHead* blocks;
|
||||
|
||||
int dirty;
|
||||
|
||||
uint8_t* cached;
|
||||
uint32_t cachedStart;
|
||||
uint32_t cachedEnd;
|
||||
} HFSPlusCompressed;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void flipHFSPlusDecmpfs(HFSPlusDecmpfs* compressData);
|
||||
io_func* openHFSPlusCompressed(Volume* volume, HFSPlusCatalogFile* file);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
#include "common.h"
|
||||
#include "hfsplus.h"
|
||||
#include "abstractfile.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void writeToFile(HFSPlusCatalogFile* file, AbstractFile* output, Volume* volume);
|
||||
void writeToHFSFile(HFSPlusCatalogFile* file, AbstractFile* input, Volume* volume);
|
||||
void get_hfs(Volume* volume, const char* inFileName, AbstractFile* output);
|
||||
int add_hfs(Volume* volume, AbstractFile* inFile, const char* outFileName);
|
||||
void grow_hfs(Volume* volume, uint64_t newSize);
|
||||
void removeAllInFolder(HFSCatalogNodeID folderID, Volume* volume, const char* parentName);
|
||||
void addAllInFolder(HFSCatalogNodeID folderID, Volume* volume, const char* parentName);
|
||||
void addall_hfs(Volume* volume, const char* dirToMerge, const char* dest);
|
||||
void extractAllInFolder(HFSCatalogNodeID folderID, Volume* volume);
|
||||
int copyAcrossVolumes(Volume* volume1, Volume* volume2, char* path1, char* path2);
|
||||
|
||||
void hfs_untar(Volume* volume, AbstractFile* tarFile);
|
||||
void hfs_ls(Volume* volume, const char* path);
|
||||
void hfs_setsilence(int s);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,586 @@
|
||||
#ifndef HFSPLUS_H
|
||||
#define HFSPLUS_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#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);
|
||||
|
||||
#define STR_SIZE(str) (sizeof(uint16_t) + (sizeof(uint16_t) * (str).length))
|
||||
|
||||
#ifndef __HFS_FORMAT__
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
#ifndef __MACTYPES__
|
||||
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;
|
||||
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
|
||||
#ifndef _STAT_H_
|
||||
#ifndef _SYS_STAT_H
|
||||
#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 */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define UF_COMPRESSED 040
|
||||
|
||||
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;
|
||||
|
||||
enum {
|
||||
kHFSPlusAttrInlineData = 0x10,
|
||||
kHFSPlusAttrForkData = 0x20,
|
||||
kHFSPlusAttrExtents = 0x30
|
||||
};
|
||||
|
||||
struct HFSPlusAttrForkData {
|
||||
uint32_t recordType;
|
||||
uint32_t reserved;
|
||||
HFSPlusForkData theFork;
|
||||
} __attribute__((__packed__));
|
||||
typedef struct HFSPlusAttrForkData HFSPlusAttrForkData;
|
||||
|
||||
struct HFSPlusAttrExtents {
|
||||
uint32_t recordType;
|
||||
uint32_t reserved;
|
||||
HFSPlusExtentRecord extents;
|
||||
};
|
||||
typedef struct HFSPlusAttrExtents HFSPlusAttrExtents;
|
||||
|
||||
struct HFSPlusAttrData {
|
||||
uint32_t recordType;
|
||||
uint32_t reserved[2];
|
||||
uint32_t size;
|
||||
uint8_t data[0];
|
||||
} __attribute__((__packed__));
|
||||
typedef struct HFSPlusAttrData HFSPlusAttrData;
|
||||
|
||||
union HFSPlusAttrRecord {
|
||||
uint32_t recordType;
|
||||
HFSPlusAttrData attrData;
|
||||
HFSPlusAttrForkData forkData;
|
||||
HFSPlusAttrExtents overflowExtents;
|
||||
};
|
||||
typedef union HFSPlusAttrRecord HFSPlusAttrRecord;
|
||||
|
||||
struct HFSPlusAttrKey {
|
||||
uint16_t keyLength;
|
||||
uint16_t pad;
|
||||
uint32_t fileID;
|
||||
uint32_t startBlock;
|
||||
HFSUniStr255 name;
|
||||
} __attribute__((__packed__));
|
||||
typedef struct HFSPlusAttrKey HFSPlusAttrKey;
|
||||
|
||||
enum {
|
||||
kHardLinkFileType = 0x686C6E6B, /* 'hlnk' */
|
||||
kHFSPlusCreator = 0x6866732B /* 'hfs+' */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
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 XAttrList {
|
||||
char* name;
|
||||
struct XAttrList* next;
|
||||
};
|
||||
typedef struct XAttrList XAttrList;
|
||||
|
||||
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;
|
||||
BTree* attrTree;
|
||||
io_func* allocationFile;
|
||||
HFSCatalogNodeID metadataDir;
|
||||
} Volume;
|
||||
|
||||
|
||||
typedef struct {
|
||||
HFSCatalogNodeID id;
|
||||
HFSPlusCatalogRecord* catalogRecord;
|
||||
Volume* volume;
|
||||
HFSPlusForkData* forkData;
|
||||
Extent* extents;
|
||||
} RawFile;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void hfs_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);
|
||||
|
||||
BTree* openAttributesTree(io_func* file);
|
||||
size_t getAttribute(Volume* volume, uint32_t fileID, const char* name, uint8_t** data);
|
||||
int setAttribute(Volume* volume, uint32_t fileID, const char* name, uint8_t* data, size_t size);
|
||||
int unsetAttribute(Volume* volume, uint32_t fileID, const char* name);
|
||||
XAttrList* getAllExtendedAttributes(HFSCatalogNodeID CNID, 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);
|
||||
|
||||
HFSCatalogNodeID getMetadataDirectoryID(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* 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);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user