-/*-------------------------------------------------------------------------------
-
-Routine: CheckNode - Checks the validity of a node.
-
-Function: Checks the validity of a node by verifying that the fLink and bLink fields
- are within the forks EOF. The node type must be one of the four known
- types. The node height must be less than or equal to the tree height. The
- node must not have more than the maximum number of records, and the record
- offsets must make sense.
-
-Input: btreePtr - pointer to BTree control block
- node - pointer to node to check
-
-Result: noErr - success
- fsBTInvalidNodeErr - failure
--------------------------------------------------------------------------------*/
-
-OSStatus CheckNode (BTreeControlBlockPtr btreePtr, NodeDescPtr node )
-{
- SInt32 index;
- SInt32 maxRecords;
- UInt32 maxNode;
- UInt16 nodeSize;
- UInt16 offset;
- UInt16 prevOffset;
-
- nodeSize = btreePtr->nodeSize;
-
- ///////////////////// are fLink and bLink within EOF ////////////////////////
-
- maxNode = (GetFileControlBlock(btreePtr->fileRefNum)->fcbEOF / nodeSize) - 1;
-
- if ( (node->fLink > maxNode) || (node->bLink > maxNode) )
- return fsBTInvalidNodeErr;
-
- /////////////// check node type (leaf, index, header, map) //////////////////
-
- if ( (node->kind < kBTLeafNode) || (node->kind > kBTMapNode) )
- return fsBTInvalidNodeErr;
-
- ///////////////////// is node height > tree depth? //////////////////////////
-
- if ( node->height > btreePtr->treeDepth )
- return fsBTInvalidNodeErr;
-
- //////////////////////// check number of records ////////////////////////////
-
- //XXX can we calculate a more accurate minimum record size?
- maxRecords = ( nodeSize - sizeof (BTNodeDescriptor) ) >> 3;
-
- if (node->numRecords > maxRecords)
- return fsBTInvalidNodeErr;
-
- ////////////////////////// check record offsets /////////////////////////////
-
- index = node->numRecords; /* start index at free space */
- prevOffset = nodeSize - (index << 1); /* use 2 bytes past end of free space */
-
- do {
- offset = GetRecordOffset (btreePtr, node, index);
-
- if (offset & 1) // offset is odd
- return fsBTInvalidNodeErr;
-
- if (offset >= prevOffset) // offset >= previous offset
- return fsBTInvalidNodeErr;
-
- /* reject keys that overflow record slot */
- if ((node->kind == kBTLeafNode) &&
- (index < node->numRecords) && /* ignore free space record */
- (CalcKeySize(btreePtr, (KeyPtr) ((Ptr)node + offset)) > (prevOffset - offset))) {
- return fsBTInvalidNodeErr;
- }
-
- prevOffset = offset;
- } while ( --index >= 0 );
-
- if (offset < sizeof (BTNodeDescriptor) ) // first offset < minimum ?
- return fsBTInvalidNodeErr;
-
- return noErr;
-}
-
-