Annotation of kernel/bsd/hfs/hfscommon/Catalog/CatalogUtilities.c, revision 1.1.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.