]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/hfs/hfscommon/Catalog/Catalog.c
xnu-344.12.2.tar.gz
[apple/xnu.git] / bsd / hfs / hfscommon / Catalog / Catalog.c
index c71d5c7f9512d74cdd82bb1a0e621ee9f021faa3..e7134028f5b16839c9f9f5363948c4af188a1b21 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
-/*
-       File:           Catalog.c
-
-       Contains:       Catalog Manager Implementation
-
-       Version:        HFS Plus 1.0
-
-       Copyright:      © 1996-2000 by Apple Computer, Inc., all rights reserved.
-
-       File Ownership:
-
-               DRI:                            Don Brady
-
-               Other Contact:          Mark Day
-
-               Technology:                     xxx put technology here xxx
-
-       Writers:
-
-               (msd)   Mark Day
-               (DSH)   Deric Horn
-               (djb)   Don Brady
-
-       Change History (most recent first):
-         <MacOSX>        2/2/99        djb             Fix CreateFileIDRef to copy entire name when creating thread record.
-         <MacOSX>        1/7/99        djb             Use a max bytes of 256 in calls to ConvertUnicodeToUTF8.
-         <MacOSX>       12/9/98        djb             UpdateCatalogNode only updates vcbLsMod if contentModDate changes.
-         <MacOSX>       11/5/98        djb             Add support for UTF-8 names.
-         <MacOSX>       8/31/98        djb             GetTimeLocal now takes an input.
-         <MacOSX>        7/8/98        ser             Added accessDate and AttributeModDate init. to create routine.
-         <MacOSX>        6/5/98        djb             Added CreateFileIDRef routine.
-         <MacOSX>        6/3/98        djb             Merge MoveCatalogRecord and RenameCatalogRecord into one routine.
-         <MacOSX>       4/17/98        djb             Add VCB locking.
-         <MacOSX>        4/6/98        djb             Catalog iterators now need to be released.
-         <MacOSX>        4/6/98        djb             Removed CreateVolumeCatalogCache and DisposeVolumeCatalogCache (obsolete).
-         <MacOSX>       3/31/98        djb             Make UpdateCatalogNode interface thread-safe.
-         <MacOSX>       3/31/98        djb             Sync up with final HFSVolumes.h header file.
-         <MacOSX>       3/17/98        djb             Fixed CreateCatalogNode interface to take kCatalogFolderNode and
-                                                                       kCatalogFileNode as type input.
-
-         <CS36>        12/10/97        DSH             2201501, UpdateCatalogNode to only update CatalogRecords which
-                                                                       are under 2 Gig by checking the overloaded valence field.
-         <CS35>        11/20/97        djb             Radar #2002357. Fixing retry mechanism.
-         <CS34>        11/17/97        djb             PrepareInputName routine now returns an error.
-         <CS33>        11/13/97        djb             Radar #1683572. Add new GetCatalogOffspringFile routine for
-                                                                       PBGetFileInfo calls (support used to be in HFSPathnameCalls.a).
-         <CS32>         11/7/97        msd             Change calls to the wrapper routine CompareUnicodeNames() to use
-                                                                       the underlying routine FastUnicodeCompare() instead.
-         <CS31>        10/19/97        msd             Bug 1684586. GetCatInfo and SetCatInfo use only contentModDate.
-         <CS30>        10/17/97        djb             Change Catalog Create/Rename to use ConvertInputNameToUnicode.
-         <CS29>        10/13/97        djb             Update volumeNameEncodingHint when changing volume name. Change
-                                                                       name of GetSystemTextEncoding to GetDefaultTextEncoding.
-         <CS28>         10/1/97        djb             Add new catalog iterators and node cache to improve performance.
-         <CS27>         9/12/97        msd             In CreateCatalogNode, make sure parent is a folder, not a file.
-         <CS26>         9/10/97        msd             In RenameCatalogNodeUnicode, remove HFS-only code and make sure
-                                                                       the conversion context is set up and marked in the volume's
-                                                                       bitmap.
-         <CS25>          9/9/97        DSH             Added RelString_Glue to avoid having to link DFAEngine with
-                                                                       Interface.o
-         <CS24>          9/8/97        msd             Make sure a folder's modifyDate is set whenever its
-                                                                       contentModDate is set. In UpdateCatalogNode, make sure the
-                                                                       modifyDate is greater or equal to contentModDate; do a DebugStr
-                                                                       only for debug builds.
-         <CS23>          9/7/97        djb             Make some DebuStrs HFS_DIAGNOSTIC only.
-         <CS22>          9/4/97        djb             Add more Catalog Iterators, Instrument RelString.
-         <CS21>          9/4/97        msd             Remove call to PropertyDeleteObject.
-         <CS20>         8/18/97        DSH             Use RelString instead of FastRelString in DFA to avoid loading
-                                                                       branch island instead of table.
-         <CS19>         8/14/97        djb             Remove hard link support. Switch over to FastRelString.
-         <CS18>          8/8/97        djb             Fixed bugs in LinkCatalogNode.
-         <CS17>          8/5/97        djb             Don't restore vcbNxtCNID if thread exists (radar #1670614).
-         <CS16>         7/25/97        DSH             Pass heuristicHint to BTSearchRecord from GetCatalogOffspring.
-         <CS15>         7/18/97        msd             Include LowMemPriv.h. In LinkCatalogNode, now sets the
-                                                                       kInsertedFileThread2 flag correctly; should only affect error
-                                                                       recovery code.
-         <CS14>         7/16/97        DSH             FilesInternal.i renamed FileMgrInternal.i to avoid name
-                                                                       collision
-         <CS13>          7/8/97        DSH             Loading PrecompiledHeaders from define passed in on C line
-         <CS12>         6/27/97        msd             Add PBLongRename SPI. Added RenameCatalogNodeUnicode call, which
-                                                                       takes Unicode names for HFS Plus volumes. Removed calls to
-                                                                       Attributes module when creating, renaming or moving nodes.
-         <CS11>         6/24/97        djb             Validate the mangled name matches in
-                                                                       LocateCatalogNodeByMangledName.
-         <CS10>         6/24/97        djb             Add hard link support.
-          <CS9>         6/20/97        msd             Use contentModDate and attributeModDate fields instead of
-                                                                       modifyDate. Made CopyCatalogNodeData public.
-          <CS8>         6/18/97        djb             Add routines LocateCatalogNodeWithRetry & UpdateVolumeEncodings.
-                                                                       Add mangled name retry to DeleteCatalogNode, MoveCatalogNode and
-                                                                       RenameCatalogNode.
-          <CS7>         6/13/97        djb             Major changes for longname support and multiple scripts.
-          <CS6>          6/9/97        msd             Instead of calling GetDateTime, call GetTimeUTC or GetTimeLocal.
-                                                                       Dates on an HFS Plus volume need to be converted to/from UTC.
-          <CS5>          6/4/97        djb             Set textEncoding hint in Rename and Create. TrashCatalogIterator
-                                                                       was not always called with the correct folder ID.
-          <CS4>         5/21/97        djb             Turn off recursive iterators.
-          <CS3>         5/19/97        djb             Add support for B-tree iterators to GetCatalogOffspring.
-          <CS2>          5/9/97        djb             Get in sync with FilesInternal.i.
-          <CS1>         4/24/97        djb             First checked into Common System Project.
-        <HFS26>         4/11/97        DSH             Use extended VCB fields catalogRefNum, and extentsRefNum.
-        <HFS25>          4/4/97        djb             Get in sync with volume format changes.
-        <HFS24>         3/31/97        djb             Additional HFS Plus optimization added to GetCatalogNode.
-        <HFS23>         3/28/97        djb             Add Optimization to GetCatalogNode.
-        <HFS22>         3/27/97        djb             Unicode conversion routines now use byte counts.
-        <HFS21>         3/17/97        DSH             Casting to compile with SC, GetRecordSize ->
-                                                                       GetCatalogRecordSize, moved some prototypes to extern.
-        <HFS20>          3/5/97        msd             Add calls to Property Manager when catalog entries are created,
-                                                                       deleted, moved, renamed.
-        <HFS19>         2/19/97        djb             HFS Plus catalog keys no longer have a pad word.
-        <HFS18>         1/24/97        DSH             (djb) GetCatalogOffSpring() fix volume->vcbDirIDM = 0
-        <HFS17>         1/23/97        DSH             Truncate name to CMMaxCName characters in PrepareInputName().
-        <HFS16>         1/14/97        djb             Fixed RenameCatalogNode for case when just a cnid is passed.
-        <HFS15>         1/13/97        djb             Added support for varaible sized thread records in HFS+.
-        <HFS14>         1/11/97        DSH             Moving PrepareInputName() declaration fo FilesInternal.h
-        <HFS13>         1/10/97        djb             CopyCatalogNodeData was trashing the resource extents on HFS+.
-        <HFS12>         1/10/97        djb             CopyCatalogNodeData was trashing dataLogicalSize on HFS+ disks.
-        <HFS11>          1/9/97        djb             Get in sync with new HFSVolumesPriv.i.
-        <HFS10>          1/6/97        djb             Added name length checking to CompareExtendedCatalogKeys. Fixed
-                                                                       GetCatalogOffspring - it was not correctly passing the HFS+ flag
-                                                                       to PrepareOutputName. Fixed BuildKey for HFS+ keys.
-         <HFS9>          1/3/97        djb             Fixed termination bug in GetCatalogOffspring. Added support for
-                                                                       large keys. Integrated latest HFSVolumesPriv.h changes.
-         <HFS8>        12/19/96        DSH             Changed call from C_FlushMDB to HFS+ savy
-                                                                       FlushVolumeControlBlock()
-         <HFS7>        12/19/96        djb             Add new B-tree manager...
-         <HFS6>        12/13/96        djb             Fixing bugs for HFS+. Switch to HFSUnicodeWrappers routines.
-         <HFS5>        12/12/96        djb             Changed the SPI for GetCatalogNode, GetCatalogOffspring, and
-                                                                       UpdateCatalogNode.
-         <HFS4>        12/12/96        DSH             Removed static function declarations for functions used by
-                                                                       FileIDServices.c.
-         <HFS3>        11/11/96        djb             Added support for HFS+ Unicode names. Major changes throughout.
-         <HFS2>         11/4/96        djb             Added FSSpec output to GetCatalogNode and GetCatalogOffspring
-                                                                       routines.
-         <HFS1>        10/29/96        djb             first checked in
-
-*/
 
 #pragma segment Catalog
 
 
 #pragma segment Catalog
 
 #include       "../headers/BTreesInternal.h"
 #include       "../headers/CatalogPrivate.h"
 #include       "../headers/HFSUnicodeWrappers.h"
 #include       "../headers/BTreesInternal.h"
 #include       "../headers/CatalogPrivate.h"
 #include       "../headers/HFSUnicodeWrappers.h"
