Annotation of kernel/bsd/hfs/hfscommon/Catalog/CatSearch.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:           CatSearch.c
                     27: 
                     28:        Contains:       CatSearch (fast search of all files on a volume)
                     29: 
                     30:        Version:        System 7.5.x (Tempo?)
                     31: 
                     32:        Copyright:      � 1996-1997 by Apple Computer, Inc., all rights reserved.
                     33: 
                     34:        File Ownership:
                     35: 
                     36:                DRI:                            Mark Day
                     37: 
                     38:                Other Contact:          Don Brady
                     39: 
                     40:                Technology:                     HFS+
                     41: 
                     42:        Writers:
                     43: 
                     44:                (JL)    Jim Luther
                     45:                (RNP)   Roger Pantos
                     46:                (DSH)   Deric Horn
                     47:                (djb)   Don Brady
                     48:                (msd)   Mark Day
                     49: 
                     50:        Change History (most recent first):
                     51:          <Rhap>        03/31/98        djb             Sync up with final HFSVolumes.h header file.
                     52: 
                     53:                                4/14/98         DSH             Now also compile some compare routines for Rhapsody for use in searchfs().
                     54:          <CS18>        11/3/97         JL              #2001483 - Return WDCBRecPtr from CatSearchC.
                     55:          <CS17>        10/19/97        msd             Bug 1684586. GetCatInfo and SetCatInfo use only contentModDate.
                     56:          <CS16>        10/17/97        msd             Conditionalize DebugStrs.
                     57:          <CS15>        10/10/97        msd             Bug 1683670. InitCatSearch was calling the wrong routine to
                     58:                                                                        flush the volume; only the user files were getting flushed.
                     59:                                                                        Added casts to Ptr for first parameter to UprText.
                     60:          <CS14>         9/27/97        RNP             Replace UprString() with UprText().
                     61:          <CS13>          9/9/97        msd             The PLstrcmp routine we link against has a bug with one
                     62:                                                                        character strings, so just call our own PascalBinaryCompare
                     63:                                                                        instead.
                     64:          <CS12>          9/4/97        msd             In CatalogNodeData, change attributeModDate to modifyDate.
                     65:          <CS11>         7/28/97        msd             Use fast new B-Tree scanner.
                     66:          <CS10>         7/23/97        msd             Radar #1668914. CatSearch should compare the file's backup date
                     67:                                                                        with the search info's backup date range, not the create date
                     68:                                                                        range. The mod date compare had the same problem.
                     69:           <CS9>         7/16/97        DSH             FilesInternal.i renamed FileMgrInternal.i to avoid name
                     70:                                                                        collision
                     71:           <CS8>          7/8/97        DSH             Loading PrecompiledHeaders from define passed in on C line
                     72:           <CS7>         6/24/97        djb             Include "CatalogInternal.h"
                     73:           <CS6>         6/20/97        msd             Use contentModDate and attributeModDate fields instead of
                     74:                                                                        modifyDate. Use CatalogNodeData as common record format. Got rid
                     75:                                                                        of NEW_CATSEARCH define by removing old code.
                     76:           <CS5>         6/17/97        msd             Bug #1661443. Initialize cat position to parent dirID =
                     77:                                                                        fsRtParID. When restoring a cat position, special case that
                     78:                                                                        parent ID since there is no such thread record. If ioSearchTime
                     79:                                                                        is -1, assume they meant infinite, and use 0 instead. The call
                     80:                                                                        to ConvertUnicodeToHFSName in CheckCriteria was getting
                     81:                                                                        parameters from the wrong places.
                     82:                 <4>     6/13/97        djb             Change PrepareOutputName calls to ConvertUnicodeToHFSName calls.
                     83:           <CS3>          6/9/97        msd             Convert HFS Plus dates from UTC to local time in MakeCatDirRec
                     84:                                                                        and MakeCatFilRec.
                     85:           <CS2>         5/16/97        msd             Fix some string type conversion problems in InsertMatch().
                     86:           <CS1>         4/24/97        djb             first checked in
                     87:         <HFS22>         4/16/97        djb             Always use new B-tree code.
                     88:         <HFS21>         4/11/97        DSH             use extended VCB fields catalogRefNum, and extentsRefNum.
                     89:         <HFS20>         3/27/97        djb             Unicode string lengths are now passed as a byte count.
                     90:         <HFS19>         2/19/97        djb             Get in sync with new B-tree definitions...
                     91:         <HFS18>          2/6/97        msd             When instrumentation is active, log a complete FSSpec when a
                     92:                                                                        match is inserted into the buffer.
                     93:         <HFS17>          2/5/97        msd             On HFS+ disks, CheckCriteria needs to test against the HFS-style
                     94:                                                                        copy of the catalog record rather than the HFS variants of the
                     95:                                                                        CatalogRecord of the actual catalog data.
                     96:         <HFS16>         1/29/97        msd             InitCatSearch needs to preset the BTree position by searching
                     97:                                                                        for a node before the directory record of the root so that the
                     98:                                                                        root will be searched, too.
                     99:         <HFS15>         1/29/97        msd             CheckCriteria was ignoring the fsSBNegate bit when testing the
                    100:                                                                        ioDirMask bit in the file attributes. Made sure that thread
                    101:                                                                        records never match.
                    102:         <HFS14>         1/17/97        msd             Add trivial instrumentation.
                    103:         <HFS13>         1/16/97        msd             When using the new BTree manager, the old btcWCount field is
                    104:                                                                        always zero, so use numUpdateNodes instead. However,
                    105:                                                                        numUpdateNodes can be zero so use numUpdateNodes+1 instead; this
                    106:                                                                        still allows the caller to set the writeCount in the
                    107:                                                                        CatPositionRec to zero to indicate a new search.
                    108:         <HFS12>          1/9/97        djb             Get in sync with new HFSVolumesPriv.i..
                    109:         <HFS11>          1/9/97        msd             The CatPosition was not being updated during or after the call.
                    110:                                                                        Also, InitCatSearch was going back to the root directory instead
                    111:                                                                        of the parent directory specified in the CatPosition.
                    112:                                                                        InitCatSearch should not use GetCatalogNode; it should use
                    113:                                                                        SearchBTreeRecord instead since we want to be able to find
                    114:                                                                        thread records and move relative to them.
                    115:         <HFS10>          1/3/97        djb             Integrated latest HFSVolumesPriv.h changes.
                    116:          <HFS9>        12/23/96        msd             Oops. Re-enable timers.
                    117:          <HFS8>        12/23/96        msd             Update to use new BTree interfaces. Conditionalized the code via
                    118:                                                                        the NEW_CATSEARCH symbol. The code should compile both ways, but
                    119:                                                                        should be cleaned up later. There is a DebugStr in case the
                    120:                                                                        BTree returns an unexpected error. Performance is noticably
                    121:                                                                        worse than the prior implementation.
                    122:          <HFS7>        12/19/96        DSH             All refs to VCB are now refs to ExtendedVCB
                    123:          <HFS6>        12/18/96        msd             Use PrepareOutputName when copying a found item's name into
                    124:                                                                        FSSpec array.
                    125:          <HFS5>        12/12/96        msd             Use the Unicode wrapper functions.
                    126:          <HFS4>        12/10/96        msd             First version of HFS+ changes complete. The HFS+ catalog data is
                    127:                                                                        converted to a CatalogRecord before comparison. Copied code from
                    128:                                                                        Catalog.c for dealing with the Unicode names.
                    129:          <HFS3>        12/10/96        msd             Begin HFS+ changes.  Check PRAGMA_LOAD_SUPPORTED before loading
                    130:                                                                        precompiled headers.
                    131:          <HFS2>        12/10/96        msd             Add support for precompiled headers.
                    132:          <HFS1>         12/9/96        msd             first checked in
                    133: 
                    134: */
                    135: 
                    136: /*
                    137: Public routines:
                    138:        CatSearchC
                    139:                                        Searches the entire volume for files/folders matching given
                    140:                                        criteria.  It does this by reading every record in the Catalog
                    141:                                        BTree; all non-index records are compared to the given criteria.
                    142:                                        And files/folders that match have their FSSpec's returned
                    143:                                        in a caller-supplied buffer.  The caller may also provide a
                    144:                                        buffer to use when reading the BTree; otherwise, a default
                    145:                                        buffer within the File Manager is used.
                    146:        
                    147:        VerifyCatSearchPB
                    148:                                        Validates the parameters in a CatSearch parameter block to
                    149:                                        make sure the values are mutually consistent and in range.
                    150: 
                    151: Internal routines:
                    152:        ExtOffLineCheck
                    153:                                        Make sure the given volume is both online and HFS (or HFS+).
                    154:                                        If not, an appropriate error is returned.
                    155: 
                    156:        StartScan               Initialize state for scan and return first record.
                    157:        EndScan                 Cleanup state and return hint
                    158:        ScanNextRecord  Get the next record in the scan.
                    159: */
                    160: 
                    161: #if ( PRAGMA_LOAD_SUPPORTED )
                    162:         #pragma        load    PrecompiledHeaders
                    163: #else
                    164:         #if TARGET_OS_MAC
                    165:         #include <Timer.h>
                    166:         #include <TextUtils.h>
                    167:         #include <LowMemPriv.h>
                    168:         #include <PLStringFuncs.h>
                    169:         #else
                    170:         #include "../headers/system/MacOSStubs.h"
                    171:         #endif         /* TARGET_OS_MAC */
                    172: #endif /* PRAGMA_LOAD_SUPPORTED */
                    173: 
                    174: 
                    175: 
                    176: #include "../headers/HFSBtreesPriv.h"
                    177: #include "../headers/HFSVolumes.h"
                    178: #include "../headers/FileMgrInternal.h"
                    179: #include "../headers/system/HFSUnicodeWrappers.h"
                    180: #include "../headers/BTreesInternal.h"
                    181: #include "../headers/BTreesPrivate.h"
                    182: #include "../headers/BTreeScanner.h"
                    183: #include "../headers/CatalogPrivate.h"
                    184: 
                    185: #if HFSInstrumentation
                    186:        #include "../headers/system/Instrumentation.h"
                    187: #endif
                    188: 
                    189: 
                    190: #ifndef CATSEARCH_DEBUG
                    191: #define CATSEARCH_DEBUG 1
                    192: #endif
                    193: 
                    194: #define BTREE_CB_TYPE                          BTreeControlBlock
                    195: #define BTREE_WRITE_COUNT(btcb)                (btcb->numUpdateNodes+1)
                    196: 
                    197: extern OSErr VerifyCatSearchPB( const CSParam *pb, UInt8 *outAttributes, UInt8 *outFlags );
                    198: extern OSErr CatSearchC( CSParam *pb, WDCBRecPtr *wdcb );
                    199: extern OSErr ExtOffLineCheck( ExtendedVCB *vcb );
                    200: 
                    201: extern OSErr CheckExternalFileSystem( ExtendedVCB *vcb );
                    202: extern OSErr DeturmineVolume3( VolumeParam *iopb, short *nameLength, Boolean *nameSpecified, ExtendedVCB **vcb, WDCBRec **wdcb, unsigned char **pathName );
                    203: extern OSErr FlushVolume( ExtendedVCB *vcb );
                    204: extern OSErr   FlushVolumeBuffers( ExtendedVCB *vcb );
                    205: extern OSErr ChkNode_glue( BTNodeDescriptor *node, BTREE_CB_TYPE *btcb );
                    206: extern void LocRec_glue( BTNodeDescriptor *node, BTREE_CB_TYPE *btcb, UInt32 recordNumber,
                    207:                                                 Ptr *key, Ptr *data, UInt32 *recordSize );
                    208: 
                    209: //
                    210: //�� These need to be moved to an interface file
                    211: //
                    212: enum {
                    213:        kBTreePrevious  = -1,
                    214:        kBTreeCurrent   = 0,
                    215:        kBTreeNext              = 1
                    216:        
                    217: };
                    218: 
                    219: enum {
                    220:        //
                    221:        //      Masks for bits in the file attributes
                    222:        //
                    223: //     kFileLockedMask         = 1,
                    224:        kMaskBatAttributes      = ~(ioDirMask | kHFSFileLockedMask),
                    225:        
                    226:        //
                    227:        //      Masks for search bits
                    228:        //
                    229:        kMaskNotSearchInfo2     = ~(fsSBPartialName | fsSBFullName | fsSBNegate),
                    230:        kMaskLengthBits         = (fsSBFlLgLen | fsSBFlPyLen | fsSBFlRLgLen | fsSBFlRPyLen),
                    231: 
                    232:        //
                    233:        //      Masks for flags
                    234:        //
                    235:        kIncludeDirs            = 1,
                    236:        kIncludeFiles           = 2,
                    237:        kIncludeNames           = 4,
                    238:        
                    239:        kMinimumBufferSize      = 512
                    240: };
                    241: 
                    242: 
                    243: struct CatPosition {
                    244:        UInt32          writeCount;                     //      The BTree's write count (to see if the catalogwriteCount
                    245:                                                                        //      changed since the last search).  If 0, the rest
                    246:                                                                        //      of the record is invalid, start from beginning.
                    247:        UInt32          nextNode;                       //      node number to resume search
                    248:        UInt32          nextRecord;                     //      record number to resume search
                    249:        UInt32          recordsFound;           //      number of leaf records seen so far
                    250: };
                    251: typedef struct CatPosition CatPosition;
                    252: 
                    253: 
                    254: typedef BTScanState ScanState;
                    255: 
                    256: 
                    257: struct CatSearchState {
                    258:        TMTask                  timer;                                  //      MUST be first field!
                    259:        CSParam                 *pb;
                    260:        Str31                   targetName;                             //      Upper case version of name being matched against
                    261:        FSSpec                  *nextMatch;
                    262:        long                    searchBits;
                    263:        CatalogKey              *currentKey;                    //      Pointer to key within current record
                    264:        CatalogRecord   *currentData;                   //      Pointer to data within current record
                    265: #if HFSInstrumentation
                    266:        InstTraceClassRef trace;
                    267:        InstEventTag    eventTag;
                    268:        InstDataDescriptorRef traceDescriptor;
                    269: #endif
                    270:        short                   vRefNum;                                //      Volume reference of volume being searched
                    271:        Boolean                 isHFS;                                  //      True if volume is HFS
                    272:        UInt8                   attributes;                             //      desired file attributes to match against
                    273:        UInt8                   flags;
                    274:        Boolean                 timerCompleted;                 //      Set to true by timer's completion routine
                    275: };
                    276: typedef struct CatSearchState CatSearchState;
                    277: 
                    278: #if TARGET_OS_MAC
                    279: static OSErr InitCatSearch( ExtendedVCB *volume, CSParam *pb, ScanState *scanState );
                    280: static void UpdateCatPosition( const ExtendedVCB *volume, CatPosition *endingPosition, const ScanState *scanState );
                    281: static void InsertMatch(CatSearchState *searchState);
                    282: static Boolean CheckCriteria(ExtendedVCB *vcb, const CatSearchState *searchState);
                    283: Boolean CompareMasked(const UInt32 *thisValue, const UInt32 *compareData,
                    284:                                                         const UInt32 *compareMask, UInt32 count);
                    285: Boolean ComparePartialName(ConstStr31Param thisName, ConstStr31Param substring);
                    286: Boolean CompareFullName(ConstStr31Param thisName, ConstStr31Param testName);
                    287: #endif /* TARGET_OS_MAC */
                    288: Boolean CompareRange(UInt32 val, UInt32 low, UInt32 high);
                    289: #define CompareRange(val, low, high)   (val >= low && val <= high)
                    290: 
                    291: extern void CSTimerGlue(void);
                    292: extern void CatSearchTimerComplete(CatSearchState *state);
                    293: 
                    294: UInt32 Low32BitsPinned(UInt64 x);
                    295: #define Low32BitsPinned(x)     (x.hi ? 0xFFFFFFFF : x.lo)
                    296: 
                    297: 
                    298: 
                    299: /*
                    300: ;__________________________________________________________________________________
                    301: ;
                    302: ; Routine:             CMCatSearch
                    303: ;
                    304: ; Function:    Locates files by search criteria
                    305: ;
                    306: ; Input:               A0.L  -  parameter block pointer
                    307: ;
                    308: ; Register Usage (during call):
                    309: ;      A0.L  -  scratch                                                                        D0.L - scratch
                    310: ;      A1.L  -  scratch                                                                        D1.L - scratch
                    311: ;      A2.L  -  scratch                                                                        D2.L - scratch
                    312: ;      A3.L  -  pointer to CatSearch State Record (CSSR)       D3.L - scratch
                    313: ;      A4.L  -  pointer to PScan State Record (PSR)            D4.L - scratch
                    314: ;      A5.L  -  pointer to user's param block              D5.L - ioSearchBits
                    315: ;      sp   -  standard file system stack
                    316: ;                                                                                                              D7.L - ioActMatchCount
                    317: ;
                    318: ; Output:              D0.W  -  result code (noErr, extFSErr, ioErr, nsvErr, catChanged, paramErr)
                    319: ;      A0.L, A1.L - trash
                    320: ;      D0.L, D1.L, D2.L - trash
                    321: ;__________________________________________________________________________________
                    322: */
                    323: #if TARGET_OS_MAC
                    324: OSErr CatSearchC( CSParam *pb, WDCBRecPtr *wdcb )
                    325: {
                    326:        OSErr                   err;
                    327:        ExtendedVCB             *vcb;
                    328:        short                   volNameLength;
                    329:        Boolean                 volNameSpecified;
                    330:        unsigned char   *pathname;
                    331:        UInt32                  catalogRecordSize;
                    332:        ScanState               scanState;
                    333:        CatSearchState  searchState;
                    334:        Boolean                 timerInstalled = false;
                    335: #if HFSInstrumentation
                    336:        FSVarsRec                       *fsVars = (FSVarsRec *) LMGetFSMVars();
                    337: #endif
                    338: 
                    339: 
                    340: #if HFSInstrumentation
                    341:        searchState.trace = (InstTraceClassRef) fsVars->later[0];
                    342:        searchState.traceDescriptor = (InstDataDescriptorRef) fsVars->later[1];
                    343:        searchState.eventTag = InstCreateEventTag();
                    344:        InstLogTraceEvent( searchState.trace, searchState.eventTag, kInstStartEvent);
                    345: #endif
                    346: 
                    347:        //
                    348:        //      Start a timer for the call
                    349:        //
                    350:        searchState.timerCompleted = false;
                    351: 
                    352:        if (pb->ioSearchTime != 0 && pb->ioSearchTime != -1) {
                    353:                searchState.timer.tmAddr = (TimerUPP) CSTimerGlue;
                    354:                InsTime((QElem *) &searchState.timer);
                    355:                PrimeTime((QElem *) &searchState.timer, pb->ioSearchTime);
                    356:                timerInstalled = true;
                    357:        }
                    358:        
                    359:        //
                    360:        //      Find the volume specified
                    361:        //
                    362:        err = DeturmineVolume3((VolumeParam *) pb, &volNameLength, &volNameSpecified, &vcb, wdcb, &pathname);
                    363:        if (err != noErr) goto ErrorExit;
                    364: 
                    365:        //
                    366:        //      Make sure the volume is ours, and online.
                    367:        //
                    368:        err = ExtOffLineCheck(vcb);
                    369:        if (err != noErr) goto ErrorExit;
                    370: 
                    371:        //
                    372:        //      Set up some information about the volume
                    373:        //
                    374:        searchState.vRefNum = vcb->vcbVRefNum;
                    375:        if (vcb->vcbSigWord == kHFSSigWord)
                    376:                searchState.isHFS = true;
                    377:        else
                    378:                searchState.isHFS = false;
                    379:        
                    380:        //
                    381:        //      Clear ioActMatchCount
                    382:        //
                    383:        pb->ioActMatchCount = 0;
                    384:        
                    385:        //
                    386:        //      Verify the parameter block
                    387:        //
                    388:        err = VerifyCatSearchPB(pb, &searchState.attributes, &searchState.flags);
                    389:        if (err != noErr) goto ErrorExit;
                    390: 
                    391:        //
                    392:        //      If no matches requested, exit early
                    393:        //
                    394:        if (pb->ioReqMatchCount == 0) {
                    395:                err = noErr;
                    396:                goto ErrorExit;
                    397:        }
                    398:        
                    399:        searchState.pb = pb;
                    400:        searchState.searchBits = pb->ioSearchBits;
                    401:        searchState.nextMatch = pb->ioMatchPtr;
                    402:        
                    403:        //
                    404:        //      If a name is part of the criteria, prepare it for matching.  (We make it upper
                    405:        //      case and remove diacriticals.)
                    406:        //
                    407:        if (searchState.flags & kIncludeNames) {
                    408:                StringPtr name;
                    409:                name = pb->ioSearchInfo1->hFileInfo.ioNamePtr;
                    410:                //      If caller's name is longer than HFS names can be, then
                    411:                //      we can optimize.
                    412:                if (name[0] > 31) {
                    413:                        //      Nothing can possibly match the given name.  If the caller asked
                    414:                        //      us to negate the search, then we need to return everything.
                    415:                        if (searchState.searchBits & fsSBNegate) {
                    416:                                searchState.searchBits = 0;             //      causes everything to match
                    417:                        }
                    418:                        else {
                    419:                                err = eofErr;                                   // nothing left to match
                    420:                                goto ErrorExit;
                    421:                        }
                    422:                }
                    423:                else {
                    424:                        //
                    425:                        //      Make a copy of the supplied name and convert it to upper case
                    426:                        //      for later comparison.
                    427:                        //
                    428:                        //�� There is a bug in the assembly CatSearch: it calls _FSUprString which
                    429:                        //�� is really just _UpperString.  It passes the length of the string in D0.
                    430:                        //�� According to the interfaces, the second parameter (in D0) is a boolean
                    431:                        //�� to determine whether it should be diacritical sensitive (i.e. whether it
                    432:                        //���should leave diacriticals vs. stripping them).  Apparently, this always
                    433:                        //�� evaluates to false (testing the high bit of the word?).
                    434:                        //
                    435:                        //�� I disagree with the above analysis. The $A054 trap, which _FSUprString is 
                    436:                        //�� aliased to, is actually UprStringTrap(), implemented in :SuperMario:OS:SysUtil.a. 
                    437:                        //�� It does in fact take a ptr to text in A0 and len in D0.   UpperString(), 
                    438:                        //���on the other hand, is glue in OSTrapsGlue.a which munges 
                    439:                        //�� the input parameters (including the diac boolean) and then turns around and calls
                    440:                        //�� _UprString, with A0 pointing to text and D0 holding length. Same as assembly CatSearch.
                    441:                        //�� So _UprString (or _UpperString) != UpperString(), sadly enough.
                    442:                        //�� - RNP.
                    443:                        //
                    444:                        // Note: we still do this even for HFS+, since we want to compare the names that
                    445:                        // would actually be returned in the same way as HFS.  That is name comparisons
                    446:                        // for HFS and HFS+ should behave identically if they returned the same name via
                    447:                        // GetCatInfo, even though HFS+ may be truncating or otherwise mangling the name
                    448:                        // to fit in 31 characters; we want to compare against the mangled name.
                    449:                        //
                    450:                        BlockMoveData(name, searchState.targetName, sizeof(Str31));
                    451:                        UprText( (Ptr)(searchState.targetName + 1), searchState.targetName[ 0]);
                    452:                }
                    453:        }
                    454: 
                    455:        //
                    456:        //      Set up for the search.
                    457:        //
                    458:        err = InitCatSearch(vcb, pb, &scanState);
                    459:        #if DEBUG_BUILD
                    460:                if (err > 0) DebugStr("\pCatSearch: Internal Error");
                    461:        #endif
                    462:        
                    463:        //
                    464:        //      Now loop over the records
                    465:        //
                    466:        while (err == noErr) {
                    467:         err = BTScanNextRecord(&scanState, searchState.timerCompleted, (void**)&searchState.currentKey, (void**)&searchState.currentData, &catalogRecordSize);
                    468:                if (err == noErr) {
                    469:                        //      Check for a match
                    470:                        if (CheckCriteria(vcb, &searchState)) {                                 //      Found a match?
                    471:                                err = BTScanCacheNode(&scanState);                                      //              Make sure current node is cached
                    472:                                InsertMatch(&searchState);                                                      //              Return in to caller
                    473:                                if (++pb->ioActMatchCount == pb->ioReqMatchCount)       //              Got enough matches yet?
                    474:                                        break;
                    475:                        }
                    476:                }
                    477:        }
                    478:        
                    479:        //
                    480:        //      See if we've scanned the entire Catalog BTree.  If so, return eofErr.
                    481:        //      If we exited because of a timeout, then it's not an error.
                    482:        //
                    483:        if (err == btNotFound || err == fsBTEndOfIterationErr)
                    484:                err = eofErr;
                    485:        if (err == fsBTTimeOutErr)
                    486:                err = noErr;
                    487:        #if DEBUG_BUILD
                    488:                if (err > 0) DebugStr("\pCatSearch: Internal Error");
                    489:        #endif
                    490:        //
                    491:        //      Update caller's CatPosition so they can resume the search
                    492:        //
                    493:        UpdateCatPosition(vcb, (CatPosition *) &pb->ioCatPosition, &scanState);
                    494: 
                    495:        //
                    496:        //      If we get here, we never actually started a scan, so all we have left
                    497:        //      is to remove the timer (if we installed one) and return the error code.
                    498:        //
                    499: ErrorExit:
                    500:        //
                    501:        //      Stop timer
                    502:        //
                    503:        if (timerInstalled)
                    504:                RmvTime((QElem *) &searchState.timer);
                    505:        
                    506: #if HFSInstrumentation
                    507:        InstLogTraceEvent( searchState.trace, searchState.eventTag, kInstEndEvent);
                    508: #endif
                    509: 
                    510:        return err;
                    511: }
                    512: 
                    513: #endif
                    514: 
                    515: /*
                    516: ;__________________________________________________________________________________
                    517: ;
                    518: ; Routine:             VerifyCSPB
                    519: ;
                    520: ; Function:    Verify that a param block contains legal values
                    521: ;
                    522: ; Input:               A0.L  -  parameter block pointer
                    523: ;
                    524: ; Register Usage (during call):
                    525: ;      A0.L  -  pointer to user's param block              D0.L - scratch
                    526: ;      A1.L  -  pointer to ioSearchInfo1                                                       D1.L - scratch
                    527: ;                                                                                                              D2.B - copy of user's ioFlAttrib mask
                    528: ;                                                                                                              D3.L - cssr.flags byte
                    529: ;      A4.L  -  pointer to ioSearchInfo2
                    530: ;      A5.L  -  pointer to user's param block              D5.L - ioSearchBits
                    531: ;
                    532: ; Output:
                    533: ;      d0.W  -  result code (noErr, paramErr)
                    534: ;      d2.b  -  copy of user's ioFlAttrib mask, ioDirFlg masked
                    535: ;      d3.b  -  cssr.flags with inclFiles, inclDirs and inclNames set correctly
                    536: ;
                    537: ; Here are the parameter checking rules for PBCatSearch:                                               <1.3>
                    538: ; The labels at the left also appear in the code which checks that rule.
                    539: ;
                    540: ; You get a paramErr if
                    541: ; P1   ioMBufPtr is nil
                    542: ; P2   ioSearchInfo1 is nil
                    543: ; P3   (ioSearchBits includes not(fsSBPartialName or fsSBFullName or fsSBNegate)) and ioSearchInfo2 is nil;
                    544: ;              i.e. A selected search bit requires the presence of ioSearchInfo2
                    545: ;
                    546: ; Then these,
                    547: ; ioSearchBits rules: You get a paramErr if
                    548: ; P4   fsSBPartialName
                    549: ;              and (ioSearchInfo1->ioNamePtr = (nil or empty string))
                    550: ; P5   fsSBFullName (same as above)
                    551: ; P6   fsSBFlAttrib and some bit other than 0 (locked) or 4 (directory) returns paramErr
                    552: ; P7   search includes directories and
                    553: ;              (ioSearchBits includes fsSBFlAttrib) and (ioSearchInfo2^.ioFlAttrib bit 0 = 1)
                    554: ;              return paramErr
                    555: ;              (i.e. "locked directory" makes no sense)
                    556: ; P8   fsSBDrNmFls and files returns paramErr
                    557: ; P9   fsSBFlLgLen and directories returns paramErr
                    558: ; P10  fsSBFlPyLen (same as above)
                    559: ; P11  fsSBFlRLgLen (same as above)
                    560: ; P12  fsSBFlRPyLen (same as above)
                    561: ;
                    562: ; A search includes (files only) if
                    563: ;      ioSearchBits includes fsSBFlAttrib
                    564: ;                      - and -
                    565: ;      ioSearchInfo1^.ioFlAttrib bit 4 = 0             i.e. explicitly looking for non-directories
                    566: ;                      - and -
                    567: ;      ioSearchInfo2^.ioFlAttrib bit 4 = 1
                    568: ;
                    569: ; A search includes (directories only) if
                    570: ;      ioSearchBits includes fsSBFlAttrib
                    571: ;                      - and -
                    572: ;      ioSearchInfo1^.ioFlAttrib bit 4 = 1             i.e. explicitly looking for directories
                    573: ;                      - and -
                    574: ;      ioSearchInfo2^.ioFlAttrib bit 4 = 1
                    575: ;
                    576: ; A search includes both if
                    577: ;      ioSearchBits includes fsSBFlAttrib
                    578: ;                      - and -
                    579: ;      ioSearchInfo2^.ioFlAttrib bit 4 = 0             i.e. don't care about the directory bit
                    580: ;
                    581: ;                      - OR -
                    582: ;      ioSearchBits doesn't include fsSBFlAttrib   i.e. don't care about attributes at all
                    583: ;__________________________________________________________________________________
                    584: */
                    585: 
                    586: OSErr VerifyCatSearchPB(
                    587:        const CSParam   *pb,                            // user's parameter block
                    588:        UInt8                   *outAttributes,         // ioFlAttrib, with ioDirFlg cleared
                    589:        UInt8                   *outFlags)                      // cssr.flags with inclFiles, inclDirs and inclNames set correctly
                    590: {
                    591:        SInt8           attributes = 0;                         // local copy of output outAttributes
                    592:        UInt8           flags;                                  // local copy of output outFlags
                    593:        long            searchBits;                             // copy of pb->ioSearchBits
                    594:        CInfoPBPtr      searchInfo1;                    // copy of pb->ioSearchInfo1
                    595:        CInfoPBPtr      searchInfo2;                    // copy of pb->ioSearchInfo2
                    596:        
                    597:        //
                    598:        //      P1: User must supply a buffer to return the found FSSpec's
                    599:        //
                    600:        if (pb->ioMatchPtr == NULL)
                    601:                goto ParamErrExit;
                    602:        
                    603:        //
                    604:        //      P2: Must supply values to compare against (ioSearchInfo1)
                    605:        //
                    606:        searchInfo1 = pb->ioSearchInfo1;
                    607:        searchInfo2 = pb->ioSearchInfo2;
                    608:        if (searchInfo1 == NULL)
                    609:                goto ParamErrExit;
                    610: 
                    611:        searchBits = pb->ioSearchBits;
                    612:        
                    613:        //
                    614:        //      P3: See if we need any end-of-range or mask values (in ioSearchInfo2).
                    615:        //      If so, the pointer must be non-NULL.
                    616:        //
                    617:        if (((searchBits & kMaskNotSearchInfo2) != 0) && (searchInfo2 == NULL))
                    618:                goto ParamErrExit;
                    619: 
                    620:        flags = 0;
                    621:        
                    622:        //
                    623:        //      P4-5: If we're searching by name (partial or full), then check the name passed.
                    624:        //
                    625:        if (searchBits & (fsSBPartialName | fsSBFullName)) {
                    626:                StringPtr name = searchInfo1->hFileInfo.ioNamePtr;
                    627:                if (name == NULL || name[0] == 0)
                    628:                        goto ParamErrExit;
                    629:                flags |= kIncludeNames;
                    630:        }
                    631:        
                    632:        //
                    633:        //      Determine whether we're looking for files, folders, or both.
                    634:        //
                    635:        if (searchBits & fsSBFlAttrib) {
                    636:                attributes = searchInfo2->hFileInfo.ioFlAttrib;         // get mask for attributes
                    637:                if (attributes & kMaskBatAttributes)    // P6: only locked and directory bits are allowed
                    638:                        goto ParamErrExit;
                    639:                if (attributes & ioDirMask)                             // do they care whether object is a file or folder?
                    640:                        if (searchInfo1->hFileInfo.ioFlAttrib & ioDirMask)
                    641:                                flags |= kIncludeDirs;                  // wanted folders only
                    642:                        else
                    643:                                flags |= kIncludeFiles;                 // wanted files only
                    644:                else
                    645:                        flags |= (kIncludeDirs | kIncludeFiles);        // caller didn't care about files vs. folders
                    646:        }
                    647:        else
                    648:                flags |= (kIncludeDirs | kIncludeFiles);
                    649:        
                    650:        attributes &= ~ioDirMask;                       // clear ioDirMask since it isn't actually on disk
                    651: 
                    652:        //
                    653:        //      P7: If they cared about file attributes, and search includes folders, then
                    654:        //      ioLockFlag must not be set (since it is meaningless for folders).
                    655:        //
                    656:        if ((flags & kIncludeDirs) && (searchBits & fsSBFlAttrib) && (attributes & kHFSFileLockedMask))
                    657:                goto ParamErrExit;
                    658: 
                    659:        //
                    660:        //      P8: If search includes files, then # of files per folder must not be set.
                    661:        //
                    662:        if ((searchBits & fsSBDrNmFls) && (flags & kIncludeFiles))
                    663:                goto ParamErrExit;
                    664: 
                    665:        //
                    666:        //      P9-P12: If search includes directories, then none of the fork length bits
                    667:        //      must be set.
                    668:        //
                    669:        if ((flags & kIncludeDirs) && (searchBits & kMaskLengthBits))
                    670:                goto ParamErrExit;
                    671: 
                    672:        //
                    673:        //      When we get here, all the checks have passed.  Return the output flags
                    674:        //      and file attributes.
                    675:        //
                    676:        *outAttributes = attributes;
                    677:        *outFlags = flags;
                    678:        return noErr;
                    679: 
                    680:        //
                    681:        //      If we get here, there was a problem with one of the parameters.
                    682:        //
                    683: ParamErrExit:
                    684:        return paramErr;
                    685: }
                    686: 
                    687: 
                    688: 
                    689: //
                    690: //     Copy the FSSpec for the current catalog node into the caller's match buffer
                    691: //
                    692: #if    TARGET_OS_MAC
                    693: static void InsertMatch(CatSearchState *searchState)
                    694: {
                    695:        CatalogKey      *current;
                    696:        FSSpec          *match;
                    697:        
                    698:        //      Get the key for the item we just found, and the place where we should
                    699:        //      store the item's FSSpec
                    700:        current = searchState->currentKey;
                    701:        match = searchState->nextMatch;
                    702:        
                    703:        //      Copy vRefNum
                    704:        match->vRefNum = searchState->vRefNum;
                    705: 
                    706:        if (searchState->isHFS) {
                    707:                //      Copy parentDirID
                    708:                match->parID = current->hfs.parentID;
                    709:                
                    710:                //      Copy the name as a PString
                    711:                BlockMoveData(current->hfs.nodeName, &match->name[0], StrLength(current->hfs.nodeName) + 1);
                    712:        }
                    713:        else {
                    714:                TextEncoding            encoding;
                    715:                HFSCatalogNodeID        cnid;
                    716: 
                    717:                cnid = searchState->currentData->hfsPlusFile.fileID;                            // note: cnid at same offset for folders
                    718:                encoding = searchState->currentData->hfsPlusFile.textEncoding;  // note: textEncoding at same offset for folders
                    719: 
                    720:                //      Copy parentDirID
                    721:                match->parID = current->hfsPlus.parentID;
                    722:                
                    723:                //      Copy the name as a PString
                    724:                (void) ConvertUnicodeToHFSName( &current->hfsPlus.nodeName, encoding, cnid, &match->name[0]);   
                    725:        }
                    726:        
                    727: #if HFSInstrumentation
                    728: //     InstLogTraceEvent( searchState->trace, searchState->eventTag, kInstMiddleEvent);
                    729:        {
                    730:                struct {
                    731:                        long    vRefNum;
                    732:                        long    parID;
                    733:                        char    name[32];
                    734:                } x;
                    735:                unsigned        len;
                    736:                
                    737:                x.vRefNum = match->vRefNum;
                    738:                x.parID = match->parID;
                    739:                
                    740:                len = match->name[0];
                    741:                BlockMoveData(&match->name[1], &x.name[0], len);
                    742:                x.name[len] = 0;
                    743:                                
                    744:                InstLogTraceEventWithDataStructure( searchState->trace, searchState->eventTag, kInstMiddleEvent,
                    745:                                                                                        searchState->traceDescriptor, (UInt8 *) &x, sizeof(x));
                    746:        }
                    747: #endif
                    748: 
                    749:        //      Point to next FSSpec in caller's buffer
                    750:        searchState->nextMatch++;
                    751: }
                    752: #endif /* TARGET_OS_MAC */
                    753: 
                    754: 
                    755: 
                    756: //
                    757: //     Determine whether the current catalog node matches the caller's criteria.  Return
                    758: //     true if the object matches.
                    759: //
                    760: #if    TARGET_OS_MAC
                    761: static Boolean CheckCriteria(ExtendedVCB *vcb, const CatSearchState *searchState)
                    762: {
                    763:        CatalogKey              *key;
                    764:        Boolean                 matched;
                    765:        long                    searchBits;
                    766:        CInfoPBRec              *searchInfo1;
                    767:        CInfoPBRec              *searchInfo2;
                    768:        CatalogNodeData catData;
                    769:        
                    770:        key = searchState->currentKey;
                    771:        
                    772:        //      Change the catalog record data into a single common form
                    773:        catData.nodeType = 0;           //      mark this record as not in use
                    774:        CopyCatalogNodeData(vcb, searchState->currentData, &catData);
                    775:        
                    776:        switch (searchState->currentData->recordType) {
                    777:                case kHFSFolderThreadRecord:
                    778:                        return false;           // Never match a thread record!
                    779:                        break;
                    780:                case kHFSPlusFolderThreadRecord:
                    781:                        return false;           // Never match a thread record!
                    782:                        break;
                    783: 
                    784:                case kHFSFolderRecord:
                    785:                case kHFSFileRecord:
                    786:                case kHFSPlusFolderRecord:
                    787:                case kHFSPlusFileRecord:
                    788:                        break;
                    789: 
                    790:                default:
                    791:                        return false;                   // Not a file or folder record, so can't search it
                    792:        }
                    793:        
                    794:        searchBits = searchState->searchBits;
                    795:        matched = true;                                 //      Assume we got a match
                    796: 
                    797:        //      See if this type of object (file vs. folder) is one of the types they're trying
                    798:        //      to match.
                    799:        if (catData.nodeType == kCatalogFolderNode && (searchState->flags & kIncludeDirs) == 0 ) {
                    800:                //      Found a folder, but they don't want folders.
                    801:                matched = false;
                    802:                goto TestDone;
                    803:        }
                    804:        if (catData.nodeType == kCatalogFileNode && (searchState->flags & kIncludeFiles) == 0 ) {
                    805:                //      Found a file, but they don't want files.
                    806:                matched = false;
                    807:                goto TestDone;
                    808:        }
                    809: 
                    810:        searchInfo1 = searchState->pb->ioSearchInfo1;
                    811:        searchInfo2 = searchState->pb->ioSearchInfo2;
                    812:        
                    813:        //
                    814:        //      First, attempt to match the name -- either partial or complete.
                    815:        //      If the volume is HFS+, then we need to make a Str31 version of the name
                    816:        //      to use for comparison.
                    817:        //
                    818:        if (searchBits & (fsSBPartialName | fsSBFullName)) {
                    819:                Str31                   keyName;
                    820:                ConstStr31Param namePtr;
                    821: 
                    822:                //      Make a pointer to a PString version of the name
                    823:                if (searchState->isHFS)
                    824:                        namePtr = &key->hfs.nodeName[0];
                    825:                else {
                    826:                        TextEncoding    encoding;
                    827:                        
                    828:                        encoding = searchState->currentData->hfsPlusFile.textEncoding;  // same offset for folders
                    829: 
                    830:                        (void) ConvertUnicodeToHFSName(&key->hfsPlus.nodeName, encoding, catData.nodeID, keyName);
                    831:                        namePtr = keyName;
                    832:                }
                    833: 
                    834:                //      Check for a partial name match
                    835:                if (searchBits & fsSBPartialName) {
                    836:                        matched = ComparePartialName(namePtr, searchState->targetName);
                    837:                        // Exit if no match, or we no there's nothing more to compare
                    838:                        if (matched == false || searchBits == fsSBPartialName)
                    839:                                goto TestDone;
                    840:                }
                    841:                
                    842:                //      Check for a full name match
                    843:                if (searchBits & fsSBFullName) {
                    844:                        matched = CompareFullName(namePtr, searchState->targetName);
                    845:                        // Exit if no match, or we no there's nothing more to compare
                    846:                        if (matched == false || searchBits == fsSBFullName)
                    847:                                goto TestDone;
                    848:                }
                    849:        }
                    850:        
                    851:        //
                    852:        //      parent ID
                    853:        //
                    854:        if (searchBits & fsSBFlParID) {
                    855:                HFSCatalogNodeID        parentID;
                    856:                
                    857:                //      Note: ioFlParID and ioDrParID have the same offset in search info, so no
                    858:                //      need to test the object type here.  However, we do need to test for HFS
                    859:                //      vs. HFSPlus, since their key structures are different.
                    860:                
                    861:                if (searchState->isHFS)
                    862:                        parentID = key->hfs.parentID;
                    863:                else
                    864:                        parentID = key->hfsPlus.parentID;
                    865: 
                    866:                matched = CompareRange(parentID, searchInfo1->hFileInfo.ioFlParID,
                    867:                                                                searchInfo2->hFileInfo.ioFlParID);
                    868:                if (matched == false) goto TestDone;
                    869:        }
                    870: 
                    871:        //
                    872:        //      File attributes
                    873:        //
                    874:        if (searchBits & fsSBFlAttrib) {
                    875:                UInt32  temp;
                    876:                
                    877:                temp = (catData.nodeFlags ^ searchInfo1->hFileInfo.ioFlAttrib) & searchState->attributes;
                    878:                if (temp != 0) {
                    879:                        matched = false;
                    880:                        goto TestDone;
                    881:                }
                    882:        }
                    883:        
                    884:        //
                    885:        //      Number of files in a directory
                    886:        //
                    887:        if (searchBits & fsSBDrNmFls) {
                    888:                matched = CompareRange(catData.valence, searchInfo1->dirInfo.ioDrNmFls,
                    889:                                                                searchInfo2->dirInfo.ioDrNmFls);
                    890:                if (matched == false) goto TestDone;
                    891:        }
                    892:        
                    893:        //
                    894:        //      Finder Info
                    895:        //
                    896:        if (searchBits & fsSBFlFndrInfo) {
                    897:                UInt32 *thisValue;
                    898:                
                    899:                thisValue = (UInt32 *) &catData.finderInfo[0];
                    900: 
                    901:                //      Note: ioFlFndrInfo and ioDrUsrWds have the same offset in search info, so
                    902:                //      no need to test the object type here.
                    903:                matched = CompareMasked(thisValue, (UInt32 *) &searchInfo1->hFileInfo.ioFlFndrInfo,
                    904:                                                                (UInt32 *) &searchInfo2->hFileInfo.ioFlFndrInfo,
                    905:                                                                sizeof(FInfo)/sizeof(UInt32));
                    906: 
                    907:                if (matched == false) goto TestDone;
                    908:        }
                    909:        
                    910:        //
                    911:        //      Extended Finder Info
                    912:        //
                    913:        if (searchBits & fsSBFlXFndrInfo) {
                    914:                UInt32 *thisValue;
                    915:                
                    916:                thisValue = (UInt32 *) &catData.extFinderInfo[0];
                    917: 
                    918:                //      Note: ioFlXFndrInfo and ioDrFndrInfo have the same offset in search info, so
                    919:                //      no need to test the object type here.
                    920:                matched = CompareMasked(thisValue, (UInt32 *) &searchInfo1->hFileInfo.ioFlXFndrInfo,
                    921:                                                                (UInt32 *) &searchInfo2->hFileInfo.ioFlXFndrInfo,
                    922:                                                                sizeof(FXInfo)/sizeof(UInt32));
                    923: 
                    924:                if (matched == false) goto TestDone;
                    925:        }
                    926:        
                    927:        //
                    928:        //      File logical length (data fork)
                    929:        //
                    930:        if (searchBits & fsSBFlLgLen) {
                    931:                matched = CompareRange(catData.dataLogicalSize, searchInfo1->hFileInfo.ioFlLgLen,
                    932:                                                                searchInfo2->hFileInfo.ioFlLgLen);
                    933:                if (matched == false) goto TestDone;
                    934:        }
                    935:        
                    936:        //
                    937:        //      File physical length (data fork)
                    938:        //
                    939:        if (searchBits & fsSBFlPyLen) {
                    940:                matched = CompareRange(catData.dataPhysicalSize, searchInfo1->hFileInfo.ioFlPyLen,
                    941:                                                                searchInfo2->hFileInfo.ioFlPyLen);
                    942:                if (matched == false) goto TestDone;
                    943:        }
                    944:        
                    945:        //
                    946:        //      File logical length (resource fork)
                    947:        //
                    948:        if (searchBits & fsSBFlRLgLen) {
                    949:                matched = CompareRange(catData.rsrcLogicalSize, searchInfo1->hFileInfo.ioFlRLgLen,
                    950:                                                                searchInfo2->hFileInfo.ioFlRLgLen);
                    951:                if (matched == false) goto TestDone;
                    952:        }
                    953:        
                    954:        //
                    955:        //      File physical length (resource fork)
                    956:        //
                    957:        if (searchBits & fsSBFlRPyLen) {
                    958:                matched = CompareRange(catData.rsrcPhysicalSize, searchInfo1->hFileInfo.ioFlRPyLen,
                    959:                                                                searchInfo2->hFileInfo.ioFlRPyLen);
                    960:                if (matched == false) goto TestDone;
                    961:        }
                    962:        
                    963:        //
                    964:        //      Create date
                    965:        //
                    966:        if (searchBits & fsSBFlCrDat) {
                    967:                matched = CompareRange(catData.createDate, searchInfo1->hFileInfo.ioFlCrDat,
                    968:                                                                searchInfo2->hFileInfo.ioFlCrDat);
                    969:                if (matched == false) goto TestDone;
                    970:        }
                    971:        
                    972:        //
                    973:        //      Mod date
                    974:        //
                    975:        if (searchBits & fsSBFlMdDat) {
                    976:                matched = CompareRange(catData.contentModDate, searchInfo1->hFileInfo.ioFlMdDat,
                    977:                                                                searchInfo2->hFileInfo.ioFlMdDat);
                    978:                if (matched == false) goto TestDone;
                    979:        }
                    980:        
                    981:        //
                    982:        //      Backup date
                    983:        //
                    984:        if (searchBits & fsSBFlBkDat) {
                    985:                matched = CompareRange(catData.backupDate, searchInfo1->hFileInfo.ioFlBkDat,
                    986:                                                                searchInfo2->hFileInfo.ioFlBkDat);
                    987:        }
                    988: 
                    989: TestDone:
                    990:        //
                    991:        //      Finally, determine whether we need to negate the sense of the match (i.e. find
                    992:        //      all objects that DON'T match).
                    993:        //
                    994:        if (searchBits & fsSBNegate) {
                    995:                matched = !matched;
                    996:        }
                    997:        
                    998:        return matched;
                    999: }
                   1000: #endif /* TARGET_OS_MAC */
                   1001: 
                   1002: 
                   1003: 
                   1004: Boolean CompareMasked(const UInt32 *thisValue, const UInt32 *compareData,
                   1005:                                                         const UInt32 *compareMask, UInt32 count)
                   1006: {
                   1007:        Boolean matched;
                   1008:        UInt32  i;
                   1009:        
                   1010:        matched = true;                 //      Assume it will all match
                   1011:        
                   1012:        for (i=0; i<count; i++) {
                   1013:                if (((*thisValue++ ^ *compareData++) & *compareMask++) != 0) {
                   1014:                        matched = false;
                   1015:                        break;
                   1016:                }
                   1017:        }
                   1018:        
                   1019:        return matched;
                   1020: }
                   1021: 
                   1022: 
                   1023: #if TARGET_OS_MAC
                   1024: Boolean CompareFullName(ConstStr31Param thisName, ConstStr31Param testName)
                   1025: {
                   1026:        Str31   tempName;
                   1027: 
                   1028:        //
                   1029:        //      Make a quick check first.  If the lengths differ, they can't possibly match.
                   1030:        //
                   1031:        if (thisName[0] != testName[0])
                   1032:                return false;
                   1033: 
                   1034:        //
                   1035:        //      Now make an upper case copy of thisName.
                   1036:        //
                   1037:        //�� Would it be better to skip making upper case versions of the names
                   1038:        //�� and just call EqualString(thisName, testName, false, false)?  I think it
                   1039:        //�� should give the same result.
                   1040:        //
                   1041:        BlockMoveData(thisName, tempName, sizeof(Str31));
                   1042:        UprText( (Ptr)(tempName + 1), tempName[0]);
                   1043:        
                   1044:        //
                   1045:        //      Compare tempName and testName; they must be identical PStrings to match.
                   1046:        //
                   1047:        return PascalBinaryCompare(tempName, testName); 
                   1048: }
                   1049: #endif /* TARGET_OS_MAC */
                   1050: 
                   1051: 
                   1052: 
                   1053: #if TARGET_OS_MAC
                   1054: Boolean ComparePartialName(ConstStr31Param thisName, ConstStr31Param substring)
                   1055: {
                   1056:        Boolean matched;
                   1057:        Str31   tempName;
                   1058: 
                   1059:        //
                   1060:        //      Make a quick check first.  If the substring is longer than this object's name,
                   1061:        //      it can't possibly match.
                   1062:        //
                   1063:        if (substring[0] > thisName[0])
                   1064:                return false;
                   1065: 
                   1066:        //
                   1067:        //      Now make an upper case copy of thisName.
                   1068:        //
                   1069:        //�� Would it be better to skip making upper case versions of the names
                   1070:        //�� and just call EqualString(thisName, testName, false, false)?  I think it
                   1071:        //�� should give the same result.
                   1072:        //
                   1073:        BlockMoveData(thisName, tempName, sizeof(Str31));
                   1074:        UprText( (Ptr)(tempName + 1), tempName[0]);
                   1075:        
                   1076:        //
                   1077:        //      Now see if substring is a substring of tempName.
                   1078:        //
                   1079:        matched = (PLstrstr(tempName, substring) != NULL);
                   1080:        
                   1081:        return matched;
                   1082: }
                   1083: #endif /* TARGET_OS_MAC */
                   1084: 
                   1085: 
                   1086: 
                   1087: //�� Same function appears in Volumes.c as CheckVolumeOffLine(), but the code is slightly different
                   1088: //�� we should delete one copy.
                   1089: #if TARGET_OS_MAC
                   1090: OSErr ExtOffLineCheck( ExtendedVCB *vcb )
                   1091: {
                   1092:        OSErr   err;
                   1093:        
                   1094:        err = CheckExternalFileSystem(vcb);
                   1095:        if (err == noErr) {
                   1096:                if (vcb->vcbDrvNum != 0)
                   1097:                        LMSetReqstVol((Ptr) vcb);
                   1098:                else
                   1099:                        err = volOffLinErr;
                   1100:        }
                   1101:        
                   1102:        return err;
                   1103: }
                   1104: #endif
                   1105: 
                   1106: 
                   1107: void CatSearchTimerComplete(CatSearchState *state)
                   1108: {
                   1109:        state->timerCompleted = true;
                   1110: }
                   1111: 
                   1112: #if TARGET_OS_MAC
                   1113: static OSErr InitCatSearch( ExtendedVCB *volume, CSParam *pb, ScanState *scanState )
                   1114: {
                   1115:        OSErr                   err;
                   1116:        FCB                             *fcb;
                   1117:        BTREE_CB_TYPE   *btcb;
                   1118:        CatPosition             *startingPosition;      
                   1119:        void                    *buffer;
                   1120:        UInt32                  bufferSize;
                   1121:        FSVarsRec               *fsVars;
                   1122:        
                   1123:        //
                   1124:        //      Set up pointers to the catalog's FCB and BTCB
                   1125:        //      
                   1126:        fcb = GetFileControlBlock(volume->catalogRefNum);
                   1127:        btcb = (BTREE_CB_TYPE *) fcb->fcbBTCBPtr;
                   1128:        
                   1129:        //
                   1130:        //      Flush all files on this volume so the BTrees will be up-to-date (since we only
                   1131:        //      read the BTree on disk, not what might be in the control blocks).
                   1132:        //
                   1133:        LMSetFlushOnly(0xFF);
                   1134:        err = FlushVolume(volume);
                   1135:        if (err != noErr) goto ErrorExit;
                   1136:        
                   1137:        //
                   1138:        //      Make sure the volume control files (especially the Catalog B-tree) gets flushed,
                   1139:        //      too, or else we'll be reading stale catalog data.
                   1140:        //
                   1141:        err = FlushVolumeBuffers(volume);
                   1142:        if (err != noErr) goto ErrorExit;
                   1143: 
                   1144:        //
                   1145:        //      Use our internal optimization buffer unless the caller supplied a suitable one.
                   1146:        //
                   1147:        fsVars = (FSVarsRec *) LMGetFSMVars();
                   1148:        buffer          = pb->ioOptBuffer;
                   1149:        bufferSize      = pb->ioOptBufSize;
                   1150:        if (buffer == NULL || bufferSize < fsVars->gAttributesBufferSize) {
                   1151:                buffer          = fsVars->gAttributesBuffer;
                   1152:                bufferSize      = fsVars->gAttributesBufferSize;
                   1153:        }
                   1154: 
                   1155:        //
                   1156:        //      Set up the scan state to start a new search, or resume a previous one.
                   1157:        //
                   1158:        startingPosition = (CatPosition *) &pb->ioCatPosition;
                   1159:        if (startingPosition->writeCount == 0) {
                   1160:                //
                   1161:                //      Starting a new search
                   1162:                //
                   1163:                err = BTScanInitialize(fcb, 0, 0, 0, buffer, bufferSize, scanState);
                   1164:        }
                   1165:        else {
                   1166:                //
                   1167:                //      Resuming a previous search.  Make sure the catalog hasn't changed
                   1168:                //      since the previous search.
                   1169:                //
                   1170:                if (startingPosition->writeCount != BTREE_WRITE_COUNT(btcb)) {
                   1171:                        startingPosition->writeCount = BTREE_WRITE_COUNT(btcb);         // return the new write count
                   1172:                        err = catChangedErr;
                   1173:                        goto ErrorExit;
                   1174:                }
                   1175:                
                   1176:                err = BTScanInitialize(fcb, startingPosition->nextNode, startingPosition->nextRecord, startingPosition->recordsFound,
                   1177:                                                                buffer, bufferSize, scanState);
                   1178:        }
                   1179: 
                   1180: ErrorExit:
                   1181:        return err;
                   1182: }
                   1183: #endif /* TARGET_OS_MAC */
                   1184: 
                   1185: #if TARGET_OS_MAC
                   1186: static void UpdateCatPosition( const ExtendedVCB *volume, CatPosition *endingPosition, const ScanState *scanState )
                   1187: {
                   1188:        FCB                             *fcb;
                   1189:        BTREE_CB_TYPE   *btcb;
                   1190: 
                   1191:        //
                   1192:        //      Set up pointers to the catalog's FCB and BTCB
                   1193:        //      
                   1194:        fcb = GetFileControlBlock(volume->catalogRefNum);
                   1195:        btcb = (BTREE_CB_TYPE *) fcb->fcbBTCBPtr;
                   1196:        
                   1197:        //
                   1198:        //      Update the caller's CatPosition for the next time
                   1199:        //
                   1200:        endingPosition->writeCount      = BTREE_WRITE_COUNT(btcb);
                   1201:        BTScanTerminate(scanState, &endingPosition->nextNode, &endingPosition->nextRecord, &endingPosition->recordsFound);
                   1202: }
                   1203: #endif /* TARGET_OS_MAC */

unix.superglobalmegacorp.com

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