Annotation of XNU/bsd/hfs/hfscommon/BTree/BTreeAllocate.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:        File:           BTreeAllocate.c
        !            24: 
        !            25:        Contains:       BTree Node Allocation routines for the BTree Module.
        !            26: 
        !            27:        Version:        xxx put the technology version here xxx
        !            28: 
        !            29:        Written by:     Gordon Sheridan and Bill Bruffey
        !            30: 
        !            31:        Copyright:      � 1992-1999 by Apple Computer, Inc., all rights reserved.
        !            32: 
        !            33:        File Ownership:
        !            34: 
        !            35:                DRI:                            Don Brady
        !            36: 
        !            37:                Other Contact:          Mark Day
        !            38: 
        !            39:                Technology:                     File Systems
        !            40: 
        !            41:        Writers:
        !            42: 
        !            43:                (djb)   Don Brady
        !            44:                (ser)   Scott Roberts
        !            45:                (msd)   Mark Day
        !            46: 
        !            47:        Change History (most recent first):
        !            48: 
        !            49:           <MOSXS>        6/1/99        djb             Sync up with Mac OS 8.6.
        !            50:           <CS3>        11/24/97        djb             Remove some debug code (Panic calls).
        !            51:           <CS2>         7/24/97        djb             CallbackProcs now take refnum instead of an FCB.
        !            52:           <CS1>         4/23/97        djb             first checked in
        !            53: 
        !            54:          <HFS2>         2/19/97        djb             Change E_BadNodeType to fsBTBadNodeType.
        !            55:          <HFS1>        12/19/96        djb             first checked in
        !            56: 
        !            57:        History applicable to original Scarecrow Design:
        !            58: 
        !            59:                 <4>    10/25/96        ser             Changing for new VFPI
        !            60:                 <3>    10/18/96        ser             Converting over VFPI changes
        !            61:                 <2>     1/10/96        msd             Change 64-bit math to use real function names from Math64.i.
        !            62:                 <1>    10/18/95        rst             Moved from Scarecrow project.
        !            63: 
        !            64:                 <8>     1/12/95        wjk             Adopt Model FileSystem changes in D5.
        !            65:                 <7>     9/30/94        prp             Get in sync with D2 interface changes.
        !            66:                 <6>     7/22/94        wjk             Convert to the new set of header files.
        !            67:                 <5>     8/31/93        prp             Use U64SetU instead of S64Set.
        !            68:                 <4>     5/21/93        gs              Fix ExtendBTree bug.
        !            69:                 <3>     5/10/93        gs              Fix pointer arithmetic bug in AllocateNode.
        !            70:                 <2>     3/23/93        gs              finish ExtendBTree routine.
        !            71:                 <1>      2/8/93        gs              first checked in
        !            72:                 <0>      1/1/93        gs              begin AllocateNode and FreeNode
        !            73: 
        !            74: */
        !            75: 
        !            76: #include "../headers/BTreesPrivate.h"
        !            77: 
        !            78: ///////////////////// Routines Internal To BTreeAllocate.c //////////////////////
        !            79: 
        !            80: OSStatus       GetMapNode (BTreeControlBlockPtr          btreePtr,
        !            81:                                                BlockDescriptor                  *nodePtr,
        !            82:                                                UInt16                                  **mapPtr,
        !            83:                                                UInt16                                   *mapSize );
        !            84: 
        !            85: /////////////////////////////////////////////////////////////////////////////////
        !            86: 
        !            87: /*-------------------------------------------------------------------------------
        !            88: 
        !            89: Routine:       AllocateNode    -       Find Free Node, Mark It Used, and Return Node Number.
        !            90: 
        !            91: Function:      Searches the map records for the first free node, marks it "in use" and
        !            92:                        returns the node number found. This routine should really only be called
        !            93:                        when we know there are free blocks, otherwise it's just a waste of time.
        !            94: 
        !            95: Note:          We have to examine map nodes a word at a time rather than a long word
        !            96:                        because the External BTree Mgr used map records that were not an integral
        !            97:                        number of long words. Too bad. In our spare time could develop a more
        !            98:                        sophisticated algorithm that read map records by long words (and long
        !            99:                        word aligned) and handled the spare bytes at the beginning and end
        !           100:                        appropriately.
        !           101: 
        !           102: Input:         btreePtr        - pointer to control block for BTree file               
        !           103: 
        !           104: Output:                nodeNum         - number of node allocated
        !           105:                        
        !           106:                        
        !           107: Result:                noErr                   - success
        !           108:                        fsBTNoMoreMapNodesErr   - no free blocks were found
        !           109:                        != noErr                - failure
        !           110: -------------------------------------------------------------------------------*/
        !           111: 
        !           112: OSStatus       AllocateNode (BTreeControlBlockPtr              btreePtr, UInt32        *nodeNum)
        !           113: {
        !           114:        OSStatus                 err;
        !           115:        BlockDescriptor  node;
        !           116:        UInt16                  *mapPtr, *pos;
        !           117:        UInt16                   mapSize, size;
        !           118:        UInt16                   freeWord;
        !           119:        UInt16                   mask;
        !           120:        UInt16                   bitOffset;
        !           121:        UInt32                   nodeNumber;
        !           122:        
        !           123:        
        !           124:        nodeNumber              = 0;                            // first node number of header map record
        !           125:        node.buffer             = nil;                          // clear node.buffer to get header node
        !           126:                                                                                //      - and for ErrorExit
        !           127:        
        !           128:        while (true)
        !           129:        {
        !           130:                err = GetMapNode (btreePtr, &node, &mapPtr, &mapSize);
        !           131:                M_ExitOnError (err);
        !           132:                
        !           133:        //////////////////////// Find Word with Free Bit ////////////////////////////
        !           134: 
        !           135:                pos             = mapPtr;
        !           136:                size    = mapSize;
        !           137:                size  >>= 1;                                            // convert to number of words
        !           138:                                                //�� assumes mapRecords contain an integral number of words
        !           139: 
        !           140:                while ( size-- )
        !           141:                {
        !           142:                        if ( *pos++ != 0xFFFF )                 // assume test fails, and increment pos
        !           143:                                break;
        !           144:                }
        !           145: 
        !           146:                --pos;                                                          // whoa! backup
        !           147: 
        !           148:                if (*pos != 0xFFFF)                                     // hey, we got one!
        !           149:                        break;
        !           150:                
        !           151:                nodeNumber += mapSize << 3;                     // covert to number of bits (nodes)
        !           152:        }
        !           153:        
        !           154:        ///////////////////////// Find Free Bit in Word /////////////////////////////
        !           155: 
        !           156:        freeWord        = *pos;
        !           157:        bitOffset       =  15;
        !           158:        mask            =  0x8000;
        !           159:        
        !           160:        do {
        !           161:                if ( (freeWord & mask) == 0)
        !           162:                        break;
        !           163:                mask >>= 1;
        !           164:        } while (--bitOffset);
        !           165: 
        !           166:        ////////////////////// Calculate Free Node Number ///////////////////////////
        !           167:        
        !           168:        nodeNumber += ((pos - mapPtr) << 4) + (15 - bitOffset); // (pos-mapPtr) = # of words!
        !           169:        
        !           170:        
        !           171:        ///////////////////////// Check for End of Map //////////////////////////////
        !           172: 
        !           173:        if (nodeNumber >= btreePtr->totalNodes)
        !           174:        {
        !           175:                err = fsBTFullErr;
        !           176:                goto ErrorExit;
        !           177:        }
        !           178: 
        !           179:        /////////////////////////// Allocate the Node ///////////////////////////////
        !           180: 
        !           181:        *pos |= mask;                                           // set the map bit for the node
        !           182: 
        !           183:        err = UpdateNode (btreePtr, &node, 0, kLockTransaction);
        !           184:        M_ExitOnError (err);
        !           185:        
        !           186:        --btreePtr->freeNodes;
        !           187:        btreePtr->flags |= kBTHeaderDirty;
        !           188:        *nodeNum = nodeNumber;
        !           189:        
        !           190:        return noErr;
        !           191: 
        !           192: ////////////////////////////////// Error Exit ///////////////////////////////////
        !           193: 
        !           194: ErrorExit:
        !           195:        
        !           196:        (void) ReleaseNode (btreePtr, &node);
        !           197:        *nodeNum = 0;
        !           198:        
        !           199:        return  err;
        !           200: }
        !           201: 
        !           202: 
        !           203: 
        !           204: /*-------------------------------------------------------------------------------
        !           205: 
        !           206: Routine:       FreeNode        -       Clear allocation bit for node.
        !           207: 
        !           208: Function:      Finds the bit representing the node specified by nodeNum in the node
        !           209:                        map and clears the bit.
        !           210: 
        !           211: 
        !           212: Input:         btreePtr        - pointer to control block for BTree file
        !           213:                        nodeNum         - number of node to mark free
        !           214: 
        !           215: Output:                none                    
        !           216:                        
        !           217: Result:                noErr                   - success
        !           218:                        fsBTNoMoreMapNodesErr   - node number is beyond end of node map
        !           219:                        != noErr                - GetNode or ReleaseNode encountered some difficulty
        !           220: -------------------------------------------------------------------------------*/
        !           221: 
        !           222: OSStatus       FreeNode (BTreeControlBlockPtr          btreePtr, UInt32        nodeNum)
        !           223: {
        !           224:        OSStatus                 err;
        !           225:        BlockDescriptor  node;
        !           226:        UInt32                   nodeIndex;
        !           227:        UInt16                   mapSize;
        !           228:        UInt16                  *mapPos;
        !           229:        UInt16                   bitOffset;
        !           230:        
        !           231: 
        !           232:        //////////////////////////// Find Map Record ////////////////////////////////
        !           233:        nodeIndex                       = 0;                            // first node number of header map record
        !           234:        node.buffer                     = nil;                          // invalidate node.buffer to get header node
        !           235:        
        !           236:        while (nodeNum >= nodeIndex)
        !           237:        {
        !           238:                err = GetMapNode (btreePtr, &node, &mapPos, &mapSize);
        !           239:                M_ExitOnError (err);
        !           240:                
        !           241:                nodeIndex += mapSize << 3;                      // covert to number of bits (nodes)
        !           242:        }
        !           243:        
        !           244:        //////////////////////////// Mark Node Free /////////////////////////////////
        !           245: 
        !           246:        nodeNum -= (nodeIndex - (mapSize << 3));                        // relative to this map record
        !           247:        bitOffset = 15 - (nodeNum & 0x0000000F);                        // last 4 bits are bit offset
        !           248:        mapPos += nodeNum >> 4;                                                         // point to word containing map bit
        !           249:        M_ClearBitNum (*mapPos, bitOffset);                                     // clear it
        !           250:        
        !           251:        err = UpdateNode (btreePtr, &node, 0, kLockTransaction);
        !           252:        M_ExitOnError (err);
        !           253:        
        !           254: 
        !           255:        ++btreePtr->freeNodes;
        !           256:        btreePtr->flags |= kBTHeaderDirty;                                      //�� how about a macro for this
        !           257: 
        !           258:        return noErr;
        !           259: 
        !           260: ErrorExit:
        !           261: 
        !           262:        (void) ReleaseNode (btreePtr, &node);
        !           263: 
        !           264:        return  err;
        !           265: }
        !           266: 
        !           267: 
        !           268: 
        !           269: /*-------------------------------------------------------------------------------
        !           270: 
        !           271: Routine:       ExtendBTree     -       Call FSAgent to extend file, and allocate necessary map nodes.
        !           272: 
        !           273: Function:      This routine calls the the FSAgent to extend the end of fork, if necessary,
        !           274:                        to accomodate the number of nodes requested. It then allocates as many
        !           275:                        map nodes as are necessary to account for all the nodes in the B*Tree.
        !           276:                        If newTotalNodes is less than the current number of nodes, no action is
        !           277:                        taken.
        !           278: 
        !           279: Note:          Internal HFS File Manager BTree Module counts on an integral number of
        !           280:                        long words in map records, although they are not long word aligned.
        !           281: 
        !           282: Input:         btreePtr                - pointer to control block for BTree file
        !           283:                        newTotalNodes   - total number of nodes the B*Tree is to extended to
        !           284:                        
        !           285: Output:                none
        !           286:                        
        !           287: Result:                noErr           - success
        !           288:                        != noErr        - failure
        !           289: -------------------------------------------------------------------------------*/
        !           290: 
        !           291: OSStatus       ExtendBTree     (BTreeControlBlockPtr   btreePtr,
        !           292:                                                 UInt32                                 newTotalNodes )
        !           293: {
        !           294:        OSStatus                                 err;
        !           295:        FCB                                             *filePtr;
        !           296:        FSSize                                   minEOF, maxEOF;        
        !           297:        UInt16                                   nodeSize;
        !           298:        UInt32                                   oldTotalNodes;
        !           299:        UInt32                                   newMapNodes;
        !           300:        UInt32                                   mapBits, totalMapBits;
        !           301:        UInt32                                   recStartBit;
        !           302:        UInt32                                   nodeNum, nextNodeNum;
        !           303:        UInt32                                   firstNewMapNodeNum, lastNewMapNodeNum;
        !           304:        BlockDescriptor                  mapNode, newNode;
        !           305:        UInt16                                  *mapPos;
        !           306:        UInt16                                  *mapStart;
        !           307:        UInt16                                   mapSize;
        !           308:        UInt16                                   mapNodeRecSize;
        !           309:        UInt32                                   bitInWord, bitInRecord;
        !           310:        UInt16                                   mapIndex;
        !           311: 
        !           312: 
        !           313:        oldTotalNodes           = btreePtr->totalNodes;
        !           314:        if (newTotalNodes  <= oldTotalNodes)                            // we're done!
        !           315:                return  noErr;
        !           316: 
        !           317:        nodeSize                        = btreePtr->nodeSize;
        !           318:        filePtr                         = GetFileControlBlock(btreePtr->fileRefNum);
        !           319:        
        !           320:        mapNode.buffer          = nil;
        !           321:        newNode.buffer          = nil;
        !           322: 
        !           323:        mapNodeRecSize  = nodeSize - sizeof(BTNodeDescriptor) - 6;      // 2 bytes of free space (see note)
        !           324: 
        !           325:        //�� update for proper 64 bit arithmetic!!
        !           326: 
        !           327: 
        !           328:        //////////////////////// Count Bits In Node Map /////////////////////////////
        !           329:        
        !           330:        totalMapBits = 0;
        !           331:        do {
        !           332:                err = GetMapNode (btreePtr, &mapNode, &mapStart, &mapSize);
        !           333:                M_ExitOnError (err);
        !           334:                
        !           335:                mapBits         = mapSize << 3;                         // mapSize (in bytes) * 8
        !           336:                recStartBit     = totalMapBits;                         // bit number of first bit in map record
        !           337:                totalMapBits  += mapBits;
        !           338:                
        !           339:        } while ( ((BTNodeDescriptor*)mapNode.buffer)->fLink != 0 );
        !           340: 
        !           341:        if (DEBUG_BUILD && totalMapBits != CalcMapBits (btreePtr))
        !           342:                Panic ("\pExtendBTree: totalMapBits != CalcMapBits");
        !           343:                
        !           344:        /////////////////////// Extend LEOF If Necessary ////////////////////////////
        !           345: 
        !           346:        minEOF = newTotalNodes * nodeSize;
        !           347:        if ( filePtr->fcbEOF < minEOF )
        !           348:        {
        !           349:                //��
        !           350:                //��    ???? Does this B*Tree pack stop working when LEOF > 2^32-1?
        !           351:                //��
        !           352:                maxEOF = ((UInt32)0xFFFFFFFFL);
        !           353: 
        !           354:                err = btreePtr->setEndOfForkProc (btreePtr->fileRefNum, minEOF, maxEOF);
        !           355:                M_ExitOnError (err);
        !           356:        }
        !           357: 
        !           358:        
        !           359:        //////////////////// Calc New Total Number Of Nodes /////////////////////////
        !           360:        
        !           361:        newTotalNodes = filePtr->fcbEOF / nodeSize;             //�� hack!
        !           362:        //�� do we wish to perform any verification of newTotalNodes at this point?
        !           363: 
        !           364:        btreePtr->totalNodes     =  newTotalNodes;              //�� do we need to update freeNodes here too?
        !           365: 
        !           366: 
        !           367:        ////////////// Calculate Number Of New Map Nodes Required ///////////////////
        !           368: 
        !           369:        newMapNodes             = 0;
        !           370:        if (newTotalNodes > totalMapBits)
        !           371:        {
        !           372:                newMapNodes                     = (((newTotalNodes - totalMapBits) >> 3) / mapNodeRecSize) + 1;
        !           373:                firstNewMapNodeNum      = oldTotalNodes;
        !           374:                lastNewMapNodeNum       = firstNewMapNodeNum + newMapNodes - 1;
        !           375:        }
        !           376:        else
        !           377:        {
        !           378:                err = ReleaseNode (btreePtr, &mapNode);
        !           379:                M_ExitOnError (err);
        !           380:        
        !           381:                goto Success;
        !           382:        }
        !           383:        
        !           384: 
        !           385:        /////////////////////// Initialize New Map Nodes ////////////////////////////
        !           386: 
        !           387:        ((BTNodeDescriptor*)mapNode.buffer)->fLink = firstNewMapNodeNum;
        !           388: 
        !           389:        nodeNum         = firstNewMapNodeNum;
        !           390:        while (true)
        !           391:        {
        !           392:                err = GetNewNode (btreePtr, nodeNum, &newNode);
        !           393:                M_ExitOnError (err);
        !           394:                
        !           395:                ((NodeDescPtr)newNode.buffer)->numRecords       = 1;
        !           396:                ((NodeDescPtr)newNode.buffer)->kind = kBTMapNode;
        !           397:                
        !           398:                // set free space offset
        !           399:                *(UInt16 *)((Ptr)newNode.buffer + nodeSize - 4) = nodeSize - 6;
        !           400: 
        !           401:                if (nodeNum++ == lastNewMapNodeNum)
        !           402:                        break;
        !           403: 
        !           404:                ((BTNodeDescriptor*)newNode.buffer)->fLink = nodeNum;   // point to next map node
        !           405:                        
        !           406:                err = UpdateNode (btreePtr, &newNode, 0, kLockTransaction);
        !           407:                M_ExitOnError (err);
        !           408:        }
        !           409:        
        !           410:        err = UpdateNode (btreePtr, &newNode, 0, kLockTransaction);
        !           411:        M_ExitOnError (err);
        !           412:                
        !           413: 
        !           414:        ///////////////////// Mark New Map Nodes Allocated //////////////////////////
        !           415: 
        !           416:        nodeNum = firstNewMapNodeNum;
        !           417:        do {    
        !           418:                bitInRecord     = nodeNum - recStartBit;
        !           419: 
        !           420:                while (bitInRecord >= mapBits)
        !           421:                {
        !           422:                        nextNodeNum = ((NodeDescPtr)mapNode.buffer)->fLink;
        !           423:                        if ( nextNodeNum == 0)
        !           424:                        {
        !           425:                                err = fsBTNoMoreMapNodesErr;
        !           426:                                goto ErrorExit;
        !           427:                        }
        !           428:                        
        !           429:                        err = UpdateNode (btreePtr, &mapNode, 0, kLockTransaction);
        !           430:                        M_ExitOnError (err);
        !           431:                        
        !           432:                        err = GetNode (btreePtr, nextNodeNum, &mapNode);
        !           433:                        M_ExitOnError (err);
        !           434:                        
        !           435:                        mapIndex = 0;
        !           436:                        
        !           437:                        mapStart         = (UInt16 *) GetRecordAddress (btreePtr, mapNode.buffer, mapIndex);
        !           438:                        mapSize          = GetRecordSize (btreePtr, mapNode.buffer, mapIndex);
        !           439:                        
        !           440:                        if (DEBUG_BUILD && mapSize != M_MapRecordSize (btreePtr->nodeSize) )
        !           441:                        {
        !           442:                                Panic ("\pExtendBTree: mapSize != M_MapRecordSize");
        !           443:                        }
        !           444:                        
        !           445:                        mapBits         = mapSize << 3;         // mapSize (in bytes) * 8
        !           446:                        recStartBit     = totalMapBits;         // bit number of first bit in map record
        !           447:                        totalMapBits  += mapBits;
        !           448: 
        !           449:                        bitInRecord     = nodeNum - recStartBit;
        !           450:                }
        !           451: 
        !           452:                mapPos          = mapStart + ((nodeNum - recStartBit) >> 4);
        !           453:                bitInWord       = 15 - ((nodeNum - recStartBit) & 0x0000000F);
        !           454:                M_SetBitNum (*mapPos, bitInWord);
        !           455:                
        !           456:                ++nodeNum;
        !           457:                
        !           458:        } while (nodeNum <= lastNewMapNodeNum);
        !           459: 
        !           460:        err = UpdateNode (btreePtr, &mapNode, 0, kLockTransaction);
        !           461:        M_ExitOnError (err);
        !           462: 
        !           463:        
        !           464:        //////////////////////////////// Success ////////////////////////////////////
        !           465: 
        !           466: Success:
        !           467:        
        !           468:        btreePtr->totalNodes     =  newTotalNodes;
        !           469:        btreePtr->freeNodes             += (newTotalNodes - oldTotalNodes) - newMapNodes;
        !           470: 
        !           471:        btreePtr->flags                 |= kBTHeaderDirty;              //�� how about a macro for this
        !           472:        
        !           473:        return  noErr;
        !           474: 
        !           475: 
        !           476:        ////////////////////////////// Error Exit ///////////////////////////////////
        !           477: 
        !           478: ErrorExit:
        !           479: 
        !           480:        (void) ReleaseNode (btreePtr, &mapNode);
        !           481:        (void) ReleaseNode (btreePtr, &newNode);
        !           482:        
        !           483:        return  err;
        !           484: }
        !           485: 
        !           486: 
        !           487: 
        !           488: /*-------------------------------------------------------------------------------
        !           489: 
        !           490: Routine:       GetMapNode      -       Get the next map node and pointer to the map record.
        !           491: 
        !           492: Function:      Given a BlockDescriptor to a map node in nodePtr, GetMapNode releases
        !           493:                        it and gets the next node. If nodePtr->buffer is nil, then the header
        !           494:                        node is retrieved.
        !           495: 
        !           496: 
        !           497: Input:         btreePtr        - pointer to control block for BTree file
        !           498:                        nodePtr         - pointer to a BlockDescriptor of a map node
        !           499:                        
        !           500: Output:                nodePtr         - pointer to the BlockDescriptor for the next map node
        !           501:                        mapPtr          - pointer to the map record within the map node
        !           502:                        mapSize         - number of bytes in the map record
        !           503:                        
        !           504: Result:                noErr                   - success
        !           505:                        fsBTNoMoreMapNodesErr   - we've run out of map nodes
        !           506:                        fsBTInvalidNodeErr                      - bad node, or not node type kMapNode
        !           507:                        != noErr                - failure
        !           508: -------------------------------------------------------------------------------*/
        !           509: 
        !           510: OSStatus       GetMapNode (BTreeControlBlockPtr          btreePtr,
        !           511:                                                BlockDescriptor                  *nodePtr,
        !           512:                                                UInt16                                  **mapPtr,
        !           513:                                                UInt16                                   *mapSize )
        !           514: {
        !           515:        OSStatus        err;
        !           516:        UInt16          mapIndex;
        !           517:        UInt32          nextNodeNum;
        !           518:        
        !           519:        if (nodePtr->buffer != nil)             // if iterator is valid...
        !           520:        {
        !           521:                nextNodeNum = ((NodeDescPtr)nodePtr->buffer)->fLink;
        !           522:                if (nextNodeNum == 0)
        !           523:                {
        !           524:                        err = fsBTNoMoreMapNodesErr;
        !           525:                        goto ErrorExit;
        !           526:                }
        !           527:                
        !           528:                err = ReleaseNode (btreePtr, nodePtr);
        !           529:                M_ExitOnError (err);
        !           530:                
        !           531:                err = GetNode (btreePtr, nextNodeNum, nodePtr);
        !           532:                M_ExitOnError (err);
        !           533:                
        !           534:                if ( ((NodeDescPtr)nodePtr->buffer)->kind != kBTMapNode)
        !           535:                {
        !           536:                        err = fsBTBadNodeType;
        !           537:                        goto ErrorExit;
        !           538:                }
        !           539:                
        !           540:                ++btreePtr->numMapNodesRead;
        !           541:                mapIndex = 0;
        !           542:        } else {
        !           543:                err = GetNode (btreePtr, kHeaderNodeNum, nodePtr);
        !           544:                M_ExitOnError (err);
        !           545:                
        !           546:                if ( ((NodeDescPtr)nodePtr->buffer)->kind != kBTHeaderNode)
        !           547:                {
        !           548:                        err = fsBTInvalidHeaderErr;                             //�� or fsBTBadNodeType
        !           549:                        goto ErrorExit;
        !           550:                }
        !           551:                
        !           552:                mapIndex = 2;
        !           553:        }
        !           554:        
        !           555:                
        !           556:        *mapPtr         = (UInt16 *) GetRecordAddress (btreePtr, nodePtr->buffer, mapIndex);
        !           557:        *mapSize        = GetRecordSize (btreePtr, nodePtr->buffer, mapIndex);
        !           558:        
        !           559:        return noErr;
        !           560:        
        !           561:        
        !           562: ErrorExit:
        !           563:        
        !           564:        (void) ReleaseNode (btreePtr, nodePtr);
        !           565:        
        !           566:        *mapPtr         = nil;
        !           567:        *mapSize        = 0;
        !           568:        
        !           569:        return  err;
        !           570: }
        !           571: 
        !           572: 
        !           573: 
        !           574: ////////////////////////////////// CalcMapBits //////////////////////////////////
        !           575: 
        !           576: UInt32         CalcMapBits     (BTreeControlBlockPtr    btreePtr)
        !           577: {
        !           578:        UInt32          mapBits;
        !           579:        
        !           580:        mapBits         = M_HeaderMapRecordSize (btreePtr->nodeSize) << 3;
        !           581:        
        !           582:        while (mapBits < btreePtr->totalNodes)
        !           583:                mapBits += M_MapRecordSize (btreePtr->nodeSize) << 3;
        !           584:        
        !           585:        return  mapBits;
        !           586: }

unix.superglobalmegacorp.com

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