]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/hfs/hfscommon/Catalog/CatalogUtilities.c
xnu-3248.60.10.tar.gz
[apple/xnu.git] / bsd / hfs / hfscommon / Catalog / CatalogUtilities.c
index 15ff358a96cd6fac6ba4308b4cd42df7d4306767..6a76e1df77be9dc58e81ab4c02eff38c0805a7d8 100644 (file)
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2002, 2004-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:           CatalogUtilities.c
-
-       Contains:       Private Catalog Manager support routines.
-
-       Version:        HFS Plus 1.0
-
-       Copyright:      © 1997-2000 by Apple Computer, Inc., all rights reserved.
-
-       File Ownership:
-
-               DRI:                            Don Brady
-
-               Other Contact:          Mark Day
-
-               Technology:                     xxx put technology here xxx
-
-       Writers:
-
-               (DSH)   Deric Horn
-               (msd)   Mark Day
-               (djb)   Don Brady
-
-       Change History (most recent first):
-         <MacOSX>        1/8/99        djb             Fixing LocateCatalogNodeByMangledName...
-         <MacOSX>        1/7/99        djb             In BuildCatalogKeyUTF8 check name length against NAME_MAX.
-         <MacOSX>       12/7/98        djb             Add ExtractTextEncoding routine to get text encodings.
-         <MacOSX>      11/20/98        djb             Add support for UTF-8 names.
-         <MacOSX>       8/31/98        djb             GetTimeLocal now takes an input.
-         <MacOSX>       4/17/98        djb             Add VCB locking.
-         <MacOSX>        4/3/98        djb             Removed last name conversion cache from LocateCatalogNodeWithRetry.
-         <MacOSX>        4/2/98        djb             InvalidateCatalogNodeCache and TrashCatalogNodeCache are not used in MacOS X.
-         <MacOSX>      03/31/98        djb             Sync up with final HFSVolumes.h header file.
-
-         <CS24>         1/29/98        DSH             Add TrashCatalogNodeCache for TrashAllFSCaches API support.
-         <CS23>        12/15/97        djb             Radar #2202860, In LocateCatalogNodeByMangledName remap
-                                                                       cmParentNotFound error code to cmNotFound.
-         <CS22>        12/10/97        DSH             2201501, Pin the leof and peof to multiple of allocation blocks
-                                                                       under 2 Gig.
-         <CS21>         12/9/97        DSH             2201501, Pin returned leof values to 2^31-1 (SInt32), instead of
-                                                                       2^32-1
-         <CS20>        11/26/97        djb             Radar #2005688, 2005461 - need to handle kTextMalformedInputErr.
-         <CS19>        11/25/97        djb             Radar #2002357 (again) fix new bug introduced in <CS18>.
-         <CS18>        11/17/97        djb             PrepareInputName routine now returns an error.
-         <CS17>        10/19/97        msd             Bug 1684586. GetCatInfo and SetCatInfo use only contentModDate.
-         <CS16>        10/17/97        djb             Add ConvertInputNameToUnicode for Catalog Create/Rename.
-         <CS15>        10/14/97        djb             Fix LocateCatalogNode's MakeFSSpec optimization (radar #1683166)
-         <CS14>        10/13/97        djb             Copy text encoding in CopyCatalogNodeData. Fix cut/paste error
-                                                                       in VolumeHasEncodings macro. When accessing encoding bitmap use
-                                                                       the MapEncodingToIndex and MapIndexToEncoding macros.
-         <CS13>         10/1/97        djb             Remove old Catalog Iterator code...
-         <CS12>          9/8/97        msd             Make sure a folder's modifyDate is set whenever its
-                                                                       contentModDate is set.
-         <CS11>          9/4/97        djb             Add MakeFSSpec optimization.
-         <CS10>          9/4/97        msd             In CatalogNodeData, change attributeModDate to modifyDate.
-          <CS9>         8/26/97        djb             Back out <CS4> (UpdateFolderCount must maintain vcbNmFls for HFS
-                                                                       Plus volumes too).
-          <CS8>         8/14/97        djb             Remove hard link support.
-          <CS7>         7/18/97        msd             Include LowMemPriv.h.
-          <CS6>         7/16/97        DSH             FilesInternal.i renamed FileMgrInternal.i to avoid name
-                                                                       collision
-          <CS5>          7/8/97        DSH             Loading PrecompiledHeaders from define passed in on C line
-          <CS4>         6/27/97        msd             UpdateFolderCount should update number of root files/folders for
-                                                                       HFS volumes, not HFS Plus.
-          <CS3>         6/24/97        djb             LocateCatalogNodeWithRetry did not always set result code.
-          <CS2>         6/24/97        djb             Add LocateCatalogNodeByMangledName routine
-          <CS1>         6/24/97        djb             first checked in
-*/
 #include <sys/param.h>
 #include <sys/utfconv.h>
