Annotation of kernel/bsd/hfs/hfscommon/Misc/VolumeRequests.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:           VolumeRequests.c
        !            27: 
        !            28:        Contains:       MountVolume and related utility routines for HFS & HFS Plus
        !            29: 
        !            30:        Version:        HFS Plus 1.0
        !            31: 
        !            32:        Written by:     Deric Horn
        !            33: 
        !            34:        Copyright:      � 1996-1998 by Apple Computer, Inc., all rights reserved.
        !            35: 
        !            36:        File Ownership:
        !            37: 
        !            38:                DRI:                            Deric Horn
        !            39: 
        !            40:                Other Contacts:         Mark Day, Don Brady
        !            41: 
        !            42:                Technology:                     File Systems
        !            43: 
        !            44:        Writers:
        !            45: 
        !            46:                (JL)    Jim Luther
        !            47:                (msd)   Mark Day
        !            48:                (DSH)   Deric Horn
        !            49:                (djb)   Don Brady
        !            50: 
        !            51:        Change History (most recent first):
        !            52:          <Rhap>         7/28/98        djb             GetDiskBlocks is now implemented in MacOSStubs.c (radar #2258148).
        !            53:          <Rhap>          4/3/98        djb             Conditionally remove FSVars reference from GetVolumeNameFromCatalog.
        !            54:          <Rhap>         3/31/98        djb             Sync up with final HFSVolumes.h header file.
        !            55:          <CS47>         1/29/98        DSH             TrashAllFSCaches is responsible for trashing all file system and
        !            56:                                                                        disk caches. Called from FlushVol when the HFS bit is set.
        !            57:          <CS46>        12/12/97        DSH             2003877, when vcbAllocPtr was copied to nextAllocation it was
        !            58:                                                                        getting sign extended.
        !            59:          <CS45>        11/26/97        DSH             2003459, fcbs was not being initialized if volume was offline
        !            60:                                                                        and we are executing an unconditional unmount.
        !            61:          <CS44>        11/24/97        DSH             2005507, FlushVolumeControlBlock() keeps MDB drCrDate in sync
        !            62:                                                                        with VolumeHeader createDate.
        !            63:          <CS43>        11/11/97        DSH             1685873, RemountWrappedVolumes was only remounting the first
        !            64:                                                                        HFS+ volume in the queue, causing HFS wrappers to be mounted if
        !            65:                                                                        multiple volumes had been mounted before InitHFSPlus.
        !            66:          <CS42>         11/4/97        DSH             Clear FCB when getting a new one.
        !            67:          <CS41>         11/3/97        JL              #2001483 - Removed unneeded parameters from MountVolume,
        !            68:                                                                        MountHFSVolume, MountHFSPlusVolume, GetVolumeInformation,
        !            69:                                                                        GetXVolumeInformation and AddVCB (and added local variables as
        !            70:                                                                        needed). Return WDCBRecPtr from UnMountVolume. Set wdcb
        !            71:                                                                        parameter to NULL in GetXVolumeInformation if working directory
        !            72:                                                                        was not specified.
        !            73:          <CS40>        10/31/97        DSH             Added consistencyStatus parameter to MountCheck
        !            74:          <CS39>        10/23/97        msd             Bug 1685113. The VolumeHeader's createDate should be in local
        !            75:                                                                        time (not GMT) and identical to the MDB's drCrDate (and VCB's
        !            76:                                                                        vcbCrDate). When checking for a remount of an offline HFS Plus
        !            77:                                                                        volume, compare write counts instead of mod dates (which could
        !            78:                                                                        be fooled by the user changing time zones). Force MountCheck to
        !            79:                                                                        run if the volume was last mounted by Bride 1.0b2 or earlier.
        !            80:          <CS38>        10/17/97        msd             Conditionalize DebugStrs.
        !            81:          <CS37>        10/13/97        djb             Update volumeNameEncodingHint when updating the volume name.
        !            82:          <CS36>        10/10/97        msd             Bug 1683571. The dates in the volume header are in GMT, so be
        !            83:                                                                        sure to convert them when mounting a volume or flushing the
        !            84:                                                                        volume header.
        !            85:          <CS35>         10/2/97        DSH             In UnmountVolume() check that the drive is on line before
        !            86:                                                                        determining if wrapper volume needs to be renamed causing IO.
        !            87:          <CS34>         10/1/97        DSH             Run on disk version of MountCheck instead of ROM version for
        !            88:                                                                        boot volumes1682475.
        !            89:          <CS33>         10/1/97        djb             Add calls to InvalidateCatalogCache (part of radar #1678833).
        !            90:          <CS32>         9/26/97        DSH             Removed debugging code: support for 'W' key wrapper mounting.
        !            91:          <CS31>         9/17/97        DSH             hfsPlusIOPosOffset was uninitialized for Wrapperless volumes.
        !            92:          <CS30>          9/5/97        djb             In MountVol initialize Catalog cache before calling Catalog!
        !            93:          <CS29>          9/4/97        msd             PropertyCloseVolume renamed to AttributesCloseVolume. Remove
        !            94:                                                                        call to AttributesOpenVolume (it no longer exists).
        !            95:          <CS28>          9/2/97        DSH             VolumeHeader is now 3rd sector in partition, altVH is 2nd to
        !            96:                                                                        last cor compatability.  Initial support for wrapperless
        !            97:                                                                        volumes.
        !            98:          <CS27>         8/26/97        djb             Only call CountRootFiles during MountVol.
        !            99:          <CS26>         8/20/97        msd             If the HFS Plus volume version doesn't match, mount the wrapper
        !           100:                                                                        instead.
        !           101:          <CS25>         8/19/97        djb             Add error handling to RenameWrapperVolume.
        !           102:          <CS24>         8/15/97        msd             Bug 1673999. In MakeVCBsExtendedVCBs, copy old VCB's vcbAllocPtr
        !           103:                                                                        to new VCB's nextAllocation field.
        !           104:          <CS23>         8/12/97        djb             Fixed GetXVolInfo to only use extended vcb fields for local
        !           105:                                                                        volumes (radar# 1673177)
        !           106:          <CS22>         8/11/97        DSH             vcbNmAlBlks is now taken from the embededExtent.blockCount
        !           107:                                                                        (1669121).
        !           108:          <CS21>         8/11/97        djb             Return actual count of files in root directory for HFS Plus
        !           109:                                                                        volumes (Radar #1669118). Added local CountRootFiles routine.
        !           110:                                                                        8/5/97 msd Make sure version field in VolumeHeader is exactly
        !           111:                                                                        kHFSPlusVersion. 8/1/97 djb GetXVolumeInformation now returns
        !           112:                                                                        extFSErr when FSID is nonzero (Radar #1649503).
        !           113:          <CS20>         7/25/97        DSH             Init and Dispose of GenericMRUCache within ExtendedVCB.
        !           114:          <CS19>         7/16/97        DSH             FilesInternal.x -> FileMgrInternal.x to avoid name collision
        !           115:          <CS18>         7/15/97        DSH             Remount Wrapper volumes mounted before HFS+ initialization
        !           116:                                                                        (166729)
        !           117:          <CS17>         7/15/97        djb             Remove ioXVersion checking in GetXVolInfo (radar #1666217).
        !           118:          <CS16>          7/8/97        DSH             Loading PrecompiledHeaders from define passed in on C line
        !           119:          <CS15>          7/7/97        djb             Add GetVolumeNameFromCatalog routine.
        !           120:          <CS14>          7/7/97        DSH             GetNewVRefNum now get's a recycled vRefNum. Bug 1664445 in
        !           121:                                                                        Installer was cacheing the vRefNum while CheckDisk unmounts and
        !           122:                                                                        remounts disk.
        !           123:          <CS13>         6/30/97        DSH             shadowing values obsoleteVCBXTRef, and obsoleteVCBCTRef when
        !           124:                                                                        HFS+ volume is mounted.
        !           125:          <CS12>         6/26/97        DSH             GetVolInfo returns HFS signature for HFS+ volumes, GetXVolInfo
        !           126:                                                                        returns real signature.
        !           127:          <CS11>         6/24/97        DSH             MakeVCBsExtendedVCBs was using wdcb->count as count not byte
        !           128:                                                                        count.
        !           129:          <CS10>         6/18/97        djb             Set/get volume encodingsBitmap.
        !           130:           <CS9>         6/16/97        msd             Include String.h and Disks.h.
        !           131:           <CS8>         6/12/97        djb             Get in sync with HFS Plus format changes.
        !           132:           <CS7>         6/11/97        msd             Make GetXVolumeInformation return true allocation block size. It
        !           133:                                                                        now checks the ioXVersion field.
        !           134:           <CS6>         5/28/97        msd             When flushing the volume header, write out the allocation file's
        !           135:                                                                        clump size (from the FCB). When mounting an HFS Plus volume,
        !           136:                                                                        zero the entire FCB extent record, not just the first extent,
        !           137:                                                                        for the various volume control files.
        !           138:           <CS5>         5/19/97        djb             Add calls to CreateVolumeCatalogCache,
        !           139:                                                                        DisposeVolumeCatalogCache.
        !           140:           <CS4>          5/9/97        djb             Get in sync with new FilesInternal.i
        !           141:           <CS3>          5/8/97        DSH             Only mount HFS+ volumes with version < 2.0 in the VolumeHeader.
        !           142:                                                                        Return wrgVolTypErr if too new.
        !           143:           <CS2>          5/2/97        djb             Disable Manual Eject code since its buggy!
        !           144:           <CS1>         4/25/97        djb             first checked in
        !           145: 
        !           146:         <HFS32>         4/11/97        DSH             MountHFSPlusVolume gets volume name from catalog, and
        !           147:                                                                        UnmountVolume shadows the name back to the wrapper partition.
        !           148:         <HFS31>          4/8/97        msd             Once volume is mounted, call AttributesOpenVolume to allow a
        !           149:                                                                        buffer to be allocated.
        !           150:         <HFS30>          4/7/97        msd             In FlushVolumeControlBlock, don't update the attributes BTree
        !           151:                                                                        fields in the Volume Header unless an attributes BTree was
        !           152:                                                                        already open.
        !           153:         <HFS29>          4/7/97        msd             In SetupFCB, add case for attributes BTree. Add code to set up
        !           154:                                                                        the attributes BTree. Remove call to PropertyOpenVolume. In
        !           155:                                                                        FlushVolumeControlBlock, write out any changes to the attributes
        !           156:                                                                        BTree.
        !           157:         <HFS28>          4/4/97        djb             Get in sync with volume format changes.
        !           158:         <HFS27>         3/31/97        djb             Added catalogDataCache to VCB; Remove ClearMem routine.
        !           159:         <HFS26>         3/18/97        msd             In MountHFSPlusVolume, the free blocks calculation can overflow,
        !           160:                                                                        setting vcbFreeBks to a too-small value.
        !           161:         <HFS25>         3/17/97        DSH             Added some utility functions AddVCB, GetParallelFCBFromRefNum,
        !           162:                                                                        casting for SC, and made some functions extern for DFA.
        !           163:         <HFS24>          3/5/97        msd             Add calls to Property Manager to open and close the volume. When
        !           164:                                                                        unmounting an HFS+ volume, the allocation (bitmap) file now gets
        !           165:                                                                        closed.
        !           166:         <HFS23>         2/19/97        djb             Update to 16-bit HFS Plus signature.
        !           167:         <HFS22>         2/12/97        msd             In GetXVolumeInformation, the result code could be
        !           168:                                                                        uninitialized.
        !           169:         <HFS21>         1/23/97        DSH             UpdateAlternateVoumeControlBlock()
        !           170:         <HFS20>         1/15/97        djb             Remove MountCheckStub. Add file names to fcbs for debugging.
        !           171:         <HFS19>         1/13/97        DSH             Use ExtendedVCB nextAllocation instead of vcbAllocPtr through
        !           172:                                                                        all code.
        !           173:         <HFS18>          1/9/97        djb             Get in sync with new VolumeHeader and Extended VCB.
        !           174:         <HFS17>          1/6/97        djb             Changed API to ParallelFCBFromRefnum (pragma parameter was
        !           175:                                                                        broken).
        !           176:         <HFS16>          1/6/97        msd             Set only the defined bits in the MDB drAtrb field (when copying
        !           177:                                                                        from VCB vcbAtrb field).
        !           178:         <HFS15>          1/6/97        DSH             CloseFile requires VCB to be passed in.
        !           179:         <HFS14>          1/6/97        djb             FlushVolumeControlBlock was writing to absolute block 0 instead
        !           180:                                                                        of to block zero of the embedded volume.
        !           181:         <HFS13>        12/20/96        msd             A comparison was using "=" instead of "=="; might have caused
        !           182:                                                                        the wrong volume to be set as the default.
        !           183:         <HFS12>        12/19/96        DSH             Setting up ExtendedVCBs
        !           184:         <HFS11>        12/19/96        djb             Updated for new B-tree Manager interface.
        !           185:         <HFS10>        12/18/96        msd             Change GetVCBRefNum so it can actually return a VCB pointer.
        !           186:          <HFS9>        12/12/96        djb             Use new SPI for GetCatalogNode.
        !           187:          <HFS8>        12/12/96        msd             Fix a bunch of errors (mostly type mismatch) when compiling with
        !           188:                                                                        Metrowerks.
        !           189:          <HFS7>        12/12/96        DSH             adding some util functions
        !           190:          <HFS6>        12/10/96        msd             Check PRAGMA_LOAD_SUPPORTED before loading precompiled headers.
        !           191:          <HFS5>         12/4/96        DSH             Ported GetVolumeInformation & GetXVolumeInformation.
        !           192:                <3*>    11/20/96        DSH             HFS Plus support to MountVolume
        !           193:          <HFS3>        11/20/96        DSH             Added UnmountVol and related routines, also backed out <2>
        !           194:                                                                        because C_FXMKeyCmp is passed as a parameter from C but called
        !           195:                                                                        from Asm in BTOpen so we need a Case ON Asm entry point.
        !           196:          <HFS2>        11/20/96        msd             Use CompareExtentKeys() instead of CFXMKeyCmp().
        !           197:          <HFS1>        11/19/96        DSH             first checked in
        !           198:                 <1>    11/19/96        DSH             first checked in
        !           199: 
        !           200: */
        !           201: 
        !           202: #if ( PRAGMA_LOAD_SUPPORTED )
        !           203:         #pragma        load    PrecompiledHeaders
        !           204: #else
        !           205:         #if TARGET_OS_MAC
        !           206:        #include        <Files.h>
        !           207:         #include       <FSM.h>
        !           208:         #include       <OSUtils.h>
        !           209:         #include       <LowMemPriv.h>
        !           210:         #include       <LowMem.h>
        !           211:         #include       <StringCompare.h>
        !           212:         #include       <Errors.h>
        !           213:         #include       <Devices.h>
        !           214:         #include       <SonyPriv.h>
        !           215:         #include       <EDiskPriv.h>
        !           216:         #include       <String.h>
        !           217:         #include       <Disks.h>
        !           218:         #else
        !           219:        #include "../../hfs.h"
        !           220:                #include "../headers/system/MacOSStubs.h"
        !           221:         #endif         /* TARGET_OS_MAC */
        !           222: #endif /* PRAGMA_LOAD_SUPPORTED */
        !           223: 
        !           224: #if TARGET_OS_MAC
        !           225: #include       <HardwarePriv.h>
        !           226: #endif
        !           227: 
        !           228: #include       "../headers/FileMgrInternal.h"
        !           229: #include       "../headers/HFSVolumes.h"
        !           230: 
        !           231: 
        !           232: #define                kIDSectorOffset 2
        !           233: 
        !           234: // Exported routine prototypes
        !           235: OSErr  MountVolume( VolumeParam *volume, Boolean forceHFSWrapperToMount );
        !           236: 
        !           237: OSErr  MountHFSVolume( short driveNumber, IOParam* lowMemParamBlock, OSErr err );
        !           238: 
        !           239: OSErr  MountHFSPlusVolume( short driveNumber, IOParam* lowMemParamBlock, OSErr err, Boolean pureHFSPlusVolume );
        !           240: 
        !           241: OSErr  GetVolumeInformation( HVolumeParam *volume, WDCBRecPtr *wdcb );
        !           242: 
        !           243: OSErr  GetXVolumeInformation( XVolumeParam *volume, WDCBRecPtr *wdcb );
        !           244: 
        !           245: 
        !           246: //     Utility function prototypes
        !           247: #if TARGET_OS_MAC
        !           248: OSErr  FindFileControlBlock( File *index, Ptr *fcbsH );
        !           249: 
        !           250: Boolean        GetNextFileControlBlock( UInt16 *index, Ptr fcbsPtr );
        !           251: 
        !           252: void   Get1stFileControlBlock( UInt16 *index, Ptr *fcbsH );
        !           253: 
        !           254: void   DisposeFileControlBlocks( ExtendedVCB *vcb );
        !           255: #else
        !           256: OSErr  GetNewFCB( ExtendedVCB *vcb, FileReference* fRefPtr);
        !           257: #endif
        !           258: 
        !           259: OSErr  AccessBTree( ExtendedVCB *vcb, FileReference refNum, UInt32 fileID, UInt32 fileClumpSize, void *CompareRoutine );
        !           260: 
        !           261: UInt16 DivUp( UInt32 byteRun, UInt32 blockSize );
        !           262: 
        !           263: Boolean        IsARamDiskDriver( void );
        !           264: 
        !           265: OSErr  GetVCBRefNum( ExtendedVCB **vcb, short vRefNum );
        !           266: 
        !           267: OSErr  ValidMasterDirectoryBlock( HFSMasterDirectoryBlock *mdb );
        !           268: 
        !           269: void   RenameWrapperVolume( Str27 newVolumeName, UInt16 driveNumber );
        !           270: 
        !           271: OSErr  CheckExternalFileSystem( ExtendedVCB *vcb );
        !           272: 
        !           273: OSErr  FlushVolume( ExtendedVCB *vcb );
        !           274: 
        !           275: FCB            *SetupFCB( ExtendedVCB *vcb, FileReference refNum, UInt32 fileID, UInt32 fileClumpSize );
        !           276: 
        !           277: OSErr  GetDiskBlocks( ExtendedVCB *vcb, unsigned long *numBlocks);
        !           278: 
        !           279: void   AddVCB( ExtendedVCB     *vcb, short driveNumber, short ioDRefNum );
        !           280: 
        !           281: short  IsPressed( unsigned short k );
        !           282: 
        !           283: FileReference  GetNewVRefNum();
        !           284: 
        !           285: OSErr  GetVolumeNameFromCatalog(ExtendedVCB *vcb);
        !           286: 
        !           287: #if TARGET_OS_MAC
        !           288: static UInt16 CountRootFiles(ExtendedVCB *vcb);
        !           289: #endif /* TARGET_OS_MAC */
        !           290: 
        !           291: 
        !           292: #if ( hasHFSManualEject )
        !           293: static void SetVCBManEject(ExtendedVCB *vcb);
        !           294: #endif
        !           295: 
        !           296: // External routines
        !           297: 
        !           298: extern OSErr   C_FlushMDB( ExtendedVCB *volume );
        !           299: 
        !           300: extern OSErr   DisposeVolumeCacheBlocks( ExtendedVCB *vcb );
        !           301: 
        !           302: extern void    DisposeVolumeControlBlock( ExtendedVCB *vcb );
        !           303: 
        !           304: extern OSErr   DeturmineVolume1( VolumeParam *iopb, short *nameLength, Boolean *nameSpecified, ExtendedVCB **vcb, WDCBRec **wdcb, unsigned char **pathName );
        !           305: 
        !           306: extern OSErr   DeturmineVolume3( VolumeParam *iopb, short *nameLength, Boolean *nameSpecified, ExtendedVCB **vcb, WDCBRec **wdcb, unsigned char **pathName );
        !           307: 
        !           308: extern OSErr   FlushVolumeBuffers( ExtendedVCB *vcb );
        !           309: 
        !           310: extern void    MultiplyUInt32IntoUInt64( UInt64 *wideResult, UInt32 num1, UInt32 num2 );
        !           311: 
        !           312: extern void            TrashCatalogNodeCache( void );
        !           313: 
        !           314: 
        !           315: 
        !           316: #if TARGET_OS_MAC
        !           317: //�������������������������������������������������������������������������������
        !           318: //     Routine:        MountVolume
        !           319: //
        !           320: // Function:   The VCB pointers are checked to see if a volume in the
        !           321: //                             specified drive is already on-line (error if so).  Reads in the
        !           322: //                             directory master block and allocates memory for VCB and additional
        !           323: //                             data structures, depending on the volume type:
        !           324: //
        !           325: //                             - For MFS volumes (handled in MFSVol), space is allocated for
        !           326: //                               a volume buffer, as well as the block map, which is read in
        !           327: //                               from disk).
        !           328: //
        !           329: //                             - For TFS volumes, space is allocated for a bitmap cache, a volume
        !           330: //                               control cache (for B*-Tree use), and a volume cache.  In addition,
        !           331: //                               two FCBs are used by the B*-Trees.
        !           332: //
        !           333: //                             No new VCB storage is allocated for remounts.
        !           334: //
        !           335: //�������������������������������������������������������������������������������
        !           336: 
        !           337: OSErr  MountVolume( VolumeParam *volume, Boolean forceHFSWrapperToMount )
        !           338: {
        !           339:        Byte                                    blockBuffer[512];
        !           340:        IOParam                                 *lowMemParamBlock;
        !           341:        short                                   ioRefNum;
        !           342:        short                                   vRefNum;
        !           343:        OSErr                                   err;
        !           344:        DrvQEl                                  *dqe;
        !           345:        Boolean                                 pureHFSPlusVolume;
        !           346:        
        !           347:        
        !           348:        //--- FSQueueSync was already called by the MountVol glue.
        !           349:        
        !           350:        vRefNum = volume->ioVRefNum;
        !           351:        err = FindDrive( &ioRefNum, &dqe, vRefNum );                                                    //      Get driver refnum
        !           352:        if ( err == noErr )
        !           353:        {
        !           354:                lowMemParamBlock                                = (IOParam *) LMParamBlock;
        !           355:                lowMemParamBlock->ioVRefNum             = vRefNum;
        !           356:                lowMemParamBlock->ioRefNum              = ioRefNum;
        !           357:                lowMemParamBlock->ioBuffer              = (char *)blockBuffer;
        !           358:                lowMemParamBlock->ioPosMode             = fsFromStart;
        !           359:                lowMemParamBlock->ioPosOffset   = kIDSectorOffset * 512;                        //      MDB is always at block #2
        !           360:                lowMemParamBlock->ioReqCount    = 512;                                                          //      MDB is always 1 512 byte block
        !           361:                
        !           362:                err = PBReadSync( (ParmBlkPtr) lowMemParamBlock );                                      //      Read the MDB
        !           363:                
        !           364:                pureHFSPlusVolume       = ((HFSPlusVolumeHeader *)blockBuffer)->signature == kHFSPlusSigWord;
        !           365:                
        !           366:                if (    ( ((HFSMasterDirectoryBlock *)blockBuffer)->drEmbedSigWord == kHFSPlusSigWord   //      Wrapped HFS+ volume
        !           367:                        ||      pureHFSPlusVolume == true )                                                                     //      Pure HFS+ volume
        !           368:                        &&      err == noErr
        !           369:                        &&      forceHFSWrapperToMount == false )                                                       //      if we don't want to force the wrapper to mount
        !           370:                {
        !           371:                        err = MountHFSPlusVolume( vRefNum, lowMemParamBlock, err, pureHFSPlusVolume );
        !           372:                }
        !           373:                else                                                                                                                            //      pass all other volume formats / errors to MountHFSVolume
        !           374:                {
        !           375:                        err = MountHFSVolume( vRefNum, lowMemParamBlock, err );
        !           376:                }
        !           377:        }
        !           378:        
        !           379:        return( err );                                                                                                                  //      pass the error back to CmdDone
        !           380: }
        !           381: #endif /* TARGET_OS_MAC */
        !           382: 
        !           383: 
        !           384: #if TARGET_OS_MAC
        !           385: //�������������������������������������������������������������������������������
        !           386: //     Routine:        MountHFSPlusVolume
        !           387: //
        !           388: // Function:   Called by MountVolume()
        !           389: //
        !           390: //     At this point we know that the MDB's Embeded signature indicates that
        !           391: //     this is an HFS Plus disk with an HFS wrapper.
        !           392: //
        !           393: //�������������������������������������������������������������������������������
        !           394: 
        !           395: OSErr  MountHFSPlusVolume( short driveNumber, IOParam* lowMemParamBlock, OSErr err, Boolean pureHFSPlusVolume )
        !           396: {
        !           397:        HFSMasterDirectoryBlock *mdb;
        !           398:        Byte                                    blockBuffer[512];
        !           399:        HFSPlusVolumeHeader             *volumeHeader;
        !           400:        ExtendedVCB                             *vcb;
        !           401:        QHdr                                    *vcbQHdr;
        !           402:        Byte                                    *flagsP;
        !           403:        Byte                                    *pbFlagsP;
        !           404:        SInt16                                  ioRefNum;
        !           405:        FSVarsRec                               *fsVars;
        !           406:        DrvQEl                                  *dqe;
        !           407:        IOParam                                 *currentIORequestPB;
        !           408:        FCB                                             *fcb;
        !           409:        Ptr                                     fcbsP;
        !           410:        ExtendedFCB                             *extendedFCB;
        !           411:        UInt32                                  hfsPlusIOPosOffset;
        !           412:        UInt16                                  hfsBlockCount;
        !           413:        UInt32                                  hfsBlockSize;
        !           414:        UInt32                                  lastMountedVersion;
        !           415:        UInt16                                  fcbIndexP;
        !           416: 
        !           417:        //--    Now read the HFS Plus VolumeHeader located at the first block within the embeded volume
        !           418: 
        !           419:        ioRefNum = lowMemParamBlock->ioRefNum;
        !           420:        
        !           421:        if ( pureHFSPlusVolume == false )
        !           422:        {
        !           423:                mdb = (HFSMasterDirectoryBlock *) lowMemParamBlock->ioBuffer;
        !           424: 
        !           425:                hfsPlusIOPosOffset                              =       (mdb->drEmbedExtent.startBlock * mdb->drAlBlkSiz) + ( mdb->drAlBlSt * 512 );
        !           426:                
        !           427:                lowMemParamBlock->ioPosMode             =       fsFromStart;                            
        !           428:                lowMemParamBlock->ioPosOffset   =       hfsPlusIOPosOffset + (kIDSectorOffset * 512);           //      VolumeHeader is 2 sectors in
        !           429:                lowMemParamBlock->ioBuffer              =       (char *)blockBuffer;
        !           430: 
        !           431:                err = PBReadSync( (ParmBlkPtr) lowMemParamBlock );                                              //      Read the VolumeHeader
        !           432:        }
        !           433:        else
        !           434:        {
        !           435:                hfsPlusIOPosOffset      = 0;            //      From beginning of volume.
        !           436:        }
        !           437:        
        !           438:        volumeHeader = (HFSPlusVolumeHeader *) lowMemParamBlock->ioBuffer;
        !           439:        
        !           440:        err = ValidVolumeHeader( volumeHeader );
        !           441: 
        !           442:        if (err == badMDBErr || err == noMacDskErr)
        !           443:                return err;                                                                                                                     // it's not valid, so don't try to mount it
        !           444: 
        !           445:        if ( err == noErr )
        !           446:        {
        !           447:                err             = notARemountErr;                                                                                       //      cuz we're looking for remounts only here
        !           448:                vcbQHdr = LMGetVCBQHdr();                                                                                       //      search the queue of VCBs
        !           449: 
        !           450:                for ( vcb = (ExtendedVCB*)vcbQHdr->qHead ; vcb != nil ; vcb = (ExtendedVCB*)vcb->qLink )        //      search the queue of VCBs
        !           451:                {
        !           452:                        if (   (vcb->vcbDrvNum  == 0)                                                                   //      matching volume better be off-line (0 drive num)
        !           453:                                && (vcb->vcbSigWord     == volumeHeader->signature)                             //      Same signature?
        !           454:                                && (vcb->vcbCrDate      == volumeHeader->createDate)                    //      Same create date?
        !           455:                                && (vcb->vcbWrCnt       == volumeHeader->writeCount)                    //      Same write count?
        !           456:                           )
        !           457:                        {
        !           458:                                //      At this point, we're fairly certain that the two volumes are, in fact, the same,
        !           459:                                //      but just to make sure (and avoid problems with stuck clocks), we'll compare the
        !           460:                                //      volume names as well:
        !           461:                                
        !           462:                                //��    How do I compare unicode names?
        !           463:                                //��    do we just skip this check?
        !           464:                //              if ( EqualString( vcb->volumeName, volumeHeader->volumeName, true, true) )      //      caseSensitive, diacSensitive
        !           465:                                        break;                                                                                                  //      Remount
        !           466:                        }
        !           467:                }
        !           468:                if ( vcb == nil ) goto RemountExit;
        !           469: 
        !           470: 
        !           471:                ((CntrlParam*)lowMemParamBlock)->csCode = drvStsCode;                           //      Drive status!
        !           472:                ((CntrlParam*)lowMemParamBlock)->csParam[1] &= 0x00ff;                          //      Clear status byte for return
        !           473:                
        !           474:                err = PBStatusSync( (ParmBlkPtr)lowMemParamBlock );                                     //      refnum and drivenum set up by read call
        !           475: 
        !           476: 
        !           477:                //--    Now propagate the write protect status byte back to the vcb
        !           478:                flagsP = (Byte *)((Ptr)(&(vcb->vcbAtrb))) + 1;
        !           479:                pbFlagsP = (Byte *)((Ptr)(((CntrlParam*)lowMemParamBlock)->csParam)+2);
        !           480:                *flagsP = *pbFlagsP & kVolumeHardwareLockMask;
        !           481: 
        !           482:                vcb->vcbDrvNum  = driveNumber;
        !           483:                vcb->vcbDRefNum = ioRefNum;                                                                                     //      Driver RefNum
        !           484:                
        !           485:                #if ( hasHFSManualEject )
        !           486:                        SetVCBManEject(vcb);
        !           487:                #endif
        !           488: 
        !           489: 
        !           490:                if ( !(*flagsP & kVolumeHardwareLockMask) )                                                     //      if bit is NOT set
        !           491:                {
        !           492:                        vcb->vcbAtrb &= ~kVolumeUnmountedMask;                                                  //      clear the kVolumeUnmounted attribute
        !           493:                        MarkVCBDirty( vcb );
        !           494:                        err = FlushVolumeControlBlock( vcb );
        !           495:                }
        !           496:                
        !           497:                err = noErr;
        !           498: 
        !           499:        }
        !           500: 
        !           501: 
        !           502: RemountExit:
        !           503:        if ( err == noErr ) goto CmdDone;                                                                               //      noErr implies a successful remount                      
        !           504:                
        !           505:        //--    if we are allowing new mounts, let the ROM handle the details.  Otherwise, let the error stand
        !           506:        fsVars = (FSVarsRec*)LMGetFSMVars();
        !           507:        if ( fsVars->fsFlags & fsNoAllocateMask )
        !           508:                goto CmdDone;
        !           509:                
        !           510:        LMSetNewMount( -1 );                                                                                                    //      assume now that it's a new volume
        !           511:        
        !           512:        
        !           513:        
        !           514:        //--    First see if the disk is already mounted.
        !           515: mv_Start:
        !           516:        err = paramErr;
        !           517:        driveNumber = lowMemParamBlock->ioVRefNum;
        !           518:        if ( driveNumber <= 0 ) goto MtVolDone;
        !           519:        err = GetVCBDriveNum( &vcb, driveNumber );
        !           520:        if ( err == noErr )
        !           521:        {
        !           522:                if ( vcb->vcbDrvNum != 0 )
        !           523:                {
        !           524:                        err = volOnLinErr;
        !           525:                        goto MtVolDone;
        !           526:                }
        !           527:        }
        !           528:        
        !           529:        //--    Find the appropriate drive queue entry and allocate a VCB.
        !           530:        err = FindDrive( &ioRefNum, &dqe, driveNumber );
        !           531:        if ( err != noErr ) goto MtVolDone;
        !           532:        
        !           533:        vcb = (ExtendedVCB *) NewPtrSysClear( sizeof( ExtendedVCB ) );          //      Zero out the Extended VCB
        !           534: 
        !           535:        if ( vcb == nil ) goto MtVolDone;                                                                       //      exit if we got no memory
        !           536:        
        !           537:        AddVCB( vcb, driveNumber, ioRefNum );                                                           //      prep the VCB for cache calls
        !           538:        
        !           539:        //--    Now try reading in the Volume Header.
        !           540:        //      We use "hfsPlusIOPosOffset / 512" cuz the VCB is not set up yet, so it's an absolute read
        !           541:        err = GetBlock_glue( gbDefault, (hfsPlusIOPosOffset / 512) + kIDSectorOffset , (Ptr*)&volumeHeader, vcb->vcbVRefNum, vcb );     //      no Flags, VH is always block #0, vcb->vcbBufAdr == CacheQueueHeader
        !           542: 
        !           543:        if ( err != noErr )     goto MtVolEr2;                                                                  //      Quit & Release VCB on errors
        !           544:        
        !           545:        //--    Now check what manner of animal we have before us:
        !           546:        err = RelBlock_glue( (Ptr)volumeHeader, rbTrashMask );
        !           547:        
        !           548:        err = ValidVolumeHeader( volumeHeader );
        !           549:        if ( err != noErr )
        !           550:        {
        !           551:                if ( err == noMacDskErr )
        !           552:                        goto MtVolEr2;
        !           553:                else
        !           554:                        goto MtVolEr1;
        !           555:        }
        !           556:        
        !           557:        //      The VolumeHeader seems OK: transfer info from buffer into VCB.
        !           558: 
        !           559:        //      Initialize our dirID/nodePtr cache associated with this volume.
        !           560:        err = InitMRUCache( sizeof(UInt32), kDefaultNumMRUCacheBlocks, &(vcb->hintCachePtr) );
        !           561:        ReturnIfError( err );
        !           562: 
        !           563:        //--    Copy fields between [vcbSigWord, vcbVN]
        !           564: 
        !           565:        vcb->vcbCrDate                                  =       volumeHeader->createDate;                                       // NOTE: local time, not GMT!
        !           566:        vcb->vcbLsMod                                   =       UTCToLocal(volumeHeader->modifyDate);
        !           567:        vcb->vcbAtrb                                    =       (UInt16)volumeHeader->attributes;                       //      VCB uses 16 bits, next 16 are for future API changes
        !           568:        vcb->vcbClpSiz                                  =       volumeHeader->rsrcClumpSize;
        !           569:        vcb->vcbNxtCNID                                 =       volumeHeader->nextCatalogID;
        !           570:        vcb->vcbVolBkUp                                 =       UTCToLocal(volumeHeader->backupDate);
        !           571:        vcb->vcbWrCnt                                   =       volumeHeader->writeCount;
        !           572:        vcb->vcbXTClpSiz                                =       volumeHeader->extentsFile.clumpSize;
        !           573:        vcb->vcbCTClpSiz                                =       volumeHeader->catalogFile.clumpSize;
        !           574:        vcb->attributesClumpSize                =       volumeHeader->attributesFile.clumpSize;
        !           575:        vcb->vcbFilCnt                                  =       volumeHeader->fileCount;
        !           576:        vcb->vcbDirCnt                                  =       volumeHeader->folderCount;
        !           577:        BlockMoveData( volumeHeader->finderInfo, vcb->vcbFndrInfo, sizeof( SInt32 ) * 8 );
        !           578:        
        !           579:        if ( pureHFSPlusVolume == true )
        !           580:        {
        !           581:                UInt32  totalSectors            =       (volumeHeader->blockSize / 512) * volumeHeader->totalBlocks;
        !           582:                HFSBlocksFromTotalSectors( totalSectors, &hfsBlockSize, &hfsBlockCount );
        !           583:        }
        !           584:        else
        !           585:        {
        !           586:                hfsBlockSize                            =       mdb->drAlBlkSiz;
        !           587:                hfsBlockCount                           =       mdb->drEmbedExtent.blockCount;
        !           588:        }
        !           589:        
        !           590:        //      vcbFreeBks is the number of free bytes divided by the (HFS compatible) allocation block size.  Since the
        !           591:        //      number of free bytes could overflow a UInt32, we actually divide both free bytes and allocation block size by
        !           592:        //      512 before doing the division.  This prevents intermediate values from overflowing until the volume size is
        !           593:        //      2 TB.  It's OK to divide by 512 since both HFS and HFS Plus require allocation blocks to be a multiple of 512.
        !           594:        vcb->vcbFreeBks = (volumeHeader->freeBlocks * (volumeHeader->blockSize / 512)) / (hfsBlockSize / 512);
        !           595:        
        !           596: 
        !           597:        //--    Fields taken from the MDB
        !           598:        vcb->vcbSigWord                                 =       kHFSPlusSigWord;                                                //      new field in VCB space
        !           599:        vcb->vcbNmAlBlks                                =       hfsBlockCount;                                                  //      number of HFS allocation blocks HFS+ volume
        !           600:        vcb->vcbAlBlkSiz                                =       hfsBlockSize;                                                   //      add to extended vcb
        !           601: 
        !           602:        //--    Now fill in the Extended VCB info
        !           603:        vcb->vcbSigWord                                 =       volumeHeader->signature;
        !           604:        vcb->nextAllocation                             =       volumeHeader->nextAllocation;
        !           605:        vcb->totalBlocks                                =       volumeHeader->totalBlocks;
        !           606:        vcb->freeBlocks                                 =       volumeHeader->freeBlocks;
        !           607:        vcb->blockSize                                  =       volumeHeader->blockSize;
        !           608:        vcb->allocationsClumpSize               =       volumeHeader->allocationFile.clumpSize;
        !           609:        vcb->checkedDate                                =       volumeHeader->checkedDate;
        !           610:        vcb->encodingsBitmap                    =       volumeHeader->encodingsBitmap;
        !           611:        
        !           612:        //      Set the allocation block start for this HFS Plus wrapped volume
        !           613:        vcb->vcbAlBlSt                                  =       hfsPlusIOPosOffset / 512;
        !           614:        vcb->hfsPlusIOPosOffset                 =       hfsPlusIOPosOffset;
        !           615:        
        !           616:        //��    Questionables
        !           617:        vcb->vcbVBMSt                                   = 0;                                                                            //�� (We should set this) BitMap start NOT used in HFS Plus
        !           618:        vcb->vcbEmbedSigWord                    = 0;
        !           619:        vcb->vcbEmbedExtent.startBlock  = 0;
        !           620:        vcb->vcbEmbedExtent.blockCount  = 0;
        !           621: 
        !           622: 
        !           623:        //--    Mark all the unused VCB fields with 0
        !           624:        vcb->vcbAllocPtr                                =       0;                                                                              //      use extended VCB value                          
        !           625:        
        !           626:        //      Remember which implementation last mounted this volume
        !           627:        lastMountedVersion                              =       volumeHeader->lastMountedVersion;
        !           628:        
        !           629:        currentIORequestPB = (IOParam *) ((QHdr *)LMGetFSQHdr())->qHead;                        //      current request
        !           630:        currentIORequestPB->ioVRefNum = vcb->vcbVRefNum;                                                        //      return volume refnum to user
        !           631:        
        !           632:        lowMemParamBlock = (IOParam *) LMParamBlock;
        !           633:        ((CntrlParam*)lowMemParamBlock)->csCode = drvStsCode;                                           //      drive status!
        !           634:        ((CntrlParam*)lowMemParamBlock)->csParam[1] &= 0x00ff;                                          //      Clear status byte for return
        !           635:        
        !           636:        err = PBStatusSync( (ParmBlkPtr)lowMemParamBlock );
        !           637:        
        !           638:        flagsP = (Byte *)((Ptr)(&(vcb->vcbAtrb))) + 1;
        !           639:        pbFlagsP = (Byte *)((Ptr)(((CntrlParam*)lowMemParamBlock)->csParam)+2);
        !           640:        *flagsP = *pbFlagsP & kVolumeHardwareLockMask;
        !           641:        
        !           642:        if ( IsARamDiskDriver() )
        !           643:        {
        !           644:                vcb->vcbAtrb |= kVolumeNoCacheRequiredMask;                                                             //      yes:�mark VCB as a RAM Disk
        !           645:        }
        !           646:        
        !           647:        vcb->vcbXTAlBlks = 0;   //      Unused, use fcb.fcbPLen instead
        !           648:        vcb->vcbCTAlBlks = 0;   //      Unused, use fcb.fcbPLen instead
        !           649:        
        !           650:        vcb->vcbWrCnt++;                                                                                                                        //      Compensate for write of MDB on last flush
        !           651:        
        !           652:        
        !           653:        //--    Try to find three free FCBs for use by the volume control B*-Trees:
        !           654:        
        !           655:        //
        !           656:        //--    Set up the Extent FCB
        !           657:        //
        !           658:        err = FindFileControlBlock( &fcbIndexP, &fcbsP );                                                                       //      Get new FCB
        !           659:        if ( err != noErr )     goto MtVolErr;
        !           660:        
        !           661:        fcb = GetFileControlBlock( fcbIndexP );
        !           662:        fcb->fcbEOF = volumeHeader->extentsFile.logicalSize.lo;                                                         //      Set extent tree's LEOF
        !           663:        fcb->fcbPLen = volumeHeader->extentsFile.totalBlocks * volumeHeader->blockSize;         //      Set extent tree's PEOF
        !           664: 
        !           665:        vcb->extentsRefNum              = fcbIndexP;                                                                                            //      Set Extents B*-Tree file RefNum
        !           666: 
        !           667:        ClearMemory( (Ptr)fcb->fcbExtRec, sizeof(HFSExtentRecord) );
        !           668: 
        !           669:        extendedFCB = ParallelFCBFromRefnum( fcbIndexP );
        !           670:        BlockMoveData( volumeHeader->extentsFile.extents, extendedFCB->extents, sizeof(HFSPlusExtentRecord) );
        !           671:        
        !           672:        //
        !           673:        //--    Set up the Catalog FCB
        !           674:        //
        !           675:        err = FindFileControlBlock( &fcbIndexP, &fcbsP );
        !           676:        if ( err != noErr )     goto MtVolErr;
        !           677:        
        !           678:        fcb = GetFileControlBlock( fcbIndexP );
        !           679:        fcb->fcbEOF = volumeHeader->catalogFile.logicalSize.lo;                                                         //      Set catalog tree's LEOF
        !           680:        fcb->fcbPLen = volumeHeader->catalogFile.totalBlocks * volumeHeader->blockSize;         //      Set catalog tree's PEOF
        !           681: 
        !           682:        vcb->catalogRefNum              = fcbIndexP;                                                                                            //      Set Catalog B*-Tree file RefNum
        !           683: 
        !           684:        ClearMemory( (Ptr)fcb->fcbExtRec, sizeof(HFSExtentRecord) );
        !           685:        
        !           686:        extendedFCB = ParallelFCBFromRefnum( fcbIndexP );
        !           687:        BlockMoveData( volumeHeader->catalogFile.extents, extendedFCB->extents, sizeof(HFSPlusExtentRecord) );
        !           688: 
        !           689:        
        !           690:        //
        !           691:        //--    Set up the Allocations FCB
        !           692:        //
        !           693:        err = FindFileControlBlock( &fcbIndexP, &fcbsP );
        !           694:        if ( err != noErr )     goto MtVolErr;
        !           695:        
        !           696:        fcb = GetFileControlBlock( fcbIndexP );
        !           697:        fcb->fcbEOF = volumeHeader->allocationFile.logicalSize.lo;                                                      //      Set catalog tree's LEOF
        !           698:        fcb->fcbPLen = volumeHeader->allocationFile.totalBlocks * volumeHeader->blockSize;      //      Set catalog tree's PEOF
        !           699: 
        !           700:        vcb->allocationsRefNum  = fcbIndexP;                                                                                            //      Set Catalog B*-Tree file RefNum
        !           701: 
        !           702:        ClearMemory( (Ptr)fcb->fcbExtRec, sizeof(HFSExtentRecord) );
        !           703: 
        !           704:        extendedFCB = ParallelFCBFromRefnum( fcbIndexP );
        !           705:        BlockMoveData( volumeHeader->allocationFile.extents, extendedFCB->extents, sizeof(HFSPlusExtentRecord) );
        !           706: 
        !           707:        
        !           708:        //
        !           709:        //--    Set up the Attributes FCB
        !           710:        //
        !           711:        vcb->attributesRefNum = 0;              //      In case there isn't an attributes BTree
        !           712:        
        !           713:        if (volumeHeader->attributesFile.extents[0].blockCount != 0)
        !           714:        {
        !           715:                err = FindFileControlBlock( &fcbIndexP, &fcbsP );
        !           716:                if ( err != noErr )     goto MtVolErr;
        !           717:                
        !           718:                fcb = GetFileControlBlock( fcbIndexP );
        !           719:                fcb->fcbEOF = volumeHeader->attributesFile.logicalSize.lo;                                                      //      Set attribute tree's LEOF
        !           720:                fcb->fcbPLen = volumeHeader->attributesFile.totalBlocks * volumeHeader->blockSize;      //      Set attribute tree's PEOF
        !           721: 
        !           722:                vcb->attributesRefNum   = fcbIndexP;                                                                                            //      Set Catalog B*-Tree file RefNum
        !           723: 
        !           724:                ClearMemory( (Ptr)fcb->fcbExtRec, sizeof(HFSExtentRecord) );
        !           725: 
        !           726:                extendedFCB = ParallelFCBFromRefnum( fcbIndexP );
        !           727:                BlockMoveData( volumeHeader->attributesFile.extents, extendedFCB->extents, sizeof(HFSPlusExtentRecord) );
        !           728:        }
        !           729:        
        !           730:        
        !           731:        vcb->vcbMAdr    = (Ptr)*(long *)SysBMCPtr;                                      //      Set up the volume bitmap cache
        !           732:        vcb->vcbCtlBuf  = (Ptr)*(long *)SysCtlCPtr;                                     //      Set up the volume control cache
        !           733:        
        !           734:        //
        !           735:        //--    Finish setting up the FCBs for the extent B*-Tree and the catalog B*-Tree:
        !           736:        //
        !           737: 
        !           738:        err = AccessBTree( vcb, vcb->extentsRefNum, kHFSExtentsFileID, vcb->vcbXTClpSiz, (void *) CompareExtentKeysPlus );
        !           739:        if ( err != noErr )     goto MtChkErr;
        !           740:        
        !           741:        err = AccessBTree( vcb, vcb->catalogRefNum, kHFSCatalogFileID, vcb->vcbCTClpSiz, (void *) CompareExtendedCatalogKeys );
        !           742:        if ( err != noErr )     goto MtChkErr;
        !           743:        
        !           744:        if (vcb->attributesRefNum)
        !           745:        {
        !           746:                err = AccessBTree( vcb, vcb->attributesRefNum, kHFSAttributesFileID, vcb->attributesClumpSize, (void *) CompareAttributeKeys );
        !           747:                if ( err != noErr )     goto MtChkErr;
        !           748:        }
        !           749: 
        !           750:        (void) SetupFCB( vcb, vcb->allocationsRefNum, kHFSAllocationFileID, volumeHeader->allocationFile.clumpSize );
        !           751:        
        !           752: 
        !           753:        err = CreateVolumeCatalogCache(vcb);
        !           754:        if ( err )
        !           755:                goto MtChkErr;
        !           756: 
        !           757:        // set up root file count...
        !           758:        
        !           759:        vcb->vcbNmFls = CountRootFiles(vcb);
        !           760:        
        !           761:        
        !           762:        //      Get the volume name from the catalog file
        !           763:        (void) GetVolumeNameFromCatalog(vcb);
        !           764:        
        !           765:        //      If the volume was not unmounted properly, then run MountCheck.
        !           766:        //      If the volume was last mounted by Bride 1.0b2 ('8.01'), then the create date may be wrong, so
        !           767:        //              we should run MountCheck to fix it.
        !           768:        if ( !(vcb->vcbAtrb & (short)kVolumeUnmountedMask) ||
        !           769:                        lastMountedVersion == '8.01')
        !           770:        {
        !           771:                UInt32          consistencyStatus;
        !           772:                
        !           773:                vcb->vcbAtrb &= ~kVolumeUnmountedMask;                                  //      From now until _Unmount (clear the bit)
        !           774:                *(Ptr)FSCallAsync = 0;
        !           775:                err = MountCheck( vcb, &consistencyStatus );
        !           776:                if ( err )
        !           777:                        goto MtChkErr;
        !           778:        }
        !           779:        else
        !           780:        {
        !           781:                vcb->vcbAtrb &= ~kVolumeUnmountedMask;                                  //      From now until _Unmount (clear the bit)
        !           782:        }
        !           783: 
        !           784: CheckRemount:
        !           785: 
        !           786:        //      ��This comment was in TFSVol.a, should look into it
        !           787:        //      Deleted stuff patched out by KillCheckRemountNiceWay in FileMgrPatches.a <SM1>
        !           788: 
        !           789: 
        !           790: MtVolOK:
        !           791:        err = noErr;
        !           792: 
        !           793: MtVolDone:
        !           794:        if ( err == noErr )
        !           795:        {
        !           796:                if ( !(vcb->vcbAtrb & kVolumeHardwareLockMask) )                //      if the disk is not write protected
        !           797:                {
        !           798:                        MarkVCBDirty( vcb );                                                            //      mark VCB dirty so it will be written
        !           799:                        err = FlushVolumeControlBlock( vcb );                           //      Go flush the VCB info BEFORE close
        !           800:                }
        !           801:        }
        !           802:        goto    CmdDone;
        !           803: 
        !           804: 
        !           805: 
        !           806: MtChkErr:
        !           807:        (void) DisposeVolumeCatalogCache(vcb);
        !           808:        InvalidateCatalogCache( vcb );
        !           809: 
        !           810:        *((OSErr *)HFSDSErr) = err;
        !           811:        err = badMDBErr;
        !           812:        
        !           813:        //--    Release any resources allocated so far before exiting with an error:
        !           814: MtVolErr:
        !           815:        DisposeFileControlBlocks( vcb );                                                                //      deallocate control file FCBs
        !           816:        
        !           817: MtVolEr1:
        !           818:        DisposeVolumeCacheBlocks( vcb );                                                                //      invalidate any cache blocks for this volume
        !           819:        
        !           820: MtVolEr2:
        !           821:        if ( (Byte)LMGetNewMount() == 0 )                                                               //      only deallocate VCB for new mounts
        !           822:        {
        !           823:                //              Remount case -- Must zero buffer and map ptrs in old VCB.
        !           824:                //              Restore VCB to its original off-line state (ie clear VCBDrvNum,
        !           825:                //              and move drive number to VCBDRefNum field)
        !           826:                vcb->vcbDRefNum = vcb->vcbDrvNum;                                                       //      write drv number to VCBDRefNum field
        !           827:                vcb->vcbDRefNum = 0;                                                                            //      clear drive number field of VCB
        !           828:                vcb->vcbMAdr    = nil;                                                                          //      clear mapptr in VCB
        !           829:                vcb->vcbBufAdr  = nil;                                                                          //      clear buffptr in VCB
        !           830:        }
        !           831:        else
        !           832:        {
        !           833:                DisposeVolumeControlBlock( vcb );
        !           834:        }
        !           835: 
        !           836:        if ( err <= 0 ) goto CmdDone;
        !           837:        
        !           838:        currentIORequestPB = (IOParam *) ((QHdr *)LMGetFSQHdr())->qHead;
        !           839:        goto mv_Start;  
        !           840: 
        !           841: CmdDone:
        !           842: return( err );
        !           843: 
        !           844: }
        !           845: #endif /* TARGET_OS_MAC */
        !           846: 
        !           847: 
        !           848: 
        !           849: #if TARGET_OS_MAC
        !           850: //�������������������������������������������������������������������������������
        !           851: //     Routine:        MountHFSVolume
        !           852: //
        !           853: // Function:   The VCB pointers are checked to see if a volume in the
        !           854: //                             specified drive is already on-line (error if so).  Reads in the
        !           855: //                             directory master block and allocates memory for VCB and additional
        !           856: //                             data structures, depending on the volume type:
        !           857: //
        !           858: //                             - For MFS volumes (handled in MFSVol), space is allocated for
        !           859: //                               a volume buffer, as well as the block map, which is read in
        !           860: //                               from disk).
        !           861: //
        !           862: //                             - For TFS volumes, space is allocated for a bitmap cache, a volume
        !           863: //                               control cache (for B*-Tree use), and a volume cache.  In addition,
        !           864: //                               two FCBs are used by the B*-Trees.
        !           865: //
        !           866: //                             No new VCB storage is allocated for remounts.
        !           867: //
        !           868: //�������������������������������������������������������������������������������
        !           869: 
        !           870: OSErr  MountHFSVolume( short driveNumber, IOParam* lowMemParamBlock, OSErr err )
        !           871: {
        !           872:        HFSMasterDirectoryBlock *mdb;
        !           873:        QHdr                                    *vcbQHdr;
        !           874:        Byte                                    *flagsP;
        !           875:        Byte                                    *mdbFlagsP;
        !           876:        FSVarsRec                               *fsVars;
        !           877:        IOParam                                 *currentIORequestPB;
        !           878:        Ptr                                     fcbsP;
        !           879:        FCB                                             *fcb;
        !           880:        ExtendedVCB                             *vcb;
        !           881:        DrvQEl                                  *dqe;
        !           882:        short                                   ioRefNum;
        !           883:        UInt16                                  fcbIndexP;
        !           884:        
        !           885:        if ( err != noErr )
        !           886:                goto RemountExit;
        !           887:        
        !           888:        ioRefNum = lowMemParamBlock->ioRefNum;
        !           889:        mdb = (HFSMasterDirectoryBlock *) lowMemParamBlock->ioBuffer;                   //      �� figure out how we use VolumeHeader & MasterDirectoryBlock, size of structures, etc.  
        !           890:        
        !           891:        err = ValidMasterDirectoryBlock( mdb );                                                         //      is this an HFS/HFS PlusDisk
        !           892:        if ( err == noErr )
        !           893:        {
        !           894:                err = notARemountErr;                                                                                   //      cuz we're looking for remounts only here
        !           895:                vcbQHdr = LMGetVCBQHdr();                                                                               //      search the queue of VCBs
        !           896:                
        !           897:                //      CheckRemountLoop:
        !           898:                for ( vcb = (ExtendedVCB*)vcbQHdr->qHead ; vcb != nil ; vcb = (ExtendedVCB*)vcb->qLink )        //      search the queue of VCBs
        !           899:                {
        !           900:                        if (   (vcb->vcbDrvNum  == 0)                                                           //      matching volume better be off-line (0 drive num)
        !           901:                                && (vcb->vcbSigWord     == mdb->drSigWord)                                      //      Same signature?
        !           902:                                && (vcb->vcbCrDate      == mdb->drCrDate)                                       //      Same create date?
        !           903:                                && (vcb->vcbLsMod       == mdb->drLsMod)                                        //      Same mod date?
        !           904:                           )
        !           905:                        {
        !           906:                                //      At this point, we're fairly certain that the two volumes are, in fact, the same,
        !           907:                                //      but just to make sure (and avoid problems with stuck clocks), we'll compare the
        !           908:                                //      volume names as well:
        !           909:                                //��    Modify this call to use the extended VCB ascii name, not the Unicode name
        !           910:                                if ( EqualString( vcb->vcbVN, mdb->drVN, true, true) )  //      caseSensitive, diacSensitive
        !           911:                                        break;                                                                                          //      Remount
        !           912:                        }
        !           913:                }
        !           914:                if ( vcb == nil ) goto RemountExit;
        !           915:        
        !           916:                //      We are now convinced that we have a remount.  We will rebuild the attributes
        !           917:                //      byte, which is the only one that could have changed.  We'll also store the
        !           918:                //      current drive number and driver refNum, and mark the volume dirty.
        !           919:                //      Remount:
        !           920:        
        !           921:                ((CntrlParam*)lowMemParamBlock)->csCode = drvStsCode;                   //      Drive status!
        !           922:                ((CntrlParam*)lowMemParamBlock)->csParam[1] &= 0x00ff;                  //      Clear status byte for return
        !           923:                
        !           924:                err = PBStatusSync( (ParmBlkPtr)lowMemParamBlock );                             //      refnum and drivenum set up by read call
        !           925:                
        !           926:                //--    Now propagate the write protect status byte back to the vcb
        !           927:                flagsP = ((Byte *)(&(vcb->vcbAtrb))) + 1;
        !           928:                mdbFlagsP = ((Byte *)(((CntrlParam*)lowMemParamBlock)->csParam)+2);
        !           929:                *flagsP = *mdbFlagsP & kVolumeHardwareLockMask;
        !           930: 
        !           931:                vcb->vcbDrvNum  = driveNumber;
        !           932:                vcb->vcbDRefNum = ioRefNum;                                                                             //      Driver RefNum
        !           933:                
        !           934:                #if ( hasHFSManualEject )
        !           935:                        SetVCBManEject(vcb);
        !           936:                #endif
        !           937:                
        !           938:                if ( !(*flagsP & kVolumeHardwareLockMask) )                                             //      if bit is NOT set
        !           939:                {
        !           940:                        vcb->vcbAtrb &= ~kVolumeUnmountedMask;                                          //      clear the kVolumeUnmounted attribute
        !           941:                        MarkVCBDirty( vcb );
        !           942:                        err = FlushVolumeControlBlock( vcb );                                           //      Go flush the VCB info BEFORE close
        !           943:                }
        !           944:                
        !           945:                err = noErr;
        !           946:        }
        !           947: 
        !           948: 
        !           949: RemountExit:
        !           950:        if ( err == noErr )
        !           951:                goto CmdDone;                                                                                                   //      noErr implies a successful remount                      
        !           952:                
        !           953:        //--    if we are allowing new mounts, let the ROM handle the details.  Otherwise, let the error stand
        !           954:        fsVars = (FSVarsRec*)LMGetFSMVars();                                                            //      $BB8
        !           955:        if ( fsVars->fsFlags & fsNoAllocateMask )
        !           956:                goto CmdDone;
        !           957:                
        !           958:        //�� This sets the word to -1, Asm only set the byte to -1
        !           959:        LMSetNewMount( -1 );                                                                                            //      assume now that it's a new volume
        !           960:        
        !           961:        
        !           962:        
        !           963:        //--    First see if the disk is already mounted.
        !           964: mv_Start:
        !           965:        err = paramErr;
        !           966:        driveNumber = lowMemParamBlock->ioVRefNum;
        !           967:        if ( driveNumber <= 0 )
        !           968:                goto MtVolDone;
        !           969:        
        !           970:        err = GetVCBDriveNum( &vcb, driveNumber );
        !           971:        if ( err == noErr )
        !           972:        {
        !           973:                if ( vcb->vcbDrvNum != 0 )
        !           974:                {
        !           975:                        err = volOnLinErr;
        !           976:                        goto MtVolDone;
        !           977:                }
        !           978:        }
        !           979:        
        !           980:        //--    Find the appropriate drive queue entry and allocate a VCB.
        !           981:        err = FindDrive( &ioRefNum, &dqe, driveNumber );
        !           982:        if ( err != noErr ) goto MtVolDone;
        !           983:        
        !           984:        vcb = (ExtendedVCB *) NewPtrSysClear( sizeof( ExtendedVCB ) );
        !           985: 
        !           986:        if ( vcb == nil ) goto MtVolDone;                                                                       //      exit if we got no memory
        !           987:        
        !           988:        AddVCB( vcb, driveNumber, ioRefNum );                                                           //      prep the VCB for cache calls
        !           989: 
        !           990:        //--    Now try reading in the master directory block.
        !           991:        err = GetBlock_glue( gbDefault, kIDSectorOffset, (Ptr*)&mdb, vcb->vcbVRefNum, vcb );    //      no Flags, MDB is always block #2, vcb->vcbBufAdr == CacheQueueHeader
        !           992:        if ( err != noErr )     goto MtVolEr2;                                                                  //      Quit & Release VCB on errors
        !           993:        
        !           994:        //--    Now check what manner of animal we have before us:
        !           995:        err = RelBlock_glue( (Ptr)mdb, rbTrashMask );
        !           996:        
        !           997:        err = ValidMasterDirectoryBlock( mdb );
        !           998:        if ( err != noErr )
        !           999:        {
        !          1000:                if ( err == noMacDskErr )
        !          1001:                        goto MtVolEr2;
        !          1002:                else
        !          1003:                        goto MtVolEr1;
        !          1004:        }
        !          1005:        
        !          1006:        //      The MDB seems OK: transfer all master directory info from buffer into VCB.
        !          1007:        
        !          1008:        //      vcbSigWord is the start of duplicate mdb/vcb info. Asm VCBDInfoSt Equ 8
        !          1009:        //      copy all fields in mdb till the drVolBkUp field
        !          1010:        
        !          1011:        BlockMoveData( mdb, &(vcb->vcbSigWord),  (Size)(&(mdb->drVolBkUp)) - (Size)mdb );
        !          1012: 
        !          1013:        //      Initialize our dirID/nodePtr cache associated with this volume.
        !          1014:        err = InitMRUCache( sizeof(UInt32), kDefaultNumMRUCacheBlocks, &(vcb->hintCachePtr) );
        !          1015:        ReturnIfError( err );
        !          1016: 
        !          1017:        //-- Some fields, vcbNmAlBlks, vcbAlBlkSiz, and vcbFreeBks are just around for API compatability.
        !          1018:        //-- The HFS/HFS Plus code we will use the corresponding ExtendedVCB fields. vcbNmAlBlks * vcbAlBlkSiz
        !          1019:        //-- still gives correct volume size.
        !          1020:        vcb->totalBlocks        =       vcb->vcbNmAlBlks;
        !          1021:        vcb->freeBlocks         =       vcb->vcbFreeBks;
        !          1022:        vcb->blockSize          =       vcb->vcbAlBlkSiz;
        !          1023: 
        !          1024:        
        !          1025:        currentIORequestPB = (IOParam *) ((QHdr *)LMGetFSQHdr())->qHead;                        //      current request
        !          1026:        currentIORequestPB->ioVRefNum = vcb->vcbVRefNum;                                                        //      return volume refnum to user
        !          1027:        
        !          1028:        lowMemParamBlock = (IOParam *) LMParamBlock;
        !          1029:        ((CntrlParam*)lowMemParamBlock)->csCode = drvStsCode;                                           //      drive status!
        !          1030:        ((CntrlParam*)lowMemParamBlock)->csParam[1] &= 0x00ff;                                          //      Clear status byte for return
        !          1031:        
        !          1032:        err = PBStatusSync( (ParmBlkPtr)lowMemParamBlock );
        !          1033:        
        !          1034:        flagsP = ((Byte *)(&(vcb->vcbAtrb))) + 1;
        !          1035:        mdbFlagsP = ((Byte *)(((CntrlParam*)lowMemParamBlock)->csParam)+2);
        !          1036:        *flagsP = *mdbFlagsP & kVolumeHardwareLockMask;
        !          1037:        
        !          1038:        if ( IsARamDiskDriver() )
        !          1039:        {
        !          1040:                vcb->vcbAtrb |= kVolumeNoCacheRequiredMask;                                                             //      yes:�mark VCB as a RAM Disk
        !          1041:        }
        !          1042:        
        !          1043:        //--    copy all fields in mdb between drXTFlSize & drVolBkUp
        !          1044:        BlockMoveData( &(mdb->drVolBkUp), &(vcb->vcbVolBkUp), (Size)&(mdb->drXTFlSize) - (Size)&(mdb->drVolBkUp) ); //  66 bytes
        !          1045:        
        !          1046:        vcb->vcbXTAlBlks = DivUp( mdb->drXTFlSize, vcb->blockSize );                            //      Pick up PEOF of extent B*-Tree
        !          1047:        vcb->vcbCTAlBlks = DivUp( mdb->drCTFlSize, vcb->blockSize );                            //      Pick up PEOF of catalog B*-Tree
        !          1048:        
        !          1049:                                                                                                                                                                //      ��� WHY ARE WE RESTARTING THE ROAVING PTR
        !          1050:        vcb->nextAllocation                             =       mdb->drAllocPtr;
        !          1051:        vcb->vcbAllocPtr = 0;                                                                                                           //      Restart the roving allocation ptr
        !          1052:        vcb->vcbWrCnt++;                                                                                                                        //      Compensate for write of MDB on last flush
        !          1053:        
        !          1054:        
        !          1055:        //--    Try to find two free FCBs for use by the volume control B*-Trees:
        !          1056:        
        !          1057:        //--    Set up the Extent FCB
        !          1058:        err = FindFileControlBlock( &fcbIndexP, &fcbsP );
        !          1059:        if ( err != noErr )     goto MtVolErr;
        !          1060:        
        !          1061:        fcb = GetFileControlBlock( fcbIndexP );
        !          1062:        fcb->fcbEOF = mdb->drXTFlSize;                                                                                          //      Set catalog tree's LEOF
        !          1063:        fcb->fcbPLen = mdb->drXTFlSize;                                                                                         //      Set catalog tree's PEOF
        !          1064: 
        !          1065:        vcb->extentsRefNum              = fcbIndexP;                                                                            //      Set Extents B*-Tree file RefNum
        !          1066:        BlockMoveData( mdb->drXTExtRec, fcb->fcbExtRec, sizeof(HFSExtentRecord) );
        !          1067:        
        !          1068:        
        !          1069:        //--    Set up the Catalog FCB
        !          1070:        err = FindFileControlBlock( &fcbIndexP, &fcbsP );
        !          1071:        if ( err != noErr )     goto MtVolErr;
        !          1072:        
        !          1073:        fcb = GetFileControlBlock( fcbIndexP );
        !          1074:        fcb->fcbEOF = mdb->drCTFlSize;                                                          //      Set catalog tree's LEOF
        !          1075:        fcb->fcbPLen = mdb->drCTFlSize;                                                         //      Set catalog tree's PEOF
        !          1076: 
        !          1077:        vcb->catalogRefNum              = fcbIndexP;                                                                            //      Set Catalog B*-Tree file RefNum
        !          1078:        BlockMoveData( mdb->drCTExtRec, fcb->fcbExtRec, sizeof(HFSExtentRecord) );
        !          1079:        
        !          1080:        
        !          1081:        vcb->vcbMAdr    = (Ptr)*(long *)SysBMCPtr;                                      //      Set up the volume bitmap cache
        !          1082:        vcb->vcbCtlBuf  = (Ptr)*(long *)SysCtlCPtr;                                     //      Set up the volume control cache
        !          1083:        
        !          1084: 
        !          1085:        //--    Finish setting up the FCBs for the extent B*-Tree and the catalog B*-Tree:
        !          1086: 
        !          1087:        err = AccessBTree( vcb, vcb->extentsRefNum, kHFSExtentsFileID, vcb->vcbXTClpSiz, (void *) CompareExtentKeys );
        !          1088:        if ( err != noErr )     goto MtChkErr;
        !          1089:        
        !          1090:        err = AccessBTree( vcb, vcb->catalogRefNum, kHFSCatalogFileID, vcb->vcbCTClpSiz, (void *) CompareCatalogKeys );
        !          1091:        if ( err != noErr )     goto MtChkErr;
        !          1092: 
        !          1093:        err = CreateVolumeCatalogCache(vcb);
        !          1094:        if ( err )      goto MtChkErr;
        !          1095: 
        !          1096:        if ( !(vcb->vcbAtrb & (short)kVolumeUnmountedMask) )
        !          1097:        {
        !          1098:                UInt32          consistencyStatus;
        !          1099: 
        !          1100:                vcb->vcbAtrb &= ~kVolumeUnmountedMask;                                  //      From now until _Unmount (clear the bit)
        !          1101:                *(Ptr)FSCallAsync = 0;
        !          1102:                err = MountCheck( vcb, &consistencyStatus );
        !          1103:                if ( err )      goto MtChkErr;
        !          1104:        }
        !          1105:        else
        !          1106:        {
        !          1107:                vcb->vcbAtrb &= ~kVolumeUnmountedMask;                                  //      From now until _Unmount (clear the bit)
        !          1108:        }
        !          1109: 
        !          1110: CheckRemount:
        !          1111: 
        !          1112:        //      ��This comment was in TFSVol.a, should look into it
        !          1113:        //      Deleted stuff patched out by KillCheckRemountNiceWay in FileMgrPatches.a <SM1>
        !          1114: 
        !          1115: 
        !          1116: MtVolOK:
        !          1117:        err = noErr;
        !          1118: 
        !          1119: MtVolDone:
        !          1120:        if ( err == noErr )
        !          1121:        {
        !          1122:                if ( !(vcb->vcbAtrb & kVolumeHardwareLockMask) )                //      if the disk is not write protected
        !          1123:                {
        !          1124:                        MarkVCBDirty( vcb );                                                            //      mark VCB dirty so it will be written
        !          1125:                        err = FlushVolumeControlBlock( vcb );                           //      Go flush the VCB info BEFORE close
        !          1126:                }
        !          1127:        }
        !          1128:        goto    CmdDone;
        !          1129: 
        !          1130: 
        !          1131: 
        !          1132: MtChkErr:
        !          1133:        (void) DisposeVolumeCatalogCache(vcb);
        !          1134:        InvalidateCatalogCache( vcb );
        !          1135: 
        !          1136: 
        !          1137:        *((OSErr *)HFSDSErr) = err;
        !          1138:        err = badMDBErr;
        !          1139:        
        !          1140:        //--    Release any resources allocated so far before exiting with an error:
        !          1141: MtVolErr:
        !          1142:        DisposeFileControlBlocks( vcb );                                                        //      deallocate control file FCBs
        !          1143:        
        !          1144: MtVolEr1:
        !          1145:        DisposeVolumeCacheBlocks( vcb );                                                        //      invalidate any cache blocks for this volume
        !          1146:        
        !          1147: MtVolEr2:
        !          1148:        if ( (Byte)LMGetNewMount() == 0 )                                                       //      only deallocate VCB for new mounts
        !          1149:        {
        !          1150:                //              Remount case -- Must zero buffer and map ptrs in old VCB.
        !          1151:                //              Restore VCB to its original off-line state (ie clear VCBDrvNum,
        !          1152:                //              and move drive number to VCBDRefNum field)
        !          1153:                vcb->vcbDRefNum = vcb->vcbDrvNum;                                               //      write drv number to VCBDRefNum field
        !          1154:                vcb->vcbDRefNum = 0;                                                                    //      clear drive number field of VCB
        !          1155:                vcb->vcbMAdr    = nil;                                                                  //      clear mapptr in VCB
        !          1156:                vcb->vcbBufAdr  = nil;                                                                  //      clear buffptr in VCB
        !          1157:        }
        !          1158:        else
        !          1159:        {
        !          1160:                DisposeVolumeControlBlock( vcb );
        !          1161:        }
        !          1162: 
        !          1163:        if ( err <= 0 )
        !          1164:                goto CmdDone;
        !          1165:        currentIORequestPB = (IOParam *) ((QHdr *)LMGetFSQHdr())->qHead;
        !          1166:        goto mv_Start;  
        !          1167: 
        !          1168: CmdDone:
        !          1169:        return( err );
        !          1170: 
        !          1171: }
        !          1172: #endif /* TARGET_OS_MAC */
        !          1173: 
        !          1174: 
        !          1175: #if TARGET_OS_MAC
        !          1176: //�������������������������������������������������������������������������������
        !          1177: //     Routine:        UnMountVolume
        !          1178: //
        !          1179: //     Function:       All files on the volume in the drive are closed and any changed
        !          1180: //                             directory information is written out to the diskette.  Memory
        !          1181: //                             for the VCB, volume buffer, and block map is deallocated.
        !          1182: //
        !          1183: //�������������������������������������������������������������������������������
        !          1184: 
        !          1185: OSErr  UnMountVolume( VolumeParam *volume, WDCBRecPtr *wdcb )
        !          1186: {
        !          1187:        FCB                                             *fcb;
        !          1188:        OSErr                                   err;
        !          1189:        SInt16                                  nameLength;
        !          1190:        Boolean                                 nameSpecified;
        !          1191:        ExtendedVCB                             *vcb;
        !          1192:        unsigned char                   *pathName;
        !          1193:        UInt16                                  index;
        !          1194:        Ptr                                             fcbs;
        !          1195:        Boolean                                 doneSearching;
        !          1196:        Boolean                                 isHFSPlus;
        !          1197:        FSSpec                                  spec;
        !          1198:        UInt16                                  driveNumber;
        !          1199:        HFSMasterDirectoryBlock *mdb;
        !          1200:        Boolean                                 mustRenameWrapperVolume = false;
        !          1201: 
        !          1202:        LMSetFlushOnly( 0 );                                                                            //      Setup same as UnmountVol
        !          1203:        err = DeturmineVolume3( volume, &nameLength, &nameSpecified, &vcb, wdcb, &pathName );
        !          1204:        if ( err != noErr )
        !          1205:                goto CmdDone;
        !          1206:                
        !          1207:        isHFSPlus       = ( vcb->vcbSigWord == kHFSPlusSigWord );
        !          1208:        
        !          1209:        //--    Get the volume name from the catalog file to set in the HFS wrapper later
        !          1210:        if ( (isHFSPlus) && (vcb->vcbDrvNum != 0) )                                     //      HFS+ volume and on-line
        !          1211:        {
        !          1212:                UInt32                                  hint;
        !          1213:                CatalogNodeData                 nodeData;
        !          1214:                
        !          1215:                err = GetCatalogNode( vcb, kHFSRootFolderID, NULL, kNoHint, &spec, &nodeData, &hint );
        !          1216:                if ( err == noErr )
        !          1217:                {
        !          1218:                        err = GetBlock_glue( gbDefault, kIDSectorOffset, (Ptr*)&mdb, vcb->vcbVRefNum, vcb );    //      Read the MDB
        !          1219:                        if ( err == noErr )
        !          1220:                        {
        !          1221:                                if ( mdb->drSigWord == kHFSSigWord )                    //      it's a wrapped volume
        !          1222:                                {
        !          1223:                                        if ( memcmp( spec.name, mdb->drVN, spec.name[0]+1 ) != 0 )      //      Has the name changed?
        !          1224:                                        {
        !          1225:                                                driveNumber = vcb->vcbDrvNum;
        !          1226:                                                mustRenameWrapperVolume = true;
        !          1227:                                        }
        !          1228:                                }
        !          1229:                                err = RelBlock_glue( (Ptr)mdb, rbTrashMask );
        !          1230:                        }
        !          1231:                }
        !          1232:        }
        !          1233:        
        !          1234:        //      Initialize fcbs pointer
        !          1235:        Get1stFileControlBlock( &index, &fcbs );
        !          1236: 
        !          1237:        if ( !(volume->ioTrap & kHFSMask) )                                                     //      if NOT Unconditional unmount?
        !          1238:        {
        !          1239:                //--    Search the FCB array for open files that reference the volume...
        !          1240:                do
        !          1241:                {
        !          1242:                        fcb = GetFileControlBlock( index );
        !          1243:                        if ( (fcb->fcbFlNm != 0) && (fcb->fcbVPtr == vcb) )     //      The file is currently open and on this volume
        !          1244:                        {
        !          1245:                                if ( fcb->fcbFlNm >= fsUsrCNID )                                //      is it a user file?
        !          1246:                                {
        !          1247:                                        //--    Found an open user file on the volume, so return a busy condition...
        !          1248:                                        err = fBsyErr;
        !          1249:                                        break;
        !          1250:                                }
        !          1251:                        }
        !          1252:                        
        !          1253:                        doneSearching = GetNextFileControlBlock( &index, fcbs );
        !          1254:                        
        !          1255:                } while ( !doneSearching );
        !          1256:        }
        !          1257:        
        !          1258:        if ( err == noErr )
        !          1259:        {
        !          1260:                err = CheckExternalFileSystem( vcb );
        !          1261:                if ( err == noErr )
        !          1262:                {
        !          1263:                        FlushVolume( vcb );
        !          1264:                        //      Unmounting a TFS volume: close the volume control B*-Tree and use the
        !          1265:                        //      volume buffer to write out the MDB
        !          1266: 
        !          1267:                        //      From UnmountForTheNineties in FileMgrPatches.a
        !          1268:                        //      Here's the change:  we no longer check whether the volume is offline.  Instead we always
        !          1269:                        //      go ahead and close the control files, since we no longer close them on _Offline or _Eject.
        !          1270:        
        !          1271:                        if ( vcb->vcbDrvNum != 0 )                                              //      Check drive number: vol. offline?
        !          1272:                        {
        !          1273:                                err = FlushVolumeBuffers( vcb );
        !          1274:                                if ( err != noErr )
        !          1275:                                        goto CmdDone;                                                   //      Punt on errors
        !          1276:                        }
        !          1277:                        else
        !          1278:                        {
        !          1279:                                //      here begins CloseControlFiles, which is derived from FlushBuffers
        !          1280:                                //      Now we have to close the control files because we no longer close them 
        !          1281:                                //      in Eject and Offline
        !          1282:                                
        !          1283:                                if ( LMGetFlushOnly() == 0 )                            //      volume needs flushing
        !          1284:                                {
        !          1285:                                        err = CloseFile( vcb, vcb->catalogRefNum, fcbs );
        !          1286:                                        if ( err != noErr )
        !          1287:                                                goto CmdDone;                                           //      Punt on errors
        !          1288:                                        
        !          1289:                                        err = CloseFile( vcb, vcb->extentsRefNum, fcbs );
        !          1290:                                        if ( err != noErr )
        !          1291:                                                goto CmdDone;                                           //      Punt on errors
        !          1292:                                                
        !          1293:                                        if ( isHFSPlus )
        !          1294:                                        {
        !          1295:                                                err = AttributesCloseVolume( vcb );
        !          1296:                                                if ( err != noErr )
        !          1297:                                                        goto CmdDone;
        !          1298: 
        !          1299:                                                err = CloseFile( vcb, vcb->allocationsRefNum, fcbs );
        !          1300:                                                if ( err != noErr )
        !          1301:                                                        goto CmdDone;
        !          1302:                                        }
        !          1303: 
        !          1304:                                        (void) DisposeMRUCache(vcb->hintCachePtr);
        !          1305:                                        (void) DisposeVolumeCatalogCache(vcb);
        !          1306:                                        InvalidateCatalogCache( vcb );
        !          1307:                                        DisposeVolumeCacheBlocks( vcb );
        !          1308:                                }
        !          1309:                        }
        !          1310: 
        !          1311:                        if ( LMGetFlushOnly() == 0 )                                    //      volume needs flushing
        !          1312:                        {
        !          1313:                                //      For UnMountVol, dequeue the VCB and trash any WDCBs for this volume ...
        !          1314:                                DisposeVolumeControlBlock( vcb );
        !          1315:                        }
        !          1316:                        
        !          1317:                        //      The volume is now unmounted, if it's an HFS+ volume, and the name does not match what's
        !          1318:                        //      in the MDB, mount the HFS wrapper rename the wrapper volume and unmount it.
        !          1319:                        if ( mustRenameWrapperVolume )
        !          1320:                        {
        !          1321:                                RenameWrapperVolume( spec.name, driveNumber );
        !          1322:                        }
        !          1323:                        
        !          1324:                        err = noErr;
        !          1325:                }
        !          1326:        }
        !          1327: 
        !          1328: CmdDone:
        !          1329:        return( err );
        !          1330: }
        !          1331: #endif /* TARGET_OS_MAC */
        !          1332: 
        !          1333: 
        !          1334: #if TARGET_OS_MAC
        !          1335: //�������������������������������������������������������������������������������
        !          1336: //     Routine:        RenameWrapperVolume     
        !          1337: //
        !          1338: //     Function:       Called during UnmountVolume if the HFS+ volume name does not
        !          1339: //                             match the name stored in the wrapper MDB.  This function
        !          1340: //                             renames the HFS wrapper volume.
        !          1341: //
        !          1342: //�������������������������������������������������������������������������������
        !          1343: void   RenameWrapperVolume( Str27 newVolumeName, UInt16 driveNumber )
        !          1344: {
        !          1345:        VolumeParam             volume;
        !          1346:        ExtendedVCB             *vcb;
        !          1347:        OSErr                   err;
        !          1348:        UInt32                  hint;
        !          1349:        FSSpec                  spec;
        !          1350:        CatalogNodeData nodeData;
        !          1351:        Ptr                             pmsp;
        !          1352:        UInt32                  modDate;
        !          1353:        WDCBRecPtr              wdcbPtr;
        !          1354:        
        !          1355:        ClearMemory( &volume, sizeof(VolumeParam) );
        !          1356:        volume.ioVRefNum        = driveNumber;
        !          1357:        
        !          1358:        err = MountVolume( &volume, true );
        !          1359:        if ( err != noErr )
        !          1360:                return;         // punt on errors
        !          1361:        
        !          1362:        err = GetVCBDriveNum( &vcb, driveNumber );
        !          1363:        if ( err != noErr )
        !          1364:                goto ErrorExit;         // punt on errors
        !          1365: 
        !          1366:        modDate = vcb->vcbLsMod;
        !          1367:        
        !          1368:        err = GetCatalogNode( vcb, kHFSRootFolderID, NULL, kNoHint, &spec, &nodeData, &hint );
        !          1369:        if ( err != noErr )
        !          1370:        {
        !          1371:                #if DEBUG_BUILD
        !          1372:                        DebugStr("\p GetCatalogNode failed");
        !          1373:                #endif
        !          1374:                goto ErrorExit;         // punt on errors
        !          1375:        }
        !          1376:        
        !          1377:        err = RenameCatalogNode( vcb, kHFSRootParentID, spec.name, newVolumeName, hint, &hint );
        !          1378:        if ( err != noErr )
        !          1379:        {
        !          1380:                #if DEBUG_BUILD
        !          1381:                        DebugStr("\p RenameCatalogNode failed");
        !          1382:                #endif
        !          1383:                goto ErrorExit;         // punt on errors
        !          1384:        }
        !          1385: 
        !          1386:        BlockMoveData( newVolumeName, vcb->vcbVN, sizeof(Str27) );
        !          1387:        vcb->vcbLsMod   = modDate;
        !          1388:        MarkVCBDirty( vcb );
        !          1389: 
        !          1390:        pmsp    = LMGetPMSPPtr();
        !          1391:        *((short*)(pmsp + kPoorMansSearchIndex))        = 0;                    //      Invalidate Poor Mans search path
        !          1392: 
        !          1393: ErrorExit:
        !          1394: 
        !          1395:        (void) UnMountVolume( &volume, &wdcbPtr );
        !          1396: }
        !          1397: #endif /*TARGET_OS_MAC */
        !          1398: 
        !          1399: 
        !          1400: #if TARGET_OS_MAC
        !          1401: //�������������������������������������������������������������������������������
        !          1402: //     Routine:        CheckExternalFileSystem         Asm: CkExtFS
        !          1403: //
        !          1404: //     Function:       Simple routine to separate out calls to be handled by an
        !          1405: //                             external file system.
        !          1406: //
        !          1407: //�������������������������������������������������������������������������������
        !          1408: OSErr  CheckExternalFileSystem( ExtendedVCB *vcb )
        !          1409: {
        !          1410:        if ( vcb->vcbFSID == 0 )
        !          1411:        {
        !          1412:                return( noErr );
        !          1413:        }
        !          1414:        else
        !          1415:        {
        !          1416:                return( extFSErr );
        !          1417:        }
        !          1418: }
        !          1419: #endif /* TARGET_OS_MAC */
        !          1420: 
        !          1421: 
        !          1422: 
        !          1423: 
        !          1424: //�������������������������������������������������������������������������������
        !          1425: //     Routine:        CheckVolumeConsistancy
        !          1426: //
        !          1427: //     Function:       Check kBootVolumeInconsistentMask, and run MountCheck if necessary
        !          1428: //�������������������������������������������������������������������������������
        !          1429: OSErr  CheckVolumeConsistency( ExtendedVCB *vcb )
        !          1430: {
        !          1431:        UInt32          consistencyStatus;
        !          1432:        OSErr           err     = noErr;
        !          1433:                
        !          1434: #if TARGET_OS_RHAPSODY
        !          1435:        if ( vcb->vcbSigWord == kHFSSigWord)                                    //      and is an HFS disk
        !          1436: #else  /* TARGET_OS_RHAPSODY */
        !          1437:        if ( ( *((UInt16*)&(((ROMHeaderRec *) LMGetROMBase())->MachineNumber)) == 0x077D ) &&   //      is supermario based
        !          1438:                 ( vcb->vcbSigWord == kHFSSigWord ) )                                   //      and is an HFS disk
        !          1439: #endif         /* TARGET_OS_RHAPSODY */
        !          1440:        {
        !          1441:                if ( vcb->vcbAtrb & kHFSBootVolumeInconsistentMask )            //      was marked inconsistant
        !          1442:                {
        !          1443:                        err = MountCheck( vcb, &consistencyStatus );
        !          1444:                        
        !          1445:                        if ( err == noErr )
        !          1446:                                vcb->vcbAtrb &= ~kHFSVolumeSoftwareLockMask;            //      clear the bit
        !          1447:                }
        !          1448: #if TARGET_OS_MAC
        !          1449:                if ( LMGetBootDrive() == vcb->vcbDrvNum )                               //      this is the boot volume
        !          1450:                        vcb->vcbAtrb |= kHFSBootVolumeInconsistentMask;
        !          1451: #endif         /* TARGET_OS_MAC */
        !          1452:        }
        !          1453:        
        !          1454:        return( err );
        !          1455: }
        !          1456: 
        !          1457: 
        !          1458: 
        !          1459: 
        !          1460: //�������������������������������������������������������������������������������
        !          1461: //     Routine:        VolumeWritable          Asm: CVFlgs
        !          1462: //
        !          1463: //     Function:       Check the volume's flags to see if modify requests are allowed.
        !          1464: //
        !          1465: //�������������������������������������������������������������������������������
        !          1466: OSErr  VolumeWritable( ExtendedVCB *vcb )
        !          1467: {
        !          1468:        if ( !(vcb->vcbAtrb & 0x8000) )         //      if the volume is not locked
        !          1469:        {
        !          1470:                if ( ! (*((Ptr)&(vcb->vcbAtrb) + 1) & kHFSVolumeHardwareLockMask) )     //      if it's not write protected
        !          1471:                        return( noErr );
        !          1472:                else
        !          1473:                        return( wPrErr );
        !          1474:        }
        !          1475:        else
        !          1476:        {
        !          1477:                return( vLckdErr );
        !          1478:        }
        !          1479: }
        !          1480: 
        !          1481: 
        !          1482: 
        !          1483: 
        !          1484: 
        !          1485: #if TARGET_OS_MAC
        !          1486: 
        !          1487: //�������������������������������������������������������������������������������
        !          1488: //     Routine:        FlushVolume             Asm: FlushVFiles
        !          1489: //
        !          1490: //     Function:       All file buffers on the volume are flushed and any changed
        !          1491: //                             directory information is written out to the disk.
        !          1492: //
        !          1493: //�������������������������������������������������������������������������������
        !          1494: OSErr  FlushVolume( ExtendedVCB *vcb )
        !          1495: {
        !          1496:        UInt16                  index;
        !          1497:        Ptr                             fcbs;
        !          1498:        FCB                             *fcb;
        !          1499:        OSErr                   err;
        !          1500:        Boolean                 doneSearching;
        !          1501:        
        !          1502:        Get1stFileControlBlock( &index, &fcbs );
        !          1503: 
        !          1504: //ckNxtFCB
        !          1505:        err = noErr;
        !          1506:        do
        !          1507:        {
        !          1508:                fcb = GetFileControlBlock( index );
        !          1509:                if ( (fcb->fcbFlNm != 0) && (fcb->fcbVPtr == vcb) )     //      The file is currently open and on this volume
        !          1510:                {
        !          1511:                        if ( fcb->fcbFlNm >= fsUsrCNID )                                //      is it a user file?
        !          1512:                        {
        !          1513:                                //--    Found an open user file on the volume, so return a busy condition...
        !          1514:                                err = CloseFile( vcb, index, fcbs );
        !          1515:                                if ( err != noErr )
        !          1516:                                        break;
        !          1517:                        }
        !          1518:                }
        !          1519:                
        !          1520:                doneSearching = GetNextFileControlBlock( &index, fcbs );
        !          1521:                
        !          1522:        } while ( !doneSearching );
        !          1523:        
        !          1524:        return( err );
        !          1525: }
        !          1526: 
        !          1527: 
        !          1528: 
        !          1529: //�������������������������������������������������������������������������������
        !          1530: //     Routine:        DisposeFileControlBlocks from Asm: DsposFCBs
        !          1531: //
        !          1532: //     Function:       Clears the extent B*-Tree refNum & catalog refnum
        !          1533: //
        !          1534: //�������������������������������������������������������������������������������
        !          1535: void   DisposeFileControlBlocks( ExtendedVCB *vcb )
        !          1536: {
        !          1537:        OSErr   err;
        !          1538:        
        !          1539:        err = AttributesCloseVolume( vcb );
        !          1540: #if DEBUG_BUILD
        !          1541:        if ( err != noErr ) DebugStr("\pHFS+: Can't close Property Manager");
        !          1542: #endif
        !          1543: 
        !          1544:        if ( vcb->extentsRefNum != 0 )
        !          1545:        {
        !          1546:                //--    Clear extent B*-Tree refNum file number in FCB as unused
        !          1547:                ( (FCB *) ( LMGetFCBSPtr() + vcb->extentsRefNum ) )->fcbFlNm = 0L;
        !          1548:        }
        !          1549:        if ( vcb->catalogRefNum != 0 )
        !          1550:        {
        !          1551:                //--    Clear catalog refnum file number in FCB as unused
        !          1552:                ( (FCB *) ( LMGetFCBSPtr() + vcb->catalogRefNum ) )->fcbFlNm = 0L;
        !          1553:        }
        !          1554:        
        !          1555:        if ( vcb->vcbSigWord == kHFSPlusSigWord && vcb->allocationsRefNum != 0)
        !          1556:        {
        !          1557:                //--    Clear allocation (bitmap) file number in FCB as unused
        !          1558:                ( (FCB *) ( LMGetFCBSPtr() + vcb->allocationsRefNum ) )->fcbFlNm = 0L;
        !          1559:        }
        !          1560: }
        !          1561: 
        !          1562: #endif /* TARGET_OS_MAC */
        !          1563: 
        !          1564: 
        !          1565: //�������������������������������������������������������������������������������
        !          1566: //     Routine:        AccessBTree from Asm: AccessBT
        !          1567: //
        !          1568: //     Function:       Create an access path for a B*-Tree file:
        !          1569: //                             1. Initialize the FCB
        !          1570: //                             2. Attach a B*-Tree control block
        !          1571: //
        !          1572: //     Note:           For now the compare proc is the entry to the assembly glue calling a C compare function.
        !          1573: //                             Once BTOpen is ported to C, we can pass in C comparison routines.
        !          1574: //
        !          1575: //     Result:         I/O result from BTOpen
        !          1576: //�������������������������������������������������������������������������������
        !          1577: #if TARGET_OS_MAC
        !          1578: OSErr  AccessBTree( ExtendedVCB *vcb, FileReference refNum, UInt32 fileID, UInt32 fileClumpSize, void *CompareRoutine )
        !          1579: {
        !          1580:        FCB                             *fcb;
        !          1581:        OSErr                   err;
        !          1582: 
        !          1583:        fcb = SetupFCB( vcb, refNum, fileID, fileClumpSize );
        !          1584:        
        !          1585:        err = OpenBTree( refNum, CompareRoutine );
        !          1586:        
        !          1587:        return( err );
        !          1588: }
        !          1589: #endif /* TARGET_OS_MAC */
        !          1590: 
        !          1591: //�������������������������������������������������������������������������������
        !          1592: //     Routine:        SetupFCB fills in the FCB info
        !          1593: //
        !          1594: //     Returns:        The filled up FCB
        !          1595: //�������������������������������������������������������������������������������
        !          1596: #if TARGET_OS_MAC
        !          1597: FCB    *SetupFCB( ExtendedVCB *vcb, FileReference refNum, UInt32 fileID, UInt32 fileClumpSize )
        !          1598: {
        !          1599:        FCB                             *fcb;
        !          1600: 
        !          1601:        fcb = (FCB *) GetFileControlBlock( refNum );
        !          1602:        
        !          1603:        fcb->fcbFlags           = 0;
        !          1604:        fcb->fcbSBlk            = 0;
        !          1605:        fcb->fcbCrPs            = 0;
        !          1606:        fcb->fcbFlNm            = fileID;
        !          1607:        fcb->fcbVPtr            = vcb;
        !          1608:        fcb->fcbClmpSize        = fileClumpSize;
        !          1609:        
        !          1610:        // for debugging...     
        !          1611:        switch (fileID)
        !          1612:        {
        !          1613:                case kHFSExtentsFileID:
        !          1614:                        BlockMoveData( "\p**** EXTENTS B-TREE", fcb->fcbCName, sizeof("\p**** EXTENTS B-TREE") );
        !          1615:                        break;
        !          1616:                case kHFSCatalogFileID:
        !          1617:                        BlockMoveData( "\p**** CATALOG B-TREE", fcb->fcbCName, sizeof("\p**** CATALOG B-TREE") );
        !          1618:                        break;
        !          1619:                case kHFSAllocationFileID:
        !          1620:                        BlockMoveData( "\p**** VOLUME BITMAP", fcb->fcbCName,  sizeof("\p**** VOLUME BITMAP") );
        !          1621:                        break;
        !          1622:                case kHFSAttributesFileID:
        !          1623:                        BlockMoveData( "\p**** ATTRIBUTES B-TREE", fcb->fcbCName,  sizeof("\p**** ATTRIBUTES B-TREE") );
        !          1624:                        break;
        !          1625:        }
        !          1626:        
        !          1627:        return( fcb );
        !          1628: }
        !          1629: #endif /* TARGET_OS_MAC */
        !          1630: 
        !          1631: 
        !          1632: #if TARGET_OS_MAC
        !          1633: 
        !          1634: //�������������������������������������������������������������������������������
        !          1635: //     Routine:        FindFileControlBlock from Asm: FindFCB
        !          1636: //
        !          1637: //     Function:       Find an unused FCB
        !          1638: //
        !          1639: //     Result:         error
        !          1640: //�������������������������������������������������������������������������������
        !          1641: OSErr  FindFileControlBlock( UInt16 *index, Ptr *fcbsH )
        !          1642: {
        !          1643:        Boolean                 doneSearching;
        !          1644:        OSErr                   err;
        !          1645:        FCB                             *fcb;
        !          1646:        
        !          1647:        Get1stFileControlBlock( index, fcbsH );
        !          1648:        
        !          1649:        do
        !          1650:        {
        !          1651:                doneSearching = GetNextFileControlBlock( index, *fcbsH );
        !          1652:                if ( doneSearching == false )
        !          1653:                {
        !          1654:                        fcb = GetFileControlBlock( *index );
        !          1655:                        if ( fcb->fcbFlNm == 0 )                                                                                //      FCB unused?
        !          1656:                        {
        !          1657:                                ClearMemory( fcb, sizeof( FCB ) );
        !          1658:                                fcb->fcbFlNm = -1;                                                                                      //      Mark it in use
        !          1659:                                err = noErr;
        !          1660:                                doneSearching = true;
        !          1661:                        }
        !          1662:                }
        !          1663:                else
        !          1664:                {
        !          1665:                        err = tmfoErr;
        !          1666:                }
        !          1667:        }       while ( doneSearching == false );
        !          1668:        
        !          1669:        return( err );
        !          1670: }
        !          1671: 
        !          1672: 
        !          1673: //�������������������������������������������������������������������������������
        !          1674: //     Routine:        Get1stFileControlBlock from Asm: Gt1stFCB
        !          1675: //
        !          1676: //     Function:       Point to the first FCB
        !          1677: //�������������������������������������������������������������������������������
        !          1678: void   Get1stFileControlBlock( UInt16 *index, Ptr *fcbsH )
        !          1679: {
        !          1680:        //              struct FCBSRec {
        !          1681:        //                      UInt16                                  length;                                                         //      first word is FCB part length
        !          1682:        //                      FCB                                             fcb[1];                                                         //      fcb array
        !          1683:        //              };
        !          1684:        *fcbsH = LMGetFCBSPtr();
        !          1685:        *index = 2;
        !          1686: }
        !          1687: 
        !          1688: 
        !          1689: //�������������������������������������������������������������������������������
        !          1690: //     Routine:        GetNextFileControlBlock from Asm: GtNxtFCB
        !          1691: //
        !          1692: //     Function:       Increment to the next FCB
        !          1693: //                                     Check if we've hit the end fcb yet
        !          1694: //
        !          1695: //     Result:         Return true if end was reached
        !          1696: //�������������������������������������������������������������������������������
        !          1697: Boolean        GetNextFileControlBlock( UInt16 *index, Ptr fcbsP )
        !          1698: {
        !          1699: 
        !          1700:        *index += LMGetFSFCBLen();
        !          1701:         
        !          1702:        return ( *index == *((UInt16 *)fcbsP) );                                                                        //      first word is length
        !          1703: }
        !          1704: 
        !          1705: #endif /* TARGET_OS_MAC */
        !          1706: 
        !          1707: 
        !          1708: //�������������������������������������������������������������������������������
        !          1709: //     Routine:        DivUp from Asm: DivUp
        !          1710: //
        !          1711: //     Function:       Given a number of bytes and block size, calculate the number of
        !          1712: //                             blocks needd to hold all the bytes.
        !          1713: //
        !          1714: //     Result:         Number of physical blocks needed
        !          1715: //�������������������������������������������������������������������������������
        !          1716: UInt16 DivUp( UInt32 byteRun, UInt32 blockSize )
        !          1717: {
        !          1718:        UInt32  blocks;
        !          1719:        
        !          1720:        blocks = (byteRun + blockSize - 1) / blockSize;                                                 //      Divide up, remember this is integer math.
        !          1721:        
        !          1722:        if ( blocks > 0xffff )                                                                                                  //      maximum 16 bit value
        !          1723:                blocks = 0xffff;
        !          1724:                
        !          1725:        return( (UInt16) blocks );
        !          1726: }
        !          1727: 
        !          1728: 
        !          1729: 
        !          1730: 
        !          1731: //�������������������������������������������������������������������������������
        !          1732: //     Routine:        HFSBlocksFromTotalSectors
        !          1733: //
        !          1734: //     Function:       Given the total number of sectors on the volume, calculate
        !          1735: //                             the 16Bit number of allocation blocks, and allocation block size.
        !          1736: //
        !          1737: //     Result:         none
        !          1738: //�������������������������������������������������������������������������������
        !          1739: void   HFSBlocksFromTotalSectors( UInt32 totalSectors, UInt32 *blockSize, UInt16 *blockCount )
        !          1740: {
        !          1741:        UInt16  newBlockSizeInSectors   = 1;
        !          1742:        UInt32  newBlockCount                   = totalSectors;
        !          1743:        
        !          1744:        while ( newBlockCount > 0XFFFF )
        !          1745:        {
        !          1746:                newBlockSizeInSectors++;
        !          1747:                newBlockCount   =  totalSectors / newBlockSizeInSectors;
        !          1748:        }
        !          1749:        
        !          1750:        *blockSize      = newBlockSizeInSectors * 512;
        !          1751:        *blockCount     = newBlockCount;
        !          1752: }
        !          1753: 
        !          1754: 
        !          1755: 
        !          1756: 
        !          1757: //�������������������������������������������������������������������������������
        !          1758: //     Routine:        ValidMasterDirectoryBlock
        !          1759: //
        !          1760: //     Function:       Run some sanity checks to make sure the MDB is valid
        !          1761: //
        !          1762: //     Result:         error
        !          1763: //�������������������������������������������������������������������������������
        !          1764: OSErr  ValidMasterDirectoryBlock( HFSMasterDirectoryBlock *mdb )
        !          1765: {
        !          1766:        OSErr   err;
        !          1767:        
        !          1768:        if ( (mdb->drSigWord == kHFSPlusSigWord) || (mdb->drSigWord == kHFSSigWord) )   //      if HFS or HFS Plus volume
        !          1769:        {
        !          1770:                if ( (mdb->drAlBlkSiz != 0) && ((mdb->drAlBlkSiz & 0x01FF) == 0) )                      //      non zero multiple of 512
        !          1771:                        err = noErr;
        !          1772:                else
        !          1773:                        err = badMDBErr;
        !          1774:        }
        !          1775:        else
        !          1776:        {
        !          1777:                err = noMacDskErr;
        !          1778:        }
        !          1779:        
        !          1780:        return( err );
        !          1781: }
        !          1782: 
        !          1783: 
        !          1784: //�������������������������������������������������������������������������������
        !          1785: //     Routine:        ValidVolumeHeader
        !          1786: //
        !          1787: //     Function:       Run some sanity checks to make sure the VolumeHeader is valid
        !          1788: //
        !          1789: //     Result:         error
        !          1790: //�������������������������������������������������������������������������������
        !          1791: OSErr  ValidVolumeHeader( HFSPlusVolumeHeader *volumeHeader )
        !          1792: {
        !          1793:        OSErr   err;
        !          1794:        
        !          1795:        if ( volumeHeader->signature == kHFSPlusSigWord && volumeHeader->version == kHFSPlusVersion )
        !          1796:        {
        !          1797:                if ( (volumeHeader->blockSize != 0) && ((volumeHeader->blockSize & 0x01FF) == 0) )                      //      non zero multiple of 512
        !          1798:                        err = noErr;
        !          1799:                else
        !          1800:                        err = badMDBErr;                                                                        //��    I want badVolumeHeaderErr in Errors.i
        !          1801:        }
        !          1802:        else
        !          1803:        {
        !          1804:                err = noMacDskErr;
        !          1805:        }
        !          1806:        
        !          1807:        return( err );
        !          1808: }
        !          1809: 
        !          1810: 
        !          1811: #if TARGET_OS_MAC
        !          1812: 
        !          1813: //�������������������������������������������������������������������������������
        !          1814: //     Routine:        FindDrive from Asm: FindDrive
        !          1815: //
        !          1816: //     Function:       Given a drive number, this routine returns the RefNum
        !          1817: //                             for the driver by searching the system drive queue.
        !          1818: //
        !          1819: //     Result:         error
        !          1820: //�������������������������������������������������������������������������������
        !          1821: OSErr  FindDrive( short *driverRefNum, DrvQEl **dqe, short driveNumber )
        !          1822: {
        !          1823:        OSErr   err             =       nsDrvErr;                                               //      initialize as "drive not found"
        !          1824:        
        !          1825:        *dqe = ((DrvQEl*)LMGetDrvQHdr()->qHead);                        //      get first DQE
        !          1826:        while ( *dqe != 0 )                                                                     //      end of list?
        !          1827:        {
        !          1828:                if ( (**dqe).dQDrive != driveNumber )                   //      find the drive we're looking for?
        !          1829:                {
        !          1830:                        *dqe = (DrvQEl*)(**dqe).qLink;                          //      get ptr to next
        !          1831:                }
        !          1832:                else
        !          1833:                {
        !          1834:                        *driverRefNum = (**dqe).dQRefNum;                       //      return driver refnum
        !          1835:                        if ( (**dqe).dQFSID == 0 )                                      //      is this a Mac Filesystem?
        !          1836:                                err = noErr;
        !          1837:                        else
        !          1838:                                err = extFSErr;                                                 //      no, return error
        !          1839:                        break;
        !          1840:                }
        !          1841:        }
        !          1842:        
        !          1843:        return( err );
        !          1844: }
        !          1845: 
        !          1846: 
        !          1847: //�������������������������������������������������������������������������������
        !          1848: //     Routine:        GetVCBDriveNum from Asm: GetVCBDrv
        !          1849: //
        !          1850: //     Function:       Determine VCB from DriveNum/VRefNum field
        !          1851: //
        !          1852: //     Result:         error
        !          1853: //�������������������������������������������������������������������������������
        !          1854: OSErr  GetVCBDriveNum( ExtendedVCB **vcbResult, short driveNumber )
        !          1855: {
        !          1856:        ExtendedVCB     *vcb;
        !          1857:        
        !          1858:        for ( vcb = (ExtendedVCB*)((LMGetVCBQHdr())->qHead) ; vcb != nil ; vcb = (ExtendedVCB*)vcb->qLink )     //      search the queue of VCBs
        !          1859:        {
        !          1860:                if ( vcb->vcbDrvNum == driveNumber )                                    //      success!
        !          1861:                        break;
        !          1862:                if ( vcb->vcbDrvNum == 0 )                                                              //      offline
        !          1863:                {
        !          1864:                        if ( vcb->vcbDRefNum == driveNumber * (-1) )            //      offline match
        !          1865:                                break;
        !          1866:                }
        !          1867:        }
        !          1868:        
        !          1869:        *vcbResult = vcb;
        !          1870: 
        !          1871:        if ( vcb == nil )
        !          1872:                return( nsvErr );
        !          1873:        else
        !          1874:                return( noErr );
        !          1875:  }
        !          1876: 
        !          1877: 
        !          1878: //�������������������������������������������������������������������������������
        !          1879: //     Routine:        GetVCBRefNum from Asm: GetVCBRfn
        !          1880: //
        !          1881: //     Function:       Determine VCB from DriveNum/VRefNum field
        !          1882: //
        !          1883: //     Result:         error
        !          1884: //�������������������������������������������������������������������������������
        !          1885: OSErr  GetVCBRefNum( ExtendedVCB **vcbResult, short vRefNum )
        !          1886: {
        !          1887:        ExtendedVCB     *vcb;
        !          1888:        
        !          1889:        for ( vcb = (ExtendedVCB*)((LMGetVCBQHdr())->qHead) ; vcb != nil ; vcb = (ExtendedVCB*)vcb->qLink )     //      search the queue of VCBs
        !          1890:        {
        !          1891:                if ( vcb->vcbVRefNum == vRefNum )                               //      success!
        !          1892:                {
        !          1893:                        *vcbResult = vcb;
        !          1894:                        return( noErr );
        !          1895:                }
        !          1896:        }
        !          1897:        
        !          1898:        return( nsvErr );
        !          1899: }
        !          1900: 
        !          1901: #endif /* TARGET_OS_MAC */
        !          1902: 
        !          1903: 
        !          1904: //�������������������������������������������������������������������������������
        !          1905: //     Routine:        IsARamDiskDriver from Asm: IsRAMDiskDriver
        !          1906: //
        !          1907: //     Function:       Test if disk driver is a RAM disk
        !          1908: //
        !          1909: //     Result:         true if RAM disk
        !          1910: //�������������������������������������������������������������������������������
        !          1911: Boolean        IsARamDiskDriver( void )
        !          1912: {
        !          1913: #if TARGET_OS_MAC
        !          1914:        OSErr                   err;
        !          1915:        ParamBlockRec   *pb;
        !          1916:        Byte                    diskType;
        !          1917:        
        !          1918:        pb = (ParamBlockRec *) LMParamBlock;                                    //      general purpose I/O param block
        !          1919:        pb->ioParam.ioCompletion        = 0;                                            //      no completion routine
        !          1920:        pb->cntrlParam.csCode           = infoCC;                                       //      pass control code
        !          1921:        pb->cntrlParam.csParam[0]       = 0;                                            //      start out clean
        !          1922:        pb->cntrlParam.csParam[1]       = 0;
        !          1923:        
        !          1924:        err = PBControlSync( pb );                                                              //      get driver info�
        !          1925:        
        !          1926:        if ( err == noErr )                                                                             //      this control call supported
        !          1927:        {
        !          1928:                diskType = ((Byte *)(pb->cntrlParam.csParam))[3];
        !          1929:                if ( (diskType == ramDiskType) || (diskType == romDiskType) )
        !          1930:                        return( true );
        !          1931:        }
        !          1932:        
        !          1933:        return( false );
        !          1934: #else
        !          1935:        return( false );
        !          1936: #endif         /* TARGET_OS_MAC */
        !          1937: }
        !          1938: 
        !          1939: 
        !          1940: #if TARGET_OS_MAC
        !          1941: 
        !          1942: OSErr  MakeVCBsExtendedVCBs( void )
        !          1943: {
        !          1944:        VCB                                             *oVCB;
        !          1945:        VCB                                             *nextVCB;
        !          1946:        ExtendedVCB                             *exVCB;
        !          1947:        ExtendedVCB                             *firstNewVCBInQueue     = nil;
        !          1948:        QHdr                                    *vcbQHdr;
        !          1949:        UInt16                                  fcbIndex;
        !          1950:        UInt16                                  i;
        !          1951:        Ptr                                             fcbs;
        !          1952:        FCB                                             *fcb;
        !          1953:        WDCBArray                               *wdcbsAry;
        !          1954:        OSErr                                   err;
        !          1955:                
        !          1956:        vcbQHdr = LMGetVCBQHdr();                                                                                       //      search the queue of VCBs
        !          1957: 
        !          1958:        for ( oVCB = (VCB *)vcbQHdr->qHead ; (oVCB != nil) && (oVCB != (VCB *)firstNewVCBInQueue) ; )
        !          1959:        {
        !          1960:                nextVCB = (VCB *) oVCB->qLink;
        !          1961:                
        !          1962:                if ( (oVCB->vcbSigWord != kHFSPlusSigWord) && (oVCB->vcbFSID == 0) )    //      if it's an HFS Plus VCB, assume it is already of ExtendedVCB type
        !          1963:                {
        !          1964:                        exVCB = (ExtendedVCB *) NewPtrSysClear( sizeof(ExtendedVCB) );  //      allocate space for the new ExtendedVCB
        !          1965:                        ReturnIfError( MemError() );
        !          1966:                        BlockMoveData( oVCB, exVCB, sizeof(VCB) );                                              //      copy the original VCB over
        !          1967:                        
        !          1968:                        if ( firstNewVCBInQueue == nil )
        !          1969:                                firstNewVCBInQueue = exVCB;
        !          1970:                        
        !          1971:                        //--    Set up the Extended fields, used internally in the HFS source
        !          1972:                        exVCB->totalBlocks              =       exVCB->vcbNmAlBlks;
        !          1973:                        exVCB->freeBlocks               =       exVCB->vcbFreeBks;
        !          1974:                        exVCB->blockSize                =       exVCB->vcbAlBlkSiz;
        !          1975:                        exVCB->nextAllocation   =       (UInt16)exVCB->vcbAllocPtr;                     //      Almost certain to be zero
        !          1976:                        // Note: SuperMario ROMs clear vcbAllocPtr and then flush the MDB.
        !          1977:                        // So, when an HFS disk gets mounted, the allocation pointer is cleared both in
        !          1978:                        // memory and on disk.  The only way to fix this is to put HFS Plus in ROM.
        !          1979: 
        !          1980:                        //--    Set up the caches for this volume
        !          1981:                        err = InitMRUCache( sizeof(UInt32), kDefaultNumMRUCacheBlocks, &(exVCB->hintCachePtr) );
        !          1982:                        ReturnIfError( err );
        !          1983:                        
        !          1984:                        err = CreateVolumeCatalogCache(exVCB);
        !          1985:                        ReturnIfError( err );
        !          1986:                        
        !          1987:                        //--    If we are dealing with the default VCB, set the corresponding ExtendedVCB as the default
        !          1988:                        if ( oVCB == (VCB*) LMGetDefVCBPtr() )
        !          1989:                                LMSetDefVCBPtr( (Ptr) exVCB );
        !          1990:                        
        !          1991:                        //--    Remove and deallocate the original VCB
        !          1992:                        err = Dequeue( (QElemPtr) oVCB, (QHdrPtr) vcbQHdr );                    //      Dequeue the VCB from the VCB Queue
        !          1993:                        ReturnIfError( err );
        !          1994:                        
        !          1995:                        //--    Search the FCB list for refs to the old VCB pointer and update them
        !          1996:                        Get1stFileControlBlock( &fcbIndex, &fcbs );
        !          1997:                        do
        !          1998:                        {
        !          1999:                                fcb = GetFileControlBlock( fcbIndex );
        !          2000:                                if ( fcb->fcbVPtr == (ExtendedVCB *) oVCB )     
        !          2001:                                        fcb->fcbVPtr = exVCB;
        !          2002:                        } while ( GetNextFileControlBlock( &fcbIndex, fcbs ) == false );//      while there's still some left
        !          2003:                        
        !          2004:                        //--    Search the WDCB list for refs to the old VCB pointer and update them
        !          2005:                        wdcbsAry = (WDCBArray*)LMGetWDCBsPtr();                                                 //      Point to WDCB array
        !          2006:                        for ( i=0 ; i< (wdcbsAry->count / sizeof(WDCBRec)) ; i++ )
        !          2007:                        {
        !          2008:                                if ( wdcbsAry->wdcb[i].wdVCBPtr == oVCB )
        !          2009:                                        wdcbsAry->wdcb[i].wdVCBPtr = (VCB *) exVCB;
        !          2010:                        }
        !          2011:                        
        !          2012:                        //--    Deallocate memory used by the old VCB
        !          2013:                        DisposePtr( (Ptr) oVCB );
        !          2014: 
        !          2015:                        //--    Insert the new extended vcb in the queue
        !          2016:                        Enqueue( (QElemPtr) exVCB, (QHdrPtr) vcbQHdr );
        !          2017:                }
        !          2018:                oVCB = nextVCB;
        !          2019:        }
        !          2020:        
        !          2021:        return( noErr );
        !          2022: }
        !          2023: 
        !          2024: 
        !          2025: //�������������������������������������������������������������������������������
        !          2026: //     Routine:        RemountWrappedVolumes
        !          2027: //
        !          2028: //     Function:       Called by InitHFSPlus, Attempt to re-mount all HFS+ volumes
        !          2029: //                             previously mounted as HFS wrappers.
        !          2030: //
        !          2031: //     Note:           This routine assumes vcbEmbedSigWord is cleared during mount.
        !          2032: //
        !          2033: //�������������������������������������������������������������������������������
        !          2034: extern void    RemountWrappedVolumes( void )
        !          2035: {
        !          2036:        ExtendedVCB             *vcb;
        !          2037:        ExtendedVCB             *nextVCB;
        !          2038:        OSErr                   err;
        !          2039: 
        !          2040:        for ( vcb = (ExtendedVCB *) ((QHdr*)LMGetVCBQHdr())->qHead ; vcb != nil ; )
        !          2041:        {
        !          2042:                //      PBMountVol and UnmountVol modify the vcb queue, so save the link
        !          2043:                nextVCB = (ExtendedVCB *) vcb->qLink;
        !          2044: 
        !          2045:                if ( (vcb->vcbEmbedSigWord == kHFSPlusSigWord) && ( vcb->vcbFSID == 0) )
        !          2046:                {       
        !          2047:                        err = UnmountVol( nil, vcb->vcbVRefNum );
        !          2048:                        if ( err == noErr )
        !          2049:                        {
        !          2050:                                ParamBlockRec theParam;
        !          2051:                                
        !          2052:                                theParam.ioParam.ioCompletion   = nil;
        !          2053:                                theParam.ioParam.ioNamePtr              = nil;
        !          2054:                                theParam.ioParam.ioVRefNum              = vcb->vcbDrvNum;
        !          2055:                                (void) PBMountVol( &theParam );
        !          2056:                        }
        !          2057:                }
        !          2058:                
        !          2059:                vcb = nextVCB;
        !          2060:        }
        !          2061: }
        !          2062: 
        !          2063: 
        !          2064: //�������������������������������������������������������������������������������
        !          2065: //     Routine:        FillHFSStack
        !          2066: //
        !          2067: //     Function:       Called by HFSInit.  Fills the newly created HFS stack so we 
        !          2068: //                             can identify how much of the stack is actually being used.
        !          2069: //
        !          2070: //�������������������������������������������������������������������������������
        !          2071: extern void    FillHFSStack( void )
        !          2072: {
        !          2073:        Ptr             p;
        !          2074:        SInt16  len             =       0;
        !          2075:        char    *s              =       "HFS+ By Don Brady, Mark Day, and Deric Horn.   ";
        !          2076:        
        !          2077:        while ( s[len] != '\0' )
        !          2078:                ++len;
        !          2079:                
        !          2080:        for ( p = LMGetHFSStkTop() - kFileSystemStackSize ; p + len < LMGetHFSStkTop() ; p += len )
        !          2081:        {
        !          2082:                BlockMoveData( s, p, len );
        !          2083:        }
        !          2084: }
        !          2085: 
        !          2086: 
        !          2087: //�������������������������������������������������������������������������������
        !          2088: //     Routine:        CheckVolumeOffLine from Asm: ExtOffLinCk
        !          2089: //
        !          2090: //     Function:       Simple routine to separate out calls to be handled by an
        !          2091: //                             external file system.
        !          2092: //
        !          2093: //     Result:         noErr if we handle it
        !          2094: //�������������������������������������������������������������������������������
        !          2095: //�� Same function appears in CatSearch.c as ExtOffLineCheck(), but the code is slightly different
        !          2096: //�� we should delete one copy.
        !          2097: OSErr  CheckVolumeOffLine( ExtendedVCB *vcb )
        !          2098: {
        !          2099:        OSErr           err;
        !          2100:        
        !          2101:        err = CheckExternalFileSystem( vcb );
        !          2102:        if ( err == noErr && vcb->vcbDrvNum == 0 )
        !          2103:                err = volOffLinErr;
        !          2104:        
        !          2105:        LMSetReqstVol( (Ptr)vcb );
        !          2106:        
        !          2107:        return( err );
        !          2108: }
        !          2109: 
        !          2110: #endif /* TARGET_OS_MAC */
        !          2111: 
        !          2112: 
        !          2113: 
        !          2114: 
        !          2115: //_______________________________________________________________________
        !          2116: //
        !          2117: //     Routine:        CountRootFiles
        !          2118: //
        !          2119: //     Input:          pointer to VCB
        !          2120: //
        !          2121: //     Function:       Return a count of the number of files and folders in
        !          2122: //                             the root directory of a volume.  For HFS volumes, this
        !          2123: //                             is maintained in the VCB (and MDB).  For HFS Plus volumes,
        !          2124: //                             we get the valence of the root directory from its catalog
        !          2125: //                             record.
        !          2126: //_______________________________________________________________________
        !          2127: UInt16 CountRootFiles(ExtendedVCB *vcb)
        !          2128: {
        !          2129:        OSErr                   err;
        !          2130:        FSSpec                  spec;
        !          2131:        CatalogNodeData catNodeData;
        !          2132:        UInt32                  hint;
        !          2133:        UInt16                  rootCount;
        !          2134:        
        !          2135: //     if (vcb->vcbSigWord == kHFSSigWord || vcb->vcbFSID != 0) {
        !          2136: //             return vcb->vcbNmFls;
        !          2137: //     }
        !          2138:        
        !          2139:        //      Here, it's an HFS Plus volume, so get the valence from the root
        !          2140:        //      directory's catalog record.
        !          2141:        
        !          2142:        rootCount = 0;
        !          2143:        
        !          2144:        err = GetCatalogNode( vcb, kHFSRootFolderID, nil, kNoHint, &spec, &catNodeData, &hint );
        !          2145:        if ( err == noErr ) {
        !          2146:                if (catNodeData.valence < 65536)
        !          2147:                        rootCount = catNodeData.valence;
        !          2148:                else
        !          2149:                        rootCount = 65535;                      //      if the value is too large, pin it
        !          2150:        }
        !          2151: 
        !          2152:        return rootCount;
        !          2153: }
        !          2154: 
        !          2155: #if TARGET_OS_MAC
        !          2156: 
        !          2157: //_______________________________________________________________________
        !          2158: //
        !          2159: //     Routine:        GetVolumeInformation    :       GetVolInfo
        !          2160: //     Arguments:      HVolumeParam    *volume
        !          2161: //     Output:         WDCBRec                 **wdcb          (Needed for ExtFsHook in CmdDone)
        !          2162: //                             OSErr                   err
        !          2163: //
        !          2164: //     Function:       Return information about the volume in a mounted drive.
        !          2165: //                             If the IOVolIndex field is 0, the name of the default
        !          2166: //                             volume is returned; if non-zero, the name of the nth
        !          2167: //                             mounted volume is returned. The maximum length of a
        !          2168: //                             volume name is 27 bytes.  The drive number for the
        !          2169: //                             volume is also returned.
        !          2170: //_______________________________________________________________________
        !          2171: 
        !          2172: OSErr  GetVolumeInformation( HVolumeParam *volume, WDCBRecPtr *wdcb )
        !          2173: {
        !          2174:        FSSpec                  spec;
        !          2175:        UInt32                  maxBlocks;
        !          2176:        SInt16                  nameLength;
        !          2177:        SInt16                  volumeIndex;
        !          2178:        FileReference                   vRefNum;
        !          2179:        OSErr                   err;
        !          2180:        Ptr                             fcbs;
        !          2181:        FCB                             *fcb;
        !          2182:        ExtendedVCB             *vcb;
        !          2183:        unsigned char   *pathName;
        !          2184:        CatalogNodeData catNodeData;
        !          2185:        Boolean                 doneSearching;
        !          2186:        Boolean                 nameSpecified;
        !          2187:        WDCBArray               *wdcbsAry;
        !          2188:        UInt16                  fcbIndex;
        !          2189: 
        !          2190:        volumeIndex = volume->ioVolIndex;
        !          2191:        if ( volumeIndex == 0 )
        !          2192:        {
        !          2193:                err = DeturmineVolume1( (VolumeParam*)volume, &nameLength, &nameSpecified, (ExtendedVCB **)&vcb, wdcb, &pathName );
        !          2194:                if ( err != noErr )     goto CmdDone;
        !          2195:        }
        !          2196:        else if ( volume->ioVolIndex < 0 )
        !          2197:        {
        !          2198:                err = DeturmineVolume3( (VolumeParam*)volume, &nameLength, &nameSpecified, (ExtendedVCB **)&vcb, wdcb, &pathName );
        !          2199:                if ( err != noErr )     goto CmdDone;
        !          2200:        }
        !          2201:        else
        !          2202:        {
        !          2203:                nameSpecified = false;                                          //      Never any name specified (ioNamePtr is output arg)
        !          2204:                volume->ioVRefNum = 0;
        !          2205: 
        !          2206:                for ( vcb = (ExtendedVCB*)((LMGetVCBQHdr())->qHead) ; vcb != nil ; vcb = (ExtendedVCB*)vcb->qLink )     //      search the queue of VCBs
        !          2207:                {
        !          2208:                        if ( --volumeIndex == 0 )
        !          2209:                                break;
        !          2210:                }
        !          2211:                if ( vcb == nil )
        !          2212:                {
        !          2213:                        err = nsvErr;
        !          2214:                        goto CmdDone;
        !          2215:                }
        !          2216:        }
        !          2217: 
        !          2218:        //      first copy the heart of the VCB into the parameter block
        !          2219:        volume->ioVCrDate       =       vcb->vcbCrDate;
        !          2220:        volume->ioVLsMod        =       vcb->vcbLsMod;
        !          2221:        volume->ioVAtrb         =       vcb->vcbAtrb;
        !          2222:        volume->ioVNmFls        =       vcb->vcbNmFls;                          // don't call CountRootFiles(vcb) anymore
        !          2223:        volume->ioVBitMap       =       vcb->vcbVBMSt;
        !          2224:        volume->ioVNmAlBlks     =       vcb->vcbNmAlBlks;                       //      we return the HFS volume format equivalents cuz ioVNmAlBlks is a short
        !          2225:        volume->ioVAlBlkSiz     =       vcb->vcbAlBlkSiz;
        !          2226:        volume->ioVClpSiz       =       vcb->vcbClpSiz;
        !          2227:        volume->ioAlBlSt        =       vcb->vcbAlBlSt;
        !          2228:        volume->ioVNxtCNID      =       vcb->vcbNxtCNID;
        !          2229:        volume->ioVFrBlk        =       vcb->vcbFreeBks;
        !          2230:        
        !          2231:        if ( vcb->vcbFSID != 0 )
        !          2232:                volume->ioAllocPtr      =       vcb->vcbAllocPtr;               // external file system
        !          2233:        else if ( vcb->nextAllocation < 0xFFFF )
        !          2234:                volume->ioAllocPtr      =       vcb->nextAllocation;
        !          2235:        else
        !          2236:                volume->ioAllocPtr      =       0xFFFF;
        !          2237:        
        !          2238: 
        !          2239:        Get1stFileControlBlock( &fcbIndex, &fcbs );
        !          2240:        doneSearching           =       false;
        !          2241: 
        !          2242:        do
        !          2243:        {
        !          2244:                fcb = GetFileControlBlock( fcbIndex );
        !          2245:                if ( fcb->fcbVPtr == (ExtendedVCB *) vcb )              //      The file is currently open and on this volume
        !          2246:                {
        !          2247:                        if ( fcb->fcbFlNm >= fsUsrCNID )
        !          2248:                                break;
        !          2249:                }
        !          2250:                doneSearching = GetNextFileControlBlock( &fcbIndex, fcbs );
        !          2251:        } while ( doneSearching == false );
        !          2252:        
        !          2253:        if ( doneSearching == true )
        !          2254:                volume->ioVAtrb         &=      ~kFilesOpenMask;                //      Clear if no open files match
        !          2255:        else
        !          2256:                volume->ioVAtrb         |=      kFilesOpenMask;                 //      Set if any files are opened
        !          2257: 
        !          2258:        if ( vcb == (ExtendedVCB *) LMGetDefVCBPtr() )          //      Are we supposedly the default?
        !          2259:                volume->ioVAtrb         |=      kDefaultVolumeMask;             //      Set volume as the default
        !          2260:        else
        !          2261:                volume->ioVAtrb         &=      ~kDefaultVolumeMask;    //      Clear volume as the default
        !          2262:        
        !          2263:        *wdcb = nil;
        !          2264:        
        !          2265:        if ( (volume->ioVolIndex <= 0) && (nameSpecified == 0) )
        !          2266:        {
        !          2267:                vRefNum = volume->ioVRefNum;
        !          2268:                if ( vRefNum > 0 )                                                              //      If driveNum, ignore it
        !          2269:                {
        !          2270:                        goto    retVRef;
        !          2271:                }
        !          2272:                else if ( vRefNum == 0 )
        !          2273:                {
        !          2274:                        vRefNum = 2;
        !          2275:                }
        !          2276:                else if ( vRefNum <= WDRfnMax )
        !          2277:                {
        !          2278:                        //      a WDRefNum was supplied as VRefNum: change the number of files to be the                <21Sep85>
        !          2279:                        //      valence of the directory in question:                                                                           <21Sep85>
        !          2280:                        vRefNum -= WDRfnMin;                                    //      Change WDRefNum to index
        !          2281:                }
        !          2282:                else
        !          2283:                {
        !          2284:                        goto retVRef;
        !          2285:                }
        !          2286:                
        !          2287:                wdcbsAry = (WDCBArray*)LMGetWDCBsPtr();                                                 //      Point to WDCB array
        !          2288:                *wdcb = (WDCBRec*)((Ptr)wdcbsAry + vRefNum);
        !          2289: 
        !          2290:                err = CheckVolumeOffLine( vcb );                        //      check external FS err
        !          2291:                if ( err == noErr )
        !          2292:                {
        !          2293:                        if ( (**wdcb).wdDirID != fsRtDirID )
        !          2294:                        {
        !          2295:                                //��    This will change to handle Don's meta struct
        !          2296:                                err = GetCatalogNode( (ExtendedVCB*)vcb, (**wdcb).wdDirID, nil, (**wdcb).wdCatHint, &spec, &catNodeData, (UInt32*)&((**wdcb).wdCatHint) );
        !          2297:                                if ( err == noErr )
        !          2298:                                {
        !          2299:                                        volume->ioVNmFls = (UInt16) catNodeData.valence;
        !          2300:                                }
        !          2301:                        }
        !          2302:                }
        !          2303:        }
        !          2304:        
        !          2305:        //      Do some hairy checking: if a working directory was specified, it shouldn't
        !          2306:        //      be overwritten by the volRefNum.        However, if a volume NAME was used, the
        !          2307:        //      volRefNum field is ignored, and SHOULD be filled in with the volume's VRefNum.
        !          2308: retVRef:
        !          2309:        if( (nameSpecified != 0) || (volume->ioVRefNum >= 0) )
        !          2310:        {
        !          2311:                volume->ioVRefNum = vcb->vcbVRefNum;
        !          2312:        }
        !          2313:        //      Copy the volume name field if specified.
        !          2314:        if ( volume->ioNamePtr != 0 )
        !          2315:                BlockMoveData( vcb->vcbVN, volume->ioNamePtr, vcb->vcbVN[0]+1 );
        !          2316: 
        !          2317: 
        !          2318:        //      Many applications call GetVolInfo for preflighting when saving files. However,
        !          2319:        //      they tend to use signed integers when calculating the volume's free space
        !          2320:        //      (vcbFreeBlks * vcbAlBlkSize).  If the free space is greater than 2 gigabytes they
        !          2321:        //      get a negative result and think there is not enough space left on the volume.
        !          2322:        //      
        !          2323:        //      To fix this problem we high water mark vcbFreeBlks and vcbNmAlBlks so that when
        !          2324:        //      multiplied by vcbAlBlkSiz the result is always less than or equal to 2GB.
        !          2325: 
        !          2326:        if ( volume->ioVAlBlkSiz > 0x8000 )                     //      Do the mock up
        !          2327:        {
        !          2328:                //      Calculate the maximum number of allocation blocks that can fit within 2 gigabytes�                                                                                      <LgVol>
        !          2329:                //      Divide 2 gig by block allocation size
        !          2330:                maxBlocks = 0x7FFFFFFF / volume->ioVAlBlkSiz;
        !          2331:                
        !          2332:                //      Clip total and free to the maximum�     
        !          2333:                if ( volume->ioVNmAlBlks > maxBlocks )
        !          2334:                {
        !          2335:                        volume->ioVNmAlBlks = maxBlocks;                //      pin the value limit
        !          2336:                        
        !          2337:                        if ( volume->ioVFrBlk > maxBlocks )
        !          2338:                        {
        !          2339:                                volume->ioVFrBlk = maxBlocks;
        !          2340:                        }
        !          2341:                }
        !          2342:        }
        !          2343:        
        !          2344:        //      Subtract the physical sizes of the extent B*-Tree and the catalog B*-Tree <21Sep85>
        !          2345:        //      from the volume size, so that the difference between the volume size and        <21Sep85>
        !          2346:        //      the free space reflects only the user's allocations:                      <21Sep85>
        !          2347:        volume->ioVNmAlBlks     -= vcb->vcbXTAlBlks;            //      Take out XT allocation
        !          2348:        volume->ioVNmAlBlks     -= vcb->vcbCTAlBlks;            //      Take out CT allocation
        !          2349:        
        !          2350:        if ( !(volume->ioTrap & kHFSMask) )             //      TFGetVolInfo vs. plain GetVolInfo?
        !          2351:        {                                                                               //      GetVolInfo
        !          2352:                if ( volume->ioVNmAlBlks > kMaxHFSAllocationBlocks )
        !          2353:                        volume->ioVNmAlBlks = kMaxHFSAllocationBlocks;
        !          2354:                
        !          2355:                if ( volume->ioVFrBlk > kMaxHFSAllocationBlocks )
        !          2356:                        volume->ioVFrBlk = kMaxHFSAllocationBlocks;
        !          2357:        }
        !          2358:        else            //      Return some additional information for TGetVolInfo requests:
        !          2359:        {
        !          2360:                volume->ioVRefNum       =       vcb->vcbVRefNum;                //      ALWAYS return VRefNum
        !          2361:                volume->ioVDrvInfo      =       vcb->vcbDrvNum;                 //      Driver number
        !          2362:                volume->ioVDRefNum      =       vcb->vcbDRefNum;                //      Driver RefNum
        !          2363:                volume->ioVFSID         =       vcb->vcbFSID;                   //      File System ID
        !          2364:                
        !          2365:                //      We return  kHFSSigWord for HFS+ volumes for copatability with
        !          2366:                //      existing applications.  All StuffIt products, AppleShare, FileSharing,
        !          2367:                //      and others incorrectly assume the volume is unsupported or MFS if the
        !          2368:                //      sigWord is not 'BD'. GetXVolInfo() returns the "real" value.
        !          2369:                volume->ioVSigWord      = vcb->vcbSigWord == kHFSPlusSigWord ? kHFSSigWord : vcb->vcbSigWord;
        !          2370:                
        !          2371:                
        !          2372: //volume->ioVFilCnt    =       0;                                      //      Clear
        !          2373: //volume->ioVFilCnt    =       vcb->vcbNmFls;          //      Stuff low word as if MFS
        !          2374:                
        !          2375:                volume->ioVBkUp         =       vcb->vcbVolBkUp;        //      Last backup date
        !          2376:                volume->ioVSeqNum       =       vcb->vcbVSeqNum;        //      Volume sequence number
        !          2377:                volume->ioVWrCnt        =       vcb->vcbWrCnt;          //      Volume write count
        !          2378:                volume->ioVFilCnt       =       vcb->vcbFilCnt;         //      Files count for volume
        !          2379:                volume->ioVDirCnt       =       vcb->vcbDirCnt;         //      Directory count for volume
        !          2380: 
        !          2381:                BlockMoveData( vcb->vcbFndrInfo, volume->ioVFndrInfo, sizeof( SInt32 ) * 8 );
        !          2382:        }
        !          2383: 
        !          2384: GVIDone:
        !          2385:        LMSetReqstVol( (Ptr)vcb );
        !          2386: 
        !          2387:        err = CheckExternalFileSystem( vcb );
        !          2388:        
        !          2389: CmdDone:
        !          2390:        return( err );
        !          2391: 
        !          2392: }
        !          2393: 
        !          2394: 
        !          2395: 
        !          2396: 
        !          2397: //_______________________________________________________________________
        !          2398: //
        !          2399: //     Routine:        GetXVolumeInformation   :       GetXVolInfo
        !          2400: //     Arguments:      XVolumeParam    *volume
        !          2401: //     Output:         WDCBRecPtr              *wdcb           (Needed for ExtFsHook in CmdDone)
        !          2402: //                             OSErr                   err
        !          2403: //
        !          2404: //     Function:       Return information about the volume in a mounted drive.
        !          2405: //                             If the IOVolIndex field is 0, the name of the default
        !          2406: //                             volume is returned; if non-zero, the name of the nth
        !          2407: //                             mounted volume is returned. The maximum length of a
        !          2408: //                             volume name is 27 bytes.  The drive number for the
        !          2409: //                             volume is also returned.
        !          2410: //_______________________________________________________________________
        !          2411: 
        !          2412: OSErr  GetXVolumeInformation( XVolumeParam *volume, WDCBRecPtr *wdcb )
        !          2413: {
        !          2414:        FSSpec                  spec;
        !          2415:        SInt16                  nameLength;
        !          2416:        SInt16                  volumeIndex;
        !          2417:        FileReference                   vRefNum;
        !          2418:        OSErr                   err;
        !          2419:        Ptr                             fcbs;
        !          2420:        FCB                             *fcb;
        !          2421:        ExtendedVCB             *vcb;
        !          2422:        unsigned char   *pathName;
        !          2423:        CatalogNodeData catNodeData;
        !          2424:        Boolean                 doneSearching;
        !          2425:        Boolean                 nameSpecified;
        !          2426:        WDCBArray               *wdcbsAry;
        !          2427:        UInt16                  fcbIndex;
        !          2428: 
        !          2429: // The Installer doesn't setup ioXVersion (radar #1666217)
        !          2430: #if 0
        !          2431:        if (volume->ioXVersion != 0)
        !          2432:                return paramErr;
        !          2433: #endif
        !          2434: 
        !          2435:        err = noErr;            //      Assume things will work
        !          2436:        
        !          2437:        volumeIndex = volume->ioVolIndex;
        !          2438:        if ( volumeIndex == 0 )
        !          2439:        {
        !          2440:                err = DeturmineVolume1( (VolumeParam*)volume, &nameLength, &nameSpecified, (ExtendedVCB **)&vcb, wdcb, &pathName );
        !          2441:                if ( err != noErr )     goto CmdDone;
        !          2442:        }
        !          2443:        else if ( volume->ioVolIndex < 0 )
        !          2444:        {
        !          2445:                err = DeturmineVolume3( (VolumeParam*)volume, &nameLength, &nameSpecified, (ExtendedVCB **)&vcb, wdcb, &pathName );
        !          2446:                if ( err != noErr )     goto CmdDone;
        !          2447:        }
        !          2448:        else
        !          2449:        {
        !          2450:                nameSpecified = false;                                          //      Never any name specified (ioNamePtr is output arg)
        !          2451:                volume->ioVRefNum = 0;
        !          2452: 
        !          2453:                for ( vcb = (ExtendedVCB*)((LMGetVCBQHdr())->qHead) ; vcb != nil ; vcb = (ExtendedVCB*)vcb->qLink )     //      search the queue of VCBs
        !          2454:                {
        !          2455:                        if ( --volumeIndex == 0 )
        !          2456:                                break;
        !          2457:                }
        !          2458:                if ( vcb == nil )
        !          2459:                {
        !          2460:                        err = nsvErr;
        !          2461:                        goto CmdDone;
        !          2462:                }
        !          2463:        }
        !          2464: 
        !          2465:        //      first copy the heart of the VCB into the parameter block
        !          2466:        volume->ioVCrDate       =       vcb->vcbCrDate;
        !          2467:        volume->ioVLsMod        =       vcb->vcbLsMod;
        !          2468:        volume->ioVAtrb         =       vcb->vcbAtrb;
        !          2469:        volume->ioVBitMap       =       vcb->vcbVBMSt;
        !          2470:        volume->ioVNmAlBlks     =       vcb->vcbNmAlBlks;                       //      16 bit value
        !          2471:        volume->ioVClpSiz       =       vcb->vcbClpSiz;
        !          2472:        volume->ioAlBlSt        =       vcb->vcbAlBlSt;
        !          2473:        volume->ioVNxtCNID      =       vcb->vcbNxtCNID;
        !          2474:        volume->ioVFrBlk        =       vcb->vcbFreeBks;
        !          2475:        volume->ioVNmFls        =       vcb->vcbNmFls;                          // don't call CountRootFiles(vcb) anymore
        !          2476: 
        !          2477:        if ( vcb->vcbFSID == 0 )        // an HFS or HFS Plus disk
        !          2478:        {
        !          2479:                volume->ioVAlBlkSiz     = vcb->blockSize;                       //      return true allocation blocks
        !          2480: 
        !          2481:                if ( vcb->nextAllocation < 0xFFFF )
        !          2482:                        volume->ioAllocPtr      =       vcb->nextAllocation;
        !          2483:                else
        !          2484:                        volume->ioAllocPtr      =       0xFFFF;
        !          2485:        }
        !          2486:        else    //      an external file system
        !          2487:        {
        !          2488:                volume->ioVAlBlkSiz     =       vcb->vcbAlBlkSiz;                       
        !          2489:                volume->ioAllocPtr      =       vcb->vcbAllocPtr;
        !          2490:        }
        !          2491: 
        !          2492: 
        !          2493:        Get1stFileControlBlock( &fcbIndex, &fcbs );
        !          2494:        doneSearching           =       false;
        !          2495: 
        !          2496:        do
        !          2497:        {
        !          2498:                fcb = GetFileControlBlock( fcbIndex );
        !          2499:                if ( fcb->fcbVPtr == vcb )                                              //      The file is currently open and on this volume
        !          2500:                {
        !          2501:                        if ( fcb->fcbFlNm >= fsUsrCNID )
        !          2502:                                break;
        !          2503:                }
        !          2504:                doneSearching = GetNextFileControlBlock( &fcbIndex, fcbs );
        !          2505:        } while ( doneSearching == false );
        !          2506:        
        !          2507:        if ( doneSearching == true )
        !          2508:                volume->ioVAtrb         &=      ~kFilesOpenMask;                //      Clear if no open files match
        !          2509:        else
        !          2510:                volume->ioVAtrb         |=      kFilesOpenMask;                 //      Set if any files are opened
        !          2511: 
        !          2512:        if ( vcb == (ExtendedVCB *) LMGetDefVCBPtr() )          //      Are we supposedly the default?
        !          2513:                volume->ioVAtrb         |=      kDefaultVolumeMask;             //      Set volume as the default
        !          2514:        else
        !          2515:                volume->ioVAtrb         &=      ~kDefaultVolumeMask;    //      Clear volume as the default
        !          2516:        
        !          2517:        
        !          2518:        *wdcb = nil;
        !          2519:        
        !          2520:        if ( (volume->ioVolIndex <= 0) && (nameSpecified == 0) )
        !          2521:        {
        !          2522:                vRefNum = volume->ioVRefNum;
        !          2523:                if ( vRefNum > 0 )                                                              //      If driveNum, ignore it
        !          2524:                {
        !          2525:                        goto    retVRef;
        !          2526:                }
        !          2527:                else if ( vRefNum == 0 )
        !          2528:                {
        !          2529:                        vRefNum = 2;
        !          2530:                }
        !          2531:                else if ( vRefNum <= WDRfnMax )
        !          2532:                {
        !          2533:                        //      a WDRefNum was supplied as VRefNum: change the number of files to be the                <21Sep85>
        !          2534:                        //      valence of the directory in question:                                                                           <21Sep85>
        !          2535:                        vRefNum -= WDRfnMin;                                            //      Change WDRefNum to index
        !          2536:                }
        !          2537:                else
        !          2538:                {
        !          2539:                        goto retVRef;
        !          2540:                }
        !          2541:                
        !          2542:                wdcbsAry = (WDCBArray*)LMGetWDCBsPtr();                 //      Point to WDCB array
        !          2543:                *wdcb = (WDCBRec*)((Ptr)wdcbsAry + vRefNum);
        !          2544: 
        !          2545:                err = CheckVolumeOffLine( (ExtendedVCB*)vcb );                  //      check external FS err
        !          2546:                if ( err == noErr )
        !          2547:                {
        !          2548:                        if ( (**wdcb).wdDirID != fsRtDirID )
        !          2549:                        {
        !          2550:                                //��    This will change to handle Don's meta struct
        !          2551:                                err = GetCatalogNode( (ExtendedVCB*)vcb, (**wdcb).wdDirID, nil, (**wdcb).wdCatHint, &spec, &catNodeData, (UInt32*)&((**wdcb).wdCatHint) );
        !          2552:                                if ( err == noErr )
        !          2553:                                {
        !          2554:                                        volume->ioVNmFls = (UInt16) catNodeData.valence;
        !          2555:                                }
        !          2556:                        }
        !          2557:                }
        !          2558:        }
        !          2559:        
        !          2560:        //      If a working directory was specified, it shouldn't be overwritten by
        !          2561:        //      the volRefNum.  However, if a volume NAME was used, the volRefNum
        !          2562:        //      field is ignored, and SHOULD be filled in with the volume's VRefNum.
        !          2563: retVRef:
        !          2564:        if( (nameSpecified != 0) || (volume->ioVRefNum >= 0) )
        !          2565:        {
        !          2566:                volume->ioVRefNum = vcb->vcbVRefNum;
        !          2567:        }
        !          2568:        //      Copy the volume name field if specified.
        !          2569:        if ( volume->ioNamePtr != 0 )
        !          2570:                BlockMoveData( vcb->vcbVN, volume->ioNamePtr, vcb->vcbVN[0]+1 );
        !          2571: 
        !          2572: 
        !          2573:        //      Calculate the total and free bytes available on the volume as a 64 bit integer:
        !          2574: 
        !          2575:        if ( vcb->vcbSigWord == kHFSPlusSigWord )
        !          2576:        {
        !          2577:                //--    Change to use ExtendedVCB fields for HFS Plus
        !          2578:                MultiplyUInt32IntoUInt64( &(volume->ioVTotalBytes), vcb->totalBlocks, vcb->blockSize );
        !          2579:                MultiplyUInt32IntoUInt64( &(volume->ioVFreeBytes), vcb->freeBlocks, vcb->blockSize );
        !          2580:        }
        !          2581:        else
        !          2582:        {
        !          2583:                //--    It's just an HFS volume or some other external file system
        !          2584:                MultiplyUInt32IntoUInt64( &(volume->ioVTotalBytes), volume->ioVNmAlBlks, volume->ioVAlBlkSiz );
        !          2585:                MultiplyUInt32IntoUInt64( &(volume->ioVFreeBytes), volume->ioVFrBlk, volume->ioVAlBlkSiz );
        !          2586:        }
        !          2587:        
        !          2588:        
        !          2589:        volume->ioVRefNum       =       vcb->vcbVRefNum;                        //      VRefNum
        !          2590:        volume->ioVSigWord      =       vcb->vcbSigWord;                        //      Volume signature
        !          2591:        volume->ioVDrvInfo      =       vcb->vcbDrvNum;                         //      Driver number
        !          2592:        volume->ioVDRefNum      =       vcb->vcbDRefNum;                        //      Driver RefNum
        !          2593:        volume->ioVFSID         =       vcb->vcbFSID;                           //      File System ID
        !          2594:        volume->ioVBkUp         =       vcb->vcbVolBkUp;                        //      Last backup date
        !          2595:        volume->ioVSeqNum       =       vcb->vcbVSeqNum;                        //      Volume sequence number
        !          2596:        volume->ioVWrCnt        =       vcb->vcbWrCnt;                          //      Volume write count
        !          2597:        volume->ioVFilCnt       =       vcb->vcbFilCnt;                         //      Files count for volume
        !          2598:        volume->ioVDirCnt       =       vcb->vcbDirCnt;                         //      Directory count for volume
        !          2599: 
        !          2600:        BlockMoveData( vcb->vcbFndrInfo, volume->ioVFndrInfo, sizeof( SInt32 ) * 8 );
        !          2601: 
        !          2602: CmdDone:
        !          2603:        if ( err == noErr && volume->ioVFSID != 0)
        !          2604:        {
        !          2605:                LMSetReqstVol((Ptr) vcb);
        !          2606:                err = extFSErr;         // not an HFS or HFS Plus volume, let others have a crack at this call...
        !          2607:        }
        !          2608: 
        !          2609:        return( err );
        !          2610: }
        !          2611: 
        !          2612: #endif /* TARGET_OS_MAC */
        !          2613: 
        !          2614: 
        !          2615: //_______________________________________________________________________
        !          2616: //
        !          2617: //     Routine:        FlushVolumeControlBlock
        !          2618: //     Arguments:      ExtendedVCB             *vcb
        !          2619: //     Output:         OSErr                   err
        !          2620: //
        !          2621: //     Function:       Flush volume information to either the VolumeHeader of the Master Directory Block
        !          2622: //_______________________________________________________________________
        !          2623: 
        !          2624: OSErr  FlushVolumeControlBlock( ExtendedVCB *vcb )
        !          2625: {
        !          2626:        OSErr                   err;
        !          2627: #if TARGET_OS_MAC
        !          2628:        HFSPlusVolumeHeader     *volumeHeader;
        !          2629:        FileReference   index;
        !          2630:        FCB                             *fcb;
        !          2631:        ExtendedFCB             *extendedFCB;
        !          2632: #endif 
        !          2633:        if ( ! IsVCBDirty( vcb ) )                      //      if it's not dirty
        !          2634:                return( noErr );
        !          2635: 
        !          2636:        if ( vcb->vcbSigWord == kHFSPlusSigWord )
        !          2637:        {
        !          2638: #if TARGET_OS_MAC
        !          2639:                err = GetBlock_glue( gbDefault, (vcb->hfsPlusIOPosOffset / 512) + kIDSectorOffset, (Ptr*)&volumeHeader, vcb->vcbVRefNum, vcb ); //      no Flags, VH is always block #0, vcb->vcbBufAdr == CacheQueueHeader
        !          2640:                #if( DEBUG_BUILD )
        !          2641:                        if ( volumeHeader->signature != vcb->vcbSigWord )
        !          2642:                                DebugStr("\p Bad VolumeHeader, signature does not match vcb" );
        !          2643:                #endif
        !          2644:                ReturnIfError( err );
        !          2645:                
        !          2646:                //      2005507, Keep the MDB creation date and VolumeHeader creation date in sync.
        !          2647:                if ( vcb->hfsPlusIOPosOffset != 0 )                                                             //      It's a wrapped HFS+ volume
        !          2648:                {
        !          2649:                        HFSMasterDirectoryBlock *mdb;
        !          2650: 
        !          2651:                        err = GetBlock_glue(    gbDefault,
        !          2652:                                                kIDSectorOffset,
        !          2653:                                                (Ptr*)&mdb,
        !          2654:                                                vcb->vcbVRefNum,
        !          2655:                                                vcb );
        !          2656:                        if ( err == noErr )
        !          2657:                        {
        !          2658:                                if ( mdb->drCrDate      != vcb->vcbCrDate )                                     //      The creation date changed
        !          2659:                                {
        !          2660:                                        mdb->drCrDate   = vcb->vcbCrDate;
        !          2661:                                        err = RelBlock_glue( (Ptr)mdb, rbWriteMask );           //      Force it to be written
        !          2662:                                }
        !          2663:                                else
        !          2664:                                {
        !          2665:                                        err = RelBlock_glue( (Ptr)mdb, rbFreeMask );            //      Just release it
        !          2666:                                }
        !          2667:                        }
        !          2668:                }
        !          2669: 
        !          2670:        //      volumeHeader->signature                 =       vcb->signature;
        !          2671:        //      volumeHeader->version                   =
        !          2672:                volumeHeader->attributes                =       vcb->vcbAtrb;                           //      VCB uses 16 bits, next 16 are for future API changes
        !          2673:                volumeHeader->lastMountedVersion=       kHFSPlusMountVersion;           //      Let others know we've mounted volume for writing
        !          2674:        //��    volumeName
        !          2675:                volumeHeader->createDate                =       vcb->vcbCrDate;                         //      NOTE: local time, not GMT!
        !          2676:                volumeHeader->modifyDate                =       LocalToUTC(vcb->vcbLsMod);
        !          2677:                volumeHeader->backupDate                =       LocalToUTC(vcb->vcbVolBkUp);
        !          2678:                volumeHeader->checkedDate               =       vcb->checkedDate;
        !          2679:                volumeHeader->fileCount                 =       vcb->vcbFilCnt;
        !          2680:                volumeHeader->folderCount               =       vcb->vcbDirCnt;
        !          2681:                volumeHeader->blockSize                 =       vcb->blockSize;
        !          2682:                volumeHeader->totalBlocks               =       vcb->totalBlocks;
        !          2683:                volumeHeader->freeBlocks                =       vcb->freeBlocks;
        !          2684:                volumeHeader->nextAllocation    =       vcb->nextAllocation;
        !          2685:                volumeHeader->rsrcClumpSize             =       vcb->vcbClpSiz;
        !          2686:                volumeHeader->dataClumpSize             =       vcb->vcbClpSiz;
        !          2687:                volumeHeader->nextCatalogID             =       vcb->vcbNxtCNID;
        !          2688:                volumeHeader->writeCount                =       vcb->vcbWrCnt;
        !          2689:                volumeHeader->encodingsBitmap   =       vcb->encodingsBitmap;
        !          2690: 
        !          2691:                //���should we use the vcb or fcb clumpSize values ????? -djb
        !          2692:                volumeHeader->allocationFile.clumpSize  = vcb->allocationsClumpSize;
        !          2693:                volumeHeader->extentsFile.clumpSize     = vcb->vcbXTClpSiz;
        !          2694:                volumeHeader->catalogFile.clumpSize     = vcb->vcbCTClpSiz;
        !          2695:                
        !          2696:                BlockMoveData( vcb->vcbFndrInfo, volumeHeader->finderInfo, sizeof(volumeHeader->finderInfo) );
        !          2697:        
        !          2698:                index = vcb->extentsRefNum;
        !          2699:                extendedFCB = GetParallelFCB( index );
        !          2700:                BlockMoveData( extendedFCB->extents, volumeHeader->extentsFile.extents, sizeof(HFSPlusExtentRecord) );
        !          2701:                fcb = GetFileControlBlock( index );
        !          2702:                volumeHeader->extentsFile.logicalSize.lo = fcb->fcbEOF;
        !          2703:                volumeHeader->extentsFile.logicalSize.hi = 0;
        !          2704:                volumeHeader->extentsFile.totalBlocks = fcb->fcbPLen / vcb->blockSize;
        !          2705:        
        !          2706:                index = vcb->catalogRefNum;
        !          2707:                extendedFCB = GetParallelFCB( index );
        !          2708:                BlockMoveData( extendedFCB->extents, volumeHeader->catalogFile.extents, sizeof(HFSPlusExtentRecord) );
        !          2709:                fcb = GetFileControlBlock( index );
        !          2710:                volumeHeader->catalogFile.logicalSize.lo = fcb->fcbPLen;
        !          2711:                volumeHeader->catalogFile.logicalSize.hi = 0;
        !          2712:                volumeHeader->catalogFile.totalBlocks = fcb->fcbPLen / vcb->blockSize;
        !          2713: 
        !          2714:                index = vcb->allocationsRefNum;
        !          2715:                extendedFCB = GetParallelFCB( index );
        !          2716:                BlockMoveData( extendedFCB->extents, volumeHeader->allocationFile.extents, sizeof(HFSPlusExtentRecord) );
        !          2717:                fcb = GetFileControlBlock( index );
        !          2718:                volumeHeader->allocationFile.logicalSize.lo = fcb->fcbPLen;
        !          2719:                volumeHeader->allocationFile.logicalSize.hi = 0;
        !          2720:                volumeHeader->allocationFile.totalBlocks = fcb->fcbPLen / vcb->blockSize;
        !          2721:        
        !          2722:                index = vcb->attributesRefNum;
        !          2723:                if (index != 0)         //      Only update fields if an attributes file existed and was open
        !          2724:                {
        !          2725:                        extendedFCB = GetParallelFCB( index );
        !          2726:                        BlockMoveData( extendedFCB->extents, volumeHeader->attributesFile.extents, sizeof(HFSPlusExtentRecord) );
        !          2727:                        fcb = GetFileControlBlock( index );
        !          2728:                        volumeHeader->attributesFile.logicalSize.lo = fcb->fcbPLen;
        !          2729:                        volumeHeader->attributesFile.logicalSize.hi = 0;
        !          2730:                        volumeHeader->attributesFile.clumpSize = fcb->fcbClmpSize;
        !          2731:                        volumeHeader->attributesFile.totalBlocks = fcb->fcbPLen / vcb->blockSize;
        !          2732:                }
        !          2733:                
        !          2734:                //--    Write the MDB out by releasing the block dirty
        !          2735:                
        !          2736:                err = RelBlock_glue( (Ptr)volumeHeader, rbWriteMask );          //      force it to be written
        !          2737:        
        !          2738:                #if( hasHFSManualEject )
        !          2739:                        // The critical volume info that needs to be maintained
        !          2740:                        // for volumes in manual-eject drives has just been flushed.
        !          2741:                        if (err == noErr)
        !          2742:                                vcb->vcbFlags &= ~vcbFlushCriticalInfoMask;
        !          2743:                #endif
        !          2744:                
        !          2745:                MarkVCBClean( vcb );
        !          2746: #else
        !          2747:                // This does now what above does also, so lets keep it all together in a single place
        !          2748:         err = C_FlushMDB( vcb );               //      Go flush the VCB info BEFORE close
        !          2749: #endif
        !          2750:        }
        !          2751:        else
        !          2752:        {
        !          2753:                // This routine doesn't really return an error!!!
        !          2754:                // So for now, we will just return noErr
        !          2755:                err = C_FlushMDB( vcb );                //      Go flush the VCB info BEFORE close
        !          2756:                return( noErr );
        !          2757:        }
        !          2758: 
        !          2759:        return( err );
        !          2760: }
        !          2761: 
        !          2762: 
        !          2763: ExtendedFCB* GetParallelFCB(FileReference fref)
        !          2764: {
        !          2765: #if TARGET_OS_MAC
        !          2766:        ParallelFCB*    pfcbArray;
        !          2767:        FSVarsRec*              fsVars;
        !          2768:        short                   index;
        !          2769: 
        !          2770:        index = fref / sizeof(FCB);
        !          2771:        
        !          2772:        fsVars = (FSVarsRec*) LMGetFSMVars();
        !          2773: 
        !          2774:        pfcbArray = (ParallelFCB*) fsVars->fcbPBuf;
        !          2775: 
        !          2776:        return &pfcbArray->extendedFCB[index];
        !          2777: #else
        !          2778:        return &VTOH(fref)->h_xfcb->fcb_extFCB;
        !          2779: #endif /* TARGET_OS_MAC */
        !          2780: }
        !          2781: 
        !          2782: 
        !          2783: //_______________________________________________________________________
        !          2784: //
        !          2785: //     Routine:        FlushAlternateVolumeControlBlock
        !          2786: //     Arguments:      ExtendedVCB             *vcb
        !          2787: //                             Boolean                 ifHFSPlus
        !          2788: //     Output:         OSErr                   err
        !          2789: //
        !          2790: //     Function:       Flush volume information to either the Alternate VolumeHeader of the 
        !          2791: //                             Alternate Master Directory Block.  Called by the BTree when the catalog
        !          2792: //                             or extent files grow.  Simply BlockMoves the original to the alternate
        !          2793: //                             location.
        !          2794: //_______________________________________________________________________
        !          2795: 
        !          2796: OSErr  FlushAlternateVolumeControlBlock( ExtendedVCB *vcb, Boolean isHFSPlus )
        !          2797: {
        !          2798:        OSErr                   err;
        !          2799:        UInt32                  alternateBlockLocation;
        !          2800: 
        !          2801:        err = FlushVolumeControlBlock( vcb );
        !          2802:        
        !          2803:        if ( isHFSPlus )                                                                                                                        //      Flush the VolumeHeader
        !          2804:        {
        !          2805:                HFSPlusVolumeHeader     *volumeHeader;
        !          2806:                HFSPlusVolumeHeader     *alternateVolumeHeader;
        !          2807: 
        !          2808:                //--    Get the VolumeHeader Block, 1st block in the HFS Plus partition
        !          2809: #if TARGET_OS_MAC
        !          2810:                err = GetBlock_glue( gbDefault, (vcb->hfsPlusIOPosOffset / 512) + kIDSectorOffset, (Ptr*)&volumeHeader, vcb->vcbVRefNum, vcb ); //      VH is always 1st sector of HFS Plus partition
        !          2811: #else
        !          2812:                 err = GetBlock_glue( gbDefault, (vcb->hfsPlusIOPosOffset / 512) + kIDSectorOffset, (Ptr*)&volumeHeader, kNoFileReference, vcb );       //      VH is always 1st sector of HFS Plus partition
        !          2813: #endif
        !          2814:                ReturnIfError( err );
        !          2815:                
        !          2816:                //--    Get the Alternate VolumeHeader Block, last sector in the HFS Plus partition
        !          2817:                alternateBlockLocation = (vcb->hfsPlusIOPosOffset / 512) + vcb->totalBlocks * (vcb->blockSize / 512) - 2;
        !          2818: #if TARGET_OS_MAC
        !          2819:                err = GetBlock_glue( gbDefault, alternateBlockLocation, (Ptr*)&alternateVolumeHeader, vcb->vcbVRefNum, vcb );   //      Alt VH is always 2nd to last sector of HFS Plus partition
        !          2820: #else
        !          2821:                 err = GetBlock_glue( gbDefault, alternateBlockLocation, (Ptr*)&alternateVolumeHeader, kNoFileReference, vcb ); //      Alt VH is always 2nd to last sector of HFS Plus partition
        !          2822: #endif
        !          2823:                if ( err == noErr )
        !          2824:                {
        !          2825:                        //--    Copy the VolumeHeader to the alternate location
        !          2826:                        BlockMoveData( volumeHeader, alternateVolumeHeader, sizeof(HFSPlusVolumeHeader) );
        !          2827:        
        !          2828:                        //--    And write it back to the disk, NOW!
        !          2829:                        err = RelBlock_glue( (Ptr)volumeHeader, rbFreeMask );                           //      free the MDB
        !          2830:                        err = RelBlock_glue( (Ptr)alternateVolumeHeader, rbWriteMask );         //      force it to be written
        !          2831:                }
        !          2832:                else
        !          2833:                {                       
        !          2834:                        err = RelBlock_glue( (Ptr)volumeHeader, rbFreeMask );                           //      free the VH
        !          2835:                }
        !          2836:        }
        !          2837:        else                                                                                                                                            //      Flush the MasterDirectoryBlock
        !          2838:        {
        !          2839:                HFSMasterDirectoryBlock *mdb;
        !          2840:                HFSMasterDirectoryBlock *alternateMDB;
        !          2841:                UInt32                                  numBlocks;
        !          2842: 
        !          2843:                
        !          2844:                err = GetDiskBlocks( vcb, &numBlocks );
        !          2845:                ReturnIfError( err );
        !          2846: 
        !          2847:                //--    Get the MDB, 2nd block on HFS disk
        !          2848: #if TARGET_OS_MAC
        !          2849:                err = GetBlock_glue( gbDefault, kIDSectorOffset, (Ptr*)&mdb, vcb->vcbVRefNum, vcb );    //      no Flags, MDB is always block
        !          2850: #else
        !          2851:                 err = GetBlock_glue( gbDefault, kIDSectorOffset, (Ptr*)&mdb, kNoFileReference, vcb );  //      no Flags, MDB is always block
        !          2852: #endif
        !          2853:                ReturnIfError( err );
        !          2854: 
        !          2855:                //--    Get the Alternate MDB, 2nd to last block on disk
        !          2856:                alternateBlockLocation = numBlocks - 2;
        !          2857: #if TARGET_OS_MAC
        !          2858:                err = GetBlock_glue( gbDefault, alternateBlockLocation, (Ptr*)&alternateMDB, vcb->vcbVRefNum, vcb );    //      no Flags, VH is always block #0, vcb->vcbBufAdr == CacheQueueHeader
        !          2859: #else
        !          2860:                 err = GetBlock_glue( gbDefault, alternateBlockLocation, (Ptr*)&alternateMDB, kNoFileReference, vcb );  //      no Flags, VH is always block #0, vcb->vcbBufAdr == CacheQueueHeader
        !          2861: #endif
        !          2862:                if ( err == noErr )
        !          2863:                {
        !          2864:                        //--    Copy the MDB to the alternate location
        !          2865:                        BlockMoveData( mdb, alternateMDB, sizeof(HFSMasterDirectoryBlock) );
        !          2866:                        
        !          2867:                        //--    And write it back to the disk, NOW!
        !          2868:                        err = RelBlock_glue( (Ptr)mdb, rbFreeMask );                                            //      free the MDB
        !          2869:                        err = RelBlock_glue( (Ptr)alternateMDB, rbWriteMask );                          //      force it to be written
        !          2870:                }
        !          2871:                else
        !          2872:                {
        !          2873:                        err = RelBlock_glue( (Ptr)mdb, rbFreeMask );                                            //      free the MDB
        !          2874:                }
        !          2875:        }
        !          2876: 
        !          2877:        return( err );
        !          2878: }
        !          2879: 
        !          2880: 
        !          2881: 
        !          2882: //_______________________________________________________________________
        !          2883: //
        !          2884: //     Routine:        TrashAllFSCaches
        !          2885: //     Arguments:      ExtendedVCB             *vcb
        !          2886: //     Output:         OSErr                   err
        !          2887: //
        !          2888: //     Function:       Trash all file system related caches as well as the disk cache.
        !          2889: //                             This allows applications such as Disk First Aid or Norton Utilities
        !          2890: //                             to be able to repair disks without first unmounting the volume.
        !          2891: //                             
        !          2892: //                             All file system caches should also have a call to the cache
        !          2893: //                             trashing routine here!
        !          2894: //_______________________________________________________________________
        !          2895: #if TARGET_OS_MAC
        !          2896: OSErr  TrashAllFSCaches( ExtendedVCB *vcb )
        !          2897: {
        !          2898:        OSErr                   err;
        !          2899:        FSVarsRec*              fsVars  = (FSVarsRec*) LMGetFSMVars();
        !          2900:        
        !          2901:        InvalidateCatalogCache( vcb );                          //      Calls TrashCatalogIterator 
        !          2902:        TrashCatalogNodeCache( );                                       //      Trash Catalog node cache, gCatalogFSSpec
        !          2903:        err = TrashCacheBlocks( 0 );                            //      Trash BTree node cache
        !          2904:        TrashMRUCache( vcb->hintCachePtr );                     //      Trash the heuristic hint cache
        !          2905:        ClearMemory( fsVars->gAttributesBuffer, fsVars->gAttributesBufferSize );        //      Clear the buffer used by MountCheck and CatSearch
        !          2906:        TrashVolumeDiskCache( vcb );                            //      Trash the disk cache, calls TRASHVBLKSA7
        !          2907:        
        !          2908:        return( err );
        !          2909: }
        !          2910: #endif /* TARGET_OS_MAC */
        !          2911: 
        !          2912: 
        !          2913: #if TARGET_OS_MAC
        !          2914: OSErr GetDiskBlocks( ExtendedVCB *vcb, unsigned long *numBlocks)
        !          2915: {
        !          2916:        /* Various constants for GetDiskBlocks() */
        !          2917:        enum
        !          2918:        {
        !          2919:                /* return format list status code */
        !          2920:                kFmtLstCode = 6,
        !          2921:                
        !          2922:                /* reference number of .SONY driver */
        !          2923:                kSonyRefNum = 0xfffb,
        !          2924:                
        !          2925:                /* values returned by DriveStatus in DrvSts.twoSideFmt */
        !          2926:                kSingleSided = 0,
        !          2927:                kDoubleSided = -1,
        !          2928:                kSingleSidedSize = 800,         /* 400K */
        !          2929:                kDoubleSidedSize = 1600,        /* 800K */
        !          2930:                
        !          2931:                /* values in DrvQEl.qType */
        !          2932:                kWordDrvSiz = 0,
        !          2933:                kLongDrvSiz = 1,
        !          2934:                
        !          2935:                /* more than enough formatListRecords */
        !          2936:                kMaxFormatListRecs = 16
        !          2937:        };
        !          2938:        
        !          2939:        DrvQEl                  *driveQElementPtr;
        !          2940:        unsigned long   blocks;
        !          2941:        ParamBlockRec   pb;
        !          2942:        DrvSts                  status;
        !          2943:        FormatListRec   formatListRecords[kMaxFormatListRecs];
        !          2944:        short                   formatListRecIndex;
        !          2945:        OSErr                   err;
        !          2946:        short                   driverRefNum;
        !          2947: 
        !          2948:        blocks = 0;
        !          2949:        
        !          2950:        //      Find the drive queue element for this volume
        !          2951:        err = FindDrive( &driverRefNum, &driveQElementPtr, vcb->vcbDrvNum );
        !          2952:        ReturnIfError( err );
        !          2953:        
        !          2954:        //      Make sure this is a real driver (dQRefNum < 0).
        !          2955:        //      AOCE's Mail Enclosures volume uses 0 for dQRefNum which will cause
        !          2956:        //      problems if you try to use it as a driver refNum.
        !          2957: 
        !          2958:        if ( driveQElementPtr->dQRefNum >= 0 )
        !          2959:        {
        !          2960:                err = paramErr;
        !          2961:        }
        !          2962:        else
        !          2963:        {
        !          2964:                //      Attempt to get the drive's format list.
        !          2965:                //      (see the Technical Note "What Your Sony Drives For You")
        !          2966:                
        !          2967:                pb.cntrlParam.ioVRefNum = driveQElementPtr->dQDrive;
        !          2968:                pb.cntrlParam.ioCRefNum = driveQElementPtr->dQRefNum;
        !          2969:                pb.cntrlParam.csCode = kFmtLstCode;
        !          2970:                pb.cntrlParam.csParam[0] = kMaxFormatListRecs;
        !          2971:                *(long *)&pb.cntrlParam.csParam[1] = (long)&formatListRecords[0];
        !          2972:                
        !          2973:                err = PBStatusSync(&pb);
        !          2974:                
        !          2975:                if ( err == noErr )
        !          2976:                {
        !          2977:                        //      The drive supports ReturnFormatList status call.
        !          2978:                        
        !          2979:                        //      Get the current disk's size.
        !          2980:                        for( formatListRecIndex = 0;
        !          2981:                                 formatListRecIndex < pb.cntrlParam.csParam[0];
        !          2982:                         ++formatListRecIndex )
        !          2983:                {
        !          2984:                        if ( (formatListRecords[formatListRecIndex].formatFlags &
        !          2985:                                  diCIFmtFlagsCurrentMask) != 0 )
        !          2986:                        {
        !          2987:                                blocks = formatListRecords[formatListRecIndex].volSize;
        !          2988:                        }
        !          2989:                        }
        !          2990:                if ( blocks == 0 )
        !          2991:                {
        !          2992:                        //      This should never happen
        !          2993:                        err = paramErr;
        !          2994:                }
        !          2995:                }
        !          2996:                else if ( driveQElementPtr->dQRefNum == (short)kSonyRefNum )
        !          2997:                {
        !          2998:                        //      The drive is a non-SuperDrive floppy which only supports 400K and 800K disks
        !          2999:                        
        !          3000:                        err = DriveStatus(driveQElementPtr->dQDrive, &status);
        !          3001:                        if ( err == noErr )
        !          3002:                        {
        !          3003:                                switch ( status.twoSideFmt )
        !          3004:                                {
        !          3005:                                case kSingleSided:
        !          3006:                                        blocks = kSingleSidedSize;
        !          3007:                                        break;
        !          3008:                                case kDoubleSided:
        !          3009:                                        blocks = kDoubleSidedSize;
        !          3010:                                        break;
        !          3011:                                default:
        !          3012:                                        //      This should never happen
        !          3013:                                        err = paramErr;
        !          3014:                                        break;
        !          3015:                                }
        !          3016:                        }
        !          3017:                }
        !          3018:                else
        !          3019:                {
        !          3020:                        //      The drive is not a floppy and it doesn't support ReturnFormatList
        !          3021:                        //      so use the dQDrvSz field(s)
        !          3022:                        
        !          3023:                        err = noErr;                    //      reset err
        !          3024:                        switch ( driveQElementPtr->qType )
        !          3025:                        {
        !          3026:                        case kWordDrvSiz:
        !          3027:                                blocks = driveQElementPtr->dQDrvSz;
        !          3028:                                break;
        !          3029:                        case kLongDrvSiz:
        !          3030:                                blocks = ((unsigned long)driveQElementPtr->dQDrvSz2 << 16) +
        !          3031:                                                 driveQElementPtr->dQDrvSz;
        !          3032:                                break;
        !          3033:                        default:
        !          3034:                                //      This should never happen
        !          3035:                                err = paramErr;
        !          3036:                                break;
        !          3037:                        }
        !          3038:                }
        !          3039:        }
        !          3040:        
        !          3041:        *numBlocks = blocks;
        !          3042:        
        !          3043:        return ( err );
        !          3044: }
        !          3045: #endif         /* TARGET_OS_MAC */
        !          3046: 
        !          3047: 
        !          3048: //
        !          3049: //     Sets up a VCB for calls to GetBlock()
        !          3050: //
        !          3051: void   AddVCB( ExtendedVCB     *vcb, short driveNumber, short ioRefNum )
        !          3052: {
        !          3053: #if TARGET_OS_MAC
        !          3054:        OSErr                   err                     = noErr;
        !          3055:        WDCBArray               *wdcbsAry;
        !          3056:        QHdr                    *vcbQHdr;
        !          3057:        WDCBRecPtr              wdcb;
        !          3058:                        
        !          3059:        vcbQHdr = LMGetVCBQHdr();
        !          3060:        if ( vcbQHdr->qHead == nil )
        !          3061:        {                                                                                                                                       //       Queue is empty, new vcb is the default now
        !          3062:                LMSetDefVCBPtr( (Ptr) vcb );
        !          3063:                wdcbsAry = (WDCBArray*)LMGetWDCBsPtr();                                                 //      Point to WDCB array
        !          3064:                
        !          3065:                wdcb = &(wdcbsAry->wdcb[0]);
        !          3066:                wdcb->wdVCBPtr  = (VCB *) vcb;                                                                  //      Set default VCB pointer in default WDCB
        !          3067:                wdcb->wdDirID   = fsRtDirID;                                                                    //      Default to root directory
        !          3068:                wdcb->wdCatHint = 0;                                                                                    //      Clear catalog hint
        !          3069:                wdcb->wdProcID  = 0;                                                                                    //      And procID of WDCB 'owner'
        !          3070:                vcbQHdr = LMGetVCBQHdr();                                                                               //      Reset for VCB insertion
        !          3071:        }
        !          3072:        
        !          3073: 
        !          3074:        Enqueue( (QElemPtr)vcb, (QHdrPtr)vcbQHdr );                                                     //      Insert the new VCB in the queue
        !          3075: 
        !          3076:        vcb->vcbDrvNum  = driveNumber;
        !          3077:        vcb->vcbDRefNum = ioRefNum;
        !          3078:        
        !          3079:        #if ( hasHFSManualEject )
        !          3080:                SetVCBManEject(vcb);                                                                                    //      set vcb maneject flag appropriately     <SM7> <BH 03Aug93>
        !          3081:        #endif
        !          3082: 
        !          3083: 
        !          3084:        vcb->vcbBufAdr = LMGetSysVolCPtr();                                                                     //      always use system-wide cache �
        !          3085: 
        !          3086:        vcb->vcbVRefNum = GetNewVRefNum();                                                                      //      Assign a refNum to this new volume.
        !          3087: 
        !          3088:        if ( vcb == (ExtendedVCB *) LMGetDefVCBPtr() )                                          //      Are we supposedly the default?
        !          3089:        {
        !          3090:                LMSetDefVRefNum( vcb->vcbVRefNum );
        !          3091:        }
        !          3092: #else
        !          3093: #pragma unused(vcb,driveNumber,ioRefNum,wdcbH)
        !          3094: #endif         /* TARGET_OS_MAC */
        !          3095: }
        !          3096: 
        !          3097: 
        !          3098: //--------------------------------------------------------------------------------------
        !          3099: //     Routine:        SetVCBManEject
        !          3100: //     Input:          VCB ptr
        !          3101: //     Called by:      MountVol
        !          3102: //     Function:       Sets or clears the manual-eject bit in the flags word of the input VCB
        !          3103: //                             based on the type of the drive indicated by vcbDrvNum.  All registers
        !          3104: //                             are preserved.  The manual-eject flag should only be changed at MountVol
        !          3105: //                             time.
        !          3106: //--------------------------------------------------------------------------------------
        !          3107: 
        !          3108: #if ( hasHFSManualEject )
        !          3109: 
        !          3110:        static void SetVCBManEject(ExtendedVCB *vcb)
        !          3111:        {
        !          3112:                DrvQEl  *driveQElementPtr;
        !          3113:                DrvSts  *driveStatsPtr;
        !          3114:                short   driverRefNum;
        !          3115:                OSErr   err;
        !          3116:        
        !          3117:                //      Find the drive queue element for this volume
        !          3118:                err = FindDrive( &driverRefNum, &driveQElementPtr, vcb->vcbDrvNum );
        !          3119:                
        !          3120:                if (err) return;
        !          3121:                
        !          3122:                driveStatsPtr = (DrvSts*) ((Ptr) driveQElementPtr - offsetof(DrvSts, qLink));
        !          3123:        
        !          3124:                if ( driveStatsPtr->installed & (1 << kdqManualEjectBit) )              // manual eject drive asserted?
        !          3125:                        vcb->vcbFlags |= vcbManualEjectMask;
        !          3126:                else
        !          3127:                        vcb->vcbFlags &= ~vcbManualEjectMask;
        !          3128:        }
        !          3129: 
        !          3130: #endif
        !          3131: 
        !          3132: 
        !          3133: //
        !          3134: //     Simple utility function to deturmine if a keyboard key is pressed.
        !          3135: //
        !          3136: short IsPressed( UInt16 k )            // k =  any keyboard scan code, 0-127
        !          3137: {
        !          3138: #if TARGET_OS_MAC
        !          3139:        unsigned char   km[16];
        !          3140: 
        !          3141:        GetKeys( *( (KeyMap*) &km ) );                                                                          //      Ugly casting to compile with MPWC & SC
        !          3142:        return ( ( km[k>>3] >> (k & 7) ) & 1);
        !          3143: #else
        !          3144: #pragma unused(k)
        !          3145:        return( 0 );
        !          3146: #endif         /* TARGET_OS_MAC */
        !          3147: }
        !          3148: 
        !          3149: 
        !          3150: #if TARGET_OS_MAC
        !          3151: //
        !          3152: //     Utility function to allocate a new vRefNum. 
        !          3153: //     This function cycles through all vRefNums, rather than reuse them.
        !          3154: //
        !          3155: FileReference  GetNewVRefNum()
        !          3156: {
        !          3157:        FileReference           refNum;
        !          3158:        ExtendedVCB     *tempVCB;
        !          3159:        OSErr           err                     = noErr;
        !          3160: 
        !          3161:        #if (0)         //      See bug 1664445
        !          3162:        {
        !          3163:                FSVarsRec       *fsVars;
        !          3164:        
        !          3165:        fsVars = (FSVarsRec*)LMGetFSMVars();
        !          3166:        for ( refNum = fsVars->nextVRefNum ; err == noErr ; refNum-- )
        !          3167:        {
        !          3168:                if ( refNum >= 0x8001 )                                                                                 //      if we've cycled through all the possible vRef nums, start over
        !          3169:                        refNum = -1;
        !          3170:                        
        !          3171:                err = GetVCBRefNum( &tempVCB, refNum );                                                 //      Check if already assigned
        !          3172:        }
        !          3173:        
        !          3174:        fsVars->nextVRefNum     = refNum;
        !          3175:        return( ++refNum );                                                                                                     //      for loop post decrements
        !          3176:        }
        !          3177:        #else
        !          3178:        {
        !          3179:                for ( refNum = -1 ; err == noErr ; refNum-- )
        !          3180:                {
        !          3181:                        err = GetVCBRefNum( &tempVCB, refNum );                                                 //      Check if already assigned
        !          3182:                }
        !          3183:                return( ++refNum );                                                                                                     //      for loop post decrements
        !          3184:        }
        !          3185:        #endif
        !          3186: }
        !          3187: #endif /* TARGET_OS_MAC */
        !          3188: 
        !          3189: //�������������������������������������������������������������������������������
        !          3190: 
        !          3191: OSErr GetVolumeNameFromCatalog( ExtendedVCB *vcb )
        !          3192: {
        !          3193:        FSSpec                  spec;
        !          3194:        CatalogNodeData nodeData;
        !          3195:        UInt32                  hint;
        !          3196:        OSErr                   err;
        !          3197: #if TARGET_OS_MAC
        !          3198:        FSVarsRec               *fsVars;
        !          3199: 
        !          3200:        fsVars = (FSVarsRec*) LMGetFSMVars();
        !          3201:        if ( fsVars->gIsUnicodeInstalled )
        !          3202: #else
        !          3203:        if ( true )
        !          3204: #endif /*TARGET_OS_MAC */
        !          3205:        {
        !          3206:                err = GetCatalogNode( vcb, kHFSRootFolderID, NULL, kNoHint, &spec, &nodeData, &hint );
        !          3207:        
        !          3208:                if ( err == noErr )
        !          3209:                {
        !          3210: #if TARGET_OS_MAC
        !          3211:                        BlockMoveData( spec.name, vcb->vcbVN, sizeof(Str27) );
        !          3212: #else
        !          3213:                        vcb->vcbVN[0] = strlen(spec.name);
        !          3214:                        BlockMoveData( spec.name, &vcb->vcbVN[1], sizeof(Str27)-1 );
        !          3215: #endif
        !          3216:                        vcb->volumeNameEncodingHint = nodeData.textEncoding;            // save encoding for FSFindTextEncodingForVolume
        !          3217:                }
        !          3218:        }
        !          3219:        else
        !          3220:        {
        !          3221:                err = paramErr;
        !          3222:        }
        !          3223:                
        !          3224:        return err;
        !          3225: }
        !          3226: 

unix.superglobalmegacorp.com

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