-#include       "../headers/HFSInstrumentation.h"
 
 
 // External routines
 
 extern SInt32 FastRelString( ConstStr255Param str1, ConstStr255Param str2 );
 
 
 
 // External routines
 
 extern SInt32 FastRelString( ConstStr255Param str1, ConstStr255Param str2 );
 
-extern SInt16 RelString_Glue(StringPtr pStr1, StringPtr pStr2);
-
-
-// Internal routines
-
-static OSErr IterateCatalogNode(ExtendedVCB *volume, CatalogIterator *catalogIterator,
-                               UInt16 index, CatalogNodeData *nodeData,
-                               HFSCatalogNodeID *nodeID, SInt16 *nodeType);
-
-void InitCatalogThreadRecord(ExtendedVCB *volume, UInt32 nodeType, CatalogKey *nodeKey,
-                                                        CatalogRecord *record, UInt32 *threadSize);
-
-void InitCatalogRecord(ExtendedVCB *volume, UInt32 nodeType, UInt32 textEncoding,
-                                        CatalogRecord *record, UInt32 *recordSize, HFSCatalogNodeID catalogNodeID);
-
-#if HFS_DIAGNOSTIC
-               #include <sys/systm.h>
-           #define PRINTIT(A) kprintf A;
-#else
-           #define PRINTIT(A)
-#endif /* HFS_DIAGNOSTIC */
 
 //_________________________________________________________________________________
 //     Exported Routines
 //
 
 //_________________________________________________________________________________
 //     Exported Routines
 //
