void grow_hfs(Volume* volume, uint64_t newSize) { uint32_t newBlocks; uint32_t blocksToGrow; uint64_t newMapSize; uint64_t i; unsigned char zero; zero = 0; newBlocks = newSize / volume->volumeHeader->blockSize; if(newBlocks <= volume->volumeHeader->totalBlocks) { printf("Cannot shrink volume\n"); return; } blocksToGrow = newBlocks - volume->volumeHeader->totalBlocks; newMapSize = newBlocks / 8; if(volume->volumeHeader->allocationFile.logicalSize < newMapSize) { if(volume->volumeHeader->freeBlocks < ((newMapSize - volume->volumeHeader->allocationFile.logicalSize) / volume->volumeHeader->blockSize)) { printf("Not enough room to allocate new allocation map blocks\n"); exit(0); } allocate((RawFile*) (volume->allocationFile->data), newMapSize); } /* unreserve last block */ setBlockUsed(volume, volume->volumeHeader->totalBlocks - 1, 0); /* don't need to increment freeBlocks because we will allocate another alternate volume header later on */ /* "unallocate" the new blocks */ for(i = ((volume->volumeHeader->totalBlocks / 8) + 1); i < newMapSize; i++) { ASSERT(WRITE(volume->allocationFile, i, 1, &zero), "WRITE"); } /* grow backing store size */ ASSERT(WRITE(volume->image, newSize - 1, 1, &zero), "WRITE"); /* write new volume information */ volume->volumeHeader->totalBlocks = newBlocks; volume->volumeHeader->freeBlocks += blocksToGrow; /* reserve last block */ setBlockUsed(volume, volume->volumeHeader->totalBlocks - 1, 1); updateVolume(volume); }
int insertKey(char *key,int key_len,char *val,int val_len,int ttl) { long len_t=val_len; int count=(val_len/BLOCK_SIZE)+1; if(global_head->freeBlockNum<count||global_head->freeNodeNum==0) return -1; int already=findKey(key,key_len); if(already!=-1) removeKey(already); int index=findFreeNode(); if(index==-1) return -1; int i; int sum=0; for (i = 0; i < count; ++i) { int t=findFreeBlock(); long ttt=len_t; if(t==-1) return -1; (global_head->p[index])->block[i]=t; if(ttt>BLOCK_SIZE) ttt=BLOCK_SIZE; memcpy(AT(t),val+sum,ttt); //long tt=snprintf(AT(t),ttt+1,"%s",val+sum); sum+=ttt; len_t-=ttt; setBlockUsed(t); } (global_head->p[index])->block[i]=-1; global_head->freeBlockNum-=count; global_head->usedBlockNum+=count; global_head->freeNodeNum--; global_head->usedNodeNum++; global_head->p[index]->size=val_len; global_head->p[index]->is_free=0; global_head->p[index]->ttl=time(0)+ttl; snprintf(global_head->p[index]->key,key_len+1,"%s",key); global_head->p[index]->key_len=key_len; for (i = 0; i < count; ++i) { setBlockUsed((global_head->p[index])->block[i]); } return 1; }
int allocate(RawFile* rawFile, off_t size) { unsigned char* zeros; Volume* volume; HFSPlusForkData* forkData; uint32_t blocksNeeded; uint32_t blocksToAllocate; Extent* extent; Extent* lastExtent; uint32_t curBlock; volume = rawFile->volume; forkData = rawFile->forkData; extent = rawFile->extents; blocksNeeded = ((uint64_t)size / (uint64_t)volume->volumeHeader->blockSize) + (((size % volume->volumeHeader->blockSize) == 0) ? 0 : 1); if(blocksNeeded > forkData->totalBlocks) { zeros = (unsigned char*) malloc(volume->volumeHeader->blockSize); memset(zeros, 0, volume->volumeHeader->blockSize); blocksToAllocate = blocksNeeded - forkData->totalBlocks; if(blocksToAllocate > volume->volumeHeader->freeBlocks) { return FALSE; } lastExtent = NULL; while(extent != NULL) { lastExtent = extent; extent = extent->next; } if(lastExtent == NULL) { rawFile->extents = (Extent*) malloc(sizeof(Extent)); lastExtent = rawFile->extents; lastExtent->blockCount = 0; lastExtent->next = NULL; curBlock = volume->volumeHeader->nextAllocation; } else { curBlock = lastExtent->startBlock + lastExtent->blockCount; } while(blocksToAllocate > 0) { if(isBlockUsed(volume, curBlock)) { if(lastExtent->blockCount > 0) { lastExtent->next = (Extent*) malloc(sizeof(Extent)); lastExtent = lastExtent->next; lastExtent->blockCount = 0; lastExtent->next = NULL; } curBlock = volume->volumeHeader->nextAllocation; volume->volumeHeader->nextAllocation++; if(volume->volumeHeader->nextAllocation >= volume->volumeHeader->totalBlocks) { volume->volumeHeader->nextAllocation = 0; } } else { if(lastExtent->blockCount == 0) { lastExtent->startBlock = curBlock; } /* zero out allocated block */ ASSERT(WRITE(volume->image, curBlock * volume->volumeHeader->blockSize, volume->volumeHeader->blockSize, zeros), "WRITE"); setBlockUsed(volume, curBlock, TRUE); volume->volumeHeader->freeBlocks--; blocksToAllocate--; curBlock++; lastExtent->blockCount++; if(curBlock >= volume->volumeHeader->totalBlocks) { curBlock = volume->volumeHeader->nextAllocation; } } } free(zeros); } else if(blocksNeeded < forkData->totalBlocks) { blocksToAllocate = blocksNeeded; lastExtent = NULL; while(blocksToAllocate > 0) { if(blocksToAllocate > extent->blockCount) { blocksToAllocate -= extent->blockCount; lastExtent = extent; extent = extent->next; } else { break; } } if(blocksToAllocate == 0 && lastExtent != NULL) { // snip the extent list here, since we don't need the rest lastExtent->next = NULL; } else if(blocksNeeded == 0) { rawFile->extents = NULL; } do { for(curBlock = (extent->startBlock + blocksToAllocate); curBlock < (extent->startBlock + extent->blockCount); curBlock++) { setBlockUsed(volume, curBlock, FALSE); volume->volumeHeader->freeBlocks++; } lastExtent = extent; extent = extent->next; if(blocksToAllocate == 0) { free(lastExtent); } else { lastExtent->next = NULL; lastExtent->blockCount = blocksToAllocate; } blocksToAllocate = 0; } while(extent != NULL); } writeExtents(rawFile); forkData->logicalSize = size; forkData->totalBlocks = blocksNeeded; updateVolume(rawFile->volume); if(rawFile->catalogRecord != NULL) { updateCatalog(rawFile->volume, rawFile->catalogRecord); } return TRUE; }