Annotation of kernel/bsd/hfs/hfscommon/Catalog/CatalogUtilities.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*
        !            26:        File:           CatalogUtilities.c
        !            27: 
        !            28:        Contains:       Private Catalog Manager support routines.
        !            29: 
        !            30:        Version:        HFS Plus 1.0
        !            31: 
        !            32:        Copyright:      � 1997-1999 by Apple Computer, Inc., all rights reserved.
        !            33: 
        !            34:        File Ownership:
        !            35: 
        !            36:                DRI:                            Don Brady
        !            37: 
        !            38:                Other Contact:          Mark Day
        !            39: 
        !            40:                Technology:                     xxx put technology here xxx
        !            41: 
        !            42:        Writers:
        !            43: 
        !            44:                (DSH)   Deric Horn
        !            45:                (msd)   Mark Day
        !            46:                (djb)   Don Brady
        !            47: 
        !            48:        Change History (most recent first):
        !            49:          <Rhap>          1/8/99        djb             Fixing LocateCatalogNodeByMangledName...
        !            50:          <Rhap>          1/7/99        djb             In BuildCatalogKeyUTF8 check name length against NAME_MAX.
        !            51:          <Rhap>         12/7/98        djb             Add ExtractTextEncoding routine to get text encodings.
        !            52:          <Rhap>        11/20/98        djb             Add support for UTF-8 names.
        !            53:          <Rhap>         8/31/98        djb             GetTimeLocal now takes an input.
        !            54:          <Rhap>         4/17/98        djb             Add VCB locking.
        !            55:          <Rhap>          4/3/98        djb             Removed last name conversion cache from LocateCatalogNodeWithRetry.
        !            56:          <Rhap>          4/2/98        djb             InvalidateCatalogNodeCache and TrashCatalogNodeCache are not used in Rhapsody.
        !            57:          <Rhap>        03/31/98        djb             Sync up with final HFSVolumes.h header file.
        !            58: 
        !            59:          <CS24>         1/29/98        DSH             Add TrashCatalogNodeCache for TrashAllFSCaches API support.
        !            60:          <CS23>        12/15/97        djb             Radar #2202860, In LocateCatalogNodeByMangledName remap
        !            61:                                                                        cmParentNotFound error code to cmNotFound.
        !            62:          <CS22>        12/10/97        DSH             2201501, Pin the leof and peof to multiple of allocation blocks
        !            63:                                                                        under 2 Gig.
        !            64:          <CS21>         12/9/97        DSH             2201501, Pin returned leof values to 2^31-1 (SInt32), instead of
        !            65:                                                                        2^32-1
        !            66:          <CS20>        11/26/97        djb             Radar #2005688, 2005461 - need to handle kTextMalformedInputErr.
        !            67:          <CS19>        11/25/97        djb             Radar #2002357 (again) fix new bug introduced in <CS18>.
        !            68:          <CS18>        11/17/97        djb             PrepareInputName routine now returns an error.
        !            69:          <CS17>        10/19/97        msd             Bug 1684586. GetCatInfo and SetCatInfo use only contentModDate.
        !            70:          <CS16>        10/17/97        djb             Add ConvertInputNameToUnicode for Catalog Create/Rename.
        !            71:          <CS15>        10/14/97        djb             Fix LocateCatalogNode's MakeFSSpec optimization (radar #1683166)
        !            72:          <CS14>        10/13/97        djb             Copy text encoding in CopyCatalogNodeData. Fix cut/paste error
        !            73:                                                                        in VolumeHasEncodings macro. When accessing encoding bitmap use
        !            74:                                                                        the MapEncodingToIndex and MapIndexToEncoding macros.
        !            75:          <CS13>         10/1/97        djb             Remove old Catalog Iterator code...
        !            76:          <CS12>          9/8/97        msd             Make sure a folder's modifyDate is set whenever its
        !            77:                                                                        contentModDate is set.
        !            78:          <CS11>          9/4/97        djb             Add MakeFSSpec optimization.
        !            79:          <CS10>          9/4/97        msd             In CatalogNodeData, change attributeModDate to modifyDate.
        !            80:           <CS9>         8/26/97        djb             Back out <CS4> (UpdateFolderCount must maintain vcbNmFls for HFS
        !            81:                                                                        Plus volumes too).
        !            82:           <CS8>         8/14/97        djb             Remove hard link support.
        !            83:           <CS7>         7/18/97        msd             Include LowMemPriv.h.
        !            84:           <CS6>         7/16/97        DSH             FilesInternal.i renamed FileMgrInternal.i to avoid name
        !            85:                                                                        collision
        !            86:           <CS5>          7/8/97        DSH             Loading PrecompiledHeaders from define passed in on C line
        !            87:           <CS4>         6/27/97        msd             UpdateFolderCount should update number of root files/folders for
        !            88:                                                                        HFS volumes, not HFS Plus.
        !            89:           <CS3>         6/24/97        djb             LocateCatalogNodeWithRetry did not always set result code.
        !            90:           <CS2>         6/24/97        djb             Add LocateCatalogNodeByMangledName routine
        !            91:           <CS1>         6/24/97        djb             first checked in
        !            92: */
        !            93: 
        !            94: #if ( PRAGMA_LOAD_SUPPORTED )
        !            95:         #pragma        load    PrecompiledHeaders
        !            96: #else
        !            97:         #if TARGET_OS_MAC
        !            98:         #include       <Errors.h>
        !            99:         #include       <Files.h>
        !           100:         #include       <FSM.h>
        !           101:         #include       <Memory.h>
        !           102:         #include       <TextUtils.h>
        !           103:         #include       <Types.h>
        !           104:         #include       <LowMemPriv.h>
        !           105:         #else
        !           106:                        #include "../headers/system/MacOSStubs.h"
        !           107:                        #include <sys/syslimits.h>
        !           108:         #endif         /* TARGET_OS_MAC */
        !           109: #endif /* PRAGMA_LOAD_SUPPORTED */
        !           110: 
        !           111: 
        !           112: #include       "../headers/FileMgrInternal.h"
        !           113: #include       "../headers/BTreesInternal.h"
        !           114: #include       "../headers/HFSVolumes.h"
        !           115: #include       "../headers/system/HFSUnicodeWrappers.h"
        !           116: #include       "../headers/CatalogPrivate.h"
        !           117: #include       <string.h>
        !           118: 
        !           119: static void ExtractTextEncoding (ItemCount length, ConstUniCharArrayPtr string, UInt32 * textEncoding);
        !           120: 
        !           121: //�������������������������������������������������������������������������������
        !           122: //     Routine:        LocateCatalogNode
        !           123: //
        !           124: // Function:   Locates the catalog record for an existing folder or file
        !           125: //                             CNode and returns pointers to the key and data records.
        !           126: //
        !           127: //�������������������������������������������������������������������������������
        !           128: 
        !           129: OSErr
        !           130: LocateCatalogNode(const ExtendedVCB *volume, HFSCatalogNodeID folderID, const CatalogName *name,
        !           131:                                        UInt32 hint, CatalogKey *keyPtr, CatalogRecord *dataPtr, UInt32 *newHint)
        !           132: {
        !           133:        OSErr                           result;
        !           134:        CatalogName             *nodeName = NULL;       /* To ward off uninitialized use warnings from compiler */
        !           135:        HFSCatalogNodeID        threadParentID;
        !           136: 
        !           137: 
        !           138:        result = LocateCatalogRecord(volume, folderID, name, hint, keyPtr, dataPtr, newHint);
        !           139: 
        !           140:        #if TARGET_OS_MAC
        !           141:        //
        !           142:        // MakeFSSpec Optimization...report a missing parent
        !           143:        //
        !           144:        if ( (result == cmNotFound) && (LMGetHFSFlags() & (1 << reportMissingParent)) )
        !           145:        {
        !           146:                HFSCatalogNodeID        parentID;
        !           147:                UInt16                          dataSize;
        !           148:                OSErr                           err;
        !           149:                Boolean                         isHFSPlus = (volume->vcbSigWord == kHFSPlusSigWord);
        !           150:                
        !           151:                result = cmParentNotFound;      // assume directory is missing
        !           152:                
        !           153:                if ( (name != NULL) && (CatalogNameLength(name, isHFSPlus) > 0) )
        !           154:                {
        !           155:                        // Look at the previous record's parent ID to determine if the
        !           156:                        // parent of the CNode we were looking for actually exists
        !           157:        
        !           158:                        err = GetBTreeRecord(volume->catalogRefNum, -1, keyPtr, dataPtr, &dataSize, newHint);
        !           159:                        if (err == noErr)
        !           160:                        {
        !           161:                                if ( isHFSPlus )
        !           162:                                        parentID = keyPtr->hfsPlus.parentID;
        !           163:                                else
        !           164:                                        parentID = keyPtr->hfs.parentID;
        !           165:                                
        !           166:                                if ( folderID == parentID )             // did parent exists?
        !           167:                                        result = cmNotFound;    // yes, so report a missing file to MakeFSSpec
        !           168:                        }
        !           169:                }
        !           170:        }
        !           171:        #endif /* TARGET_OS_MAC */
        !           172: 
        !           173:        ReturnIfError(result);
        !           174:        
        !           175:        // if we got a thread record, then go look up real record
        !           176:        switch ( dataPtr->recordType )
        !           177:        {
        !           178:                case kHFSFileThreadRecord:
        !           179:                case kHFSFolderThreadRecord:
        !           180:                        threadParentID = dataPtr->hfsThread.parentID;
        !           181:                        nodeName = (CatalogName *) &dataPtr->hfsThread.nodeName;
        !           182:                        break;
        !           183: 
        !           184:                case kHFSPlusFileThreadRecord:
        !           185:                case kHFSPlusFolderThreadRecord:
        !           186:                        threadParentID = dataPtr->hfsPlusThread.parentID;
        !           187:                        nodeName = (CatalogName *) &dataPtr->hfsPlusThread.nodeName;    
        !           188:                        break;
        !           189: 
        !           190:                default:
        !           191:                        threadParentID = 0;
        !           192:                        break;
        !           193:        }
        !           194:        
        !           195:        if ( threadParentID )           // found a thread
        !           196:                result = LocateCatalogRecord(volume, threadParentID, nodeName, kNoHint, keyPtr, dataPtr, newHint);
        !           197:        
        !           198:        return result;
        !           199: }
        !           200: 
        !           201: //
        !           202: //     Routine:        LocateCatalogNodeByKey
        !           203: //
        !           204: // Function:   Locates the catalog record for an existing folder or file
        !           205: //                             CNode and returns the key and data records.
        !           206: //
        !           207: 
        !           208: OSErr
        !           209: LocateCatalogNodeByKey(const ExtendedVCB *volume, UInt32 hint, CatalogKey *keyPtr,
        !           210:                                                CatalogRecord *dataPtr, UInt32 *newHint)
        !           211: {
        !           212:        OSErr                           result;
        !           213:        CatalogName             *nodeName = NULL;       /* To ward off uninitialized use warnings from compiler */
        !           214:        HFSCatalogNodeID        threadParentID;
        !           215:        UInt16 tempSize;
        !           216: 
        !           217: 
        !           218:        result = SearchBTreeRecord(volume->catalogRefNum, keyPtr, hint, keyPtr,
        !           219:                                                                dataPtr, &tempSize, newHint);
        !           220:        if (result == btNotFound)
        !           221:                result = cmNotFound;    
        !           222:        ReturnIfError(result);
        !           223:        
        !           224:        // if we got a thread record, then go look up real record
        !           225:        switch ( dataPtr->recordType )
        !           226:        {
        !           227:                case kHFSFileThreadRecord:
        !           228:                case kHFSFolderThreadRecord:
        !           229:                        threadParentID = dataPtr->hfsThread.parentID;
        !           230:                        nodeName = (CatalogName *) &dataPtr->hfsThread.nodeName;
        !           231:                        break;
        !           232: 
        !           233:                case kHFSPlusFileThreadRecord:
        !           234:                case kHFSPlusFolderThreadRecord:
        !           235:                        threadParentID = dataPtr->hfsPlusThread.parentID;
        !           236:                        nodeName = (CatalogName *) &dataPtr->hfsPlusThread.nodeName;    
        !           237:                        break;
        !           238: 
        !           239:                default:
        !           240:                        threadParentID = 0;
        !           241:                        break;
        !           242:        }
        !           243:        
        !           244:        if ( threadParentID )           // found a thread
        !           245:                result = LocateCatalogRecord(volume, threadParentID, nodeName, kNoHint, keyPtr, dataPtr, newHint);
        !           246:        
        !           247:        return result;
        !           248: }
        !           249: 
        !           250: 
        !           251: #if 0
        !           252: //�������������������������������������������������������������������������������
        !           253: //     Routine:        LocateCatalogNodeWithRetry
        !           254: //
        !           255: // Function:   Locates the catalog record for an existing folder or file node.
        !           256: //                             For HFS Plus volumes a retry is performed when a catalog node is
        !           257: //                             not found and the volume contains more than one text encoding.
        !           258: //
        !           259: //�������������������������������������������������������������������������������
        !           260: 
        !           261: #define VolumeHasEncodings(v) \
        !           262:        ( ((v)->encodingsBitmap.lo | (v)->encodingsBitmap.hi) != 0 )
        !           263: 
        !           264: #define        EncodingInstalled(i) \
        !           265:        ( (fsVars)->gConversionContext[(i)].toUnicode != 0 )
        !           266: 
        !           267: #define        EncodingUsedByVolume(v,i) \
        !           268:        ( i < 32 ? ((v)->encodingsBitmap.lo & (1 << (i))) : ((v)->encodingsBitmap.hi & (1 << (i-32))) )
        !           269: 
        !           270: 
        !           271: OSErr
        !           272: LocateCatalogNodeWithRetry (const ExtendedVCB *volume, HFSCatalogNodeID folderID, ConstStr31Param pascalName, CatalogName *unicodeName,
        !           273:                                                        UInt32 hint, CatalogKey *keyPtr, CatalogRecord *dataPtr, UInt32 *newHint)
        !           274: {
        !           275:        TextEncoding            defaultEncoding;
        !           276:        TextEncoding            encoding;
        !           277:        ItemCount                       encodingsToTry;
        !           278:        FSVarsRec                       *fsVars;
        !           279:        OSErr                           result = cmNotFound;
        !           280: 
        !           281:        fsVars = (FSVarsRec*) LMGetFSMVars();   // used by macros
        !           282: 
        !           283:        defaultEncoding = GetDefaultTextEncoding();
        !           284:        encodingsToTry = CountInstalledEncodings();
        !           285: 
        !           286:        // 1. Try finding file using default encoding (typical case)
        !           287: 
        !           288:        {
        !           289:                --encodingsToTry;
        !           290:                result = PrepareInputName(pascalName, true, defaultEncoding, unicodeName);
        !           291:                if (result == noErr)
        !           292:                        result = LocateCatalogNode(volume, folderID, unicodeName, hint, keyPtr, dataPtr, newHint);
        !           293:                else
        !           294:                        result = cmNotFound;
        !           295: 
        !           296:                if ( result != cmNotFound || encodingsToTry == 0)
        !           297:                        return result;
        !           298:        }
        !           299: 
        !           300:        //
        !           301:        // XXX if the pascal string contains all 7-bit ascii then we don't need to do anymore retries
        !           302:        //
        !           303: 
        !           304:        // 2. Try finding file using Mac Roman (if not already tried above)
        !           305: 
        !           306:        if ( defaultEncoding != kTextEncodingMacRoman )
        !           307:        {
        !           308:                --encodingsToTry;
        !           309:                result = PrepareInputName(pascalName, true, kTextEncodingMacRoman, unicodeName);
        !           310:                if (result == noErr)
        !           311:                        result = LocateCatalogNode(volume, folderID, unicodeName, hint, keyPtr, dataPtr, newHint);
        !           312:                else
        !           313:                        result = cmNotFound;
        !           314: 
        !           315:                if ( result != cmNotFound || encodingsToTry == 0 )
        !           316:                        return result;
        !           317:        }
        !           318: 
        !           319:        // 3. Try with encodings from disk (if any)
        !           320: 
        !           321:        if ( VolumeHasEncodings(volume) )       // any left to try?
        !           322:        {
        !           323:                UInt32  index;
        !           324: 
        !           325:                index = 0;      // since we pre increment this will skip MacRoman (which was already tried above)
        !           326: 
        !           327:                while ( index < kMacBaseEncodingCount )
        !           328:                {
        !           329:                        ++index;
        !           330:                        
        !           331:                        encoding = MapIndexToEncoding(index);
        !           332: 
        !           333:                        if ( encoding == defaultEncoding )
        !           334:                                continue;               // we did this one already
        !           335: 
        !           336:                        if ( EncodingInstalled(index) && EncodingUsedByVolume(volume, index) )
        !           337:                        {
        !           338:                                --encodingsToTry;
        !           339:                                result = PrepareInputName(pascalName, true, encoding, unicodeName);
        !           340:                                if (result == noErr)
        !           341:                                        result = LocateCatalogNode(volume, folderID, unicodeName, hint, keyPtr, dataPtr, newHint);
        !           342:                                else
        !           343:                                        result = cmNotFound;
        !           344: 
        !           345:                                if ( result != cmNotFound || encodingsToTry == 0 )
        !           346:                                        return result;
        !           347:                        }
        !           348:                }
        !           349:        }
        !           350: 
        !           351:        // 4. Try any remaining encodings (if any)
        !           352: 
        !           353:        {
        !           354:                UInt32  index;
        !           355: 
        !           356:                index = 0;      // since we pre increment this will skip MacRoman (which was already tried above)
        !           357:        
        !           358:                while ( (encodingsToTry > 0) && (index < kMacBaseEncodingCount) )
        !           359:                {
        !           360:                        ++index;
        !           361:        
        !           362:                        encoding = MapIndexToEncoding(index);
        !           363:        
        !           364:                        if ( encoding == defaultEncoding )
        !           365:                                continue;               // we did this one already
        !           366:        
        !           367:                        if ( EncodingInstalled(index) && EncodingUsedByVolume(volume, index) == false )
        !           368:                        {
        !           369:                                --encodingsToTry;
        !           370:                                result = PrepareInputName(pascalName, true, encoding, unicodeName);
        !           371:                                if (result == noErr)
        !           372:                                        result = LocateCatalogNode(volume, folderID, unicodeName, hint, keyPtr, dataPtr, newHint);
        !           373:                                else
        !           374:                                        result = cmNotFound;
        !           375: 
        !           376:                                if ( result != cmNotFound || encodingsToTry == 0 )
        !           377:                                        return result;
        !           378:                        }
        !           379:                }
        !           380:        }
        !           381: 
        !           382:        return cmNotFound;
        !           383: }
        !           384: #endif
        !           385: 
        !           386: //�������������������������������������������������������������������������������
        !           387: //     Routine:        LocateCatalogNodeByMangledName
        !           388: //
        !           389: // Function:   Locates the catalog record associated with a mangled name (if any)
        !           390: //
        !           391: //�������������������������������������������������������������������������������
        !           392: 
        !           393: OSErr
        !           394: LocateCatalogNodeByMangledName( const ExtendedVCB *volume, HFSCatalogNodeID folderID,
        !           395:                                                                const unsigned char * name, CatalogKey *keyPtr,
        !           396:                                                                CatalogRecord *dataPtr, UInt32 *hintPtr )
        !           397: {
        !           398:        HFSCatalogNodeID        fileID;
        !           399:        unsigned char           nodeName[64];
        !           400:        OSErr                           result;
        !           401:        ByteCount                       actualDstLen;
        !           402:        ByteCount                       prefixlen;
        !           403: 
        !           404: 
        !           405:        if (name == NULL || name[0] == '\0')
        !           406:                return cmNotFound;
        !           407: 
        !           408:        fileID = GetEmbeddedFileID(name, &prefixlen);
        !           409: 
        !           410:        if ( fileID < kHFSFirstUserCatalogNodeID )
        !           411:                return cmNotFound;
        !           412:                
        !           413:        result = LocateCatalogNode(volume, fileID, NULL, kNoHint, keyPtr, dataPtr, hintPtr);
        !           414:        if ( result == cmParentNotFound )       // GetCatalogNode already handled cmParentNotFound case         <CS23>
        !           415:                result = cmNotFound;                    // so remap                                                                                                     <CS23>
        !           416:        ReturnIfError(result);
        !           417:                
        !           418:        // first make sure that the parents match
        !           419:        if ( folderID != keyPtr->hfsPlus.parentID )
        !           420:                return cmNotFound;                      // not the same folder so this is a false match
        !           421: 
        !           422:        result =  ConvertUnicodeToUTF8( keyPtr->hfsPlus.nodeName.length * sizeof (UniChar),
        !           423:                                                                        keyPtr->hfsPlus.nodeName.unicode,
        !           424:                                                                        64,
        !           425:                                                                        &actualDstLen,
        !           426:                                                                        nodeName);
        !           427: 
        !           428:        if ( (actualDstLen < prefixlen) || bcmp(nodeName, name, prefixlen) != 0)
        !           429:                return cmNotFound;      // mangled names didn't match so this is a false match
        !           430:        
        !           431:        return noErr;   // we found it
        !           432: }
        !           433: 
        !           434: 
        !           435: //�������������������������������������������������������������������������������
        !           436: //     Routine:        LocateCatalogRecord
        !           437: //
        !           438: // Function:   Locates the catalog record associated with folderID and name
        !           439: //
        !           440: //�������������������������������������������������������������������������������
        !           441: 
        !           442: OSErr
        !           443: LocateCatalogRecord(const ExtendedVCB *volume, HFSCatalogNodeID folderID, const CatalogName *name,
        !           444:                                        UInt32 hint, CatalogKey *keyPtr, CatalogRecord *dataPtr, UInt32 *newHint)
        !           445: {
        !           446:        OSErr                   result;
        !           447:        CatalogKey              tempKey;        // 518 bytes
        !           448:        UInt16                  tempSize;
        !           449: 
        !           450:        BuildCatalogKey(folderID, name, (volume->vcbSigWord == kHFSPlusSigWord), &tempKey);
        !           451: 
        !           452:        if ( name == NULL )
        !           453:                hint = kNoHint;                 // no CName given so clear the hint
        !           454: 
        !           455:        result = SearchBTreeRecord(volume->catalogRefNum, &tempKey, hint, keyPtr, dataPtr, &tempSize, newHint);
        !           456:        
        !           457:        return (result == btNotFound ? cmNotFound : result);    
        !           458: }
        !           459: 
        !           460: 
        !           461: //�������������������������������������������������������������������������������
        !           462: //     Routine:        LocateCatalogThread
        !           463: //
        !           464: //     Function:       Locates a catalog thread record in the catalog BTree file and 
        !           465: //                             returns a pointer to the data record.
        !           466: //
        !           467: //�������������������������������������������������������������������������������
        !           468: 
        !           469: OSErr
        !           470: LocateCatalogThread(const ExtendedVCB *volume, HFSCatalogNodeID nodeID, CatalogRecord *threadData, UInt16 *threadSize, UInt32 *threadHint)
        !           471: {
        !           472:        CatalogKey      threadKey;      // 518 bytes
        !           473:        OSErr           result;
        !           474: 
        !           475:        //--- build key record
        !           476: 
        !           477:        BuildCatalogKey(nodeID, NULL, (volume->vcbSigWord == kHFSPlusSigWord), &threadKey);
        !           478: 
        !           479:        //--- locate thread record in BTree
        !           480: 
        !           481:        result = SearchBTreeRecord( volume->catalogRefNum, &threadKey, kNoHint, &threadKey,
        !           482:                                                                threadData, threadSize, threadHint);
        !           483:        
        !           484:        return (result == btNotFound ? cmNotFound : result);    
        !           485: }
        !           486: 
        !           487: 
        !           488: /*
        !           489:  *     Routine:        BuildCatalogKey
        !           490:  *
        !           491:  *     Function:       Constructs a catalog key record (ckr) given the parent
        !           492:  *                             folder ID and CName.  Works for both classic and extended
        !           493:  *                             HFS volumes.
        !           494:  *
        !           495:  */
        !           496: 
        !           497: void
        !           498: BuildCatalogKey(HFSCatalogNodeID parentID, const CatalogName *cName, Boolean isHFSPlus, CatalogKey *key)
        !           499: {
        !           500:        if ( isHFSPlus )
        !           501:        {
        !           502:                key->hfsPlus.keyLength                  = kHFSPlusCatalogKeyMinimumLength;      // initial key length (4 + 2)
        !           503:                key->hfsPlus.parentID                   = parentID;             // set parent ID
        !           504:                key->hfsPlus.nodeName.length    = 0;                    // null CName length
        !           505:                if ( cName != NULL )
        !           506:                {
        !           507:                        CopyCatalogName(cName, (CatalogName *) &key->hfsPlus.nodeName, isHFSPlus);
        !           508:                        key->hfsPlus.keyLength += sizeof(UniChar) * cName->ustr.length; // add CName size to key length
        !           509:                }
        !           510:        }
        !           511:        else
        !           512:        {
        !           513:                key->hfs.keyLength              = kHFSCatalogKeyMinimumLength;  // initial key length (1 + 4 + 1)
        !           514:                key->hfs.reserved               = 0;                            // clear unused byte
        !           515:                key->hfs.parentID               = parentID;                     // set parent ID
        !           516:                key->hfs.nodeName[0]    = 0;                            // null CName length
        !           517:                if ( cName != NULL )
        !           518:                {
        !           519:                        UpdateCatalogName(cName->pstr, key->hfs.nodeName);
        !           520:                        key->hfs.keyLength += key->hfs.nodeName[0];             // add CName size to key length
        !           521:                }
        !           522:        }
        !           523: }
        !           524: 
        !           525: /*
        !           526:  * for HFS, only MacRoman is supported. If a non-MacRoman character is found, an error is returned
        !           527:  */
        !           528: OSErr
        !           529: BuildCatalogKeyUTF8(HFSCatalogNodeID parentID, const char *name,
        !           530:                                Boolean isHFSPlus, CatalogKey *key, UInt32 *textEncoding)
        !           531: {
        !           532:        OSErr err = 0;
        !           533:        UInt32 nameLength;
        !           534: 
        !           535:        if ( name != NULL )
        !           536:                nameLength = strlen(name);
        !           537:        else
        !           538:                nameLength = 0;
        !           539: 
        !           540:        if (nameLength > NAME_MAX)
        !           541:                err = bdNamErr; /* name is too long */
        !           542: 
        !           543:        if ( isHFSPlus ) {
        !           544:                ByteCount unicodeBytes = 0;
        !           545: 
        !           546:                key->hfsPlus.keyLength = kHFSPlusCatalogKeyMinimumLength;       // initial key length (4 + 2)
        !           547:                key->hfsPlus.parentID = parentID;                       // set parent ID
        !           548:                key->hfsPlus.nodeName.length = 0;                       // null CName length
        !           549:                if ( nameLength > 0 ) {
        !           550:                        err = ConvertUTF8ToUnicode(nameLength, name, sizeof(key->hfsPlus.nodeName.unicode),
        !           551:                                                                &unicodeBytes, key->hfsPlus.nodeName.unicode);
        !           552:                        key->hfsPlus.nodeName.length = unicodeBytes / sizeof(UniChar);
        !           553:                        key->hfsPlus.keyLength += unicodeBytes;
        !           554:                }
        !           555: 
        !           556:                ExtractTextEncoding(key->hfsPlus.nodeName.length, key->hfsPlus.nodeName.unicode, textEncoding);
        !           557:        }
        !           558:        else {
        !           559:                key->hfs.keyLength              = kHFSCatalogKeyMinimumLength;  // initial key length (1 + 4 + 1)
        !           560:                key->hfs.reserved               = 0;                            // clear unused byte
        !           561:                key->hfs.parentID               = parentID;                     // set parent ID
        !           562:                key->hfs.nodeName[0]    = 0;                            // null CName length
        !           563:                if ( nameLength > 0 ) {
        !           564:                        err = ConvertUTF8ToMacRoman(nameLength, name, &key->hfs.nodeName[0]);
        !           565:                        key->hfs.keyLength += key->hfs.nodeName[0];             // add CName size to key length
        !           566:                }
        !           567:                *textEncoding = 0;
        !           568:        }
        !           569: 
        !           570:        if (err) {
        !           571:                if (err == kTECOutputBufferFullStatus)
        !           572:                        err = bdNamErr; /* name is too long */
        !           573:                else
        !           574:                        err = paramErr; /* name has invalid characters */
        !           575:        }
        !           576: 
        !           577:        return err;
        !           578: }
        !           579: 
        !           580: 
        !           581: /*
        !           582:  * make a guess at the text encoding value that coresponds to the Unicode characters
        !           583:  */
        !           584: static void
        !           585: ExtractTextEncoding(ItemCount length, ConstUniCharArrayPtr string, UInt32 * textEncoding)
        !           586: {
        !           587:        int i;
        !           588:        UniChar ch;
        !           589: 
        !           590:        *textEncoding = 0;
        !           591: 
        !           592:        for (i = 0; i < length; ++i) {
        !           593:                ch = string[i];
        !           594:                /* CJK codepoints are 0x3000 thru 0x9FFF */
        !           595:                if (ch >= 0x3000) {
        !           596:                        if (ch < 0xa000) {
        !           597:                                *textEncoding = kTextEncodingMacJapanese;
        !           598:                                break;
        !           599:                        }
        !           600: 
        !           601:                        /* fullwidth character codepoints are 0xFF00 thru 0xFFEF */
        !           602:                        if (ch >= 0xff00 && ch <= 0xffef) {
        !           603:                                *textEncoding = kTextEncodingMacJapanese;
        !           604:                                break;  
        !           605:                        }
        !           606:                }
        !           607:        }
        !           608: }
        !           609: 
        !           610: 
        !           611: //�������������������������������������������������������������������������������
        !           612: //     Routine:        FlushCatalog
        !           613: //
        !           614: // Function:   Flushes the catalog for a specified volume.
        !           615: //
        !           616: //�������������������������������������������������������������������������������
        !           617: 
        !           618: OSErr
        !           619: FlushCatalog(ExtendedVCB *volume)
        !           620: {
        !           621:        FCB *   fcb;
        !           622:        OSErr   result;
        !           623:        
        !           624:        fcb = GetFileControlBlock(volume->catalogRefNum);
        !           625:        result = BTFlushPath(fcb);
        !           626: 
        !           627:        if (result == noErr)
        !           628:        {
        !           629:                //--- check if catalog's fcb is dirty...
        !           630:                
        !           631:                if ( fcb->fcbFlags & fcbModifiedMask )
        !           632:                {
        !           633:                        VCB_LOCK(volume);
        !           634:                        volume->vcbFlags |= 0xFF00;                     // Mark the VCB dirty
        !           635:                        volume->vcbLsMod = GetTimeLocal(volume->vcbSigWord == kHFSSigWord);     // update last modified date
        !           636:                        VCB_UNLOCK(volume);
        !           637: 
        !           638:                        result = FlushVolumeControlBlock(volume);
        !           639:                }
        !           640:        }
        !           641:        
        !           642:        return result;
        !           643: }
        !           644: 
        !           645: 
        !           646: //�������������������������������������������������������������������������������
        !           647: //     Routine:        InvalidateCatalogNodeCache
        !           648: //
        !           649: //     Function:       Invalidates the Catalog node cache if volume and folderID match
        !           650: //
        !           651: //�������������������������������������������������������������������������������
        !           652: #if TARGET_OS_MAC
        !           653: void
        !           654: InvalidateCatalogNodeCache(ExtendedVCB *volume, HFSCatalogNodeID parentID)
        !           655: {
        !           656:        FSVarsRec       *fsVars;
        !           657: 
        !           658:        fsVars = (FSVarsRec*) LMGetFSMVars();
        !           659:        
        !           660:        if ( (fsVars->gCatalogFSSpec.parID == parentID) && (volume->vcbVRefNum == fsVars->gCatalogFSSpec.vRefNum) )
        !           661:        {
        !           662:                fsVars->gCatalogFSSpec.parID = 0;
        !           663:                fsVars->gCatalogFSSpec.vRefNum = 0;
        !           664:        }
        !           665: }
        !           666: #endif
        !           667: 
        !           668: //�������������������������������������������������������������������������������
        !           669: //     Routine:        TrashCatalogNodeCache
        !           670: //
        !           671: //     Function:       Invalidates the Catalog node cache.
        !           672: //
        !           673: //�������������������������������������������������������������������������������
        !           674: #if TARGET_OS_MAC
        !           675: void
        !           676: TrashCatalogNodeCache( void )
        !           677: {
        !           678:        FSVarsRec       *fsVars = (FSVarsRec*) LMGetFSMVars();
        !           679:        
        !           680:        fsVars->gCatalogFSSpec.parID    = 0;
        !           681:        fsVars->gCatalogFSSpec.vRefNum  = 0;
        !           682: }
        !           683: #endif
        !           684: 
        !           685: 
        !           686: //�������������������������������������������������������������������������������
        !           687: //     Routine:        UpdateCatalogName
        !           688: //
        !           689: //     Function:       Updates a CName.
        !           690: //
        !           691: //�������������������������������������������������������������������������������
        !           692: 
        !           693: void
        !           694: UpdateCatalogName(ConstStr31Param srcName, Str31 destName)
        !           695: {
        !           696:        Size length = srcName[0];
        !           697:        
        !           698:        if (length > CMMaxCName)
        !           699:                length = CMMaxCName;                            // truncate to max
        !           700: 
        !           701:        destName[0] = length;                                   // set length byte
        !           702:        
        !           703:        BlockMoveData(&srcName[1], &destName[1], length);
        !           704: }
        !           705: 
        !           706: 
        !           707: //�������������������������������������������������������������������������������
        !           708: //     Routine:        AdjustVolumeCounts
        !           709: //
        !           710: //     Function:       Adjusts the folder and file counts in the VCB
        !           711: //
        !           712: //�������������������������������������������������������������������������������
        !           713: 
        !           714: void
        !           715: AdjustVolumeCounts(ExtendedVCB *volume, SInt16 type, SInt16 delta)
        !           716: {
        !           717:        //�� also update extended VCB fields...
        !           718: 
        !           719:        VCB_LOCK(volume);
        !           720: 
        !           721:        if (type == kHFSFolderRecord || type == kHFSPlusFolderRecord)
        !           722:                volume->vcbDirCnt += delta;                     // adjust volume folder count, �� worry about overflow?
        !           723:        else
        !           724:                volume->vcbFilCnt += delta;                     // adjust volume file count
        !           725:        
        !           726:        volume->vcbFlags |= 0xFF00;                     // Mark the VCB dirty
        !           727:        volume->vcbLsMod = GetTimeLocal(volume->vcbSigWord == kHFSSigWord);     // update last modified date
        !           728: 
        !           729:        VCB_UNLOCK(volume);
        !           730: }
        !           731: 
        !           732: 
        !           733: //�������������������������������������������������������������������������������
        !           734: 
        !           735: void
        !           736: UpdateVolumeEncodings(ExtendedVCB *volume, TextEncoding encoding)
        !           737: {
        !           738:        UInt32  index;
        !           739: 
        !           740:        encoding &= 0x7F;
        !           741:        
        !           742:        index = MapEncodingToIndex(encoding);
        !           743: 
        !           744:        VCB_LOCK(volume);
        !           745: 
        !           746:        if ( index < 32 )
        !           747:                volume->encodingsBitmap.lo |= (1 << index);
        !           748:        else
        !           749:                volume->encodingsBitmap.hi |= (1 << (index - 32));
        !           750: 
        !           751:        VCB_UNLOCK(volume);
        !           752:                
        !           753:        // vcb should already be marked dirty
        !           754: }
        !           755: 
        !           756: 
        !           757: //�������������������������������������������������������������������������������
        !           758: 
        !           759: OSErr
        !           760: UpdateFolderCount( ExtendedVCB *volume, HFSCatalogNodeID parentID, const CatalogName *name, SInt16 newType,
        !           761:                                        UInt32 hint, SInt16 valenceDelta)
        !           762: {
        !           763:        CatalogKey                      tempKey;        // 518 bytes
        !           764:        CatalogRecord           tempData;       // 520 bytes
        !           765:        UInt32                          tempHint;
        !           766:        HFSCatalogNodeID        folderID;
        !           767:        UInt16                          recordSize;
        !           768:        OSErr                           result;
        !           769: 
        !           770: #if 0
        !           771:        result = SearchBTreeRecord(volume->catalogRefNum, parentKey, hint,
        !           772:                                                                &tempKey, &tempData, &recordSize, &tempHint);
        !           773:        if (result)
        !           774:                return (result == btNotFound ? cmNotFound : result);    
        !           775: #else
        !           776: 
        !           777:        result = LocateCatalogNode(volume, parentID, name, hint, &tempKey, &tempData, &tempHint);
        !           778:        ReturnIfError(result);
        !           779: #endif
        !           780: 
        !           781:        if ( volume->vcbSigWord == kHFSPlusSigWord ) // HFS Plus
        !           782:        {
        !           783:                UInt32          timeStamp;
        !           784:                
        !           785:                if ( DEBUG_BUILD && tempData.recordType != kHFSPlusFolderRecord )
        !           786:                        DebugStr("\p UpdateFolder: found HFS folder on HFS+ volume!");
        !           787: 
        !           788:                timeStamp = GetTimeUTC();
        !           789:                tempData.hfsPlusFolder.valence += valenceDelta;         // adjust valence
        !           790:                tempData.hfsPlusFolder.contentModDate = timeStamp;      // set date/time last modified
        !           791:                folderID = tempData.hfsPlusFolder.folderID;
        !           792:                recordSize = sizeof(tempData.hfsPlusFolder);
        !           793:        }
        !           794:        else // classic HFS
        !           795:        {
        !           796:                if ( DEBUG_BUILD && tempData.recordType != kHFSFolderRecord )
        !           797:                        DebugStr("\p UpdateFolder: found HFS+ folder on HFS volume!");
        !           798: 
        !           799:                tempData.hfsFolder.valence += valenceDelta;                             // adjust valence
        !           800:                tempData.hfsFolder.modifyDate = GetTimeLocal(true);             // set date/time last modified
        !           801:                folderID = tempData.hfsFolder.folderID;
        !           802:                recordSize = sizeof(tempData.hfsFolder);
        !           803:        }
        !           804:        
        !           805:        result = ReplaceBTreeRecord(volume->catalogRefNum, &tempKey, tempHint,
        !           806:                                                                &tempData, recordSize, &tempHint);
        !           807:        ReturnIfError(result);
        !           808: 
        !           809:        if ( folderID == kHFSRootFolderID )
        !           810:        {
        !           811:                if (newType == kHFSFolderRecord || newType == kHFSPlusFolderRecord)
        !           812:                {
        !           813:                        VCB_LOCK(volume);
        !           814:                        volume->vcbNmRtDirs += valenceDelta;    // adjust root folder count (undefined for HFS Plus)
        !           815:                        VCB_UNLOCK(volume);
        !           816:                }
        !           817:                else
        !           818:                {
        !           819:                        VCB_LOCK(volume);
        !           820:                        volume->vcbNmFls += valenceDelta;               // adjust root file count (used by GetVolInfo)
        !           821:                        VCB_UNLOCK(volume);
        !           822:                }
        !           823:        }
        !           824: 
        !           825:        //XXX also update extended VCB fields...
        !           826: 
        !           827:        return result;
        !           828: }
        !           829: 
        !           830: 
        !           831: //�������������������������������������������������������������������������������
        !           832: 
        !           833: UInt16 
        !           834: GetCatalogRecordSize(const CatalogRecord *dataRecord)
        !           835: {
        !           836:        switch (dataRecord->recordType)
        !           837:        {
        !           838:                case kHFSFileRecord:
        !           839:                        return sizeof(HFSCatalogFile);
        !           840: 
        !           841:                case kHFSFolderRecord:
        !           842:                        return sizeof(HFSCatalogFolder);
        !           843: 
        !           844:                case kHFSPlusFileRecord:
        !           845:                        return sizeof(HFSPlusCatalogFile);
        !           846: 
        !           847:                case kHFSPlusFolderRecord:
        !           848:                        return sizeof(HFSPlusCatalogFolder);
        !           849:                        
        !           850:                case kHFSFolderThreadRecord:
        !           851:                case kHFSFileThreadRecord:
        !           852:                        return sizeof(HFSCatalogThread);
        !           853: 
        !           854:                case kHFSPlusFolderThreadRecord:
        !           855:                case kHFSPlusFileThreadRecord:
        !           856:                        return sizeof(HFSPlusCatalogThread);
        !           857: 
        !           858:                default:
        !           859:                        return 0;
        !           860:        }
        !           861: }
        !           862: 
        !           863: 
        !           864: //�������������������������������������������������������������������������������
        !           865: 
        !           866: void
        !           867: CopyCatalogNodeData(const ExtendedVCB *volume, const CatalogRecord *dataPtr, CatalogNodeData *nodeData)
        !           868: {      
        !           869:        switch (dataPtr->recordType)
        !           870:        {
        !           871:                case kHFSFolderRecord:
        !           872:                {
        !           873:                        nodeData->nodeType                      = kCatalogFolderNode;
        !           874:                        nodeData->nodeFlags                     = dataPtr->hfsFolder.flags;
        !           875:                        nodeData->nodeID                        = dataPtr->hfsFolder.folderID;
        !           876:                        nodeData->createDate            = dataPtr->hfsFolder.createDate;
        !           877:                        nodeData->contentModDate        = dataPtr->hfsFolder.modifyDate;
        !           878:                        nodeData->backupDate            = dataPtr->hfsFolder.backupDate;
        !           879:                        nodeData->valence                       = dataPtr->hfsFolder.valence;
        !           880: 
        !           881:                        BlockMoveData(&dataPtr->hfsFolder.userInfo, &nodeData->finderInfo, 32);         // copy 32 bytes of finder data 
        !           882:                        break;
        !           883:                }
        !           884: 
        !           885:                case kHFSFileRecord:
        !           886:                {
        !           887:                        UInt32  i;
        !           888: 
        !           889:                        nodeData->nodeType                      = kCatalogFileNode;
        !           890:                        nodeData->nodeFlags                     = dataPtr->hfsFile.flags;
        !           891:                        nodeData->nodeID                        = dataPtr->hfsFile.fileID;
        !           892:                        nodeData->createDate            = dataPtr->hfsFile.createDate;
        !           893:                        nodeData->contentModDate        = dataPtr->hfsFile.modifyDate;
        !           894:                        nodeData->backupDate            = dataPtr->hfsFile.backupDate;
        !           895:                        nodeData->valence                       = 0;
        !           896:        
        !           897:                        BlockMoveData(&dataPtr->hfsFile.userInfo, &nodeData->finderInfo, 16);           // copy finder data
        !           898:                        BlockMoveData(&dataPtr->hfsFile.finderInfo, &nodeData->extFinderInfo, 16);      // copy finder data
        !           899: 
        !           900:                        nodeData->dataLogicalSize  = dataPtr->hfsFile.dataLogicalSize;
        !           901:                        nodeData->dataPhysicalSize = dataPtr->hfsFile.dataPhysicalSize;
        !           902:                        nodeData->rsrcLogicalSize  = dataPtr->hfsFile.rsrcLogicalSize;
        !           903:                        nodeData->rsrcPhysicalSize = dataPtr->hfsFile.rsrcPhysicalSize;
        !           904: 
        !           905:                        for (i = 0; i < kHFSExtentDensity; ++i)
        !           906:                        {
        !           907:                                nodeData->dataExtents[i].startBlock = (UInt32) (dataPtr->hfsFile.dataExtents[i].startBlock);
        !           908:                                nodeData->dataExtents[i].blockCount = (UInt32) (dataPtr->hfsFile.dataExtents[i].blockCount);
        !           909: 
        !           910:                                nodeData->rsrcExtents[i].startBlock = (UInt32) (dataPtr->hfsFile.rsrcExtents[i].startBlock);
        !           911:                                nodeData->rsrcExtents[i].blockCount = (UInt32) (dataPtr->hfsFile.rsrcExtents[i].blockCount);
        !           912:                        }
        !           913:                        break;
        !           914:                }
        !           915: 
        !           916:                case kHFSPlusFolderRecord:
        !           917:                {
        !           918:                        nodeData->nodeType                      = kCatalogFolderNode;
        !           919:                        nodeData->nodeFlags                     = dataPtr->hfsPlusFolder.flags;
        !           920:                        nodeData->nodeID                        = dataPtr->hfsPlusFolder.folderID;
        !           921:                        nodeData->textEncoding          = dataPtr->hfsPlusFolder.textEncoding;
        !           922:                        nodeData->createDate            = UTCToLocal(dataPtr->hfsPlusFolder.createDate);
        !           923:                        nodeData->contentModDate        = UTCToLocal(dataPtr->hfsPlusFolder.contentModDate);
        !           924:                        nodeData->backupDate            = UTCToLocal(dataPtr->hfsPlusFolder.backupDate);
        !           925:                        if (dataPtr->hfsPlusFolder.valence > 0xffff)
        !           926:                                nodeData->valence = 0xffff;             // pass maximum 16-bit value
        !           927:                        else
        !           928:                                nodeData->valence = dataPtr->hfsPlusFolder.valence;
        !           929: 
        !           930:                        BlockMoveData(&dataPtr->hfsPlusFolder.userInfo, &nodeData->finderInfo, 32);     // copy finder data
        !           931: #if TARGET_OS_RHAPSODY
        !           932:             nodeData->accessDate               = UTCToLocal(dataPtr->hfsPlusFolder.accessDate);
        !           933:             nodeData->attributeModDate         = UTCToLocal(dataPtr->hfsPlusFolder.attributeModDate);
        !           934:             nodeData->permissions              = dataPtr->hfsPlusFolder.permissions; 
        !           935: #endif
        !           936:                        break;
        !           937:                }
        !           938: 
        !           939:                case kHFSPlusFileRecord:
        !           940:                {
        !           941:                        UInt32  largestFileSizeUnder2Gig;
        !           942:                        
        !           943:                        nodeData->nodeType                      = kCatalogFileNode;
        !           944:                        nodeData->nodeFlags                     = dataPtr->hfsPlusFile.flags;
        !           945:                        nodeData->nodeID                        = dataPtr->hfsPlusFile.fileID;
        !           946:                        nodeData->textEncoding          = dataPtr->hfsPlusFile.textEncoding;
        !           947:                        nodeData->createDate            = UTCToLocal(dataPtr->hfsPlusFile.createDate);
        !           948:                        nodeData->contentModDate        = UTCToLocal(dataPtr->hfsPlusFile.contentModDate);
        !           949:                        nodeData->backupDate            = UTCToLocal(dataPtr->hfsPlusFile.backupDate);
        !           950:                        nodeData->valence                       = 0;
        !           951: 
        !           952:                        BlockMoveData(&dataPtr->hfsPlusFile.userInfo, &nodeData->finderInfo, 32);       // copy finder data
        !           953:                
        !           954:                        //      2201501, Pin values to 2^31-1 (SInt32)
        !           955:                        largestFileSizeUnder2Gig        =  (0x7FFFFFFF / volume->blockSize) * volume->blockSize;
        !           956:                        
        !           957:                        if ( (dataPtr->hfsPlusFile.dataFork.logicalSize.hi == 0) && (dataPtr->hfsPlusFile.dataFork.logicalSize.lo <= largestFileSizeUnder2Gig) )
        !           958:                        {
        !           959:                                nodeData->dataLogicalSize       = dataPtr->hfsPlusFile.dataFork.logicalSize.lo;
        !           960:                                nodeData->dataPhysicalSize      = (dataPtr->hfsPlusFile.dataFork.totalBlocks * volume->blockSize);
        !           961:                        }
        !           962:                        else
        !           963:                        {
        !           964:                                nodeData->dataPhysicalSize      =  largestFileSizeUnder2Gig;
        !           965:                                nodeData->dataLogicalSize       =  nodeData->dataPhysicalSize;          // signal to Open that this file is too big
        !           966:                                nodeData->valence                       |= kLargeDataForkMask;                          // overload the valence for files over 2Gig
        !           967:                        }
        !           968: 
        !           969:                        if ( (dataPtr->hfsPlusFile.resourceFork.logicalSize.hi == 0) && (dataPtr->hfsPlusFile.resourceFork.logicalSize.lo <= largestFileSizeUnder2Gig) )
        !           970:                        {
        !           971:                                nodeData->rsrcLogicalSize       = dataPtr->hfsPlusFile.resourceFork.logicalSize.lo;
        !           972:                                nodeData->rsrcPhysicalSize      = (SInt32) ((SInt32)dataPtr->hfsPlusFile.resourceFork.totalBlocks * (SInt32)volume->blockSize);
        !           973:                        }
        !           974:                        else
        !           975:                        {
        !           976:                                nodeData->rsrcPhysicalSize      =  largestFileSizeUnder2Gig;
        !           977:                                nodeData->rsrcLogicalSize       =  nodeData->rsrcPhysicalSize;          // signal to Open that this file is too big
        !           978:                                nodeData->valence                       |= kLargeRsrcForkMask;                          // overload the valence for files over 2Gig
        !           979:                        }
        !           980: 
        !           981:                        // copy data and rsrc extents
        !           982:                        BlockMoveData(&dataPtr->hfsPlusFile.dataFork.extents, &nodeData->dataExtents, sizeof(HFSPlusExtentRecord));
        !           983:                        BlockMoveData(&dataPtr->hfsPlusFile.resourceFork.extents, &nodeData->rsrcExtents, sizeof(HFSPlusExtentRecord));
        !           984: #if TARGET_OS_RHAPSODY
        !           985:             nodeData->accessDate               = UTCToLocal(dataPtr->hfsPlusFile.accessDate);
        !           986:             nodeData->attributeModDate         = UTCToLocal(dataPtr->hfsPlusFile.attributeModDate);
        !           987:             nodeData->permissions              = dataPtr->hfsPlusFile.permissions;
        !           988: #endif
        !           989:                        break;
        !           990:                }
        !           991:                
        !           992:                default:
        !           993:                        nodeData->nodeType = '????';    // must have hit a thread record
        !           994:        }
        !           995: }
        !           996: 
        !           997: 
        !           998: //�������������������������������������������������������������������������������
        !           999: #if 0
        !          1000: OSErr
        !          1001: PrepareInputName(ConstStr31Param name, Boolean unicode, TextEncoding encoding, CatalogName *catalogName)
        !          1002: {
        !          1003:        OSErr   result = noErr;
        !          1004:        
        !          1005:        if (name == NULL)
        !          1006:        {
        !          1007:                catalogName->ustr.length = 0;   // set length byte (works for both unicode and pascal)
        !          1008:        }
        !          1009:        else
        !          1010:        {
        !          1011:                Size length = name[0];
        !          1012:        
        !          1013:                if (length > CMMaxCName)
        !          1014:                        length = CMMaxCName;    // truncate to max
        !          1015:                        
        !          1016:                if ( length == 0 )
        !          1017:                {
        !          1018:                        catalogName->ustr.length = 0;
        !          1019:                }
        !          1020:                else if (unicode)
        !          1021:                {
        !          1022:                        Str31           truncatedName;
        !          1023:                        StringPtr       pName;
        !          1024:        
        !          1025:                        if (name[0] <= CMMaxCName)      //�� should be CMMaxCName
        !          1026:                        {
        !          1027:                                pName = (StringPtr)name;
        !          1028:                        }
        !          1029:                        else
        !          1030:                        {
        !          1031:                                BlockMoveData(&name[1], &truncatedName[1], CMMaxCName);
        !          1032:                                truncatedName[0] = CMMaxCName;
        !          1033:                                pName = truncatedName;
        !          1034:                        }
        !          1035:        
        !          1036:                        //���need to pass pascal string length (could be clipped above)
        !          1037:                        result = ConvertHFSNameToUnicode (      pName, encoding, &catalogName->ustr );
        !          1038:                }
        !          1039:                else
        !          1040:                {
        !          1041:                        BlockMoveData(&name[1], &catalogName->pstr[1], length);
        !          1042:                        catalogName->pstr[0] = length;                                  // set length byte (might be smaller than name[0]
        !          1043:                }
        !          1044:        }
        !          1045:        
        !          1046:        return result;
        !          1047: }
        !          1048: #endif
        !          1049: 
        !          1050: //_______________________________________________________________________
        !          1051: 
        !          1052: #if 0
        !          1053: void
        !          1054: ConvertInputNameToUnicode(ConstStr31Param name, TextEncoding encodingHint, TextEncoding *actualEncoding, CatalogName *catalogName)
        !          1055: {
        !          1056:        Size            length;
        !          1057:        OSErr           result;
        !          1058:        
        !          1059:        catalogName->ustr.length = 0;   // setup defaults...
        !          1060:        *actualEncoding = encodingHint;
        !          1061: 
        !          1062:        if (name == NULL)
        !          1063:                return;         // catalogName is empty string
        !          1064: 
        !          1065:        length = name[0];
        !          1066: 
        !          1067:        if (length == 0 || length > CMMaxCName)
        !          1068:                return;         // catalogName is empty string
        !          1069: 
        !          1070:        result = ConvertHFSNameToUnicode ( name, encodingHint, &catalogName->ustr );
        !          1071:        
        !          1072:        if (result != noErr)
        !          1073:        {
        !          1074:                // The converter didn't like our string, try again with roman encoding
        !          1075:                // This takes care of errors like:      kTextMalformedInputErr
        !          1076:                //                                                                      kTECPartialCharErr
        !          1077:                //                                                                      kTECUnmappableElementErr
        !          1078:                //                                                                      kTECIncompleteElementErr
        !          1079:                //
        !          1080:                if ( encodingHint != kTextEncodingMacRoman )
        !          1081:                {
        !          1082:                        *actualEncoding = kTextEncodingMacRoman;
        !          1083:                        result = ConvertHFSNameToUnicode ( name, kTextEncodingMacRoman, &catalogName->ustr );
        !          1084:                        
        !          1085:                }
        !          1086: 
        !          1087:                if (DEBUG_BUILD && result != noErr)
        !          1088:                        DebugStr("\p ConvertHFSNameToUnicode could not convert string!");
        !          1089:        }
        !          1090: }
        !          1091: #endif
        !          1092: 
        !          1093: //_______________________________________________________________________
        !          1094: 
        !          1095: void
        !          1096: CopyCatalogName(const CatalogName *srcName, CatalogName *dstName, Boolean isHFSPLus)
        !          1097: {
        !          1098:        UInt32  length;
        !          1099:        
        !          1100:        if ( srcName == NULL )
        !          1101:        {
        !          1102:                if ( dstName != NULL )
        !          1103:                        dstName->ustr.length = 0;       // set length byte to zero (works for both unicode and pascal)          
        !          1104:                return;
        !          1105:        }
        !          1106:        
        !          1107:        if (isHFSPLus)
        !          1108:                length = sizeof(UniChar) * (srcName->ustr.length + 1);
        !          1109:        else
        !          1110:                length = sizeof(UInt8) + srcName->pstr[0];
        !          1111: 
        !          1112:        if ( length > 1 )
        !          1113:                BlockMoveData(srcName, dstName, length);
        !          1114:        else
        !          1115:                dstName->ustr.length = 0;       // set length byte to zero (works for both unicode and pascal)          
        !          1116: }
        !          1117: 
        !          1118: //_______________________________________________________________________
        !          1119: 
        !          1120: UInt32
        !          1121: CatalogNameLength(const CatalogName *name, Boolean isHFSPlus)
        !          1122: {
        !          1123:        if (isHFSPlus)
        !          1124:                return name->ustr.length;
        !          1125:        else
        !          1126:                return name->pstr[0];
        !          1127: }
        !          1128: 
        !          1129: 
        !          1130: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.