|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: File: VolumeRequests.c
24:
25: Contains: MountVolume and related utility routines for HFS & HFS Plus
26:
27: Version: HFS Plus 1.0
28:
29: Written by: Deric Horn
30:
31: Copyright: � 1996-1998 by Apple Computer, Inc., all rights reserved.
32:
33: File Ownership:
34:
35: DRI: Deric Horn
36:
37: Other Contacts: Mark Day, Don Brady
38:
39: Technology: File Systems
40:
41: Writers:
42:
43: (JL) Jim Luther
44: (msd) Mark Day
45: (DSH) Deric Horn
46: (djb) Don Brady
47:
48: Change History (most recent first):
49: <MacOSX> 7/28/98 djb GetDiskBlocks is now implemented in MacOSStubs.c (radar #2258148).
50: <MacOSX> 4/3/98 djb Conditionally remove FSVars reference from GetVolumeNameFromCatalog.
51: <MacOSX> 3/31/98 djb Sync up with final HFSVolumes.h header file.
52: <CS47> 1/29/98 DSH TrashAllFSCaches is responsible for trashing all file system and
53: disk caches. Called from FlushVol when the HFS bit is set.
54: <CS46> 12/12/97 DSH 2003877, when vcbAllocPtr was copied to nextAllocation it was
55: getting sign extended.
56: <CS45> 11/26/97 DSH 2003459, fcbs was not being initialized if volume was offline
57: and we are executing an unconditional unmount.
58: <CS44> 11/24/97 DSH 2005507, FlushVolumeControlBlock() keeps MDB drCrDate in sync
59: with VolumeHeader createDate.
60: <CS43> 11/11/97 DSH 1685873, RemountWrappedVolumes was only remounting the first
61: HFS+ volume in the queue, causing HFS wrappers to be mounted if
62: multiple volumes had been mounted before InitHFSPlus.
63: <CS42> 11/4/97 DSH Clear FCB when getting a new one.
64: <CS41> 11/3/97 JL #2001483 - Removed unneeded parameters from MountVolume,
65: MountHFSVolume, MountHFSPlusVolume, GetVolumeInformation,
66: GetXVolumeInformation and AddVCB (and added local variables as
67: needed). Return WDCBRecPtr from UnMountVolume. Set wdcb
68: parameter to NULL in GetXVolumeInformation if working directory
69: was not specified.
70: <CS40> 10/31/97 DSH Added consistencyStatus parameter to MountCheck
71: <CS39> 10/23/97 msd Bug 1685113. The VolumeHeader's createDate should be in local
72: time (not GMT) and identical to the MDB's drCrDate (and VCB's
73: vcbCrDate). When checking for a remount of an offline HFS Plus
74: volume, compare write counts instead of mod dates (which could
75: be fooled by the user changing time zones). Force MountCheck to
76: run if the volume was last mounted by Bride 1.0b2 or earlier.
77: <CS38> 10/17/97 msd Conditionalize DebugStrs.
78: <CS37> 10/13/97 djb Update volumeNameEncodingHint when updating the volume name.
79: <CS36> 10/10/97 msd Bug 1683571. The dates in the volume header are in GMT, so be
80: sure to convert them when mounting a volume or flushing the
81: volume header.
82: <CS35> 10/2/97 DSH In UnmountVolume() check that the drive is on line before
83: determining if wrapper volume needs to be renamed causing IO.
84: <CS34> 10/1/97 DSH Run on disk version of MountCheck instead of ROM version for
85: boot volumes1682475.
86: <CS33> 10/1/97 djb Add calls to InvalidateCatalogCache (part of radar #1678833).
87: <CS32> 9/26/97 DSH Removed debugging code: support for 'W' key wrapper mounting.
88: <CS31> 9/17/97 DSH hfsPlusIOPosOffset was uninitialized for Wrapperless volumes.
89: <CS30> 9/5/97 djb In MountVol initialize Catalog cache before calling Catalog!
90: <CS29> 9/4/97 msd PropertyCloseVolume renamed to AttributesCloseVolume. Remove
91: call to AttributesOpenVolume (it no longer exists).
92: <CS28> 9/2/97 DSH VolumeHeader is now 3rd sector in partition, altVH is 2nd to
93: last cor compatability. Initial support for wrapperless
94: volumes.
95: <CS27> 8/26/97 djb Only call CountRootFiles during MountVol.
96: <CS26> 8/20/97 msd If the HFS Plus volume version doesn't match, mount the wrapper
97: instead.
98: <CS25> 8/19/97 djb Add error handling to RenameWrapperVolume.
99: <CS24> 8/15/97 msd Bug 1673999. In MakeVCBsExtendedVCBs, copy old VCB's vcbAllocPtr
100: to new VCB's nextAllocation field.
101: <CS23> 8/12/97 djb Fixed GetXVolInfo to only use extended vcb fields for local
102: volumes (radar# 1673177)
103: <CS22> 8/11/97 DSH vcbNmAlBlks is now taken from the embededExtent.blockCount
104: (1669121).
105: <CS21> 8/11/97 djb Return actual count of files in root directory for HFS Plus
106: volumes (Radar #1669118). Added local CountRootFiles routine.
107: 8/5/97 msd Make sure version field in VolumeHeader is exactly
108: kHFSPlusVersion. 8/1/97 djb GetXVolumeInformation now returns
109: extFSErr when FSID is nonzero (Radar #1649503).
110: <CS20> 7/25/97 DSH Init and Dispose of GenericMRUCache within ExtendedVCB.
111: <CS19> 7/16/97 DSH FilesInternal.x -> FileMgrInternal.x to avoid name collision
112: <CS18> 7/15/97 DSH Remount Wrapper volumes mounted before HFS+ initialization
113: (166729)
114: <CS17> 7/15/97 djb Remove ioXVersion checking in GetXVolInfo (radar #1666217).
115: <CS16> 7/8/97 DSH Loading PrecompiledHeaders from define passed in on C line
116: <CS15> 7/7/97 djb Add GetVolumeNameFromCatalog routine.
117: <CS14> 7/7/97 DSH GetNewVRefNum now get's a recycled vRefNum. Bug 1664445 in
118: Installer was cacheing the vRefNum while CheckDisk unmounts and
119: remounts disk.
120: <CS13> 6/30/97 DSH shadowing values obsoleteVCBXTRef, and obsoleteVCBCTRef when
121: HFS+ volume is mounted.
122: <CS12> 6/26/97 DSH GetVolInfo returns HFS signature for HFS+ volumes, GetXVolInfo
123: returns real signature.
124: <CS11> 6/24/97 DSH MakeVCBsExtendedVCBs was using wdcb->count as count not byte
125: count.
126: <CS10> 6/18/97 djb Set/get volume encodingsBitmap.
127: <CS9> 6/16/97 msd Include String.h and Disks.h.
128: <CS8> 6/12/97 djb Get in sync with HFS Plus format changes.
129: <CS7> 6/11/97 msd Make GetXVolumeInformation return true allocation block size. It
130: now checks the ioXVersion field.
131: <CS6> 5/28/97 msd When flushing the volume header, write out the allocation file's
132: clump size (from the FCB). When mounting an HFS Plus volume,
133: zero the entire FCB extent record, not just the first extent,
134: for the various volume control files.
135: <CS5> 5/19/97 djb Add calls to CreateVolumeCatalogCache,
136: DisposeVolumeCatalogCache.
137: <CS4> 5/9/97 djb Get in sync with new FilesInternal.i
138: <CS3> 5/8/97 DSH Only mount HFS+ volumes with version < 2.0 in the VolumeHeader.
139: Return wrgVolTypErr if too new.
140: <CS2> 5/2/97 djb Disable Manual Eject code since its buggy!
141: <CS1> 4/25/97 djb first checked in
142:
143: <HFS32> 4/11/97 DSH MountHFSPlusVolume gets volume name from catalog, and
144: UnmountVolume shadows the name back to the wrapper partition.
145: <HFS31> 4/8/97 msd Once volume is mounted, call AttributesOpenVolume to allow a
146: buffer to be allocated.
147: <HFS30> 4/7/97 msd In FlushVolumeControlBlock, don't update the attributes BTree
148: fields in the Volume Header unless an attributes BTree was
149: already open.
150: <HFS29> 4/7/97 msd In SetupFCB, add case for attributes BTree. Add code to set up
151: the attributes BTree. Remove call to PropertyOpenVolume. In
152: FlushVolumeControlBlock, write out any changes to the attributes
153: BTree.
154: <HFS28> 4/4/97 djb Get in sync with volume format changes.
155: <HFS27> 3/31/97 djb Added catalogDataCache to VCB; Remove ClearMem routine.
156: <HFS26> 3/18/97 msd In MountHFSPlusVolume, the free blocks calculation can overflow,
157: setting vcbFreeBks to a too-small value.
158: <HFS25> 3/17/97 DSH Added some utility functions AddVCB, GetParallelFCBFromRefNum,
159: casting for SC, and made some functions extern for DFA.
160: <HFS24> 3/5/97 msd Add calls to Property Manager to open and close the volume. When
161: unmounting an HFS+ volume, the allocation (bitmap) file now gets
162: closed.
163: <HFS23> 2/19/97 djb Update to 16-bit HFS Plus signature.
164: <HFS22> 2/12/97 msd In GetXVolumeInformation, the result code could be
165: uninitialized.
166: <HFS21> 1/23/97 DSH UpdateAlternateVoumeControlBlock()
167: <HFS20> 1/15/97 djb Remove MountCheckStub. Add file names to fcbs for debugging.
168: <HFS19> 1/13/97 DSH Use ExtendedVCB nextAllocation instead of vcbAllocPtr through
169: all code.
170: <HFS18> 1/9/97 djb Get in sync with new VolumeHeader and Extended VCB.
171: <HFS17> 1/6/97 djb Changed API to ParallelFCBFromRefnum (pragma parameter was
172: broken).
173: <HFS16> 1/6/97 msd Set only the defined bits in the MDB drAtrb field (when copying
174: from VCB vcbAtrb field).
175: <HFS15> 1/6/97 DSH CloseFile requires VCB to be passed in.
176: <HFS14> 1/6/97 djb FlushVolumeControlBlock was writing to absolute block 0 instead
177: of to block zero of the embedded volume.
178: <HFS13> 12/20/96 msd A comparison was using "=" instead of "=="; might have caused
179: the wrong volume to be set as the default.
180: <HFS12> 12/19/96 DSH Setting up ExtendedVCBs
181: <HFS11> 12/19/96 djb Updated for new B-tree Manager interface.
182: <HFS10> 12/18/96 msd Change GetVCBRefNum so it can actually return a VCB pointer.
183: <HFS9> 12/12/96 djb Use new SPI for GetCatalogNode.
184: <HFS8> 12/12/96 msd Fix a bunch of errors (mostly type mismatch) when compiling with
185: Metrowerks.
186: <HFS7> 12/12/96 DSH adding some util functions
187: <HFS6> 12/10/96 msd Check PRAGMA_LOAD_SUPPORTED before loading precompiled headers.
188: <HFS5> 12/4/96 DSH Ported GetVolumeInformation & GetXVolumeInformation.
189: <3*> 11/20/96 DSH HFS Plus support to MountVolume
190: <HFS3> 11/20/96 DSH Added UnmountVol and related routines, also backed out <2>
191: because C_FXMKeyCmp is passed as a parameter from C but called
192: from Asm in BTOpen so we need a Case ON Asm entry point.
193: <HFS2> 11/20/96 msd Use CompareExtentKeys() instead of CFXMKeyCmp().
194: <HFS1> 11/19/96 DSH first checked in
195: <1> 11/19/96 DSH first checked in
196:
197: */
198: #include <sys/param.h>
199: #include <sys/systm.h>
200: #include <sys/kernel.h>
201: #include <sys/vnode.h>
202:
203: #include "../../hfs.h"
204:
205: #include "../headers/FileMgrInternal.h"
206:
207: #define kIDSectorOffset 2
208:
209: OSErr GetNewFCB( ExtendedVCB *vcb, FileReference* fRefPtr);
210:
211: OSErr AccessBTree( ExtendedVCB *vcb, FileReference refNum, UInt32 fileID, UInt32 fileClumpSize, void *CompareRoutine );
212:
213: UInt16 DivUp( UInt32 byteRun, UInt32 blockSize );
214:
215: Boolean IsARamDiskDriver( void );
216:
217: OSErr GetVCBRefNum( ExtendedVCB **vcb, short vRefNum );
218:
219: OSErr ValidMasterDirectoryBlock( HFSMasterDirectoryBlock *mdb );
220:
221: void RenameWrapperVolume( Str27 newVolumeName, UInt16 driveNumber );
222:
223: OSErr CheckExternalFileSystem( ExtendedVCB *vcb );
224:
225: OSErr FlushVolume( ExtendedVCB *vcb );
226:
227: FCB *SetupFCB( ExtendedVCB *vcb, FileReference refNum, UInt32 fileID, UInt32 fileClumpSize );
228:
229: void AddVCB( ExtendedVCB *vcb, short driveNumber, short ioDRefNum );
230:
231: short IsPressed( unsigned short k );
232:
233: FileReference GetNewVRefNum();
234:
235: OSErr GetVolumeNameFromCatalog(ExtendedVCB *vcb);
236:
237: #if TARGET_API_MAC_OS8
238: static UInt16 CountRootFiles(ExtendedVCB *vcb);
239: #endif /* TARGET_API_MAC_OS8 */
240:
241:
242: #if ( hasHFSManualEject )
243: static void SetVCBManEject(ExtendedVCB *vcb);
244: #endif
245:
246: // External routines
247:
248: extern OSErr C_FlushMDB( ExtendedVCB *volume );
249:
250: extern OSErr DisposeVolumeCacheBlocks( ExtendedVCB *vcb );
251:
252: extern void DisposeVolumeControlBlock( ExtendedVCB *vcb );
253:
254: extern OSErr FlushVolumeBuffers( ExtendedVCB *vcb );
255:
256: extern void MultiplyUInt32IntoUInt64( UInt64 *wideResult, UInt32 num1, UInt32 num2 );
257:
258: extern void TrashCatalogNodeCache( void );
259:
260:
261: //�������������������������������������������������������������������������������
262: // Routine: VolumeWritable Asm: CVFlgs
263: //
264: // Function: Check the volume's flags to see if modify requests are allowed.
265: //
266: //�������������������������������������������������������������������������������
267: OSErr VolumeWritable( ExtendedVCB *vcb )
268: {
269: if ( !(vcb->vcbAtrb & 0x8000) ) // if the volume is not locked
270: {
271: if ( ! (*((Ptr)&(vcb->vcbAtrb) + 1) & kHFSVolumeHardwareLockMask) ) // if it's not write protected
272: return( noErr );
273: else
274: return( wPrErr );
275: }
276: else
277: {
278: return( vLckdErr );
279: }
280: }
281:
282:
283: //�������������������������������������������������������������������������������
284: // Routine: DivUp from Asm: DivUp
285: //
286: // Function: Given a number of bytes and block size, calculate the number of
287: // blocks needd to hold all the bytes.
288: //
289: // Result: Number of physical blocks needed
290: //�������������������������������������������������������������������������������
291: UInt16 DivUp( UInt32 byteRun, UInt32 blockSize )
292: {
293: UInt32 blocks;
294:
295: blocks = (byteRun + blockSize - 1) / blockSize; // Divide up, remember this is integer math.
296:
297: if ( blocks > 0xffff ) // maximum 16 bit value
298: blocks = 0xffff;
299:
300: return( (UInt16) blocks );
301: }
302:
303:
304:
305:
306: //�������������������������������������������������������������������������������
307: // Routine: HFSBlocksFromTotalSectors
308: //
309: // Function: Given the total number of sectors on the volume, calculate
310: // the 16Bit number of allocation blocks, and allocation block size.
311: //
312: // Result: none
313: //�������������������������������������������������������������������������������
314: void HFSBlocksFromTotalSectors( UInt32 totalSectors, UInt32 *blockSize, UInt16 *blockCount )
315: {
316: UInt16 newBlockSizeInSectors = 1;
317: UInt32 newBlockCount = totalSectors;
318:
319: while ( newBlockCount > 0XFFFF )
320: {
321: newBlockSizeInSectors++;
322: newBlockCount = totalSectors / newBlockSizeInSectors;
323: }
324:
325: *blockSize = newBlockSizeInSectors * 512;
326: *blockCount = newBlockCount;
327: }
328:
329:
330:
331:
332: //�������������������������������������������������������������������������������
333: // Routine: ValidMasterDirectoryBlock
334: //
335: // Function: Run some sanity checks to make sure the MDB is valid
336: //
337: // Result: error
338: //�������������������������������������������������������������������������������
339: OSErr ValidMasterDirectoryBlock( HFSMasterDirectoryBlock *mdb )
340: {
341: OSErr err;
342:
343: if ( (mdb->drSigWord == kHFSPlusSigWord) || (mdb->drSigWord == kHFSSigWord) ) // if HFS or HFS Plus volume
344: {
345: if ( (mdb->drAlBlkSiz != 0) && ((mdb->drAlBlkSiz & 0x01FF) == 0) ) // non zero multiple of 512
346: err = noErr;
347: else
348: err = badMDBErr;
349: }
350: else
351: {
352: err = noMacDskErr;
353: }
354:
355: return( err );
356: }
357:
358:
359: //�������������������������������������������������������������������������������
360: // Routine: ValidVolumeHeader
361: //
362: // Function: Run some sanity checks to make sure the VolumeHeader is valid
363: //
364: // Result: error
365: //�������������������������������������������������������������������������������
366: OSErr ValidVolumeHeader( HFSPlusVolumeHeader *volumeHeader )
367: {
368: OSErr err;
369:
370: if ( volumeHeader->signature == kHFSPlusSigWord && volumeHeader->version == kHFSPlusVersion )
371: {
372: if ( (volumeHeader->blockSize != 0) && ((volumeHeader->blockSize & 0x01FF) == 0) ) // non zero multiple of 512
373: err = noErr;
374: else
375: err = badMDBErr; //�� I want badVolumeHeaderErr in Errors.i
376: }
377: else
378: {
379: err = noMacDskErr;
380: }
381:
382: return( err );
383: }
384:
385:
386:
387:
388: //_______________________________________________________________________
389: //
390: // Routine: CountRootFiles
391: //
392: // Input: pointer to VCB
393: //
394: // Function: Return a count of the number of files and folders in
395: // the root directory of a volume. For HFS volumes, this
396: // is maintained in the VCB (and MDB). For HFS Plus volumes,
397: // we get the valence of the root directory from its catalog
398: // record.
399: //_______________________________________________________________________
400: UInt16 CountRootFiles(ExtendedVCB *vcb)
401: {
402: OSErr err;
403: FSSpec spec;
404: CatalogNodeData catNodeData;
405: UInt32 hint;
406: UInt16 rootCount;
407:
408: // if (vcb->vcbSigWord == kHFSSigWord || vcb->vcbFSID != 0) {
409: // return vcb->vcbNmFls;
410: // }
411:
412: // Here, it's an HFS Plus volume, so get the valence from the root
413: // directory's catalog record.
414:
415: rootCount = 0;
416:
417: err = GetCatalogNode( vcb, kHFSRootFolderID, nil, kUndefinedStrLen, kNoHint, &spec, &catNodeData, &hint );
418: if ( err == noErr ) {
419: if (catNodeData.cnd_valence < 65536)
420: rootCount = catNodeData.cnd_valence;
421: else
422: rootCount = 65535; // if the value is too large, pin it
423: }
424:
425: return rootCount;
426: }
427:
428:
429:
430: //_______________________________________________________________________
431: //
432: // Routine: FlushVolumeControlBlock
433: // Arguments: ExtendedVCB *vcb
434: // Output: OSErr err
435: //
436: // Function: Flush volume information to either the VolumeHeader of the Master Directory Block
437: //_______________________________________________________________________
438:
439: OSErr FlushVolumeControlBlock( ExtendedVCB *vcb )
440: {
441: OSErr err;
442:
443: if ( ! IsVCBDirty( vcb ) ) // if it's not dirty
444: return( noErr );
445:
446: if ( vcb->vcbSigWord == kHFSPlusSigWord )
447: {
448: err = C_FlushMDB( vcb ); // Go flush the VCB info BEFORE close
449: }
450: else
451: {
452: // This routine doesn't really return an error!!!
453: // So for now, we will just return noErr
454: err = C_FlushMDB( vcb ); // Go flush the VCB info BEFORE close
455: return( noErr );
456: }
457:
458: return( err );
459: }
460:
461:
462: //�������������������������������������������������������������������������������
463:
464: OSErr GetVolumeNameFromCatalog( ExtendedVCB *vcb )
465: {
466: FSSpec spec;
467: CatalogNodeData nodeData;
468: UInt32 hint;
469: OSErr err;
470:
471: if ( true )
472: {
473: err = GetCatalogNode( vcb, kHFSRootFolderID, NULL, kUndefinedStrLen, kNoHint, &spec, &nodeData, &hint );
474:
475: if ( err == noErr )
476: {
477: BlockMoveData( spec.name, vcb->vcbVN, strlen(spec.name));
478: vcb->volumeNameEncodingHint = nodeData.cnd_textEncoding; // save encoding for FSFindTextEncodingForVolume
479: }
480: }
481: else
482: {
483: err = paramErr;
484: }
485:
486: return err;
487: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.