err = noErr;
*hint = 0;
+
+ // XXXdbg - preflight that there's enough space
+ err = BTCheckFreeSpace(GetFileControlBlock(vcb->extentsRefNum));
+ if (err)
+ return err;
+
MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK);
bzero(btIterator, sizeof(*btIterator));
if (err == noErr)
*hint = btIterator->hint.nodeNum;
+ (void) BTFlushPath(GetFileControlBlock(vcb->extentsRefNum));
+
FREE(btIterator, M_TEMP);
return err;
}
OSErr err;
err = noErr;
+
+ // XXXdbg - preflight that there's enough space
+ err = BTCheckFreeSpace(GetFileControlBlock(vcb->extentsRefNum));
+ if (err)
+ return err;
+
MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK);
bzero(btIterator, sizeof(*btIterator));
}
err = BTDeleteRecord(GetFileControlBlock(vcb->extentsRefNum), btIterator);
-
+ (void) BTFlushPath(GetFileControlBlock(vcb->extentsRefNum));
+
FREE(btIterator, M_TEMP);
return err;
}
// Need to find and change a record in Extents BTree
//
btFCB = GetFileControlBlock(vcb->extentsRefNum);
+
+ // XXXdbg - preflight that there's enough space
+ err = BTCheckFreeSpace(btFCB);
+ if (err)
+ return err;
+
MALLOC(btIterator, BTreeIterator *, sizeof(*btIterator), M_TEMP, M_WAITOK);
bzero(btIterator, sizeof(*btIterator));
if (err == noErr)
err = BTReplaceRecord(btFCB, btIterator, &btRecord, btRecordSize);
+ (void) BTFlushPath(btFCB);
}
else { // HFS Plus volume
HFSPlusExtentRecord foundData; // The extent data actually found
BlockMoveData(extentData, &foundData, sizeof(HFSPlusExtentRecord));
err = BTReplaceRecord(btFCB, btIterator, &btRecord, btRecordSize);
}
+ (void) BTFlushPath(btFCB);
}
FREE(btIterator, M_TEMP);
}
return true;
}
+
+
+//_________________________________________________________________________________
+//
+// Routine: NodesAreContiguous
+//
+// Purpose: Ensure that all b-tree nodes are contiguous on disk
+// Called by BTOpenPath during volume mount
+//_________________________________________________________________________________
+
+Boolean NodesAreContiguous(
+ ExtendedVCB *vcb,
+ FCB *fcb,
+ UInt32 nodeSize)
+{
+ UInt32 mask;
+ UInt32 startBlock;
+ UInt32 blocksChecked;
+ UInt32 hint;
+ HFSPlusExtentKey key;
+ HFSPlusExtentRecord extents;
+ OSErr result;
+ Boolean lastExtentReached;
+
+
+ if (vcb->blockSize >= nodeSize)
+ return TRUE;
+
+ mask = (nodeSize / vcb->blockSize) - 1;
+
+ // check the local extents
+ (void) GetFCBExtentRecord(fcb, extents);
+ if ( !ExtentsAreIntegral(extents, mask, &blocksChecked, &lastExtentReached) )
+ return FALSE;
+
+ if (lastExtentReached || (SInt64)((SInt64)blocksChecked * (SInt64)vcb->blockSize) >= fcb->ff_size)
+ return TRUE;
+
+ startBlock = blocksChecked;
+
+ // check the overflow extents (if any)
+ while ( !lastExtentReached )
+ {
+ result = FindExtentRecord(vcb, kDataForkType, fcb->ff_cp->c_fileid, startBlock, FALSE, &key, extents, &hint);
+ if (result) break;
+
+ if ( !ExtentsAreIntegral(extents, mask, &blocksChecked, &lastExtentReached) )
+ return FALSE;
+
+ startBlock += blocksChecked;
+ }
+
+ return TRUE;
+}
+