-//             CreateCatalogNode               -  Creates a new folder or file CNode.
-//             DeleteCatalogNode               -  Deletes an existing folder or file CNode.
-//             GetCatalogNode                  -  Locates an existing folder or file CNode.
-//             GetCatalogOffspringFile -  Gets an offspring file record from a folder.
-//             GetCatalogOffspring             -  Gets an offspring record from a folder.
-//             MoveRenameCatalogNode   -  Moves/Renames an existing folder or file CNode.
-//             UpdateCatalogNode               -  Marks a Catalog BTree node as 'dirty'.
-//             CreateFileIDRef                 -  Creates a file thread record for hfs file node
-//             CompareCatalogKeys              -  Compares two catalog keys.
-//
-//_________________________________________________________________________________
-
-
-//_________________________________________________________________________________
-//
-//     About date/time values:
-//
-//     Date/time values stored in control blocks and generic structures (such as
-//     CatalogNodeData) are always stored in local time.  Values stored in HFS volume
-//     format structures (such as B-tree records) are also stored in local time.
-//     Values stored in HFS Plus format structures are stored in UTC.
-//_________________________________________________________________________________
-
-
-// Implementation
-
-
-//_________________________________________________________________________________
-//     Routine:        CreateCatalogNode
-//
-//     Function:       Creates a new folder or file CNode.     A new folder or file
-//                             record is added to the catalog BTree.  If a folder CNode is
-//                             being created, a new thread record is also added.
-//
-//_________________________________________________________________________________
-
-OSErr
-CreateCatalogNode ( ExtendedVCB *volume, HFSCatalogNodeID parentID, ConstUTF8Param name,
-                                       UInt32 nodeType, HFSCatalogNodeID *catalogNodeID, UInt32 *catalogHint)
-{
-       CatalogKey              *nodeKey;
-       CatalogRecord   nodeData;                       // 520 bytes
-       UInt32                  nodeDataSize;
-       CatalogRecord   parentThreadData;       // 520 bytes
-       HFSCatalogNodeID parentsParentID;
-       CatalogName             *parentNamePtr;
-       UInt32                  tempHint;
-       UInt32                  textEncoding;
-       UInt16                  tempSize;
-       OSErr                   result;
-       Boolean                 isHFSPlus = (volume->vcbSigWord == kHFSPlusSigWord);
-       FCB *fcb;
-       FSBufferDescriptor btRecord;
-       BTreeIterator iterator;
-       BTreeIterator threadIter;
-       HFSCatalogNodeID nextCNID;
-
-       if (nodeType != kCatalogFolderNode && nodeType != kCatalogFileNode)
-               return paramErr;
-
-       fcb = GetFileControlBlock(volume->catalogRefNum);
-       nodeKey = (CatalogKey *) &iterator.key;
-
-       //--- make sure parent exists (by locating the parent's thread record)
-                       
-       result = LocateCatalogThread(volume, parentID, &parentThreadData, &tempSize, &tempHint);
-       ReturnIfError(result);
-
-       TrashCatalogIterator(volume, parentID);         // invalidate any iterators for this parentID
-
-       // save copy of parent's parentID and name.
-
-       if (isHFSPlus)
-       {
-               if (parentThreadData.recordType != kHFSPlusFolderThreadRecord)
-                       return dirNFErr;
-               
-               parentsParentID = parentThreadData.hfsPlusThread.parentID;
-               parentNamePtr = (CatalogName*) &parentThreadData.hfsPlusThread.nodeName;
-       }
-       else
-       {
-               if (parentThreadData.recordType != kHFSFolderThreadRecord)
-                       return dirNFErr;
-               
-               parentsParentID = parentThreadData.hfsThread.parentID;
-               parentNamePtr = (CatalogName*) &parentThreadData.hfsThread.nodeName;
-       }
-       
-       // invalidate cache for parent since its about to change
-       InvalidateCatalogNodeCache(volume, parentsParentID);    
-
-       //--- build key for new catalog node
-       result = BuildCatalogKeyUTF8(volume, parentID, name, kUndefinedStrLen, nodeKey, &textEncoding);
-       ReturnIfError(result);
-
-       /* make sure it doesn't exist */
-       result = BTSearchRecord(fcb, &iterator, kInvalidMRUCacheKey, NULL, NULL, &iterator);
-       if (result != btNotFound)
-               return (cmExists);
-
-       nextCNID = volume->vcbNxtCNID;
-       if (!isHFSPlus && nextCNID == 0xFFFFFFFF)
-               return (dskFulErr);
-
-       //--- build thread record for new CNode
-       if (isHFSPlus || nodeType == kCatalogFolderNode)
-       {
-               CatalogRecord   threadData;     // 520 bytes
-               UInt32          threadSize;
-
-               btRecord.bufferAddress = &threadData;
-               btRecord.itemSize = threadSize;
-               btRecord.itemCount = 1;
-               InitCatalogThreadRecord(volume, nodeType, nodeKey, &threadData, &threadSize);
-TryNextID:             
-               BuildCatalogKey(nextCNID, NULL, isHFSPlus, (CatalogKey*) &threadIter.key);
-               result = BTInsertRecord(fcb, &threadIter, &btRecord, threadSize);
-               if (result == btExists && isHFSPlus)
-               {
-                       /*
-                        * Allow CNIDs on HFS Plus volumes to wrap around
-                        */
-                       ++nextCNID;
-                       if (nextCNID < kHFSFirstUserCatalogNodeID)
-                       {
-                               volume->vcbAtrb |= kHFSCatalogNodeIDsReusedMask;
-                               volume->vcbFlags |= 0xFF00;
-                               nextCNID = kHFSFirstUserCatalogNodeID;
-                       }
-                       goto TryNextID;
-               }
-               ReturnIfError(result);
-       }
-
-       //--- initialize catalog data record (for folder or file)
-       btRecord.bufferAddress = &nodeData;
-       btRecord.itemSize = nodeDataSize;
-       btRecord.itemCount = 1;
-       InitCatalogRecord(volume, nodeType, textEncoding, &nodeData, &nodeDataSize, nextCNID);
-
-       //--- add new folder/file record to catalog BTree
-       result = BTInsertRecord(fcb, &iterator, &btRecord, nodeDataSize );
-       if (result)
-       {
-               if (result == btExists)
-                       result = cmExists;
-
-               if (isHFSPlus || nodeType == kCatalogFolderNode)
-                       (void) BTDeleteRecord(fcb, &threadIter);
-
-               return result;
-       }
-
-       /*
-        * Return the CNID actually used.  Update the volume's next ID.
-        */
-       *catalogNodeID = nextCNID;
-       if (++nextCNID < kHFSFirstUserCatalogNodeID)
-       {
-               volume->vcbAtrb |= kHFSCatalogNodeIDsReusedMask;
-               volume->vcbFlags |= 0xFF00;
-               nextCNID = kHFSFirstUserCatalogNodeID;
-       }
-       volume->vcbNxtCNID = nextCNID;
-
-       //--- update counters...
-
-       result = UpdateFolderCount( volume, parentsParentID, parentNamePtr, nodeData.recordType, kNoHint, +1);
-       ReturnIfError(result);  /* XXX what about cleanup ??? */
-       
-       AdjustVolumeCounts(volume, nodeData.recordType, +1);
-
-       result = FlushCatalog(volume);
-
-       return result;
-
-} // end CreateCatalogNode
-
-
-/*
- * initialize catalog data record (for folder or file)
- */
-void InitCatalogRecord(ExtendedVCB *volume, UInt32 nodeType, UInt32 textEncoding, CatalogRecord *record, UInt32 *recordSize, HFSCatalogNodeID nodeID)
-{
-       UInt32 timeStamp;
-
-       ClearMemory(record, sizeof(CatalogRecord));     // first clear the record
-       
-       if (volume->vcbSigWord == kHFSPlusSigWord)
-       {
-               timeStamp = GetTimeUTC();               // get current date/time (universal)
-
-               UpdateVolumeEncodings(volume, textEncoding);
-
-               if (nodeType == kCatalogFolderNode )
-               {
-                       record->recordType = kHFSPlusFolderRecord;
-                       record->hfsPlusFolder.folderID = nodeID;
-                       record->hfsPlusFolder.createDate = timeStamp;
-                       record->hfsPlusFolder.contentModDate = timeStamp;
-            record->hfsPlusFolder.accessDate = timeStamp;
-            record->hfsPlusFolder.attributeModDate     = timeStamp;
-                       record->hfsPlusFolder.textEncoding = textEncoding;
-                       *recordSize = sizeof(HFSPlusCatalogFolder);
-               //      threadType = kHFSPlusFolderThreadRecord;
-               }
-               else if (nodeType == kCatalogFileNode )
-               {
-                       record->recordType = kHFSPlusFileRecord;
-                       record->hfsPlusFile.fileID = nodeID;
-                       record->hfsPlusFile.createDate = timeStamp;
-            record->hfsPlusFile.contentModDate = timeStamp;
-            record->hfsPlusFile.accessDate = timeStamp;
-            record->hfsPlusFile.attributeModDate = timeStamp;
-                       record->hfsPlusFile.flags |= kHFSThreadExistsMask;
-                       record->hfsPlusFile.textEncoding = textEncoding;
-                       *recordSize = sizeof(HFSPlusCatalogFile);
-               //      threadType = kHFSPlusFileThreadRecord;
-               }
-       }
-       else /* standard hfs */
-       {
-               timeStamp = GetTimeLocal(true);         // get current local date/time
-
-               if (nodeType == kCatalogFolderNode )
-               {
-                       record->recordType = kHFSFolderRecord;
-                       record->hfsFolder.folderID = nodeID;
-                       record->hfsFolder.createDate = timeStamp;
-                       record->hfsFolder.modifyDate = timeStamp;
-                       *recordSize = sizeof(HFSCatalogFolder);
-               //      threadType = kHFSFolderThreadRecord;
-               }
-               else if (nodeType == kCatalogFileNode )
-               {
-                       record->recordType = kHFSFileRecord;
-                       record->hfsFile.fileID = nodeID;
-                       record->hfsFile.createDate = timeStamp;
-                       record->hfsFile.modifyDate = timeStamp;
-                       *recordSize = sizeof(HFSCatalogFile);
-               }
-       }
-}
-
-
-void InitCatalogThreadRecord(ExtendedVCB *volume, UInt32 nodeType, CatalogKey *nodeKey,
-                                                        CatalogRecord *record, UInt32 *threadSize)
-{      
-       ClearMemory(record, sizeof(CatalogRecord) );    // first clear the record
-
-       if (volume->vcbSigWord == kHFSPlusSigWord)
-       {
-               if (nodeType == kCatalogFolderNode)
-                       record->recordType = kHFSPlusFolderThreadRecord;
-               else
-                       record->recordType = kHFSPlusFileThreadRecord;
-               record->hfsPlusThread.parentID = nodeKey->hfsPlus.parentID;                     
-               *threadSize = sizeof(record->hfsPlusThread);
-
-               // HFS Plus has varaible sized threads so adjust to actual length
-               *threadSize -= ( sizeof(record->hfsPlusThread.nodeName.unicode) -
-                                               (nodeKey->hfsPlus.nodeName.length * sizeof(UniChar)) );
-               BlockMoveData(&nodeKey->hfsPlus.nodeName, &record->hfsPlusThread.nodeName,
-                                         sizeof(UniChar) * (nodeKey->hfsPlus.nodeName.length + 1));
-    }
-    else // classic HFS
-    {
-               if (nodeType == kCatalogFolderNode)
-                       record->recordType = kHFSFolderThreadRecord;
-               else
-                       record->recordType = kHFSFileThreadRecord;
-               record->hfsThread.parentID = nodeKey->hfs.parentID;     
-               *threadSize = sizeof(record->hfsThread);
-               BlockMoveData(&nodeKey->hfs.nodeName, &record->hfsThread.nodeName,
-                                         nodeKey->hfs.nodeName[0] + 1);
-    }
-}
-
-
-//_________________________________________________________________________________
-//     Routine:        DeleteCatalogNode
-//
-//     Function:       Deletes an existing folder or file CNode. The thread record
-//                             is also deleted for directories and files that have thread
-//                             records.
-//
-//                             The valence for a folder must be zero before it can be deleted.
-//                             The rootfolder cannot be deleted.
-//
-//_________________________________________________________________________________
-
-OSErr
-DeleteCatalogNode(ExtendedVCB *volume, HFSCatalogNodeID parentID, ConstUTF8Param name, UInt32 hint)
-{
-       CatalogKey                      key;            // 518 bytes
-       CatalogRecord           data;           // 520 bytes
-       UInt32                          nodeHint;
-       HFSCatalogNodeID        nodeID;
-       HFSCatalogNodeID        nodeParentID;
-       UInt16                          nodeType;
-       OSErr                           result;
-       Boolean                         isHFSPlus = (volume->vcbSigWord == kHFSPlusSigWord);
-       
-       //--- locate subject catalog node
-
-       result = BuildCatalogKeyUTF8(volume, parentID, name, kUndefinedStrLen, &key, NULL);
-       ReturnIfError(result);
-
-       result = LocateCatalogNodeByKey(volume, hint, &key, &data, &nodeHint);
-
-       // if we did not find it by name, then look for an embedded file ID in a mangled name
-       if ( (result == cmNotFound) && isHFSPlus )
-        result = LocateCatalogNodeByMangledName(volume, parentID, name, kUndefinedStrLen, &key, &data, &nodeHint);
-       ReturnIfError(result);
-
-       nodeParentID = isHFSPlus ? key.hfsPlus.parentID : key.hfs.parentID;     // establish real parent cnid
-       nodeType = data.recordType;             // establish cnode type
-       nodeID = 0;
-
-       switch (nodeType)
-       {
-               case kHFSFolderRecord:
-                       if (data.hfsFolder.valence != 0)                // is it empty?
-                               return cmNotEmpty;
-                       
-                       nodeID = data.hfsFolder.folderID;
-                       break;
-
-               case kHFSPlusFolderRecord:
-                       if (data.hfsPlusFolder.valence != 0)            // is it empty?
-                               return cmNotEmpty;
-                       
-                       nodeID = data.hfsPlusFolder.folderID;
-                       break;
-
-               case kHFSFileRecord:
-                       if (data.hfsFile.flags & kHFSThreadExistsMask)
-                               nodeID = data.hfsFile.fileID;
-                       break;
-
-               case kHFSPlusFileRecord:
-                       nodeID = data.hfsPlusFile.fileID;       // note: HFS Plus files always have a thread
-                       break;
-
-               default:
-                       return cmNotFound;
-       }
-
-
-       if (nodeID == fsRtDirID)        // is this the root folder?
-               return cmRootCN;                // sorry, you can't delete the root!
-
-       TrashCatalogIterator(volume, nodeParentID);                     // invalidate any iterators for this parentID
-       InvalidateCatalogNodeCache(volume, nodeParentID);       // and invalidate node cache
-
-       //--- delete catalog records for CNode and file threads if they exist
-
-       result = DeleteBTreeRecord(volume->catalogRefNum, &key);
-       ReturnIfError(result);
-
-       if ( nodeID ) 
-       {
-               CatalogKey threadKey;   // 518 bytes
-               
-               BuildCatalogKey(nodeID, NULL, isHFSPlus, &threadKey);
-               
-               (void) DeleteBTreeRecord(volume->catalogRefNum, &threadKey);    // ignore errors for thread deletes
-       }
-
-       //--- update counters...
-
-       result = UpdateFolderCount(volume, nodeParentID, NULL, nodeType, kNoHint, -1);
-       ReturnIfError(result);
-
-       AdjustVolumeCounts(volume, nodeType, -1);       // all done with this file or folder
-
-       result = FlushCatalog(volume);
-
-       return result;
-
-} // end DeleteCatalogNode
-
-
-//_________________________________________________________________________________
-//     Routine:        GetCatalogNode
-//
-//     Function:       Locates an existing folder or file CNode and pointer to the CNode data record.
+//             CompareCatalogKeys  -  Compares two catalog keys.
 //
 //_________________________________________________________________________________
 
 //
 //_________________________________________________________________________________
 
