Annotation of kernel/bsd/hfs/hfscommon/Misc/BTreeWrapper.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*
        !            26:        File:           BTreeWrapper.c
        !            27: 
        !            28:        Contains:       Interface glue for new B-tree manager.
        !            29: 
        !            30:        Version:        HFS Plus 1.0
        !            31: 
        !            32:        Copyright:      � 1996-1998 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:                (msd)   Mark Day
        !            45:                (DSH)   Deric Horn
        !            46:                (djb)   Don Brady
        !            47: 
        !            48:        Change History (most recent first):
        !            49:          <Rhap>         8/10/98        djb             Removed all references to btcb global iterator (lastIterator).
        !            50:          <Rhap>        04/02/98        djb             GetBTreeRecord is only used for MacOS builds.
        !            51:          <Rhap>        03/31/98        djb             Sync up with final HFSVolumes.h header file.
        !            52:          <CS18>          9/4/97        msd             Fix ValidHFSRecord to determine the type of B-tree by FileID,
        !            53:                                                                        not record size. Add better checking for attribute b-tree keys.
        !            54:          <CS17>         8/22/97        djb             Get blockReadFromDisk flag from GetCacheBlock call.
        !            55:          <CS16>         8/14/97        djb             Remove reserved field checks in ValidHFSRecord (radar #1649593).
        !            56:                                                                        Only call if ValidHFSRecord DEBUG_BUILD is true.
        !            57:          <CS15>         8/11/97        djb             Bug 1670441. In SetEndOfForkProc, don't DebugStr if the disk is
        !            58:                                                                        full.
        !            59:          <CS14>         7/25/97        DSH             Pass heuristicHint to BTSearchRecord from SearchBTreeRecord.
        !            60:          <CS13>         7/24/97        djb             CallBackProcs now take a file refNum instead of an FCB.
        !            61:                                                                        GetBlockProc now reports if block came from disk.
        !            62:          <CS12>         7/22/97        djb             Move all trace points to BTree.c file.
        !            63:          <CS11>         7/21/97        djb             LogEndTime now takes an error code.
        !            64:          <CS10>         7/16/97        DSH             FilesInternal.x -> FileMgrInternal.x to avoid name collision
        !            65:           <CS9>         7/15/97        msd             Bug #1664103.  OpenBTree is not propagating errors from
        !            66:                                                                        BTOpenPath.
        !            67:           <CS8>          7/9/97        djb             Remove maxCNID check from ValidHFSRecord (radar #1649593).
        !            68:           <CS7>         6/13/97        djb             In ValidHFSRecord HFSPlus threads names can be > 31 chars.
        !            69:           <CS6>          6/2/97        DSH             Also flush AlternateVolumeHeader whenever Attributes or Startup
        !            70:                                                                        files change size.
        !            71:           <CS5>         5/28/97        msd             In ValidHFSRecord, check for attribute keys.
        !            72:           <CS4>         5/19/97        djb             Move summary traces from GetBTreeRecord to BTIterateRecord.
        !            73:           <CS3>          5/9/97        djb             Get in sync with new FilesInternal.i.
        !            74:           <CS2>          5/7/97        djb             Add summary traces to B-tree SPI.
        !            75:           <CS1>         4/24/97        djb             first checked in
        !            76:         <HFS18>         4/16/97        djb             Always use new B-tree code.
        !            77:         <HFS17>          4/4/97        djb             Remove clumpSize test from ValidHFSRecord.
        !            78:         <HFS16>          4/4/97        djb             Get in sync with volume format changes.
        !            79:         <HFS15>         3/17/97        DSH             Casting for SC, BlockProcs are now not static.
        !            80:         <HFS14>          3/3/97        djb             Call trash block after closing btree!
        !            81:         <HFS13>         2/19/97        djb             Add support for accessing bigger B-tree nodes.
        !            82:         <HFS12>          2/6/97        msd             In CheckBTreeKey, remove test and DebugStr for parent ID being
        !            83:                                                                        too big.
        !            84:         <HFS11>         1/23/97        DSH             SetEndOfForkProc now calls through to update the Alternate MDB
        !            85:                                                                        or VolumeHeader.
        !            86:         <HFS10>         1/16/97        djb             Switched to dynamic lengths for BufferDescriptor length field in
        !            87:                                                                        SearchBTreeRecord and GetBTreeRecord. Round up to clump size in
        !            88:                                                                        SetEndOfForkProc.
        !            89:          <HFS9>         1/15/97        djb             Don't return errors for bad file ids in key.
        !            90:          <HFS8>         1/13/97        djb             Adding support for getting current record. ValidHFSRecord now
        !            91:                                                                        supports variable sized thread records.
        !            92:          <HFS7>          1/9/97        djb             Call CheckBTreeKey before using key length in a BlockMoveData
        !            93:                                                                        call.
        !            94:          <HFS6>          1/6/97        djb             Implement SetEndOfForkProc.
        !            95:          <HFS5>          1/6/97        djb             Added HFS Plus support to CheckBTreeKey and ValidHFSRecord.
        !            96:          <HFS4>          1/3/97        djb             Added support for large keys. Integrated latest HFSVolumesPriv.h
        !            97:                                                                        changes.
        !            98:          <HFS3>        12/23/96        djb             Fixed problem in SearchBTreeRecord (dataSize is an output so it
        !            99:                                                                        was undefined). Added some debugging code.
        !           100:          <HFS2>        12/20/96        msd             Fix OpenBTree to use the real data type for the key compare proc
        !           101:                                                                        pointer (not void *). Fixed problem in SearchBTreeRecord that
        !           102:                                                                        assigns a pointer to a buffer size field (forgot to dereference
        !           103:                                                                        the pointer).
        !           104:          <HFS1>        12/19/96        djb             first checked in
        !           105: 
        !           106: */
        !           107: 
        !           108: #include "../headers/FileMgrInternal.h"
        !           109: 
        !           110: #include "../headers/BTreesInternal.h"
        !           111: #include "../headers/BTreesPrivate.h"
        !           112: 
        !           113: 
        !           114: 
        !           115: 
        !           116: // B-tree callbacks...
        !           117: #if TARGET_OS_MAC
        !           118: OSStatus       GetBlockProc ( FileReference fileRefNum, UInt32 blockNum, GetBlockOptions options, BlockDescriptor *block );
        !           119: OSStatus       ReleaseBlockProc ( FileReference fileRefNum, BlockDescPtr blockPtr, ReleaseBlockOptions options );
        !           120: OSStatus       SetBlockSizeProc ( FileReference fileRefNum, ByteCount blockSize, ItemCount minBlockCount );
        !           121: #endif
        !           122: 
        !           123: 
        !           124: // local routines
        !           125: static OSErr   CheckBTreeKey(const BTreeKey *key, const BTreeControlBlock *btcb);
        !           126: static Boolean ValidHFSRecord(const void *record, const BTreeControlBlock *btcb, UInt16 recordSize);
        !           127: 
        !           128: 
        !           129: #if TARGET_OS_MAC
        !           130: OSErr OpenBTree(FileReference refNum, KeyCompareProcPtr keyCompareProc)
        !           131: {
        !           132:        FCB                                     *fcb;
        !           133:        OSStatus                         result;
        !           134:        
        !           135: 
        !           136:        fcb = GetFileControlBlock(refNum);
        !           137: 
        !           138:        result = BTOpenPath (fcb, keyCompareProc, GetBlockProc, ReleaseBlockProc, SetEndOfForkProc, SetBlockSizeProc);
        !           139:        ExitOnError(result);
        !           140:        
        !           141: ErrorExit:
        !           142: 
        !           143:        return result;
        !           144: }
        !           145: #endif /* TARGET_OS_MAC */
        !           146: 
        !           147: 
        !           148: #if TARGET_OS_MAC
        !           149: OSErr CloseBTree(FileReference refNum)
        !           150: {
        !           151:        OSErr   result;
        !           152: 
        !           153: 
        !           154:        result = BTClosePath ( GetFileControlBlock(refNum) );
        !           155:        ExitOnError(result);
        !           156:        
        !           157:        TrashCacheBlocks (refNum);
        !           158: 
        !           159: ErrorExit:
        !           160: 
        !           161:        return result;
        !           162: }
        !           163: #endif
        !           164: 
        !           165: 
        !           166: #if TARGET_OS_MAC
        !           167: OSErr FlushBTree(FileReference refNum)
        !           168: {
        !           169:        OSErr   result;
        !           170: 
        !           171: 
        !           172:        result = BTFlushPath( GetFileControlBlock(refNum) );
        !           173: 
        !           174:        return result;
        !           175: }
        !           176: #endif
        !           177: 
        !           178: 
        !           179: OSErr SearchBTreeRecord(FileReference refNum, const void* key, UInt32 hint, void* foundKey, void* data, UInt16 *dataSize, UInt32 *newHint)
        !           180: {
        !           181:        FSBufferDescriptor       btRecord;
        !           182:        BTreeIterator            searchIterator;
        !           183:        FCB                                     *fcb;
        !           184:        BTreeControlBlock       *btcb;
        !           185:        OSStatus                         result;
        !           186: 
        !           187: 
        !           188:        fcb = GetFileControlBlock(refNum);
        !           189:        btcb = (BTreeControlBlock*) fcb->fcbBTCBPtr;
        !           190: 
        !           191:        btRecord.bufferAddress = data;
        !           192:        btRecord.itemCount = 1;
        !           193:        if ( btcb->maxKeyLength == kHFSExtentKeyMaximumLength )
        !           194:                btRecord.itemSize = sizeof(HFSExtentRecord);
        !           195:        else if ( btcb->maxKeyLength == kHFSPlusExtentKeyMaximumLength )
        !           196:                btRecord.itemSize = sizeof(HFSPlusExtentRecord);
        !           197:        else
        !           198:                btRecord.itemSize = sizeof(CatalogRecord);
        !           199: 
        !           200:        searchIterator.hint.writeCount = 0;     // clear these out for debugging...
        !           201:        searchIterator.hint.reserved1 = 0;
        !           202:        searchIterator.hint.reserved2 = 0;
        !           203: 
        !           204:        searchIterator.hint.nodeNum = hint;
        !           205:        searchIterator.hint.index = 0;
        !           206: 
        !           207:        result = CheckBTreeKey((BTreeKey *) key, btcb);
        !           208:        ExitOnError(result);
        !           209: 
        !           210:        BlockMoveData(key, &searchIterator.key, CalcKeySize(btcb, (BTreeKey *) key));           //�� should we range check against maxkeylen?
        !           211:        
        !           212:        //      We only optimize for catalog records
        !           213:        if( btRecord.itemSize == sizeof(CatalogRecord) )
        !           214:        {
        !           215:                UInt32  heuristicHint;
        !           216:                UInt32  *cachedHint;
        !           217:                Ptr             hintCachePtr = fcb->fcbVPtr->hintCachePtr;
        !           218: 
        !           219:                //      We pass a 2nd hint/guess into BTSearchRecord.  The heuristicHint is a mapping of
        !           220:                //      dirID and nodeNumber, in hopes that the current search will be in the same node
        !           221:                //      as the last search with the same parentID.
        !           222:                result = GetMRUCacheBlock( ((HFSCatalogKey *)key)->parentID, hintCachePtr, (Ptr *)&cachedHint );
        !           223:                heuristicHint = (result == noErr) ? *cachedHint : kInvalidMRUCacheKey;
        !           224: 
        !           225:                result = BTSearchRecord( fcb, &searchIterator, heuristicHint, &btRecord, dataSize, &searchIterator );
        !           226: 
        !           227:                InsertMRUCacheBlock( hintCachePtr, ((HFSCatalogKey *)key)->parentID, (Ptr) &(searchIterator.hint.nodeNum) );
        !           228:        }
        !           229:        else
        !           230:        {
        !           231:                result = BTSearchRecord( fcb, &searchIterator, kInvalidMRUCacheKey, &btRecord, dataSize, &searchIterator );
        !           232:        }
        !           233: 
        !           234:        if (result == noErr)
        !           235:        {
        !           236:                *newHint = searchIterator.hint.nodeNum;
        !           237: 
        !           238:                result = CheckBTreeKey(&searchIterator.key, btcb);
        !           239:                ExitOnError(result);
        !           240: 
        !           241:                BlockMoveData(&searchIterator.key, foundKey, CalcKeySize(btcb, &searchIterator.key));   //�� warning, this could overflow user's buffer!!!
        !           242: 
        !           243:                if ( DEBUG_BUILD && !ValidHFSRecord(data, btcb, *dataSize) )
        !           244:                        DebugStr("\pSearchBTreeRecord: bad record?");
        !           245:        }
        !           246: 
        !           247: ErrorExit:
        !           248: 
        !           249:        return result;
        !           250: }
        !           251: 
        !           252: 
        !           253: 
        !           254: //     Note
        !           255: //     The new B-tree manager differs from the original b-tree in how it does iteration. We need
        !           256: //     to account for these differences here.  We save an iterator in the BTree control block so
        !           257: //     that we have a context in which to perfrom the iteration. Also note that the old B-tree
        !           258: //     allowed you to specify any number relative to the last operation (including 0) whereas the
        !           259: //     new B-tree only allows next/previous.
        !           260: #if TARGET_OS_MAC
        !           261: OSErr GetBTreeRecord(FileReference refNum, SInt16 selectionIndex, void* key, void* data, UInt16 *dataSize, UInt32 *newHint)
        !           262: {
        !           263:        FSBufferDescriptor      btRecord;
        !           264:        BTreeIterator           *iterator;
        !           265:        FCB                                     *fcb;
        !           266:        BTreeControlBlock       *btcb;
        !           267:        OSStatus                        result;
        !           268:        UInt16                          operation;
        !           269: 
        !           270: 
        !           271:        fcb = GetFileControlBlock(refNum);
        !           272: 
        !           273:        // pick up our iterator in the BTCB for context...
        !           274: 
        !           275:        btcb = (BTreeControlBlock*) fcb->fcbBTCBPtr;
        !           276:        iterator = &btcb->lastIterator;
        !           277: 
        !           278:        btRecord.bufferAddress = data;
        !           279:        btRecord.itemCount = 1;
        !           280:        if ( btcb->maxKeyLength == kHFSExtentKeyMaximumLength )
        !           281:                btRecord.itemSize = sizeof(HFSExtentRecord);
        !           282:        else if ( btcb->maxKeyLength == kHFSPlusExtentKeyMaximumLength )
        !           283:                btRecord.itemSize = sizeof(HFSPlusExtentRecord);
        !           284:        else
        !           285:                btRecord.itemSize = sizeof(CatalogRecord);
        !           286:        
        !           287:        // now we have to map index into next/prev operations...
        !           288:        
        !           289:        if (selectionIndex == 1)
        !           290:        {
        !           291:                operation = kBTreeNextRecord;
        !           292:        }
        !           293:        else if (selectionIndex == -1)
        !           294:        {
        !           295:                operation = kBTreePrevRecord;
        !           296:        }
        !           297:        else if (selectionIndex == 0)
        !           298:        {
        !           299:                operation = kBTreeCurrentRecord;
        !           300:        }
        !           301:        else if (selectionIndex == (SInt16) 0x8001)
        !           302:        {
        !           303:                operation = kBTreeFirstRecord;
        !           304:        }
        !           305:        else if (selectionIndex == (SInt16) 0x7FFF)
        !           306:        {
        !           307:                operation = kBTreeLastRecord;
        !           308:        }
        !           309:        else if (selectionIndex > 1)
        !           310:        {
        !           311:                UInt32  i;
        !           312: 
        !           313:                for (i = 1; i < selectionIndex; ++i)
        !           314:                {
        !           315:                        result = BTIterateRecord( fcb, kBTreeNextRecord, iterator, &btRecord, dataSize );
        !           316:                        ExitOnError(result);
        !           317:                }
        !           318:                operation = kBTreeNextRecord;
        !           319:        }
        !           320:        else // (selectionIndex < -1)
        !           321:        {
        !           322:                SInt32  i;
        !           323: 
        !           324:                for (i = -1; i > selectionIndex; --i)
        !           325:                {
        !           326:                        result = BTIterateRecord( fcb, kBTreePrevRecord, iterator, &btRecord, dataSize );
        !           327:                        ExitOnError(result);
        !           328:                }
        !           329:                operation = kBTreePrevRecord;
        !           330:        }
        !           331: 
        !           332:        result = BTIterateRecord( fcb, operation, iterator, &btRecord, dataSize );
        !           333: 
        !           334:        if (result == noErr)
        !           335:        {
        !           336:                *newHint = iterator->hint.nodeNum;
        !           337: 
        !           338:                result = CheckBTreeKey(&iterator->key, btcb);
        !           339:                ExitOnError(result);
        !           340:                
        !           341:                BlockMoveData(&iterator->key, key, CalcKeySize(btcb, &iterator->key));  //�� warning, this could overflow user's buffer!!!
        !           342:                
        !           343:                if ( DEBUG_BUILD && !ValidHFSRecord(data, btcb, *dataSize) )
        !           344:                        DebugStr("\pGetBTreeRecord: bad record?");
        !           345: 
        !           346:        }
        !           347:        
        !           348: ErrorExit:
        !           349: 
        !           350:        return result;
        !           351: }
        !           352: #endif /* TARGET_OS_MAC */
        !           353: 
        !           354: 
        !           355: OSErr InsertBTreeRecord(FileReference refNum, void* key, void* data, UInt16 dataSize, UInt32 *newHint)
        !           356: {
        !           357:        FSBufferDescriptor      btRecord;
        !           358:        BTreeIterator           iterator;
        !           359:        FCB                                     *fcb;
        !           360:        BTreeControlBlock       *btcb;
        !           361:        OSStatus                        result;
        !           362:        
        !           363: 
        !           364:        fcb = GetFileControlBlock(refNum);
        !           365:        btcb = (BTreeControlBlock*) fcb->fcbBTCBPtr;
        !           366: 
        !           367:        btRecord.bufferAddress = data;
        !           368:        btRecord.itemSize = dataSize;
        !           369:        btRecord.itemCount = 1;
        !           370: 
        !           371:        iterator.hint.nodeNum = 0;                      // no hint
        !           372: 
        !           373:        result = CheckBTreeKey((BTreeKey *) key, btcb);
        !           374:        ExitOnError(result);
        !           375: 
        !           376:        BlockMoveData(key, &iterator.key, CalcKeySize(btcb, (BTreeKey *) key)); //�� should we range check against maxkeylen?
        !           377: 
        !           378:        if ( DEBUG_BUILD && !ValidHFSRecord(data, btcb, dataSize) )
        !           379:                DebugStr("\pInsertBTreeRecord: bad record?");
        !           380: 
        !           381:        result = BTInsertRecord( fcb, &iterator, &btRecord, dataSize );
        !           382: 
        !           383:        *newHint = iterator.hint.nodeNum;
        !           384:        
        !           385: ErrorExit:
        !           386: 
        !           387:        return result;
        !           388: }
        !           389: 
        !           390: 
        !           391: OSErr DeleteBTreeRecord(FileReference refNum, void* key)
        !           392: {
        !           393:        BTreeIterator           iterator;
        !           394:        FCB                                     *fcb;
        !           395:        BTreeControlBlock       *btcb;
        !           396:        OSStatus                        result;
        !           397:        
        !           398: 
        !           399:        fcb = GetFileControlBlock(refNum);
        !           400:        btcb = (BTreeControlBlock*) fcb->fcbBTCBPtr;
        !           401:        
        !           402:        iterator.hint.nodeNum = 0;                      // no hint
        !           403: 
        !           404:        result = CheckBTreeKey((BTreeKey *) key, btcb);
        !           405:        ExitOnError(result);
        !           406: 
        !           407:        BlockMoveData(key, &iterator.key, CalcKeySize(btcb, (BTreeKey *) key)); //�� should we range check against maxkeylen?
        !           408: 
        !           409:        result = BTDeleteRecord( fcb, &iterator );
        !           410: 
        !           411: ErrorExit:
        !           412: 
        !           413:        return result;
        !           414: }
        !           415: 
        !           416: 
        !           417: OSErr ReplaceBTreeRecord(FileReference refNum, const void* key, UInt32 hint, void *newData, UInt16 dataSize, UInt32 *newHint)
        !           418: {
        !           419:        FSBufferDescriptor      btRecord;
        !           420:        BTreeIterator           iterator;
        !           421:        FCB                                     *fcb;
        !           422:        BTreeControlBlock       *btcb;
        !           423:        OSStatus                        result;
        !           424: 
        !           425: 
        !           426:        fcb = GetFileControlBlock(refNum);
        !           427:        btcb = (BTreeControlBlock*) fcb->fcbBTCBPtr;
        !           428: 
        !           429:        btRecord.bufferAddress = newData;
        !           430:        btRecord.itemSize = dataSize;
        !           431:        btRecord.itemCount = 1;
        !           432: 
        !           433:        iterator.hint.nodeNum = hint;
        !           434: 
        !           435:        result = CheckBTreeKey((BTreeKey *) key, btcb);
        !           436:        ExitOnError(result);
        !           437: 
        !           438:        BlockMoveData(key, &iterator.key, CalcKeySize(btcb, (BTreeKey *) key));         //�� should we range check against maxkeylen?
        !           439: 
        !           440:        if ( DEBUG_BUILD && !ValidHFSRecord(newData, btcb, dataSize) )
        !           441:                DebugStr("\pReplaceBTreeRecord: bad record?");
        !           442: 
        !           443:        result = BTReplaceRecord( fcb, &iterator, &btRecord, dataSize );
        !           444: 
        !           445:        *newHint = iterator.hint.nodeNum;
        !           446: 
        !           447:        //���do we need to invalidate the iterator?
        !           448: 
        !           449: ErrorExit:
        !           450: 
        !           451:        return result;
        !           452: }
        !           453: 
        !           454: 
        !           455: 
        !           456: #if TARGET_OS_MAC
        !           457: OSStatus GetBlockProc ( FileReference fileRefNum, UInt32 blockNum, GetBlockOptions options, BlockDescriptor *block )
        !           458: {
        !           459:     OSStatus   result;
        !           460:     short              cacheOptions = 0;
        !           461: 
        !           462:     if (options == kGetBlock)
        !           463:         cacheOptions = gbDefault;      
        !           464:     else if (options & kForceReadBlock)
        !           465:         cacheOptions = gbReadMask;     
        !           466:     else if (options & kGetEmptyBlock)
        !           467:         cacheOptions = gbNoReadMask;   
        !           468:     else
        !           469:         Panic ("\pGetBlockProc: Invalid option!");
        !           470: 
        !           471:     if ( block->blockSize == 512 )
        !           472:         {
        !           473:         result = GetBlock_glue( cacheOptions, blockNum, (Ptr *)&block->buffer, fileRefNum, GetFileControlBlock(fileRefNum)->fcbVPtr );
        !           474:         block->blockReadFromDisk = BlockCameFromDisk();
        !           475:         }
        !           476:     else
        !           477:         {
        !           478:         result = GetCacheBlock( fileRefNum, blockNum, block->blockSize, cacheOptions, &block->buffer, &block->blockReadFromDisk);
        !           479:         }
        !           480: 
        !           481:     return result;
        !           482: }
        !           483: #endif /* TARGET_OS_MAC */
        !           484: 
        !           485: 
        !           486: #if TARGET_OS_MAC
        !           487: OSStatus       ReleaseBlockProc ( FileReference fileRefNum, BlockDescPtr blockPtr, ReleaseBlockOptions options )
        !           488: {
        !           489: #pragma unused (fileRefNum)
        !           490: 
        !           491:        OSStatus        result;
        !           492:        short           cacheOptions = 0;
        !           493: 
        !           494: 
        !           495:        if (options == kReleaseBlock)
        !           496:                cacheOptions = rbDefault;       
        !           497:        else if (options & kMarkBlockDirty)
        !           498:                cacheOptions = rbDirtyMask;     
        !           499:        else if (options & kForceWriteBlock)
        !           500:                cacheOptions = rbWriteMask;     
        !           501:        else if (options & kTrashBlock)
        !           502:                cacheOptions = rbTrashMask;     
        !           503:        else
        !           504:                Panic ("\pGetBlockProc: Invalid option!");
        !           505:                
        !           506:        //�� if kReleaseBlock and just markdirty should we call markblock??
        !           507:        
        !           508:        if ( blockPtr->blockSize == 512 )
        !           509:                result = RelBlock_glue( blockPtr->buffer, cacheOptions );
        !           510:        else
        !           511:                result = ReleaseCacheBlock( blockPtr->buffer, cacheOptions );
        !           512: 
        !           513:        return result;
        !           514: }
        !           515: #endif /* TARGET_OS_MAC */
        !           516: 
        !           517: 
        !           518: #if TARGET_OS_MAC
        !           519: OSStatus
        !           520: SetBlockSizeProc ( FileReference fileRefNum, ByteCount blockSize, ItemCount minBlockCount)
        !           521: {
        !           522: #pragma unused (fileRefNum)
        !           523: 
        !           524:        OSStatus result;
        !           525: 
        !           526:        // for HFS Plus volumes we'll need to set up a big node cache...
        !           527: 
        !           528:        if ( blockSize > 512 )
        !           529:                result = InitializeBlockCache (blockSize, minBlockCount);
        !           530:        else
        !           531:                result = noErr;
        !           532:        
        !           533:        return result;
        !           534: }
        !           535: #endif /* TARGET_OS_MAC */
        !           536: 
        !           537: 
        !           538: 
        !           539: OSStatus
        !           540: SetEndOfForkProc ( FileReference fileRefNum, FSSize minEOF, FSSize maxEOF )
        !           541: {
        !           542: #pragma unused (maxEOF)
        !           543: 
        !           544:        OSStatus        result;
        !           545:        UInt32          actualBytesAdded;
        !           546:        UInt32          bytesToAdd;
        !           547:        ExtendedVCB     *vcb;
        !           548:        FCB                     *filePtr;
        !           549: 
        !           550: 
        !           551:        filePtr = GetFileControlBlock(fileRefNum);
        !           552: 
        !           553:        if ( minEOF > filePtr->fcbEOF )
        !           554:        {
        !           555:                bytesToAdd = minEOF - filePtr->fcbEOF;
        !           556: 
        !           557:                if (bytesToAdd < filePtr->fcbClmpSize)
        !           558:                        bytesToAdd = filePtr->fcbClmpSize;              //���why not always be a mutiple of clump size ???
        !           559:        }
        !           560:        else
        !           561:        {
        !           562:                if ( DEBUG_BUILD )
        !           563:                        DebugStr("\pSetEndOfForkProc: minEOF is smaller than current size!");
        !           564:                return -1;
        !           565:        }
        !           566: 
        !           567:        vcb = filePtr->fcbVPtr;
        !           568:        result = ExtendFileC ( vcb, filePtr, bytesToAdd, 0, &actualBytesAdded );
        !           569:        ReturnIfError(result);
        !           570: 
        !           571:        if (DEBUG_BUILD && actualBytesAdded < bytesToAdd)
        !           572:                DebugStr("\pSetEndOfForkProc: actualBytesAdded < bytesToAdd!");
        !           573:                
        !           574:        filePtr->fcbEOF = filePtr->fcbPLen;             // new B-tree looks at fcbEOF
        !           575:        
        !           576:        //
        !           577:        //      Update the Alternate MDB or Alternate VolumeHeader
        !           578:        //
        !           579:        if ( vcb->vcbSigWord == kHFSPlusSigWord )
        !           580:        {
        !           581:                //      If any of the HFS+ private files change size, flush them back to the Alternate volume header
        !           582:                if (    (filePtr->fcbFlNm == kHFSExtentsFileID) 
        !           583:                         ||     (filePtr->fcbFlNm == kHFSCatalogFileID)
        !           584:                         ||     (filePtr->fcbFlNm == kHFSStartupFileID)
        !           585:                         ||     (filePtr->fcbFlNm == kHFSAttributesFileID) )
        !           586:                {
        !           587:                        MarkVCBDirty( vcb );
        !           588:                        result = FlushAlternateVolumeControlBlock( vcb, true );
        !           589:                }
        !           590:        }
        !           591:        else if ( vcb->vcbSigWord == kHFSSigWord )
        !           592:        {
        !           593:                if ( filePtr->fcbFlNm == kHFSExtentsFileID )
        !           594:                {
        !           595:                        vcb->vcbXTAlBlks = filePtr->fcbPLen / vcb->blockSize;
        !           596:                        MarkVCBDirty( vcb );
        !           597:                        result = FlushAlternateVolumeControlBlock( vcb, false );
        !           598:                }
        !           599:                else if ( filePtr->fcbFlNm == kHFSCatalogFileID )
        !           600:                {
        !           601:                        vcb->vcbCTAlBlks = filePtr->fcbPLen / vcb->blockSize;
        !           602:                        MarkVCBDirty( vcb );
        !           603:                        result = FlushAlternateVolumeControlBlock( vcb, false );
        !           604:                }
        !           605:        }
        !           606:        
        !           607:        return result;
        !           608: 
        !           609: } // end SetEndOfForkProc
        !           610: 
        !           611: 
        !           612: static OSErr CheckBTreeKey(const BTreeKey *key, const BTreeControlBlock *btcb)
        !           613: {
        !           614:        UInt16  keyLen;
        !           615:        
        !           616:        if ( btcb->attributes & kBTBigKeysMask )
        !           617:                keyLen = key->length16;
        !           618:        else
        !           619:                keyLen = key->length8;
        !           620: 
        !           621:        if ( (keyLen < 6) || (keyLen > btcb->maxKeyLength) )
        !           622:        {
        !           623:                if ( DEBUG_BUILD )
        !           624:                        DebugStr("\pCheckBTreeKey: bad key length!");
        !           625:                return fsBTInvalidKeyLengthErr;
        !           626:        }
        !           627:        
        !           628:        return noErr;
        !           629: }
        !           630: 
        !           631: 
        !           632: static Boolean ValidHFSRecord(const void *record, const BTreeControlBlock *btcb, UInt16 recordSize)
        !           633: {
        !           634:        UInt32                  cNodeID;
        !           635:        
        !           636:        if ( btcb->maxKeyLength == kHFSExtentKeyMaximumLength )
        !           637:        {
        !           638:                return ( recordSize == sizeof(HFSExtentRecord) );
        !           639:        }
        !           640:        else if (btcb->maxKeyLength == kHFSPlusExtentKeyMaximumLength )
        !           641:        {
        !           642:                return ( recordSize == sizeof(HFSPlusExtentRecord) );
        !           643:        }
        !           644:        else if (btcb->maxKeyLength == kAttributeKeyMaximumLength )
        !           645:        {
        !           646:        HFSPlusAttrRecord       *attributeRecord = (HFSPlusAttrRecord *) record;
        !           647:                
        !           648:                switch (attributeRecord->recordType) {
        !           649:                        case kHFSPlusAttrInlineData:
        !           650:                                break;
        !           651:                        
        !           652:             case kHFSPlusAttrForkData:
        !           653:                                break;
        !           654:                        
        !           655:             case kHFSPlusAttrExtents:
        !           656:                                break;
        !           657:                }
        !           658:        }
        !           659:        else // Catalog record
        !           660:        {
        !           661:                CatalogRecord *catalogRecord = (CatalogRecord*) record;
        !           662: 
        !           663:                switch(catalogRecord->recordType)
        !           664:                {
        !           665:                        case kHFSFolderRecord:
        !           666:                        {
        !           667:                                if ( recordSize != sizeof(HFSCatalogFolder) )
        !           668:                                        return false;
        !           669:                                if ( catalogRecord->hfsFolder.flags != 0 )
        !           670:                                        return false;
        !           671:                                if ( catalogRecord->hfsFolder.valence > 0x7FFF )
        !           672:                                        return false;
        !           673:                                        
        !           674:                                cNodeID = catalogRecord->hfsFolder.folderID;
        !           675:        
        !           676:                                if ( (cNodeID == 0) || (cNodeID < 16 && cNodeID > 2) )
        !           677:                                        return false;
        !           678:                        }
        !           679:                        break;
        !           680: 
        !           681:                        case kHFSPlusFolderRecord:
        !           682:                        {
        !           683:                                if ( recordSize != sizeof(HFSPlusCatalogFolder) )
        !           684:                                        return false;
        !           685:                                if ( catalogRecord->hfsPlusFolder.flags != 0 )
        !           686:                                        return false;
        !           687:                                if ( catalogRecord->hfsPlusFolder.valence > 0x7FFF )
        !           688:                                        return false;
        !           689:                                        
        !           690:                                cNodeID = catalogRecord->hfsPlusFolder.folderID;
        !           691:        
        !           692:                                if ( (cNodeID == 0) || (cNodeID < 16 && cNodeID > 2) )
        !           693:                                        return false;
        !           694:                        }
        !           695:                        break;
        !           696:        
        !           697:                        case kHFSFileRecord:
        !           698:                        {
        !           699: //                             UInt16                                  i;
        !           700:                                HFSExtentDescriptor     *dataExtent;
        !           701:                                HFSExtentDescriptor     *rsrcExtent;
        !           702:                                
        !           703:                                if ( recordSize != sizeof(HFSCatalogFile) )
        !           704:                                        return false;                                                           
        !           705:                                if ( (catalogRecord->hfsFile.flags & ~(0x83)) != 0 )
        !           706:                                        return false;
        !           707:                                        
        !           708:                                cNodeID = catalogRecord->hfsFile.fileID;
        !           709:                                
        !           710:                                if ( cNodeID < 16 )
        !           711:                                        return false;
        !           712:                
        !           713:                                // make sure 0 � LEOF � PEOF for both forks
        !           714:                                
        !           715:                                if ( catalogRecord->hfsFile.dataLogicalSize < 0 )
        !           716:                                        return false;
        !           717:                                if ( catalogRecord->hfsFile.dataPhysicalSize < catalogRecord->hfsFile.dataLogicalSize )
        !           718:                                        return false;
        !           719:                                if ( catalogRecord->hfsFile.rsrcLogicalSize < 0 )
        !           720:                                        return false;
        !           721:                                if ( catalogRecord->hfsFile.rsrcPhysicalSize < catalogRecord->hfsFile.rsrcLogicalSize )
        !           722:                                        return false;
        !           723:                
        !           724:                                dataExtent = (HFSExtentDescriptor*) &catalogRecord->hfsFile.dataExtents;
        !           725:                                rsrcExtent = (HFSExtentDescriptor*) &catalogRecord->hfsFile.rsrcExtents;
        !           726:        
        !           727: #if 0
        !           728:                                for (i = 0; i < kHFSExtentDensity; ++i)
        !           729:                                {
        !           730:                                        if ( (dataExtent[i].blockCount > 0) && (dataExtent[i].startBlock == 0) )
        !           731:                                                return false;
        !           732:                                        if ( (rsrcExtent[i].blockCount > 0) && (rsrcExtent[i].startBlock == 0) )
        !           733:                                                return false;
        !           734:                                }
        !           735: #endif
        !           736:                        }
        !           737:                        break;
        !           738:        
        !           739:                        case kHFSPlusFileRecord:
        !           740:                        {
        !           741: //                             UInt16                                  i;
        !           742:                                HFSPlusExtentDescriptor *dataExtent;
        !           743:                                HFSPlusExtentDescriptor *rsrcExtent;
        !           744:                                
        !           745:                                if ( recordSize != sizeof(HFSPlusCatalogFile) )
        !           746:                                        return false;                                                           
        !           747:                                if ( (catalogRecord->hfsPlusFile.flags & ~(0x83)) != 0 )
        !           748:                                        return false;
        !           749:                                        
        !           750:                                cNodeID = catalogRecord->hfsPlusFile.fileID;
        !           751:                                
        !           752:                                if ( cNodeID < 16 )
        !           753:                                        return false;
        !           754:                
        !           755:                                // make sure 0 � LEOF � PEOF for both forks
        !           756:                                
        !           757:                                if ( catalogRecord->hfsPlusFile.dataFork.logicalSize.hi != 0 )
        !           758:                                        return false;
        !           759:                                if ( catalogRecord->hfsPlusFile.resourceFork.logicalSize.hi != 0 )
        !           760:                                        return false;
        !           761:                
        !           762:                                dataExtent = (HFSPlusExtentDescriptor*) &catalogRecord->hfsPlusFile.dataFork.extents;
        !           763:                                rsrcExtent = (HFSPlusExtentDescriptor*) &catalogRecord->hfsPlusFile.resourceFork.extents;
        !           764:        
        !           765: #if 0
        !           766:                                for (i = 0; i < kHFSPlusExtentDensity; ++i)
        !           767:                                {
        !           768:                                        if ( (dataExtent[i].blockCount > 0) && (dataExtent[i].startBlock == 0) )
        !           769:                                                return false;
        !           770:                                        if ( (rsrcExtent[i].blockCount > 0) && (rsrcExtent[i].startBlock == 0) )
        !           771:                                                return false;
        !           772:                                }
        !           773: #endif
        !           774:                        }
        !           775:                        break;
        !           776: 
        !           777:                        case kHFSFolderThreadRecord:
        !           778:                        case kHFSFileThreadRecord:
        !           779:                        {
        !           780:                                if ( recordSize != sizeof(HFSCatalogThread) )
        !           781:                                        return false;
        !           782:        
        !           783:                                cNodeID = catalogRecord->hfsThread.parentID;
        !           784:                                if ( (cNodeID == 0) || (cNodeID < 16 && cNodeID > 2) )
        !           785:                                        return false;
        !           786:                                                        
        !           787:                                if ( (catalogRecord->hfsThread.nodeName[0] == 0) ||
        !           788:                                         (catalogRecord->hfsThread.nodeName[0] > 31) )
        !           789:                                        return false;
        !           790:                        }
        !           791:                        break;
        !           792:                
        !           793:                        case kHFSPlusFolderThreadRecord:
        !           794:                        case kHFSPlusFileThreadRecord:
        !           795:                        {
        !           796:                                if ( recordSize > sizeof(HFSPlusCatalogThread) || recordSize < (sizeof(HFSPlusCatalogThread) - sizeof(HFSUniStr255)))
        !           797:                                        return false;
        !           798:        
        !           799:                                cNodeID = catalogRecord->hfsPlusThread.parentID;
        !           800:                                if ( (cNodeID == 0) || (cNodeID < 16 && cNodeID > 2) )
        !           801:                                        return false;
        !           802:                                                        
        !           803:                                if ( (catalogRecord->hfsPlusThread.nodeName.length == 0) ||
        !           804:                                         (catalogRecord->hfsPlusThread.nodeName.length > 255) )
        !           805:                                        return false;
        !           806:                        }
        !           807:                        break;
        !           808: 
        !           809:                        default:
        !           810:                                return false;
        !           811:                }
        !           812:        }
        !           813:        
        !           814:        return true;    // record appears to be OK
        !           815: }

unix.superglobalmegacorp.com

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