Esempio n. 1
0
static OSErr  MoveExtents( ExtendedVCB *vcb, u_int32_t srcFileID, u_int32_t destFileID, Boolean isHFSPlus )
{
	FCB *				fcb;
	ExtentsRecBuffer	extentsBuffer[kNumExtentsToCache];
	ExtentKey *			extentKeyPtr;
	ExtentRecord		extentData;
	BTreeIterator		btIterator;
	FSBufferDescriptor	btRecord;
	u_int16_t			btKeySize;
	u_int16_t			btRecordSize;
	int16_t				i, j;
	OSErr				err;
	

	fcb = GetFileControlBlock(vcb->extentsRefNum);
	
	(void) BTInvalidateHint(&btIterator);
	extentKeyPtr = (ExtentKey*) &btIterator.key;
	btRecord.bufferAddress = &extentData;
	btRecord.itemCount = 1;

	//--	Collect the extent records

	//
	//	A search on the following key will cause the BTree to be positioned immediately
	//	before the first extent record for file #srcFileID, but not actually positioned
	//	on any record.  This is because there cannot be an extent record with FABN = 0
	//	(the first extent of the fork, which would be in the catalog entry, not an extent
	//	record).
	//
	//	Using BTIterateRecord with kBTreeNextRecord will then get that first extent record.
	//
	if (isHFSPlus) {
		btRecord.itemSize = sizeof(HFSPlusExtentRecord);
		btKeySize = sizeof(HFSPlusExtentKey);

		extentKeyPtr->hfsPlus.keyLength	 = kHFSPlusExtentKeyMaximumLength;
		extentKeyPtr->hfsPlus.forkType	 = 0;
		extentKeyPtr->hfsPlus.pad		 = 0;
		extentKeyPtr->hfsPlus.fileID	 = srcFileID;
		extentKeyPtr->hfsPlus.startBlock = 0;
	}
	else {
		btRecord.itemSize = sizeof(HFSExtentRecord);
		btKeySize = sizeof(HFSExtentKey);

		extentKeyPtr->hfs.keyLength	 = kHFSExtentKeyMaximumLength;
		extentKeyPtr->hfs.forkType	 = 0;
		extentKeyPtr->hfs.fileID	 = srcFileID;
		extentKeyPtr->hfs.startBlock = 0;
	}
	
	//
	//	We do an initial BTSearchRecord to position the BTree's iterator just before any extent
	//	records for srcFileID.  We then do a few BTIterateRecord and BTInsertRecord of those found
	//	records, but with destFileID as the file number in the key.  Keep doing this sequence of
	//	BTIterateRecord and BTInsertRecord until we find an extent for another file, or there are
	//	no more extent records in the tree.
	//
	//	Basically, we're copying records kNumExtentsToCache at a time.  The copies have their file ID
	//	set to destFileID.
	//
	//	This depends on BTInsertRecord not effecting the iterator used by BTIterateRecord.  If it
	//	_did_ effect the iterator, then we would need to do a BTSearchRecord before each series
	//	of BTIterateRecord.  We'd need to set up the key for BTSearchRecord to find the last record
	//	we found, so that BTIterateRecord would get the next one (the first we haven't processed).
	//

	err = BTSearchRecord(fcb, &btIterator, &btRecord, &btRecordSize, &btIterator);
	
	//	We expect a btNotFound here, since there shouldn't be an extent record with FABN = 0.
	if (err != btNotFound)
	{
		if ( DEBUG_BUILD )
			DebugStr("Unexpected error from SearchBTreeRecord");
		
		if (err == noErr)			//	If we found such a bogus extent record, then the tree is really messed up
			err = cmBadNews;		//	so return an error that conveys the disk is hosed.
		
		return err;
	}

	do
	{
		btRecord.bufferAddress = &extentData;
		btRecord.itemCount = 1;

		for ( i=0 ; i<kNumExtentsToCache ; i++ )
		{
			HFSCatalogNodeID	foundFileID;

			err = BTIterateRecord(fcb, kBTreeNextRecord, &btIterator, &btRecord, &btRecordSize);
			if ( err == btNotFound )		//	Did we run out of extent records in the extents tree?
				break;						//	if xkrFNum(A0) is cleared on this error, then this test is bogus!
			else if ( err != noErr )
				return( err );				//	must be ioError
			
			foundFileID = isHFSPlus ? extentKeyPtr->hfsPlus.fileID : extentKeyPtr->hfs.fileID;
			if ( foundFileID == srcFileID )
			{
				CopyExtentInfo(extentKeyPtr, &extentData, extentsBuffer, i);
			}
			else
			{
				break;
			}
		}
		
		//--	edit each extent key, and reinsert each extent record in the extent file
		if (isHFSPlus)
			btRecordSize = sizeof(HFSPlusExtentRecord);
		else
			btRecordSize = sizeof(HFSExtentRecord);

		for ( j=0 ; j<i ; j++ )
		{
			BTreeIterator tmpIterator;

			if (isHFSPlus)
				extentsBuffer[j].extentKey.hfsPlus.fileID = destFileID;	//	change only the id in the key to dest ID
			else
				extentsBuffer[j].extentKey.hfs.fileID = destFileID;	//	change only the id in the key to dest ID

			// get iterator and buffer descriptor ready...
			(void) BTInvalidateHint(&tmpIterator);
			BlockMoveData(&(extentsBuffer[j].extentKey), &tmpIterator.key, btKeySize);
			btRecord.bufferAddress = &(extentsBuffer[j].extentData);

			err = BTInsertRecord(fcb, &tmpIterator, &btRecord, btRecordSize);
			if ( err != noErr )
			{									//	parse the error
				if ( err == btExists )
				{
					if ( DEBUG_BUILD )
						DebugStr("Can't insert record -- already exists");
					return( cmBadNews );
				}
				else
					return( err );
			}
		}
		
		//--	okay, done with this buffered batch, go get the next set of extent records
		//	If our buffer is not full, we must be done, or recieved an error
		
		if ( i != kNumExtentsToCache )			//	if the buffer is not full, we must be done
		{
			err = DeleteExtents( vcb, srcFileID, isHFSPlus );	//	Now delete all the extent entries with the sourceID
			if ( DEBUG_BUILD && err != noErr )
				DebugStr("Error from DeleteExtents");
			break;									//	we're done!
		}
	} while ( true );
	
	return( err );
}
Esempio n. 2
0
//--	Delete all extents in extent file that have the ID given.
static OSErr  DeleteExtents( ExtendedVCB *vcb, u_int32_t fileID, Boolean isHFSPlus )
{
	FCB *				fcb;
	ExtentKey *			extentKeyPtr;
	ExtentRecord		extentData;
	BTreeIterator		btIterator;
	FSBufferDescriptor	btRecord;
	u_int16_t			btRecordSize;
	OSErr				err;

	fcb = GetFileControlBlock(vcb->extentsRefNum);

	(void) BTInvalidateHint(&btIterator);
	extentKeyPtr = (ExtentKey*) &btIterator.key;
	btRecord.bufferAddress = &extentData;
	btRecord.itemCount = 1;

	//	The algorithm is to position the BTree just before any extent records for fileID.
	//	Then just keep getting successive records.  If the record is still for fileID,
	//	then delete it.
	
	if (isHFSPlus) {
		btRecord.itemSize = sizeof(HFSPlusExtentRecord);

		extentKeyPtr->hfsPlus.keyLength	 = kHFSPlusExtentKeyMaximumLength;
		extentKeyPtr->hfsPlus.forkType	 = 0;
		extentKeyPtr->hfsPlus.pad		 = 0;
		extentKeyPtr->hfsPlus.fileID	 = fileID;
		extentKeyPtr->hfsPlus.startBlock = 0;
	}
	else {
		btRecord.itemSize = sizeof(HFSExtentRecord);

		extentKeyPtr->hfs.keyLength	 = kHFSExtentKeyMaximumLength;
		extentKeyPtr->hfs.forkType	 = 0;
		extentKeyPtr->hfs.fileID	 = fileID;
		extentKeyPtr->hfs.startBlock = 0;
	}

	err = BTSearchRecord(fcb, &btIterator, &btRecord, &btRecordSize, &btIterator);
	if ( err != btNotFound )
	{
		if (err == noErr) {		//	Did we find a bogus extent record?
			err = cmBadNews;	//	Yes, so indicate things are messed up.
		}
		
		return err;				//	Got some unexpected error, so return it
	}

	do
	{
		BTreeIterator 		tmpIterator;
		HFSCatalogNodeID	foundFileID;

		err = BTIterateRecord(fcb, kBTreeNextRecord, &btIterator, &btRecord, &btRecordSize);
		if ( err != noErr )
		{
			if (err == btNotFound)	//	If we hit the end of the BTree
				err = noErr;		//		then it's OK
				
			break;					//	We're done now.
		}
		
		foundFileID = isHFSPlus ? extentKeyPtr->hfsPlus.fileID : extentKeyPtr->hfs.fileID;
		if ( foundFileID != fileID )
			break;					//	numbers don't match, we must be done

		tmpIterator = btIterator;
		err = BTDeleteRecord( fcb, &tmpIterator );
		if (err != noErr)
			break;
	}	while ( true );
	
	return( err );
}
Esempio n. 3
0
static OSErr  MoveExtents( ExtendedVCB *vcb, u_int32_t srcFileID, u_int32_t destFileID, int quitEarly, u_int8_t forkType, Boolean isHFSPlus )
{
	FCB *				fcb;
	ExtentsRecBuffer	extentsBuffer[kNumExtentsToCache];
	ExtentKey *			extentKeyPtr;
	ExtentRecord		extentData;
	struct BTreeIterator *btIterator = NULL;
	struct BTreeIterator *tmpIterator = NULL;
	FSBufferDescriptor	btRecord;
	u_int16_t			btKeySize;
	u_int16_t			btRecordSize;
	int16_t				i, j;
	OSErr				err;
	
	MALLOC (btIterator, struct BTreeIterator*, sizeof(struct BTreeIterator), M_TEMP, M_WAITOK);
	if (btIterator == NULL) {
		return memFullErr;  // translates to ENOMEM
	}


	MALLOC (tmpIterator, struct BTreeIterator*, sizeof(struct BTreeIterator), M_TEMP, M_WAITOK);
	if (tmpIterator == NULL) {	
		FREE (btIterator, M_TEMP);	
		return memFullErr;  // translates to ENOMEM
	}

	bzero(btIterator, sizeof(*btIterator));
	bzero (tmpIterator, sizeof(*tmpIterator));


	fcb = GetFileControlBlock(vcb->extentsRefNum);
	
	(void) BTInvalidateHint(btIterator);
	extentKeyPtr = (ExtentKey*) &btIterator->key;
	btRecord.bufferAddress = &extentData;
	btRecord.itemCount = 1;

	//--	Collect the extent records

	//
	//	A search on the following key will cause the BTree to be positioned immediately
	//	before the first extent record for file #srcFileID, but not actually positioned
	//	on any record.  This is because there cannot be an extent record with FABN = 0
	//	(the first extent of the fork, which would be in the catalog entry, not an extent
	//	record).
	//
	//	Using BTIterateRecord with kBTreeNextRecord will then get that first extent record.
	//
	if (isHFSPlus) {
		btRecord.itemSize = sizeof(HFSPlusExtentRecord);
		btKeySize = sizeof(HFSPlusExtentKey);

		extentKeyPtr->hfsPlus.keyLength	 = kHFSPlusExtentKeyMaximumLength;
		extentKeyPtr->hfsPlus.forkType	 = forkType;
		extentKeyPtr->hfsPlus.pad		 = 0;
		extentKeyPtr->hfsPlus.fileID	 = srcFileID;
		extentKeyPtr->hfsPlus.startBlock = 0;
	}
#if CONFIG_HFS_STD
	else {
		btRecord.itemSize = sizeof(HFSExtentRecord);
		btKeySize = sizeof(HFSExtentKey);

		extentKeyPtr->hfs.keyLength	 = kHFSExtentKeyMaximumLength;
		extentKeyPtr->hfs.forkType	 = 0;
		extentKeyPtr->hfs.fileID	 = srcFileID;
		extentKeyPtr->hfs.startBlock = 0;
	}
#else
    else {
        return cmBadNews;