+#include <sys/stat.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <libkern/libkern.h>
 
 #include       "../headers/FileMgrInternal.h"
 #include       "../headers/BTreesInternal.h"
 #include       "../headers/CatalogPrivate.h"
 #include       "../headers/HFSUnicodeWrappers.h"
+#include       "../headers/BTreesPrivate.h"
 #include       <string.h>
 
-static void ExtractTextEncoding (ItemCount length, ConstUniCharArrayPtr string, UInt32 * textEncoding);
-
-//*******************************************************************************
-//     Routine:        LocateCatalogNode
+//
+//     Routine:        LocateCatalogNodeByKey
 //
 // Function:   Locates the catalog record for an existing folder or file
-//                             CNode and returns pointers to the key and data records.
+//                             CNode and returns the key and data records.
 //
-//*******************************************************************************
 
 OSErr
-LocateCatalogNode(const ExtendedVCB *volume, HFSCatalogNodeID folderID, const CatalogName *name,
-                                       UInt32 hint, CatalogKey *keyPtr, CatalogRecord *dataPtr, UInt32 *newHint)
+LocateCatalogNodeByKey(const ExtendedVCB *volume, u_int32_t hint, CatalogKey *keyPtr,
+                                               CatalogRecord *dataPtr, u_int32_t *newHint)
 {
        OSErr                           result;
-       CatalogName             *nodeName = NULL;       /* To ward off uninitialized use warnings from compiler */
+       CatalogName             *nodeName = NULL;
        HFSCatalogNodeID        threadParentID;
+       u_int16_t tempSize;
+       FSBufferDescriptor       btRecord;
+       struct BTreeIterator *searchIterator;
+       FCB                     *fcb;
+
+       MALLOC (searchIterator, struct BTreeIterator*, sizeof(struct BTreeIterator), M_TEMP, M_WAITOK);
+       if (searchIterator == NULL) {
+               return memFullErr;  // translates to ENOMEM
+       }
 
+       bzero(searchIterator, sizeof(*searchIterator));
 
-       result = LocateCatalogRecord(volume, folderID, name, hint, keyPtr, dataPtr, newHint);
-       ReturnIfError(result);
-       
-       // if we got a thread record, then go look up real record
-       switch ( dataPtr->recordType )
-       {
-               case kHFSFileThreadRecord:
-               case kHFSFolderThreadRecord:
-                       threadParentID = dataPtr->hfsThread.parentID;
-                       nodeName = (CatalogName *) &dataPtr->hfsThread.nodeName;
-                       break;
+       fcb = GetFileControlBlock(volume->catalogRefNum);
 
-               case kHFSPlusFileThreadRecord:
-               case kHFSPlusFolderThreadRecord:
-                       threadParentID = dataPtr->hfsPlusThread.parentID;
-                       nodeName = (CatalogName *) &dataPtr->hfsPlusThread.nodeName;    
-                       break;
+       btRecord.bufferAddress = dataPtr;
+       btRecord.itemCount = 1;
+       btRecord.itemSize = sizeof(CatalogRecord);
 
-               default:
-                       threadParentID = 0;
-                       break;
-       }
-       
-       if ( threadParentID )           // found a thread
-               result = LocateCatalogRecord(volume, threadParentID, nodeName, kNoHint, keyPtr, dataPtr, newHint);
+       searchIterator->hint.nodeNum = hint;
+
+       bcopy(keyPtr, &searchIterator->key, sizeof(CatalogKey));
        
-       return result;
-}
+       result = BTSearchRecord( fcb, searchIterator, &btRecord, &tempSize, searchIterator );
 
