X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/d7e50217d7adf6e52786a38bcaa4cd698cb9a79e..7e41aa883dd258f888d0470250eead40a53ef1f5:/bsd/hfs/hfscommon/Catalog/FileIDsServices.c

diff --git a/bsd/hfs/hfscommon/Catalog/FileIDsServices.c b/bsd/hfs/hfscommon/Catalog/FileIDsServices.c
index 2481b7463..fa7e210d0 100644
--- a/bsd/hfs/hfscommon/Catalog/FileIDsServices.c
+++ b/bsd/hfs/hfscommon/Catalog/FileIDsServices.c
@@ -1,16 +1,19 @@
 /*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
  * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
@@ -20,7 +23,7 @@
  * Please see the License for the specific language governing rights and
  * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 
 #include "../../hfs_macos_defs.h"
@@ -29,6 +32,9 @@
 #include	"../headers/FileMgrInternal.h"
 #include	"../headers/HFSUnicodeWrappers.h"
 #include	"../headers/CatalogPrivate.h"
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <libkern/libkern.h>
 
 
 struct ExtentsRecBuffer {
@@ -38,39 +44,88 @@ struct ExtentsRecBuffer {
 typedef struct ExtentsRecBuffer ExtentsRecBuffer;
 
 
-UInt32	CheckExtents( void *extents, UInt32 blocks, Boolean isHFSPlus );
-OSErr	DeleteExtents( ExtendedVCB *vcb, UInt32 fileNumber, Boolean isHFSPlus );
-OSErr	MoveExtents( ExtendedVCB *vcb, UInt32 srcFileID, UInt32 destFileID, Boolean isHFSPlus );
-void	CopyCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest );
-void	CopyBigCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest );
-void	CopyExtentInfo( ExtentKey *key, ExtentRecord *data, ExtentsRecBuffer *buffer, UInt16 bufferCount );
+static u_int32_t CheckExtents( void *extents, u_int32_t blocks, Boolean isHFSPlus );
+static OSErr  DeleteExtents( ExtendedVCB *vcb, u_int32_t fileNumber, int quitEarly, u_int8_t forkType, Boolean isHFSPlus );
+static OSErr  MoveExtents( ExtendedVCB *vcb, u_int32_t srcFileID, u_int32_t destFileID, int quitEarly, u_int8_t forkType, Boolean isHFSPlus );
 
+#if CONFIG_HFS_STD
+static void  CopyCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest );
+#endif
 
+static void  CopyBigCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest );
+static void  CopyExtentInfo( ExtentKey *key, ExtentRecord *data, ExtentsRecBuffer *buffer, u_int16_t bufferCount );
 
-OSErr ExchangeFileIDs( ExtendedVCB *vcb, ConstUTF8Param srcName, ConstUTF8Param destName, HFSCatalogNodeID srcID, HFSCatalogNodeID destID, UInt32 srcHint, UInt32 destHint )
+/* 
+ * 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 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
-	SInt16		numSrcExtentBlocks;
-	SInt16		numDestExtentBlocks;
+	int16_t		numSrcExtentBlocks;
+	int16_t		numDestExtentBlocks;
 	OSErr		err;
 	Boolean		isHFSPlus = ( vcb->vcbSigWord == kHFSPlusSigWord );
 
-	TrashCatalogIterator(vcb, srcID);	//	invalidate any iterators for this parentID
-	TrashCatalogIterator(vcb, destID);	//	invalidate any iterators for this parentID
-
 	err = BuildCatalogKeyUTF8(vcb, srcID, srcName, kUndefinedStrLen, &srcKey, NULL);
 	ReturnIfError(err);
 
 	err = BuildCatalogKeyUTF8(vcb, destID, destName, kUndefinedStrLen, &destKey, NULL);
 	ReturnIfError(err);
 
-	err = BTCheckFreeSpace(GetFileControlBlock(vcb->extentsRefNum));
-	ReturnIfError(err);
-	
 	if ( isHFSPlus )
 	{
 		//--	Step 1: Check the catalog nodes for extents
@@ -102,48 +157,61 @@ OSErr ExchangeFileIDs( ExtendedVCB *vcb, ConstUTF8Param srcName, ConstUTF8Param
 		//--	Step 2: Exchange the Extent key in the extent file
 		
 		//--	Exchange the extents key in the extent file
-		err = DeleteExtents( vcb, kHFSBogusExtentFileID, isHFSPlus );
+		err = DeleteExtents( vcb, kHFSBogusExtentFileID, 0, 0, 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 );
+			err = MoveExtents( vcb, srcData.hfsPlusFile.fileID, kHFSBogusExtentFileID, 0,0, isHFSPlus );
 			if ( err != noErr )
 			{
-				if ( err != dskFulErr )
+				if ( err != dskFulErr ) {
 					return( err );
-				else
-					goto ExUndo1a;
+                }
+				else {
+                    err = DeleteExtents( vcb, kHFSBogusExtentFileID, 0, 0, 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.hfsPlusFile.fileID, srcData.hfsPlusFile.fileID, isHFSPlus );
+			err = MoveExtents( vcb, destData.hfsPlusFile.fileID, srcData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
 			if ( err != noErr )
 			{
 				if ( err != dskFulErr )
 					return( err );
 
-ExUndo2aPlus:	err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, isHFSPlus );
+ExUndo2aPlus:	err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
 				ReturnIfError( err );					//	we are doomed. Just QUIT!
 
-                err = MoveExtents( vcb, kHFSBogusExtentFileID, srcData.hfsPlusFile.fileID, isHFSPlus );	//	Move the extents back
+                err = MoveExtents( vcb, kHFSBogusExtentFileID, srcData.hfsPlusFile.fileID, 0, 0, isHFSPlus );	//	Move the extents back
 				ReturnIfError( err );					//	we are doomed. Just QUIT!
 					
-				goto ExUndo1a;
+                err = DeleteExtents( vcb, kHFSBogusExtentFileID, 0, 0, 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 bogus extents file id's to the dest id's
-            err = MoveExtents( vcb, kHFSBogusExtentFileID, destData.hfsPlusFile.fileID, isHFSPlus );
+            err = MoveExtents( vcb, kHFSBogusExtentFileID, destData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
 			if ( err != noErr )
 			{
 				if ( err != dskFulErr )
 					return( err );
 
-				err = DeleteExtents( vcb, destData.hfsPlusFile.fileID, isHFSPlus );
+				err = DeleteExtents( vcb, destData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
 				ReturnIfError( err );					//	we are doomed. Just QUIT!
 
-				err = MoveExtents( vcb, srcData.hfsPlusFile.fileID, destData.hfsPlusFile.fileID, isHFSPlus );	//	Move the extents back
+				err = MoveExtents( vcb, srcData.hfsPlusFile.fileID, destData.hfsPlusFile.fileID, 0, 0, isHFSPlus );	//	Move the extents back
 				ReturnIfError( err );					//	we are doomed. Just QUIT!
 					
 				goto ExUndo2aPlus;
@@ -152,13 +220,13 @@ ExUndo2aPlus:	err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, isHFSPlus );
 		}
 		else if ( numSrcExtentBlocks )	//	just the source file has extents
 		{
-			err = MoveExtents( vcb, srcData.hfsPlusFile.fileID, destData.hfsPlusFile.fileID, isHFSPlus );
+			err = MoveExtents( vcb, srcData.hfsPlusFile.fileID, destData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
 			if ( err != noErr )
 			{
 				if ( err != dskFulErr )
 					return( err );
 
-				err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, isHFSPlus );
+				err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
 				ReturnIfError( err );					//	we are doomed. Just QUIT!
 
 				goto FlushAndReturn;
@@ -166,13 +234,13 @@ ExUndo2aPlus:	err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, isHFSPlus );
 		}
 		else if ( numDestExtentBlocks )	//	just the destination file has extents
 		{
-			err = MoveExtents( vcb, destData.hfsPlusFile.fileID, srcData.hfsPlusFile.fileID, isHFSPlus );
+			err = MoveExtents( vcb, destData.hfsPlusFile.fileID, srcData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
 			if ( err != noErr )
 			{
 				if ( err != dskFulErr )
 					return( err );
 
-				err = DeleteExtents( vcb, destData.hfsPlusFile.fileID, isHFSPlus );
+				err = DeleteExtents( vcb, destData.hfsPlusFile.fileID, 0, 0, isHFSPlus );
 				ReturnIfError( err );					//	we are doomed. Just QUIT!
 
 				goto FlushAndReturn;
@@ -201,6 +269,7 @@ ExUndo2aPlus:	err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, isHFSPlus );
 		err = ReplaceBTreeRecord( vcb->catalogRefNum, &destKey, destHint, &destData, sizeof(HFSPlusCatalogFile), &destHint );
 		ReturnIfError( err );
 	}
+#if CONFIG_HFS_STD
 	else		//	HFS	//
 	{
 		//--	Step 1: Check the catalog nodes for extents
@@ -238,19 +307,19 @@ ExUndo2aPlus:	err = DeleteExtents( vcb, srcData.hfsPlusFile.fileID, isHFSPlus );
 		//--	Step 2: Exchange the Extent key in the extent file
 		
 		//--	Exchange the extents key in the extent file
-        err = DeleteExtents( vcb, kHFSBogusExtentFileID, isHFSPlus );
+        err = DeleteExtents( vcb, kHFSBogusExtentFileID, 0, 0, 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 );
+        err = MoveExtents( vcb, srcData.hfsFile.fileID, kHFSBogusExtentFileID, 0, 0, isHFSPlus );
 			if ( err != noErr )
 			{
 				if ( err != dskFulErr )
 					return( err );
 
-ExUndo1a:		err = DeleteExtents( vcb, kHFSBogusExtentFileID, isHFSPlus );
+ExUndo1a:		err = DeleteExtents( vcb, kHFSBogusExtentFileID, 0, 0, isHFSPlus );
 				ReturnIfError( err );					//	we are doomed. Just QUIT!
 
 				err = FlushCatalog( vcb );   			//	flush the catalog
@@ -259,32 +328,32 @@ ExUndo1a:		err = DeleteExtents( vcb, kHFSBogusExtentFileID, isHFSPlus );
 			}
 			
 			//--	Change the destination extents file id's to the source id's
-			err = MoveExtents( vcb, destData.hfsFile.fileID, srcData.hfsFile.fileID, isHFSPlus );
+			err = MoveExtents( vcb, destData.hfsFile.fileID, srcData.hfsFile.fileID, 0, 0, isHFSPlus );
 			if ( err != noErr )
 			{
 				if ( err != dskFulErr )
 					return( err );
 
-ExUndo2a:		err = DeleteExtents( vcb, srcData.hfsFile.fileID, isHFSPlus );
+ExUndo2a:		err = DeleteExtents( vcb, srcData.hfsFile.fileID, 0, 0, isHFSPlus );
 				ReturnIfError( err );					//	we are doomed. Just QUIT!
 
-                err = MoveExtents( vcb, kHFSBogusExtentFileID, srcData.hfsFile.fileID, isHFSPlus );	//	Move the extents back
+                err = MoveExtents( vcb, kHFSBogusExtentFileID, srcData.hfsFile.fileID, 0, 0, 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 );
+            err = MoveExtents( vcb, kHFSBogusExtentFileID, destData.hfsFile.fileID, 0, 0, isHFSPlus );
 			if ( err != noErr )
 			{
 				if ( err != dskFulErr )
 					return( err );
 
-				err = DeleteExtents( vcb, destData.hfsFile.fileID, isHFSPlus );
+				err = DeleteExtents( vcb, destData.hfsFile.fileID, 0, 0, isHFSPlus );
 				ReturnIfError( err );					//	we are doomed. Just QUIT!
 
-				err = MoveExtents( vcb, srcData.hfsFile.fileID, destData.hfsFile.fileID, isHFSPlus );	//	Move the extents back
+				err = MoveExtents( vcb, srcData.hfsFile.fileID, destData.hfsFile.fileID, 0, 0, isHFSPlus );	//	Move the extents back
 				ReturnIfError( err );					//	we are doomed. Just QUIT!
 					
 				goto ExUndo2a;
@@ -293,13 +362,13 @@ ExUndo2a:		err = DeleteExtents( vcb, srcData.hfsFile.fileID, isHFSPlus );
 		}
 		else if ( numSrcExtentBlocks )	//	just the source file has extents
 		{
-			err = MoveExtents( vcb, srcData.hfsFile.fileID, destData.hfsFile.fileID, isHFSPlus );
+			err = MoveExtents( vcb, srcData.hfsFile.fileID, destData.hfsFile.fileID, 0, 0, isHFSPlus );
 			if ( err != noErr )
 			{
 				if ( err != dskFulErr )
 					return( err );
 
-				err = DeleteExtents( vcb, srcData.hfsFile.fileID, isHFSPlus );
+				err = DeleteExtents( vcb, srcData.hfsFile.fileID, 0, 0, isHFSPlus );
 				ReturnIfError( err );					//	we are doomed. Just QUIT!
 
 				goto FlushAndReturn;
@@ -307,13 +376,13 @@ ExUndo2a:		err = DeleteExtents( vcb, srcData.hfsFile.fileID, isHFSPlus );
 		}
 		else if ( numDestExtentBlocks )	//	just the destination file has extents
 		{
-			err = MoveExtents( vcb, destData.hfsFile.fileID, srcData.hfsFile.fileID, isHFSPlus );
+			err = MoveExtents( vcb, destData.hfsFile.fileID, srcData.hfsFile.fileID, 0, 0, isHFSPlus );
 			if ( err != noErr )
 			{
 				if ( err != dskFulErr )
 					return( err );
 
-				err = DeleteExtents( vcb, destData.hfsFile.fileID, isHFSPlus );
+				err = DeleteExtents( vcb, destData.hfsFile.fileID, 0, 0, isHFSPlus );
 				ReturnIfError( err );					//	we are doomed. Just QUIT!
 
 				goto FlushAndReturn;
@@ -344,7 +413,8 @@ ExUndo2a:		err = DeleteExtents( vcb, srcData.hfsFile.fileID, isHFSPlus );
 		err = ReplaceBTreeRecord( vcb->catalogRefNum, &destKey, destHint, &destData, sizeof(HFSCatalogFile), &destHint );
 		ReturnIfError( err );
 	}
-	
+#endif
+
 	err = noErr;
 
 	//--	Step 4: Error Handling section
@@ -357,7 +427,8 @@ FlushAndReturn:
 }
 
 
-void	CopyCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest )
+#if CONFIG_HFS_STD
+static void  CopyCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest )
 {
 	dest->hfsFile.dataLogicalSize	= src->hfsFile.dataLogicalSize;
 	dest->hfsFile.dataPhysicalSize = src->hfsFile.dataPhysicalSize;
@@ -367,8 +438,9 @@ void	CopyCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest )
 	BlockMoveData( src->hfsFile.dataExtents, dest->hfsFile.dataExtents, sizeof(HFSExtentRecord) );
 	BlockMoveData( src->hfsFile.rsrcExtents, dest->hfsFile.rsrcExtents, sizeof(HFSExtentRecord) );
 }
+#endif
 
-void	CopyBigCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest )
+static void  CopyBigCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest )
 {
 	BlockMoveData( &src->hfsPlusFile.dataFork, &dest->hfsPlusFile.dataFork, sizeof(HFSPlusForkData) );
 	BlockMoveData( &src->hfsPlusFile.resourceFork, &dest->hfsPlusFile.resourceFork, sizeof(HFSPlusForkData) );
@@ -376,24 +448,40 @@ void	CopyBigCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest )
 }
 
 
-OSErr	MoveExtents( ExtendedVCB *vcb, UInt32 srcFileID, UInt32 destFileID, Boolean isHFSPlus )
+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;
-	BTreeIterator		btIterator;
+	struct BTreeIterator *btIterator = NULL;
+	struct BTreeIterator *tmpIterator = NULL;
 	FSBufferDescriptor	btRecord;
-	UInt16				btKeySize;
-	UInt16				btRecordSize;
-	SInt16				i, j;
+	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;
+	(void) BTInvalidateHint(btIterator);
+	extentKeyPtr = (ExtentKey*) &btIterator->key;
 	btRecord.bufferAddress = &extentData;
 	btRecord.itemCount = 1;
 
@@ -413,11 +501,12 @@ OSErr	MoveExtents( ExtendedVCB *vcb, UInt32 srcFileID, UInt32 destFileID, Boolea
 		btKeySize = sizeof(HFSPlusExtentKey);
 
 		extentKeyPtr->hfsPlus.keyLength	 = kHFSPlusExtentKeyMaximumLength;
-		extentKeyPtr->hfsPlus.forkType	 = 0;
+		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);
@@ -427,6 +516,11 @@ OSErr	MoveExtents( ExtendedVCB *vcb, UInt32 srcFileID, UInt32 destFileID, Boolea
 		extentKeyPtr->hfs.fileID	 = srcFileID;
 		extentKeyPtr->hfs.startBlock = 0;
 	}
+#else
+    else {
+        return cmBadNews;
+    }
+#endif
 	
 	//
 	//	We do an initial BTSearchRecord to position the BTree's iterator just before any extent
@@ -444,17 +538,19 @@ OSErr	MoveExtents( ExtendedVCB *vcb, UInt32 srcFileID, UInt32 destFileID, Boolea
 	//	we found, so that BTIterateRecord would get the next one (the first we haven't processed).
 	//
 
-	err = BTSearchRecord(fcb, &btIterator, &btRecord, &btRecordSize, &btIterator);
+	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("\pUnexpected error from SearchBTreeRecord");
+			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.
 		
+		FREE (tmpIterator, M_TEMP);	
+		FREE (btIterator, M_TEMP);
 		return err;
 	}
 
@@ -465,76 +561,102 @@ OSErr	MoveExtents( ExtendedVCB *vcb, UInt32 srcFileID, UInt32 destFileID, Boolea
 
 		for ( i=0 ; i<kNumExtentsToCache ; i++ )
 		{
-			HFSCatalogNodeID	foundFileID;
-
-			err = BTIterateRecord(fcb, kBTreeNextRecord, &btIterator, &btRecord, &btRecordSize);
+			HFSCatalogNodeID	foundFileID = 0;
+			
+			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 )
+			else if ( err != noErr ) {
+				FREE (btIterator, M_TEMP);
+				FREE (tmpIterator, M_TEMP);
 				return( err );				//	must be ioError
-			
-			foundFileID = isHFSPlus ? extentKeyPtr->hfsPlus.fileID : extentKeyPtr->hfs.fileID;
-			if ( foundFileID == srcFileID )
-			{
+			}
+            if (isHFSPlus) {
+                foundFileID = extentKeyPtr->hfsPlus.fileID;
+            }
+#if CONFIG_HFS_STD
+            else {
+                foundFileID = extentKeyPtr->hfs.fileID;
+            }
+#endif
+			if ( foundFileID == srcFileID ) {
+				/* Check if we need to quit early. */
+				if (quitEarly && isHFSPlus) {
+					if (extentKeyPtr->hfsPlus.forkType != forkType) {
+						break;
+					}
+				}
 				CopyExtentInfo(extentKeyPtr, &extentData, extentsBuffer, i);
 			}
