]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/hfs/hfscommon/Catalog/FileIDsServices.c
xnu-3248.60.10.tar.gz
[apple/xnu.git] / bsd / hfs / hfscommon / Catalog / FileIDsServices.c
index 4e7a2d0f90d0650133b7d6e063fe55d569571021..fa7e210d0f6924e2480eff193821f97874aeaf07 100644 (file)
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * 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. 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.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * 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
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
-/*
-       File:           FileIDServices.c
-
-       Contains:       File ID manipulating routines.
-
-       Version:        HFS Plus 1.0
-
-       Written by:     Deric Horn
-
-       Copyright:      © 1996-1999 by Apple Computer, Inc., all rights reserved.
-
-       File Ownership:
-
-               DRI:                            Deric Horn
-
-               Other Contact:          xxx put other contact here xxx
-
-               Technology:                     xxx put technology here xxx
-
-       Writers:
-
-               (JL)    Jim Luther
-               (msd)   Mark Day
-               (djb)   Don Brady
-               (DSH)   Deric Horn
-
-       Change History (most recent first):
-         <MacOSX>       3/2/98         djb             Fix extents corruption bug in MoveExtents (radar #2309434).
-         <MacOSX>      11/20/98        djb             Add support for UTF-8 names.
-         <MacOSX>        4/2/98        djb             Switch over to real BTree interface in MoveExtents and DeleteExtents.
-         <MacOSX>       3/31/98        djb             Sync up with final HFSVolumes.h header file.
-
-         <CS21>        11/17/97        djb             PrepareInputName routine now returns an error.
-         <CS20>        11/13/97        djb             Radar #2001699 ResolveFileID needs to use CMNotFound error.
-         <CS19>        10/31/97        JL              #2000184 - CreateFileThreadID and ExchangeFiles now return the
-                                                                       WDCBRecPtr or NULL for external file systems. ExchangeFiles no
-                                                                       longer returns length of FCB table to caller since that wasn't
-                                                                       ever needed.
-               <18>    10/23/97        DSH             1685058, Fix ExchangeFiles by invalidating the node cache before
-                                                                       switching the files.
-         <CS17>        10/19/97        msd             Bug 1684586. GetCatInfo and SetCatInfo use only contentModDate.
-         <CS16>        10/16/97        DSH             Return badFidErr in ResolveFileID if LocateCatalogThread fails
-         <CS15>        10/15/97        DSH             CreateFileThreadID(), remap btExists to fidExists.
-         <CS14>          9/7/97        djb             Turn off some DebugStr calls.
-         <CS13>          9/4/97        msd             Remove call to PropertyExchangeObjects.
-         <CS12>         8/14/97        djb             Remove hard link support.
-         <CS11>         7/18/97        msd             Include LowMemPriv.h.
-         <CS10>         7/16/97        DSH             FilesInternal.i renamed FileMgrInternal.i to avoid name
-                                                                       collision
-          <CS9>          7/8/97        DSH             Loading PrecompiledHeaders from define passed in on C line
-          <CS8>         6/24/97        djb             Add hard link support to ResolveFileID and CreateFileIDRef.
-          <CS7>         6/20/97        msd             Use contentModDate and attributeModDate fields instead of
-                                                                       modifyDate.
-          <CS6>         6/13/97        djb             Switch over from PrepareOutputName to ConvertUnicodeToHFSName.
-                                                                       PrepareInputName now takes an encoding.
-          <CS5>         5/28/97        msd             Move the declaration of FindFileName to FilesInternal.i.
-          <CS4>         5/19/97        djb             No longer need to invalidate vcbDirIDM field.
-          <CS3>         5/16/97        msd             In ExchangeFiles, change srcNamePtr from char * to StringPtr
-                                                                       (fixes warnings).
-          <CS2>         4/28/97        djb             (DSH) Added VolumeWritable check back into CreateFileIDThread.
-          <CS1>         4/24/97        djb             first checked in
-        <HFS23>         4/11/97        DSH             Use extended VCB fields catalogRefNum, and extentsRefNum.
-        <HFS22>          4/9/97        msd             Rewrite CreateFileThreadID so that it properly handles
-                                                                       pathnames, and doesn't overwrite the ioNamePtr. The data field
-                                                                       of FindFileNameGlueRec points to a CatalogNodeData, not
-                                                                       CatalogRecord.
-        <HFS21>          4/4/97        djb             Get in sync with volume format changes.
-        <HFS20>         3/31/97        djb             Change ClearMem to ClearMemory.
-        <HFS19>         3/17/97        DSH             C_FlushCache prototype to FilesInternal.h
-        <HFS18>          3/5/97        msd             ExchangeFiles needs to call PropertyExchangeObjects.
-        <HFS17>         2/13/97        msd             Fix MoveExtents and DeleteExtents to work with HFS+ extent
-                                                                       records.
-        <HFS16>         1/31/97        msd             In MoveExtents, when a record isn't found and you want the next
-                                                                       record in order, use the "next record" offset = 1 instead of
-                                                                       "current record" offset = 0. DeleteExtents would always exit
-                                                                       without doing anything because it was searching for an invalid
-                                                                       key. Removed several DebugStrs that were used as cheap code
-                                                                       coverage.
-        <HFS15>         1/15/97        DSH             Resolve wasn't passing the name back for HFS
-        <HFS14>         1/13/97        djb             LocateCatalogThread now passes back the thread record size.
-        <HFS13>         1/11/97        DSH             HFS+, fixed some Unicode/Pascal strings related bugs for use on
-                                                                       HFS+ volumes.
-        <HFS12>          1/9/97        DSH             Fix ExchangeFiles extents
-        <HFS11>          1/6/97        DSH             pass VCB in CloseFile() routine.
-        <HFS10>          1/6/97        djb             Fixed ResolveFileID - it was not returning a directory ID!
-         <HFS9>          1/3/97        msd             Fix prototype for C_FlushCache. Fix prototype for
-                                                                       TrashFileBlocks.
-         <HFS8>          1/3/97        djb             Integrate latest HFSVolumesPriv.h changes.
-         <HFS7>          1/2/97        DSH             C port of ExchangeFileIDs
-         <HFS6>        12/20/96        djb             Fixed bug in CreateFileID.
-         <HFS5>        12/19/96        DSH             All refs to VCB are now refs to ExtendedVCB
-         <HFS4>        12/19/96        msd             Use kFileThreadExistsMask (from HFSVolumesPriv.h) instead of
-                                                                       kFileThreadMask (from FilesInternal.h) since the latter was
-                                                                       incorrectly defined and has now been removed.
-         <HFS3>        12/19/96        djb             Updated for new B-tree Manager interface.
-         <HFS2>        12/18/96        msd             GetFileThreadID was using a bitwise-OR (|) instead of
-                                                                       bitwise-AND (&) to test for a bit being set.
-         <HFS1>        12/12/96        DSH             first checked in
-
-*/
 
 #include "../../hfs_macos_defs.h"
 #include "../../hfs_format.h"
 #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 {
