STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
      const UInt64 ** /* inSizes */,
      UInt32 numInStreams,
      ISequentialOutStream **outStreams,
      const UInt64 ** /* outSizes */,
      UInt32 numOutStreams,
      ICompressProgressInfo *progress)
{
  if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
      numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
    return E_INVALIDARG;

  Init(inStreams, outStreams);

  int i;
  for (i = 0; i < _coders.Size(); i++)
    if (i != _progressCoderIndex)
    {
      RINOK(_coders[i].Create());
    }

  for (i = 0; i < _coders.Size(); i++)
    if (i != _progressCoderIndex)
      _coders[i].Start();

  _coders[_progressCoderIndex].Code(progress);

  for (i = 0; i < _coders.Size(); i++)
    if (i != _progressCoderIndex)
      _coders[i].WaitFinish();

  RINOK(ReturnIfError(E_ABORT));
  RINOK(ReturnIfError(E_OUTOFMEMORY));

  for (i = 0; i < _coders.Size(); i++)
  {
    HRESULT result = _coders[i].Result;
    if (result != S_OK && result != E_FAIL && result != S_FALSE)
      return result;
  }

  RINOK(ReturnIfError(S_FALSE));

  for (i = 0; i < _coders.Size(); i++)
  {
    HRESULT result = _coders[i].Result;
    if (result != S_OK)
      return result;
  }
  return S_OK;
}
Beispiel #2
0
/* 
 * This function moves the overflow extents associated with srcID into the file associated with dstID.
 * We should have already verified that 'srcID' has overflow extents. So now we move all of the overflow
 * extent records.
 */