-//
-//     Routine:        LocateCatalogNodeByKey
-//
-// Function:   Locates the catalog record for an existing folder or file
-//                             CNode and returns the key and data records.
-//
+       if (result == noErr)
+       {
+               *newHint = searchIterator->hint.nodeNum;
 
-OSErr
-LocateCatalogNodeByKey(const ExtendedVCB *volume, UInt32 hint, CatalogKey *keyPtr,
-                                               CatalogRecord *dataPtr, UInt32 *newHint)
-{
-       OSErr                           result;
-       CatalogName             *nodeName = NULL;       /* To ward off uninitialized use warnings from compiler */
-       HFSCatalogNodeID        threadParentID;
-       UInt16 tempSize;
+               BlockMoveData(&searchIterator->key, keyPtr, sizeof(CatalogKey));
+       }
 
+       if (result == btNotFound) {
+               result = cmNotFound;
+       }       
 
-       result = SearchBTreeRecord(volume->catalogRefNum, keyPtr, hint, keyPtr,
-                                                               dataPtr, &tempSize, newHint);
-       if (result == btNotFound)
-               result = cmNotFound;    
-       ReturnIfError(result);
+       if (result) {
+               FREE(searchIterator, M_TEMP);
+               return result;
+       }
        
        // if we got a thread record, then go look up real record
        switch ( dataPtr->recordType )
        {
+
+#if CONFIG_HFS_STD
                case kHFSFileThreadRecord:
                case kHFSFolderThreadRecord:
                        threadParentID = dataPtr->hfsThread.parentID;
                        nodeName = (CatalogName *) &dataPtr->hfsThread.nodeName;
                        break;
+#endif
 
                case kHFSPlusFileThreadRecord:
                case kHFSPlusFolderThreadRecord:
@@ -190,197 +119,11 @@ LocateCatalogNodeByKey(const ExtendedVCB *volume, UInt32 hint, CatalogKey *keyPt
        if ( threadParentID )           // found a thread
                result = LocateCatalogRecord(volume, threadParentID, nodeName, kNoHint, keyPtr, dataPtr, newHint);
        
+       FREE (searchIterator, M_TEMP);
        return result;
 }
 
 
-#if 0
-//*******************************************************************************
-//     Routine:        LocateCatalogNodeWithRetry
-//
-// Function:   Locates the catalog record for an existing folder or file node.
-//                             For HFS Plus volumes a retry is performed when a catalog node is
-//                             not found and the volume contains more than one text encoding.
-//
-//ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
-
-#define VolumeHasEncodings(v) \
-       ( ((v)->encodingsBitmap != 0 )
-
-#define        EncodingInstalled(i) \
-       ( (fsVars)->gConversionContext[(i)].toUnicode != 0 )
-
-#define        EncodingUsedByVolume(v,i) \
-       ( ((v)->encodingsBitmap & (1 << (i))) )
-
-
-OSErr
-LocateCatalogNodeWithRetry (const ExtendedVCB *volume, HFSCatalogNodeID folderID, ConstStr31Param pascalName, CatalogName *unicodeName,
-                                                       UInt32 hint, CatalogKey *keyPtr, CatalogRecord *dataPtr, UInt32 *newHint)
-{
-       TextEncoding            defaultEncoding;
-       TextEncoding            encoding;
-       ItemCount                       encodingsToTry;
-       FSVarsRec                       *fsVars;
-       OSErr                           result = cmNotFound;
-
-       fsVars = (FSVarsRec*) LMGetFSMVars();   // used by macros
-
-       defaultEncoding = GetDefaultTextEncoding();
-       encodingsToTry = CountInstalledEncodings();
-
-       // 1. Try finding file using default encoding (typical case)
-
-       {
-               --encodingsToTry;
-               result = PrepareInputName(pascalName, true, defaultEncoding, unicodeName);
-               if (result == noErr)
-                       result = LocateCatalogNode(volume, folderID, unicodeName, hint, keyPtr, dataPtr, newHint);
-               else
-                       result = cmNotFound;
-
-               if ( result != cmNotFound || encodingsToTry == 0)
-                       return result;
-       }
-
-       //
-       // XXX if the pascal string contains all 7-bit ascii then we don't need to do anymore retries
-       //
-
-       // 2. Try finding file using Mac Roman (if not already tried above)
-
-       if ( defaultEncoding != kTextEncodingMacRoman )
-       {
-               --encodingsToTry;
-               result = PrepareInputName(pascalName, true, kTextEncodingMacRoman, unicodeName);
-               if (result == noErr)
-                       result = LocateCatalogNode(volume, folderID, unicodeName, hint, keyPtr, dataPtr, newHint);
-               else
-                       result = cmNotFound;
-
-               if ( result != cmNotFound || encodingsToTry == 0 )
-                       return result;
-       }
-
-       // 3. Try with encodings from disk (if any)
-
-       if ( VolumeHasEncodings(volume) )       // any left to try?
-       {
-               UInt32  index;
-
-               index = 0;      // since we pre increment this will skip MacRoman (which was already tried above)
-
-               while ( index < kMacBaseEncodingCount )
-               {
-                       ++index;
-                       
-                       encoding = MapIndexToEncoding(index);
-
-                       if ( encoding == defaultEncoding )
-                               continue;               // we did this one already
-
-                       if ( EncodingInstalled(index) && EncodingUsedByVolume(volume, index) )
-                       {
-                               --encodingsToTry;
-                               result = PrepareInputName(pascalName, true, encoding, unicodeName);
-                               if (result == noErr)
-                                       result = LocateCatalogNode(volume, folderID, unicodeName, hint, keyPtr, dataPtr, newHint);
-                               else
-                                       result = cmNotFound;
-
-                               if ( result != cmNotFound || encodingsToTry == 0 )
-                                       return result;
-                       }
-               }
-       }
-
-       // 4. Try any remaining encodings (if any)
-
-       {
-               UInt32  index;
-
-               index = 0;      // since we pre increment this will skip MacRoman (which was already tried above)
-       
-               while ( (encodingsToTry > 0) && (index < kMacBaseEncodingCount) )
-               {
-                       ++index;
-       
-                       encoding = MapIndexToEncoding(index);
-       
-                       if ( encoding == defaultEncoding )
-                               continue;               // we did this one already
-       
-                       if ( EncodingInstalled(index) && EncodingUsedByVolume(volume, index) == false )
-                       {
-                               --encodingsToTry;
-                               result = PrepareInputName(pascalName, true, encoding, unicodeName);
-                               if (result == noErr)
-                                       result = LocateCatalogNode(volume, folderID, unicodeName, hint, keyPtr, dataPtr, newHint);
-                               else
-                                       result = cmNotFound;
-
-                               if ( result != cmNotFound || encodingsToTry == 0 )
-                                       return result;
-                       }
-               }
-       }
-
-       return cmNotFound;
-}
-#endif
-
-//*******************************************************************************
-//     Routine:        LocateCatalogNodeByMangledName
-//
-// Function:   Locates the catalog record associated with a mangled name (if any)
-//
-//*******************************************************************************
-#define kMaxCompareLen         64              /* If it compares this far...lets believe it */
-
-OSErr
-LocateCatalogNodeByMangledName( const ExtendedVCB *volume, HFSCatalogNodeID folderID,
-                                                               const unsigned char * name, UInt32 length, CatalogKey *keyPtr,
-                                                               CatalogRecord *dataPtr, UInt32 *hintPtr )
-{
-       HFSCatalogNodeID        fileID;
-       unsigned char           nodeName[kMaxCompareLen+1];
-       OSErr                           result;
-       size_t                  actualDstLen;
-       ByteCount                       prefixlen;
-
-
-       if (name == NULL || name[0] == '\0')
-               return cmNotFound;
-
-       fileID = GetEmbeddedFileID(name, length, &prefixlen);
-
-       if ( fileID < kHFSFirstUserCatalogNodeID )
-               return cmNotFound;
-               
-       result = LocateCatalogNode(volume, fileID, NULL, kNoHint, keyPtr, dataPtr, hintPtr);
-       if ( result == cmParentNotFound )       // GetCatalogNode already handled cmParentNotFound case         <CS23>
-               result = cmNotFound;                    // so remap                                                                                                     <CS23>
-       ReturnIfError(result);
-               
-       // first make sure that the parents match
-       if ( folderID != keyPtr->hfsPlus.parentID )
-               return cmNotFound;                      // not the same folder so this is a false match
-
-       (void) utf8_encodestr(keyPtr->hfsPlus.nodeName.unicode,
-                       keyPtr->hfsPlus.nodeName.length * sizeof (UniChar),
-                       nodeName, &actualDstLen, kMaxCompareLen+1, ':', 0);
-
-       prefixlen = min(prefixlen, kMaxCompareLen);
-       
-       if ((prefixlen - actualDstLen) < 6)
-               prefixlen = actualDstLen;       /* To take into account UTF8 rounding */
-               
-       if ( (actualDstLen < prefixlen) || bcmp(nodeName, name, prefixlen-6) != 0)
-               return cmNotFound;      // mangled names didn't match so this is a false match
-       
-       return noErr;   // we found it
-}
-
 
 //*******************************************************************************
 //     Routine:        LocateCatalogRecord
@@ -391,50 +134,44 @@ LocateCatalogNodeByMangledName( const ExtendedVCB *volume, HFSCatalogNodeID fold
 
 OSErr
 LocateCatalogRecord(const ExtendedVCB *volume, HFSCatalogNodeID folderID, const CatalogName *name,
-                                       UInt32 hint, CatalogKey *keyPtr, CatalogRecord *dataPtr, UInt32 *newHint)
+                                       __unused u_int32_t hint, CatalogKey *keyPtr, CatalogRecord *dataPtr, u_int32_t *newHint)
 {
-       OSErr                   result;
-       CatalogKey              tempKey;        // 518 bytes
-       UInt16                  tempSize;
+       OSErr result;
+       uint16_t tempSize;
+       FSBufferDescriptor btRecord;
+       struct BTreeIterator *searchIterator = NULL;
+       FCB *fcb;
+       BTreeControlBlock *btcb;
+
+       MALLOC (searchIterator, struct BTreeIterator*, sizeof(struct BTreeIterator), M_TEMP, M_WAITOK);
+       if (searchIterator == NULL) {
+               return memFullErr;  // translates to ENOMEM
+       }
 
-       BuildCatalogKey(folderID, name, (volume->vcbSigWord == kHFSPlusSigWord), &tempKey);
+       bzero(searchIterator, sizeof(*searchIterator));
 
-       if ( name == NULL )
-               hint = kNoHint;                 // no CName given so clear the hint
 
-       result = SearchBTreeRecord(volume->catalogRefNum, &tempKey, hint, keyPtr, dataPtr, &tempSize, newHint);
+       fcb = GetFileControlBlock(volume->catalogRefNum);
+       btcb = (BTreeControlBlock *)fcb->fcbBTCBPtr;
        
-       return (result == btNotFound ? cmNotFound : result);    
-}
+       btRecord.bufferAddress = dataPtr;
+       btRecord.itemCount = 1;
+       btRecord.itemSize = sizeof(CatalogRecord);
 
+       BuildCatalogKey(folderID, name, (volume->vcbSigWord == kHFSPlusSigWord), (CatalogKey *)&searchIterator->key);
 
-//*******************************************************************************
-//     Routine:        LocateCatalogThread
-//
-//     Function:       Locates a catalog thread record in the catalog BTree file and 
-//                             returns a pointer to the data record.
-//
-//*******************************************************************************
-
-OSErr
-LocateCatalogThread(const ExtendedVCB *volume, HFSCatalogNodeID nodeID, CatalogRecord *threadData, UInt16 *threadSize, UInt32 *threadHint)
-{
-       CatalogKey      threadKey;      // 518 bytes
-       OSErr           result;
-
-       //--- build key record
-
-       BuildCatalogKey(nodeID, NULL, (volume->vcbSigWord == kHFSPlusSigWord), &threadKey);
-
-       //--- locate thread record in BTree
+       result = BTSearchRecord(fcb, searchIterator, &btRecord, &tempSize, searchIterator);
+       if (result == noErr) {
+               *newHint = searchIterator->hint.nodeNum;
+               BlockMoveData(&searchIterator->key, keyPtr, CalcKeySize(btcb, &searchIterator->key));
+       }
 
-       result = SearchBTreeRecord( volume->catalogRefNum, &threadKey, kNoHint, &threadKey,
-                                                               threadData, threadSize, threadHint);
-       
-       return (result == btNotFound ? cmNotFound : result);    
+       FREE (searchIterator, M_TEMP);
+       return (result == btNotFound ? cmNotFound : result);
 }
 
 
+
 /*
  *     Routine:        BuildCatalogKey
  *
@@ -458,6 +195,7 @@ BuildCatalogKey(HFSCatalogNodeID parentID, const CatalogName *cName, Boolean isH
                        key->hfsPlus.keyLength += sizeof(UniChar) * cName->ustr.length; // add CName size to key length
                }
        }
+#if CONFIG_HFS_STD
        else
        {
                key->hfs.keyLength              = kHFSCatalogKeyMinimumLength;  // initial key length (1 + 4 + 1)
@@ -470,21 +208,20 @@ BuildCatalogKey(HFSCatalogNodeID parentID, const CatalogName *cName, Boolean isH
                        key->hfs.keyLength += key->hfs.nodeName[0];             // add CName size to key length
                }
        }
+#endif
+
 }
 
-/*
- * for HFS, only MacRoman is supported. If a non-MacRoman character is found, an error is returned
- */
 OSErr
-BuildCatalogKeyUTF8(ExtendedVCB *volume, HFSCatalogNodeID parentID, const char *name, UInt32 nameLength,
-                   CatalogKey *key, UInt32 *textEncoding)
+BuildCatalogKeyUTF8(ExtendedVCB *volume, HFSCatalogNodeID parentID, const unsigned char *name, u_int32_t nameLength,
+                   CatalogKey *key, u_int32_t *textEncoding)
 {
        OSErr err = 0;
 
     if ( name == NULL)
         nameLength = 0;
     else if (nameLength == kUndefinedStrLen)
-        nameLength = strlen(name);
+        nameLength = strlen((const char *)name);
 
        if ( volume->vcbSigWord == kHFSPlusSigWord ) {
                size_t unicodeBytes = 0;
@@ -499,9 +236,11 @@ BuildCatalogKeyUTF8(ExtendedVCB *volume, HFSCatalogNodeID parentID, const char *
                        key->hfsPlus.keyLength += unicodeBytes;
                }
 
-               if (textEncoding)
-               ExtractTextEncoding(key->hfsPlus.nodeName.length, key->hfsPlus.nodeName.unicode, textEncoding);
+               if (textEncoding && (*textEncoding != kTextEncodingMacUnicode))
+                       *textEncoding = hfs_pickencoding(key->hfsPlus.nodeName.unicode,
+                               key->hfsPlus.nodeName.length);
        }
+#if CONFIG_HFS_STD
        else {
                key->hfs.keyLength              = kHFSCatalogKeyMinimumLength;  // initial key length (1 + 4 + 1)
                key->hfs.reserved               = 0;                            // clear unused byte
@@ -521,6 +260,7 @@ BuildCatalogKeyUTF8(ExtendedVCB *volume, HFSCatalogNodeID parentID, const char *
                if (textEncoding)
                        *textEncoding = 0;
        }
+#endif
 
        if (err) {
                if (err == ENAMETOOLONG)
@@ -533,36 +273,6 @@ BuildCatalogKeyUTF8(ExtendedVCB *volume, HFSCatalogNodeID parentID, const char *
 }
 
 
-/*
- * make a guess at the text encoding value that coresponds to the Unicode characters
- */
-static void
-ExtractTextEncoding(ItemCount length, ConstUniCharArrayPtr string, UInt32 * textEncoding)
-{
-       int i;
-       UniChar ch;
-
-       *textEncoding = 0;
-
-       for (i = 0; i < length; ++i) {
-               ch = string[i];
-               /* CJK codepoints are 0x3000 thru 0x9FFF */
-               if (ch >= 0x3000) {
-                       if (ch < 0xa000) {
-                               *textEncoding = kTextEncodingMacJapanese;
-                               break;
-                       }
-
-                       /* fullwidth character codepoints are 0xFF00 thru 0xFFEF */
-                       if (ch >= 0xff00 && ch <= 0xffef) {
-                               *textEncoding = kTextEncodingMacJapanese;
-                               break;  
-                       }
-               }
-       }
-}
-
-
 //*******************************************************************************
 //     Routine:        FlushCatalog
 //
@@ -575,6 +285,7 @@ FlushCatalog(ExtendedVCB *volume)
 {
        FCB *   fcb;
        OSErr   result;
+       struct hfsmount *hfsmp = VCBTOHFS (volume);
        
        fcb = GetFileControlBlock(volume->catalogRefNum);
        result = BTFlushPath(fcb);
@@ -583,14 +294,14 @@ FlushCatalog(ExtendedVCB *volume)
        {
                //--- check if catalog's fcb is dirty...
                
-               if ( fcb->fcbFlags & fcbModifiedMask )
+               if ( (0) /*fcb->fcbFlags & fcbModifiedMask*/ )
                {
-                       VCB_LOCK(volume);
-                       volume->vcbFlags |= 0xFF00;             // Mark the VCB dirty
+                       hfs_lock_mount (hfsmp);
+                       MarkVCBDirty(volume);   // Mark the VCB dirty
                        volume->vcbLsMod = GetTimeUTC();        // update last modified date
-                       VCB_UNLOCK(volume);
+                       hfs_unlock_mount (hfsmp);
 
-                       result = FlushVolumeControlBlock(volume);
+               //      result = FlushVolumeControlBlock(volume);
                }
        }
        
@@ -618,243 +329,12 @@ UpdateCatalogName(ConstStr31Param srcName, Str31 destName)
        BlockMoveData(&srcName[1], &destName[1], length);
 }
 
-
-//*******************************************************************************
-//     Routine:        AdjustVolumeCounts
-//
-//     Function:       Adjusts the folder and file counts in the VCB
-//
-//*******************************************************************************
-
-void
-AdjustVolumeCounts(ExtendedVCB *volume, SInt16 type, SInt16 delta)
-{
-       //\80\80 also update extended VCB fields...
-
-       VCB_LOCK(volume);
-
-       if (type == kHFSFolderRecord || type == kHFSPlusFolderRecord)
-               volume->vcbDirCnt += delta;                     // adjust volume folder count, \80\80 worry about overflow?
-       else
-               volume->vcbFilCnt += delta;                     // adjust volume file count
-       
-       volume->vcbFlags |= 0xFF00;             // Mark the VCB dirty
-       volume->vcbLsMod = GetTimeUTC();        // update last modified date
-
-       VCB_UNLOCK(volume);
-}
-
-
-//*******************************************************************************
-
-void
-UpdateVolumeEncodings(ExtendedVCB *volume, TextEncoding encoding)
-{
-       UInt32  index;
-
-       encoding &= 0x7F;
-       
-       index = MapEncodingToIndex(encoding);
-
-       VCB_LOCK(volume);
-
-       volume->encodingsBitmap |= (1 << index);
-
-       VCB_UNLOCK(volume);
-               
-       // vcb should already be marked dirty
-}
-
-
-//*******************************************************************************
-
-OSErr
-UpdateFolderCount( ExtendedVCB *volume, HFSCatalogNodeID parentID, const CatalogName *name, SInt16 newType,
-                                       UInt32 hint, SInt16 valenceDelta)
-{
-       CatalogKey                      tempKey;        // 518 bytes
-       CatalogRecord           tempData;       // 520 bytes
-       UInt32                          tempHint;
-       HFSCatalogNodeID        folderID;
-       UInt16                          recordSize;
-       OSErr                           result;
-
-#if 0
-       result = SearchBTreeRecord(volume->catalogRefNum, parentKey, hint,
-                                                               &tempKey, &tempData, &recordSize, &tempHint);
-       if (result)
-               return (result == btNotFound ? cmNotFound : result);    
-#else
-
-       result = LocateCatalogNode(volume, parentID, name, hint, &tempKey, &tempData, &tempHint);
-       ReturnIfError(result);
-#endif
-
-       if ( volume->vcbSigWord == kHFSPlusSigWord ) // HFS Plus
-       {
-               UInt32          timeStamp;
-               
-               if ( DEBUG_BUILD && tempData.recordType != kHFSPlusFolderRecord )
-                       DebugStr("\p UpdateFolder: found HFS folder on HFS+ volume!");
-
-               timeStamp = GetTimeUTC();
-               /* adjust valence, but don't go negative */
-               if (valenceDelta > 0)
-                       tempData.hfsPlusFolder.valence += valenceDelta;
-               else if (tempData.hfsPlusFolder.valence != 0)
-                       tempData.hfsPlusFolder.valence += valenceDelta;
-               else
-                       volume->vcbFlags |= kHFS_DamagedVolume;
-               tempData.hfsPlusFolder.contentModDate = timeStamp;      // set date/time last modified
-               folderID = tempData.hfsPlusFolder.folderID;
-               recordSize = sizeof(tempData.hfsPlusFolder);
-       }
-       else // classic HFS
-       {
-               if ( DEBUG_BUILD && tempData.recordType != kHFSFolderRecord )
-                       DebugStr("\p UpdateFolder: found HFS+ folder on HFS volume!");
-
-               /* adjust valence, but don't go negative */
-               if (valenceDelta > 0)
-                       tempData.hfsFolder.valence += valenceDelta;
-               else if (tempData.hfsFolder.valence != 0)
-                       tempData.hfsFolder.valence += valenceDelta;
-               else
-                       volume->vcbFlags |= kHFS_DamagedVolume;
-               tempData.hfsFolder.modifyDate = GetTimeLocal(true);             // set date/time last modified
-               folderID = tempData.hfsFolder.folderID;
-               recordSize = sizeof(tempData.hfsFolder);
-       }
-       
-       result = ReplaceBTreeRecord(volume->catalogRefNum, &tempKey, tempHint,
-                                                               &tempData, recordSize, &tempHint);
-       ReturnIfError(result);
-
-       if ( folderID == kHFSRootFolderID )
-       {
-               if (newType == kHFSFolderRecord || newType == kHFSPlusFolderRecord)
-               {
-                       VCB_LOCK(volume);
-                       volume->vcbNmRtDirs += valenceDelta;    // adjust root folder count (undefined for HFS Plus)
-                       VCB_UNLOCK(volume);
-               }
-               else
-               {
-                       VCB_LOCK(volume);
-                       volume->vcbNmFls += valenceDelta;               // adjust root file count (used by GetVolInfo)
-                       VCB_UNLOCK(volume);
-               }
-       }
-
-       //XXX also update extended VCB fields...
-
-       return result;
-}
-
-
-//*******************************************************************************
-
-UInt16 
-GetCatalogRecordSize(const CatalogRecord *dataRecord)
-{
-       switch (dataRecord->recordType)
-       {
-               case kHFSFileRecord:
-                       return sizeof(HFSCatalogFile);
-
-               case kHFSFolderRecord:
-                       return sizeof(HFSCatalogFolder);
-
-               case kHFSPlusFileRecord:
-                       return sizeof(HFSPlusCatalogFile);
-
-               case kHFSPlusFolderRecord:
-                       return sizeof(HFSPlusCatalogFolder);
-                       
-               case kHFSFolderThreadRecord:
-               case kHFSFileThreadRecord:
-                       return sizeof(HFSCatalogThread);
-
-               case kHFSPlusFolderThreadRecord:
-               case kHFSPlusFileThreadRecord:
-                       return sizeof(HFSPlusCatalogThread);
-
-               default:
-                       return 0;
-       }
-}
-
-
-//*******************************************************************************
-
-void
-CopyCatalogNodeData(const ExtendedVCB *volume, const CatalogRecord *dataPtr, CatalogNodeData *nodeData)
-{
-       /* convert classic hfs records to hfs plus format */
-
-       if (dataPtr->recordType == kHFSFolderRecord) {
-               nodeData->cnd_type = kCatalogFolderNode;
-               nodeData->cnd_flags = dataPtr->hfsFolder.flags;
-               nodeData->cnd_nodeID = dataPtr->hfsFolder.folderID;
-               nodeData->cnd_createDate = LocalToUTC(dataPtr->hfsFolder.createDate);
-               nodeData->cnd_contentModDate = LocalToUTC(dataPtr->hfsFolder.modifyDate);
-               nodeData->cnd_backupDate = LocalToUTC(dataPtr->hfsFolder.backupDate);
-               nodeData->cnd_valence = dataPtr->hfsFolder.valence;
-
-               BlockMoveData(&dataPtr->hfsFolder.userInfo, &nodeData->cnd_finderInfo, 32);
-       } else if (dataPtr->recordType == kHFSFileRecord) {
-                       UInt32  i;
-
-               nodeData->cnd_type = kCatalogFileNode;
-               nodeData->cnd_flags = dataPtr->hfsFile.flags;
-               nodeData->cnd_nodeID = dataPtr->hfsFile.fileID;
-               nodeData->cnd_createDate = LocalToUTC(dataPtr->hfsFile.createDate);
-               nodeData->cnd_contentModDate = LocalToUTC(dataPtr->hfsFile.modifyDate);
-               nodeData->cnd_backupDate = LocalToUTC(dataPtr->hfsFile.backupDate);
-               nodeData->cnd_linkCount = 0;
-
-               BlockMoveData(&dataPtr->hfsFile.userInfo, &nodeData->cnd_finderInfo, 16);
-               BlockMoveData(&dataPtr->hfsFile.finderInfo, (void*)((UInt32)&nodeData->cnd_finderInfo + 16), 16);
-
-               nodeData->cnd_datafork.logicalSize = dataPtr->hfsFile.dataLogicalSize;
-               nodeData->cnd_datafork.totalBlocks =
-                       dataPtr->hfsFile.dataPhysicalSize / volume->blockSize;
-
-               nodeData->cnd_rsrcfork.logicalSize  = dataPtr->hfsFile.rsrcLogicalSize;
-               nodeData->cnd_rsrcfork.totalBlocks =
-                       dataPtr->hfsFile.rsrcPhysicalSize / volume->blockSize;
-
-               for (i = 0; i < kHFSExtentDensity; ++i) {
-                       nodeData->cnd_datafork.extents[i].startBlock =
-                               (UInt32) (dataPtr->hfsFile.dataExtents[i].startBlock);
-
-                       nodeData->cnd_datafork.extents[i].blockCount =
-                               (UInt32) (dataPtr->hfsFile.dataExtents[i].blockCount);
-
-                       nodeData->cnd_rsrcfork.extents[i].startBlock =
-                               (UInt32) (dataPtr->hfsFile.rsrcExtents[i].startBlock);
-
-                       nodeData->cnd_rsrcfork.extents[i].blockCount =
-                               (UInt32) (dataPtr->hfsFile.rsrcExtents[i].blockCount);
-               }
-               for (i = kHFSExtentDensity; i < kHFSPlusExtentDensity; ++i) {
-                       nodeData->cnd_datafork.extents[i].startBlock = 0;
-                       nodeData->cnd_datafork.extents[i].blockCount = 0;
-                       nodeData->cnd_rsrcfork.extents[i].startBlock = 0;
-                       nodeData->cnd_rsrcfork.extents[i].blockCount = 0;
-               }
-       } else {
-               nodeData->cnd_type = 0;
-       }
-}
-
-
 //_______________________________________________________________________
 
 void
-CopyCatalogName(const CatalogName *srcName, CatalogName *dstName, Boolean isHFSPLus)
+CopyCatalogName(const CatalogName *srcName, CatalogName *dstName, Boolean isHFSPlus)
 {
-       UInt32  length;
+       u_int32_t       length = 0;
        
        if ( srcName == NULL )
        {
@@ -863,10 +343,14 @@ CopyCatalogName(const CatalogName *srcName, CatalogName *dstName, Boolean isHFSP
                return;
        }
        
-       if (isHFSPLus)
+       if (isHFSPlus) {
                length = sizeof(UniChar) * (srcName->ustr.length + 1);
-       else
-               length = sizeof(UInt8) + srcName->pstr[0];
+       }
+#if CONFIG_HFS_STD
+       else {
+               length = sizeof(u_int8_t) + srcName->pstr[0];
+       }
+#endif
 
        if ( length > 1 )
                BlockMoveData(srcName, dstName, length);
@@ -874,16 +358,3 @@ CopyCatalogName(const CatalogName *srcName, CatalogName *dstName, Boolean isHFSP
                dstName->ustr.length = 0;       // set length byte to zero (works for both unicode and pascal)          
 }
 
-//_______________________________________________________________________
-
-UInt32
-CatalogNameLength(const CatalogName *name, Boolean isHFSPlus)
-{
-       if (isHFSPlus)
-               return name->ustr.length;
-       else
-               return name->pstr[0];
-}
-
-
-