#include "Scavenger.h"
int utf_encodestr(ucsp, ucslen, utf8p, utf8len)
const u_int16_t * ucsp;
size_t ucslen;
u_int8_t * utf8p;
size_t * utf8len;
{
u_int8_t * bufstart;
u_int16_t ucs_ch;
int charcnt;
bufstart = utf8p;
charcnt = ucslen / 2;
while (charcnt-- > 0) {
ucs_ch = *ucsp++;
if (ucs_ch < 0x0080) {
if (ucs_ch == '\0')
continue;
*utf8p++ = ucs_ch;
} else if (ucs_ch < 0x800) {
*utf8p++ = (ucs_ch >> 6) | 0xc0;
*utf8p++ = (ucs_ch & 0x3f) | 0x80;
} else {
*utf8p++ = (ucs_ch >> 12) | 0xe0;
*utf8p++ = ((ucs_ch >> 6) & 0x3f) | 0x80;
*utf8p++ = ((ucs_ch) & 0x3f) | 0x80;
}
}
*utf8len = utf8p - bufstart;
return (0);
}
int
utf_decodestr(utf8p, utf8len, ucsp, ucslen)
const u_int8_t* utf8p;
size_t utf8len;
u_int16_t* ucsp;
size_t *ucslen;
{
u_int16_t* bufstart;
u_int16_t ucs_ch;
u_int8_t byte;
bufstart = ucsp;
while (utf8len-- > 0 && (byte = *utf8p++) != '\0') {
if (byte < 0x80) {
*ucsp++ = byte;
continue;
}
switch (byte & 0xf0) {
case 0xc0:
case 0xd0:
ucs_ch = (byte & 0x1F) << 6;
if (ucs_ch < 0x0080)
return (-1);
break;
case 0xe0:
ucs_ch = (byte & 0x0F) << 6;
if (((byte = *utf8p++) & 0xc0) != 0x80)
return (-1);
utf8len--;
ucs_ch += (byte & 0x3F);
ucs_ch <<= 6;
if (ucs_ch < 0x0800)
return (-1);
break;
default:
return (-1);
}
if (((byte = *utf8p++) & 0xc0) != 0x80)
return (-1);
utf8len--;
ucs_ch += (byte & 0x3F);
*ucsp++ = ucs_ch;
}
*ucslen = (u_int8_t*)ucsp - (u_int8_t*)bufstart;
return (0);
}
OSErr GetFBlk( SGlobPtr GPtr, SInt16 fileRefNum, SInt32 blockNumber, void **bufferH );
UInt32 gDFAStage;
UInt32 GetDFAStage( void )
{
return (gDFAStage);
}
void SetDFAStage( UInt32 stage )
{
gDFAStage = stage;
}
void RcdError( SGlobPtr GPtr, OSErr errorCode )
{
GPtr->ErrCode = errorCode;
WriteError( GPtr, errorCode, GPtr->TarID, GPtr->TarBlock ); }
int IntError( SGlobPtr GPtr, OSErr errorCode )
{
GPtr->RepLevel = repairLevelUnrepairable;
if ( errorCode == ioErr ) errorCode = R_RdErr;
if( (errorCode == R_RdErr) || (errorCode == R_WrErr) )
{
GPtr->ErrCode = GPtr->volumeErrorCode;
GPtr->IntErr = 0;
return( errorCode );
}
else
{
GPtr->ErrCode = R_IntErr;
GPtr->IntErr = errorCode;
return( R_IntErr );
}
}
int AllocBTN( SGlobPtr GPtr, SInt16 fileRefNum, UInt32 nodeNumber )
{
UInt16 bitPos;
unsigned char mask;
char *byteP;
BTreeControlBlock *calculatedBTCB = GetBTreeControlBlock( fileRefNum );
byteP = ( (BTreeExtensionsRec*)calculatedBTCB->refCon)->BTCBMPtr + (nodeNumber / 8 ); bitPos = nodeNumber % 8; mask = ( 0x80 >> bitPos );
if ( (*byteP & mask) != 0 )
{
RcdError( GPtr, E_OvlNode );
return( E_OvlNode ); }
*byteP = *byteP | mask; calculatedBTCB->freeNodes--;
return( noErr );
}
OSErr GetBTreeHeader( SGlobPtr GPtr, SFCB *fcb, BTHeaderRec *header )
{
OSErr err;
Ptr headerPtr;
BlockDescriptor block;
GPtr->TarBlock = kHeaderNodeNum;
if (fcb->fcbBlockSize == 0)
(void) SetFileBlockSize(fcb, 512);
err = GetFileBlock(fcb, kHeaderNodeNum, kGetBlock, &block);
ReturnIfError(err);
headerPtr = (char*)block.buffer + sizeof(BTNodeDescriptor);
CopyMemory(headerPtr, header, sizeof(BTHeaderRec));
err = ReleaseFileBlock (fcb, &block, kReleaseBlock);
ReturnIfError(err);
switch (header->nodeSize) {
case 512:
case 1024:
case 2048:
case 4096:
case 8192:
case 16384:
case 32768:
break;
default:
RcdError( GPtr, E_InvalidNodeSize );
err = E_InvalidNodeSize;
}
return( err );
}
RepairOrderPtr AllocMinorRepairOrder( SGlobPtr GPtr, int n )
{
RepairOrderPtr p;
n += sizeof( RepairOrder );
p = (RepairOrderPtr) AllocateClearMemory( n );
if ( p != NULL ) {
p->link = GPtr->MinorRepairsP; GPtr->MinorRepairsP = p;
}
if ( GPtr->RepLevel == repairLevelNoProblemsFound )
GPtr->RepLevel = repairLevelVolumeRecoverable;
return( p ); }
void InvalidateCalculatedVolumeBitMap( SGlobPtr GPtr )
{
}
#if !BSD
OSErr GetVolumeFeatures( SGlobPtr GPtr )
{
OSErr err;
HParamBlockRec pb;
GetVolParmsInfoBuffer buffer;
long response;
GPtr->volumeFeatures = 0;
err = GetVCBDriveNum( &GPtr->realVCB, GPtr->DrvNum );
ReturnIfError( err );
if ( GPtr->realVCB != nil )
{
GPtr->volumeFeatures |= volumeIsMountedMask;
pb.ioParam.ioNamePtr = nil;
pb.ioParam.ioVRefNum = GPtr->realVCB->vcbVRefNum;
pb.ioParam.ioBuffer = (Ptr) &buffer;
pb.ioParam.ioReqCount = sizeof( buffer );
if ( PBHGetVolParms( &pb, false ) == noErr )
{
if ( buffer.vMAttrib & (1 << bSupportsTrashVolumeCache) )
GPtr->volumeFeatures |= supportsTrashVolumeCacheFeatureMask;
}
}
err = Gestalt( gestaltFSAttr, &response );
ReturnIfError( err );
if ( (response & (1 << gestaltFSSupportsHFSPlusVols)) != 0 )
GPtr->volumeFeatures |= supportsHFSPlusVolsFeatureMask;
return( noErr );
}
#endif
#if !BSD
void ClearMemory( void* start, UInt32 length )
{
UInt32 zero = 0;
UInt32* dataPtr;
UInt8* bytePtr;
UInt32 fragCount;
if ( length == 0 )
return;
if ( length < 4 ) {
bytePtr = (UInt8 *) start;
do
{
*bytePtr++ = zero; }
while ( --length );
return;
}
fragCount = (UInt32) start & 3;
if ( fragCount ) {
bytePtr = (UInt8 *) start;
do
{
*bytePtr++ = zero; ++fragCount;
--length;
}
while ( (fragCount < 4) && (length > 0) );
if ( length == 0 )
return;
dataPtr = (UInt32*) (((UInt32) start & 0xFFFFFFFC) + 4); }
else
{
dataPtr = (UInt32*) ((UInt32) start & 0xFFFFFFFC); }
fragCount = length & 3;
if ( fragCount )
{
bytePtr = (UInt8 *) ((UInt32) dataPtr + (UInt32) length - 1);
length -= fragCount;
do
{
*bytePtr-- = zero; }
while ( --fragCount );
if ( length == 0 )
return;
}
#if DEBUG_BUILD
if ( length < 4 )
DebugStr("\p ClearMemory: length < 4");
#endif
fragCount = length & (64-1);
#if DEBUG_BUILD
if ( fragCount < 4 && fragCount > 0 )
DebugStr("\p ClearMemory: fragCount < 4");
#endif
if ( fragCount )
{
length -= fragCount; fragCount >>= 2; do
{
*dataPtr++ = zero;
}
while (--fragCount);
}
if ( length == 0 )
return;
length >>= 6; do
{
*dataPtr++ = zero; *dataPtr++ = zero; *dataPtr++ = zero; *dataPtr++ = zero;
*dataPtr++ = zero; *dataPtr++ = zero; *dataPtr++ = zero; *dataPtr++ = zero;
*dataPtr++ = zero; *dataPtr++ = zero; *dataPtr++ = zero; *dataPtr++ = zero;
*dataPtr++ = zero; *dataPtr++ = zero; *dataPtr++ = zero; *dataPtr++ = zero;
}
while (--length);
}
#endif
void
CopyCatalogName(const CatalogName *srcName, CatalogName *dstName, Boolean isHFSPLus)
{
UInt32 length;
if ( srcName == NULL )
{
if ( dstName != NULL )
dstName->ustr.length = 0; return;
}
if (isHFSPLus)
length = sizeof(UniChar) * (srcName->ustr.length + 1);
else
length = sizeof(UInt8) + srcName->pstr[0];
if ( length > 1 )
CopyMemory(srcName, dstName, length);
else
dstName->ustr.length = 0; }
UInt32
CatalogNameLength(const CatalogName *name, Boolean isHFSPlus)
{
if (isHFSPlus)
return name->ustr.length;
else
return name->pstr[0];
}
UInt32 CatalogNameSize( const CatalogName *name, Boolean isHFSPlus)
{
UInt32 length = CatalogNameLength( name, isHFSPlus );
if ( isHFSPlus )
length *= sizeof(UniChar);
return( length );
}
void
BuildCatalogKey(HFSCatalogNodeID parentID, const CatalogName *cName, Boolean isHFSPlus, CatalogKey *key)
{
if ( isHFSPlus )
{
key->hfsPlus.keyLength = kHFSPlusCatalogKeyMinimumLength; key->hfsPlus.parentID = parentID; key->hfsPlus.nodeName.length = 0; if ( cName != NULL )
{
CopyCatalogName(cName, (CatalogName *) &key->hfsPlus.nodeName, isHFSPlus);
key->hfsPlus.keyLength += sizeof(UniChar) * cName->ustr.length; }
}
else
{
key->hfs.keyLength = kHFSCatalogKeyMinimumLength; key->hfs.reserved = 0; key->hfs.parentID = parentID; key->hfs.nodeName[0] = 0; if ( cName != NULL )
{
UpdateCatalogName(cName->pstr, key->hfs.nodeName);
key->hfs.keyLength += key->hfs.nodeName[0]; }
}
}
SInt32 CompareKeys( BTreeControlBlockPtr btreePtr, KeyPtr searchKey, KeyPtr trialKey )
{
KeyCompareProcPtr compareProc = (KeyCompareProcPtr)btreePtr->keyCompareProc;
return( compareProc(searchKey, trialKey) );
}
void
UpdateCatalogName(ConstStr31Param srcName, Str31 destName)
{
Size length = srcName[0];
if (length > kHFSMaxFileNameChars)
length = kHFSMaxFileNameChars;
destName[0] = length;
CopyMemory(&srcName[1], &destName[1], length);
}
void
UpdateVolumeEncodings(SVCB *volume, TextEncoding encoding)
{
UInt32 index;
encoding &= 0x7F;
index = MapEncodingToIndex(encoding);
volume->vcbEncodingsBitmap |= (1 << index);
}
OSErr ValidVolumeHeader( HFSPlusVolumeHeader *volumeHeader )
{
OSErr err;
if ( volumeHeader->signature == kHFSPlusSigWord && volumeHeader->version == kHFSPlusVersion )
{
if ( (volumeHeader->blockSize != 0) && ((volumeHeader->blockSize & 0x01FF) == 0) ) err = noErr;
else
err = badMDBErr; }
else
{
err = noMacDskErr;
}
return( err );
}
void InitBTreeHeader (UInt32 fileSize, UInt32 clumpSize, UInt16 nodeSize, UInt16 recordCount, UInt16 keySize,
UInt32 attributes, UInt32 *mapNodes, void *buffer)
{
UInt32 nodeCount;
UInt32 usedNodes;
UInt32 nodeBitsInHeader;
BTHeaderRec *bth;
BTNodeDescriptor *ndp;
UInt32 *bitMapPtr;
SInt16 *offsetPtr;
ClearMemory(buffer, nodeSize);
nodeCount = fileSize / nodeSize;
nodeBitsInHeader = 8 * (nodeSize - sizeof(BTNodeDescriptor) - sizeof(BTHeaderRec) - kBTreeHeaderUserBytes - 4*sizeof(SInt16));
usedNodes = 1; *mapNodes = 0;
ndp = (BTNodeDescriptor*) buffer;
ndp->kind = kBTHeaderNode; ndp->numRecords = 3;
if (nodeCount > nodeBitsInHeader) {
UInt32 nodeBitsInMapNode;
nodeBitsInMapNode = 8 * (nodeSize - sizeof(BTNodeDescriptor) - 2*sizeof(SInt16) - 2);
if (recordCount > 0) ndp->fLink = 2; else
ndp->fLink = 1;
*mapNodes = (nodeCount - nodeBitsInHeader + (nodeBitsInMapNode - 1)) / nodeBitsInMapNode;
usedNodes += *mapNodes;
}
bth = (BTHeaderRec*) ((char*)buffer + sizeof(BTNodeDescriptor));
if (recordCount > 0)
{
++usedNodes;
bth->treeDepth = 1; bth->rootNode = 1; bth->firstLeafNode = 1; bth->lastLeafNode = 1; }
bth->attributes = attributes; bth->leafRecords = recordCount; bth->nodeSize = nodeSize; bth->maxKeyLength = keySize; bth->totalNodes = nodeCount; bth->freeNodes = nodeCount - usedNodes; bth->clumpSize = clumpSize;
bitMapPtr = (UInt32*) ((Byte*) buffer + sizeof(BTNodeDescriptor) + sizeof(BTHeaderRec) + kBTreeHeaderUserBytes);
*bitMapPtr = ~((UInt32) 0xFFFFFFFF >> usedNodes);
offsetPtr = (SInt16*) ((Byte*) buffer + nodeSize - 4*sizeof(SInt16));
*offsetPtr++ = sizeof(BTNodeDescriptor) + sizeof(BTHeaderRec) + kBTreeHeaderUserBytes + nodeBitsInHeader/8; *offsetPtr++ = sizeof(BTNodeDescriptor) + sizeof(BTHeaderRec) + kBTreeHeaderUserBytes; *offsetPtr++ = sizeof(BTNodeDescriptor) + sizeof(BTHeaderRec); *offsetPtr = sizeof(BTNodeDescriptor); }
void CalculateItemCount( SGlob *GPtr, UInt64 *itemCount, UInt64 *onePercent )
{
BTreeControlBlock *btcb;
UInt64 items;
UInt32 realFreeNodes;
SVCB* vcb = GPtr->calculatedVCB;
items = GPtr->calculatedVCB->vcbTotalBlocks / 1024;
btcb = (BTreeControlBlock*) vcb->vcbCatalogFile->fcbBtree;
realFreeNodes = ((BTreeExtensionsRec*)btcb->refCon)->realFreeNodeCount;
items += (2 * btcb->leafRecords) + (btcb->totalNodes - realFreeNodes);
btcb = (BTreeControlBlock*) vcb->vcbExtentsFile->fcbBtree;
realFreeNodes = ((BTreeExtensionsRec*)btcb->refCon)->realFreeNodeCount;
items += btcb->leafRecords + (btcb->totalNodes - realFreeNodes);
if ( vcb->vcbAttributesFile != NULL )
{
btcb = (BTreeControlBlock*) vcb->vcbAttributesFile->fcbBtree;
realFreeNodes = ((BTreeExtensionsRec*)btcb->refCon)->realFreeNodeCount;
items += (btcb->leafRecords + (btcb->totalNodes - realFreeNodes));
}
*onePercent = items/ 100;
if ( (GPtr->volumeType == kEmbededHFSPlusVolumeType) && (GPtr->inputFlags & examineWrapperMask) )
items *= 100;
items += *onePercent * 5;
*itemCount = items;
}
SFCB* ResolveFCB(short fileRefNum)
{
return( (SFCB*)((unsigned long)GetFCBSPtr() + (unsigned long)fileRefNum) );
}
void SetupFCB( SVCB *vcb, SInt16 refNum, UInt32 fileID, UInt32 fileClumpSize )
{
SFCB *fcb;
fcb = ResolveFCB(refNum);
fcb->fcbFileID = fileID;
fcb->fcbVolume = vcb;
fcb->fcbClumpSize = fileClumpSize;
}
pascal short ResolveFileRefNum(SFCB * fileCtrlBlockPtr)
{
return( (unsigned long)fileCtrlBlockPtr - (unsigned long)GetFCBSPtr() );
}
Ptr gFCBSPtr;
void SetFCBSPtr( Ptr value )
{
gFCBSPtr = value;
}
Ptr GetFCBSPtr( void )
{
return (gFCBSPtr);
}
OSErr FlushVolumeControlBlock( SVCB *vcb )
{
OSErr err;
HFSPlusVolumeHeader *volumeHeader;
SFCB *fcb;
BlockDescriptor block;
if ( ! IsVCBDirty( vcb ) ) return( noErr );
if ( vcb->vcbSignature == kHFSPlusSigWord )
{
err = GetVolumeBlock(vcb, (vcb->vcbEmbeddedOffset / 512) + 2, kGetBlock, &block);
ReturnIfError( err );
volumeHeader = (HFSPlusVolumeHeader *) block.buffer;
if ( vcb->vcbEmbeddedOffset != 0 ) {
HFSMasterDirectoryBlock *mdb;
BlockDescriptor mdb_block;
err = GetVolumeBlock(vcb, 2, kGetBlock, &mdb_block);
if ( err == noErr )
{
mdb = (HFSMasterDirectoryBlock *) mdb_block.buffer;
if ( mdb->drCrDate != vcb->vcbCreateDate ) {
mdb->drCrDate = vcb->vcbCreateDate;
(void) ReleaseVolumeBlock(vcb, &mdb_block, kForceWriteBlock);
}
else
{
(void) ReleaseVolumeBlock(vcb, &mdb_block, kReleaseBlock);
}
}
}
volumeHeader->attributes = vcb->vcbAttributes;
volumeHeader->lastMountedVersion = kFSCKMountVersion;
volumeHeader->createDate = vcb->vcbCreateDate; volumeHeader->modifyDate = vcb->vcbModifyDate;
volumeHeader->backupDate = vcb->vcbBackupDate;
volumeHeader->checkedDate = vcb->vcbCheckedDate;
volumeHeader->fileCount = vcb->vcbFileCount;
volumeHeader->folderCount = vcb->vcbFolderCount;
volumeHeader->blockSize = vcb->vcbBlockSize;
volumeHeader->totalBlocks = vcb->vcbTotalBlocks;
volumeHeader->freeBlocks = vcb->vcbFreeBlocks;
volumeHeader->nextAllocation = vcb->vcbNextAllocation;
volumeHeader->rsrcClumpSize = vcb->vcbRsrcClumpSize;
volumeHeader->dataClumpSize = vcb->vcbDataClumpSize;
volumeHeader->nextCatalogID = vcb->vcbNextCatalogID;
volumeHeader->writeCount = vcb->vcbWriteCount;
volumeHeader->encodingsBitmap = vcb->vcbEncodingsBitmap;
volumeHeader->allocationFile.clumpSize = vcb->vcbAllocationFile->fcbClumpSize;
volumeHeader->extentsFile.clumpSize = vcb->vcbExtentsFile->fcbClumpSize;
volumeHeader->catalogFile.clumpSize = vcb->vcbCatalogFile->fcbClumpSize;
CopyMemory( vcb->vcbFinderInfo, volumeHeader->finderInfo, sizeof(volumeHeader->finderInfo) );
fcb = vcb->vcbExtentsFile;
CopyMemory( fcb->fcbExtents32, volumeHeader->extentsFile.extents, sizeof(HFSPlusExtentRecord) );
volumeHeader->extentsFile.logicalSize = fcb->fcbLogicalSize;
volumeHeader->extentsFile.totalBlocks = fcb->fcbPhysicalSize / vcb->vcbBlockSize;
fcb = vcb->vcbCatalogFile;
CopyMemory( fcb->fcbExtents32, volumeHeader->catalogFile.extents, sizeof(HFSPlusExtentRecord) );
volumeHeader->catalogFile.logicalSize = fcb->fcbLogicalSize;
volumeHeader->catalogFile.totalBlocks = fcb->fcbPhysicalSize / vcb->vcbBlockSize;
fcb = vcb->vcbAllocationFile;
CopyMemory( fcb->fcbExtents32, volumeHeader->allocationFile.extents, sizeof(HFSPlusExtentRecord) );
volumeHeader->allocationFile.logicalSize = fcb->fcbLogicalSize;
volumeHeader->allocationFile.totalBlocks = fcb->fcbPhysicalSize / vcb->vcbBlockSize;
if (vcb->vcbAttributesFile != NULL) {
fcb = vcb->vcbAttributesFile;
CopyMemory( fcb->fcbExtents32, volumeHeader->attributesFile.extents, sizeof(HFSPlusExtentRecord) );
volumeHeader->attributesFile.logicalSize = fcb->fcbLogicalSize;
volumeHeader->attributesFile.clumpSize = fcb->fcbClumpSize;
volumeHeader->attributesFile.totalBlocks = fcb->fcbPhysicalSize / vcb->vcbBlockSize;
}
err = ReleaseVolumeBlock(vcb, &block, kForceWriteBlock);
MarkVCBClean( vcb );
}
else
{
HFSMasterDirectoryBlock *mdbP;
err = GetVolumeBlock(vcb, MDB_BlkN, kGetBlock, &block);
ReturnIfError(err);
mdbP = (HFSMasterDirectoryBlock *) block.buffer;
mdbP->drCrDate = vcb->vcbCreateDate;
mdbP->drLsMod = vcb->vcbModifyDate;
mdbP->drAtrb = (UInt16)vcb->vcbAttributes;
mdbP->drClpSiz = vcb->vcbDataClumpSize;
mdbP->drNxtCNID = vcb->vcbNextCatalogID;
mdbP->drFreeBks = vcb->vcbFreeBlocks;
mdbP->drXTClpSiz = vcb->vcbExtentsFile->fcbClumpSize;
mdbP->drCTClpSiz = vcb->vcbCatalogFile->fcbClumpSize;
mdbP->drNmFls = vcb->vcbNmFls;
mdbP->drNmRtDirs = vcb->vcbNmRtDirs;
mdbP->drFilCnt = vcb->vcbFileCount;
mdbP->drDirCnt = vcb->vcbFolderCount;
err = ReleaseVolumeBlock(vcb, &block, kForceWriteBlock);
MarkVCBClean( vcb );
}
return( err );
}
OSErr FlushAlternateVolumeControlBlock( SVCB *vcb, Boolean isHFSPlus )
{
OSErr err;
UInt64 primaryBlockLocation;
UInt64 alternateBlockLocation;
BlockDescriptor pri_block, alt_block;
err = FlushVolumeControlBlock( vcb );
if ( isHFSPlus ) {
primaryBlockLocation = (vcb->vcbEmbeddedOffset / 512) + 2;
alternateBlockLocation = ((UInt64)vcb->vcbEmbeddedOffset / 512) +
(UInt64)vcb->vcbTotalBlocks * (UInt64)(vcb->vcbBlockSize / 512) - 2;
} else {
UInt64 sectors;
UInt32 sectorSize;
err = GetDeviceSize( vcb->vcbDriveNumber, §ors, §orSize );
ReturnIfError(err);
primaryBlockLocation = 2;
alternateBlockLocation = sectors - 2;
}
err = GetVolumeBlock(vcb, primaryBlockLocation, kGetBlock, &pri_block);
ReturnIfError(err);
err = GetVolumeBlock(vcb, alternateBlockLocation, kGetBlock, &alt_block);
if (err == noErr) {
CopyMemory(pri_block.buffer, alt_block.buffer, 512);
(void) ReleaseVolumeBlock(vcb, &alt_block, rbWriteMask);
}
(void) ReleaseVolumeBlock(vcb, &pri_block, kReleaseBlock);
return( err );
}
void
ConvertToHFSPlusExtent( const HFSExtentRecord oldExtents, HFSPlusExtentRecord newExtents)
{
UInt16 i;
for (i = kHFSPlusExtentDensity-1; i > 2; --i)
{
newExtents[i].blockCount = 0;
newExtents[i].startBlock = 0;
}
newExtents[2].blockCount = oldExtents[2].blockCount;
newExtents[2].startBlock = oldExtents[2].startBlock;
newExtents[1].blockCount = oldExtents[1].blockCount;
newExtents[1].startBlock = oldExtents[1].startBlock;
newExtents[0].blockCount = oldExtents[0].blockCount;
newExtents[0].startBlock = oldExtents[0].startBlock;
}
OSErr CacheWriteInPlace( SVCB *vcb, UInt32 fileRefNum, HIOParam *iopb, UInt32 currentPosition, UInt32 maximumBytes, UInt32 *actualBytes )
{
OSErr err;
UInt64 diskBlock;
UInt32 contiguousBytes;
void* buffer;
*actualBytes = 0;
buffer = (char*)iopb->ioBuffer + iopb->ioActCount;
err = MapFileBlockC(vcb, ResolveFCB(fileRefNum), maximumBytes, (currentPosition >> kSectorShift),
&diskBlock, &contiguousBytes );
if (err)
return (err);
err = DeviceWrite(vcb->vcbDriverWriteRef, vcb->vcbDriveNumber, buffer, (diskBlock << Log2BlkLo), contiguousBytes, actualBytes);
return( err );
}