-			else
-			{
+			else{
+				/* The fileID's are of a different file.  We're done here. */
 				break;
 			}
 		}
 		
+		
+		
 		//--	edit each extent key, and reinsert each extent record in the extent file
 		if (isHFSPlus)
 			btRecordSize = sizeof(HFSPlusExtentRecord);
+#if CONFIG_HFS_STD
 		else
 			btRecordSize = sizeof(HFSExtentRecord);
-
+#endif
+        
 		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
+#if CONFIG_HFS_STD
 			else
 				extentsBuffer[j].extentKey.hfs.fileID = destFileID;	//	change only the id in the key to dest ID
-
+#endif
+            
 			// get iterator and buffer descriptor ready...
-			(void) BTInvalidateHint(&tmpIterator);
-			BlockMoveData(&(extentsBuffer[j].extentKey), &tmpIterator.key, btKeySize);
+			(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
+			err = BTInsertRecord(fcb, tmpIterator, &btRecord, btRecordSize);
+			if ( err != noErr ) {								
+				/* Parse the error and free iterators */
+				FREE (btIterator, M_TEMP);
+				FREE (tmpIterator, M_TEMP);
 				if ( err == btExists )
 				{
-					if ( DEBUG_BUILD )
-						DebugStr("\pCan't insert record -- already exists");
+					if ( DEBUG_BUILD ) {
+						DebugStr("Can't insert record -- already exists"); 
+					}
 					return( cmBadNews );
 				}
-				else
+				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
+			err = DeleteExtents( vcb, srcFileID, quitEarly, forkType, isHFSPlus );	//	Now delete all the extent entries with the sourceID
 			if ( DEBUG_BUILD && err != noErr )
-				DebugStr("\pError from DeleteExtents");
+				DebugStr("Error from DeleteExtents");
 			break;									//	we're done!
 		}
 	} while ( true );
 	
