in hfs/btree.c [916:996]
static uint32_t splitNode(uint32_t node, BTNodeDescriptor* descriptor, BTree* tree) {
int nodesToMove;
int i;
off_t internalOffset;
BTNodeDescriptor* fDescriptor;
BTNodeDescriptor newDescriptor;
uint32_t newNodeNum;
off_t newNodeOffset;
off_t toMove;
size_t toMoveLength;
unsigned char *buffer;
off_t offsetsToMove;
size_t offsetsToMoveLength;
uint16_t *offsetsBuffer;
nodesToMove = descriptor->numRecords - (descriptor->numRecords/2);
toMove = getRecordOffset(descriptor->numRecords/2, node, tree);
toMoveLength = getRecordOffset(descriptor->numRecords, node, tree) - toMove;
buffer = (unsigned char *)malloc(toMoveLength);
ASSERT(READ(tree->io, toMove, toMoveLength, buffer), "READ");
offsetsToMove = (node * tree->headerRec->nodeSize) + tree->headerRec->nodeSize - (sizeof(uint16_t) * (descriptor->numRecords + 1));
offsetsToMoveLength = sizeof(uint16_t) * (nodesToMove + 1);
offsetsBuffer = (uint16_t *)malloc(offsetsToMoveLength);
ASSERT(READ(tree->io, offsetsToMove, offsetsToMoveLength, offsetsBuffer), "READ");
for(i = 0; i < (nodesToMove + 1); i++) {
FLIPENDIAN(offsetsBuffer[i]);
}
internalOffset = offsetsBuffer[nodesToMove] - 14;
for(i = 0; i < (nodesToMove + 1); i++) {
offsetsBuffer[i] -= internalOffset;
FLIPENDIAN(offsetsBuffer[i]);
}
newNodeNum = getNewNode(tree);
newNodeOffset = newNodeNum * tree->headerRec->nodeSize;
newDescriptor.fLink = descriptor->fLink;
newDescriptor.bLink = node;
newDescriptor.kind = descriptor->kind;
newDescriptor.height = descriptor->height;
newDescriptor.numRecords = nodesToMove;
newDescriptor.reserved = 0;
ASSERT(writeBTNodeDescriptor(&newDescriptor, newNodeNum, tree), "writeBTNodeDescriptor");
if(newDescriptor.fLink != 0) {
fDescriptor = readBTNodeDescriptor(newDescriptor.fLink, tree);
fDescriptor->bLink = newNodeNum;
ASSERT(writeBTNodeDescriptor(fDescriptor, newDescriptor.fLink, tree), "writeBTNodeDescriptor");
free(fDescriptor);
}
descriptor->fLink = newNodeNum;
descriptor->numRecords = descriptor->numRecords/2;
ASSERT(writeBTNodeDescriptor(descriptor, node, tree), "writeBTNodeDescriptor");
ASSERT(WRITE(tree->io, newNodeOffset + 14, toMoveLength, buffer), "WRITE");
ASSERT(WRITE(tree->io, newNodeOffset + tree->headerRec->nodeSize - (sizeof(uint16_t) * (nodesToMove + 1)), offsetsToMoveLength, offsetsBuffer), "WRITE");
// The offset for the existing descriptor's new numRecords will happen to be where the old data was, which is now where the free space starts
// So we don't have to manually set the free space offset
free(buffer);
free(offsetsBuffer);
if(descriptor->kind == kBTLeafNode && node == tree->headerRec->lastLeafNode) {
tree->headerRec->lastLeafNode = newNodeNum;
ASSERT(writeBTHeaderRec(tree), "writeBTHeaderRec");
}
return newNodeNum;
}