-OSErr
-GetCatalogNode( ExtendedVCB *volume, HFSCatalogNodeID parentID, ConstUTF8Param name, UInt32 nameLen, UInt32 hint,
-               CatalogNodeData *nodeData, UInt32 *newHint)
-{
-       CatalogKey *key;
-       CatalogRecord *record;
-       BTreeIterator searchIterator;
-       FSBufferDescriptor btRecord;
-       ByteCount utf8len;
-       UInt32 heuristicHint;
-       UInt32 *cachedHint;
-       FCB *fcb;
-       OSErr result = noErr;
-       UInt16 dataSize;
-       Boolean isHFSPlus = (volume->vcbSigWord == kHFSPlusSigWord);
-
-       if (isHFSPlus) {
-               btRecord.bufferAddress = nodeData;
-               btRecord.itemSize = sizeof(CatalogNodeData);
-       } else {
-               btRecord.bufferAddress = &nodeData->cnd_extra;
-               btRecord.itemSize = sizeof(HFSCatalogFile);
-       }
-
-       btRecord.itemCount = 1;
-       record = (CatalogRecord *) btRecord.bufferAddress;
-       key = (CatalogKey *) &searchIterator.key;
-       
-    if (name && nameLen == kUndefinedStrLen)
-               nameLen = strlen(name);
-
-       result = BuildCatalogKeyUTF8(volume, parentID, name, nameLen, key, NULL);
-       ReturnIfError(result);
-       
-       fcb = GetFileControlBlock(volume->catalogRefNum);
-       searchIterator.hint.nodeNum = *newHint;
-       searchIterator.hint.index = 0;
-       
-       /*
-        * We pass a 2nd hint/guess into BTSearchRecord.  The heuristicHint
-        * is a mapping of dirID and nodeNumber, in hopes that the current
-        * search will be in the same node as the last search with the same
-        * parentID.
-        */
-       if (name != NULL && GetMRUCacheBlock(parentID, volume->hintCachePtr, (Ptr *)&cachedHint) == 0)
-               heuristicHint = *cachedHint;
-       else
-               heuristicHint = kInvalidMRUCacheKey;
-
-       result = BTSearchRecord(fcb, &searchIterator, heuristicHint, &btRecord, &dataSize, &searchIterator);
-       if (result == btNotFound)
-               result = cmNotFound;    
-
-       if (name != NULL && result == noErr)
-               InsertMRUCacheBlock(volume->hintCachePtr, parentID, (Ptr) &(searchIterator.hint.nodeNum));
-
-       if (result == noErr) {
-               CatalogName *nodeName = NULL;
-               HFSCatalogNodeID threadParentID;
-
-               /* if we got a thread record, then go look up real record */
-               switch (record->recordType) {
-
-               case kHFSFileThreadRecord:
-               case kHFSFolderThreadRecord:
-                       threadParentID = record->hfsThread.parentID;
-                       nodeName = (CatalogName *) &record->hfsThread.nodeName;
-                       break;
-
-               case kHFSPlusFileThreadRecord:
-               case kHFSPlusFolderThreadRecord:
-                       threadParentID = record->hfsPlusThread.parentID;
-                       nodeName = (CatalogName *) &record->hfsPlusThread.nodeName;     
-                       break;
-
-               default:
-                       threadParentID = 0;
-                       *newHint = searchIterator.hint.nodeNum;
-                       break;
-               }
-               if (threadParentID) {
-                       BuildCatalogKey(threadParentID, nodeName, isHFSPlus, key);
-                       searchIterator.hint.nodeNum = kNoHint;
-                       searchIterator.hint.index = 0;
-
-                       result = BTSearchRecord(fcb, &searchIterator, kInvalidMRUCacheKey, &btRecord, &dataSize, &searchIterator);
-                       if (result == btNotFound)
-                               result = cmNotFound;
-                       if (result == noErr)
-                               *newHint = searchIterator.hint.nodeNum;
-               }
-       }
-       /*
-        * If we did not find it by name, then look for an embedded
-        * file ID in a mangled name.
-        */
-       if ( result == cmNotFound && isHFSPlus)
-               result = LocateCatalogNodeByMangledName(volume, parentID, name, nameLen,
-                                                       key, record, newHint);
-
-       /*
-        * In Mac OS X there can also be HFS filenames that
-        * could not be encoded using the default encoding.
-        * In which case they were encoded as MacRoman.
-        */
-       if (result == cmNotFound && !isHFSPlus) {
-               Str31 hfsName;
-
-               utf8_to_mac_roman(nameLen, name, hfsName);      
-               result = LocateCatalogNode(volume, parentID, (CatalogName*)hfsName,
-                                          0, key, record, newHint);
-       }
-       ReturnIfError(result);
-       
-       nodeData->cnm_parID = isHFSPlus ? key->hfsPlus.parentID : key->hfs.parentID;
-
-       if (nodeData->cnm_flags & kCatNameNoCopyName) {
-               if (! isHFSPlus) {
-                       if (record->recordType == kHFSFolderRecord || record->recordType == kHFSFileRecord)
-                               CopyCatalogNodeData(volume, record, nodeData);
-                       else
-                               result = cmNotFound;
-               }
-       }
-       else {
-               nodeData->cnm_nameptr = nodeData->cnm_namespace;
-               if ( isHFSPlus ) {
-                       result = utf8_encodestr(key->hfsPlus.nodeName.unicode,
-                                       key->hfsPlus.nodeName.length * sizeof(UniChar),
-                                       nodeData->cnm_namespace, (size_t *)&utf8len,
-                                       MAXHFSVNODELEN + 1, ':', 0);
-
-                       /* Need to allocate buffer large enough */
-                       if (result == ENAMETOOLONG) {
-                               utf8len = utf8_encodelen(key->hfsPlus.nodeName.unicode,
-                                               key->hfsPlus.nodeName.length * sizeof(UniChar),
-                                               ':', 0);
-                               nodeData->cnm_nameptr = NewPtr(utf8len + 1);
-                               nodeData->cnm_flags |= kCatNameIsAllocated;
-                               result = utf8_encodestr(key->hfsPlus.nodeName.unicode,
-                                               key->hfsPlus.nodeName.length * sizeof(UniChar),
-                                               nodeData->cnm_nameptr, (size_t *)&utf8len,
-                                               utf8len + 1, ':', 0);
-                       }
-               } 
-               else { // classic HFS
-
-                       /* convert data to HFS Plus format */
-                       if (record->recordType == kHFSFolderRecord || record->recordType == kHFSFileRecord) {
-                               CopyCatalogNodeData(volume, record, nodeData);
-                               result = hfs_to_utf8(volume, key->hfs.nodeName, MAXHFSVNODELEN + 1,
-                                               &utf8len, nodeData->cnm_namespace);
-                               /* Need to allocate buffer large enough */
-                               if (result == ENAMETOOLONG) {
-                                       nodeData->cnm_nameptr = NewPtr(utf8len + 1);
-                                       nodeData->cnm_flags |= kCatNameIsAllocated;
-                                       result = hfs_to_utf8(volume, key->hfs.nodeName, utf8len + 1,
-                                                       &utf8len, nodeData->cnm_nameptr);
-                               } else if (result) {
-                                       /*
-                                        * When an HFS name cannot be encoded with the current
-                                        * volume encoding we use MacRoman as a fallback.
-                                        */
-                                       result = mac_roman_to_utf8(key->hfs.nodeName, MAXHFSVNODELEN + 1,
-                                                                  &utf8len, nodeData->cnm_namespace);
-                               }
-                       } else
-                               result = cmNotFound;
-               }
-
-               nodeData->cnm_length = utf8len;
-               if (result && (nodeData->cnm_flags & kCatNameIsAllocated))
-               {
-                       DisposePtr(nodeData->cnm_nameptr);
-                       nodeData->cnm_flags &= ~kCatNameIsAllocated;
-                       nodeData->cnm_nameptr = 0;              /* Just to be clean */
-               }
-       }
-
-       
-  #if DEBUG_BUILD
-       if ( nodeData->cnd_nodeID > volume->vcbNxtCNID || nodeData->cnd_nodeID == 0)
-               DebugStr("\pGetCatalogNode bad file ID found!");
-  #endif
-       return result;
-
-} // end GetCatalogNode
 
 
 UInt32
 
 
 UInt32
@@ -797,12 +64,18 @@ GetDirEntrySize(BTreeIterator *bip, ExtendedVCB * vol)
                                    cnp->ustr.length * sizeof(UniChar), ':', 0);
                if (utf8chars > kdirentMaxNameBytes)
                        utf8chars = kdirentMaxNameBytes;
                                    cnp->ustr.length * sizeof(UniChar), ':', 0);
                if (utf8chars > kdirentMaxNameBytes)
                        utf8chars = kdirentMaxNameBytes;
-               utf8chars++;  /* account for NULL termination */
        } else { /* hfs */
                cnp = (CatalogName*) ckp->hfs.nodeName;
                result = hfs_to_utf8(vol, cnp->pstr, kdirentMaxNameBytes + 1,
                                &utf8chars, name);
        } else { /* hfs */
                cnp = (CatalogName*) ckp->hfs.nodeName;
                result = hfs_to_utf8(vol, cnp->pstr, kdirentMaxNameBytes + 1,
                                &utf8chars, name);
-               /*XXX ignoring error */
+               if (result) {
+                       /*
+                        * When an HFS name cannot be encoded with the current
+                        * volume encoding we use MacRoman as a fallback.
+                        */
+                       result = mac_roman_to_utf8(cnp->pstr, MAXHFSVNODELEN + 1,
+                                                                  &utf8chars, name);
+               }
        }
 
        return DIRENTRY_SIZE(utf8chars);
        }
 
        return DIRENTRY_SIZE(utf8chars);