+	FREE (tmpIterator, M_TEMP);
+	FREE (btIterator, M_TEMP);
+
 	return( err );
 }
 
 
-void	CopyExtentInfo( ExtentKey *key, ExtentRecord *data, ExtentsRecBuffer *buffer, UInt16 bufferCount )
+static void  CopyExtentInfo( ExtentKey *key, ExtentRecord *data, ExtentsRecBuffer *buffer, u_int16_t bufferCount )
 {
 	BlockMoveData( key, &(buffer[bufferCount].extentKey), sizeof( ExtentKey ) );
 	BlockMoveData( data, &(buffer[bufferCount].extentData), sizeof( ExtentRecord ) );
@@ -542,20 +664,27 @@ void	CopyExtentInfo( ExtentKey *key, ExtentRecord *data, ExtentsRecBuffer *buffe
 
 
 //--	Delete all extents in extent file that have the ID given.
-OSErr	DeleteExtents( ExtendedVCB *vcb, UInt32 fileID, Boolean isHFSPlus )
+static OSErr  DeleteExtents( ExtendedVCB *vcb, u_int32_t fileID, int quitEarly,  u_int8_t forkType, Boolean isHFSPlus )
 {
 	FCB *				fcb;
 	ExtentKey *			extentKeyPtr;
 	ExtentRecord		extentData;
-	BTreeIterator		btIterator;
+	struct BTreeIterator *btIterator = NULL;
+	struct BTreeIterator *tmpIterator = NULL;
 	FSBufferDescriptor	btRecord;
-	UInt16				btRecordSize;
+	u_int16_t			btRecordSize;
 	OSErr				err;
 
+	MALLOC (btIterator, struct BTreeIterator*, sizeof(struct BTreeIterator),
+			M_TEMP, M_WAITOK | M_ZERO);
+
+	MALLOC (tmpIterator, struct BTreeIterator*, sizeof(struct BTreeIterator),
+			M_TEMP, M_WAITOK | M_ZERO);
+
 	fcb = GetFileControlBlock(vcb->extentsRefNum);
 
-	(void) BTInvalidateHint(&btIterator);
-	extentKeyPtr = (ExtentKey*) &btIterator.key;
+	(void) BTInvalidateHint(btIterator);
+	extentKeyPtr = (ExtentKey*) &btIterator->key;
 	btRecord.bufferAddress = &extentData;
 	btRecord.itemCount = 1;
 
@@ -567,36 +696,42 @@ OSErr	DeleteExtents( ExtendedVCB *vcb, UInt32 fileID, Boolean isHFSPlus )
 		btRecord.itemSize = sizeof(HFSPlusExtentRecord);
 
 		extentKeyPtr->hfsPlus.keyLength	 = kHFSPlusExtentKeyMaximumLength;
-		extentKeyPtr->hfsPlus.forkType	 = 0;
+		extentKeyPtr->hfsPlus.forkType	 = forkType;
 		extentKeyPtr->hfsPlus.pad		 = 0;
 		extentKeyPtr->hfsPlus.fileID	 = fileID;
 		extentKeyPtr->hfsPlus.startBlock = 0;
 	}
+#if CONFIG_HFS_STD
 	else {
 		btRecord.itemSize = sizeof(HFSExtentRecord);
 
 		extentKeyPtr->hfs.keyLength	 = kHFSExtentKeyMaximumLength;
-		extentKeyPtr->hfs.forkType	 = 0;
+		extentKeyPtr->hfs.forkType	 = forkType;
 		extentKeyPtr->hfs.fileID	 = fileID;
 		extentKeyPtr->hfs.startBlock = 0;
 	}
+#else 
+	else {
+		err = cmBadNews;
+		goto exit;
+	}
+#endif
 
-	err = BTSearchRecord(fcb, &btIterator, &btRecord, &btRecordSize, &btIterator);
+	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
+
+		goto exit;
 	}
 
 	do
 	{
-		BTreeIterator 		tmpIterator;
-		HFSCatalogNodeID	foundFileID;
+		HFSCatalogNodeID	foundFileID = 0;
 
-		err = BTIterateRecord(fcb, kBTreeNextRecord, &btIterator, &btRecord, &btRecordSize);
+		err = BTIterateRecord(fcb, kBTreeNextRecord, btIterator, &btRecord, &btRecordSize);
 		if ( err != noErr )
 		{
 			if (err == btNotFound)	//	If we hit the end of the BTree
@@ -604,26 +739,45 @@ OSErr	DeleteExtents( ExtendedVCB *vcb, UInt32 fileID, Boolean isHFSPlus )
 				
 			break;					//	We're done now.
 		}
-		
-		foundFileID = isHFSPlus ? extentKeyPtr->hfsPlus.fileID : extentKeyPtr->hfs.fileID;
-		if ( foundFileID != fileID )
+        if (isHFSPlus) {
+            foundFileID = extentKeyPtr->hfsPlus.fileID;
+        }
+#if CONFIG_HFS_STD
+        else {
+            foundFileID = extentKeyPtr->hfs.fileID;
+        }
+#endif
+        
+		if ( foundFileID != fileID ) {
 			break;					//	numbers don't match, we must be done
-
-		tmpIterator = btIterator;
-		err = BTDeleteRecord( fcb, &tmpIterator );
+		}
+		if (quitEarly && isHFSPlus) {
+			/* If we're only deleting one type of fork, then quit early if it doesn't match */
+			if (extentKeyPtr->hfsPlus.forkType != forkType) {
+				break;
+			}
+		}
+		
+		*tmpIterator = *btIterator;
+		err = BTDeleteRecord( fcb, tmpIterator );
 		if (err != noErr)
 			break;
 	}	while ( true );
+
+exit:
 	
+	FREE (tmpIterator, M_TEMP);
+	FREE (btIterator, M_TEMP);
+
 	return( err );
 }
 
 
 //	Check if there are extents represented in the extents overflow file.
-UInt32	CheckExtents( void *extents, UInt32 totalBlocks, Boolean isHFSPlus )
+static u_int32_t  CheckExtents( void *extents, u_int32_t totalBlocks, Boolean isHFSPlus )
 {
-	UInt32		extentAllocationBlocks;
-	UInt16		i;
+	u_int32_t		extentAllocationBlocks;
+	u_int16_t		i;
 
 
 	if ( totalBlocks == 0 )
@@ -640,6 +794,7 @@ UInt32	CheckExtents( void *extents, UInt32 totalBlocks, Boolean isHFSPlus )
 				return( 0 );
 		}
 	}
+#if CONFIG_HFS_STD
 	else
 	{
 		for ( i = 0 ; i < kHFSExtentDensity ; i++ )
@@ -649,6 +804,7 @@ UInt32	CheckExtents( void *extents, UInt32 totalBlocks, Boolean isHFSPlus )
 				return( 0 );
 		}
 	}
+#endif
 	
 	return( extentAllocationBlocks );
 }