2 * Copyright (c) 1999-2011 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
32 #include "BTreePrivate.h"
34 #include "BTreeScanner.h"
35 #include "hfs_endian.h"
36 #include "../fsck_debug.h"
37 #include "../fsck_messages.h"
38 #include "../fsck_hfs_msgnums.h"
39 #include "../fsck_msgnums.h"
40 #include "../fsck_hfs.h"
43 #include <sys/xattr.h>
45 #include <sys/kauth.h>
46 #include <sys/errno.h>
47 #include <sys/syslimits.h>
48 #include <sys/param.h>
49 #include <sys/sysctl.h>
50 #include <sys/mount.h>
51 #include <hfs/hfs_mount.h>
58 #define kFSCKMountVersion 0x6673636B /* 'fsck' made changes */
61 Log2BlkLo
= 9, // number of left shifts to convert bytes to block.lo
62 Log2BlkHi
= 23 // number of right shifts to convert bytes to block.hi
74 /* IO size for reading or writing disk blocks */
75 #define DISK_IOSIZE 32768
77 #define kMaxReScan 3 /* max times to re-scan volume on repair success */
79 #define kBTreeHeaderUserBytes 128
81 #define kBusErrorValue 0x50FF8001
83 //¥¥ Danger! This should not be hard coded
84 #define kMaxClumpSize 0x100000 /* max clump size is 1MB (2048 btree nodes) */
86 #define MDB_FNum 1 /* file number representing the MDB */
87 #define AMDB_FNum -1 /* file number representing the alternate MDB */
88 #define VBM_FNum 2 /* file number representing the volume bit map */
89 #define MDB_BlkN 2 /* logical block number for the MDB */
91 #define kCalculatedExtentRefNum ( 0 )
92 #define kCalculatedCatalogRefNum ( 1*sizeof(SFCB) )
93 #define kCalculatedAllocationsRefNum ( 2*sizeof(SFCB) )
94 #define kCalculatedAttributesRefNum ( 3*sizeof(SFCB) )
95 #define kCalculatedStartupRefNum ( 4*sizeof(SFCB) )
96 #define kCalculatedRepairRefNum ( 5*sizeof(SFCB) )
98 #define Max_ABSiz 0x7FFFFE00 /* max allocation block size (multiple of 512 */
99 #define Blk_Size 512 /* size of a logical block */
100 #define kHFSBlockSize 512 /* HFS block size */
102 // only the lower 7 bits are considered to be invalid, all others are valid -djb
103 #define VAtrb_Msk 0x007F /* volume attribute mask - invalid bits */
104 #define VAtrb_DFlt 0x0100 /* default volume attribute flags */
105 #define VAtrb_Cons 0x0100 /* volume consistency flag */
106 #define kHFSCatalogNodeIDsReused 0x1000
110 * File type and creator for TextEdit documents
113 kTextFileType
= 0x54455854, /* 'TEXT' */
114 kTextFileCreator
= 0x74747874, /* 'ttxt' */
118 * Alias type and creator for directory hard links
121 kHFSAliasType
= 0x66647270, /* 'fdrp' */
122 kHFSAliasCreator
= 0x4D414353 /* 'MACS' */
125 /*------------------------------------------------------------------------------
126 BTree data structures
127 ------------------------------------------------------------------------------*/
129 /* misc BTree constants */
131 #define BTMaxDepth 8 /* max tree depth */
132 #define Num_HRecs 3 /* number of records in BTree Header node */
133 #define Num_MRecs 1 /* number of records in BTree Map node */
137 // DFA extensions to the HFS/HFS+ BTreeControlBlock
138 typedef struct BTreeExtensionsRec
140 Ptr BTCBMPtr
; // pointer to scavenger BTree bit map
141 UInt32 BTCBMSize
; // size of the bitmap, bytes
142 BTreeControlBlock
*altBTCB
; // BTCB DFA builds up
143 UInt32 realFreeNodeCount
; // Number of real free nodes, taken from disk, for more accurate progress information
144 } BTreeExtensionsRec
;
149 * Scavenger BTree Path Record (STPR)
151 typedef struct STPR
{
152 UInt32 TPRNodeN
; /* node number */
153 SInt16 TPRRIndx
; /* record index */
154 SInt16 unused
; /* not used - makes debugging easier */
155 UInt32 TPRLtSib
; /* node number of left sibling node */
156 UInt32 TPRRtSib
; /* node number of right sibling node */
159 typedef STPR SBTPT
[BTMaxDepth
]; /* BTree path table */
161 #define LenSBTPT ( sizeof(STPR) * BTMaxDepth ) /* length of BTree Path Table */
166 /*------------------------------------------------------------------------------
167 CM (Catalog Manager) data structures
168 ------------------------------------------------------------------------------*/
173 #define CMMaxDepth 100 /* max catalog depth (Same as Finder 7.0) */
175 #define fNameLocked 4096
181 typedef union CatalogName CatalogName
;
184 // Scavenger Directory Path Record (SDPR)
186 typedef struct SDPR
{
187 UInt32 directoryID
; // directory ID
188 UInt32 offspringIndex
; // offspring index
189 UInt32 directoryHint
; // BTree hint for directory record
190 long threadHint
; // BTree hint for thread record
191 HFSCatalogNodeID parentDirID
; // parent directory ID
192 CatalogName directoryName
; // directory CName
196 // kInvalidMRUCacheKey = -1L, /* flag to denote current MRU cache key is invalid*/
197 kDefaultNumMRUCacheBlocks
= 16 /* default number of blocks in each cache*/
202 * UTCacheReadIP and UTCacheWriteIP cacheOption
206 noCacheBit
= 5, /* don't cache this please */
207 noCacheMask
= 0x0020,
208 rdVerifyBit
= 6, /* read verify */
209 rdVerifyMask
= 0x0040
213 /*------------------------------------------------------------------------------
214 Low-level File System Error codes
215 ------------------------------------------------------------------------------*/
217 /* The DCE bits are defined as follows (for the word of flags): */
222 Is_Agent
= 1, // future use
223 FollowsNewRules
= 2, // New DRVR Rules Bit
235 Is_AppleTalk_Mask
= 1 << Is_AppleTalk
,
236 Is_Agent_Mask
= 1 << Is_Agent
,
237 FollowsRules_Mask
= 1 << FollowsNewRules
,
238 Is_Open_Mask
= 1 << Is_Open
,
239 Is_Ram_Based_Mask
= 1 << Is_Ram_Based
,
240 Is_Active_Mask
= 1 << Is_Active
,
241 Read_Enable_Mask
= 1 << Read_Enable
,
242 Write_Enable_Mask
= 1 << Write_Enable
,
243 Control_Enable_Mask
= 1 << Control_Enable
,
244 Status_Enable_Mask
= 1 << Status_Enable
,
245 Needs_Goodbye_Mask
= 1 << Needs_Goodbye
,
246 Needs_Time_Mask
= 1 << Needs_Time
,
247 Needs_Lock_Mask
= 1 << Needs_Lock
251 cdInternalErr
= -1312, // internal CheckDisk error
252 cdVolumeNotFoundErr
= -1313, // cound not find volume (could be offline)
253 cdCannotReadErr
= -1314, // unable to read from disk
254 cdCannotWriteErr
= -1315, // unable to write to disk
255 cdNotHFSVolumeErr
= -1316, // not an HFS disk
256 cdUnrepairableErr
= -1317, // volume needs major repairs that CheckDisk cannot fix
257 cdRepairFailedErr
= -1318, // repair failed
258 cdUserCanceledErr
= -1319, // user interrupt
259 cdVolumeInUseErr
= -1320, // volume modifed by another app
260 cdNeedsRepairsErr
= -1321, // volume needs repairs (see repairInfo for additional info)
261 cdReMountErr
= -1322, // Cannot remount volume
262 cdUnknownProcessesErr
= -1323, // Volume cannot be unmounted and unknown processes are running
263 cdDamagedWrapperErr
= -1324, // HFS Wrapper damaged error.
264 cdIncompatibleOSErr
= -1325, // Current OS version is incompatible
265 cdMemoryFullErr
= -1326 // not enough memory to check disk
270 fsDSIntErr
= -127 /* non-hardware Internal file system error */
273 // Repair Info - additional info returned when a repair is attempted
275 kFileSharingEnabled
= 0x00000001,
276 kDiskIsLocked
= 0x00000002,
277 kDiskIsBoot
= 0x00000004,
278 kDiskHasOpenFiles
= 0x00000008,
279 kVolumeHadOverlappingExtents
= 0x00000010, // repairLevelSomeDataLoss
280 kVolumeClean
= 0x00000020,
282 kRepairsWereMade
= 0x80000000
285 // Input parameters to CheckDisk
288 ignoreRunningProcessesMask
= 0x00000001, // Assumes caller has shut down processes
289 checkDiskVersionMask
= 0x00000004 // Will just return back the version in repairInfo.
292 // Message types, so the user can treat and display accordingly
294 kStatusMessage
= 0x0000,
295 kTitleMessage
= 0x0001,
296 kErrorMessage
= 0x0002
299 // <10> Current stage of CheckDisk passed to cancel proc.
300 // File System is marked busy during kRepairStage, so WaitNextEvent and I/O cannot be done during this stage.
309 // Resource ID of 'STR ' resource containing the name of of the folder to create aliases to damaged files.
311 rDamagedFilesDirSTRid
= -20886
316 kUnknownVolumeType
= 0,
318 kEmbededHFSPlusVolumeType
,
319 kPureHFSPlusVolumeType
327 kHighLevelInfo
= 1100,
335 /*------------------------------------------------------------------------------
336 Minor Repair Interface (records compiled during scavenge, later repaired)
337 Note that not all repair types use all of these fields.
338 -----------------------------------------------------------------------------*/
340 typedef struct RepairOrder
/* a node describing a needed minor repair */
342 struct RepairOrder
*link
; /* link to next node, or NULL */
343 SInt16 type
; /* type of error, as an error code (E_DirVal etc) */
344 SInt16 forkType
; /* which file fork */
345 UInt64 correct
; /* correct valence */
346 UInt64 incorrect
; /* valence as found in volume (for consistency chk) */
347 UInt32 maskBit
; /* incorrect bit */
348 UInt32 hint
; /* B-tree node hint */
349 UInt32 parid
; /* parent ID */
350 unsigned char name
[1]; /* dir or file name */
351 } RepairOrder
, *RepairOrderPtr
;
354 typedef struct EmbededVolDescription
357 UInt16 drEmbedSigWord
;
358 HFSExtentDescriptor drEmbedExtent
;
359 } EmbededVolDescription
;
362 // define the correct drive queue structure
363 typedef struct ExtendedDrvQueue
367 char dQUsedInternally
;
368 char dQDiskIsSingleSided
;
379 /*------------------------------------------------------------------------------
380 Scavenger Global Area - (SGlob)
381 ------------------------------------------------------------------------------*/
382 typedef struct MissingThread
384 struct MissingThread
*link
; /* link to next node, or NULL */
386 HFSPlusCatalogKey nextKey
;
387 HFSPlusCatalogThread thread
;
391 #define kRsrcFork (-1)
395 HFSCatalogNodeID fileID
;
398 UInt32 newStartBlock
;
401 /* didRepair stores the result of moving of overlap extent and is used
402 * to decide which disk blocks (original blocks or blocks allocated for
403 * for new extent location) should be marked used and free.
407 typedef struct ExtentInfo ExtentInfo
;
409 struct ExtentsTable
{
411 ExtentInfo extentInfo
[1];
413 typedef struct ExtentsTable ExtentsTable
;
416 struct FileIdentifier
{
418 HFSCatalogNodeID fileID
;
419 HFSCatalogNodeID parID
; // Used for files on HFS volumes without threads
420 Str31 name
; // Used for files on HFS volumes without threads
422 typedef struct FileIdentifier FileIdentifier
;
424 struct FileIdentifierTable
{
426 FileIdentifier fileIdentifier
[1];
428 typedef struct FileIdentifierTable FileIdentifierTable
;
430 /* Universal Extent Key */
434 HFSPlusExtentKey hfsPlus
;
436 typedef union ExtentKey ExtentKey
;
437 /* Universal extent descriptor */
439 union ExtentDescriptor
{
440 HFSExtentDescriptor hfs
;
441 HFSPlusExtentDescriptor hfsPlus
;
443 typedef union ExtentDescriptor ExtentDescriptor
;
444 /* Universal extent record */
448 HFSPlusExtentRecord hfsPlus
;
450 typedef union ExtentRecord ExtentRecord
;
451 /* Universal catalog key */
455 HFSPlusCatalogKey hfsPlus
;
457 typedef union CatalogKey CatalogKey
;
458 /* Universal catalog data record */
460 union CatalogRecord
{
462 HFSCatalogFolder hfsFolder
;
463 HFSCatalogFile hfsFile
;
464 HFSCatalogThread hfsThread
;
465 HFSPlusCatalogFolder hfsPlusFolder
;
466 HFSPlusCatalogFile hfsPlusFile
;
467 HFSPlusCatalogThread hfsPlusThread
;
469 typedef union CatalogRecord CatalogRecord
;
472 Key for records in the attributes file. Fields are compared in the order:
473 cnid, attributeName, startBlock
476 struct AttributeKey
{
477 UInt16 keyLength
; /* must set kBTBigKeysMask and kBTVariableIndexKeysMask in BTree header's attributes */
479 HFSCatalogNodeID cnid
; /* file or folder ID */
480 UInt32 startBlock
; /* block # relative to start of attribute */
481 UInt16 attrNameLen
; /* number of unicode characters */
482 UInt16 attrName
[127]; /* attribute name (Unicode) */
484 typedef struct AttributeKey AttributeKey
;
486 kAttributeKeyMaximumLength
= sizeof(AttributeKey
) - sizeof(UInt16
),
487 kAttributeKeyMinimumLength
= kAttributeKeyMaximumLength
- 127 * sizeof(UInt16
) + sizeof(UInt16
)
491 QElemPtr qLink
; /*queue link in header*/
492 short qType
; /*type byte for safety check*/
493 short ioTrap
; /*FS: the Trap*/
494 Ptr ioCmdAddr
; /*FS: address to dispatch to*/
495 void* ioCompletion
; /*completion routine addr (0 for synch calls)*/
496 OSErr ioResult
; /*result code*/
497 StringPtr ioNamePtr
; /*ptr to Vol:FileName string*/
498 short ioVRefNum
; /*volume refnum (DrvNum for Eject and MountVol)*/
509 typedef struct HIOParam HIOParam
;
511 typedef HIOParam
* HIOParamPtr
;
515 UInt32 length
; /* first word is FCB part length*/
516 SFCB fcb
[1]; /* fcb array*/
518 typedef struct FCBArray FCBArray
;
521 UserCancel callback routine
524 progress: number from 1 to 100 indicating current progress
525 progressChanged: boolean flag that is true if progress number has been updated
526 context: pointer to context data (if any) that the caller passed to CheckDisk
529 return true if the user wants to cancel the CheckDisk operation
532 typedef int (*UserCancelProcPtr
)(UInt16 progress
, UInt16 secondsRemaining
, Boolean progressChanged
, UInt16 stage
, void *context
, int passno
);
537 //-- User Cancel Proc
538 typedef UniversalProcPtr UserCancelUPP
;
541 uppUserCancelProcInfo
= kPascalStackBased
542 | RESULT_SIZE(kTwoByteCode
)
543 | STACK_ROUTINE_PARAMETER(1, kTwoByteCode
)
544 | STACK_ROUTINE_PARAMETER(2, kTwoByteCode
)
545 | STACK_ROUTINE_PARAMETER(3, kTwoByteCode
)
546 | STACK_ROUTINE_PARAMETER(4, kTwoByteCode
)
547 | STACK_ROUTINE_PARAMETER(5, kFourByteCode
)
550 #define NewUserCancelProc(userRoutine) \
551 (UserCancelUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppUserCancelProcInfo, GetCurrentArchitecture())
553 #define CallUserCancelProc(userRoutine, progress, secondsRemaining, progressChanged, stage, context, p) \
554 CallUniversalProc((UniversalProcPtr)(userRoutine), uppUserCancelProcInfo, (progress), (secondsRemaining), (progressChanged), (stage), (context), (p))
558 typedef UserCancelProcPtr UserCancelUPP
;
560 #define NewUserCancelProc(userRoutine) \
561 ((UserCancelUPP) (userRoutine))
563 #define CallUserCancelProc(userRoutine, progress, secondsRemaining, progressChanged, stage, context, p) \
564 (*(userRoutine))((progress), (secondsRemaining), (progressChanged), (stage), (context), (p))
570 UserMessage callback routine
573 message: message from CheckDisk
574 messageType: type of message
575 context: pointer to context data (if any) that the caller passed to CheckDisk
578 return true if the user wants to cancel the CheckDisk operation
582 typedef pascal void (*UserMessageProcPtr
)(StringPtr message
, SInt16 messageType
, void *context
);
586 //-- User Message Proc
587 typedef UniversalProcPtr UserMessageUPP
;
590 uppUserMessageProcInfo
= kPascalStackBased
591 | STACK_ROUTINE_PARAMETER(1, kFourByteCode
)
592 | STACK_ROUTINE_PARAMETER(2, kTwoByteCode
)
593 | STACK_ROUTINE_PARAMETER(3, kFourByteCode
)
596 #define NewUserMessageProc(userRoutine) \
597 (UserMessageUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppUserMessageProcInfo, GetCurrentArchitecture())
599 #define CallUserMessageProc(userRoutine, message, messageType, context) \
600 CallUniversalProc((UniversalProcPtr)(userRoutine), uppUserMessageProcInfo, (message), (messageType), (context))
604 typedef UserMessageProcPtr UserMessageUPP
;
606 #define NewUserMessageProc(userRoutine) \
607 ((UserMessageUPP) (userRoutine))
609 #define CallUserMessageProc(userRoutine, message, messageType, context) \
610 (*(userRoutine))((message), (messageType), (context))
614 /* 3843779 Structure to determine consistency of attribute data and
615 * corresponding bit in catalog record. Based on Chinese Remainder
618 typedef struct PrimeBuckets
{
632 /* Record last attribute ID checked, used in CheckAttributeRecord, initialized in ScavSetup */
633 typedef struct attributeInfo
{
638 unsigned char attrname
[XATTR_MAXNAMELEN
+1];
639 u_int32_t totalBlocks
;
640 u_int32_t calculatedTotalBlocks
;
641 u_int64_t logicalSize
;
645 VolumeObject encapsulates all infomration about the multiple volume anchor blocks (VHB and MSD)
646 on HFS and HFS+ volumes. An HFS volume will have two MDBs (primary and alternate HFSMasterDirectoryBlock),
647 a pure HFS+ volume will have two VHBs (primary and alternate HFSPlusVolumeHeader), and a wrapped HFS+
648 volume will have two MDBs and two VHBs.
651 /* values for VolumeObject.flags */
653 kVO_Inited
= 0x00000001, // this structured has been initialized
654 kVO_PriVHBOK
= 0x00000002, // the primary Volume Header Block is valid
655 kVO_AltVHBOK
= 0x00000004, // the alternate Volume Header Block is valid
656 kVO_PriMDBOK
= 0x00000008, // the primary Master Directory Block is valid
657 kVO_AltMDBOK
= 0x00000010, // the alternate Master Directory Block is valid
660 typedef struct VolumeObject
{
662 SVCB
* vcbPtr
; // pointer to VCB used for this volume
663 UInt32 volumeType
; // (kHFSVolumeType or kEmbededHFSPlusVolumeType or kPureHFSPlusVolumeType)
664 UInt32 embeddedOffset
; // offset of embedded HFS+ (in bytes) volume into HFS wrapper volume
665 // NOTE - UInt32 is OK since we don't support HFS Wrappers on TB volumes
666 UInt32 sectorSize
; // size of a sector for this device
667 UInt64 totalDeviceSectors
; // total number of sectors for this volume (from GetDeviceSize)
668 UInt64 totalEmbeddedSectors
; // total number of sectors for embedded volume
669 // location of all possible volume anchor blocks (MDB and VHB) on this volume. These locations
670 // are the sector offset into the volume. Only wrapped HFS+ volumes use all 4 of these.
671 UInt64 primaryVHB
; // not used for HFS volumes
672 UInt64 alternateVHB
; // not used for HFS volumes
673 UInt64 primaryMDB
; // not used for pure HFS+ volumes
674 UInt64 alternateMDB
; // not used for pure HFS+ volumes
675 } VolumeObject
, *VolumeObjectPtr
;
678 typedef struct SGlob
{
679 void * scavStaticPtr
; // pointer to static structure allocated in ScavSetUp
680 SInt16 DrvNum
; // drive number of target drive
681 SInt16 RepLevel
; // repair level, 1 = minor repair, 2 = major repair
682 SInt16 ScavRes
; // scavenge result code
683 OSErr ErrCode
; // error code
684 OSErr IntErr
; // internal error code
685 UInt16 VIStat
; // scavenge status flags for volume info
686 UInt16 ABTStat
; // scavenge status flags for Attributes BTree
687 UInt16 EBTStat
; // scavenge status flags for extent BTree
688 UInt16 CBTStat
; // scavenge status flags for catalog BTree
689 UInt32 CatStat
; // scavenge status flags for catalog file
690 UInt16 VeryMinorErrorsStat
; // scavenge status flags for very minor errors
691 UInt16 JStat
; // scavange status flags for journal errors
692 UInt16 PrintStat
; // info about messages that should be displayed only once
693 DrvQElPtr DrvPtr
; // pointer to driveQ element for target drive
694 UInt32 TarID
; // target ID (CNID of data structure being verified)
695 UInt64 TarBlock
; // target block/node number being verified
696 SInt16 BTLevel
; // current BTree enumeration level
697 SBTPT
*BTPTPtr
; // BTree path table pointer
698 SInt16 DirLevel
; // current directory enumeration level
699 SDPR
*DirPTPtr
; // directory path table pointer (pointer to array of SDPR)
700 uint32_t dirPathCount
; // number of SDPR entries allocated in directory path table
701 SInt16 CNType
; // current CNode type
702 UInt32 ParID
; // current parent DirID
703 CatalogName CName
; // current CName
704 RepairOrderPtr MinorRepairsP
; // ptr to list of problems for later repair
705 MissingThread
*missingThreadList
;
706 Ptr FCBAPtr
; // pointer to scavenger FCB array
707 UInt32
**validFilesList
; // List of valid HFS file IDs
709 ExtentsTable
**overlappedExtents
; // List of overlapped extents
710 FileIdentifierTable
**fileIdentifierTable
; // List of files for post processing
712 UInt32 inputFlags
; // Caller can specify some DFA behaviors
714 UInt32 volumeFeatures
; // bit vector of volume and OS features
715 Boolean usersAreConnected
; // true if user are connected
716 Boolean fileSharingOn
; // true if file sharing is on
717 UInt32 altBlockLocation
;
718 Boolean checkingWrapper
;
719 SInt16 numExtents
; // Number of memory resident extents. 3 or 8
720 OSErr volumeErrorCode
;
722 UserCancelUPP userCancelProc
;
723 UserMessageUPP userMessageProc
;
727 UInt64 itemsToProcess
;
728 UInt64 itemsProcessed
;
731 UInt16 secondsRemaining
;
737 SFCB
*calculatedExtentsFCB
;
738 SFCB
*calculatedCatalogFCB
;
739 SFCB
*calculatedAllocationsFCB
;
740 SFCB
*calculatedAttributesFCB
;
741 SFCB
*calculatedStartupFCB
;
742 SFCB
*calculatedRepairFCB
;
743 BTreeControlBlock
*calculatedExtentsBTCB
;
744 BTreeControlBlock
*calculatedCatalogBTCB
;
745 BTreeControlBlock
*calculatedRepairBTCB
;
746 BTreeControlBlock
*calculatedAttributesBTCB
;
748 Boolean cleanUnmount
;
753 int rebuildOptions
; // options to indicate type of btree(s) to rebuild
754 Boolean minorRepairErrors
; // indicates some minor repairs failed
755 Boolean minorRepairFalseSuccess
; // indicates minor repair function is returning false success, do not delete from the list
756 int canWrite
; // we can safely write to the block device
757 int writeRef
; // file descriptor with write access on the volume
758 int lostAndFoundMode
; // used when creating lost+found directory
759 int liveVerifyState
; // indicates if live verification is being done or not
760 BTScanState scanState
;
761 int scanCount
; /* Number of times fsck_hfs has looped */
763 unsigned char volumeName
[256]; /* volume name in ASCII or UTF-8 */
764 char deviceNode
[256]; /* device node in ASCII */
766 /* Extended attribute check related stuff */
767 uint32_t cat_ea_count
; /* number of catalog records that have attribute bit set */
768 uint32_t cat_acl_count
; /* number of catalog records that have security bit set */
769 uint32_t attr_ea_count
; /* number of unique fileID attributes found in attribute btree */
770 uint32_t attr_acl_count
; /* number of acls found in attribute btree */
771 PrimeBuckets CBTAttrBucket
; /* prime number buckets for Attribute bit in Catalog btree */
772 PrimeBuckets CBTSecurityBucket
; /* prime number buckets for Security bit in Catalog btree */
773 PrimeBuckets ABTAttrBucket
; /* prime number buckets for Attribute bit in Attribute btree */
774 PrimeBuckets ABTSecurityBucket
; /* prime number buckets for Security bit in Attribute btree */
775 attributeInfo lastAttrInfo
; /* Record last attribute ID checked, used in CheckAttributeRecord, initialized in ScavSetup */
776 UInt16 securityAttrName
[XATTR_MAXNAMELEN
]; /* Store security attribute name in UTF16, to avoid frequent conversion */
777 size_t securityAttrLen
;
779 /* File Hard Links related stuff */
780 uint32_t filelink_priv_dir_id
;
782 /* Directory Hard Links related stuff */
783 uint32_t dirlink_priv_dir_id
;
784 uint32_t dirlink_priv_dir_valence
;
785 uint32_t calculated_dirinodes
;
786 uint32_t calculated_dirlinks
;
788 /* Journal file ID's */
789 uint32_t journal_file_id
;
790 uint32_t jib_file_id
;
796 supportsTrashVolumeCacheFeatureMask
= 1,
797 supportsHFSPlusVolsFeatureMask
= 2,
798 volumeIsMountedMask
= 4
801 /* scavenger flags */
803 /* volume info status flags (contents of VIStat) */
805 #define S_MDB 0x8000 // MDB/VHB damaged
806 #define S_AltMDB 0x4000 // Unused /* alternate MDB damaged */
807 #define S_VBM 0x2000 // volume bit map damaged
808 #define S_WMDB 0x1000 // wrapper MDB is damaged
809 #define S_OverlappingExtents 0x0800 // Overlapping extents found
810 #define S_BadMDBdrAlBlSt 0x0400 // Invalid drAlBlSt field in MDB
811 #define S_InvalidWrapperExtents 0x0200 // Invalid catalog extent start in MDB
813 /* BTree status flags (contents of EBTStat, CBTStat and ABTStat) */
815 #define S_BTH 0x8000 /* BTree header damaged */
816 #define S_BTM 0x4000 /* BTree map damaged */
817 #define S_Indx 0x2000 // Unused /* index structure damaged */
818 #define S_Leaf 0x1000 // Unused /* leaf structure damaged */
819 #define S_Orphan 0x0800 // orphaned file
820 #define S_OrphanedExtent 0x0400 // orphaned extent
821 #define S_ReservedNotZero 0x0200 // the flags or reserved fields are not zero
822 #define S_RebuildBTree 0x0100 // similar to S_Indx, S_Leaf, but if one is bad we stop checking and the other may also be bad.
823 #define S_ReservedBTH 0x0080 // fields in the BTree header should be zero but are not
824 #define S_AttributeCount 0x0040 // incorrect number of xattr in attribute btree in comparison with attribute bit in catalog btree
825 #define S_SecurityCount 0x0020 // incorrect number of security xattrs in attribute btree in comparison with security bit in catalog btree
826 #define S_AttrRec 0x0010 // orphaned/unknown record in attribute BTree
827 #define S_ParentHierarchy 0x0008 // bad parent hierarchy, could not lookup parent directory record */
828 #define S_UnusedNodesNotZero 0x0004 /* Unused B-tree nodes are not filled with zeroes */
830 /* catalog file status flags (contents of CatStat) */
832 #define S_IllName 0x00008000 /* illegal name found */
833 #define S_Valence 0x00004000 /* a directory valence is out of sync */
834 #define S_FThd 0x00002000 /* dangling file thread records exist */
835 #define S_DFCorruption 0x00001000 /* disappearing folder corruption detected */
836 #define S_NoDir 0x00000800 /* missing directory record */
837 #define S_LockedDirName 0x00000400 // locked dir name
838 #define S_MissingThread 0x00000200 /* missing thread record */
839 #define S_UnlinkedFile 0x00000100 /* orphaned link node */
840 #define S_LinkCount 0x00000080 /* data node link count needs repair */
841 #define S_Permissions 0x00000040 /* BSD permissions need repair */
842 #define S_FileAllocation 0x00000020 /* peof or leof needs adjustment */
843 #define S_BadExtent 0x00000010 /* invalid extent */
844 #define S_LinkErrRepair 0x00000008 /* repairable file/directory hard link corruption detected */
845 #define S_LinkErrNoRepair 0x00000004 /* un-repairable file/directory hard link corruptions detected */
846 #define S_FileHardLinkChain 0x00000002 /* incorrect number of file hard links, doubly linked list chain needs repair */
847 #define S_DirHardLinkChain 0x00000001 /* incorrect number of directory hard links, doubly linked list chain needs repair */
849 /* VeryMinorErrorsStat */
851 #define S_BloatedThreadRecordFound 0x8000 // 2210409, excessivly large thread record found
853 /* user file status flags (contents of FilStat) */
855 //#define S_LockedName 0x4000 // locked file name
857 /* Journal status flag (contents of JStat) */
858 #define S_BadJournal 0x8000 /* Bad journal content */
859 #define S_DirtyJournal 0x4000 /* Journal is dirty (needs to be replayed) */
861 /* Print status flag (contents of PrintStat) */
862 #define S_DamagedDir 0x8000 /* message for M_LookDamagedDir already printed */
863 #define S_SymlinkCreate 0x4000 /* message for E_SymlinkCreate already printed */
865 /*------------------------------------------------------------------------------
867 ------------------------------------------------------------------------------*/
869 // Command Codes (commands to ScavControl)
872 scavInitialize
= 1, // Start initial volume check
873 scavVerify
, // Start verify operation
874 scavRepair
, // Start repair opeation
875 scavTerminate
, // Cleanup after scavenge
882 repairLevelNoProblemsFound
= 0,
883 repairLevelRepairIfOtherErrorsExist
, // Bloated thread records, ...
884 repairLevelVeryMinorErrors
, // Missing Custom Icon, Locked Directory name,..., Errors that don't need fixing from CheckDisk (Installer), Non Volume corruption bugs.
885 repairLevelVolumeRecoverable
, // Minor Volume corruption exists
886 repairLevelSomeDataLoss
, // Overlapping extents, some data loss but no scavaging will get it back
887 repairLevelWillCauseDataLoss
, // Missing leaf nodes, repair will lose nodes without scavaging (proceed at your own risk, check disk with other utils)
888 repairLevelCatalogBtreeRebuild
, // Catalog Btree is damaged, repair may lose some data
889 repairLevelUnrepairable
// DFA cannot repair volume
893 /* Status messages written to summary */
900 /* Internal DFA error codes */
902 errRebuildBtree
= -1001 /* BTree requires rebuilding. */
906 enum { /* extendFileContigMask = 0x0002*/
907 kEFContigBit
= 1, /* force contiguous allocation*/
908 kEFContigMask
= 0x02,
909 kEFAllBit
= 0, /* allocate all requested bytes or none*/
911 kEFNoClumpBit
= 2, /* Don't round up requested size to multiple of clump size*/
912 kEFNoClumpMask
= 0x04, /* TruncateFile option flags*/
913 kEFNoExtOvflwBit
= 3, /* Don't use extens overflow file */
914 kEFNoExtOvflwMask
= 0x08,
916 kTFTrunExtBit
= 0, /* truncate to the extent containing new PEOF*/
922 // Encoding vs. Index
924 // For runtime table lookups and for the volume encoding bitmap we
925 // need to map some encodings to keep them in a reasonable range.
929 kTextEncodingMacRoman
= 0L,
930 kTextEncodingMacFarsi
= 0x8C, /* Like MacArabic but uses Farsi digits*/
931 /* The following use script code 7, smCyrillic*/
932 kTextEncodingMacUkrainian
= 0x98, /* The following use script code 32, smUnimplemented*/
934 kIndexMacUkrainian
= 48, // MacUkrainian encoding is 152
935 kIndexMacFarsi
= 49 // MacFarsi encoding is 140
938 #define MapEncodingToIndex(e) \
939 ( (e) < 48 ? (e) : ( (e) == kTextEncodingMacUkrainian ? kIndexMacUkrainian : ( (e) == kTextEncodingMacFarsi ? kIndexMacFarsi : kTextEncodingMacRoman) ) )
941 #define MapIndexToEncoding(i) \
942 ( (i) == kIndexMacFarsi ? kTextEncodingMacFarsi : ( (i) == kIndexMacUkrainian ? kTextEncodingMacUkrainian : (i) ) )
944 #define ValidMacEncoding(e) \
945 ( ((e) < 39) || ((e) == kTextEncodingMacFarsi) || ((e) == kTextEncodingMacUkrainian) )
950 extern void WriteMsg( SGlobPtr GPtr
, short messageID
, short messageType
);
951 extern void WriteError( SGlobPtr GPtr
, short msgID
, UInt32 tarID
, UInt64 tarBlock
);
952 extern short CheckPause( void );
954 /* ------------------------------- From SControl.c ------------------------------- */
956 void ScavCtrl( SGlobPtr GPtr
, UInt32 ScavOp
, short *ScavRes
);
958 extern short CheckForStop( SGlobPtr GPtr
);
961 /* ------------------------------- From SRepair.c -------------------------------- */
963 extern OSErr
RepairVolume( SGlobPtr GPtr
);
965 extern int FixDFCorruption( const SGlobPtr GPtr
, RepairOrderPtr DFOrderP
);
967 extern OSErr
ProcessFileExtents( SGlobPtr GPtr
, SFCB
*fcb
, UInt8 forkType
, UInt16 flags
, Boolean isExtentsBTree
, Boolean
*hasOverflowExtents
, UInt32
*blocksUsed
);
969 /* Function to get return file path/name given an ID */
970 extern OSErr
GetSystemFileName(UInt32 fileID
, char *filename
, unsigned int *filenamelen
);
971 extern OSErr
GetFileNamePathByID(SGlobPtr GPtr
, UInt32 fileID
, char *fullPath
, unsigned int *fullPathLen
, char *fileName
, unsigned int *fileNameLen
, u_int16_t
*status
);
972 #define FNAME_BUF2SMALL 0x001 /* filename buffer was too small */
973 #define FNAME_BIGNAME 0x002 /* filename is greater than NAME_MAX bytes */
974 #define FPATH_BUF2SMALL 0x010 /* path buffer was too small */
975 #define FPATH_BIGNAME 0x020 /* intermediate component in path is greater than NAME_MAX bytes */
976 #define F_RESERVE_FILEID 0x100 /* file ID was less than kHFSFirstUserCatalogNodeID */
978 /* ------------------------------- From SUtils.c --------------------------------- */
980 extern int AllocBTN( SGlobPtr GPtr
, short FilRefN
, UInt32 NodeNum
);
982 extern int IntError( SGlobPtr GPtr
, OSErr ErrCode
);
984 extern void RcdError( SGlobPtr GPtr
, OSErr ErrCode
);
986 extern RepairOrderPtr
AllocMinorRepairOrder( SGlobPtr GPtr
, size_t extraBytes
);
988 extern int IsDuplicateRepairOrder(SGlobPtr GPtr
, RepairOrderPtr orig
);
990 extern void DeleteRepairOrder(SGlobPtr GPtr
, RepairOrderPtr orig
);
992 extern void SetDFAStage( UInt32 stage
);
993 extern UInt32
GetDFAGlobals( void );
995 extern void InitializeVolumeObject( SGlobPtr GPtr
);
996 extern void CheckEmbeddedVolInfoInMDBs( SGlobPtr GPtr
);
997 extern VolumeObjectPtr
GetVolumeObjectPtr( void );
998 extern OSErr
GetVolumeObjectVHB( BlockDescriptor
* theBlockDescPtr
);
999 extern void GetVolumeObjectBlockNum( UInt64
* theBlockNumPtr
);
1000 extern OSErr
GetVolumeObjectAlternateBlock( BlockDescriptor
* theBlockDescPtr
);
1001 extern OSErr
GetVolumeObjectPrimaryBlock( BlockDescriptor
* theBlockDescPtr
);
1002 extern void GetVolumeObjectAlternateBlockNum( UInt64
* theBlockNumPtr
);
1003 extern void GetVolumeObjectPrimaryBlockNum( UInt64
* theBlockNumPtr
);
1004 extern OSErr
GetVolumeObjectAlternateMDB( BlockDescriptor
* theBlockDescPtr
);
1005 extern OSErr
GetVolumeObjectPrimaryMDB( BlockDescriptor
* theBlockDescPtr
);
1006 extern OSErr
GetVolumeObjectVHBorMDB( BlockDescriptor
* theBlockDescPtr
);
1007 extern void PrintName( int theCount
, const UInt8
*theNamePtr
, Boolean isUnicodeString
);
1008 extern void PrintVolumeObject( void );
1009 extern Boolean
VolumeObjectIsValid( SGlobPtr gptr
);
1010 extern Boolean
VolumeObjectIsHFSPlus( void );
1011 extern Boolean
VolumeObjectIsHFS( void );
1012 extern Boolean
VolumeObjectIsEmbeddedHFSPlus( void );
1013 extern Boolean
VolumeObjectIsPureHFSPlus( void );
1014 extern Boolean
VolumeObjectIsHFSX(SGlobPtr
);
1016 extern void InvalidateCalculatedVolumeBitMap( SGlobPtr GPtr
);
1018 extern OSErr
GetVolumeFeatures( SGlobPtr GPtr
);
1020 OSErr
FlushAlternateVolumeControlBlock( SVCB
*vcb
, Boolean isHFSPlus
);
1022 extern void ConvertToHFSPlusExtent(const HFSExtentRecord oldExtents
, HFSPlusExtentRecord newExtents
);
1024 void add_prime_bucket_uint32(PrimeBuckets
*cur
, uint32_t num
);
1026 void add_prime_bucket_uint64(PrimeBuckets
*cur
, uint64_t num
);
1028 int compare_prime_buckets(PrimeBuckets
*bucket1
, PrimeBuckets
*bucket2
);
1030 /* ------------------------------- From CatalogCheck.c -------------------------------- */
1032 extern OSErr
CheckCatalogBTree( SGlobPtr GPtr
); // catalog btree check
1034 extern OSErr
CheckFolderCount( SGlobPtr GPtr
); // Compute folderCount
1036 extern int RecordBadAllocation(UInt32 parID
, unsigned char * filename
, UInt32 forkType
, UInt32 oldBlkCnt
, UInt32 newBlkCnt
);
1038 extern int RecordTruncation(UInt32 parID
, unsigned char * filename
, UInt32 forkType
, UInt64 oldSize
, UInt64 newSize
);
1040 /* ------------------------------- From SVerify1.c -------------------------------- */
1042 extern OSErr
CatFlChk( SGlobPtr GPtr
); // catalog file check
1044 extern OSErr
CatHChk( SGlobPtr GPtr
); // catalog hierarchy check
1046 extern OSErr
ExtBTChk( SGlobPtr GPtr
); // extent btree check
1048 extern OSErr
BadBlockFileExtentCheck( SGlobPtr GPtr
); // bad block file extent check
1050 extern OSErr
AttrBTChk( SGlobPtr GPtr
); // attributes btree check
1052 extern OSErr
IVChk( SGlobPtr GPtr
);
1054 /* Operation type for CheckForClean */
1056 kCheckVolume
, // check if volume is clean/dirty
1057 kMarkVolumeDirty
, // mark the volume dirty
1058 kMarkVolumeClean
// mark the volume clean
1060 extern int CheckForClean( SGlobPtr GPtr
, UInt8 operation
, Boolean
*modified
);
1062 extern int CheckIfJournaled(SGlobPtr GPtr
, Boolean journal_bit_only
);
1064 typedef struct fsckJournalInfo
{
1065 int jnlfd
; // File descriptor for journal device
1066 off_t jnlOffset
; // Offset of journal on journal device
1067 off_t jnlSize
; // Size of journal on same
1068 char *name
; // Name of journal device
1069 } fsckJournalInfo_t
;
1071 extern int IsJournalEmpty(SGlobPtr
, fsckJournalInfo_t
*);
1073 extern OSErr
VInfoChk( SGlobPtr GPtr
);
1075 extern OSErr
VLockedChk( SGlobPtr GPtr
);
1077 extern void BuildExtentKey( Boolean isHFSPlus
, UInt8 forkType
, HFSCatalogNodeID fileNumber
, UInt32 blockNumber
, void * key
);
1079 extern OSErr
OrphanedFileCheck( SGlobPtr GPtr
, Boolean
*problemsFound
);
1081 extern int cmpLongs (const void *a
, const void *b
);
1083 extern int CheckAttributeRecord(SGlobPtr GPtr
, const HFSPlusAttrKey
*key
, const HFSPlusAttrRecord
*rec
, UInt16 reclen
);
1085 extern void RecordXAttrBits(SGlobPtr GPtr
, UInt16 flags
, HFSCatalogNodeID fileid
, UInt16 btreetype
);
1087 extern int FindOrigOverlapFiles(SGlobPtr GPtr
);
1089 extern void PrintOverlapFiles (SGlobPtr GPtr
);
1091 /* ------------------------------- From SVerify2.c -------------------------------- */
1093 typedef int (* CheckLeafRecordProcPtr
)(SGlobPtr GPtr
, void *key
, void *record
, UInt16 recordLen
);
1095 extern int BTCheck(SGlobPtr GPtr
, short refNum
, CheckLeafRecordProcPtr checkLeafRecord
);
1097 extern int BTMapChk( SGlobPtr GPtr
, short FilRefN
);
1099 extern OSErr
ChkCName( SGlobPtr GPtr
, const CatalogName
*name
, Boolean unicode
); // check catalog name
1101 extern OSErr
CmpBTH( SGlobPtr GPtr
, SInt16 fileRefNum
);
1103 extern int CmpBTM( SGlobPtr GPtr
, short FilRefN
);
1105 extern int CmpMDB( SGlobPtr GPtr
, HFSMasterDirectoryBlock
* mdbP
);
1107 extern int CmpVBM( SGlobPtr GPtr
);
1109 extern OSErr
CmpBlock( void *block1P
, void *block2P
, size_t length
); /* same as 'memcmp', but EQ/NEQ only */
1111 extern OSErr
ChkExtRec ( SGlobPtr GPtr
, UInt32 fileID
, const void *extents
, unsigned int *lastExtentIndex
);
1113 extern int BTCheckUnusedNodes(SGlobPtr GPtr
, short fileRefNum
, UInt16
*btStat
);
1116 /* -------------------------- From SRebuildBTree.c ------------------------- */
1118 extern OSErr
RebuildBTree( SGlobPtr theSGlobPtr
, int FileID
);
1121 /* -------------------------- From SCatalog.c ------------------------- */
1123 extern OSErr
UpdateFolderCount( SVCB
*vcb
,
1124 HFSCatalogNodeID pid
,
1125 const CatalogName
*name
,
1128 SInt16 valenceDelta
);
1130 /* ------------------------------- From SExtents.c -------------------------------- */
1131 OSErr
ZeroFileBlocks( SVCB
*vcb
, SFCB
*fcb
, UInt32 startingSector
, UInt32 numberOfSectors
);
1133 OSErr
MapFileBlockC (
1134 SVCB
*vcb
, // volume that file resides on
1135 SFCB
*fcb
, // FCB of file
1136 UInt32 numberOfBytes
, // number of contiguous bytes desired
1137 UInt64 sectorOffset
, // starting offset within file (in 512-byte sectors)
1138 UInt64
*startSector
, // first 512-byte volume sector (NOT an allocation block)
1139 UInt32
*availableBytes
); // number of contiguous bytes (up to numberOfBytes)
1141 OSErr
DeallocateFile(SVCB
*vcb
, CatalogRecord
* fileRec
);
1144 SVCB
*vcb
, // volume that file resides on
1145 SFCB
*fcb
, // FCB of file to truncate
1146 UInt32 sectorsToAdd
, // number of sectors to allocate
1147 UInt32 flags
, // EFContig and/or EFAll
1148 UInt32
*actualSectorsAdded
); // number of bytes actually allocated
1150 OSErr
FlushExtentFile( SVCB
*vcb
);
1152 void ExtDataRecToExtents(
1153 const HFSExtentRecord oldExtents
,
1154 HFSPlusExtentRecord newExtents
);
1156 OSErr
UpdateExtentRecord (
1159 const HFSPlusExtentKey
*extentFileKey
,
1160 HFSPlusExtentRecord extentData
,
1161 UInt32 extentBTreeHint
);
1163 OSErr
ReleaseExtents(
1165 const HFSPlusExtentRecord extentRecord
,
1166 UInt32
*numReleasedAllocationBlocks
,
1167 Boolean
*releasedLastExtent
);
1169 OSErr
CheckFileExtents( SGlobPtr GPtr
, UInt32 fileNumber
, UInt8 forkType
, const unsigned char *xattrName
,
1170 const void *extents
, UInt32
*blocksUsed
);
1171 OSErr
GetBTreeHeader( SGlobPtr GPtr
, SFCB
* fcb
, BTHeaderRec
*header
);
1172 OSErr
CompareVolumeBitMap( SGlobPtr GPtr
, SInt32 whichBuffer
);
1173 OSErr
CompareVolumeHeader( SGlobPtr GPtr
, HFSPlusVolumeHeader
*vh
);
1174 OSErr
CreateExtentsBTreeControlBlock( SGlobPtr GPtr
);
1175 OSErr
CreateCatalogBTreeControlBlock( SGlobPtr GPtr
);
1176 OSErr
CreateAttributesBTreeControlBlock( SGlobPtr GPtr
);
1177 OSErr
CreateExtendedAllocationsFCB( SGlobPtr GPtr
);
1180 OSErr
CacheWriteInPlace( SVCB
*vcb
, UInt32 fileRefNum
, HIOParam
*iopb
, UInt64 currentPosition
,
1181 UInt32 maximumBytes
, UInt32
*actualBytes
);
1184 /* Generic B-tree call back routines */
1185 OSStatus
GetBlockProc (SFCB
*filePtr
, UInt32 blockNum
, GetBlockOptions options
, BlockDescriptor
*block
);
1186 OSStatus
ReleaseBlockProc (SFCB
*filePtr
, BlockDescPtr blockPtr
, ReleaseBlockOptions options
);
1187 OSStatus
SetEndOfForkProc (SFCB
*filePtr
, FSSize minEOF
, FSSize maxEOF
);
1188 OSStatus
SetBlockSizeProc (SFCB
*filePtr
, ByteCount blockSize
, ItemCount minBlockCount
);
1190 void DFA_PrepareInputName(ConstStr31Param name
, Boolean isHFSPlus
, CatalogName
*catalogName
);
1192 extern UInt32
CatalogNameSize( const CatalogName
*name
, Boolean isHFSPlus
);
1194 void SetupFCB( SVCB
*vcb
, SInt16 refNum
, UInt32 fileID
, UInt32 fileClumpSize
);
1197 extern void CalculateItemCount( SGlob
*GPtr
, UInt64
*itemCount
, UInt64
*onePercent
);
1202 extern BTreeControlBlock
* GetBTreeControlBlock( short refNum
);
1203 #define GetBTreeControlBlock(refNum) ((BTreeControlBlock*) ResolveFCB((refNum))->fcbBtree)
1205 /* The following macro marks a VCB as dirty by setting the upper 8 bits of the flags*/
1206 EXTERN_API_C( void )
1207 MarkVCBDirty (SVCB
* vcb
);
1209 #define MarkVCBDirty(vcb) ((void) (vcb->vcbFlags |= 0xFF00))
1210 EXTERN_API_C( void )
1211 MarkVCBClean (SVCB
* vcb
);
1213 #define MarkVCBClean(vcb) ((void) (vcb->vcbFlags &= 0x00FF))
1214 EXTERN_API_C( Boolean
)
1215 IsVCBDirty (SVCB
* vcb
);
1217 #define IsVCBDirty(vcb) ((Boolean) ((vcb->vcbFlags & 0xFF00) != 0))
1220 extern pascal void M_Debugger(void);
1221 extern pascal void M_DebugStr(ConstStr255Param debuggerMsg
);
1223 #define M_Debuger() Debugger()
1224 #define M_DebugStr( debuggerMsg ) DebugStr( debuggerMsg )
1227 #define M_DebugStr( debuggerMsg )
1231 /* Test for error and return if error occurred*/
1232 EXTERN_API_C( void )
1233 ReturnIfError (OSErr result
);
1235 #define ReturnIfError(result) if ( (result) != noErr ) return (result); else ;
1236 /* Test for passed condition and return if true*/
1237 EXTERN_API_C( void )
1238 ReturnErrorIf (Boolean condition
,
1241 #define ReturnErrorIf(condition, error) if ( (condition) ) return( (error) );
1242 /* Exit function on error*/
1243 EXTERN_API_C( void )
1244 ExitOnError (OSErr result
);
1246 #define ExitOnError( result ) if ( ( result ) != noErr ) goto ErrorExit; else ;
1248 /* Return the low 16 bits of a 32 bit value, pinned if too large*/
1249 EXTERN_API_C( UInt16
)
1250 LongToShort (UInt32 l
);
1252 #define LongToShort( l ) l <= (UInt32)0x0000FFFF ? ((UInt16) l) : ((UInt16) 0xFFFF)
1255 EXTERN_API_C( UInt32
)
1259 DeleteCatalogNode(SVCB
*vcb
, UInt32 pid
, const CatalogName
* name
, UInt32 hint
, Boolean for_rename
);
1262 GetCatalogNode(SVCB
*vcb
, UInt32 pid
, const CatalogName
* name
, UInt32 hint
, CatalogRecord
*data
);
1264 EXTERN_API_C( SInt32
)
1265 CompareCatalogKeys (HFSCatalogKey
* searchKey
,
1266 HFSCatalogKey
* trialKey
);
1268 EXTERN_API_C( SInt32
)
1269 CompareExtendedCatalogKeys (HFSPlusCatalogKey
* searchKey
,
1270 HFSPlusCatalogKey
* trialKey
);
1271 EXTERN_API_C( SInt32
)
1272 CaseSensitiveCatalogKeyCompare (HFSPlusCatalogKey
* searchKey
,
1273 HFSPlusCatalogKey
* trialKey
);
1275 EXTERN_API_C( SInt32
)
1276 CompareExtentKeys (const HFSExtentKey
* searchKey
,
1277 const HFSExtentKey
* trialKey
);
1279 EXTERN_API_C( SInt32
)
1280 CompareExtentKeysPlus (const HFSPlusExtentKey
* searchKey
,
1281 const HFSPlusExtentKey
* trialKey
);
1282 EXTERN_API_C( SInt32
)
1283 CompareAttributeKeys (const AttributeKey
* searchKey
, const AttributeKey
* trialKey
);
1285 ResolveFCB (short fileRefNum
);
1287 EXTERN_API_C( OSErr
)
1288 ValidVolumeHeader (HFSPlusVolumeHeader
* volumeHeader
);
1291 /* Old B-tree Manager API (going away soon!) */
1293 EXTERN_API_C( OSErr
)
1294 SearchBTreeRecord (SFCB
*fcb
,
1302 EXTERN_API_C( OSErr
)
1303 GetBTreeRecord (SFCB
*fcb
,
1304 SInt16 selectionIndex
,
1310 EXTERN_API_C( OSErr
)
1311 InsertBTreeRecord (SFCB
*fcb
,
1317 EXTERN_API_C( OSErr
)
1318 DeleteBTreeRecord (SFCB
*fcb
,
1321 EXTERN_API_C( OSErr
)
1322 ReplaceBTreeRecord (SFCB
*fcb
,
1329 EXTERN_API_C( void )
1330 InitBTreeHeader (UInt32 fileSize
,
1339 EXTERN_API_C( OSErr
)
1340 UpdateFreeCount (SVCB
* vcb
);
1343 EXTERN_API_C(Boolean
)
1344 NodesAreContiguous( SFCB
*fcb
,
1349 UInt32
GetTimeUTC(void);
1350 UInt32
GetTimeLocal(Boolean forHFS
);
1352 OSErr
FlushVolumeControlBlock( SVCB
*vcb
);
1354 pascal short ResolveFileRefNum(SFCB
* fileCtrlBlockPtr
);
1356 extern UInt32
CatalogNameLength( const CatalogName
*name
, Boolean isHFSPlus
);
1358 extern void CopyCatalogName( const CatalogName
*srcName
, CatalogName
*dstName
, Boolean isHFSPLus
);
1360 extern void UpdateCatalogName( ConstStr31Param srcName
, Str31 destName
);
1362 extern void BuildCatalogKey( HFSCatalogNodeID parentID
, const CatalogName
*name
, Boolean isHFSPlus
,
1365 extern void UpdateVolumeEncodings( SVCB
*volume
, TextEncoding encoding
);
1368 OSErr
BlockAllocate (SVCB
*vcb
, UInt32 startingBlock
, UInt32 blocksRequested
, UInt32 blocksMaximum
,
1369 Boolean forceContiguous
, UInt32
*actualStartBlock
, UInt32
*actualNumBlocks
);
1370 OSErr
BlockDeallocate ( SVCB
*vcb
, UInt32 firstBlock
, UInt32 numBlocks
);
1371 UInt32
DivideAndRoundUp( UInt32 numerator
, UInt32 denominator
);
1372 OSErr
BlockFindAll(SFCB
*fcb
, UInt32 needed
);
1374 OSErr
InitializeBlockCache ( UInt32 blockSize
, UInt32 blockCount
);
1376 void SetFCBSPtr( Ptr value
);
1377 Ptr
GetFCBSPtr( void );
1381 * UTF-8 conversion routines
1383 extern int utf_decodestr(const unsigned char *, size_t, u_int16_t
*, size_t *, size_t);
1384 extern int utf_encodestr(const u_int16_t
*, size_t, unsigned char *, size_t *, size_t);
1387 * HardLink checking routines
1389 extern int HardLinkCheckBegin(SGlobPtr gp
, void** cookie
);
1390 extern void HardLinkCheckEnd(void * cookie
);
1391 extern void CaptureHardLink(void * cookie
, const HFSPlusCatalogFile
*file
);
1392 extern int CheckHardLinks(void *cookie
);
1394 extern void hardlink_add_bucket(PrimeBuckets
*bucket
, uint32_t inode_id
, uint32_t cur_link_id
);
1395 extern int inode_check(SGlobPtr
, PrimeBuckets
*, CatalogRecord
*, CatalogKey
*, Boolean
);
1396 extern void record_link_badchain(SGlobPtr
, Boolean
);
1397 extern int record_link_badflags(SGlobPtr
, uint32_t, Boolean
, uint32_t, uint32_t);
1398 extern int record_inode_badflags(SGlobPtr
, uint32_t, Boolean
, uint32_t, uint32_t, Boolean
);
1399 extern int record_dirlink_badownerflags(SGlobPtr
, uint32_t, uint8_t, uint8_t, int);
1400 extern int record_link_badfinderinfo(SGlobPtr
, uint32_t, Boolean
);
1402 extern int get_first_link_id(SGlobPtr gptr
, CatalogRecord
*inode_rec
, uint32_t inode_id
, Boolean isdir
, uint32_t *first_link_id
);
1403 extern int filelink_hash_inode(UInt32 inode_id
, UInt32 linkCount
);
1406 * Directory Hard Link checking routines
1408 extern int dirhardlink_init(SGlobPtr gptr
);
1409 extern int dirhardlink_check(SGlobPtr gptr
);
1411 extern OSErr
GetCatalogRecordByID(SGlobPtr GPtr
, UInt32 file_id
, Boolean isHFSPlus
, CatalogKey
*key
, CatalogRecord
*rec
, uint16_t *recsize
);
1413 struct HardLinkInfo
;
1414 extern int RepairHardLinkChains(SGlobPtr
, Boolean
);
1417 * Volume Bitmap checking routines
1419 extern int BitMapCheckBegin(SGlobPtr g
);
1420 extern int BitMapCheckEnd(void);
1421 extern int CaptureBitmapBits(UInt32 startBit
, UInt32 bitCount
);
1422 extern int ReleaseBitmapBits(UInt32 startBit
, UInt32 bitCount
);
1423 extern int CheckVolumeBitMap(SGlobPtr g
, Boolean repair
);
1424 extern void UpdateFreeBlockCount(SGlobPtr g
);
1425 extern int AllocateContigBitmapBits (SVCB
*vcb
, UInt32 numBlocks
, UInt32
*actualStartBlock
);
1426 extern int IsTrimSupported(void);
1427 extern void TrimFreeBlocks(SGlobPtr g
);
1430 * Variables and routines to support mapping a physical block number to a
1433 struct found_blocks
{
1438 #define FOUND_BLOCKS_QUANTUM 30
1439 extern int gBlkListEntries
;
1440 extern u_int64_t
*gBlockList
;
1441 extern int gFoundBlockEntries
;
1442 extern struct found_blocks
*gFoundBlocksList
;
1443 extern long gBlockSize
;
1444 void CheckPhysicalMatch(SVCB
*vcb
, UInt32 startblk
, UInt32 blkcount
, UInt32 fileNumber
, UInt8 forkType
);
1445 void dumpblocklist(SGlobPtr GPtr
);
1451 #endif /* __SCAVENGER__ */