@@ -839,26 +112,12 @@ PositionIterator(CatalogIterator *cip, UInt32 offset, BTreeIterator *bip, UInt16
                *op = kBTreeNextRecord;
 
        } else { /* start from beginning */
                *op = kBTreeNextRecord;
 
        } else { /* start from beginning */
-               UInt32  heuristicHint;
-               UInt32  *cachedHint;
-
                *op = kBTreeNextRecord;
 
                *op = kBTreeNextRecord;
 
-               /*
-                * We pass a 2nd hint/guess into BTSearchRecord.  The heuristicHint
-                * is a mapping of dirID and nodeNumber, in hopes that the current
-                * search will be in the same node as the last search with the same
-                * parentID.
-                */
-               result = GetMRUCacheBlock( cip->folderID, vol->hintCachePtr, (Ptr *)&cachedHint );
-               heuristicHint = (result == noErr) ? *cachedHint : kInvalidMRUCacheKey;
-
                /* Position iterator at the folder's thread record */
                /* Position iterator at the folder's thread record */
-               result = BTSearchRecord(fcb, bip, heuristicHint, NULL, NULL, bip);
+               result = BTSearchRecord(fcb, bip, NULL, NULL, bip);
                if (result)
                        goto exit;
                if (result)
                        goto exit;
-
-               InsertMRUCacheBlock( vol->hintCachePtr, cip->folderID, (Ptr) &bip->hint.nodeNum );
                
                /* find offset (note: n^2 / 2) */
                if (offset > CAT_START_OFFSET) { 
                
                /* find offset (note: n^2 / 2) */
                if (offset > CAT_START_OFFSET) { 
@@ -878,7 +137,7 @@ PositionIterator(CatalogIterator *cip, UInt32 offset, BTreeIterator *bip, UInt16
                        pid = *idp;
 
                        curOffset = CAT_START_OFFSET;
                        pid = *idp;
 
                        curOffset = CAT_START_OFFSET;
-                       nextOffset = GetDirEntrySize(bip, vol);
+                       nextOffset = CAT_START_OFFSET + GetDirEntrySize(bip, vol);
 
                        while (nextOffset < offset) {
                                result = BTIterateRecord( fcb, kBTreeNextRecord, bip, NULL, NULL );             
 
                        while (nextOffset < offset) {
                                result = BTIterateRecord( fcb, kBTreeNextRecord, bip, NULL, NULL );             
@@ -915,866 +174,6 @@ exit:
 } /* end PositionIterator */
 
 
 } /* end PositionIterator */
 
 
-//_________________________________________________________________________________
-//     Routine:        GetCatalogOffspring
-//
-//     Function:       Gets an offspring record from a specified folder. The folder
-//                             is identified by it's folderID.  The desired offspring CNode is
-//                             indicated by the value of the offspring index (1 = 1st offspring
-//                             CNode, 2 = 2nd offspring CNode, etc.).
-//
-//_________________________________________________________________________________
-
-OSErr
-GetCatalogOffspring(ExtendedVCB *volume, HFSCatalogNodeID folderID, UInt16 index,
-                   CatalogNodeData *nodeData,
-                   HFSCatalogNodeID *nodeID, SInt16 *nodeType)
-{
-       CatalogIterator *       catalogIterator;
-       OSErr                           result;
-
-
-       if ( folderID == 0 )
-               return cmNotFound;
-
-       /*
-        * return cmNotFound for index 32767, to prevent overflowing
-        * the index into negative numbers.
-        */
-       if ( index == 32767 )
-               return cmNotFound;
-
-       // get best catalog iterator...
-       catalogIterator = oGetCatalogIterator(volume, folderID, index);
-       
-       result = IterateCatalogNode(volume, catalogIterator, index,
-                                   nodeData, nodeID, nodeType);
-
-       (void) ReleaseCatalogIterator(catalogIterator);
-
-       return result;
-
-} // end GetCatalogOffspring
-
-
-//_________________________________________________________________________________
-//     Routine:        IterateCatalogNode
-//
-//     Function:       Gets an offspring record from a specified folder. The folder
-//                             is identified by it's folderID.  The desired offspring CNode is
-//                             indicated by the value of the offspring index (1 = 1st offspring
-//                             CNode, 2 = 2nd offspring CNode, etc.).
-//
-//_________________________________________________________________________________
-
-static OSErr
-IterateCatalogNode( ExtendedVCB *volume, CatalogIterator *catalogIterator, UInt16 index,
-                   CatalogNodeData *nodeData, HFSCatalogNodeID *nodeID,
-                   SInt16 *nodeType )
-{
-       HFSCatalogNodeID        offspringParentID;
-       CatalogKey *            offspringKey;
-       CatalogName *           offspringName;
-       BTreeIterator           btreeIterator;
-       FSBufferDescriptor      btRecord;
-       CatalogRecord * record;
-       UInt8 databuf[32];      /* space for partial record */
-       FCB *                           fcb;
-       SInt16                          selectionIndex;
-       UInt16                          tempSize;
-       UInt16                          operation;
-       OSErr                           result;
-       Boolean                         isHFSPlus;
-       ByteCount                       utf8len;
-
-
-       isHFSPlus = (volume->vcbSigWord == kHFSPlusSigWord);
-       fcb = GetFileControlBlock(volume->catalogRefNum);
-
-       // make a btree iterator from catalog iterator
-       UpdateBtreeIterator(catalogIterator, &btreeIterator);
-
-       /* if client doesn't want data (ie readdir), just get type and id */
-       if (nodeData == NULL) {
-               /* data buf has space to cover all type/id offsets */
-               btRecord.bufferAddress = databuf;
-               btRecord.itemSize = sizeof(databuf);
-       } else if (isHFSPlus) {
-               btRecord.bufferAddress = nodeData;
-               btRecord.itemSize = sizeof(CatalogNodeData);
-       } else {
-               btRecord.bufferAddress = &nodeData->cnd_extra;
-               btRecord.itemSize = sizeof(HFSCatalogFile);
-       }
-       btRecord.itemCount = 1;
-
-       //--- if neccessary position the iterator at the thread record for the specified folder
-
-       if ( catalogIterator->currentIndex == 0 )       // is this a new iterator?
-       {
-               UInt32  heuristicHint;
-               UInt32  *cachedHint;
-
-               //      We pass a 2nd hint/guess into BTSearchRecord.  The heuristicHint is a mapping of
-               //      dirID and nodeNumber, in hopes that the current search will be in the same node
-               //      as the last search with the same parentID.
-               result = GetMRUCacheBlock( catalogIterator->folderID, volume->hintCachePtr, (Ptr *)&cachedHint );
-               heuristicHint = (result == noErr) ? *cachedHint : kInvalidMRUCacheKey;
-
-               result = BTSearchRecord( fcb, &btreeIterator, heuristicHint, &btRecord, &tempSize, &btreeIterator );
-               ExitOnError(result);
-               
-               UpdateCatalogIterator(&btreeIterator, catalogIterator); // update btree hint and key
-
-               InsertMRUCacheBlock( volume->hintCachePtr, catalogIterator->folderID, (Ptr) &btreeIterator.hint.nodeNum );
-       }
-
-       //--- get offspring record (relative to catalogIterator's position)
-
-       selectionIndex = index - catalogIterator->currentIndex;
-
-       // now we have to map index into next/prev operations...
-       if (selectionIndex == 1)
-       {
-               operation = kBTreeNextRecord;
-       }
-       else if (selectionIndex == -1)
-       {
-               operation = kBTreePrevRecord;
-       }
-       else if (selectionIndex == 0)
-       {
-               operation = kBTreeCurrentRecord;
-       }
-       else if (selectionIndex > 1)
-       {
-               UInt32  i;
-               
-               for (i = 1; i < selectionIndex; ++i)
-               {
-                       result = BTIterateRecord( fcb, kBTreeNextRecord, &btreeIterator, &btRecord, &tempSize );
-                       ExitOnError(result);
-               }
-               operation = kBTreeNextRecord;
-       }
-       else // (selectionIndex < -1)
-       {
-               SInt32  i;
-
-               for (i = -1; i > selectionIndex; --i)
-               {
-                       result = BTIterateRecord( fcb, kBTreePrevRecord, &btreeIterator, &btRecord, &tempSize );
-                       ExitOnError(result);
-               }
-               operation = kBTreePrevRecord;
-       }
-
-       result = BTIterateRecord( fcb, operation, &btreeIterator, &btRecord, &tempSize );
-       ExitOnError(result);
-
-       offspringKey = (CatalogKey*) &btreeIterator.key;
-
-       if (isHFSPlus)
-       {
-               offspringParentID = offspringKey->hfsPlus.parentID;
-               offspringName = (CatalogName*) &offspringKey->hfsPlus.nodeName;
-       }
-       else
-       {
-               offspringParentID = offspringKey->hfs.parentID;
-               offspringName = (CatalogName*) offspringKey->hfs.nodeName;
-       }
-
-       if (offspringParentID != catalogIterator->folderID)             // different parent?
-       {
-               AgeCatalogIterator(catalogIterator);    // we reached the end, so don't hog the cache!
-
-               result = cmNotFound;                            // must be done with this folder
-               goto ErrorExit;
-       }
-
-       UpdateCatalogIterator(&btreeIterator, catalogIterator);         // update btree hint and key
-       catalogIterator->currentIndex = index;                                          // update the offspring index marker
-
-       record = (CatalogRecord *) btRecord.bufferAddress;
-
-       if (nodeData == NULL) { /* Just copy the id and type...not name */
-               if (isHFSPlus)
-               {
-                       *nodeType = record->recordType;
-                       *nodeID = record->hfsPlusFolder.folderID;
-               }
-               else /* hfs name */
-               {
-
-                       if (record->recordType == kHFSFileRecord) {
-                               *nodeType = kCatalogFileNode;
-                               *nodeID = record->hfsFile.fileID;
-                       } else if (record->recordType == kHFSFolderRecord) {
-                               *nodeType = kCatalogFolderNode;
-                               *nodeID = record->hfsFolder.folderID;
-                       } else 
-                               result = cmNotFound;
-               }
-       } else {
-               nodeData->cnm_parID = isHFSPlus ? offspringKey->hfsPlus.parentID : offspringKey->hfs.parentID;
-               nodeData->cnm_nameptr = nodeData->cnm_namespace;
-               if (isHFSPlus)
-               {
-                       result = utf8_encodestr(offspringName->ustr.unicode,
-                                       offspringName->ustr.length * sizeof(UniChar),
-                                       nodeData->cnm_namespace, (size_t *)&utf8len,
-                                       MAXHFSVNODELEN + 1, ':', 0);
-
-                       /* Need to allocate buffer large enough */
-                       if (result == ENAMETOOLONG) {
-                               utf8len = utf8_encodelen(offspringName->ustr.unicode,
-                                               offspringName->ustr.length * sizeof(UniChar),
-                                               ':', 0);
-                               nodeData->cnm_nameptr = NewPtr(utf8len + 1);
-                               nodeData->cnm_flags |= kCatNameIsAllocated;
-                               result = utf8_encodestr(offspringName->ustr.unicode,
-                                               offspringName->ustr.length * sizeof(UniChar),
-                                               nodeData->cnm_nameptr, (size_t *)&utf8len,
-                                               utf8len + 1, ':', 0);
-                       }
-               }
-               else /* hfs name */
-               {
-                       if (record->recordType == kHFSFolderRecord || record->recordType == kHFSFileRecord) {
-
-                               CopyCatalogNodeData(volume, record, nodeData);
-                               result = hfs_to_utf8(volume, offspringName->pstr, MAXHFSVNODELEN + 1, &utf8len, nodeData->cnm_namespace);
-                               if (result == ENAMETOOLONG) {                   /* Need to allocate buffer large enough */
-                                       nodeData->cnm_nameptr = NewPtr(utf8len+1);
-                                       nodeData->cnm_flags |= kCatNameIsAllocated;
-                                       result = hfs_to_utf8(volume, offspringName->pstr, utf8len + 1, &utf8len, nodeData->cnm_nameptr);
-                               }
-
-                       } else {
-                               result = cmNotFound;
-                       }
-               }
-       }
-       
-       return result;
-
-ErrorExit:
-
-       if ( result == btNotFound )
-               result = cmNotFound;
-
-       return result;
-
-} // end IterateCatalogNode
-
-
-//_________________________________________________________________________________
-//     Routine:        MoveRenameCatalogNode
-//
-//     Function:       Moves and/or rename an existing folder or file CNode.
-//                             Note that when moving a folder, all decendants (its offspring,
-//                             their offspring, etc.) are also moved.
-//
-// Assumes srcHint contains a text encoding that was set by a GetCatalogNode call
-//_________________________________________________________________________________
-
-OSErr
-MoveRenameCatalogNode(ExtendedVCB *volume, HFSCatalogNodeID srcParentID, ConstUTF8Param srcName,
-                                         UInt32 srcHint, HFSCatalogNodeID dstParentID, ConstUTF8Param dstName, UInt32 *newHint)
-{
-       CatalogKey                      srcKey;                 // 518 bytes
-       CatalogRecord           srcRecord;              // 520 bytes
-       CatalogKey                      dstKey;                 // 518 bytes
-       CatalogKey                      dstFolderKey;   // 518 bytes
-       HFSCatalogNodeID        dstFolderParentID = 0;
-       UInt32                          dstFolderHint;
-       CatalogName                *dstFolderNamePtr = NULL;
-       CatalogRecord           tmpRecord;              // 520 bytes
-       HFSCatalogNodeID        threadID;
-       UInt32                          textEncoding;
-       OSErr                           result;
-       Boolean                         isNewName;
-       Boolean                         isHFSPlus = (volume->vcbSigWord == kHFSPlusSigWord);
-       Boolean                         isOrigDeleted = false;
-       short srcNameLen;
-       short dstNameLen;
-
-
-       result = BuildCatalogKeyUTF8(volume, srcParentID, srcName, kUndefinedStrLen, &srcKey, &textEncoding);
-       ReturnIfError(result);
-
-       /* XXX can strlen and bcmp handle NULL pointers? */
-
-       srcNameLen = strlen(srcName);
-       dstNameLen = strlen(dstName);
-
-       //--- check if names match
-
-       if ((srcNameLen == dstNameLen) && (bcmp(srcName, dstName, srcNameLen) == 0))
-       {
-               isNewName = false;
-               dstKey = srcKey;
-        if ( isHFSPlus ) {
-            dstKey.hfsPlus.parentID = dstParentID;                     // set parent ID
-        }
-        else {
-            dstKey.hfs.parentID                = dstParentID;                  // set parent ID
-               }
-       }
-       else /* names are different */
-       {
-               isNewName = true;
-        result = BuildCatalogKeyUTF8(volume, dstParentID, dstName, kUndefinedStrLen, &dstKey, &textEncoding);
-               ReturnIfError(result);
-       }
-
-       //--- make sure source record exists
-       
-       result = LocateCatalogNodeByKey(volume, srcHint, &srcKey, &srcRecord, &srcHint);
-
-       // if we did not find it by name, then look for an embedded file ID in a mangled name
-       if ( (result == cmNotFound) && isHFSPlus )
-        result = LocateCatalogNodeByMangledName(volume, srcParentID, srcName, kUndefinedStrLen, &srcKey, &srcRecord, &srcHint);
-       ReturnIfError(result);
-
-       srcParentID = (isHFSPlus ? srcKey.hfsPlus.parentID : srcKey.hfs.parentID);
-
-       // if we're moving then do some additional preflighting...
-
-       if (srcParentID != dstParentID)
-       {
-               //--- make sure destination folder exists
-
-               result = LocateCatalogNode(volume, dstParentID, NULL, kNoHint, &dstFolderKey, &tmpRecord, &dstFolderHint);
-               ReturnIfError(result);
-                       
-               if (tmpRecord.recordType == kHFSPlusFolderRecord)
-               {
-                       dstParentID = tmpRecord.hfsPlusFolder.folderID;
-                       dstFolderParentID = dstFolderKey.hfsPlus.parentID;
-                       dstFolderNamePtr = (CatalogName*) &dstFolderKey.hfsPlus.nodeName;
-               }
-               else if (tmpRecord.recordType == kHFSFolderRecord)
-               {
-                       dstParentID = tmpRecord.hfsFolder.folderID;
-                       dstFolderParentID = dstFolderKey.hfs.parentID;
-                       dstFolderNamePtr = (CatalogName*) &dstFolderKey.hfs.nodeName;
-               }
-               else
-               {
-                       return badMovErr;
-               }
-       
-               //--- if source is a folder, make sure its a proper move
-       
-               if (srcRecord.recordType == kHFSPlusFolderRecord || srcRecord.recordType == kHFSFolderRecord)
-               {
-                       HFSCatalogNodeID srcFolderID;
-                       HFSCatalogNodeID ancestorParentID;
-                       CatalogKey              tempKey;        // 518 bytes
-                       UInt32                  tempHint;
-       
-                       if (isHFSPlus)
-                       {
-                               srcFolderID = srcRecord.hfsPlusFolder.folderID;
-                               ancestorParentID = dstFolderKey.hfsPlus.parentID;
-                       }
-                       else
-                       {
-                               srcFolderID = srcRecord.hfsFolder.folderID;
-                               ancestorParentID = dstFolderKey.hfs.parentID;
-                       }
-       
-                       if ( srcFolderID == fsRtDirID   ||              // source == root?
-                                srcFolderID == dstParentID     ||              // source == destination?
-                                srcFolderID == ancestorParentID )      // source == destination's parent?
-                       {
-                               return badMovErr;
-                       }
-       
-                       while (ancestorParentID > fsRtDirID)    // loop until we reach the root folder
-                       {
-                               // locate next folder up the tree...    
-                               result = LocateCatalogNode(volume, ancestorParentID, NULL, kNoHint, &tempKey, &tmpRecord, &tempHint);
-                               ReturnIfError(result);
-                               
-                               ancestorParentID = isHFSPlus ? tempKey.hfsPlus.parentID : tempKey.hfs.parentID;
-       
-                               if (srcFolderID == ancestorParentID)    // source = destination ancestor?
-                                       return badMovErr;
-                       }
-               }
-
-               TrashCatalogIterator(volume, dstParentID);              // invalidate any iterators for destination parentID
-       }
-       else /* (srcParentID == dstParentID) */
-       {
-               if ( !isNewName )
-               {
-                       *newHint = srcHint;             // they match, so we're all done!
-                       return noErr;
-               }
-       }
-
-       TrashCatalogIterator(volume, srcParentID);                      // invalidate any iterators for source's parentID
-       InvalidateCatalogNodeCache(volume, srcParentID);        // invalidate node cache since parent changed
-
-       if (isNewName && isHFSPlus)
-       {
-               // update textEncoding hint (works for folders and files)
-               srcRecord.hfsPlusFolder.textEncoding = textEncoding;
-
-               UpdateVolumeEncodings(volume, textEncoding);
-       }
-
-       //--- insert source CNode record in BTree with new key (a new parent id and/or new name)
-
-       result = InsertBTreeRecord(volume->catalogRefNum, &dstKey, &srcRecord, GetCatalogRecordSize(&srcRecord), newHint);
-
-       if (result == btExists)
-       {
-               UInt16 dataSize;
-
-               /* XXX what about the case: move id1,foo to id2,FOO ?? */
-               if (srcParentID != dstParentID || isNewName == false)
-                       return cmExists;
-
-               //--- new CNode name already exists in the same folder, locate the existing one
-               result = SearchBTreeRecord(volume->catalogRefNum, &dstKey, srcHint,
-                                                                       &dstFolderKey, &tmpRecord, &dataSize, newHint);
-
-               if (result == btNotFound)
-                       result = cmNotFound;    
-               ReturnIfError(result);
-
-               //--- check if its the same CNode (same name but different upper/lower case)
-                       
-               if (srcRecord.recordType != tmpRecord.recordType)
-                       return cmExists;
-
-               switch (srcRecord.recordType)
-               {
-                       case kHFSPlusFileRecord:        /* HFS Plus records share same cnid location */
-                       case kHFSPlusFolderRecord:
-                               if (srcRecord.hfsPlusFolder.folderID != tmpRecord.hfsPlusFolder.folderID)
-                                       return cmExists;
-                               break;
-
-                       case kHFSFolderRecord:
-                               if (srcRecord.hfsFolder.folderID != tmpRecord.hfsFolder.folderID)
-                                       return cmExists;
-                               break;
-
-                       case kHFSFileRecord:
-                               if (srcRecord.hfsFile.fileID != tmpRecord.hfsFile.fileID)
-                                       return cmExists;
-                               break;
-                       
-                       default:
-                               return cmExists;
-               }
-
-               //--- same name but different case, so delete old and insert with new name...
-       
-               result = DeleteBTreeRecord(volume->catalogRefNum, &srcKey);
-               ReturnIfError(result);
-        isOrigDeleted = true;  // So we dont delete it again down below
-
-               result = InsertBTreeRecord(volume->catalogRefNum, &dstKey, &srcRecord, dataSize, newHint);
-       }
-       ReturnIfError(result);
-
-       //
-       // from this point on we need to cleanup (ie delete the new record) if we encounter errors!     
-       //
-
-       //--- update thread record for node (if it exists)
-       
-       switch (srcRecord.recordType)
-       {
-               case kHFSPlusFileRecord:
-               case kHFSPlusFolderRecord:
-                       threadID = srcRecord.hfsPlusFolder.folderID;
-                       break;
-
-               case kHFSFolderRecord:
-                       threadID = srcRecord.hfsFolder.folderID;
-                       break;
-
-               case kHFSFileRecord:
-                       if (srcRecord.hfsFile.flags & kHFSThreadExistsMask)
-                       {
-                               threadID = srcRecord.hfsFile.fileID;
-                               break;
-                       }
-                       /* fall through if no thread... */
-
-               default:
-                       threadID = 0;
-       }
-
-       if (threadID)
-       {
-               UInt32                  threadHint;
-               CatalogKey              threadKey;              // 518 bytes
-               CatalogRecord   threadRecord;   // 520 bytes
-               UInt16                  threadSize;
-
-               result = LocateCatalogRecord(volume, threadID, NULL, kNoHint, &threadKey, &threadRecord, &threadHint);
-               if (result != noErr) goto Exit_Delete;
-               
-               if (isHFSPlus)
-               {
-                       if (srcParentID != dstParentID)
-                               threadRecord.hfsPlusThread.parentID = dstParentID;
-                       if (isNewName)
-                               CopyCatalogName((CatalogName *)&dstKey.hfsPlus.nodeName, (CatalogName *) &threadRecord.hfsPlusThread.nodeName, isHFSPlus);
-
-                       threadSize = sizeof(threadRecord.hfsPlusThread);
-                       // HFS Plus has varaible sized threads so adjust to actual length
-                       threadSize -= ( sizeof(threadRecord.hfsPlusThread.nodeName.unicode) - (threadRecord.hfsPlusThread.nodeName.length * sizeof(UniChar)) );
-               }
-               else
-               {
-                       if (srcParentID != dstParentID)
-                               threadRecord.hfsThread.parentID = dstParentID;
-                       if (isNewName)
-                               CopyCatalogName((CatalogName *)&dstKey.hfs.nodeName,(CatalogName *) threadRecord.hfsThread.nodeName, isHFSPlus);
-
-                       threadSize = sizeof(threadRecord.hfsThread);
-               }
-
-               result = DeleteBTreeRecord(volume->catalogRefNum, &threadKey);
-               if (result != noErr) goto Exit_Delete;
-
-               result = InsertBTreeRecord(volume->catalogRefNum, &threadKey, &threadRecord, threadSize, &threadHint);
-               if (result != noErr) goto Exit_Delete;  //XXX exiting with a missing thread!
-       }
-
-       //--- we successfully added the new node so delete the old source CNode record
-
-    if (! isOrigDeleted) {
-        result = DeleteBTreeRecord(volume->catalogRefNum, &srcKey);
-        if (result)
-            {
-            // uh oh, we could not delete the original
-            // so we better get rid of the new node...
-
-            (void) DeleteBTreeRecord(volume->catalogRefNum, &dstKey);
-
-            //XXX also need to fix up the thread...
-
-            return result;
-            }
-    }
-
-       if (srcParentID != dstParentID)
-       {
-               result = UpdateFolderCount(volume, srcParentID, NULL, srcRecord.recordType, kNoHint, -1);
-               result = UpdateFolderCount(volume, dstFolderParentID, dstFolderNamePtr, srcRecord.recordType, dstFolderHint, +1);
-       }
-
-       //--- make sure changes get flushed out
-       VCB_LOCK(volume);
-        volume->vcbFlags |= 0xFF00;            // Mark the VCB dirty
-        volume->vcbLsMod = GetTimeUTC();       // update last modified date
-       VCB_UNLOCK(volume);
-
-       (void) FlushCatalog(volume);
-       
-       return result;
-
-
-Exit_Delete:
-       (void) DeleteBTreeRecord(volume->catalogRefNum, &dstKey);
-
-       return result;
-
-} // end MoveRenameCatalogNode
-
-
-//_________________________________________________________________________________
-//     Routine:        UpdateCatalogNode
-//
-//     Function:       Marks the Catalog BTree node identified by the given catalog hint
-//                             as 'dirty'.
-//
-//_________________________________________________________________________________
-
-
-OSErr
-UpdateCatalogNode(ExtendedVCB *volume, HFSCatalogNodeID parentID, ConstUTF8Param name,
-                                 UInt32 catalogHint, const CatalogNodeData *nodeData)
-{
-       CatalogKey              *key;
-       CatalogRecord   *record;
-       UInt32                  hint;
-       UInt16                  recordSize;
-       OSErr                   result;         
-       CatalogKey              catalogKey;             // 518 bytes
-       CatalogRecord   catalogRecord;  // 520 bytes
-       Boolean                 isHFSPlus = volume->vcbSigWord == kHFSPlusSigWord;
-
-       /* XXX no reason to have ptrs to local variables... */
-       key        = &catalogKey;
-       record = &catalogRecord;
-       
-       result = BuildCatalogKeyUTF8(volume, parentID, name, kUndefinedStrLen, key, NULL);
-       ReturnIfError(result);
-
-       //--- locate subject catalog node
-
-       result = LocateCatalogNodeByKey(volume, catalogHint, key, record, &hint);
-
-       // if we did not find it by name, then look for an embedded file ID in a mangled name
-       if ( (result == cmNotFound) && isHFSPlus )
-        result = LocateCatalogNodeByMangledName(volume, parentID, name, kUndefinedStrLen, key, record, &hint);
-
-       if (result == btNotFound)
-               result = cmNotFound;
-
-       if (catalogHint != hint)
-               PRINTIT(("UpdateCatalogNode: catalogHint does not match (in: %ld, out: %ld)\n", catalogHint, hint));
-       ReturnIfError(result);
-
-       // update user modifiable fields in the catalog node record...
-
-       switch (record->recordType)
-       {
-               case kHFSFolderRecord:
-               {
-                 #if DEBUG_BUILD
-                       if (nodeData->cnd_type != kCatalogFolderNode)
-                               DebugStr("\p UpdateCatalogNode: folder/file mismatch!");
-                 #endif
-
-                       record->hfsFolder.createDate = UTCToLocal(nodeData->cnd_createDate);
-                       record->hfsFolder.modifyDate = UTCToLocal(nodeData->cnd_contentModDate);
-                       record->hfsFolder.backupDate = UTCToLocal(nodeData->cnd_backupDate);
-
-                       *(DInfo*) &record->hfsFolder.userInfo = *(DInfo*) &nodeData->cnd_finderInfo;
-                       *(DXInfo*) &record->hfsFolder.finderInfo = *(DXInfo*) ((UInt32)&nodeData->cnd_finderInfo + 16);
-
-                       recordSize = sizeof(HFSCatalogFolder);
-                       break;
-               }
-
-               case kHFSFileRecord:
-               {
-                       UInt32  i;
-                       
-                 #if DEBUG_BUILD
-                       if (nodeData->cnd_type != kCatalogFileNode)
-                               DebugStr("UpdateCatalogNode: folder/file mismatch!");
-                       if ((nodeData->cnd_datafork.totalBlocks > (0x7FFFFFFF/volume->blockSize)) ||
-                           (nodeData->cnd_rsrcfork.totalBlocks > (0x7FFFFFFF/volume->blockSize)))
-                               DebugStr("HFS file size is larger than 2Gig");
-                 #endif
-
-                       record->hfsFile.flags = (UInt8) nodeData->cnd_flags;
-                       record->hfsFile.createDate = UTCToLocal(nodeData->cnd_createDate);
-                       record->hfsFile.modifyDate = UTCToLocal(nodeData->cnd_contentModDate);
-                       record->hfsFile.backupDate = UTCToLocal(nodeData->cnd_backupDate);
-
-                       record->hfsFile.dataLogicalSize  = nodeData->cnd_datafork.logicalSize;
-                       record->hfsFile.dataPhysicalSize = nodeData->cnd_datafork.totalBlocks * volume->blockSize;
-                       record->hfsFile.rsrcLogicalSize  = nodeData->cnd_rsrcfork.logicalSize;
-                       record->hfsFile.rsrcPhysicalSize = nodeData->cnd_rsrcfork.totalBlocks * volume->blockSize;
-
-                       *(FInfo*) &record->hfsFile.userInfo = *(FInfo*) &nodeData->cnd_finderInfo;
-                       *(FXInfo*) &record->hfsFile.finderInfo = *(FXInfo*) ((UInt32)&nodeData->cnd_finderInfo + 16);
-
-                       // copy extent info
-                       for (i = 0; i < kHFSExtentDensity; ++i)
-                       {
-                               record->hfsFile.dataExtents[i].startBlock =
-                                   (UInt16) nodeData->cnd_datafork.extents[i].startBlock;
-                               record->hfsFile.dataExtents[i].blockCount =
-                                   (UInt16) nodeData->cnd_datafork.extents[i].blockCount;
-                               record->hfsFile.rsrcExtents[i].startBlock =
-                                   (UInt16) nodeData->cnd_rsrcfork.extents[i].startBlock;
-                               record->hfsFile.rsrcExtents[i].blockCount =
-                                   (UInt16) nodeData->cnd_rsrcfork.extents[i].blockCount;
-                       }
-
-                       recordSize = sizeof(HFSCatalogFile);
-                       break;
-               }
-
-               case kHFSPlusFolderRecord:
-               {
-                       record->hfsPlusFolder.createDate = nodeData->cnd_createDate;
-                       record->hfsPlusFolder.contentModDate = nodeData->cnd_contentModDate;
-                       record->hfsPlusFolder.backupDate = nodeData->cnd_backupDate;
-                       record->hfsPlusFolder.accessDate = nodeData->cnd_accessDate;
-                       record->hfsPlusFolder.attributeModDate = nodeData->cnd_attributeModDate;
-                       record->hfsPlusFolder.bsdInfo.ownerID = nodeData->cnd_ownerID;
-                       record->hfsPlusFolder.bsdInfo.groupID = nodeData->cnd_groupID;
-                       record->hfsPlusFolder.bsdInfo.ownerFlags = nodeData->cnd_ownerFlags;
-                       record->hfsPlusFolder.bsdInfo.adminFlags = nodeData->cnd_adminFlags;
-                       record->hfsPlusFolder.bsdInfo.fileMode = nodeData->cnd_mode;
-                       record->hfsPlusFolder.textEncoding = nodeData->cnd_textEncoding;
-
-                       BlockMoveData(&nodeData->cnd_finderInfo, &record->hfsPlusFolder.userInfo, 32);
-
-                       recordSize = sizeof(HFSPlusCatalogFolder);
-                       break;
-               }
-
-               case kHFSPlusFileRecord:
-               {
-                       record->hfsPlusFile.flags = nodeData->cnd_flags;
-                       record->hfsPlusFile.createDate = nodeData->cnd_createDate;
-                       record->hfsPlusFile.contentModDate = nodeData->cnd_contentModDate;
-                       record->hfsPlusFile.backupDate = nodeData->cnd_backupDate;
-                       record->hfsPlusFile.accessDate = nodeData->cnd_accessDate;
-                       record->hfsPlusFile.attributeModDate = nodeData->cnd_attributeModDate;
-                       record->hfsPlusFile.bsdInfo.ownerID = nodeData->cnd_ownerID;
-                       record->hfsPlusFile.bsdInfo.groupID = nodeData->cnd_groupID;
-                       record->hfsPlusFile.bsdInfo.ownerFlags = nodeData->cnd_ownerFlags;
-                       record->hfsPlusFile.bsdInfo.adminFlags = nodeData->cnd_adminFlags;
-                       record->hfsPlusFile.bsdInfo.fileMode = nodeData->cnd_mode;
-                       /* get special value (iNodeNum, linkCount or rawDevice) */
-                       record->hfsPlusFile.bsdInfo.special.rawDevice = nodeData->cnd_rawDevice;
-                       record->hfsPlusFile.textEncoding = nodeData->cnd_textEncoding;
-
-                       record->hfsPlusFile.dataFork.logicalSize = nodeData->cnd_datafork.logicalSize;
-                       record->hfsPlusFile.dataFork.totalBlocks = nodeData->cnd_datafork.totalBlocks;
-                       BlockMoveData(&nodeData->cnd_datafork.extents,
-                           &record->hfsPlusFile.dataFork.extents, sizeof(HFSPlusExtentRecord));
-
-                       record->hfsPlusFile.resourceFork.logicalSize = nodeData->cnd_rsrcfork.logicalSize;
-                       record->hfsPlusFile.resourceFork.totalBlocks = nodeData->cnd_rsrcfork.totalBlocks;
-                       BlockMoveData(&nodeData->cnd_rsrcfork.extents,
-                           &record->hfsPlusFile.resourceFork.extents, sizeof(HFSPlusExtentRecord));
-                       
-                       BlockMoveData(&nodeData->cnd_finderInfo, &record->hfsPlusFile.userInfo, 32);
-
-#if HFS_HARDLINKS && DEBUG_BUILD
-            /* Must swap opaque finder data */
-                       if (SWAP_BE32 (record->hfsPlusFile.userInfo.fdType) == kHardLinkFileType &&
-                           SWAP_BE32 (record->hfsPlusFile.userInfo.fdCreator) == kHardLinkCreator) {
-                           if (record->hfsPlusFile.dataFork.logicalSize != 0)
-                               DebugStr("UpdateCatalogNode: link has data fork!");
-                       }
-#endif
-                       recordSize = sizeof(HFSPlusCatalogFile);
-                       break;
-               }
-
-               default:
-                       return cmNotFound;
-       }
-
-       result = ReplaceBTreeRecord(volume->catalogRefNum, key, catalogHint, record, recordSize, &hint);
-       
-       if ( result == btNotFound )
-       {
-               result = cmNotFound;
-       }
-       else if ( result == noErr )
-       {
-               /* if we're just updating the accessDate then no need to change volume mod date */
-               if (nodeData->cnd_contentModDate > volume->vcbLsMod ||
-                       (isHFSPlus && nodeData->cnd_attributeModDate > volume->vcbLsMod))
-               {
-                       VCB_LOCK(volume);
-                       volume->vcbFlags |= 0xFF00;             // Mark the VCB dirty
-                       volume->vcbLsMod = GetTimeUTC();        // update last modified date
-                       VCB_UNLOCK(volume);
-               }
-
-               result = FlushCatalog(volume);          // flush the catalog
-       }
-
-       return result;
-}
-
-
-//_________________________________________________________________________________
-//     Routine:        CreateFileIDRef
-//
-//     Function:       Creates a file thread record for hfs file node
-//
-//_________________________________________________________________________________
-
-OSErr
-CreateFileIDRef(ExtendedVCB *volume, HFSCatalogNodeID parentID, ConstUTF8Param name, UInt32 hint, HFSCatalogNodeID *threadID)
-{
-       CatalogKey                      nodeKey;        // 518 bytes
-       CatalogRecord           nodeData;       // 520 bytes
-       HFSCatalogKey           threadKey;
-       HFSCatalogThread        threadData;
-       UInt32                          nodeHint;
-       UInt32                          tempHint;
-       OSErr                           result;
-       Boolean                         isHFSPlus = (volume->vcbSigWord == kHFSPlusSigWord);
-       
-       *threadID = 0;
-       
-    result = BuildCatalogKeyUTF8(volume, parentID, name, kUndefinedStrLen, &nodeKey, NULL);
-       ReturnIfError(result);
-
-       //--- locate subject catalog node
-
-       result = LocateCatalogNodeByKey(volume, hint, &nodeKey, &nodeData, &nodeHint);
-
-       // if we did not find it by name, then look for an embedded file ID in a mangled name
-       if ( (result == cmNotFound) && isHFSPlus )
-        result = LocateCatalogNodeByMangledName(volume, parentID, name, kUndefinedStrLen, &nodeKey, &nodeData, &nodeHint);
-       ReturnIfError(result);
-       
-    if (nodeData.recordType == kHFSPlusFileRecord)
-       {
-               *threadID = nodeData.hfsPlusFile.fileID;
-               return noErr;   // already have one
-       }
-       
-       if (nodeData.recordType != kHFSFileRecord)
-       {
-               return notAFileErr;
-       }
-
-
-       if (nodeData.hfsFile.flags & kHFSThreadExistsMask)
-       {
-               *threadID = nodeData.hfsFile.fileID;
-               return noErr;   // already have one
-       }
-
-       result = VolumeWritable( volume );
-       if ( result != noErr ) return result;
-
-       //
-       // need to insert a thread record
-       //              
-    BuildCatalogKey(nodeData.hfsFile.fileID, NULL, false, (CatalogKey *)&threadKey);
-       
-       ClearMemory(&threadData, sizeof(HFSCatalogThread));
-    threadData.recordType = kHFSFileThreadRecord;
-       threadData.parentID = nodeKey.hfs.parentID;     
-       BlockMoveData(&nodeKey.hfs.nodeName, &threadData.nodeName, nodeKey.hfs.nodeName[0] + 1);
-
-       result = InsertBTreeRecord(volume->catalogRefNum, &threadKey, &threadData, sizeof(HFSCatalogThread), &tempHint);
-       if (result == btExists) result = noErr;         //XXX could return cmExists or fidExists
-       ReturnIfError(result);
-
-       //
-       //      Finally, set the flag in the file record to say this file has a thread record.
-       //
-       nodeData.hfsFile.flags |= kHFSThreadExistsMask;
-       result = ReplaceBTreeRecord(volume->catalogRefNum, &nodeKey, nodeHint, &nodeData, sizeof(HFSCatalogFile), &nodeHint );
-
-       if (result == noErr) {
-               (void) FlushCatalog(volume);
-               *threadID = nodeData.hfsFile.fileID;
-       }
-
-       return result;
-}
-
-
 //_________________________________________________________________________________
 //     Routine:        CompareCatalogKeys
 //
 //_________________________________________________________________________________
 //     Routine:        CompareCatalogKeys
 //
@@ -1799,18 +198,8 @@ CompareCatalogKeys(HFSCatalogKey *searchKey, HFSCatalogKey *trialKey)
        else if ( searchParentID < trialParentID )
                result = -1;
        else // parent dirID's are equal, compare names
        else if ( searchParentID < trialParentID )
                result = -1;
        else // parent dirID's are equal, compare names
-       {
-         #if ( ! FORDISKFIRSTAID )
-               LogStartTime(kTraceRelString);
-
                result = FastRelString(searchKey->nodeName, trialKey->nodeName);
 
                result = FastRelString(searchKey->nodeName, trialKey->nodeName);
 
-               LogEndTime(kTraceRelString, noErr);
-         #else
-               result = (SInt32) RelString_Glue(searchKey->nodeName, trialKey->nodeName);
-         #endif
-       }
-
        return result;
 }
 
        return result;
 }