|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.