OSErr MoveData( ExtendedVCB *vcb, HFSCatalogNodeID srcID, HFSCatalogNodeID destID, int rsrc) { 
	
	OSErr		err;
	
	/* 
	 * Only the source file should have extents, so we just track those.
	 * We operate on the fork represented by the open FD that was used to call into this
	 * function
	 */
	if (rsrc) {		
		/* Copy the extent overflow blocks. */
		err = MoveExtents( vcb, srcID, destID, 1, (u_int8_t)0xff, 1);
		if ( err != noErr ) {
			if ( err != dskFulErr ) {
				return( err );
			}
			/* 
			 * In case of error, we would have probably run into problems
			 * growing the extents b-tree.  Since the move is actually a copy + delete
			 * just delete the new entries. Same for below.
			 */
			err = DeleteExtents( vcb, destID, 1, (u_int8_t)0xff, 1); 
			ReturnIfError( err ); //	we are doomed. Just QUIT!
			goto FlushAndReturn;
		}
	}
	else {		
		/* Copy the extent overflow blocks. */
		err = MoveExtents( vcb, srcID, destID, 1, 0, 1);
		if ( err != noErr ) {
			if ( err != dskFulErr ) {
				return( err );
			}
			err = DeleteExtents( vcb, destID, 1, 0, 1); 
			ReturnIfError( err ); //	we are doomed. Just QUIT!
			goto FlushAndReturn;
		}
	}
	
FlushAndReturn:
	/* Write out the catalog and extent overflow B-Tree changes */
	err = FlushCatalog( vcb );
	err = FlushExtentFile( vcb );
	
	return( err );
}
OSErr
LocateCatalogNode(const ExtendedVCB *volume, HFSCatalogNodeID folderID, const CatalogName *name,
					u_int32_t hint, CatalogKey *keyPtr, CatalogRecord *dataPtr, u_int32_t *newHint)
{
	OSErr				result;
	CatalogName 		*nodeName = NULL;	/* To ward off uninitialized use warnings from compiler */
	HFSCatalogNodeID	threadParentID;


	result = LocateCatalogRecord(volume, folderID, name, hint, keyPtr, dataPtr, newHint);
	ReturnIfError(result);
	
	// if we got a thread record, then go look up real record
	switch ( dataPtr->recordType )
	{
		case kHFSFileThreadRecord:
		case kHFSFolderThreadRecord:
			threadParentID = dataPtr->hfsThread.parentID;
			nodeName = (CatalogName *) &dataPtr->hfsThread.nodeName;
			break;

		case kHFSPlusFileThreadRecord:
		case kHFSPlusFolderThreadRecord:
			threadParentID = dataPtr->hfsPlusThread.parentID;
			nodeName = (CatalogName *) &dataPtr->hfsPlusThread.nodeName;	
			break;

		default:
			threadParentID = 0;
			break;
	}
	
	if ( threadParentID )		// found a thread
		result = LocateCatalogRecord(volume, threadParentID, nodeName, kNoHint, keyPtr, dataPtr, newHint);
	
	return result;
}
Beispiel #4
0
OSErr ExchangeFileIDs( ExtendedVCB *vcb, ConstUTF8Param srcName, ConstUTF8Param destName, HFSCatalogNodeID srcID, HFSCatalogNodeID destID, u_int32_t srcHint, u_int32_t destHint )
{
	CatalogKey	srcKey;		// 518 bytes
	CatalogKey	destKey;	// 518 bytes
	CatalogRecord	srcData;	// 520 bytes
	CatalogRecord	destData;	// 520 bytes
	CatalogRecord	swapData;	// 520 bytes
	int16_t		numSrcExtentBlocks;
	int16_t		numDestExtentBlocks;
	OSErr		err;
	Boolean		isHFSPlus = ( vcb->vcbSigWord == kHFSPlusSigWord );

	err = BuildCatalogKeyUTF8(vcb, srcID, srcName, kUndefinedStrLen, &srcKey, NULL);
	ReturnIfError(err);

	err = BuildCatalogKeyUTF8(vcb, destID, destName, kUndefinedStrLen, &destKey, NULL);
	ReturnIfError(err);

	if ( isHFSPlus )
	{
		//--	Step 1: Check the catalog nodes for extents
		
		//--	locate the source file, test for extents in extent file, and copy the cat record for later
		err = LocateCatalogNodeByKey( vcb, srcHint, &srcKey, &srcData, &srcHint );
		ReturnIfError( err );
	
		if ( srcData.recordType != kHFSPlusFileRecord )
			return( cmFThdDirErr );					//	Error "cmFThdDirErr = it is a directory"
			
		//--	Check if there are any extents in the source file
		//€€	I am only checling the extents in the low 32 bits, routine will fail if files extents after 2 gig are in overflow
		numSrcExtentBlocks = CheckExtents( srcData.hfsPlusFile.dataFork.extents, srcData.hfsPlusFile.dataFork.totalBlocks, isHFSPlus );
		if ( numSrcExtentBlocks == 0 )					//	then check the resource fork extents
			numSrcExtentBlocks = CheckExtents( srcData.hfsPlusFile.resourceFork.extents, srcData.hfsPlusFile.resourceFork.totalBlocks, isHFSPlus );

		//--	Check if there are any extents in the destination file
		err = LocateCatalogNodeByKey( vcb, destHint, &destKey, &destData, &destHint );
		ReturnIfError( err );
	
		if ( destData.recordType != kHFSPlusFileRecord )
			return( cmFThdDirErr );					//	Error "cmFThdDirErr = it is a directory"

		numDestExtentBlocks = CheckExtents( destData.hfsPlusFile.dataFork.extents, destData.hfsPlusFile.dataFork.totalBlocks, isHFSPlus );
		if ( numDestExtentBlocks == 0 )					//	then check the resource fork extents
			numDestExtentBlocks = CheckExtents( destData.hfsPlusFile.resourceFork.extents, destData.hfsPlusFile.resourceFork.totalBlocks, isHFSPlus );

		//--	Step 2: Exchange the Extent key in the extent file
		
		//--	Exchange the extents key in the extent file
		err = DeleteExtents( vcb, kHFSBogusExtentFileID, isHFSPlus );
		ReturnIfError( err );
		
		if ( numSrcExtentBlocks && numDestExtentBlocks )	//	if both files have extents
		{
			//--	Change the source extents file ids to our known bogus value
			err = MoveExtents( vcb, srcData.hfsPlusFile.fileID, kHFSBogusExtentFileID, isHFSPlus );
			if ( err != noErr )
			{
				if ( err != dskFulErr )
					return( err );
				else
					goto ExUndo1a;
			}
			
			//--	Change the destination extents file id's to the source id's
			err = MoveExtents( vcb, destData.hfsPlusFile.fileID, srcData.hfsPlusFile.fileID, isHFSPlus );
			if ( err != noErr )
			{
				if ( err != dskFulErr )
					return( err );

ExUndo2aPlus:	err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, isHFSPlus );
				ReturnIfError( err );					//	we are doomed. Just QUIT!

                err = MoveExtents( vcb, kHFSBogusExtentFileID, srcData.hfsPlusFile.fileID, isHFSPlus );	//	Move the extents back
				ReturnIfError( err );					//	we are doomed. Just QUIT!
					
				goto ExUndo1a;
			}
			
			//--	Change the bogus extents file id's to the dest id's
            err = MoveExtents( vcb, kHFSBogusExtentFileID, destData.hfsPlusFile.fileID, isHFSPlus );
			if ( err != noErr )
			{
				if ( err != dskFulErr )
					return( err );

				err = DeleteExtents( vcb, destData.hfsPlusFile.fileID, isHFSPlus );
				ReturnIfError( err );					//	we are doomed. Just QUIT!

				err = MoveExtents( vcb, srcData.hfsPlusFile.fileID, destData.hfsPlusFile.fileID, isHFSPlus );	//	Move the extents back
				ReturnIfError( err );					//	we are doomed. Just QUIT!
					
				goto ExUndo2aPlus;
			}
			
		}
		else if ( numSrcExtentBlocks )	//	just the source file has extents
		{
			err = MoveExtents( vcb, srcData.hfsPlusFile.fileID, destData.hfsPlusFile.fileID, isHFSPlus );
			if ( err != noErr )
			{
				if ( err != dskFulErr )
					return( err );

				err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, isHFSPlus );
				ReturnIfError( err );					//	we are doomed. Just QUIT!

				goto FlushAndReturn;
			}
		}
		else if ( numDestExtentBlocks )	//	just the destination file has extents
		{
			err = MoveExtents( vcb, destData.hfsPlusFile.fileID, srcData.hfsPlusFile.fileID, isHFSPlus );
			if ( err != noErr )
			{
				if ( err != dskFulErr )
					return( err );

				err = DeleteExtents( vcb, destData.hfsPlusFile.fileID, isHFSPlus );
				ReturnIfError( err );					//	we are doomed. Just QUIT!

				goto FlushAndReturn;
			}
		}

		//--	Step 3: Change the data in the catalog nodes
		
		//--	find the source cnode and put dest info in it
		err = LocateCatalogNodeByKey( vcb, srcHint, &srcKey, &srcData, &srcHint );
		if ( err != noErr )
			return( cmBadNews );
		
		BlockMoveData( &srcData, &swapData, sizeof(CatalogRecord) );
		CopyBigCatalogNodeInfo( &destData, &srcData );
		
		err = ReplaceBTreeRecord( vcb->catalogRefNum, &srcKey, srcHint, &srcData, sizeof(HFSPlusCatalogFile), &srcHint );
		ReturnIfError( err );

		//	find the destination cnode and put source info in it		
		err = LocateCatalogNodeByKey( vcb, destHint, &destKey, &destData, &destHint );
		if ( err != noErr )
			return( cmBadNews );
			
		CopyBigCatalogNodeInfo( &swapData, &destData );
		err = ReplaceBTreeRecord( vcb->catalogRefNum, &destKey, destHint, &destData, sizeof(HFSPlusCatalogFile), &destHint );
		ReturnIfError( err );
	}
	else		//	HFS	//
	{
		//--	Step 1: Check the catalog nodes for extents
		
		//--	locate the source file, test for extents in extent file, and copy the cat record for later
		err = LocateCatalogNodeByKey( vcb, srcHint, &srcKey, &srcData, &srcHint );
		ReturnIfError( err );
	
		if ( srcData.recordType != kHFSFileRecord )
			return( cmFThdDirErr );					//	Error "cmFThdDirErr = it is a directory"
			
		//--	Check if there are any extents in the source file
		numSrcExtentBlocks = CheckExtents( srcData.hfsFile.dataExtents, srcData.hfsFile.dataPhysicalSize / vcb->blockSize, isHFSPlus );
		if ( numSrcExtentBlocks == 0 )					//	then check the resource fork extents
			numSrcExtentBlocks = CheckExtents( srcData.hfsFile.rsrcExtents, srcData.hfsFile.rsrcPhysicalSize / vcb->blockSize, isHFSPlus );
		
		
		//€€	Do we save the found source node for later use?
		
				
		//--	Check if there are any extents in the destination file
		err = LocateCatalogNodeByKey( vcb, destHint, &destKey, &destData, &destHint );
		ReturnIfError( err );
	
		if ( destData.recordType != kHFSFileRecord )
			return( cmFThdDirErr );					//	Error "cmFThdDirErr = it is a directory"

		numDestExtentBlocks = CheckExtents( destData.hfsFile.dataExtents, destData.hfsFile.dataPhysicalSize / vcb->blockSize, isHFSPlus );
		if ( numDestExtentBlocks == 0 )					//	then check the resource fork extents
			numDestExtentBlocks = CheckExtents( destData.hfsFile.rsrcExtents, destData.hfsFile.rsrcPhysicalSize / vcb->blockSize, isHFSPlus );
			
		//€€	Do we save the found destination node for later use?


		//--	Step 2: Exchange the Extent key in the extent file
		
		//--	Exchange the extents key in the extent file
        err = DeleteExtents( vcb, kHFSBogusExtentFileID, isHFSPlus );
		ReturnIfError( err );
		
		if ( numSrcExtentBlocks && numDestExtentBlocks )	//	if both files have extents
		{
			//--	Change the source extents file ids to our known bogus value
        err = MoveExtents( vcb, srcData.hfsFile.fileID, kHFSBogusExtentFileID, isHFSPlus );
			if ( err != noErr )
			{
				if ( err != dskFulErr )
					return( err );

ExUndo1a:		err = DeleteExtents( vcb, kHFSBogusExtentFileID, isHFSPlus );
				ReturnIfError( err );					//	we are doomed. Just QUIT!

				err = FlushCatalog( vcb );   			//	flush the catalog
				err = FlushExtentFile( vcb );			//	flush the extent file (unneeded for common case, but it's cheap)			
				return( dskFulErr );
			}
			
			//--	Change the destination extents file id's to the source id's
			err = MoveExtents( vcb, destData.hfsFile.fileID, srcData.hfsFile.fileID, isHFSPlus );
			if ( err != noErr )
			{
				if ( err != dskFulErr )
					return( err );

ExUndo2a:		err = DeleteExtents( vcb, srcData.hfsFile.fileID, isHFSPlus );
				ReturnIfError( err );					//	we are doomed. Just QUIT!

                err = MoveExtents( vcb, kHFSBogusExtentFileID, srcData.hfsFile.fileID, isHFSPlus );	//	Move the extents back
				ReturnIfError( err );					//	we are doomed. Just QUIT!
					
				goto ExUndo1a;
			}
			
			//--	Change the bogus extents file id's to the dest id's
            err = MoveExtents( vcb, kHFSBogusExtentFileID, destData.hfsFile.fileID, isHFSPlus );
			if ( err != noErr )
			{
				if ( err != dskFulErr )
					return( err );

				err = DeleteExtents( vcb, destData.hfsFile.fileID, isHFSPlus );
				ReturnIfError( err );					//	we are doomed. Just QUIT!

				err = MoveExtents( vcb, srcData.hfsFile.fileID, destData.hfsFile.fileID, isHFSPlus );	//	Move the extents back
				ReturnIfError( err );					//	we are doomed. Just QUIT!
					
				goto ExUndo2a;
			}
			
		}
		else if ( numSrcExtentBlocks )	//	just the source file has extents
		{
			err = MoveExtents( vcb, srcData.hfsFile.fileID, destData.hfsFile.fileID, isHFSPlus );
			if ( err != noErr )
			{
				if ( err != dskFulErr )
					return( err );

				err = DeleteExtents( vcb, srcData.hfsFile.fileID, isHFSPlus );
				ReturnIfError( err );					//	we are doomed. Just QUIT!

				goto FlushAndReturn;
			}
		}
		else if ( numDestExtentBlocks )	//	just the destination file has extents
		{
			err = MoveExtents( vcb, destData.hfsFile.fileID, srcData.hfsFile.fileID, isHFSPlus );
			if ( err != noErr )
			{
				if ( err != dskFulErr )
					return( err );

				err = DeleteExtents( vcb, destData.hfsFile.fileID, isHFSPlus );
				ReturnIfError( err );					//	we are doomed. Just QUIT!

				goto FlushAndReturn;
			}
		}

		//--	Step 3: Change the data in the catalog nodes
		
		//--	find the source cnode and put dest info in it
		err = LocateCatalogNodeByKey( vcb, srcHint, &srcKey, &srcData, &srcHint );
		if ( err != noErr )
			return( cmBadNews );
		
		BlockMoveData( &srcData, &swapData, sizeof(CatalogRecord) );
		//€€	Asm source copies from the saved dest catalog node
		CopyCatalogNodeInfo( &destData, &srcData );
		
		err = ReplaceBTreeRecord( vcb->catalogRefNum, &srcKey, srcHint, &srcData, sizeof(HFSCatalogFile), &srcHint );
		ReturnIfError( err );

		
		//	find the destination cnode and put source info in it		
		err = LocateCatalogNodeByKey( vcb, destHint, &destKey, &destData, &destHint );
		if ( err != noErr )
			return( cmBadNews );
			
		CopyCatalogNodeInfo( &swapData, &destData );
		err = ReplaceBTreeRecord( vcb->catalogRefNum, &destKey, destHint, &destData, sizeof(HFSCatalogFile), &destHint );
		ReturnIfError( err );
	}
	
	err = noErr;

	//--	Step 4: Error Handling section