-       ExtentKey               extentKey;
+       ExtentKey       extentKey;
        ExtentRecord    extentData;
 };
 typedef struct ExtentsRecBuffer ExtentsRecBuffer;
 
 
-OSErr  CreateFileID( ExtendedVCB *vcb, HFSCatalogNodeID fileID, CatalogName *name, HFSCatalogNodeID *threadID );
-OSErr  GetFileThreadID( ExtendedVCB *vcb, HFSCatalogNodeID id, const CatalogName *name, Boolean isHFSPlus, UInt32 *threadID );
+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 );
 
-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 );
+#if CONFIG_HFS_STD
+static void  CopyCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest );
+#endif
 
-void   CopyExtentInfo( ExtentKey *key, ExtentRecord *data, ExtentsRecBuffer *buffer, UInt16 bufferCount );
-extern void    TrashFileBlocks( ExtendedVCB *vcb, UInt32 fileNumber );
+static void  CopyBigCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest );
+static void  CopyExtentInfo( ExtentKey *key, ExtentRecord *data, ExtentsRecBuffer *buffer, u_int16_t bufferCount );
 
+/* 
+ * 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, UInt32 srcHint, UInt32 destHint )
+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      srcKey;         // 518 bytes
+       CatalogKey      destKey;        // 518 bytes
        CatalogRecord   srcData;        // 520 bytes
-       CatalogKey              destKey;        // 518 bytes
        CatalogRecord   destData;       // 520 bytes
        CatalogRecord   swapData;       // 520 bytes
-       SInt16                  numSrcExtentBlocks;
-       SInt16                  numDestExtentBlocks;
-       UInt32                  textEncoding;
-       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
+       int16_t         numSrcExtentBlocks;
+       int16_t         numDestExtentBlocks;
+       OSErr           err;
+       Boolean         isHFSPlus = ( vcb->vcbSigWord == kHFSPlusSigWord );
 
-       err = BuildCatalogKeyUTF8(vcb, srcID, srcName, kUndefinedStrLen, &srcKey, &textEncoding);
+       err = BuildCatalogKeyUTF8(vcb, srcID, srcName, kUndefinedStrLen, &srcKey, NULL);
        ReturnIfError(err);
 
-       err = BuildCatalogKeyUTF8(vcb, destID, destName, kUndefinedStrLen, &destKey, &textEncoding);
+       err = BuildCatalogKeyUTF8(vcb, destID, destName, kUndefinedStrLen, &destKey, NULL);
        ReturnIfError(err);
 
        if ( isHFSPlus )
@@ -202,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;
@@ -252,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;
@@ -266,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;
@@ -301,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
@@ -338,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
@@ -359,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;
@@ -393,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;
@@ -407,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;
@@ -444,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
@@ -457,20 +427,20 @@ FlushAndReturn:
 }
 
 
-void   CopyCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest )
+#if CONFIG_HFS_STD
+static void  CopyCatalogNodeInfo( CatalogRecord *src, CatalogRecord *dest )
 {
-//     dest->hfsFile.filStBlk = src->hfsFile.filStBlk;
        dest->hfsFile.dataLogicalSize   = src->hfsFile.dataLogicalSize;
        dest->hfsFile.dataPhysicalSize = src->hfsFile.dataPhysicalSize;
-//     dest->hfsFile.filRStBlk = src->hfsFile.filRStBlk;
        dest->hfsFile.rsrcLogicalSize   = src->hfsFile.rsrcLogicalSize;
        dest->hfsFile.rsrcPhysicalSize = src->hfsFile.rsrcPhysicalSize;
        dest->hfsFile.modifyDate = src->hfsFile.modifyDate;
        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) );
@@ -478,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;
 
@@ -515,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);
@@ -529,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
@@ -546,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, kInvalidMRUCacheKey, &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;
        }
 
@@ -567,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 ) );
@@ -644,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;
 
@@ -669,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, kInvalidMRUCacheKey, &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
@@ -706,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 )
@@ -742,6 +794,7 @@ UInt32      CheckExtents( void *extents, UInt32 totalBlocks, Boolean isHFSPlus )
                                return( 0 );
                }
        }
+#if CONFIG_HFS_STD
        else
        {
                for ( i = 0 ; i < kHFSExtentDensity ; i++ )
@@ -751,6 +804,7 @@ UInt32      CheckExtents( void *extents, UInt32 totalBlocks, Boolean isHFSPlus )
                                return( 0 );
                }
        }
+#endif
        
        return( extentAllocationBlocks );
 }