static int growBTree()

in hfs/btree.c [755:837]


static int growBTree(BTree* tree) {
  int i;
  unsigned char* buffer;
  uint16_t offset;
  
  uint32_t byteNumber;
  uint32_t mapNode;
  int increasedNodes;
  
  off_t newNodeOffset;
  uint32_t newNodesStart;
  
  BTNodeDescriptor* descriptor;
  BTNodeDescriptor newDescriptor;
  
  allocate((RawFile*)(tree->io->data), ((RawFile*)(tree->io->data))->forkData->logicalSize + ((RawFile*)(tree->io->data))->forkData->clumpSize);
  increasedNodes = (((RawFile*)(tree->io->data))->forkData->logicalSize/tree->headerRec->nodeSize) - tree->headerRec->totalNodes;
  
  newNodesStart = tree->headerRec->totalNodes / tree->headerRec->nodeSize;
  
  tree->headerRec->freeNodes += increasedNodes;
  tree->headerRec->totalNodes += increasedNodes;
  
  byteNumber = tree->headerRec->totalNodes / 8;
  mapNode = 0;

  buffer = (unsigned char*) malloc(tree->headerRec->nodeSize - 20);
  for(i = 0; i < (tree->headerRec->nodeSize - 20); i++) {
    buffer[i] = 0;
  }
  
  if(byteNumber < (tree->headerRec->nodeSize - 256)) {
    ASSERT(writeBTHeaderRec(tree), "writeBTHeaderREc");
    free(buffer);
    return TRUE;
  } else {
    byteNumber -= tree->headerRec->nodeSize - 256;
    
    while(TRUE) {
      descriptor = readBTNodeDescriptor(mapNode, tree);

      if(descriptor->fLink == 0) {
        descriptor->fLink = newNodesStart;
        ASSERT(writeBTNodeDescriptor(descriptor, mapNode, tree), "writeBTNodeDescriptor");
        
        newDescriptor.fLink = 0;
        newDescriptor.bLink = 0;
        newDescriptor.kind = kBTMapNode;
        newDescriptor.height = 0;
        newDescriptor.numRecords = 1;
        newDescriptor.reserved = 0;
        ASSERT(writeBTNodeDescriptor(&newDescriptor, descriptor->fLink, tree), "writeBTNodeDescriptor");
        
        newNodeOffset = descriptor->fLink * tree->headerRec->nodeSize;
        
        ASSERT(WRITE(tree->io, newNodeOffset + 14, tree->headerRec->nodeSize - 20, buffer), "WRITE");
        offset = 14;
        FLIPENDIAN(offset);
        ASSERT(WRITE(tree->io, newNodeOffset + tree->headerRec->nodeSize - 2, sizeof(offset), &offset), "WRITE");
        offset = 14 + tree->headerRec->nodeSize - 20;
        FLIPENDIAN(offset);
        ASSERT(WRITE(tree->io, newNodeOffset + tree->headerRec->nodeSize - 4, sizeof(offset), &offset), "WRITE");
        
        // mark the map node as being used
        ASSERT(markUsed(newNodesStart, tree), "markUsed");
        tree->headerRec->freeNodes--;
        newNodesStart++;
      }
      mapNode = descriptor->fLink;
      
      if(byteNumber > (tree->headerRec->nodeSize - 20)) {
        byteNumber -= tree->headerRec->nodeSize - 20;
      } else {
        free(buffer);
        
        ASSERT(writeBTHeaderRec(tree), "writeBTHeaderRec");
        return TRUE;
      }
    }
  }
  
  return FALSE;
}