FlushAndReturn:
	err = FlushCatalog( vcb );   			//	flush the catalog
	err = FlushExtentFile( vcb );			//	flush the extent file (unneeded for common case, but it's cheap)			
	return( err );
}
OSErr
LocateCatalogNodeByKey(const ExtendedVCB *volume, u_int32_t hint, CatalogKey *keyPtr,
						CatalogRecord *dataPtr, u_int32_t *newHint)
{
	OSErr				result;
	CatalogName 		*nodeName = NULL;
	HFSCatalogNodeID	threadParentID;
	u_int16_t tempSize;
	FSBufferDescriptor	 btRecord;
	BTreeIterator		 searchIterator; 
	FCB			*fcb;

	bzero(&searchIterator, sizeof(searchIterator));

	fcb = GetFileControlBlock(volume->catalogRefNum);

	btRecord.bufferAddress = dataPtr;
	btRecord.itemCount = 1;
	btRecord.itemSize = sizeof(CatalogRecord);

	searchIterator.hint.nodeNum = hint;

	bcopy(keyPtr, &searchIterator.key, sizeof(CatalogKey));
	
	result = BTSearchRecord( fcb, &searchIterator, &btRecord, &tempSize, &searchIterator );

	if (result == noErr)
	{
		*newHint = searchIterator.hint.nodeNum;

		BlockMoveData(&searchIterator.key, keyPtr, sizeof(CatalogKey));
	}

	if (result == btNotFound)
		result = cmNotFound;	
	ReturnIfError(result);
	
	// if we got a thread record, then go look up real record
	switch ( dataPtr->recordType )
	{
		case kHFSFileThreadRecord:
		case kHFSFolderThreadRecord:
			threadParentID = dataPtr->hfsThread.parentID;
			nodeName = (CatalogName *) &dataPtr->hfsThread.nodeName;
			break;

		case kHFSPlusFileThreadRecord:
		case kHFSPlusFolderThreadRecord:
			threadParentID = dataPtr->hfsPlusThread.parentID;
			nodeName = (CatalogName *) &dataPtr->hfsPlusThread.nodeName;	
			break;

		default:
			threadParentID = 0;
			break;
	}
	
	if ( threadParentID )		// found a thread
		result = LocateCatalogRecord(volume, threadParentID, nodeName, kNoHint, keyPtr, dataPtr, newHint);
	
	return result;
}