Beispiel #1
0
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);
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}