Esempio n. 1
0
static int attrKeyWrite(off_t offset, BTKey* toWrite, io_func* io) {
	HFSPlusAttrKey* key;
	uint16_t keyLength;
	uint16_t nodeNameLength;
	int i;

	keyLength = toWrite->keyLength;
	key = (HFSPlusAttrKey*) malloc(keyLength);
	memcpy(key, toWrite, keyLength);

	nodeNameLength = key->name.length;

	FLIPENDIAN(key->keyLength);
	FLIPENDIAN(key->fileID);
	FLIPENDIAN(key->startBlock);
	FLIPENDIAN(key->name.length);

	for(i = 0; i < nodeNameLength; i++) {
		FLIPENDIAN(key->name.unicode[i]);
	}

	if(!WRITE(io, offset, keyLength, key))
		return FALSE;

	free(key);

	return TRUE;
}
Esempio n. 2
0
static BTKey* attrKeyRead(off_t offset, io_func* io) {
	int i;
	HFSPlusAttrKey* key;

	key = (HFSPlusAttrKey*) malloc(sizeof(HFSPlusAttrKey));

	if(!READ(io, offset, UNICODE_START, key))
		return NULL;

	FLIPENDIAN(key->keyLength);
	FLIPENDIAN(key->fileID);
	FLIPENDIAN(key->startBlock);
	FLIPENDIAN(key->name.length);
	
	if(key->name.length > 254)
	{
		printf("Invalid xattr key at offset %x\n", offset);
		free(key);
		return NULL;
	}

	if(!READ(io, offset + UNICODE_START, key->name.length * sizeof(uint16_t), ((unsigned char *)key) + UNICODE_START))
		return NULL;

	for(i = 0; i < key->name.length; i++) {
		FLIPENDIAN(key->name.unicode[i]);
	}

	return (BTKey*)key;
}
Esempio n. 3
0
uint8* decrypt_key(const char* filesystem, uint8* passphrase) {
  int i = 0;
  EVP_CIPHER_CTX ctx;
  uint8 data[0x30];
  int outlen, tmplen = 0;
  
  FILE* fd = fopen(filesystem, "rb");
  if (fd == NULL) {
    fprintf(stderr, "error opening file: %s", filesystem);
    return NULL;
  }
  
  uint8* buffer = (uint8*) malloc(BUF_SIZE);
  if(buffer == NULL) {
  	fprintf(stderr, "unable to allocate memory\n");
  	fclose(fd);
  	return NULL;
  }
  
  fread(buffer, 1, sizeof(encrcdsa_header), fd);
  
  uint32 blocks = 0;
  fread(&blocks, 1, sizeof(uint32), fd);
  FLIPENDIAN(blocks);
  
  fread(buffer, 1, sizeof(encrcdsa_block) * blocks, fd);
  fread(buffer, 1, 0x80, fd);
  
  uint32 skip = 0;
  fread(&skip, 1, sizeof(uint32), fd);
  FLIPENDIAN(skip);
  fread(buffer, 1, skip-3, fd);
		
  uint8* out = malloc(0x30);
  free(buffer);

  for (i = 0; i < 0x20; i++) {
    if (fread(data, 1, 0x30, fd) <= 0) {
      fprintf(stderr, "Error reading filesystem image");
      free(out);
      return NULL;
    }
    
    if(data[0] == 0) break;

    EVP_CIPHER_CTX_init(&ctx);
    EVP_DecryptInit_ex(&ctx, EVP_des_ede3_cbc(), NULL, passphrase,
        &passphrase[24]);

    EVP_DecryptUpdate(&ctx, out, &outlen, data, 0x30);
    if (EVP_DecryptFinal_ex(&ctx, out + outlen, &tmplen)) {
      return out;
    }
    
    fseek(fd, 0x238, SEEK_CUR);
  }

  fclose(fd);
  return out;
}
Esempio n. 4
0
void flipCompHeader(CompHeader* header) {
    FLIPENDIAN(header->signature);
    FLIPENDIAN(header->compression_type);
    FLIPENDIAN(header->checksum);
    FLIPENDIAN(header->length_uncompressed);
    FLIPENDIAN(header->length_compressed);
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
void flipForkData(HFSPlusForkData* forkData) {
	FLIPENDIAN(forkData->logicalSize);
	FLIPENDIAN(forkData->clumpSize);
	FLIPENDIAN(forkData->totalBlocks);

	flipExtentRecord(&forkData->extents);
}
Esempio n. 7
0
static void flipCSumResource(unsigned char* data, char out) {
  CSumResource* cSum;
  
  cSum = (CSumResource*) data;
  
  FLIPENDIAN(cSum->version);
  FLIPENDIAN(cSum->type);
  FLIPENDIAN(cSum->checksum);
}
Esempio n. 8
0
void flipHFSPlusCmpfEnd(HFSPlusCmpfEnd* data) {
	FLIPENDIAN(data->unk1);
	FLIPENDIAN(data->unk2);
	FLIPENDIAN(data->unk3);
	FLIPENDIAN(data->magic);
	FLIPENDIAN(data->flags);
	FLIPENDIANLE(data->size);
	FLIPENDIANLE(data->unk4);
}
Esempio n. 9
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;
}
Esempio n. 10
0
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);
}
Esempio n. 11
0
AbstractFile* duplicateAbstractFile(AbstractFile* file, AbstractFile* backing) {
	uint32_t signatureBE;
	uint32_t signatureLE;
	AbstractFile* orig;

	if (!backing) { /* imagine that: createAbstractFileFromComp() fails, because of decompress_lzss() */
		return NULL;
	}
	
	file->seek(file, 0);
	file->read(file, &signatureBE, sizeof(signatureBE));
	signatureLE = signatureBE;
	FLIPENDIAN(signatureBE);
	FLIPENDIANLE(signatureLE);
	file->seek(file, 0);
	
	if(signatureLE == IMG2_SIGNATURE) {
		orig = createAbstractFileFromImg2(file);
		return duplicateAbstractFile(orig, duplicateImg2File(orig, backing));
	} else if(signatureLE == IMG3_SIGNATURE) {
		orig = createAbstractFileFromImg3(file);
		return duplicateAbstractFile(orig, duplicateImg3File(orig, backing));
	} else if(signatureBE == COMP_SIGNATURE) {
		orig = createAbstractFileFromComp(file);
		return duplicateAbstractFile(orig, duplicateCompFile(orig, backing));
	} else {
		file->close(file);
		return backing;
	}
}
Esempio n. 12
0
AbstractFile *openAbstractFile(AbstractFile * file)
{
	uint32_t signatureBE;
	uint32_t signatureLE;

	if (!file)
		return NULL;

	file->seek(file, 0);
	file->read(file, &signatureBE, sizeof(signatureBE));
	signatureLE = signatureBE;
	FLIPENDIAN(signatureBE);
	FLIPENDIANLE(signatureLE);
	file->seek(file, 0);
	if (signatureBE == SIGNATURE_8900) {
		return openAbstractFile(createAbstractFileFrom8900(file));
	} else if (signatureLE == IMG2_SIGNATURE) {
		return openAbstractFile(createAbstractFileFromImg2(file));
	} else if (signatureLE == IMG3_SIGNATURE) {
		return openAbstractFile(createAbstractFileFromImg3(file));
	} else if (signatureBE == COMP_SIGNATURE) {
		return openAbstractFile(createAbstractFileFromComp(file));
	} else {
		return file;
	}
}
Esempio n. 13
0
File: udif.c Progetto: 1butler1/xpwn
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]);
    }
  }
}
Esempio n. 14
0
AbstractFile *duplicateAbstractFile2(AbstractFile * file,
				     AbstractFile * backing,
				     const unsigned int *key,
				     const unsigned int *iv,
				     AbstractFile * certificate)
{
	uint32_t signatureBE;
	uint32_t signatureLE;
	AbstractFile *orig;
	AbstractFile *newFile;

	file->seek(file, 0);
	file->read(file, &signatureBE, sizeof(signatureBE));
	signatureLE = signatureBE;
	FLIPENDIAN(signatureBE);
	FLIPENDIANLE(signatureLE);
	file->seek(file, 0);

	if (signatureBE == SIGNATURE_8900) {
		orig = createAbstractFileFrom8900(file);
		newFile = duplicate8900File(orig, backing);
		if (certificate != NULL)
			replaceCertificate8900(newFile, certificate);
		return duplicateAbstractFile(orig, newFile);
	} else if (signatureLE == IMG2_SIGNATURE) {
		orig = createAbstractFileFromImg2(file);
		return duplicateAbstractFile(orig,
					     duplicateImg2File(orig, backing));
	} else if (signatureLE == IMG3_SIGNATURE) {
		AbstractFile2 *newFile;
		AbstractFile2 *img3;

		img3 = (AbstractFile2 *) createAbstractFileFromImg3(file);
		if (key != NULL)
			img3->setKey(img3, key, iv);

		newFile =
		    (AbstractFile2 *) duplicateImg3File((AbstractFile *) img3,
							backing);
		if (key != NULL)
			img3->setKey(newFile, key, iv);

		if (certificate != NULL)
			replaceCertificateImg3((AbstractFile *) newFile,
					       certificate);
		return duplicateAbstractFile((AbstractFile *) img3,
					     (AbstractFile *) newFile);
	} else if (signatureBE == COMP_SIGNATURE) {
		orig = createAbstractFileFromComp(file);
		return duplicateAbstractFile(orig,
					     duplicateCompFile(orig, backing));
	} else {
		file->close(file);
		return backing;
	}
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
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;
}
Esempio n. 17
0
void flipApple8900Header(Apple8900Header* header) {
	FLIPENDIAN(header->magic);
	FLIPENDIANLE(header->unknown1);
	FLIPENDIANLE(header->sizeOfData);
	FLIPENDIANLE(header->footerSignatureOffset);
	FLIPENDIANLE(header->footerCertOffset);
	FLIPENDIANLE(header->footerCertLen);
	FLIPENDIANLE(header->unknown2);
	FLIPENDIANLE(header->epoch);
}
Esempio n. 18
0
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);
}
Esempio n. 19
0
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] = ':';
	  }
	}
  }
}
Esempio n. 20
0
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);
}
Esempio n. 21
0
static void
doPartialSHA1(unsigned char md[SHA_DIGEST_LENGTH], const unsigned char *toHashData, int toHashLength, DataValue *partialDigest)
{
	const unsigned *q = (const unsigned *)partialDigest->value;
	unsigned v31 = q[0]; // XXX ASSERT(v31 == ecid->size == 64)?
	unsigned v32 = q[1];
	SHA_CTX hashctx;
	memset(&hashctx, 0, sizeof(hashctx));
	hashctx.h0 = q[2];
	hashctx.h1 = q[3];
	hashctx.h2 = q[4];
	hashctx.h3 = q[5];
	hashctx.h4 = q[6];
	FLIPENDIAN(hashctx.h0);
	FLIPENDIAN(hashctx.h1);
	FLIPENDIAN(hashctx.h2);
	FLIPENDIAN(hashctx.h3);
	FLIPENDIAN(hashctx.h4);
	FLIPENDIANLE(v32);
	hashctx.Nl = 8 * v32 + 64; // XXX could this 64 be actually v31?
	SHA1_Update(&hashctx, toHashData, toHashLength);
	SHA1_Final(md, &hashctx);
}
Esempio n. 22
0
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;
}
Esempio n. 23
0
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);
}
Esempio n. 24
0
void replaceCertificateAbstractFile(AbstractFile* file, AbstractFile* certificate) {
	uint32_t signatureBE;
	uint32_t signatureLE;
	AbstractFile* f;
	
	file->seek(file, 0);
	file->read(file, &signatureBE, sizeof(signatureBE));
	signatureLE = signatureBE;
	FLIPENDIAN(signatureBE);
	FLIPENDIANLE(signatureLE);
	file->seek(file, 0);

	if(signatureLE == IMG3_SIGNATURE) {
		f = createAbstractFileFromImg3(file);
		replaceCertificateImg3(f, certificate);
		f->close(f);
	}
}
Esempio n. 25
0
AbstractFile *openAbstractFile3(AbstractFile * file, const unsigned int *key,
				const unsigned int *iv, int layers)
{
	uint32_t signatureBE;
	uint32_t signatureLE;

	AbstractFile *cur;

	if (!file)
		return NULL;

	file->seek(file, 0);
	file->read(file, &signatureBE, sizeof(signatureBE));
	signatureLE = signatureBE;
	FLIPENDIAN(signatureBE);
	FLIPENDIANLE(signatureLE);
	file->seek(file, 0);

	if (signatureBE == SIGNATURE_8900) {
		cur = createAbstractFileFrom8900(file);
	} else if (signatureLE == IMG2_SIGNATURE) {
		cur = createAbstractFileFromImg2(file);
	} else if (signatureLE == IMG3_SIGNATURE) {
		AbstractFile2 *img3 =
		    (AbstractFile2 *) createAbstractFileFromImg3(file);

		if (key && iv)
			img3->setKey(img3, key, iv);
		cur = (AbstractFile *) img3;
		key = NULL;
		iv = NULL;
	} else if (signatureBE == COMP_SIGNATURE) {
		cur = createAbstractFileFromComp(file);
		key = NULL;
		iv = NULL;
	} else {
		return file;
	}

	if (layers < 0 || layers > 0)
		return openAbstractFile3(cur, key, iv, layers - 1);
	else
		return cur;
}
Esempio n. 26
0
static BTKey* attrDataRead(off_t offset, io_func* io) {
	HFSPlusAttrRecord* record;

	record = (HFSPlusAttrRecord*) malloc(sizeof(HFSPlusAttrRecord));

	if(!READ(io, offset, sizeof(uint32_t), record))
		return NULL;

	FLIPENDIAN(record->recordType);
	switch(record->recordType)
	{
		case kHFSPlusAttrInlineData:
			if(!READ(io, offset, sizeof(HFSPlusAttrData), record))
				return NULL;

			flipAttrData((HFSPlusAttrData*) record);

			record = realloc(record, sizeof(HFSPlusAttrData) + ((HFSPlusAttrData*) record)->size);
			if(!READ(io, offset + sizeof(HFSPlusAttrData), ((HFSPlusAttrData*) record)->size, ((HFSPlusAttrData*) record)->data))
				return NULL;

			break;

		case kHFSPlusAttrForkData:
			if(!READ(io, offset, sizeof(HFSPlusAttrForkData), record))
				return NULL;

			flipAttrForkData((HFSPlusAttrForkData*) record);

			break;

		case kHFSPlusAttrExtents:
			if(!READ(io, offset, sizeof(HFSPlusAttrExtents), record))
				return NULL;

			flipAttrExtents((HFSPlusAttrExtents*) record);

			break;
	}

	return (BTKey*)record;
}
Esempio n. 27
0
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;
}
Esempio n. 28
0
static inline void flipAttrForkData(HFSPlusAttrForkData* data) {
  FLIPENDIAN(data->recordType);
  flipForkData(&data->theFork);
}
Esempio n. 29
0
static inline void flipAttrData(HFSPlusAttrData* data) {
  FLIPENDIAN(data->recordType);
  FLIPENDIAN(data->size);
}
Esempio n. 30
0
static inline void flipAttrExtents(HFSPlusAttrExtents* data) {
  FLIPENDIAN(data->recordType);
  flipExtentRecord(&data->extents);
}